lazarus-ccr/components/mbColorLib/mbColorPickerControl.pas

544 lines
13 KiB
ObjectPascal

unit mbColorPickerControl;
{$MODE DELPHI}
interface
uses
LCLIntf, LCLType, LMessages, SysUtils, Classes, Controls, Graphics, Forms, Themes,
HTMLColors, mbColorConv, mbBasicPicker;
type
TMarkerStyle = (msCircle, msSquare, msCross, msCrossCirc);
{ TmbCustomPicker }
TmbCustomPicker = class(TmbBasicPicker)
private
FHintFormat: string;
FMarkerStyle: TMarkerStyle;
FWebSafe: boolean;
procedure SetMarkerStyle(s: TMarkerStyle);
procedure SetWebSafe(s: boolean);
protected
FSelected: TColor;
mx, my: integer;
procedure CreateGradient; override;
function GetHintStr({%H-}X, {%H-}Y: Integer): String; override;
function GetSelectedColor: TColor; override;
procedure InternalDrawMarker(X, Y: Integer; C: TColor);
procedure SetSelectedColor(C: TColor); override;
procedure WebSafeChanged; dynamic;
procedure CMGotFocus(var Message: TLMessage); message CM_ENTER;
procedure CMLostFocus(var Message: TLMessage); message CM_EXIT;
// procedure CMMouseLeave(var Message: TLMessage); message CM_MOUSELEAVE;
property MarkerStyle: TMarkerStyle read FMarkerStyle write SetMarkerStyle;
public
constructor Create(AOwner: TComponent); override;
property ColorUnderCursor;
published
property HintFormat: string read FHintFormat write FHintFormat;
property WebSafe: boolean read FWebSafe write SetWebSafe default false;
end;
TmbColorPickerControl = class(TmbCustomPicker)
published
property Anchors;
property Align;
property BorderSpacing;
property ShowHint;
property ParentShowHint;
property Visible;
property Enabled;
property PopupMenu;
property TabOrder;
property TabStop default true;
property Color;
property ParentColor;
property DragCursor;
property DragMode;
property DragKind;
property Constraints;
property OnContextPopup;
property OnGetHintStr;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnResize;
property OnStartDrag;
end;
TmbHSLVColorPickerControl = class(TmbColorPickerControl)
private
FBrightnessMode: TBrightnessMode;
function GetHue: Integer;
function GetLum: Integer;
function GetSat: Integer;
function GetVal: Integer;
function GetRed: Integer;
function GetGreen: Integer;
function GetBlue: Integer;
procedure SetHue(h: integer);
procedure SetLum(L: Integer);
procedure SetSat(s: integer);
procedure SetVal(v: integer);
procedure SetRed(R: Integer);
procedure SetGreen(G: Integer);
procedure SetBlue(B: Integer);
protected
FHue, FSat, FLum, FVal: Double;
FMaxHue, FMaxSat, FMaxLum, FMaxVal: Integer;
procedure ColorToHSLV(c: TColor; var H, S, L, V: Double);
procedure CorrectCoords(var x, y: integer);
function HSLVtoColor(H, S, L, V: Double): TColor;
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 SelectColor({%H-}x, {%H-}y: Integer); virtual;
procedure SetBrightnessMode(AMode: TBrightnessMode); virtual;
procedure SetMaxHue(H: Integer); virtual;
procedure SetMaxLum(L: Integer); virtual;
procedure SetMaxSat(S: Integer); virtual;
procedure SetMaxVal(V: Integer); virtual;
procedure SetRelHue(H: Double); virtual;
procedure SetRelLum(L: Double); virtual;
procedure SetRelSat(S: Double); virtual;
procedure SetRelVal(V: Double); virtual;
public
constructor Create(AOwner: TComponent); override;
property RelHue: Double read FHue write SetRelHue;
property RelSaturation: Double read FSat write SetRelSat;
property RelLuminance: Double read FLum write SetRelLum;
property RelValue: Double read FVal write SetRelVal;
property Red: Integer read GetRed write SetRed;
property Green: Integer read GetGreen write SetGreen;
property Blue: Integer read GetBlue write SetBlue;
published
property BrightnessMode: TBrightnessMode
read FBrightnessMode write SetBrightnessMode default bmLuminance;
property Hue: integer read GetHue write SetHue;
property Luminance: Integer read GetLum write SetLum;
property Saturation: integer read GetSat write SetSat;
property Value: integer read GetVal write SetVal;
property MaxHue: Integer read FMaxHue write SetMaxHue default 360;
property MaxSaturation: Integer read FMaxSat write SetMaxSat default 255;
property MaxLuminance: Integer read FMaxLum write SetMaxLum default 255;
property MaxValue: Integer read FMaxVal write SetMaxVal default 255;
end;
implementation
uses
Math, IntfGraphics, fpimage,
PalUtils, SelPropUtils, mbUtils;
constructor TmbCustomPicker.Create(AOwner: TComponent);
begin
inherited;
//ControlStyle := ControlStyle + [csOpaque] - [csAcceptsControls];
TabStop := true;
mx := 0;
my := 0;
FHintFormat := 'Hex #%hex'#10#13'RGB[%r, %g, %b]'#10#13'HSL[%hslH, %hslS, %hslL]'#10#13'HSV[%hsvH, %hsvS, %hsvV]'#10#13'CMYK[%c, %m, %y, %k]'#10#13'L*a*b*[%cieL, %cieA, %cieB]'#10#13'XYZ[%cieX, %cieY, %cieZ]';
FWebSafe := false;
end;
procedure TmbCustomPicker.CMGotFocus(var Message: TLMessage);
begin
inherited;
Invalidate;
end;
procedure TmbCustomPicker.CMLostFocus(var Message: TLMessage);
begin
inherited;
Invalidate;
end;
(*
procedure TmbCustomPicker.CMMouseLeave(var Message: TLMessage);
begin
mx := 0;
my := 0;
inherited;
end;
*)
procedure TmbCustomPicker.CreateGradient;
var
x, y: Integer;
col: TColor;
fpcol: TFPColor;
intfimg: TLazIntfImage;
imgHandle, imgMaskHandle: HBitmap;
begin
if FBufferBmp = nil then
begin
FBufferBmp := TBitmap.Create;
// FBufferBmp.PixelFormat := pf32bit;
end;
FBufferBmp.Width := FGradientWidth;
FBufferBmp.Height := FGradientHeight;
intfimg := TLazIntfImage.Create(FBufferBmp.Width, FBufferBmp.Height);
try
intfImg.LoadFromBitmap(FBufferBmp.Handle, FBufferBmp.MaskHandle);
for y := 0 to FBufferBmp.Height - 1 do
begin
for x := 0 to FBufferBmp.Width - 1 do
begin
col := GetGradientColor2D(x, y);
if WebSafe then
col := GetWebSafe(col);
fpcol := TColorToFPColor(col);
intfImg.Colors[x, y] := fpcol;
end;
end;
intfimg.CreateBitmaps(imgHandle, imgMaskHandle, false);
FBufferBmp.Handle := imgHandle;
FBufferBmp.MaskHandle := imgMaskHandle;
finally
intfimg.Free;
end;
end;
function TmbCustomPicker.GetHintStr(X, Y: Integer): String;
begin
Result := FormatHint(FHintFormat, GetColorUnderCursor);
end;
function TmbCustomPicker.GetSelectedColor: TColor;
begin
Result := FSelected; // valid for most descendents
end;
procedure TmbCustomPicker.InternalDrawMarker(X, Y: Integer; C: TColor);
begin
case MarkerStyle of
msCircle : DrawSelCirc(x, y, Canvas);
msSquare : DrawSelSquare(x, y, Canvas);
msCross : DrawSelCross(x, y, Canvas, c);
msCrossCirc : DrawSelCrossCirc(x, y, Canvas, c);
end;
end;
procedure TmbCustomPicker.SetMarkerStyle(s: TMarkerStyle);
begin
if FMarkerStyle <> s then
begin
FMarkerStyle := s;
Invalidate;
end;
end;
procedure TmbCustomPicker.SetSelectedColor(C: TColor);
begin
FSelected := C;
//handled in descendents
end;
procedure TmbCustomPicker.SetWebSafe(s: boolean);
begin
if FWebSafe <> s then
begin
FWebSafe := s;
WebSafeChanged;
end;
end;
procedure TmbCustomPicker.WebSafeChanged;
begin
CreateGradient;
Invalidate;
end;
{ TmbHSLVColorPickerControl }
constructor TmbHSLVColorPickerControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FBrightnessMode := bmLuminance;
FMaxHue := 360;
FMaxSat := 255;
FMaxVal := 255;
FMaxLum := 255;
end;
procedure TmbHSLVColorPickerControl.ColorToHSLV(c: TColor;
var H, S, L, V: Double);
begin
case FBrightnessMode of
bmLuminance : ColorToHSL(c, H, S, L);
bmValue : ColorToHSV(c, H, S, V);
end;
end;
procedure TmbHSLVColorPickerControl.CorrectCoords(var x, y: integer);
begin
Clamp(x, 0, Width - 1);
Clamp(y, 0, Height - 1);
end;
function TmbHSLVColorPickerControl.GetBlue: Integer;
begin
Result := GetBValue(GetSelectedColor);
end;
function TmbHSLVColorPickerControl.GetGreen: Integer;
begin
Result := GetGValue(GetSelectedColor);
end;
function TmbHSLVColorPickerControl.GetHue: Integer;
begin
Result := Round(FHue * FMaxHue);
end;
function TmbHSLVColorPickerControl.GetLum: Integer;
begin
Result := Round(FLum * FMaxLum);
end;
function TmbHSLVColorPickerControl.GetRed: Integer;
begin
Result := GetRValue(GetSelectedColor);
end;
function TmbHSLVColorPickerControl.GetSat: Integer;
begin
Result := Round(FSat * FMaxSat);
end;
function TmbHSLVColorPickerControl.GetVal: Integer;
begin
Result := Round(FVal * FMaxVal);
end;
function TmbHSLVColorPickerControl.HSLVtoColor(H, S, L, V: Double): TColor;
begin
case FBrightnessMode of
bmLuminance : Result := HSLToColor(H, S, L);
bmValue : Result := HSVtoColor(H, S, V);
end;
if WebSafe then
Result := GetWebSafe(Result);
end;
procedure TmbHSLVColorPickerControl.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 TmbHSLVColorPickerControl.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if csDesigning in ComponentState then
Exit;
if Button = mbLeft then
SelectColor(x, y);
SetFocus;
end;
procedure TmbHSLVColorPickerControl.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
inherited;
if csDesigning in ComponentState then
Exit;
if ssLeft in Shift then
SelectColor(x, y);
end;
procedure TmbHSLVColorPickerControl.MouseUp(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
if csDesigning in ComponentState then
Exit;
if Button = mbLeft then
SelectColor(x, y);
end;
procedure TmbHSLVColorPickerControl.SelectColor(x, y: Integer);
begin
end;
procedure TmbHSLVColorPickerControl.SetBlue(B: Integer);
begin
Clamp(B, 0, 255);
SetSelectedColor(RgbToColor(Red, Green, B));
end;
procedure TmbHSLVColorPickerControl.SetBrightnessMode(AMode: TBrightnessMode);
var
c: TColor;
begin
c := HSLVtoColor(FHue, FSat, FLum, FVal);
FBrightnessMode := AMode;
ColorToHSLV(c, FHue, FSat, FLum, FVal);
CreateGradient;
Invalidate;
DoChange;
end;
procedure TmbHSLVColorPickerControl.SetGreen(G: Integer);
begin
Clamp(G, 0, 255);
SetSelectedColor(RgbToColor(Red, G, Blue));
end;
procedure TmbHSLVColorPickerControl.SetHue(H: Integer);
begin
SetRelHue(H / FMaxHue);
end;
procedure TmbHSLVColorPickerControl.SetLum(L: Integer);
begin
SetRelLum(L / FMaxLum);
end;
procedure TmbHSLVColorPickerControl.SetMaxHue(h: Integer);
begin
if h = FMaxHue then
exit;
FMaxHue := h;
CreateGradient;
Invalidate;
end;
procedure TmbHSLVColorPickerControl.SetMaxLum(L: Integer);
begin
if L = FMaxLum then
exit;
FMaxLum := L;
if BrightnessMode = bmLuminance then begin
CreateGradient;
Invalidate;
end;
end;
procedure TmbHSLVColorPickerControl.SetMaxSat(S: Integer);
begin
if S = FMaxSat then
exit;
FMaxSat := S;
CreateGradient;
Invalidate;
end;
procedure TmbHSLVColorPickerControl.SetMaxVal(V: Integer);
begin
if V = FMaxVal then
exit;
FMaxVal := V;
if BrightnessMode = bmLuminance then
begin
CreateGradient;
Invalidate;
end;
end;
procedure TmbHSLVColorPickerControl.SetRed(R: Integer);
begin
Clamp(R, 0, 255);
SetSelectedColor(RgbToColor(R, Green, Blue));
end;
procedure TmbHSLVColorPickerControl.SetRelHue(H: Double);
begin
Clamp(H, 0, 1.0);
if FHue <> H then
begin
FHue := H;
FSelected := HSLVtoColor(FHue, FSat, FLum, FVal);
CreateGradient;
Invalidate;
DoChange;
end;
end;
procedure TmbHSLVColorPickerControl.SetRelLum(L: Double);
begin
Clamp(L, 0, 1.0);
if FLum <> L then
begin
FLum := L;
FSelected := HSLVtoColor(FHue, FSat, FLum, FVal);
if BrightnessMode = bmLuminance then begin
CreateGradient;
Invalidate;
end;
DoChange;
end;
end;
procedure TmbHSLVColorPickerControl.SetRelSat(S: Double);
begin
Clamp(S, 0, 1.0);
if FSat <> S then
begin
FSat := S;
FSelected := HSLVtoColor(FHue, FSat, FLum, FVal);
CreateGradient;
Invalidate;
DoChange;
end;
end;
procedure TmbHSLVColorPickerControl.SetRelVal(V: Double);
begin
Clamp(v, 0, 1.0);
if FVal <> V then
begin
FVal := V;
if BrightnessMode = bmValue then
begin
FSelected := HSLVtoColor(FHue, FSat, FLum, FVal);
CreateGradient;
Invalidate;
end;
DoChange;
end;
end;
procedure TmbHSLVColorPickerControl.SetSat(S: Integer);
begin
SetRelSat(S / FMaxSat);
end;
procedure TmbHSLVColorPickerControl.SetVal(V: Integer);
begin
SetRelVal(V / FMaxVal);
end;
end.