lazarus-ccr/components/mbColorLib/GAxisColorPicker.pas
2018-03-24 09:52:51 +00:00

239 lines
5.2 KiB
ObjectPascal

unit GAxisColorPicker;
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
interface
uses
LCLType, LCLIntf, SysUtils, Classes, Controls, Graphics, Forms,
HTMLColors, mbColorPickerControl;
type
TGAxisColorPicker = class(TmbColorPickerControl)
private
FR, FG, FB: integer;
procedure SetRValue(r: integer);
procedure SetGValue(g: integer);
procedure SetBValue(b: integer);
protected
procedure CorrectCoords(var x, y: integer);
procedure CreateWnd; override;
procedure DrawMarker(x, y: integer);
function GetGradientColor2D(x, y: Integer): TColor; override;
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure Paint; override;
procedure Resize; override;
procedure SelectColor(x, y: Integer);
procedure SetSelectedColor(c: TColor); override;
public
constructor Create(AOwner: TComponent); override;
function GetColorAtPoint(x, y: Integer): TColor; override;
published
property SelectedColor default clLime;
property Red: integer read FR write SetRValue default 0;
property Green: integer read FG write SetGValue default 255;
property Blue: integer read FB write SetBValue default 0;
property MarkerStyle default msCircle;
property OnChange;
end;
implementation
uses
Math, mbUtils;
{TGAxisColorPicker}
constructor TGAxisColorPicker.Create(AOwner: TComponent);
begin
inherited;
FGradientWidth := 256;
FGradientHeight := 256;
SetInitialBounds(0, 0, 256, 256);
HintFormat := 'R: %r B: %b'#13'Hex: %hex';
FG := 255;
FB := 0;
FR := 0;
FSelected := clLime;
MarkerStyle := msCircle;
end;
procedure TGAxisColorPicker.CorrectCoords(var x, y: integer);
begin
Clamp(x, 0, Width-1);
Clamp(y, 0, Height-1);
end;
procedure TGAxisColorPicker.CreateWnd;
begin
inherited;
CreateGradient;
end;
procedure TGAxisColorPicker.DrawMarker(x, y: integer);
var
c: TColor;
begin
CorrectCoords(x, y);
FR := GetRValue(FSelected);
FG := GetGValue(FSelected);
FB := GetBValue(FSelected);
if Focused or (csDesigning in ComponentState) then
c := clBlack
else
c := clWhite;
InternalDrawMarker(x, y, c);
end;
function TGAxisColorPicker.GetColorAtPoint(x, y: Integer): TColor;
var
r, b: Integer;
begin
b := round(x / (Width - 1) * 255);
r := 255 - round(y / (Height - 1) * 255);
Result := RGBtoColor(r, FG, b);
end;
// x is BLUE, y is RED
function TGAxisColorPicker.GetGradientColor2D(x, y: Integer): TColor;
begin
Result := RGB(FBufferBmp.Height - 1 - y, FG, x);
end;
procedure TGAxisColorPicker.KeyDown(var Key: Word; Shift: TShiftState);
var
eraseKey: Boolean;
delta: Integer;
begin
eraseKey := true;
delta := IfThen(ssCtrl in Shift, 10, 1);
case Key of
VK_LEFT : SelectColor(mx - delta, my);
VK_RIGHT : SelectColor(mx + delta, my);
VK_UP : SelectColor(mx, my - delta);
VK_DOWN : SelectColor(mx, my + delta);
else eraseKey := false;
end;
if eraseKey then Key := 0;
inherited;
end;
procedure TGAxisColorPicker.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if Button = mbLeft then
SelectColor(x, y);
SetFocus;
end;
procedure TGAxisColorPicker.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
inherited;
if ssLeft in Shift then
SelectColor(x, y);
end;
procedure TGAxisColorPicker.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if Button = mbLeft then
SelectColor(x, y);
end;
procedure TGAxisColorPicker.Paint;
begin
Canvas.StretchDraw(ClientRect, FBufferBmp);
DrawMarker(mx, my);
end;
procedure TGAxisColorPicker.Resize;
begin
mx := Round(FB * Width / 255);
my := Round((255 - FR) * Height / 255);
inherited;
end;
procedure TGAxisColorPicker.SelectColor(x, y: Integer);
var
c: TColor;
r, g, b: Integer;
needNewGradient: Boolean;
begin
CorrectCoords(x, y);
mx := x;
my := y;
c := GetColorAtPoint(x, y);
if c = FSelected then
exit;
FSelected := c;
r := GetRValue(c);
g := GetGValue(c);
b := GetBValue(c);
needNewGradient := g <> FG;
FR := r;
FG := g;
FB := b;
if needNewGradient then
CreateGradient;
Invalidate;
DoChange;
end;
procedure TGAxisColorPicker.SetBValue(b: integer);
begin
Clamp(b, 0, 255);
SetSelectedColor(RGBToColor(FR, FG, b));
end;
procedure TGAxisColorPicker.SetGValue(g: integer);
begin
Clamp(g, 0, 255);
if FG <> g then
SetSelectedColor(RGBToColor(FR, g, FB));
end;
procedure TGAxisColorPicker.SetRValue(r: integer);
begin
Clamp(r, 0, 255);
SetSelectedColor(RGBToColor(r, FG, FB));
end;
procedure TGAxisColorPicker.SetSelectedColor(c: TColor);
var
r, g, b: Integer;
needNewGradient: Boolean;
begin
if WebSafe then
c := GetWebSafe(c);
if c = FSelected then
exit;
r := GetRValue(c);
g := GetGValue(c);
b := GetBValue(c);
needNewGradient := g <> FG;
FR := r;
FG := g;
FB := b;
FSelected := c;
mx := Round(FB * Width / 255); // BLUE is x
my := Round((255 - FR) * Height / 255); // RED is y
if needNewGradient then
CreateGradient;
Invalidate;
DoChange;
end;
end.