
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8129 8e941d3f-bd1b-0410-a28a-d453659cc2b4
253 lines
5.3 KiB
ObjectPascal
253 lines
5.3 KiB
ObjectPascal
unit HSColorPicker;
|
|
|
|
{$IFDEF FPC}
|
|
{$MODE DELPHI}
|
|
{$ENDIF}
|
|
|
|
interface
|
|
|
|
uses
|
|
LCLIntf, LCLType, SysUtils, Classes, Controls, Graphics, Forms,
|
|
HTMLColors, mbColorConv, mbColorPickerControl;
|
|
|
|
type
|
|
|
|
{ THSColorPicker }
|
|
|
|
THSColorPicker = class(TmbHSLVColorPickerControl)
|
|
private
|
|
FLumDisp, FValDisp: Double; // Lum and Value used for display
|
|
protected
|
|
procedure CreateWnd; override;
|
|
procedure DrawMarker(x, y: integer);
|
|
function GetGradientColor2D(x, y: Integer): TColor; override;
|
|
function GetSelectedColor: TColor; override;
|
|
procedure Paint; override;
|
|
function PredictColor: TColor;
|
|
procedure Resize; override;
|
|
procedure SelectColor(x, y: Integer); override;
|
|
procedure SetMaxHue(H: Integer); override;
|
|
procedure SetMaxSat(S: Integer); override;
|
|
procedure SetRelHue(H: Double); override;
|
|
procedure SetRelSat(S: Double); override;
|
|
procedure SetSelectedColor(c: TColor); override;
|
|
procedure UpdateCoords;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
function GetColorAtPoint(x, y: Integer): TColor; override;
|
|
published
|
|
property SelectedColor default clRed;
|
|
property Hue default 0;
|
|
property Saturation default 255;
|
|
property Luminance default 127;
|
|
property Value default 255;
|
|
property MaxHue default 360;
|
|
property MaxSaturation default 255;
|
|
property MaxLuminance default 255;
|
|
property MaxValue default 255;
|
|
property MarkerStyle default msCross;
|
|
property OnChange;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
Math, mbUtils;
|
|
|
|
{ THSColorPicker }
|
|
|
|
constructor THSColorPicker.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
FGradientWidth := FMaxHue; // We want to skip the point at 360° --> no +1
|
|
FGradientHeight := FMaxSat + 1;
|
|
SetInitialBounds(0, 0, FGradientWidth, FGradientHeight);
|
|
FHue := 0;
|
|
FSat := 1.0;
|
|
FLum := 0.5;
|
|
FLumDisp := 0.5;
|
|
FVal := 1.0;
|
|
FValDisp := 1.0;
|
|
FSelected := clRed;
|
|
CreateGradient;
|
|
HintFormat := 'H: %h S: %hslS'#13'Hex: %hex';
|
|
MarkerStyle := msCross;
|
|
end;
|
|
|
|
procedure THSColorPicker.CreateWnd;
|
|
begin
|
|
inherited;
|
|
CreateGradient;
|
|
end;
|
|
|
|
procedure THSColorPicker.DrawMarker(x, y: integer);
|
|
var
|
|
c: TColor;
|
|
dummy: Double = 0;
|
|
begin
|
|
CorrectCoords(x, y);
|
|
ColorToHSLV(FSelected, FHue, FSat, dummy, dummy);
|
|
if Focused or (csDesigning in ComponentState) then
|
|
c := clBlack
|
|
else
|
|
case BrightnessMode of
|
|
bmLuminance: c := clWhite;
|
|
bmValue : c := clGray;
|
|
end;
|
|
InternalDrawMarker(x, y, c);
|
|
end;
|
|
|
|
function THSColorPicker.GetColorAtPoint(x, y: Integer): TColor;
|
|
var
|
|
H, S: Double;
|
|
begin
|
|
if InRange(x, 0, Width - 1) and InRange(y, 0, Height - 1) then
|
|
begin
|
|
H := x / Width; // Width = FMaxHue
|
|
S := 1 - y / (Height - 1);
|
|
Result := HSLVtoColor(H, S, FLum, FVal);
|
|
end else
|
|
Result := clNone;
|
|
end;
|
|
|
|
function THSColorPicker.GetGradientColor2D(x, y: Integer): TColor;
|
|
var
|
|
H, S: Double;
|
|
begin
|
|
H := x / FMaxHue;
|
|
S := 1 - y / FMaxSat;
|
|
Result := HSLVtoColor(H, S, FLumDisp, FValDisp);
|
|
end;
|
|
|
|
function THSColorPicker.GetSelectedColor: TColor;
|
|
begin
|
|
Result := HSLVtoColor(FHue, FSat, FLum, FVal);
|
|
end;
|
|
|
|
procedure THSColorPicker.Paint;
|
|
begin
|
|
Canvas.StretchDraw(ClientRect, FBufferBmp);
|
|
DrawMarker(mx, my);
|
|
end;
|
|
|
|
function THSColorPicker.PredictColor: TColor;
|
|
begin
|
|
Result := GetColorUnderCursor;
|
|
end;
|
|
|
|
procedure THSColorPicker.Resize;
|
|
begin
|
|
SetSelectedColor(FSelected);
|
|
inherited;
|
|
end;
|
|
|
|
procedure THSColorPicker.SelectColor(x, y: Integer);
|
|
var
|
|
H: Double = 0;
|
|
S: Double = 0;
|
|
L: Double = 0;
|
|
V: Double = 0;
|
|
c: TColor;
|
|
begin
|
|
CorrectCoords(x, y);
|
|
mx := x;
|
|
my := y;
|
|
c := GetColorAtPoint(x, y);
|
|
if WebSafe then c := GetWebSafe(c);
|
|
|
|
ColorToHSLV(c, H, S, L, V);
|
|
{
|
|
if (H = FHue) and (S = FSat) then
|
|
exit;
|
|
}
|
|
FHue := H;
|
|
FSat := S;
|
|
FSelected := HSLVtoColor(FHue, FSat, FLum, FVal);
|
|
|
|
Invalidate;
|
|
DoChange;
|
|
end;
|
|
|
|
procedure THSColorPicker.SetMaxHue(H: Integer);
|
|
begin
|
|
if H = FMaxHue then
|
|
exit;
|
|
FGradientWidth := H + 1;
|
|
inherited;
|
|
end;
|
|
|
|
procedure THSColorPicker.SetMaxSat(S: Integer);
|
|
begin
|
|
if S = FMaxSat then
|
|
exit;
|
|
FGradientHeight := S + 1;
|
|
inherited;
|
|
end;
|
|
|
|
procedure THSColorPicker.SetRelHue(H: Double);
|
|
begin
|
|
Clamp(H, 0, 1 - 1/FMaxHue); // Don't use H=360°
|
|
if H = FHue then
|
|
exit;
|
|
|
|
FHue := H;
|
|
FSelected := GetSelectedColor;
|
|
UpdateCoords;
|
|
Invalidate;
|
|
DoChange;
|
|
end;
|
|
|
|
procedure THSColorPicker.SetRelSat(S: Double);
|
|
begin
|
|
Clamp(S, 0.0, 1.0);
|
|
if S = FSat then
|
|
exit;
|
|
|
|
FSat := S;
|
|
FSelected := GetSelectedColor;
|
|
UpdateCoords;
|
|
Invalidate;
|
|
DoChange;
|
|
end;
|
|
|
|
// NOTE: In the picker display only the hue and the saturation of the input
|
|
// color are used, the luminance is replaced by the preset value of the picker.
|
|
// --> The selected color in the üicker display in general is different from the
|
|
// input color.
|
|
procedure THSColorPicker.SetSelectedColor(c: TColor);
|
|
var
|
|
H: Double = 0;
|
|
S: Double = 0;
|
|
L: Double = 0;
|
|
V: Double = 0;
|
|
begin
|
|
if WebSafe then
|
|
c := GetWebSafe(c);
|
|
|
|
ColorToHSLV(c, H, S, L, V);
|
|
if (H = FHue) and (S = FSat) then
|
|
exit;
|
|
|
|
FSelected := c;
|
|
FHue := H;
|
|
FSat := S;
|
|
case BrightnessMode of
|
|
bmLuminance : FLum := L;
|
|
bmValue : FVal := V;
|
|
end;
|
|
|
|
UpdateCoords;
|
|
Invalidate;
|
|
DoChange;
|
|
end;
|
|
|
|
procedure THSColorPicker.UpdateCoords;
|
|
begin
|
|
mx := Round(FHue * Width);
|
|
my := Round((1.0 - FSat) * Height);
|
|
CorrectCoords(mx, my);
|
|
end;
|
|
|
|
end.
|