lazarus-ccr/components/mbColorLib/HSColorPicker.pas
wp_xxyyzz abdec8801e mbColorLib: Less hints and warnings.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8129 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2021-10-27 17:26:55 +00:00

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.