lasarus_compotents/ECC/ecgroupctrls.pas

1584 lines
54 KiB
ObjectPascal

{****************************************************
This file is part of the Eye Candy Controls (EC-C)
Copyright (C) 2014 Vojtěch Čihák, Czech Republic
This library is free software.
See the file COPYING.LGPL.txt,
included in this distribution,
for details about the license.
****************************************************}
unit ECGroupCtrls;
{$mode objfpc}{$H+}
//{$DEFINE DBGGRP} {don't remove, just comment}
interface
uses
Classes, SysUtils, Controls, ExtCtrls, Forms, Graphics, ImgList, LCLIntf,
LCLProc, LCLType, LMessages, LResources, Math, Themes, Types, ECTypes;
type
{$PACKENUM 2}
TGCOption = (egoAllowAllUp, egoCaptionBy, egoCentered,
egoColumnThenRow, egoNativeGlyphs, egoSplitted);
TGCOptions = set of TGCOption;
{ Event }
TGroupCtrlItemsMethod = procedure(AIndex: Integer) of object;
{ TGroupCtrlItem }
TGroupCtrlItem = class(TCollectionItem)
private
FCaption: TTranslateString;
FChecked: Boolean;
FImageIndex: SmallInt;
FImageIndexChecked: SmallInt;
procedure SetCaption(AValue: TTranslateString);
procedure SetChecked(AValue: Boolean);
procedure SetImageIndex(AValue: SmallInt);
procedure SetImageIndexChecked(AValue: SmallInt);
protected const
cDefCaption = 'Item';
protected
FItemRect: TRect;
function GetDisplayName: string; override;
public
constructor Create(ACollection: TCollection); override;
published
property Caption: TTranslateString read FCaption write SetCaption;
property Checked: Boolean read FChecked write SetChecked default False;
property ImageIndex: SmallInt read FImageIndex write SetImageIndex default -1;
property ImageIndexChecked: SmallInt read FImageIndexChecked write SetImageIndexChecked default -1;
end;
TCustomECGroupCtrl = class;
{ TGroupCtrlItems }
TGroupCtrlItems = class(TCollection)
private
function GetItems(Index: Integer): TGroupCtrlItem;
procedure SetItems(Index: Integer; AValue: TGroupCtrlItem);
protected
FGroupCtrl: TCustomECGroupCtrl;
OnCheckedChange: TGroupCtrlItemsMethod;
OnClick: TGroupCtrlItemsMethod;
function GetOwner: TPersistent; override;
procedure InvalidateItemRect(AIndex: Integer);
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); override;
procedure Update(Item: TCollectionItem); override;
public
constructor Create(AGroupCtrl: TCustomECGroupCtrl);
function Add: TGroupCtrlItem;
procedure Click(AIndex: Integer);
procedure Reset;
property Items[Index: Integer]: TGroupCtrlItem read GetItems write SetItems; default;
end;
{ TCustomECGroupCtrl }
TCustomECGroupCtrl = class(TECBaseControl)
private
FBlockColor: TColor;
FCheckedFontColor: TColor;
FCheckedFontStyles: TFontStyles;
FImages: TCustomImageList;
FIndent: SmallInt;
FItems: TGroupCtrlItems;
FHighlighted: SmallInt;
FOptions: TGCOptions;
FRowCount: SmallInt;
FSpacing: SmallInt;
FUncheckedFontColor: TColor;
FUncheckedFontStyles: TFontStyles;
procedure SetBlockColor(AValue: TColor);
procedure SetCheckedFontColor(AValue: TColor);
procedure SetCheckedFontStyles(AValue: TFontStyles);
procedure SetHighlighted(AValue: SmallInt);
procedure SetImages(AValue: TCustomImageList);
procedure SetIndent(AValue: SmallInt);
procedure SetItems(AValue: TGroupCtrlItems);
procedure SetOptions(AValue: TGCOptions);
procedure SetRowCount(AValue: SmallInt);
procedure SetSpacing(AValue: SmallInt);
procedure SetUncheckedFontColor(AValue: TColor);
procedure SetUncheckedFontStyles(AValue: TFontStyles);
protected const
cDefCheckedFontStyles = [fsBold];
cDefIndent = 3;
cDefSpacing = 5;
protected
Bitmaps: array [low(TItemState)..high(TItemState)] of TBitmap;
FBlockRect: TRect;
FCaptionRect: TRect;
FColWidth, FRowHeight: Single;
FPushedBtn: SmallInt;
FRealColCount, FRealRowCount: SmallInt;
ValidStates: TItemStates;
procedure Calculate(AEnabled: Boolean);
procedure CMBiDiModeChanged({%H-}var Message: TLMessage); message CM_BIDIMODECHANGED;
procedure CMColorChanged(var {%H-}Message: TLMessage); message CM_COLORCHANGED;
procedure CMEnabledChanged(var Message: TLMessage); message CM_ENABLEDCHANGED;
procedure CMParentColorChanged(var Message: TLMessage); message CM_PARENTCOLORCHANGED;
procedure CreateValidBitmaps(AEnabled: Boolean);
function DialogChar(var Message: TLMKey): Boolean; override;
procedure DrawBlocks(AEnabled: Boolean);
class function GetControlClassDefaultSize: TSize; override;
function GetElementDetails(AIState: TItemState): TThemedElementDetails; virtual; abstract;
procedure InvalidateCustomRect({%H-}AMove: Boolean); override;
procedure InvalidateItem(AIndex: Integer);
procedure ItemsChanged(ARecalculate: Boolean);
procedure KeyPress(var Key: Char); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure MouseLeave; override;
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
procedure OrientationChanged(AValue: TObjectOrientation); override;
procedure Paint; override;
procedure RecalcInvalidate;
procedure RecalcRedraw; override;
procedure Redraw3DColorAreas; override;
procedure TextChanged; override;
procedure WMSize(var Message: TLMSize); message LM_SIZE;
property Highlighted: SmallInt read FHighlighted write SetHighlighted;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Redraw; override;
property BlockColor: TColor read FBlockColor write SetBlockColor default clDefault;
property CheckedFontColor: TColor read FCheckedFontColor write SetCheckedFontColor default clDefault;
property CheckedFontStyles: TFontStyles read FCheckedFontStyles write SetCheckedFontStyles default cDefCheckedFontStyles;
property Images: TCustomImageList read FImages write SetImages;
property Indent: SmallInt read FIndent write SetIndent default cDefIndent;
property Items: TGroupCtrlItems read FItems write SetItems;
property Options: TGCOptions read FOptions write SetOptions;
property RowCount: SmallInt read FRowCount write SetRowCount default 1;
property Spacing: SmallInt read FSpacing write SetSpacing default cDefSpacing;
property UncheckedFontColor: TColor read FUncheckedFontColor write SetUncheckedFontColor default clDefault;
property UncheckedFontStyles: TFontStyles read FUncheckedFontStyles write SetUncheckedFontStyles default [];
end;
{ TCustomECRadioGroup }
TCustomECRadioGroup = class(TCustomECGroupCtrl)
private
FItemIndex: SmallInt;
FOnSelectionChange: TNotifyEvent;
procedure SetItemIndex(AValue: SmallInt);
protected const
cDefRGOptions = [egoCentered, egoSplitted];
protected
function GetElementDetails(AIState: TItemState): TThemedElementDetails; override;
procedure GroupCtrlItemCheckedChanged(AIndex: Integer);
procedure GroupCtrlItemClick(AIndex: Integer);
public
constructor Create(AOwner: TComponent); override;
property ItemIndex: SmallInt read FItemIndex write SetItemIndex default -1;
property OnSelectionChange: TNotifyEvent read FOnSelectionChange write FOnSelectionChange;
end;
{ TCustomECCheckGroup }
TCustomECCheckGroup = class(TCustomECGroupCtrl)
private
FOnItemClick: TCheckGroupClicked;
function GetChecked(Index: SmallInt): Boolean;
procedure SetChecked(Index: SmallInt; AValue: Boolean);
protected const
cDefCGOptions = [egoAllowAllUp, egoCentered, egoSplitted];
protected
function GetElementDetails(AIState: TItemState): TThemedElementDetails; override;
procedure GroupCtrlItemCheckedChanged(AIndex: Integer);
procedure GroupCtrlItemClick(AIndex: Integer);
public
constructor Create(AOwner: TComponent); override;
property Checked[Index: SmallInt]: Boolean read GetChecked write SetChecked;
property OnItemClick: TCheckGroupClicked read FOnItemClick write FOnItemClick;
end;
{ TECRadioGroup }
TECRadioGroup = class(TCustomECRadioGroup)
published
property Align;
property Anchors;
property BevelInner;
property BevelOuter;
property BevelSpace;
property BevelWidth;
property BiDiMode;
property BlockColor;
property BorderSpacing;
property Caption;
property CheckedFontColor;
property CheckedFontStyles;
{property Color;} { not needed }
property Color3DDark;
property Color3DLight;
property Constraints;
property Cursor;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property Font;
property Height;
property HelpContext;
property HelpKeyword;
property HelpType;
property Hint;
property Images;
property Indent;
property ItemIndex;
property Items;
property Left;
property Name;
property Options default cDefRGOptions;
property Orientation default eooHorizontal;
property ParentBiDiMode;
{property ParentColor;} { not needed }
property ParentFont;
property ParentShowHint;
property PopupMenu;
property RowCount;
property ShowHint;
property Spacing;
property Style default eosButton;
property TabOrder;
property TabStop;
property Tag;
property Top;
property UncheckedFontColor;
property UncheckedFontStyles;
property Visible;
property Width;
property OnChangeBounds;
property OnClick;
property OnContextPopup;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseMove;
property OnMouseUp;
property OnResize;
property OnSelectionChange;
property OnStartDrag;
property OnUTF8KeyPress;
end;
{ TECCheckGroup }
TECCheckGroup = class(TCustomECCheckGroup)
published
property Align;
property Anchors;
property BevelInner;
property BevelOuter;
property BevelSpace;
property BevelWidth;
property BiDiMode;
property BlockColor;
property BorderSpacing;
property Caption;
property CheckedFontColor;
property CheckedFontStyles;
{property Color;} { not needed }
property Color3DDark;
property Color3DLight;
property Constraints;
property Cursor;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property Font;
property Height;
property HelpContext;
property HelpKeyword;
property HelpType;
property Hint;
property Images;
property Indent;
property Items;
property Left;
property Name;
property Options default cDefCGOptions;
property Orientation default eooHorizontal;
property ParentBiDiMode;
{property ParentColor;} { not needed }
property ParentFont;
property ParentShowHint;
property PopupMenu;
property RowCount;
property ShowHint;
property Spacing;
property Style default eosButton;
property TabOrder;
property TabStop;
property Tag;
property Top;
property UncheckedFontColor;
property UncheckedFontStyles;
property Visible;
property Width;
property OnChangeBounds;
property OnClick;
property OnContextPopup;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnItemClick;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseMove;
property OnMouseUp;
property OnResize;
property OnStartDrag;
property OnUTF8KeyPress;
end;
procedure Register;
implementation
{ TGroupCtrlItem }
constructor TGroupCtrlItem.Create(ACollection: TCollection);
begin
inherited Create(ACollection);
FChecked:=False;
FImageIndex:=-1;
FImageIndexChecked:=-1;
end;
function TGroupCtrlItem.GetDisplayName: string;
begin
Result:=Caption;
if Result='' then Result:=cDefCaption+inttostr(Index);
end;
{ TGroupCtrlItem.Setters }
procedure TGroupCtrlItem.SetCaption(AValue: TTranslateString);
begin
if FCaption=AValue then exit;
FCaption:=AValue;
Changed(False)
end;
procedure TGroupCtrlItem.SetChecked(AValue: Boolean);
begin
if FChecked=AValue then exit;
FChecked:=AValue;
if assigned(Collection) then
with Collection as TGroupCtrlItems do
begin
if assigned(OnCheckedChange) then OnCheckedChange(Index);
InvalidateItemRect(Index);
end;
end;
procedure TGroupCtrlItem.SetImageIndex(AValue: SmallInt);
begin
if FImageIndex=AValue then exit;
FImageIndex:=AValue;
Changed(False);
end;
procedure TGroupCtrlItem.SetImageIndexChecked(AValue: SmallInt);
begin
if FImageIndexChecked=AValue then exit;
FImageIndexChecked:=AValue;
Changed(False);
end;
{ TGroupCtrlItems }
constructor TGroupCtrlItems.Create(AGroupCtrl: TCustomECGroupCtrl);
begin
inherited Create(TGroupCtrlItem);
FGroupCtrl:=AGroupCtrl;
end;
function TGroupCtrlItems.Add: TGroupCtrlItem;
begin
Result:=TGroupCtrlItem(inherited Add);
end;
procedure TGroupCtrlItems.Click(AIndex: Integer);
begin
if assigned(OnClick) then OnClick(AIndex);
end;
function TGroupCtrlItems.GetOwner: TPersistent;
begin
Result:=FGroupCtrl;
end;
procedure TGroupCtrlItems.InvalidateItemRect(AIndex: Integer);
begin
if assigned(Owner) then
with Owner as TCustomECGroupCtrl do
InvalidateItem(AIndex);
end;
procedure TGroupCtrlItems.Notify(Item: TCollectionItem; Action: TCollectionNotification);
begin
inherited Notify(Item, Action);
if Action=cnAdded then
if not (csLoading in (Owner as TCustomECGroupCtrl).ComponentState) then
TGroupCtrlItem(Item).FCaption:=TGroupCtrlItem.cDefCaption+inttostr(Item.Index);
end;
procedure TGroupCtrlItems.Reset;
var i: Integer;
begin
for i:=0 to Count-1 do
Items[i].Checked:=False;
end;
procedure TGroupCtrlItems.Update(Item: TCollectionItem);
begin
inherited Update(Item);
FGroupCtrl.ItemsChanged(Item=nil);
end;
{ TGroupCtrlItems.Setters }
function TGroupCtrlItems.GetItems(Index: Integer): TGroupCtrlItem;
begin
Result:=TGroupCtrlItem(inherited Items[Index]);
end;
procedure TGroupCtrlItems.SetItems(Index: Integer; AValue: TGroupCtrlItem);
begin
Items[Index].Assign(AValue);
end;
{ TCustomECGroupCtrl }
constructor TCustomECGroupCtrl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle:=ControlStyle+[csParentBackground, csReplicatable, csSetCaption]
-csMultiClicks-[csCaptureMouse, csNoFocus, csOpaque];
FBlockColor:=clDefault;
FCheckedFontColor:=clDefault;
FCheckedFontStyles:=cDefCheckedFontStyles;
FHighlighted:=-1;
FIndent:=cDefIndent;
FItems:=TGroupCtrlItems.Create(self);
FOrientation:=eooHorizontal;
FRowCount:=1;
FSpacing:=cDefSpacing;
FUncheckedFontColor:=clDefault;
FUncheckedFontStyles:=[];
with GetControlClassDefaultSize do
SetInitialBounds(0, 0, cx, cy);
RedrawMode:=ermRecalcRedraw;
end;
destructor TCustomECGroupCtrl.Destroy;
var aIState: TItemState;
begin
for aIState:=low(TItemState) to high(TItemState) do
if assigned(Bitmaps[aIState]) then FreeAndNil(Bitmaps[aIState]);
FreeAndNil(FItems);
inherited Destroy;
end;
procedure TCustomECGroupCtrl.Calculate(AEnabled: Boolean);
var aIState: TItemState;
aExtent: TSize;
i, aCount: Integer;
begin
if HasCaption then
begin
aExtent:=Canvas.TextExtent(Caption);
if Orientation=eooHorizontal then
begin
if not IsRightToLeft then
begin { Horizontal }
FCaptionRect:=Rect(0, 0, aExtent.cx, aExtent.cy);
if not (egoCaptionBy in Options)
then FBlockRect:=Rect(0, aExtent.cy+Indent, Width, Height)
else FBlockRect:=Rect(aExtent.cx+Indent, 0, Width, Height);
end else
begin
FCaptionRect:=Rect(Width-aExtent.cx+1, 0, Width, aExtent.cy);
if not (egoCaptionBy in Options)
then FBlockRect:=Rect(0, aExtent.cy+Indent, Width, Height)
else FBlockRect:=Rect(0, 0, Width-aExtent.cx-Indent+2, Height);
end;
end else
begin { Vertical }
if not IsRightToLeft then
begin
FCaptionRect:=Rect(0, 0, aExtent.cy, aExtent.cx);
if not (egoCaptionBy in Options)
then FBlockRect:=Rect(aExtent.cy+Indent, 0, Width, Height)
else FBlockRect:=Rect(0, aExtent.cx+Indent, Width, Height);
end else
begin
FCaptionRect:=Rect(Width-aExtent.cy, 0, Width, aExtent.cx);
if not (egoCaptionBy in Options)
then FBlockRect:=Rect(0, 0, Width-aExtent.cy-Indent, Height)
else FBlockRect:=Rect(0, aExtent.cx+Indent, Width, Height);
end;
end;
end else
FBlockRect:=ClientRect;
aExtent.cx:=FBlockRect.Right-FBlockRect.Left;
aExtent.cy:=FBlockRect.Bottom-FBlockRect.Top;
if AEnabled then
for aIState:=eisHighlighted to eisPushedHihlighted do
Bitmaps[aIState].SetSize(aExtent.cx, aExtent.cy)
else
begin
Bitmaps[eisDisabled].SetSize(aExtent.cx, aExtent.cy);
Bitmaps[eisPushedDisabled].SetSize(aExtent.cx, aExtent.cy);
end;
aCount:=Items.Count;
aExtent.cy:=Math.max(1, Math.min(FRowCount, aCount));
aExtent.cx:=aCount div aExtent.cy;
if (aExtent.cx=0) or ((aCount mod aExtent.cy)>0) then inc(aExtent.cx);
i:=aExtent.cx*aExtent.cy-aCount;
if i>=0 then dec(aExtent.cy, i div aExtent.cx);
FRealColCount:=aExtent.cx;
FRealRowCount:=aExtent.cy;
if aCount>0 then
begin
if Orientation=eooHorizontal then
begin { Horizontal }
FColWidth:=(Bitmaps[caItemState[AEnabled]].Width)/aExtent.cx;
FRowHeight:=(Bitmaps[caItemState[AEnabled]].Height)/aExtent.cy;
end else
begin { Vertical }
FColWidth:=(Bitmaps[caItemState[AEnabled]].Height)/aExtent.cx;
FRowHeight:=(Bitmaps[caItemState[AEnabled]].Width)/aExtent.cy;
end;
end;
end;
procedure TCustomECGroupCtrl.CMBiDiModeChanged(var Message: TLMessage);
begin
RecalcInvalidate;
end;
procedure TCustomECGroupCtrl.CMColorChanged(var Message: TLMessage);
begin
Redraw;
end;
procedure TCustomECGroupCtrl.CMEnabledChanged(var Message: TLMessage);
begin
if IsEnabled then Highlighted:=-1;
inherited CMEnabledChanged(Message);
end;
procedure TCustomECGroupCtrl.CMParentColorChanged(var Message: TLMessage);
begin
inherited CMParentColorChanged(Message);
Redraw;
end;
procedure TCustomECGroupCtrl.CreateValidBitmaps(AEnabled: Boolean);
var aIState: TItemState;
aWidth, aHeight: Integer;
begin
if assigned(Bitmaps[eisEnabled]) then
begin
aWidth:=Bitmaps[eisEnabled].Width;
aHeight:=Bitmaps[eisEnabled].Height;
end else
if assigned(Bitmaps[eisDisabled]) then
begin
aWidth:=Bitmaps[eisDisabled].Width;
aHeight:=Bitmaps[eisDisabled].Height;
end else
begin
aWidth:=0;
aHeight:=0;
end;
for aIState in ValidStates do
FreeAndNil(Bitmaps[aIState]);
if AEnabled
then ValidStates:=caEnabledStates
else ValidStates:=caDisabledStates;
for aIState in ValidStates do
begin
Bitmaps[aIState]:=TBitmap.Create;
Bitmaps[aIState].SetProperties(aWidth, aHeight);
end;
end;
function TCustomECGroupCtrl.DialogChar(var Message: TLMKey): Boolean;
var i: Integer;
begin
Result:=False;
if Message.Msg=LM_SYSCHAR then
begin
if IsEnabled and IsVisible then
begin
for i:=0 to Items.Count-1 do
if IsAccel(Message.CharCode, Items[i].Caption) then
begin
Items.Click(i);
SetFocus;
Result:=True;
exit; { Exit! }
end;
Result:=inherited DialogChar(Message);
end;
end;
end;
procedure TCustomECGroupCtrl.DrawBlocks(AEnabled: Boolean);
var i, j, aBorder, aCount, aIndex, aLeft, aTop: Integer;
aColor: TColor;
aColWidth, aRowHeight, aText1Top: Single;
aFlags: Cardinal;
aGlyphSize, aImageSize: TSize;
aRect: TRect;
aIState: TItemState;
bGlyphs, bHasImages, bHorizontal, bR2L: Boolean;
procedure IncIndent(var AResult: Integer; AIncrement: Integer);
begin
if AResult<>0 then
begin
inc(AResult, AIncrement);
if AIncrement<>0 then inc(AResult, Spacing);
end
else AResult:=AIncrement
end;
procedure DrawGlyphImageText;
var aCaption: string;
aElementRect: TRect;
aImage, aImgCh: Integer;
aPoint: TPoint;
aTextWidth, w, x, y: Integer;
bImages: Boolean;
begin
aImage:=Items[aIndex].ImageIndex;
aImgCh:=Items[aIndex].ImageIndexChecked;
if not (bHasImages and (aImage>=0) and (aImage<Images.Count)) then aImage:=-1;
if not (bHasImages and (aImgCh>=0) and (aImgCh<Images.Count)) then
if aImage>=0
then aImgCh:=aImage
else aImgCh:=-1;
if bGlyphs
then w:=aGlyphSize.cx
else w:=0;
bImages:= ((aImgCh>=0) and ((aIState>=eisPushed) or not (egoCentered in Options)))
or ((aImage>=0) and (aIState<=eisEnabled));
if bImages then IncIndent(w, aImageSize.cx);
aCaption:=Items[aIndex].Caption;
if bHorizontal then DeleteAmpersands(aCaption);
aTextWidth:=Bitmaps[aIState].Canvas.TextWidth(aCaption);
IncIndent(w, aTextWidth);
aLeft:=round(i*aColWidth);
if bHorizontal then
begin
Items[aIndex].FItemRect:=Rect(FBlockRect.Left+aLeft, FBlockRect.Top+round(j*aRowHeight),
FBlockRect.Left+round((i+1)*aColWidth), FBlockRect.Top+round((j+1)*aRowHeight));
end else
begin
Items[aIndex].FItemRect:=Rect(FBlockRect.Left+round(j*aRowHeight), FBlockRect.Top+aLeft,
FBlockRect.Left+round((j+1)*aRowHeight), FBlockRect.Top+round((i+1)*aColWidth));
end;
if not (egoCentered in Options) then
begin
x:=aBorder+Spacing;
if bR2L and bHorizontal then x:=round(FColWidth-w-x);
end else
x:=round(0.5*(aColWidth-w));
if bGlyphs then
begin
if bHorizontal then
begin
y:=round(0.5*(aRowHeight-aGlyphSize.cy)+j*aRowHeight);
if not bR2L then
begin
aElementRect:=Rect(aLeft+x, y, aLeft+x+aGlyphSize.cx, y+aGlyphSize.cy);
inc(x, aGlyphSize.cx+Spacing);
end else
begin
aElementRect:=Rect(aLeft+x+w-aGlyphSize.cx, y, aLeft+x+w, y+aGlyphSize.cy);
dec(x, aGlyphSize.cx+Spacing);
end;
end else
begin
y:=round(0.5*(aRowHeight-aGlyphSize.cx)+j*aRowHeight);
aElementRect:=Rect(y, aLeft+x, y+aGlyphSize.cx, aLeft+x+aGlyphSize.cy);
inc(x, aGlyphSize.cy+Spacing);
end;
ThemeServices.DrawElement(Bitmaps[aIState].Canvas.Handle,
GetElementDetails(aIState), aElementRect, nil);
end;
if bImages then
begin
y:=round(0.5*(FRowHeight-aImageSize.cy)+j*aRowHeight);
if not bR2L or not bHorizontal then
begin
aPoint:=Point(aLeft+x, y);
inc(x, aImageSize.cx+Spacing);
end else
begin
aPoint:=Point(aLeft+x+w-aImageSize.cx, y);
dec(x, aImageSize.cx+Spacing);
end;
if not bHorizontal then
begin
w:=aPoint.X;
aPoint.X:=aPoint.Y;
aPoint.Y:=w;
end;
if aIState>=eisPushed then aImage:=aImgCh;
if aImage>=0 then
ThemeServices.DrawIcon(Bitmaps[aIState].Canvas, GetElementDetails(aIState),
aPoint, Images, aImage);
end;
aElementRect.Top:=round(aText1Top+j*aRowHeight);
aElementRect.Right:=Bitmaps[aIState].Width;
aElementRect.Bottom:=Bitmaps[aIState].Height;
if not bR2L or not bHorizontal
then aElementRect.Left:=aLeft+x
else aElementRect.Left:=aLeft+x+w-aTextWidth;
if bHorizontal then
begin
Bitmaps[aIState].Canvas.Font.Orientation:=0;
ThemeServices.DrawText(Bitmaps[aIState].Canvas,
ThemeServices.GetElementDetails(caThemedContent[aIState]),
Items[aIndex].Caption, aElementRect, aFlags, 0);
end else
begin
Bitmaps[aIState].Canvas.Brush.Style:=bsClear;
Bitmaps[aIState].Canvas.Font.Orientation:=900;
Bitmaps[aIState].Canvas.TextOut(aElementRect.Top,
aElementRect.Left+aTextWidth, Items[aIndex].Caption);
end;
end;
begin
{$IFDEF DBGGRP} DebugLn('TCustomECGroupCtrl.Draw'); {$ENDIF}
aColWidth:=FColWidth;
aCount:=Items.Count;
aRowHeight:=FRowHeight;
aBorder:=GetBorderWidth;
aText1Top:=round(0.5*(aRowHeight-Bitmaps[caItemState[AEnabled]].Canvas.TextHeight('É,9')));
aRect:=Rect(0, 0, Bitmaps[caItemState[AEnabled]].Width, Bitmaps[caItemState[AEnabled]].Height);
bGlyphs:= egoNativeGlyphs in Options;
bHasImages:= assigned(Images);
bHorizontal:= Orientation=eooHorizontal;
bR2L:= IsRightToLeft;
aFlags:=DT_SINGLELINE;
if bR2L then aFlags:=aFlags+DT_RTLREADING;
{ set Glyphs size if needed; assumes that disabled/enables/pushed/hot have the same size }
if bGlyphs then aGlyphSize:=ThemeServices.GetDetailSize(GetElementDetails(caItemState[AEnabled]));
if bHasImages then aImageSize:=Size(Images.Width, Images.Height); { set Images size if needed }
aColor:=ColorToRGB(GetColorResolvingDefault(Color, Parent.Brush.Color));
if (aColor and $FF) > 0
then dec(aColor)
else inc(aColor);
for aIState in ValidStates do
begin
{ Draw Background }
Bitmaps[aIState].TransparentColor:=aColor;
Bitmaps[aIState].TransparentClear;
case Style of
eosButton: Bitmaps[aIState].Canvas.DrawButtonBackground(aRect, aIState);
eosPanel: Bitmaps[aIState].Canvas.DrawPanelBackGround(aRect, BevelInner, BevelOuter,
BevelSpace, BevelWidth, Color3DDark, Color3DLight,
GetColorResolvingDefault(BlockColor, Parent.Brush.Color));
end;
{ Draw Spliters }
if egoSplitted in Options then
if bHorizontal then
begin { Horizontal }
for i:=1 to FRealColCount-1 do
begin
aLeft:=round(i*aColWidth)-1;
Bitmaps[aIState].Canvas.Pen.Color:=cl3DShadow;
Bitmaps[aIState].Canvas.Line(aLeft, aBorder, aLeft, Bitmaps[aIState].Height-aBorder);
if aIState<eisPushed then
begin
inc(aLeft);
Bitmaps[aIState].Canvas.Pen.Color:=cl3DHiLight;
Bitmaps[aIState].Canvas.Line(aLeft, aBorder, aLeft, Bitmaps[aIState].Height-aBorder);
end;
end;
for j:=1 to FRealRowCount-1 do
begin
aTop:=round(j*aRowHeight)-1;
Bitmaps[aIState].Canvas.Pen.Color:=cl3DShadow;
Bitmaps[aIState].Canvas.Line(aBorder, aTop, Bitmaps[aIState].Width-aBorder, aTop);
if aIState<eisPushed then
begin
inc(aTop);
Bitmaps[aIState].Canvas.Pen.Color:=cl3DHiLight;
Bitmaps[aIState].Canvas.Line(aBorder, aTop, Bitmaps[aIState].Width-aBorder, aTop);
end;
end;
end else
begin { Vertical }
for i:=1 to FRealColCount-1 do
begin
aTop:=round(i*aColWidth)-1;
Bitmaps[aIState].Canvas.Pen.Color:=cl3DShadow;
Bitmaps[aIState].Canvas.Line(aBorder, aTop, Bitmaps[aIState].Width-aBorder, aTop);
if aIState<eisPushed then
begin
inc(aTop);
Bitmaps[aIState].Canvas.Pen.Color:=cl3DHiLight;
Bitmaps[aIState].Canvas.Line(aBorder, aTop, Bitmaps[aIState].Width-aBorder, aTop);
end;
end;
for j:=1 to FRealRowCount-1 do
begin
aLeft:=round(j*aRowHeight)-1;
Bitmaps[aIState].Canvas.Pen.Color:=cl3DShadow;
Bitmaps[aIState].Canvas.Line(aLeft, aBorder, aLeft, Bitmaps[aIState].Height-aBorder);
if aIState<eisPushed then
begin
inc(aLeft);
Bitmaps[aIState].Canvas.Pen.Color:=cl3DHiLight;
Bitmaps[aIState].Canvas.Line(aLeft, aBorder, aLeft, Bitmaps[aIState].Height-aBorder);
end;
end;
end;
{ Draw Glyphs, Images and Captions }
if aIState<eisPushed then
begin
Bitmaps[aIState].Canvas.Font.Color:=GetColorResolvingDefault(UncheckedFontColor, clBtnText);
Bitmaps[aIState].Canvas.Font.Style:=UncheckedFontStyles;
end else
begin
Bitmaps[aIState].Canvas.Font.Color:=GetColorResolvingDefault(CheckedFontColor, clBtnText);
Bitmaps[aIState].Canvas.Font.Style:=CheckedFontStyles;
end;
if not (egoColumnThenRow in Options) then
begin
if not bR2L xor not bHorizontal then
begin { Horizontal then Vertical, Left to Right }
for j:=0 to FRealRowCount-1 do
for i:=0 to FRealColCount-1 do
begin
aIndex:=i+j*FRealColCount;
if aIndex>=aCount then break;
DrawGlyphImageText;
end;
end else
begin { Horizontal then Vertical, Right to Left }
for j:=0 to FRealRowCount-1 do
for i:=FRealColCount-1 downto 0 do
begin
aIndex:=FRealColCount-i-1+j*FRealColCount;
if aIndex>=aCount then break;
DrawGlyphImageText;
end;
end;
end else
begin
if not bR2L xor not bHorizontal then
begin { Vertical then Horizontal, Left to Right }
for i:=0 to FRealColCount-1 do
for j:=0 to FRealRowCount-1 do
begin
aIndex:=i*FRealRowCount+j;
if aIndex>=aCount then break;
DrawGlyphImageText;
end;
end else
begin { Vertical then Horizontal, Right to Left }
for i:=FRealColCount-1 downto 0 do
for j:=0 to FRealRowCount-1 do
begin
aIndex:=(FRealColCount-i-1)*FRealRowCount+j;
if aIndex>=aCount then break;
DrawGlyphImageText;
end;
end;
end;
end;
end;
class function TCustomECGroupCtrl.GetControlClassDefaultSize: TSize;
begin
Result.cx:=150;
Result.cy:=39;
end;
procedure TCustomECGroupCtrl.InvalidateCustomRect(AMove: Boolean);
begin
if UpdateCount=0 then InvalidateRect(Handle, @FInvalidRect, False);
end;
procedure TCustomECGroupCtrl.InvalidateItem(AIndex: Integer);
begin
if RedrawMode<=ermFreeRedraw then
begin
RedrawMode:=ermMoveKnob;
if FInvalidRect.Left<0
then FInvalidRect:=Items[AIndex].FItemRect
else IncludeRectangle(FInvalidRect, Items[AIndex].FItemRect);
InvalidateCustomRect(False);
end else
InvalidateNonUpdated;
end;
procedure TCustomECGroupCtrl.ItemsChanged(ARecalculate: Boolean);
begin
if not ARecalculate
then Redraw
else RecalcRedraw;
end;
procedure TCustomECGroupCtrl.KeyPress(var Key: Char);
var aIndex: Integer;
begin
inherited KeyPress(Key);
aIndex:=ord(Key)-VK_1;
if (aIndex>=0) and (aIndex<=8) and (aIndex<Items.Count)
then Items.Click(aIndex) { VK_1..VK_9 click items}
else if (ord(Key)=VK_0) and (egoAllowAllUp in Options) then Items.Reset; { and VK_0 resets all }
end;
procedure TCustomECGroupCtrl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
inherited MouseDown(Button, Shift, X, Y);
if Button=mbLeft then FPushedBtn:=Highlighted;
SetFocus;
end;
procedure TCustomECGroupCtrl.MouseLeave;
begin
{$IFDEF DBGGRP} DebugLn('TCustomECGroupCtrl.MouseLeave'); {$ENDIF}
inherited MouseLeave;
Highlighted:=-1;
end;
procedure TCustomECGroupCtrl.MouseMove(Shift: TShiftState; X, Y: Integer);
var aCol, aCount, aIndex, aRow: Integer;
begin
inherited MouseMove(Shift, X, Y);
aCount:=Items.Count;
if (aCount>0) and PtInRect(FBlockRect, Point(X, Y)) then
begin
if Orientation=eooHorizontal then
begin
X:=X-FBlockRect.Left;
Y:=Y-FBlockRect.Top;
end else
begin
aRow:=Y;
Y:=X-FBlockRect.Left;
X:=aRow-FBlockRect.Top;
end;
if not (egoColumnThenRow in Options) then
begin
aRow:=trunc(Y/FRowHeight);
if not IsRightToLeft xor (Orientation=eooVertical)
then aIndex:=aRow*FRealColCount+trunc(X/FColWidth)
else aIndex:=aRow*FRealColCount+FRealColCount-trunc(X/FColWidth)-1;
end else
begin
if not IsRightToLeft xor (Orientation=eooVertical)
then aCol:=trunc(X/FColWidth)
else aCol:=FRealColCount-trunc(X/FColWidth)-1;
aIndex:=aCol*FRealRowCount+trunc(Y/FRowHeight);
end;
if aIndex>=aCount then aIndex:=-1;
end else
aIndex:=-1;
Highlighted:=aIndex;
end;
procedure TCustomECGroupCtrl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
inherited MouseUp(Button, Shift, X, Y);
if Button=mbLeft then
if (FPushedBtn=Highlighted) and (Highlighted>=0) then Items.Click(Highlighted);
end;
procedure TCustomECGroupCtrl.OrientationChanged(AValue: TObjectOrientation);
begin
if not (csLoading in ComponentState) then SetBounds(Left, Top, Height, Width);
inherited OrientationChanged(AValue);
end;
procedure TCustomECGroupCtrl.Paint;
var aCount, aIndex, i, j: Integer;
aFlags: Cardinal;
aRect, aDest: TRect;
bEnabled: Boolean;
function GetItemState: TItemState;
begin
{$IFDEF DBGGRP} DebugLn('GroupCtrl.GetItemState, '+inttostr(aIndex)); {$ENDIF}
if aIndex<aCount then
begin
if bEnabled then
begin
if not Items[aIndex].Checked then
begin
if not (Highlighted=aIndex)
then Result:=eisEnabled
else Result:=eisHighlighted;
end else
begin
if not (Highlighted=aIndex)
then Result:=eisPushed
else Result:=eisPushedHihlighted;
end
end else
if not Items[aIndex].Checked
then Result:=eisDisabled
else Result:=eisPushedDisabled;
end else
Result:=caItemState[bEnabled];
end;
begin
{$IFDEF DBGGRP}
DebugLn('RedrawMode '+inttostr(SmallInt(RedrawMode)));
DebugLn(inttostr(FInvalidRect.Left)+', '+inttostr(FInvalidRect.Top)+', '+
inttostr(FInvalidRect.Right)+', '+inttostr(FInvalidRect.Bottom));
{$ENDIF}
inherited Paint;
bEnabled:=IsEnabled;
if (bEnabled xor (eisEnabled in ValidStates)) or (ValidStates=[]) then
begin
if RedrawMode<ermRedrawBkgnd then RedrawMode:=ermRedrawBkgnd;
CreateValidBitmaps(bEnabled);
end;
if RedrawMode=ermRecalcRedraw then Calculate(bEnabled);
if RedrawMode>=ermRedrawBkgnd then DrawBlocks(bEnabled);
{ Paint Body }
aCount:=Items.Count;
if aCount=0 then
begin
aRect:=Rect(0, 0, Bitmaps[caItemState[bEnabled]].Width, Bitmaps[caItemState[bEnabled]].Height);
Canvas.CopyRect(FBlockRect, Bitmaps[caItemState[bEnabled]].Canvas, aRect);
end else
begin
if Orientation=eooHorizontal then
begin { Horizontal }
if not IsRightToLeft then
begin
if not (egoColumnThenRow in Options) then
begin { Horizontal then Vertical, Left to Right }
for j:=0 to FRealRowCount-1 do
begin
aRect.Top:=round(j*FRowHeight);
aRect.Bottom:=round((j+1)*FRowHeight);
aDest.Top:=FBlockRect.Top+aRect.Top;
aDest.Bottom:=FBlockRect.Top+aRect.Bottom;
for i:=0 to FRealColCount-1 do
begin
aRect.Left:=round(i*FColWidth);
aRect.Right:=round((i+1)*FColWidth);
aDest.Left:=FBlockRect.Left+aRect.Left;
aDest.Right:=FBlockRect.Left+aRect.Right;
aIndex:=i+j*FRealColCount;
if (RedrawMode>=ermFreeRedraw) or
PtInRect(FInvalidRect, Point(aDest.Left+1, aDest.Top+1))
then Canvas.CopyRect(aDest, Bitmaps[GetItemState].Canvas, aRect);
end;
end;
end else
begin { Vertical then Horizontal, Left to Right }
for i:=0 to FRealColCount-1 do
begin
aRect.Left:=round(i*FColWidth);
aRect.Right:=round((i+1)*FColWidth);
aDest.Left:=FBlockRect.Left+aRect.Left;
aDest.Right:=FBlockRect.Left+aRect.Right;
for j:=0 to FRealRowCount-1 do
begin
aRect.Top:=round(j*FRowHeight);
aRect.Bottom:=round((j+1)*FRowHeight);
aDest.Top:=FBlockRect.Top+aRect.Top;
aDest.Bottom:=FBlockRect.Top+aRect.Bottom;
aIndex:=i*FRealRowCount+j;
if (RedrawMode>=ermFreeRedraw) or
PtInRect(FInvalidRect, Point(aDest.Left+1, aDest.Top+1))
then Canvas.CopyRect(aDest, Bitmaps[GetItemState].Canvas, aRect);
end;
end;
end;
end else
begin
if not (egoColumnThenRow in Options) then
begin { Horizontal then Vertical, Right to Left }
for j:=FRealRowCount-1 downto 0 do
begin
aRect.Top:=round(j*FRowHeight);
aRect.Bottom:=round((j+1)*FRowHeight);
aDest.Top:=FBlockRect.Top+aRect.Top;
aDest.Bottom:=FBlockRect.Top+aRect.Bottom;
for i:=0 to FRealColCount-1 do
begin
aRect.Left:=round(i*FColWidth);
aRect.Right:=round((i+1)*FColWidth);
aDest.Left:=FBlockRect.Left+aRect.Left;
aDest.Right:=FBlockRect.Left+aRect.Right;
aIndex:=FRealColCount-i-1+j*FRealColCount;
if (RedrawMode>=ermFreeRedraw) or
PtInRect(FInvalidRect, Point(aDest.Left+1, aDest.Top+1))
then Canvas.CopyRect(aDest, Bitmaps[GetItemState].Canvas, aRect);
end;
end;
end else
begin { Vertical then Horizontal, Right to Left }
for i:=FRealColCount-1 downto 0 do
begin
aRect.Left:=round(i*FColWidth);
aRect.Right:=round((i+1)*FColWidth);
aDest.Left:=FBlockRect.Left+aRect.Left;
aDest.Right:=FBlockRect.Left+aRect.Right;
for j:=0 to FRealRowCount-1 do
begin
aRect.Top:=round(j*FRowHeight);
aRect.Bottom:=round((j+1)*FRowHeight);
aDest.Top:=FBlockRect.Top+aRect.Top;
aDest.Bottom:=FBlockRect.Top+aRect.Bottom;
aIndex:=(FRealColCount-i-1)*FRealRowCount+j;
if (RedrawMode>=ermFreeRedraw) or
PtInRect(FInvalidRect, Point(aDest.Left+1, aDest.Top+1))
then Canvas.CopyRect(aDest, Bitmaps[GetItemState].Canvas, aRect);
end;
end;
end;
end;
end else
begin { Vertical }
if not IsRightToLeft then
begin
if not (egoColumnThenRow in Options) then
begin { Horizontal then Vertical, Left to Right }
for j:=0 to FRealRowCount-1 do
begin
aRect.Left:=round(j*FRowHeight);
aRect.Right:=round((j+1)*FRowHeight);
aDest.Left:=FBlockRect.Left+aRect.Left;
aDest.Right:=FBlockRect.Left+aRect.Right;
for i:=0 to FRealColCount-1 do
begin
aRect.Top:=round(i*FColWidth);
aRect.Bottom:=round((i+1)*FColWidth);
aDest.Top:=FBlockRect.Top+aRect.Top;
aDest.Bottom:=FBlockRect.Top+aRect.Bottom;
aIndex:=FRealColCount-i-1+j*FRealColCount;
if (RedrawMode>=ermFreeRedraw) or
PtInRect(FInvalidRect, Point(aDest.Left+1, aDest.Top+1))
then Canvas.CopyRect(aDest, Bitmaps[GetItemState].Canvas, aRect);
end;
end;
end else
begin { Vertical then Horizontal, Left to Right }
for i:=0 to FRealColCount-1 do
begin
aRect.Top:=round(i*FColWidth);
aRect.Bottom:=round((i+1)*FColWidth);
aDest.Top:=FBlockRect.Top+aRect.Top;
aDest.Bottom:=FBlockRect.Top+aRect.Bottom;
for j:=0 to FRealRowCount-1 do
begin
aRect.Left:=round(j*FRowHeight);
aRect.Right:=round((j+1)*FRowHeight);
aDest.Left:=FBlockRect.Left+aRect.Left;
aDest.Right:=FBlockRect.Left+aRect.Right;
aIndex:=(FRealColCount-i-1)*FRealRowCount+j;
if (RedrawMode>=ermFreeRedraw) or
PtInRect(FInvalidRect, Point(aDest.Left+1, aDest.Top+1))
then Canvas.CopyRect(aDest, Bitmaps[GetItemState].Canvas, aRect);
end;
end;
end;
end else
begin
if not (egoColumnThenRow in Options) then
begin { Horizontal then Vertical, Right to Left }
for j:=FRealRowCount-1 downto 0 do
begin
aRect.Left:=round(j*FRowHeight);
aRect.Right:=round((j+1)*FRowHeight);
aDest.Left:=FBlockRect.Left+aRect.Left;
aDest.Right:=FBlockRect.Left+aRect.Right;
for i:=0 to FRealColCount-1 do
begin
aRect.Top:=round(i*FColWidth);
aRect.Bottom:=round((i+1)*FColWidth);
aDest.Top:=FBlockRect.Top+aRect.Top;
aDest.Bottom:=FBlockRect.Top+aRect.Bottom;
aIndex:=i+j*FRealColCount;
if (RedrawMode>=ermFreeRedraw) or
PtInRect(FInvalidRect, Point(aDest.Left+1, aDest.Top+1))
then Canvas.CopyRect(aDest, Bitmaps[GetItemState].Canvas, aRect);
end;
end;
end else
begin { Vertical then Horizontal, Right to Left }
for i:=FRealColCount-1 downto 0 do
begin
aRect.Top:=round(i*FColWidth);
aRect.Bottom:=round((i+1)*FColWidth);
aDest.Top:=FBlockRect.Top+aRect.Top;
aDest.Bottom:=FBlockRect.Top+aRect.Bottom;
for j:=0 to FRealRowCount-1 do
begin
aRect.Left:=round(j*FRowHeight);
aRect.Right:=round((j+1)*FRowHeight);
aDest.Left:=FBlockRect.Left+aRect.Left;
aDest.Right:=FBlockRect.Left+aRect.Right;
aIndex:=i*FRealRowCount+j;
if (RedrawMode>=ermFreeRedraw) or
PtInRect(FInvalidRect, Point(aDest.Left+1, aDest.Top+1))
then Canvas.CopyRect(aDest, Bitmaps[GetItemState].Canvas, aRect);
end;
end;
end;
end;
end;
end;
{ Paint Caption and FocusRect }
if HasCaption then
begin
if RedrawMode>=ermFreeRedraw then
begin
Canvas.Brush.Style:=bsClear;
if Orientation=eooHorizontal then
begin
Canvas.Font.Orientation:=0;
aFlags:=DT_SINGLELINE+DT_NOPREFIX;
if IsRightToLeft then aFlags:=aFlags+DT_RTLREADING;
with ThemeServices do
DrawText(Canvas, GetElementDetails(caThemedContent[caItemState[bEnabled]]),
Caption, FCaptionRect, aFlags, 0)
end else
begin
Canvas.Font.Orientation:=900;
Canvas.TextOut(FCaptionRect.Left, FCaptionRect.Bottom, Caption);
end;
if Focused then
begin
LCLIntf.SetBkColor(Canvas.Handle, ColorToRGB(clForm));
LCLIntf.DrawFocusRect(Canvas.Handle, FCaptionRect);
end;
end;
end else
begin
if Focused then
begin
LCLIntf.SetBkColor(Canvas.Handle, ColorToRGB(clForm));
aRect:=Rect(3, 3, ClientWidth-3, ClientHeight-3);
LCLIntf.DrawFocusRect(Canvas.Handle, aRect);
end
end;
FInvalidRect:=Rect(-1, -1, -1, -1);
RedrawMode:=ermFreeRedraw;
end;
procedure TCustomECGroupCtrl.RecalcInvalidate;
begin
RedrawMode:=ermRecalcRedraw;
Invalidate;
end;
procedure TCustomECGroupCtrl.RecalcRedraw;
begin
{$IFDEF DBGGRP} DebugLn('TCustomECGroupCtrl.RecalcRedraw'); {$ENDIF}
RedrawMode:=ermRecalcRedraw;
if UpdateCount=0 then
begin
if AutoSize then
begin
InvalidatePreferredSize;
AdjustSize;
end;
Invalidate;
end;
end;
procedure TCustomECGroupCtrl.Redraw;
begin
{$IFDEF DBGGRP} DebugLn('TCustomECGroupCtrl.Redraw'); {$ENDIF}
if RedrawMode<ermRedrawBkgnd then RedrawMode:=ermRedrawBkgnd;
if UpdateCount=0 then Invalidate;
end;
procedure TCustomECGroupCtrl.Redraw3DColorAreas;
begin
if (Style=eosPanel) and (RedrawMode<ermRedrawBkgnd) then RedrawMode:=ermRedrawBkgnd;
if UpdateCount=0 then Invalidate;
end;
procedure TCustomECGroupCtrl.TextChanged;
begin
inherited TextChanged;
RecalcInvalidate;
end;
procedure TCustomECGroupCtrl.WMSize(var Message: TLMSize);
begin
inherited WMSize(Message);
RedrawMode:=ermRecalcRedraw;
if UpdateCount=0 then Invalidate; { because of GTK2 }
end;
{ TCustomECGroupCtrl.Setters }
procedure TCustomECGroupCtrl.SetBlockColor(AValue: TColor);
begin
if FBlockColor=AValue then exit;
FBlockColor:=AValue;
Redraw;
end;
procedure TCustomECGroupCtrl.SetCheckedFontColor(AValue: TColor);
begin
if FCheckedFontColor=AValue then exit;
FCheckedFontColor:=AValue;
Redraw;
end;
procedure TCustomECGroupCtrl.SetCheckedFontStyles(AValue: TFontStyles);
begin
if FCheckedFontStyles=AValue then exit;
FCheckedFontStyles:=AValue;
Redraw;
end;
procedure TCustomECGroupCtrl.SetHighlighted(AValue: SmallInt);
var aOldIndex: SmallInt;
begin
if FHighlighted=AValue then exit;
aOldIndex:=FHighlighted;
FHighlighted:=AValue;
if RedrawMode<=ermFreeRedraw then
begin
RedrawMode:=ermHoverKnob;
if aOldIndex>=0 then
if FInvalidRect.Left<0
then FInvalidRect:=Items[aOldIndex].FItemRect
else IncludeRectangle(FInvalidRect, Items[aOldIndex].FItemRect);
if AValue>=0 then
if FInvalidRect.Left<0
then FInvalidRect:=Items[AValue].FItemRect
else IncludeRectangle(FInvalidRect, Items[AValue].FItemRect);
InvalidateCustomRect(False);
end else
Invalidate;
end;
procedure TCustomECGroupCtrl.SetImages(AValue: TCustomImageList);
begin
if FImages=AValue then exit;
FImages:=AValue;
RecalcInvalidate;
end;
procedure TCustomECGroupCtrl.SetIndent(AValue: SmallInt);
begin
if FIndent=AValue then exit;
FIndent:=AValue;
if HasCaption then RecalcInvalidate;
end;
procedure TCustomECGroupCtrl.SetItems(AValue: TGroupCtrlItems);
begin
if AValue<>FItems then
begin
FItems.Assign(AValue);
RecalcInvalidate;
end;
end;
procedure TCustomECGroupCtrl.SetOptions(AValue: TGCOptions);
begin
if FOptions=AValue then exit;
FOptions:=AValue;
RecalcInvalidate;
end;
procedure TCustomECGroupCtrl.SetRowCount(AValue: SmallInt);
begin
if (FRowCount=AValue) or (AValue<1) then exit;
FRowCount:=AValue;
RecalcInvalidate;
end;
procedure TCustomECGroupCtrl.SetSpacing(AValue: SmallInt);
begin
if FSpacing=AValue then exit;
FSpacing:=AValue;
Redraw;
end;
procedure TCustomECGroupCtrl.SetUncheckedFontColor(AValue: TColor);
begin
if FUncheckedFontColor=AValue then exit;
FUncheckedFontColor:=AValue;
Redraw;
end;
procedure TCustomECGroupCtrl.SetUncheckedFontStyles(AValue: TFontStyles);
begin
if FUncheckedFontStyles=AValue then exit;
FUncheckedFontStyles:=AValue;
Redraw;
end;
{ TCustomECRadioGroup }
constructor TCustomECRadioGroup.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FItemIndex:=-1;
Items.OnCheckedChange:=@GroupCtrlItemCheckedChanged;
Items.OnClick:=@GroupCtrlItemClick;
FOptions:=cDefRGOptions;
end;
function TCustomECRadioGroup.GetElementDetails(AIState: TItemState): TThemedElementDetails;
const caElements: array [low(TItemState)..high(TItemState)] of TThemedButton =
(tbRadioButtonUncheckedDisabled, tbRadioButtonUncheckedHot, tbRadioButtonUncheckedNormal,
tbRadioButtonCheckedNormal, tbRadioButtonCheckedHot, tbRadioButtonCheckedDisabled);
begin
Result:=ThemeServices.GetElementDetails(caElements[AIState]);
end;
procedure TCustomECRadioGroup.GroupCtrlItemCheckedChanged(AIndex: Integer);
var i: Integer;
begin
if Items[AIndex].Checked then
begin
for i:=0 to AIndex-1 do
TGroupCtrlItem(Items[i]).FChecked:=False;
for i:=AIndex+1 to Items.Count-1 do
TGroupCtrlItem(Items[i]).FChecked:=False;
ItemIndex:=AIndex;
end else
ItemIndex:=-1;
end;
procedure TCustomECRadioGroup.GroupCtrlItemClick(AIndex: Integer);
begin
if not (egoAllowAllUp in Options)
then Items[AIndex].Checked:=True { default }
else Items[AIndex].Checked:= not Items[AIndex].Checked;
end;
procedure TCustomECRadioGroup.SetItemIndex(AValue: SmallInt);
var anOldIndex: SmallInt;
begin
anOldIndex:=FItemIndex;
if (anOldIndex=AValue) or (AValue>=Items.Count)
or ((anOldIndex<0) and (AValue<0)) then exit;
FItemIndex:=AValue;
if anOldIndex>=0 then
begin
Items[anOldIndex].FChecked:=False;
if FInvalidRect.Left<0
then FInvalidRect:=Items[anOldIndex].FItemRect
else IncludeRectangle(FInvalidRect, Items[anOldIndex].FItemRect);
end;
if AValue>=0 then
begin
Items[AValue].FChecked:=True;
if FInvalidRect.Left<0
then FInvalidRect:=Items[AValue].FItemRect
else IncludeRectangle(FInvalidRect, Items[AValue].FItemRect);
end;
if RedrawMode<=ermFreeRedraw then
begin
RedrawMode:=ermMoveKnob;
InvalidateCustomRect(False);
end else
InvalidateNonUpdated;
if assigned(OnSelectionChange) then OnSelectionChange(self);
end;
{ TCustomECCheckGroup }
constructor TCustomECCheckGroup.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Items.OnCheckedChange:=@GroupCtrlItemCheckedChanged;
Items.OnClick:=@GroupCtrlItemClick;
FOptions:=cDefCGOptions;
end;
procedure TCustomECCheckGroup.GroupCtrlItemCheckedChanged(AIndex: Integer);
begin
if assigned(OnItemClick) then OnItemClick(self, AIndex);
end;
procedure TCustomECCheckGroup.GroupCtrlItemClick(AIndex: Integer);
var i: Integer;
bFound, bValue: Boolean;
begin
bValue:=Items[AIndex].Checked;
if (egoAllowAllUp in Options) or not bValue
then Items[AIndex].Checked:= not bValue { default }
else
begin { at least one checkbox must stay Checked }
bFound:=False;
for i:=0 to AIndex-1 do
if Items[i].Checked then
begin
bFound:=True;
break;
end;
if not bFound then
for i:=AIndex+1 to Items.Count-1 do
if Items[i].Checked then
begin
bFound:=True;
break;
end;
if bFound then Items[AIndex].Checked:= not bValue;
end;
end;
function TCustomECCheckGroup.GetElementDetails(AIState: TItemState): TThemedElementDetails;
const caElements: array [low(TItemState)..high(TItemState)] of TThemedButton =
(tbCheckBoxUncheckedDisabled, tbCheckBoxUncheckedHot, tbCheckBoxUncheckedNormal,
tbCheckBoxCheckedNormal, tbCheckBoxCheckedHot, tbCheckBoxCheckedDisabled);
begin
Result:=ThemeServices.GetElementDetails(caElements[AIState]);
end;
function TCustomECCheckGroup.GetChecked(Index: SmallInt): Boolean;
begin
Result:=Items[Index].Checked;
end;
procedure TCustomECCheckGroup.SetChecked(Index: SmallInt; AValue: Boolean);
begin
Items[Index].Checked:=AValue;
end;
procedure Register;
begin
{$I ecgroupctrls.lrs}
RegisterComponents('EC-C', [TECRadioGroup, TECCheckGroup]);
end;
end.