From 277ce7472ce02921a9608bdc15ad660c5abca926 Mon Sep 17 00:00:00 2001 From: wp_xyz Date: Wed, 13 Oct 2021 18:45:08 +0200 Subject: [PATCH] LCL: Move TCheckCombobox to LazControls --- components/lazcontrols/checkcombo.pas | 603 ++++++++++++++++++ .../design/registerlazcontrols.pas | 4 +- .../lazcontrols/images/lazcontrols_list.txt | 3 + .../lazcontrols/images}/tcheckcombobox.png | Bin .../images}/tcheckcombobox_150.png | Bin .../images}/tcheckcombobox_200.png | Bin components/lazcontrols/lazcontrols.lpk | 10 +- components/lazcontrols/lazcontrols.pas | 3 +- components/lazcontrols/lazcontrols.res | Bin 30669 -> 32045 bytes .../languages/lazutilsstrconsts.cs.po | 39 +- .../languages/lazutilsstrconsts.de.po | 39 +- .../languages/lazutilsstrconsts.es.po | 39 +- .../languages/lazutilsstrconsts.fr.po | 39 +- .../languages/lazutilsstrconsts.hu.po | 39 +- .../languages/lazutilsstrconsts.it.po | 39 +- .../languages/lazutilsstrconsts.lt.po | 39 +- .../languages/lazutilsstrconsts.pl.po | 39 +- .../lazutils/languages/lazutilsstrconsts.pot | 39 +- .../languages/lazutilsstrconsts.pt_BR.po | 39 +- .../languages/lazutilsstrconsts.ru.po | 39 +- .../languages/lazutilsstrconsts.tr.po | 39 +- .../languages/lazutilsstrconsts.uk.po | 39 +- .../languages/lazutilsstrconsts.zh_CN.po | 39 +- images/components_images.res | Bin 360848 -> 359472 bytes images/components_images_list.txt | 3 - lcl/comboex.pas | 142 +---- lcl/include/comboex.inc | 416 ------------ 27 files changed, 1080 insertions(+), 650 deletions(-) create mode 100644 components/lazcontrols/checkcombo.pas rename {images/components => components/lazcontrols/images}/tcheckcombobox.png (100%) rename {images/components => components/lazcontrols/images}/tcheckcombobox_150.png (100%) rename {images/components => components/lazcontrols/images}/tcheckcombobox_200.png (100%) diff --git a/components/lazcontrols/checkcombo.pas b/components/lazcontrols/checkcombo.pas new file mode 100644 index 0000000000..ffe85e3f2a --- /dev/null +++ b/components/lazcontrols/checkcombo.pas @@ -0,0 +1,603 @@ +{ Visual component TCheckComboBox + + Copyright (C) 2014 Vojtěch Čihák, e-mail: cihakvjtch@seznam.cz + + This library is free software; you can redistribute it and/or modify it under the terms of the + GNU Library General Public License as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version with the following modification: + + As a special exception, the copyright holders of this library give you permission to link this + library with independent modules to produce an executable, regardless of the license terms of + these independent modules,and to copy and distribute the resulting executable under terms of + your choice, provided that you also meet, for each linked independent module, the terms and + conditions of the license of that module. An independent module is a module which is not derived + from or based on this library. If you modify this library, you may extend this exception to your + version of the library, but you are not obligated to do so. If you do not wish to do so, delete + this exception statement from your version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + the GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License along with this + library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth + Floor, Boston, MA 02110-1335, USA. +} + +unit CheckCombo; +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, types, + LCLIntf, LCLType, LMessages, LResources, LazLoggerBase, + ImgList, Controls, StdCtrls, ComCtrls, ExtCtrls, Graphics, GraphUtil, + Themes, Forms; + +type + { Events } + TCheckItemChange = procedure(Sender: TObject; AIndex: Integer) of object; + + { TCheckComboItemState } + TCheckComboItemState = class + public + State: TCheckBoxState; + Enabled: Boolean; + Data: TObject; + end; + + { TCustomCheckCombo } + TCustomCheckCombo = class(TCustomComboBox) + private + FAllowGrayed: Boolean; + FOnItemChange: TCheckItemChange; + procedure AsyncCheckItemStates(Data: PtrInt); + function GetChecked(AIndex: Integer): Boolean; + function GetCount: Integer; + function GetItemEnabled(AIndex: Integer): Boolean; + function GetObject(AIndex: Integer): TObject; + function GetState(AIndex: Integer): TCheckBoxState; + procedure SetChecked(AIndex: Integer; AValue: Boolean); + procedure SetItemEnabled(AIndex: Integer; AValue: Boolean); + procedure SetObject(AIndex: Integer; AValue: TObject); + procedure SetState(AIndex: Integer; AValue: TCheckBoxState); + protected + FCheckHighlight: Boolean; + FCheckSize: TSize; + FDropped: Boolean; + FHilightedIndex: Integer; + FHiLiteLeft: Integer; + FHiLiteRight: Integer; + FNeedMeasure: Boolean; + FRejectDropDown: Boolean; + FRejectToggleOnSelect: Boolean; + FRightToLeft: Boolean; + FTextHeight: SmallInt; + procedure CMBiDiModeChanged(var Message: TLMessage); message CM_BIDIMODECHANGED; + procedure ClearItemStates; + procedure CloseUp; override; + procedure DrawItem(Index: Integer; ARect: TRect; State: TOwnerDrawState); override; + procedure DropDown; override; + procedure FontChanged(Sender: TObject); override; + procedure InitializeWnd; override; + procedure InitItemStates; + procedure CheckItemStates; + procedure QueueCheckItemStates; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure Loaded; override; + procedure MouseLeave; override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure SetItemHeight(const AValue: Integer); override; + procedure SetItems(const Value: TStrings); override; + procedure Select; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure AddItem(const AItem: string; AState: TCheckBoxState; AEnabled: Boolean = True); reintroduce; + procedure AssignItems(AItems: TStrings); + procedure Clear; override; + procedure DeleteItem(AIndex: Integer); + procedure CheckAll(AState: TCheckBoxState; AAllowGrayed: Boolean = True; AAllowDisabled: Boolean = True); + procedure Toggle(AIndex: Integer); + property AllowGrayed: Boolean read FAllowGrayed write FAllowGrayed default False; + property Count: Integer read GetCount; + property Checked[AIndex: Integer]: Boolean read GetChecked write SetChecked; + property ItemEnabled[AIndex: Integer]: Boolean read GetItemEnabled write SetItemEnabled; + property Objects[AIndex: Integer]: TObject read GetObject write SetObject; + property State[AIndex: Integer]: TCheckBoxState read GetState write SetState; + property OnItemChange: TCheckItemChange read FOnItemChange write FOnItemChange; + end; + + { TCheckComboBox } + TCheckComboBox = class(TCustomCheckCombo) + published + property Align; + property AllowGrayed; + property Anchors; + property ArrowKeysTraverseList; + property AutoDropDown; + property AutoSize; + property BidiMode; + property BorderSpacing; + property BorderStyle; + property Color; + property Constraints; + property Count; + property DragCursor; + property DragKind; + property DragMode; + property DropDownCount; + property Enabled; + property Font; + property ItemHeight; + property ItemIndex; + property Items; + property ItemWidth; + property MaxLength; + property OnChange; + property OnChangeBounds; + property OnClick; + property OnCloseUp; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDrag; + property OnDropDown; + property OnEditingDone; + property OnEnter; + property OnExit; + property OnGetItems; + property OnItemChange; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnMouseWheel; + property OnMouseWheelDown; + property OnMouseWheelUp; + property OnStartDrag; + property OnSelect; + property OnUTF8KeyPress; + property ParentBidiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Sorted; + property TabOrder; + property TabStop; + property Text; + property TextHint; + property Visible; + end; + + +implementation + +{ TCustomCheckCombo } + +constructor TCustomCheckCombo.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + TStringList(Items).Duplicates:=dupIgnore; + Style:=csOwnerDrawFixed; + FNeedMeasure:=True; + FRejectToggleOnSelect:=True; +end; + +destructor TCustomCheckCombo.Destroy; +begin + ClearItemStates; + inherited Destroy; +end; + +procedure TCustomCheckCombo.AddItem(const AItem: string; AState: TCheckBoxState; AEnabled: Boolean); +var pItemState: TCheckComboItemState; +begin + pItemState:=TCheckComboItemState.Create; + pItemState.State:=aState; + pItemState.Enabled:=AEnabled; + pItemState.Data:=nil; + inherited AddItem(AItem, pItemState); +end; + +procedure TCustomCheckCombo.AssignItems(AItems: TStrings); +begin + ClearItemStates; + Items.Assign(AItems); + InitItemStates; +end; + +procedure TCustomCheckCombo.CheckAll(AState: TCheckBoxState; AAllowGrayed: Boolean; + AAllowDisabled: Boolean); +var i: Integer; +begin + for i:=0 to Items.Count-1 do + begin + if (AAllowGrayed or (State[i]<>cbGrayed)) and (AAllowDisabled or ItemEnabled[i]) + then State[i]:=AState; + end; +end; + +procedure TCustomCheckCombo.Clear; +begin + ClearItemStates; + inherited Clear; +end; + +procedure TCustomCheckCombo.ClearItemStates; +var i: Integer; +begin + for i:=0 to Items.Count-1 do + begin + Items.Objects[i].Free; + Items.Objects[i]:=nil; + end; +end; + +procedure TCustomCheckCombo.CloseUp; +begin + FDropped:=False; + if FRejectDropDown then + begin + FRejectDropDown:=False; + Update; + end else + inherited CloseUp; +end; + +procedure TCustomCheckCombo.CMBiDiModeChanged(var Message: TLMessage); +begin + inherited CMBiDiModeChanged(Message); + FRightToLeft:=IsRightToLeft; + FNeedMeasure:=True; + Invalidate; +end; + +procedure TCustomCheckCombo.DeleteItem(AIndex: Integer); +begin + if (AIndex>=0) and (AIndex0) and not aDropped); + {$ELSE} + aFocusedEditableMainItemNoDD := False; + {$ENDIF} + if (ARect.Left=0) or aFocusedEditableMainItemNoDD then + begin + if odSelected in State then + begin + if not aEnabled then + begin + aGray:=ColorToGray(Canvas.Brush.Color); + Canvas.Brush.Color:=RGBToColor(aGray, aGray, aGray); + end; + end else + Canvas.Brush.Color:=clWindow; + Canvas.Brush.Style:=bsSolid; + Canvas.FillRect(ARect); + end; + if not (csDesigning in ComponentState) + then aState:=ItemState.State + else aState:=cbUnchecked; + aDetail:=ThemeServices.GetElementDetails(caCheckThemes + [aEnabled, aState, not aDropped and FCheckHighlight]); + if FNeedMeasure then + begin + FCheckSize:=ThemeServices.GetDetailSize(aDetail); + FTextHeight:=Canvas.TextHeight('ŠjÁÇ'); + if not aDropped then + begin + if not FRightToLeft then + begin + FHiLiteLeft:=-1; + FHiLiteRight:=ARect.Right; + end else + begin + FHiLiteLeft:=ARect.Left; + FHiLiteRight:=ARect.Right; + end; + FNeedMeasure := False; + end; + end; + if not FRightToLeft + then anyRect.Left:=ARect.Left+cCheckIndent + else anyRect.Left:=ARect.Right-cCheckIndent-FCheckSize.cx; + anyRect.Right:=anyRect.Left+FCheckSize.cx; + anyRect.Top:=(ARect.Bottom+ARect.Top-FCheckSize.cy) div 2; + anyRect.Bottom:=anyRect.Top+FCheckSize.cy; + ThemeServices.DrawElement(Canvas.Handle, aDetail, anyRect); + Canvas.Brush.Style:=bsClear; + if (not (odSelected in State) or not aDropped) and not aFocusedEditableMainItemNoDD + then Canvas.Font.Color:=clWindowText + else begin + Canvas.Font.Color:=clHighlightText; + FHilightedIndex:=Index; + end; + if aFocusedEditableMainItemNoDD then + begin + LCLIntf.SetBkColor(Canvas.Handle, ColorToRGB(clBtnFace)); + LCLIntf.DrawFocusRect(Canvas.Handle, aRect); + end; + aFlags:=DT_END_ELLIPSIS+DT_VCENTER+DT_SINGLELINE+DT_NOPREFIX; + if not FRightToLeft then + begin + anyRect.Left:=ARect.Left+cCheckIndent+FCheckSize.cx+cTextIndent; + anyRect.Right:=ARect.Right; + end else + begin + anyRect.Right:=anyRect.Left-cTextIndent; + anyRect.Left:=ARect.Left; + aFlags:=aFlags or DT_RIGHT or DT_RTLREADING; + end; + anyRect.Top:=(ARect.Top+ARect.Bottom-FTextHeight) div 2; + anyRect.Bottom:=anyRect.Top+FTextHeight; + DrawText(Canvas.Handle, PChar(Items[Index]), Length(Items[Index]), anyRect, aFlags); +end; + +procedure TCustomCheckCombo.DropDown; +{$IF DEFINED(LCLWin32) or DEFINED(LCLWin64)} +{$ELSE} +var aCursorPos: TPoint; + aRect: TRect; +{$ENDIF} +begin + {$IF DEFINED(LCLWin32) or DEFINED(LCLWin64)} + FRejectDropDown:=False; + {$ELSE} + aCursorPos:=ScreenToControl(Mouse.CursorPos); + aRect:=Rect(FHiLiteLeft, 0, FHiLiteRight, Height); + FRejectDropDown:=PtInRect(aRect, aCursorPos); + {$ENDIF} + FDropped:=True; + if not FRejectDropDown then + begin + inherited DropDown; + FRejectToggleOnSelect:=False; + end else + if (ItemIndex>=0) and ItemEnabled[ItemIndex] then Toggle(ItemIndex); +end; + +procedure TCustomCheckCombo.FontChanged(Sender: TObject); +begin + FNeedMeasure:=True; + inherited FontChanged(Sender); +end; + +procedure TCustomCheckCombo.InitializeWnd; +begin + InitItemStates; + inherited InitializeWnd; + CheckItemStates; + FRightToLeft:=IsRightToLeft; +end; + +procedure TCustomCheckCombo.InitItemStates; +var i: Integer; + pItemState: TCheckComboItemState; +begin + for i:=0 to Items.Count-1 do + if Items.Objects[i]=nil then begin + pItemState:=TCheckComboItemState.Create; + pItemState.Enabled:=True; + pItemState.State:=cbUnchecked; + pItemState.Data:=nil; + Items.Objects[i]:=pItemState; + end else if not (Items.Objects[i] is TCheckComboItemState) then + raise Exception.Create(DbgSName(Self)+': Item '+IntToStr(i)+' is not a TCheckComboItemState'); +end; + +procedure TCustomCheckCombo.CheckItemStates; +var + i: Integer; +begin + for i:=0 to Items.Count-1 do + if not (Items.Objects[i] is TCheckComboItemState) then + raise Exception.Create(DbgSName(Self)+': Item '+IntToStr(i)+' is not a TCheckComboItemState'); +end; + +procedure TCustomCheckCombo.QueueCheckItemStates; +begin + Application.QueueAsyncCall(@AsyncCheckItemStates,0); +end; + +procedure TCustomCheckCombo.KeyDown(var Key: Word; Shift: TShiftState); +begin + case Key of + VK_RETURN: + if FDropped then + if (ItemIndex=FHilightedIndex) and ItemEnabled[ItemIndex] then Toggle(ItemIndex); + VK_SPACE: + if DroppedDown then + if (ItemIndex>=0) and ItemEnabled[ItemIndex] then + begin + if ItemIndex<>FHilightedIndex then + begin + ItemIndex:=FHilightedIndex; + inherited Select; + end; + Toggle(ItemIndex); + DroppedDown:=False; + end; + end; + inherited KeyDown(Key, Shift); +end; + +procedure TCustomCheckCombo.Loaded; +begin + inherited Loaded; + InitItemStates; +end; + +procedure TCustomCheckCombo.MouseLeave; +begin + FCheckHighlight:=False; + inherited MouseLeave; +end; + +procedure TCustomCheckCombo.MouseMove(Shift: TShiftState; X, Y: Integer); +var aHighlight: Boolean; +begin + inherited MouseMove(Shift, X, Y); + aHighlight:=((X>FHiLiteLeft) and (XFCheckHighlight then + begin + FCheckHighlight:=aHighlight; + Invalidate; + end; +end; + +procedure TCustomCheckCombo.Select; +begin + inherited Select; + {$IF DEFINED(LCLWin32) or DEFINED(LCLWin64)} + if DroppedDown then FRejectToggleOnSelect:=True; + {$ENDIF} + if not FRejectToggleOnSelect then + begin + if (ItemIndex >= 0) and ItemEnabled[ItemIndex] then Toggle(ItemIndex); + FRejectToggleOnSelect:=True; + end; + FDropped:=False; +end; + +procedure TCustomCheckCombo.SetItemHeight(const AValue: Integer); +begin + inherited SetItemHeight(AValue); + FNeedMeasure:=True; +end; + +procedure TCustomCheckCombo.SetItems(const Value: TStrings); +begin + ClearItemStates; + inherited SetItems(Value); + InitItemStates; +end; + +procedure TCustomCheckCombo.Toggle(AIndex: Integer); +const caNewStateMap: array [TCheckBoxState, Boolean] of TCheckBoxState = + { False (AllowGrayed) True } + ((cbChecked, cbGrayed), { cbUnchecked } + (cbUnChecked, cbUnChecked), { cbChecked } + (cbChecked, cbChecked)); { cbGrayed } +begin + State[AIndex]:=caNewStateMap[State[AIndex], AllowGrayed]; +end; + +{ TCustomCheckCombo.Getters and Setters } + +function TCustomCheckCombo.GetChecked(AIndex: Integer): Boolean; +begin + Result:=(TCheckComboItemState(Items.Objects[AIndex]).State=cbChecked); +end; + +procedure TCustomCheckCombo.AsyncCheckItemStates(Data: PtrInt); +begin + CheckItemStates; +end; + +function TCustomCheckCombo.GetCount: Integer; +begin + Result:=Items.Count; +end; + +function TCustomCheckCombo.GetItemEnabled(AIndex: Integer): Boolean; +begin + Result:=TCheckComboItemState(Items.Objects[AIndex]).Enabled; +end; + +function TCustomCheckCombo.GetObject(AIndex: Integer): TObject; +begin + Result:=TCheckComboItemState(Items.Objects[AIndex]).Data; +end; + +function TCustomCheckCombo.GetState(AIndex: Integer): TCheckBoxState; +begin + Result:=TCheckComboItemState(Items.Objects[AIndex]).State; +end; + +procedure TCustomCheckCombo.SetChecked(AIndex: Integer; AValue: Boolean); +begin + if AValue=(TCheckComboItemState(Items.Objects[AIndex]).State=cbChecked) then exit; + if AValue + then TCheckComboItemState(Items.Objects[AIndex]).State:=cbChecked + else TCheckComboItemState(Items.Objects[AIndex]).State:=cbUnchecked; + if Assigned(FOnItemChange) then + FOnItemChange(Self, AIndex); + if AIndex=ItemIndex then + Invalidate; +end; + +procedure TCustomCheckCombo.SetItemEnabled(AIndex: Integer; AValue: Boolean); +begin + if TCheckComboItemState(Items.Objects[AIndex]).Enabled=AValue then exit; + TCheckComboItemState(Items.Objects[AIndex]).Enabled:=AValue; + if AIndex=ItemIndex then + Invalidate; +end; + +procedure TCustomCheckCombo.SetObject(AIndex: Integer; AValue: TObject); +begin + TCheckComboItemState(Items.Objects[AIndex]).Data:=AValue; +end; + +procedure TCustomCheckCombo.SetState(AIndex: Integer; AValue: TCheckBoxState); +begin + if TCheckComboItemState(Items.Objects[AIndex]).State=AValue then exit; + TCheckComboItemState(Items.Objects[AIndex]).State:=AValue; + if Assigned(FOnItemChange) then + FOnItemChange(self, AIndex); + if AIndex=ItemIndex then + Invalidate; +end; + + +end. + + diff --git a/components/lazcontrols/design/registerlazcontrols.pas b/components/lazcontrols/design/registerlazcontrols.pas index acf8b5440b..4b2f162c1a 100644 --- a/components/lazcontrols/design/registerlazcontrols.pas +++ b/components/lazcontrols/design/registerlazcontrols.pas @@ -6,7 +6,7 @@ interface uses Classes, SysUtils, ExtendedTabControls, ComponentEditors, ObjInspStrConsts, PropEdits, - ComCtrls, CheckBoxThemed, DividerBevel, ExtendedNotebook, ListFilterEdit, + ComCtrls, CheckBoxThemed, CheckCombo, DividerBevel, ExtendedNotebook, ListFilterEdit, ListViewFilterEdit, LvlGraphCtrl, ShortPathEdit, SpinEx, TreeFilterEdit; type @@ -33,7 +33,7 @@ begin RegisterComponents('LazControls', [TCheckBoxThemed, TDividerBevel, TExtendedNotebook, TListFilterEdit, TListViewFilterEdit, TLvlGraphControl, TShortPathEdit, TSpinEditEx, TFloatSpinEditEx, - TTreeFilterEdit, TExtendedTabControl]); + TTreeFilterEdit, TExtendedTabControl, TCheckComboBox]); //RegisterPropertyEditor(TypeInfo(TCaption), TCheckBoxThemed, 'Caption', TStringMultilinePropertyEditor); RegisterNoIcon([TExtendedTabToolbar, TExtendedTabToolButton, TExtendedTabSheet]); RegisterComponentEditor(TExtendedTabControl, TExtendedTabControlComponentEditor); diff --git a/components/lazcontrols/images/lazcontrols_list.txt b/components/lazcontrols/images/lazcontrols_list.txt index a42ee5d1d7..db3c727447 100644 --- a/components/lazcontrols/images/lazcontrols_list.txt +++ b/components/lazcontrols/images/lazcontrols_list.txt @@ -1,6 +1,9 @@ tcheckboxthemed.png tcheckboxthemed_150.png tcheckboxthemed_200.png +tcheckcombobox.png +tcheckcombobox_150.png +tcheckcombobox_200.png tdividerbevel.png tdividerbevel_150.png tdividerbevel_200.png diff --git a/images/components/tcheckcombobox.png b/components/lazcontrols/images/tcheckcombobox.png similarity index 100% rename from images/components/tcheckcombobox.png rename to components/lazcontrols/images/tcheckcombobox.png diff --git a/images/components/tcheckcombobox_150.png b/components/lazcontrols/images/tcheckcombobox_150.png similarity index 100% rename from images/components/tcheckcombobox_150.png rename to components/lazcontrols/images/tcheckcombobox_150.png diff --git a/images/components/tcheckcombobox_200.png b/components/lazcontrols/images/tcheckcombobox_200.png similarity index 100% rename from images/components/tcheckcombobox_200.png rename to components/lazcontrols/images/tcheckcombobox_200.png diff --git a/components/lazcontrols/lazcontrols.lpk b/components/lazcontrols/lazcontrols.lpk index 2ab3179ade..830a27b9da 100644 --- a/components/lazcontrols/lazcontrols.lpk +++ b/components/lazcontrols/lazcontrols.lpk @@ -1,6 +1,6 @@ - + @@ -19,7 +19,7 @@ - + @@ -68,7 +68,12 @@ + + + + + @@ -80,7 +85,6 @@ - <_ExternHelp Items="Count"/> diff --git a/components/lazcontrols/lazcontrols.pas b/components/lazcontrols/lazcontrols.pas index 8f98228888..c899c0cfa8 100644 --- a/components/lazcontrols/lazcontrols.pas +++ b/components/lazcontrols/lazcontrols.pas @@ -10,7 +10,8 @@ interface uses CheckBoxThemed, DividerBevel, ExtendedNotebook, ListFilterEdit, ListViewFilterEdit, TreeFilterEdit, ShortPathEdit, LvlGraphCtrl, - ExtendedTabControls, SpinEx, SmallOrderedSetEditor, LazarusPackageIntf; + ExtendedTabControls, SpinEx, SmallOrderedSetEditor, CheckCombo, + LazarusPackageIntf; implementation diff --git a/components/lazcontrols/lazcontrols.res b/components/lazcontrols/lazcontrols.res index 4fb094b6e9cadd733ee5ad8a13e81de71195fc99..b5f1fcda41036c00669ba8e7e43221d3607c82cb 100644 GIT binary patch delta 963 zcmX^6o^kCj#ti}-jA0WM#d)0>{26>1oPZ<{Pi|Cgsb{$C>EamT(fM}DUfyN{f!6&l z@AhF${s}}qb5Mr9xG$nlQo6EobzUv&mSGq$)sp!@z zlVcXYX1(rS_gYMn_i%&Zvt{Qty;=7B$Hy5B-{(yc(p25^eX?!Zr!T&uu8xt@7)*RO z+a8FrmWs}fXMXp+etTAQj9BI24Kpk?+^%j1BE7>@&^>|SoKBT^AP2SwH}s)P!(WRD(ddG726vTda)KyqI$KuX?_EVcwCV#Za|8^$mr<3N>l)K+;SFO5rXK~1i zb=fMOMkfl+T{P*nTWI2YahvWV3%2JnJ%%myi7Wg$7+M5g?BeS&bP3#IZO^@xt3{wa zJ>ALs@rRw(ays z7V+E&XJO|4%U&pT7W4iev!gCr^NeAj?A(` z<_o?!K46MzXj|*xwCsW37ZJ~`nh}C$?)SMqTRp*D?(AmU&ngUUKkwI^5nrV7Ynet$ z@3!3dEY^ne<>EzV@!pNgGVetmS1OeGFR8w}u~4S`=(7o&CqB!BhVETsFUK$9nm8xD z{v&6s@2q7UO$>dH6+DF)9Ad8rcrAQi{n#djsYO7djd9=mX+5N#ePp zFayK9=L=t3wIp&dT!?b^+NsIDl7V4DkW=>G-+M)i7!T|_G+&1+V)p)R2mESGuUUPJ zTx0g}66cK~XSd*txHZ1Kb*CiGZhBMDw@Ih`?e6G${uvv-e>r!+qro@7?%XPd=w)Yx zzQ1Su*4VxA82h}Oxfwu?@C|mp19lF)zZpzZ>ez^;Jd8)Mdw`x=K0w)|m` UP>e6zaV+`|a-eVKP!`^kc z6e4ok$~49}`kL#DuIm;V4a0yj=BCcF?55}V@tA=3o|Fep^; zoL+t(00000NkvXXu0mjf004Ud002Y)009603IJ39LjXtsMU!ux1(U+d9+Td=e1G^! zL_t(oh3%KS4TCTgMQ>0lHt{M*z!Vk?Kmi@S3rfTqSd76GtN|od5QJ|~{2UaY&gfYj zp?i@H7%s+byl`FjK`kJqoH*Ry2gr9VSlJk2mpi-=(-M!F+@?cJ3kAx3WN}cXJ_wQbKF}`@I!%0l>b(pDYSko4>ZePJA`iI`LVo zHu2I4*m6TgQ)phSO$~m^7|pWmaE`JpckR1>P7j!{_w>%dNPtame$J`@Tc*tt_wNDr zfs3)m2cB%5X!q{{6W9k1z&=0?`v5g$K5*9Lx_=Ltz&>yQ_5o`6-zdW{wEO@VAzya5 b##{V@a-@fHqydL=qymR>qyx8dqy)a#{aC30 diff --git a/images/components_images_list.txt b/images/components_images_list.txt index b4ffa27bfe..f59b60e04a 100644 --- a/images/components_images_list.txt +++ b/images/components_images_list.txt @@ -43,9 +43,6 @@ components/tcalendardialog_200.png components/tcheckbox.png components/tcheckbox_150.png components/tcheckbox_200.png -components/tcheckcombobox.png -components/tcheckcombobox_150.png -components/tcheckcombobox_200.png components/tcheckgroup.png components/tcheckgroup_150.png components/tcheckgroup_200.png diff --git a/lcl/comboex.pas b/lcl/comboex.pas index dc3eaa8512..a42c43f2e3 100644 --- a/lcl/comboex.pas +++ b/lcl/comboex.pas @@ -49,7 +49,6 @@ type TListItemsCompare = function (AList: TListControlItems; AItem1, AItem2: Integer): Integer; TListItemsSortType = TSortType; { Events } - TCheckItemChange = procedure(Sender: TObject; AIndex: Integer) of object; TListControlItem = class; { forward } TListCompareEvent = function(AList: TListControlItems; AItem1, AItem2: TListControlItem): Integer of object; @@ -258,145 +257,6 @@ type property Visible; end; - { TCheckComboItemState } - TCheckComboItemState = class - public - State: TCheckBoxState; - Enabled: Boolean; - Data: TObject; - end; - - { TCustomCheckCombo } - TCustomCheckCombo = class(TCustomComboBox) - private - FAllowGrayed: Boolean; - FOnItemChange: TCheckItemChange; - procedure AsyncCheckItemStates(Data: PtrInt); - function GetChecked(AIndex: Integer): Boolean; - function GetCount: Integer; - function GetItemEnabled(AIndex: Integer): Boolean; - function GetObject(AIndex: Integer): TObject; - function GetState(AIndex: Integer): TCheckBoxState; - procedure SetChecked(AIndex: Integer; AValue: Boolean); - procedure SetItemEnabled(AIndex: Integer; AValue: Boolean); - procedure SetObject(AIndex: Integer; AValue: TObject); - procedure SetState(AIndex: Integer; AValue: TCheckBoxState); - protected - FCheckHighlight: Boolean; - FCheckSize: TSize; - FDropped: Boolean; - FHilightedIndex: Integer; - FHiLiteLeft: Integer; - FHiLiteRight: Integer; - FNeedMeasure: Boolean; - FRejectDropDown: Boolean; - FRejectToggleOnSelect: Boolean; - FRightToLeft: Boolean; - FTextHeight: SmallInt; - procedure CMBiDiModeChanged(var Message: TLMessage); message CM_BIDIMODECHANGED; - procedure ClearItemStates; - procedure CloseUp; override; - procedure DrawItem(Index: Integer; ARect: TRect; State: TOwnerDrawState); override; - procedure DropDown; override; - procedure FontChanged(Sender: TObject); override; - procedure InitializeWnd; override; - procedure InitItemStates; - procedure CheckItemStates; - procedure QueueCheckItemStates; - procedure KeyDown(var Key: Word; Shift: TShiftState); override; - procedure Loaded; override; - procedure MouseLeave; override; - procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; - procedure SetItemHeight(const AValue: Integer); override; - procedure SetItems(const Value: TStrings); override; - procedure Select; override; - public - constructor Create(AOwner: TComponent); override; - destructor Destroy; override; - procedure AddItem(const AItem: string; AState: TCheckBoxState; AEnabled: Boolean = True); reintroduce; - procedure AssignItems(AItems: TStrings); - procedure Clear; override; - procedure DeleteItem(AIndex: Integer); - procedure CheckAll(AState: TCheckBoxState; AAllowGrayed: Boolean = True; AAllowDisabled: Boolean = True); - procedure Toggle(AIndex: Integer); - property AllowGrayed: Boolean read FAllowGrayed write FAllowGrayed default False; - property Count: Integer read GetCount; - property Checked[AIndex: Integer]: Boolean read GetChecked write SetChecked; - property ItemEnabled[AIndex: Integer]: Boolean read GetItemEnabled write SetItemEnabled; - property Objects[AIndex: Integer]: TObject read GetObject write SetObject; - property State[AIndex: Integer]: TCheckBoxState read GetState write SetState; - property OnItemChange: TCheckItemChange read FOnItemChange write FOnItemChange; - end; - - { TCheckComboBox } - TCheckComboBox = class(TCustomCheckCombo) - published - property Align; - property AllowGrayed; - property Anchors; - property ArrowKeysTraverseList; - property AutoDropDown; - property AutoSize; - property BidiMode; - property BorderSpacing; - property BorderStyle; - property Color; - property Constraints; - property Count; - property DragCursor; - property DragKind; - property DragMode; - property DropDownCount; - property Enabled; - property Font; - property ItemHeight; - property ItemIndex; - property Items; - property ItemWidth; - property MaxLength; - property OnChange; - property OnChangeBounds; - property OnClick; - property OnCloseUp; - property OnContextPopup; - property OnDblClick; - property OnDragDrop; - property OnDragOver; - property OnEndDrag; - property OnDropDown; - property OnEditingDone; - property OnEnter; - property OnExit; - property OnGetItems; - property OnItemChange; - property OnKeyDown; - property OnKeyPress; - property OnKeyUp; - property OnMouseDown; - property OnMouseEnter; - property OnMouseLeave; - property OnMouseMove; - property OnMouseUp; - property OnMouseWheel; - property OnMouseWheelDown; - property OnMouseWheelUp; - property OnStartDrag; - property OnSelect; - property OnUTF8KeyPress; - property ParentBidiMode; - property ParentColor; - property ParentFont; - property ParentShowHint; - property PopupMenu; - property ShowHint; - property Sorted; - property TabOrder; - property TabStop; - property Text; - property TextHint; - property Visible; - end; - procedure Register; implementation @@ -405,7 +265,7 @@ implementation procedure Register; begin - RegisterComponents('Misc', [TComboBoxEx, TCheckComboBox]); + RegisterComponents('Misc', [TComboBoxEx]); end; end. diff --git a/lcl/include/comboex.inc b/lcl/include/comboex.inc index de8cd0aa9b..230290db29 100644 --- a/lcl/include/comboex.inc +++ b/lcl/include/comboex.inc @@ -485,420 +485,4 @@ begin FStyleEx:=AValue; end; -{ TCustomCheckCombo } - -constructor TCustomCheckCombo.Create(AOwner: TComponent); -begin - inherited Create(AOwner); - TStringList(Items).Duplicates:=dupIgnore; - Style:=csOwnerDrawFixed; - FNeedMeasure:=True; - FRejectToggleOnSelect:=True; -end; - -destructor TCustomCheckCombo.Destroy; -begin - ClearItemStates; - inherited Destroy; -end; - -procedure TCustomCheckCombo.AddItem(const AItem: string; AState: TCheckBoxState; AEnabled: Boolean); -var pItemState: TCheckComboItemState; -begin - pItemState:=TCheckComboItemState.Create; - pItemState.State:=aState; - pItemState.Enabled:=AEnabled; - pItemState.Data:=nil; - inherited AddItem(AItem, pItemState); -end; - -procedure TCustomCheckCombo.AssignItems(AItems: TStrings); -begin - ClearItemStates; - Items.Assign(AItems); - InitItemStates; -end; - -procedure TCustomCheckCombo.CheckAll(AState: TCheckBoxState; AAllowGrayed: Boolean; - AAllowDisabled: Boolean); -var i: Integer; -begin - for i:=0 to Items.Count-1 do - begin - if (AAllowGrayed or (State[i]<>cbGrayed)) and (AAllowDisabled or ItemEnabled[i]) - then State[i]:=AState; - end; -end; - -procedure TCustomCheckCombo.Clear; -begin - ClearItemStates; - inherited Clear; -end; - -procedure TCustomCheckCombo.ClearItemStates; -var i: Integer; -begin - for i:=0 to Items.Count-1 do - begin - Items.Objects[i].Free; - Items.Objects[i]:=nil; - end; -end; - -procedure TCustomCheckCombo.CloseUp; -begin - FDropped:=False; - if FRejectDropDown then - begin - FRejectDropDown:=False; - Update; - end else - inherited CloseUp; -end; - -procedure TCustomCheckCombo.CMBiDiModeChanged(var Message: TLMessage); -begin - inherited CMBiDiModeChanged(Message); - FRightToLeft:=IsRightToLeft; - FNeedMeasure:=True; - Invalidate; -end; - -procedure TCustomCheckCombo.DeleteItem(AIndex: Integer); -begin - if (AIndex>=0) and (AIndex0) and not aDropped); - {$ELSE} - aFocusedEditableMainItemNoDD := False; - {$ENDIF} - if (ARect.Left=0) or aFocusedEditableMainItemNoDD then - begin - if odSelected in State then - begin - if not aEnabled then - begin - aGray:=ColorToGray(Canvas.Brush.Color); - Canvas.Brush.Color:=RGBToColor(aGray, aGray, aGray); - end; - end else - Canvas.Brush.Color:=clWindow; - Canvas.Brush.Style:=bsSolid; - Canvas.FillRect(ARect); - end; - if not (csDesigning in ComponentState) - then aState:=ItemState.State - else aState:=cbUnchecked; - aDetail:=ThemeServices.GetElementDetails(caCheckThemes - [aEnabled, aState, not aDropped and FCheckHighlight]); - if FNeedMeasure then - begin - FCheckSize:=ThemeServices.GetDetailSize(aDetail); - FTextHeight:=Canvas.TextHeight('ŠjÁÇ'); - if not aDropped then - begin - if not FRightToLeft then - begin - FHiLiteLeft:=-1; - FHiLiteRight:=ARect.Right; - end else - begin - FHiLiteLeft:=ARect.Left; - FHiLiteRight:=ARect.Right; - end; - FNeedMeasure := False; - end; - end; - if not FRightToLeft - then anyRect.Left:=ARect.Left+cCheckIndent - else anyRect.Left:=ARect.Right-cCheckIndent-FCheckSize.cx; - anyRect.Right:=anyRect.Left+FCheckSize.cx; - anyRect.Top:=(ARect.Bottom+ARect.Top-FCheckSize.cy) div 2; - anyRect.Bottom:=anyRect.Top+FCheckSize.cy; - ThemeServices.DrawElement(Canvas.Handle, aDetail, anyRect); - Canvas.Brush.Style:=bsClear; - if (not (odSelected in State) or not aDropped) and not aFocusedEditableMainItemNoDD - then Canvas.Font.Color:=clWindowText - else begin - Canvas.Font.Color:=clHighlightText; - FHilightedIndex:=Index; - end; - if aFocusedEditableMainItemNoDD then - begin - LCLIntf.SetBkColor(Canvas.Handle, ColorToRGB(clBtnFace)); - LCLIntf.DrawFocusRect(Canvas.Handle, aRect); - end; - aFlags:=DT_END_ELLIPSIS+DT_VCENTER+DT_SINGLELINE+DT_NOPREFIX; - if not FRightToLeft then - begin - anyRect.Left:=ARect.Left+cCheckIndent+FCheckSize.cx+cTextIndent; - anyRect.Right:=ARect.Right; - end else - begin - anyRect.Right:=anyRect.Left-cTextIndent; - anyRect.Left:=ARect.Left; - aFlags:=aFlags or DT_RIGHT or DT_RTLREADING; - end; - anyRect.Top:=(ARect.Top+ARect.Bottom-FTextHeight) div 2; - anyRect.Bottom:=anyRect.Top+FTextHeight; - DrawText(Canvas.Handle, PChar(Items[Index]), Length(Items[Index]), anyRect, aFlags); -end; - -procedure TCustomCheckCombo.DropDown; -{$IF DEFINED(LCLWin32) or DEFINED(LCLWin64)} -{$ELSE} -var aCursorPos: TPoint; - aRect: TRect; -{$ENDIF} -begin - {$IF DEFINED(LCLWin32) or DEFINED(LCLWin64)} - FRejectDropDown:=False; - {$ELSE} - aCursorPos:=ScreenToControl(Mouse.CursorPos); - aRect:=Rect(FHiLiteLeft, 0, FHiLiteRight, Height); - FRejectDropDown:=PtInRect(aRect, aCursorPos); - {$ENDIF} - FDropped:=True; - if not FRejectDropDown then - begin - inherited DropDown; - FRejectToggleOnSelect:=False; - end else - if (ItemIndex>=0) and ItemEnabled[ItemIndex] then Toggle(ItemIndex); -end; - -procedure TCustomCheckCombo.FontChanged(Sender: TObject); -begin - FNeedMeasure:=True; - inherited FontChanged(Sender); -end; - -procedure TCustomCheckCombo.InitializeWnd; -begin - InitItemStates; - inherited InitializeWnd; - CheckItemStates; - FRightToLeft:=IsRightToLeft; -end; - -procedure TCustomCheckCombo.InitItemStates; -var i: Integer; - pItemState: TCheckComboItemState; -begin - for i:=0 to Items.Count-1 do - if Items.Objects[i]=nil then begin - pItemState:=TCheckComboItemState.Create; - pItemState.Enabled:=True; - pItemState.State:=cbUnchecked; - pItemState.Data:=nil; - Items.Objects[i]:=pItemState; - end else if not (Items.Objects[i] is TCheckComboItemState) then - raise Exception.Create(DbgSName(Self)+': Item '+IntToStr(i)+' is not a TCheckComboItemState'); -end; - -procedure TCustomCheckCombo.CheckItemStates; -var - i: Integer; -begin - for i:=0 to Items.Count-1 do - if not (Items.Objects[i] is TCheckComboItemState) then - raise Exception.Create(DbgSName(Self)+': Item '+IntToStr(i)+' is not a TCheckComboItemState'); -end; - -procedure TCustomCheckCombo.QueueCheckItemStates; -begin - Application.QueueAsyncCall(@AsyncCheckItemStates,0); -end; - -procedure TCustomCheckCombo.KeyDown(var Key: Word; Shift: TShiftState); -begin - case Key of - VK_RETURN: - if FDropped then - if (ItemIndex=FHilightedIndex) and ItemEnabled[ItemIndex] then Toggle(ItemIndex); - VK_SPACE: - if DroppedDown then - if (ItemIndex>=0) and ItemEnabled[ItemIndex] then - begin - if ItemIndex<>FHilightedIndex then - begin - ItemIndex:=FHilightedIndex; - inherited Select; - end; - Toggle(ItemIndex); - DroppedDown:=False; - end; - end; - inherited KeyDown(Key, Shift); -end; - -procedure TCustomCheckCombo.Loaded; -begin - inherited Loaded; - InitItemStates; -end; - -procedure TCustomCheckCombo.MouseLeave; -begin - FCheckHighlight:=False; - inherited MouseLeave; -end; - -procedure TCustomCheckCombo.MouseMove(Shift: TShiftState; X, Y: Integer); -var aHighlight: Boolean; -begin - inherited MouseMove(Shift, X, Y); - aHighlight:=((X>FHiLiteLeft) and (XFCheckHighlight then - begin - FCheckHighlight:=aHighlight; - Invalidate; - end; -end; - -procedure TCustomCheckCombo.Select; -begin - inherited Select; - {$IF DEFINED(LCLWin32) or DEFINED(LCLWin64)} - if DroppedDown then FRejectToggleOnSelect:=True; - {$ENDIF} - if not FRejectToggleOnSelect then - begin - if (ItemIndex >= 0) and ItemEnabled[ItemIndex] then Toggle(ItemIndex); - FRejectToggleOnSelect:=True; - end; - FDropped:=False; -end; - -procedure TCustomCheckCombo.SetItemHeight(const AValue: Integer); -begin - inherited SetItemHeight(AValue); - FNeedMeasure:=True; -end; - -procedure TCustomCheckCombo.SetItems(const Value: TStrings); -begin - ClearItemStates; - inherited SetItems(Value); - InitItemStates; -end; - -procedure TCustomCheckCombo.Toggle(AIndex: Integer); -const caNewStateMap: array [TCheckBoxState, Boolean] of TCheckBoxState = - { False (AllowGrayed) True } - ((cbChecked, cbGrayed), { cbUnchecked } - (cbUnChecked, cbUnChecked), { cbChecked } - (cbChecked, cbChecked)); { cbGrayed } -begin - State[AIndex]:=caNewStateMap[State[AIndex], AllowGrayed]; -end; - -{ TCustomCheckCombo.Getters and Setters } - -function TCustomCheckCombo.GetChecked(AIndex: Integer): Boolean; -begin - Result:=(TCheckComboItemState(Items.Objects[AIndex]).State=cbChecked); -end; - -procedure TCustomCheckCombo.AsyncCheckItemStates(Data: PtrInt); -begin - CheckItemStates; -end; - -function TCustomCheckCombo.GetCount: Integer; -begin - Result:=Items.Count; -end; - -function TCustomCheckCombo.GetItemEnabled(AIndex: Integer): Boolean; -begin - Result:=TCheckComboItemState(Items.Objects[AIndex]).Enabled; -end; - -function TCustomCheckCombo.GetObject(AIndex: Integer): TObject; -begin - Result:=TCheckComboItemState(Items.Objects[AIndex]).Data; -end; - -function TCustomCheckCombo.GetState(AIndex: Integer): TCheckBoxState; -begin - Result:=TCheckComboItemState(Items.Objects[AIndex]).State; -end; - -procedure TCustomCheckCombo.SetChecked(AIndex: Integer; AValue: Boolean); -begin - if AValue=(TCheckComboItemState(Items.Objects[AIndex]).State=cbChecked) then exit; - if AValue - then TCheckComboItemState(Items.Objects[AIndex]).State:=cbChecked - else TCheckComboItemState(Items.Objects[AIndex]).State:=cbUnchecked; - if Assigned(FOnItemChange) then - FOnItemChange(Self, AIndex); - if AIndex=ItemIndex then - Invalidate; -end; - -procedure TCustomCheckCombo.SetItemEnabled(AIndex: Integer; AValue: Boolean); -begin - if TCheckComboItemState(Items.Objects[AIndex]).Enabled=AValue then exit; - TCheckComboItemState(Items.Objects[AIndex]).Enabled:=AValue; - if AIndex=ItemIndex then - Invalidate; -end; - -procedure TCustomCheckCombo.SetObject(AIndex: Integer; AValue: TObject); -begin - TCheckComboItemState(Items.Objects[AIndex]).Data:=AValue; -end; - -procedure TCustomCheckCombo.SetState(AIndex: Integer; AValue: TCheckBoxState); -begin - if TCheckComboItemState(Items.Objects[AIndex]).State=AValue then exit; - TCheckComboItemState(Items.Objects[AIndex]).State:=AValue; - if Assigned(FOnItemChange) then - FOnItemChange(self, AIndex); - if AIndex=ItemIndex then - Invalidate; -end; -