lazarus-ccr/components/mbColorLib/mbColorPalette.pas
2016-12-08 23:14:26 +00:00

1191 lines
32 KiB
ObjectPascal

unit mbColorPalette;
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
interface
{$I mxs.inc}
uses
{$IFDEF FPC}
LCLIntf, LCLType, LMessages,
{$ELSE}
Windows, Messages,
{$ENDIF}
SysUtils, Classes, Controls, Graphics, {$IFDEF DELPHI_7_UP} Themes, {$ENDIF}
Forms, HTMLColors, PalUtils, Dialogs;
type
TMouseLoc = (mlNone, mlOver, mlDown);
TTransparentStyle = (tsPhotoshop, tsPhotoshop2, tsCorel, tsMicroangelo, tsNone);
TCellStyle = (csDefault, csCorel);
TColorCellState = (ccsNone, ccsOver, ccsDown, ccsChecked, ccsCheckedHover);
TMoveDirection = (mdLeft, mdRight, mdUp, mdDown);
TPaintCellEvent = procedure (ACanvas: TCanvas; ACellRect: TRect; AColor: TColor; Index: integer; AState: TColorCellState; var AStyle: TTransparentStyle; var PaintingHandled: boolean) of object;
TCellClickEvent = procedure (Button: TMouseButton; Shift: TShiftState; Index: integer; AColor: TColor; var DontCheck: boolean) of object;
TGetHintTextEvent = procedure (AColor: TColor; Index: integer; var HintStr: string; var Handled: boolean) of object;
TArrowKeyEvent = procedure (Key: Word; Shift: TShiftState) of object;
TmbColorPalette = class(TCustomControl)
private
FMouseLoc: TMouseLoc;
FMouseOver, FMouseDown, FAutoHeight: boolean;
FColCount, FRowCount, FTop, FLeft, FIndex, FCheckedIndex, FCellSize, FTotalCells: integer;
FTempBmp, PBack: TBitmap;
FState: TColorCellState;
FColors, FNames: TStrings;
FPalette: TFileName;
FHintFormat: string;
FOnChange, FOnColorsChange: TNotifyEvent;
FMinColors, FMaxColors: integer;
FSort: TSortMode;
FOrder: TSortOrder;
FOld: TColor;
FOnPaintCell: TPaintCellEvent;
FTStyle: TTransparentStyle;
FOnCellClick: TCellClickEvent;
FOldIndex: integer;
FOnGetHintText: TGetHintTextEvent;
FCellStyle: TCellStyle;
FOnArrowKey: TArrowKeyEvent;
function GetMoveCellIndex(move: TMoveDirection): integer;
function GetSelColor: TColor;
procedure SetCellStyle(s: TCellStyle);
procedure SetTStyle(s: TTransparentStyle);
procedure SetCellSize(s: integer);
procedure SetSortMode(s: TSortMode);
procedure SetSortOrder(s: TSortOrder);
procedure SetMinColors(m: integer);
procedure SetMaxColors(m: integer);
procedure SetAutoHeight(auto: boolean);
procedure LoadPalette(FileName: TFileName);
procedure SetStrings(s: TStrings);
procedure SetNames(n: TStrings);
procedure SetSelColor(k: TColor);
procedure SortColors;
procedure CalcAutoHeight;
function GetTotalRowCount: integer;
protected
procedure Paint; override;
procedure PaintTransparentGlyph(ACanvas: TCanvas; R: TRect);
procedure DrawCell(clr: string);
procedure DrawCellBack(ACanvas: TCanvas; R: TRect; AIndex: integer);
procedure ColorsChange(Sender: TObject);
procedure Click; override;
procedure Resize; override;
procedure SelectCell(i: integer);
procedure PaintParentBack;
procedure CreateWnd; override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
{$IFDEF DELPHI}
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
procedure CNKeyDown(var Message: TWMKeyDown); message CN_KEYDOWN;
procedure CMGotFocus(var Message: TCMGotFocus); message CM_ENTER;
procedure CMLostFocus(var Message: TCMLostFocus); message CM_EXIT;
procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
procedure CMHintShow(var Message: TMessage); message CM_HINTSHOW;
{$ELSE}
procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
procedure CMMouseEnter(var Message: TLMessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Message: TLMessage); message CM_MOUSELEAVE;
procedure CNKeyDown(var Message: TLMKeyDown); message CN_KEYDOWN;
procedure CMGotFocus(var Message: TLMessage); message CM_ENTER;
procedure CMLostFocus(var Message: TLMessage); message CM_EXIT;
procedure CMEnabledChanged(var Message: TLMessage); message CM_ENABLEDCHANGED;
procedure CMHintShow(var Message: TLMessage); message CM_HINTSHOW;
{$ENDIF}
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetColorUnderCursor: TColor;
function GetSelectedCellRect: TRect;
function GetIndexUnderCursor: integer;
property ColorUnderCursor: TColor read GetColorUnderCursor;
property VisibleRowCount: integer read FRowCount;
property RowCount: integer read GetTotalRowCount;
property ColCount: integer read FColCount;
property IndexUnderCursor: integer read GetIndexUnderCursor;
procedure SaveColorsAsPalette(FileName: TFileName);
procedure GeneratePalette(BaseColor: TColor);
procedure GenerateGradientPalette(Colors: array of TColor);
published
property Align;
property Anchors;
property Enabled;
property SortMode: TSortMode read FSort write SetSortMode default smNone;
property SortOrder: TSortOrder read FOrder write SetSortOrder default soAscending;
property MinColors: integer read FMinColors write SetMinColors default 0;
property MaxColors: integer read FMaxColors write SetMaxColors default 0;
property SelectedCell: integer read FCheckedIndex write SelectCell default -1;
property SelectedColor: TColor read GetSelColor write SetSelColor default clNone;
property Colors: TStrings read FColors write SetStrings;
property Palette: TFileName read FPalette write LoadPalette;
property HintFormat: string read FHintFormat write FHintFormat;
property AutoHeight: boolean read FAutoHeight write SetAutoHeight default false;
property CellSize: integer read FCellSize write SetCellSize default 18;
property TransparentStyle: TTransparentStyle read FTStyle write SetTStyle default tsNone;
property CellStyle: TCellStyle read FCellStyle write SetCellStyle default csDefault;
property ColorNames: TStrings read FNames write SetNames;
{$IFDEF DELPHI_7_UP} {$IFDEF DELPHI}
property ParentBackground default true;
{$ENDIF} {$ENDIF}
property TabStop default true;
property TabOrder;
property ShowHint default false;
property Constraints;
property Color;
property ParentColor;
property ParentShowHint default true;
property PopupMenu;
property Visible;
property DragCursor;
property DragKind;
property DragMode;
property OnDragDrop;
property OnDragOver;
property OnEndDock;
property OnEndDrag;
property OnStartDock;
property OnStartDrag;
property OnSelColorChange: TNotifyEvent read FOnChange write FOnChange;
property OnColorsChange: TNotifyEvent read FOnColorsChange write FOnColorsChange;
property OnPaintCell: TPaintCellEvent read FOnPaintCell write FOnPaintCell;
property OnCellClick: TCellClickEvent read FOnCellClick write FOnCellClick;
property OnGetHintText: TGetHintTextEvent read FOnGetHintText write FOnGetHintText;
property OnArrowKey: TArrowKeyEvent read FOnArrowKey write FOnArrowKey;
property OnContextPopup;
property OnMouseMove;
property OnMouseDown;
property OnMouseUp;
property OnKeyDown;
property OnKeyUp;
property OnKeyPress;
property OnResize;
property OnClick;
end;
procedure Register;
implementation
{$IFDEF FPC}
{$R mbColorPalette.dcr}
{$ENDIF}
procedure Register;
begin
RegisterComponents('mbColor Lib', [TmbColorPalette]);
end;
constructor TmbColorPalette.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle - [csAcceptsControls] + [csOpaque];
DoubleBuffered := true;
PBack := TBitmap.Create;
PBack.PixelFormat := pf32bit;
{$IFDEF DELPHI_7_UP} {$IFDEF DELPHI}
ParentBackground := true;
{$ENDIF} {$ENDIF}
TabStop := true;
ParentShowHint := true;
ShowHint := false;
Width := 180;
Height := 126;
FMouseLoc := mlNone;
FMouseOver := false;
FMouseDown := false;
FColCount := 0;
FRowCount := 0;
FIndex := -1;
FCheckedIndex := -1;
FTop := 0;
FLeft := 0;
FCellSize := 18;
FState := ccsNone;
FNames := TStringList.Create;
FColors := TStringList.Create;
(FColors as TStringList).OnChange := ColorsChange;
FTotalCells := 0;
FHintFormat := 'RGB(%r, %g, %b)'#13'Hex: %hex';
FAutoHeight := false;
FMinColors := 0;
FMaxColors := 0;
FSort := smNone;
FOrder := soAscending;
FOld := clNone;
FTStyle := tsNone;
FCellStyle := csDefault;
end;
destructor TmbColorPalette.Destroy;
begin
PBack.Free;
FNames.Free;
FColors.Free;
inherited Destroy;
end;
procedure TmbColorPalette.CalcAutoHeight;
begin
if Parent = nil then
exit;
FColCount := Width div FCellSize;
if FAutoHeight and (FColCount <> 0) then
begin
if FColors.Count mod FColCount > 0 then
Height := (FColors.Count div FColCount + 1) * FCellSize
else
Height := (FColors.Count div FColCount) * FCellSize;
end;
if Height = 0 then Height := FCellSize;
FRowCount := Height div FCellSize;
Width := FColCount * FCellSize;
end;
function TmbColorPalette.GetTotalRowCount: integer;
begin
if FColCount <> 0 then
Result := FTotalCells div FColCount
else
Result := 0;
end;
procedure TmbColorPalette.CreateWnd;
begin
inherited;
CalcAutoHeight;
Invalidate;
end;
procedure TmbColorPalette.PaintParentBack;
{$IFDEF DELPHI_7_UP}
var
MemDC: HDC;
OldBMP: HBITMAP;
{$ENDIF}
begin
if PBack = nil then
begin
PBack := TBitmap.Create;
PBack.PixelFormat := pf32bit;
end;
PBack.Width := Width;
PBack.Height := Height;
{$IFDEF FPC}
if Color = clDefault then
PBack.Canvas.Brush.Color := clForm
else
{$ENDIF}
PBack.Canvas.Brush.Color := Color;
PBack.Canvas.FillRect(PBack.Canvas.ClipRect);
{$IFDEF DELPHI_7_UP} {$IFDEF DELPHI}
if ParentBackground then
with ThemeServices do
if ThemesEnabled then
begin
MemDC := CreateCompatibleDC(0);
OldBMP := SelectObject(MemDC, PBack.Handle);
DrawParentBackground(Handle, MemDC, nil, False);
if OldBMP <> 0 then SelectObject(MemDC, OldBMP);
if MemDC <> 0 then DeleteDC(MemDC);
end;
{$ENDIF} {$ENDIF}
end;
procedure TmbColorPalette.Paint;
var
i: integer;
begin
PaintParentBack;
//make bmp
FTempBmp := TBitmap.Create;
try
FTempBmp.PixelFormat := pf32bit;
FTempBmp.Width := Width;
FTempBmp.Height := Height;
{$IFDEF FPC}
if Color = clDefault then
FTempBmp.Canvas.Brush.Color := clForm
else
{$ENDIF}
FTempBmp.Canvas.Brush.Color := Color;
{$IFDEF DELPHI_7_UP} {$IFDEF DELPHI}
if not ParentBackground then
{$ENDIF} {$ENDIF}
FTempBmp.Canvas.FillRect(FTempBmp.Canvas.ClipRect)
{$IFDEF DELPHI_7_UP}{$IFDEF DELPHI}
else
FTempBmp.Canvas.Draw(0, 0, PBack){$ENDIF} {$ENDIF};
FTotalCells := FColors.Count - 1;
//reset counters
FTop := 0;
FLeft := 0;
//draw the cells
for i := 0 to FColors.Count - 1 do
begin
if FColors.Strings[i] <> '' then
DrawCell(FColors.Strings[i]);
Inc(FLeft);
end;
//draw the result
Canvas.Draw(0, 0, FTempBmp);
//csDesiginng border
if csDesigning in ComponentState then
begin
Canvas.Brush.Style := bsClear;
Canvas.Pen.Style := psDot;
Canvas.Pen.Color := clBtnShadow;
Canvas.Rectangle(ClientRect);
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Style := psSolid;
end;
finally
FTempBmp.Free;
end;
end;
procedure TmbColorPalette.DrawCell(clr: string);
var
R: Trect;
FCurrentIndex: integer;
c: TColor;
Handled: boolean;
begin
// set props
if (FLeft + 1) * FCellSize > FTempBmp.width then
begin
Inc(FTop);
FLeft := 0;
end;
FCurrentIndex := FTop * FColCount + FLeft;
R := Rect(FLeft * FCellSize, FTop * FCellSize, (FLeft + 1) * FCellSize, (FTop + 1) * FCellSize);
//start drawing
with FTempBmp.Canvas do
begin
{$IFDEF FPC}
if Color = clDefault then
Brush.Color := clForm else
{$ENDIF}
Brush.Color := Color;
//get current state
if FCurrentIndex = FCheckedIndex then
begin
if FCheckedIndex = FIndex then
begin
if FMouseDown then
FState := ccsDown
else
FState := ccsCheckedHover;
end
else
FState := ccsChecked;
end
else
if FIndex = FCurrentIndex then
case FMouseLoc of
mlNone: FState := ccsNone;
mlOver: FState := ccsOver;
end
else
FState := ccsNone;
//paint
DrawCellBack(FTempBmp.Canvas, R, FCurrentIndex);
// fire the event
Handled := false;
if Assigned(FOnPaintCell) then
case FCellStyle of
csDefault: FOnPaintCell(FTempBmp.Canvas, R, mbStringToColor(clr), FCurrentIndex, FState, FTStyle, Handled);
csCorel:
if FColCount = 1 then
FOnPaintCell(FTempBmp.Canvas, R, mbStringToColor(clr), FCurrentIndex, FState, FTStyle, Handled)
else
FOnPaintCell(FTempBmp.Canvas, Rect(R.Left, R.Top, R.Right + 1, R.Bottom), mbStringToColor(clr), FCurrentIndex, FState, FTStyle, Handled);
end;
if not Handled then
begin
// if standard colors draw the rect
if not SameText(clr, 'clCustom') and not SameText(clr, 'clTransparent') then
case FCellStyle of
csDefault:
begin
InflateRect(R, -3, -3);
c := mbStringToColor(clr);
if Enabled then
begin
Brush.Color := c;
Pen.Color := clBtnShadow;
end
else
begin
Brush.Color := clGray;
Pen.Color := clGray;
end;
Rectangle(R);
Exit;
end;
csCorel:
begin
if (FState <> ccsNone) then
InflateRect(R, -2, -2)
else
begin
Inc(R.Left);
Dec(R.Bottom);
if R.Top <= 1 then
Inc(R.Top);
if R.Right = Width then
Dec(R.Right);
end;
c := mbStringToColor(clr);
if Enabled then
Brush.Color := c
else
Brush.Color := clGray;
FillRect(R);
Exit;
end;
end;
//if transparent draw the glyph
if SameText(clr, 'clTransparent') then PaintTransparentGlyph(FTempBmp.Canvas, R);
end;
end;
end;
procedure TmbColorPalette.DrawCellBack(ACanvas: TCanvas; R: TRect; AIndex: integer);
begin
case FCellStyle of
csDefault:
begin
{$IFDEF DELPHI_7_UP}
if ThemeServices.ThemesEnabled then
begin
with ThemeServices do
if Enabled then
case FState of
ccsNone: ACanvas.CopyRect(R, PBack.Canvas, R);
ccsOver: DrawElement(ACanvas.Handle, GetElementDetails(ttbButtonHot), R);
ccsDown: DrawElement(ACanvas.Handle, GetElementDetails(ttbButtonPressed), R);
ccsChecked: DrawElement(ACanvas.Handle, GetElementDetails(ttbButtonChecked), R);
ccsCheckedHover: DrawElement(ACanvas.Handle, GetElementDetails(ttbButtonCheckedHot), R);
end
else
DrawElement(ACanvas.Handle, GetElementDetails(ttbButtonDisabled), R);
end
else
{$ENDIF}
if Enabled then
case FState of
ccsNone: ACanvas.FillRect(R);
ccsOver: DrawEdge(ACanvas.Handle, R, BDR_RAISEDINNER, BF_RECT);
ccsDown, ccsChecked, ccsCheckedHover: DrawEdge(ACanvas.Handle, R, BDR_SUNKENOUTER, BF_RECT);
end
else
DrawFrameControl(ACanvas.Handle, R, DFC_BUTTON, 0 or DFCS_BUTTONPUSH or DFCS_FLAT or DFCS_INACTIVE);
end;
csCorel:
begin
if Enabled then
begin
{$IFDEF DELPHI_7_UP}
if ThemeServices.ThemesEnabled then
case FState of
ccsNone:
begin
ACanvas.Brush.Color := clWhite;
ACanvas.Pen.Color := clBlack;
//left
ACanvas.MoveTo(R.Left, R.Top);
ACanvas.LineTo(R.Left, R.Bottom-1);
//bottom
ACanvas.MoveTo(R.Left, R.Bottom-1);
ACanvas.LineTo(R.Right, R.Bottom-1);
//top
if R.Top = 0 then
begin
ACanvas.MoveTo(R.Left, R.Top);
ACanvas.LineTo(R.Right, R.Top);
end;
//right
if (R.Right = Width) then
begin
ACanvas.MoveTo(R.Right-1, R.Top);
ACanvas.LineTo(R.Right-1, R.Bottom-1);
end
else
if (AIndex = FTotalCells) then
begin
ACanvas.MoveTo(R.Right, R.Top);
ACanvas.LineTo(R.Right, R.Bottom);
end;
end;
ccsOver: ThemeServices.DrawElement(ACanvas.Handle, ThemeServices.GetElementDetails(ttbButtonHot), R);
ccsDown: ThemeServices.DrawElement(ACanvas.Handle, ThemeServices.GetElementDetails(ttbButtonPressed), R);
ccsChecked: ThemeServices.DrawElement(ACanvas.Handle, ThemeServices.GetElementDetails(ttbButtonChecked), R);
ccsCheckedHover: ThemeServices.DrawElement(ACanvas.Handle, ThemeServices.GetElementDetails(ttbButtonCheckedHot), R);
end
else
{$ENDIF}
case FState of
ccsNone:
begin
ACanvas.Brush.Color := clWhite;
ACanvas.Pen.Color := clBlack;
ACanvas.Brush.Color := clWhite;
ACanvas.Pen.Color := clBlack;
//left
ACanvas.MoveTo(R.Left, R.Top);
ACanvas.LineTo(R.Left, R.Bottom-1);
//bottom
ACanvas.MoveTo(R.Left, R.Bottom-1);
ACanvas.LineTo(R.Right, R.Bottom-1);
//top
if R.Top = 0 then
begin
ACanvas.MoveTo(R.Left, R.Top);
ACanvas.LineTo(R.Right, R.Top);
end;
//right
if (R.Right = Width) then
begin
ACanvas.MoveTo(R.Right-1, R.Top);
ACanvas.LineTo(R.Right-1, R.Bottom-1);
end
else
if (AIndex = FTotalCells) then
begin
ACanvas.MoveTo(R.Right, R.Top);
ACanvas.LineTo(R.Right, R.Bottom);
end;
end;
ccsOver:
begin
OffsetRect(R, 1,1);
DrawEdge(ACanvas.Handle, R, BDR_RAISED, BF_RECT);
end;
ccsDown, ccsChecked, ccsCheckedHover: DrawEdge(ACanvas.Handle, R, BDR_SUNKENOUTER, BF_RECT);
end;
end
else
{$IFDEF DELPHI_7_UP}
if ThemeServices.ThemesEnabled then
ThemeServices.DrawElement(ACanvas.Handle, ThemeServices.GetElementDetails(ttbButtonDisabled), R)
else
{$ENDIF}
begin
ACanvas.Brush.Color := Color;
ACanvas.FillRect(R);
end;
end;
end;
end;
procedure TmbColorPalette.PaintTransparentGlyph(ACanvas: TCanvas; R: TRect);
begin
InflateRect(R, -3, -3);
if FCellStyle = csCorel then
begin
if FState <> ccsNone then
InflateRect(R, -2, -2)
else
if FColCount > 1 then
Inc(R.Right);
end;
with ACanvas do
case FTStyle of
tsPhotoshop:
begin
if Enabled then
Pen.Color := clBtnShadow
else
Pen.Color := clGray;
Brush.Color := clWhite;
Rectangle(R);
Brush.Color := clSilver;
FillRect(Rect(R.Left + (R.Right - R.Left) div 2, R.Top + 1, R.Right - 1, R.Top + (R.Bottom - R.Top) div 2));
FillRect(Rect(R.Left + 1, R.Top + (R.Bottom - R.Top) div 2, R.Left + (R.Right - R.Left) div 2, R.Bottom - 1));
end;
tsPhotoshop2:
begin
InflateRect(R, -1, -1);
Brush.Color := clWhite;
Rectangle(R);
Pen.Color := clRed;
Pen.Width := 2;
InflateRect(R, 1, 1);
MoveTo(R.Left, R.Top);
LineTo(R.Right - 1, R.Bottom - 1);
Pen.Width := 1;
Pen.Color := clBlack;
end;
tsCorel:
begin
if FCellStyle = csCorel then
begin
Pen.Color := clBlack;
InflateRect(R, 3, 3);
Brush.Color := clWhite;
Rectangle(R);
//the \ line
MoveTo(R.Left, R.Top);
LineTo(R.Right, R.Bottom);
//the / line
MoveTo(R.Right-1, R.Top);
LineTo(R.Left-1, R.Bottom);
end
else
begin
if Enabled then
Pen.Color := clBtnShadow
else
Pen.Color := clGray;
Brush.Color := clWhite;
Rectangle(R);
MoveTo(R.Left, R.Top);
LineTo(R.Right, R.Bottom);
MoveTo(R.Right - 1, R.Top);
LineTo(R.Left - 1, R.Bottom);
end;
end;
tsMicroangelo:
begin
InflateRect(R, -1, -1);
Dec(R.Bottom);
Pen.Color := clBlack;
Brush.Color := clTeal;
Rectangle(R);
Pixels[R.Left + 2, R.Top + 2] := clWhite;
Pixels[R.Left + (R.Right - R.Left) div 2, R.Bottom] := clBlack;
MoveTo(R.Left + (R.Right - R.Left) div 2 - 2, R.Bottom + 1);
LineTo(R.Left + (R.Right - R.Left) div 2 + 3, R.Bottom + 1);
end;
end;
end;
procedure TmbColorPalette.Resize;
begin
inherited;
CalcAutoHeight;
Invalidate;
end;
procedure TmbColorPalette.CMMouseEnter(
var Message: {$IFDEF DELPHI}TMessage{$ELSE}TLMessage{$ENDIF} );
begin
FMouseOver := true;
FMouseLoc := mlOver;
Invalidate;
inherited;
end;
procedure TmbColorPalette.CMMouseLeave(
var Message: {$IFDEF DELPHI}TMessage{$ELSE}TLMessage{$ENDIF} );
begin
FMouseOver := false;
FMouseLoc := mlNone;
FIndex := -1;
Invalidate;
inherited;
end;
procedure TmbColorPalette.MouseMove(Shift: TShiftState; X, Y: Integer);
begin
if FIndex <> (y div FCellSize)* FColCount + (x div FCellSize) then
begin
FIndex := (y div FCellSize)* FColCount + (x div FCellSize);
if FIndex > FTotalCells then FIndex := -1;
Invalidate;
end;
inherited;
end;
procedure TmbColorPalette.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
begin
SetFocus;
FMouseDown := true;
FMouseLoc := mlDown;
if (y div FCellSize)* FColCount + (x div FCellSize) <= FTotalCells then
if FCheckedIndex <> (y div FCellSize)* FColCount + (x div FCellSize) then
begin
FOldIndex := FCheckedIndex;
FCheckedIndex := (y div FCellSize)* FColCount + (x div FCellSize);
end;
Invalidate;
end;
inherited;
end;
procedure TmbColorPalette.Click;
begin
inherited;
end;
procedure TmbColorPalette.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
DontCheck: boolean;
AColor: TColor;
begin
FMouseDown := false;
if FMouseOver then
FMouseLoc := mlOver
else
FMouseLoc := mlNone;
DontCheck := false;
if (FCheckedIndex > -1) and (FCheckedIndex < FColors.Count) then
AColor := mbStringToColor(FColors.Strings[FCheckedIndex])
else
AColor := clNone;
if (Button = mbLeft) and PtInRect(ClientRect, Point(x, y)) then
if Assigned(FOnCellClick) then
FOnCellClick(Button, Shift, FCheckedIndex, AColor, DontCheck);
if DontCheck then FCheckedIndex := FOldIndex;
Invalidate;
inherited;
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure TmbColorPalette.CMGotFocus(
var Message: {$IFDEF DELPHI}TMessage{$ELSE}TLMessage{$ENDIF} );
begin
inherited;
Invalidate;
end;
procedure TmbColorPalette.CMLostFocus(
var Message: {$IFDEF DELPHI}TMessage{$ELSE}TLMessage{$ENDIF} );
begin
inherited;
if FMouseOver then
FMouseLoc := mlOver
else
FMouseLoc := mlNone;
Invalidate;
end;
procedure TmbColorPalette.CMEnabledChanged(
var Message: {$IFDEF DELPHI}TMessage{$ELSE}TLMessage{$ENDIF} );
begin
inherited;
Invalidate;
end;
procedure TmbColorPalette.WMEraseBkgnd(
var Message: {$IFDEF DELPHI}TWMEraseBkgnd{$ELSE}TLMEraseBkgnd{$ENDIF});
begin
Message.Result := 1;
end;
procedure TmbColorPalette.SelectCell(i: integer);
begin
if i < FColors.Count - 1 then
FCheckedIndex := i
else
FCheckedIndex := -1;
Invalidate;
if Assigned(FOnChange) then FOnChange(Self);
end;
function TmbColorPalette.GetSelColor: TColor;
begin
if (FCheckedIndex > -1) and (FCheckedIndex <= FTotalCells) then
Result := mbStringToColor(FColors.Strings[FCheckedIndex])
else
Result := FOld;
end;
function TmbColorPalette.GetColorUnderCursor: TColor;
begin
Result := clNone;
if FIndex > -1 then
if FIndex < FColors.Count then
Result := mbStringToColor(FColors.Strings[FIndex]);
end;
function TmbColorPalette.GetIndexUnderCursor: integer;
begin
Result := -1;
if FIndex > -1 then
if FIndex < FColors.Count then
Result := FIndex;
end;
procedure TmbColorPalette.SetTStyle(s: TTransparentStyle);
begin
if FTStyle <> s then
begin
FTStyle := s;
Invalidate;
end;
end;
procedure TmbColorPalette.SetCellStyle(s: TCellStyle);
begin
if FCellStyle <> s then
begin
FCellStyle := s;
Invalidate;
end;
end;
procedure TmbColorPalette.SetSelColor(k: TColor);
var
s: string;
i: integer;
begin
s := mbColorToString(k);
for i:= 0 to FColors.Count - 1 do
if SameText(s, FColors.Strings[i]) then
begin
FCheckedIndex := i;
Break;
end
else
FCheckedIndex := -1;
Invalidate;
FOld := k;
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure TmbColorPalette.SetStrings(s: TStrings);
var
i: integer;
begin
FColors.Clear;
FColors.AddStrings(s);
if FColors.Count < FMinColors then
for i := 0 to FMinColors - FColors.Count - 1 do
FColors.Add('clNone');
if (FColors.Count > FMaxColors) and (FMaxColors > 0) then
for i := FColors.Count - 1 downto FMaxColors do
FColors.Delete(i);
CalcAutoHeight;
SortColors;
Invalidate;
end;
procedure TmbColorPalette.SetNames(n: TStrings);
var
i: integer;
begin
FNames.Clear;
FNames.AddStrings(n);
if (FNames.Count > FMaxColors) and (FMaxColors > 0) then
for i := FNames.Count - 1 downto FMaxColors do
FNames.Delete(i);
end;
function TmbColorPalette.GetMoveCellIndex(move: TMoveDirection): integer;
var
FBefore: integer;
begin
Result := -1;
case move of
mdLeft:
if FCheckedIndex -1 < 0 then
Result := FTotalCells
else
Result := FCheckedIndex - 1;
mdRight:
if FCheckedIndex + 1 > FTotalCells then
Result := 0
else
Result := FCheckedIndex + 1;
mdUp:
if FCheckedIndex - FColCount < 0 then
begin
FBefore := (FTotalcells div FColCount) * FColCount;
if FBefore + FCheckedIndex - 1 > FTotalCells then Dec(FBefore, FColCount);
Result := FBefore + FCheckedIndex - 1;
end
else
Result := FCheckedIndex - FColCount;
mdDown:
if FCheckedIndex + FColCount > FTotalCells then
Result := FCheckedIndex mod FColCount + 1
else
Result := FCheckedIndex + FColCount;
end;
if Result > FColors.Count - 1 then
Result := 0;
end;
procedure TmbColorPalette.CNKeyDown(
var Message: {$IFDEF DELPHI}TWMKeyDown{$ELSE}TLMKeyDown{$ENDIF} );
var
FInherited: boolean;
Shift: TShiftState;
begin
Shift := KeyDataToShiftState(Message.KeyData);
Finherited := false;
case Message.CharCode of
VK_LEFT:
begin
FCheckedIndex := GetMoveCellIndex(mdLeft);
if Assigned(FOnArrowKey) then FOnArrowKey(Message.CharCode, Shift);
end;
VK_RIGHT:
begin
FCheckedIndex := GetMoveCellIndex(mdRight);
if Assigned(FOnArrowKey) then FOnArrowKey(Message.CharCode, Shift);
end;
VK_UP:
begin
FCheckedIndex := GetMoveCellIndex(mdUp);
if Assigned(FOnArrowKey) then FOnArrowKey(Message.CharCode, Shift);
end;
VK_DOWN:
begin
FCheckedIndex := GetMoveCellIndex(mdDown);
if Assigned(FOnArrowKey) then FOnArrowKey(Message.CharCode, Shift);
end;
VK_SPACE, VK_RETURN: if Assigned(FOnChange) then FOnChange(Self);
else
begin
FInherited := true;
inherited;
end;
end;
if not FInherited then
begin
Invalidate;
if Assigned(OnKeyDown) then OnKeyDown(Self, Message.CharCode, Shift);
if Assigned(FOnChange) then FOnChange(Self);
end;
end;
procedure TmbColorPalette.CMHintShow(
var Message: {$IFDEF DELPHI}TMessage{$ELSE}TLMessage{$ENDIF} );
var
clr: TColor;
Handled: boolean;
begin
if (Colors.Count > 0) and (FIndex > -1) then
with TCMHintShow(Message) do
begin
if not ShowHint then
Message.Result := 1
else
begin
with HintInfo^ do
begin
// show that we want a hint
Result := 0;
ReshowTimeout := 1;
HideTimeout := 5000;
clr := GetColorUnderCursor;
//fire event
Handled := false;
if Assigned(FOnGetHintText) then FOnGetHintText(clr, GetIndexUnderCursor, HintStr, Handled);
if Handled then Exit;
//do default
if FIndex < FNames.Count then
HintStr := FNames.Strings[FIndex]
else
if SameText(FColors.Strings[GetIndexUnderCursor], 'clCustom') or SameText(FColors.Strings[GetIndexUnderCursor], 'clTransparent') then
HintStr := StringReplace(FColors.Strings[GetIndexUnderCursor], 'cl', '', [rfReplaceAll])
else
HintStr := FormatHint(FHintFormat, GetColorUnderCursor);
end;
end;
end;
end;
procedure TmbColorPalette.SetAutoHeight(auto: boolean);
begin
FAutoHeight := auto;
CalcAutoHeight;
Invalidate;
end;
procedure TmbColorPalette.SetMinColors(m: integer);
var
i: integer;
begin
if (FMaxColors > 0) and (m > FMaxColors) then
m := FMaxColors;
FMinColors := m;
if FColors.Count < m then
for i := 0 to m - FColors.Count - 1 do
FColors.Add('clNone');
CalcAutoHeight;
SortColors;
Invalidate;
end;
procedure TmbColorPalette.SetMaxColors(m: integer);
var
i: integer;
begin
if m < 0 then m := 0;
FMaxColors := m;
if (m < FMinColors) and (m > 0) then
SetMinColors(m);
if (FColors.Count > FMaxColors) and (FMaxColors > 0) then
for i := FColors.Count - 1 downto FMaxColors do
FColors.Delete(i);
CalcAutoHeight;
SortColors;
Invalidate;
end;
procedure TmbColorPalette.SetSortMode(s: TSortMode);
begin
if FSort <> s then
begin
FSort := s;
SortColors;
Invalidate;
end;
end;
procedure TmbColorPalette.SetSortOrder(s: TSortOrder);
begin
if FOrder <> s then
begin
FOrder := s;
SortColors;
Invalidate;
end;
end;
procedure TmbColorPalette.ColorsChange(Sender: TObject);
begin
if Assigned(FOnColorsChange) then FOnColorsChange(Self);
FTotalCells := FColors.Count - 1;
CalcAutoHeight;
Invalidate;
end;
procedure TmbColorPalette.SetCellSize(s: integer);
begin
FCellSize := s;
CalcAutoHeight;
Invalidate;
end;
function TmbColorPalette.GetSelectedCellRect: TRect;
var
row, fbottom, fleft: integer;
begin
if FCheckedIndex > -1 then
begin
if FCheckedIndex mod FColCount = 0 then
begin
row := FCheckedIndex div FColCount;
fleft := Width - FCellSize;
end
else
begin
row := FCheckedIndex div FColCount + 1;
fleft := (FCheckedIndex mod FColCount - 1) * FCellSize;
end;
fbottom := row * FCellSize;
Result := Rect(fleft, fbottom - FCellSize, fleft + FCellSize, fbottom);
end
else
Result := Rect(0, 0, 0, 0);
end;
procedure TmbColorPalette.GeneratePalette(BaseColor: TColor);
begin
FColors.Text := MakePalette(BaseColor, FOrder);
CalcAutoHeight;
SortColors;
Invalidate;
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure TmbColorPalette.GenerateGradientPalette(Colors: array of TColor);
begin
FColors.Text := MakeGradientPalette(Colors);
CalcAutoHeight;
SortColors;
Invalidate;
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure TmbColorPalette.LoadPalette(FileName: TFileName);
var
supported: boolean;
a: AcoColors;
i: integer;
begin
supported := false;
if SameText(ExtractFileExt(FileName), '.pal') then
begin
supported := true;
FNames.Clear;
FColors.Text := ReadJASCPal(FileName);
end
else
if SameText(ExtractFileExt(FileName), '.aco') then
begin
supported := true;
a := ReadPhotoshopAco(FileName);
FColors.Clear;
for i := 0 to Length(a.Colors) - 1 do
FColors.Add(ColorToString(a.Colors[i]));
FNames.Clear;
if a.HasNames then
for i := 0 to Length(a.Names) - 1 do
FNames.Add(a.Names[i]);
end
else
if SameText(ExtractFileExt(FileName), '.act') then
begin
supported := true;
FNames.Clear;
FColors.Text := ReadPhotoshopAct(FileName);
end
else
Exception.Create('The file format you are trying to load is not supported in this version of the palette'#13'Please send a request to MXS along with the files of this format so'#13'loading support for this file can be added too');
if supported then
begin
CalcAutoHeight;
SortColors;
Invalidate;
if Assigned(FOnChange) then FOnChange(Self);
end;
end;
procedure TmbColorPalette.SaveColorsAsPalette(FileName: TFileName);
begin
if SameText(ExtractFileExt(FileName), '.pal') then
SaveJASCPal(FColors, FileName)
else
raise Exception.Create('The file extension specified does not identify a supported file format!'#13'Supported files formats are: .pal .aco .act');
end;
procedure TmbColorPalette.SortColors;
var
old: TColor;
begin
if FSort <> smNone then
begin
if FColors.Count = 0 then Exit;
old := GetSelColor;
SortPalColors(FColors, FSort, FOrder);
SetSelColor(old);
Invalidate;
end;
end;
end.