lazcontrols: added TSmallOrderedSetEditDlg

git-svn-id: trunk@56563 -
This commit is contained in:
mattias 2017-11-30 21:20:09 +00:00
parent 28e9959386
commit fb2f71df0f
4 changed files with 505 additions and 1 deletions

2
.gitattributes vendored
View File

@ -2452,6 +2452,8 @@ components/lazcontrols/listfilteredit.pas svneol=native#text/plain
components/lazcontrols/listviewfilteredit.pas svneol=native#text/pascal
components/lazcontrols/lvlgraphctrl.pas svneol=native#text/plain
components/lazcontrols/shortpathedit.pas svneol=native#text/plain
components/lazcontrols/smallorderedseteditor.lfm svneol=native#text/plain
components/lazcontrols/smallorderedseteditor.pas svneol=native#text/plain
components/lazcontrols/spinex.inc svneol=native#text/plain
components/lazcontrols/spinex.pp svneol=native#text/pascal
components/lazcontrols/treefilteredit.pas svneol=native#text/plain

View File

@ -16,7 +16,7 @@
<Description Value="Some extra LCL controls needed by the IDE."/>
<License Value="modified LGPL-2"/>
<Version Major="1" Release="1"/>
<Files Count="11">
<Files Count="12">
<Item1>
<Filename Value="checkboxthemed.pas"/>
<UnitName Value="CheckBoxThemed"/>
@ -61,6 +61,10 @@
<Filename Value="spinex.inc"/>
<Type Value="Include"/>
</Item11>
<Item12>
<Filename Value="smallorderedseteditor.pas"/>
<UnitName Value="SmallOrderedSetEditor"/>
</Item12>
</Files>
<LazDoc Paths="docs"/>
<RequiredPkgs Count="1">

View File

@ -0,0 +1,174 @@
object SmallOrderedSetEditDlg: TSmallOrderedSetEditDlg
Left = 407
Height = 241
Top = 264
Width = 221
Caption = 'SmallOrderedSetEditDlg'
ClientHeight = 241
ClientWidth = 221
LCLVersion = '1.9.0.0'
object ButtonPanel1: TButtonPanel
Left = 6
Height = 36
Top = 199
Width = 209
OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True
HelpButton.Name = 'HelpButton'
HelpButton.DefaultCaption = True
CloseButton.Name = 'CloseButton'
CloseButton.DefaultCaption = True
CancelButton.Name = 'CancelButton'
CancelButton.DefaultCaption = True
TabOrder = 1
ShowButtons = [pbOK, pbCancel]
end
object HeaderLabel: TLabel
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = Owner
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 6
Height = 13
Top = 6
Width = 209
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Around = 6
Caption = 'HeaderLabel'
ParentColor = False
Visible = False
end
object ItemsTreeView: TTreeView
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = HeaderLabel
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = MoveUpBitBtn
AnchorSideBottom.Control = ButtonPanel1
Left = 6
Height = 168
Top = 25
Width = 175
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Around = 6
HideSelection = False
Images = ImageList1
ReadOnly = True
RowSelect = True
ScrollBars = ssAutoBoth
ShowButtons = False
ShowRoot = False
TabOrder = 0
OnAdvancedCustomDrawItem = ItemsTreeViewAdvancedCustomDrawItem
OnMouseDown = ItemsTreeViewMouseDown
OnSelectionChanged = ItemsTreeViewSelectionChanged
Options = [tvoAutoItemHeight, tvoKeepCollapsedNodes, tvoReadOnly, tvoRowSelect, tvoShowLines, tvoToolTips, tvoThemedDraw]
end
object MoveUpBitBtn: TBitBtn
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 187
Height = 28
Top = 40
Width = 28
Anchors = [akTop, akRight]
AutoSize = True
BorderSpacing.Around = 6
Glyph.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000137E2DFF117C2BFF0F7B29FF0D7A28FF0C79
27FF000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000127E2DFF107D2BFF0E7B29FF0C7A27FF0B79
26FF000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000127F2DFF107D2BFF0E7C28FF0C7A27FF0A79
25FF000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000012802DFF107E2BFF0E7C29FF0C7B27FF0B7A
26FF000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000012802DFF107F2BFF0E7D29FF0D7C28FF0B7A
26FF000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000013822EFF11802CFF0F7F2BFF0E7D29FF0D7B
28FF000000000000000000000000000000000000000000000000000000000000
0000188432FF178431FF158430FF14832FFF12822EFF11802CFF0F7E2AFF0E7C
29FF0E7B29FF0E7B29FF0F7B2AFF000000000000000000000000000000000000
000000000000178532FF168531FF158430FF14832FFF12812DFF117F2CFF107E
2BFF107D2BFF107C2BFF00000000000000000000000000000000000000000000
00000000000000000000178532FF168531FF158430FF14822FFF13802DFF127F
2DFF127E2CFF0000000000000000000000000000000000000000000000000000
0000000000000000000000000000178532FF168431FF158330FF15812FFF1480
2FFF000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000178432FF168331FF168231FF0000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000178332FF000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000
}
OnClick = MoveUpBitBtnClick
ParentShowHint = False
ShowHint = True
TabOrder = 2
end
object MoveDownBitBtn: TBitBtn
AnchorSideTop.Control = MoveUpBitBtn
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 187
Height = 28
Top = 74
Width = 28
Anchors = [akTop, akRight]
AutoSize = True
BorderSpacing.Around = 6
Glyph.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000F7B2AFF000000000000
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000107C2BFF0E7B29FF0D7A27FF0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000127E2DFF107D2BFF0E7B28FF0C7A27FF0B79
26FF000000000000000000000000000000000000000000000000000000000000
0000000000000000000014802EFF127F2DFF107E2BFF0E7C29FF0C7A27FF0B79
26FF0A7925FF0000000000000000000000000000000000000000000000000000
000000000000168231FF15812FFF13802DFF107F2BFF0E7D29FF0C7B27FF0B7A
26FF0B7926FF0B7926FF00000000000000000000000000000000000000000000
0000178332FF178331FF158330FF13822EFF11802CFF0F7E2AFF0D7D29FF0C7B
27FF0C7A27FF0C7A27FF0D7A28FF000000000000000000000000000000000000
000000000000000000000000000014832FFF12812DFF10802CFF0F7E2AFF0E7C
29FF000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000158430FF13822EFF12812DFF107F2BFF0F7E
2AFF000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000158430FF14832FFF13822EFF12802DFF117E
2CFF000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000168531FF158430FF14822FFF14812EFF137F
2DFF000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000178532FF168431FF168330FF158130FF1480
2FFF000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000188532FF178432FF178331FF178231FF1680
30FF000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000
}
OnClick = MoveDownBitBtnClick
ParentShowHint = False
ShowHint = True
TabOrder = 3
end
object ImageList1: TImageList
left = 66
top = 72
end
end

View File

@ -0,0 +1,324 @@
{ TSmallOrderedSetEditDlg
Copyright (C) 2017 Lazarus team
This library is free software; you can redistribute it and/or modify it
under the same terms as the Lazarus Component Library (LCL)
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
Abstract:
Dialog to edit a set of items (string) and able to order them.
}
unit SmallOrderedSetEditor;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Types, math, Forms, Controls, Graphics, Dialogs, StdCtrls,
ButtonPanel, ComCtrls, Buttons, LCLType, Themes, LazLoggerBase;
type
TSmOrdSetEditOption = (
oseoHideUpDown,
oseoErrorDuplicateItems, // default: ignore and skip
oseoErrorDuplicateAvailable, // default: ignore and skip
oseoErrorItemsContainNotAvailable // default: merge Items into AvailableItems
);
TSmOrdSetEditOptions = set of TSmOrdSetEditOption;
{ TSmallOrderedSetEditDlg }
TSmallOrderedSetEditDlg = class(TForm)
ButtonPanel1: TButtonPanel;
HeaderLabel: TLabel;
ImageList1: TImageList;
ItemsTreeView: TTreeView;
MoveDownBitBtn: TBitBtn;
MoveUpBitBtn: TBitBtn;
procedure ItemsTreeViewAdvancedCustomDrawItem(Sender: TCustomTreeView;
Node: TTreeNode; {%H-}State: TCustomDrawState; Stage: TCustomDrawStage;
var PaintImages, {%H-}DefaultDraw: Boolean);
procedure ItemsTreeViewMouseDown(Sender: TObject; {%H-}Button: TMouseButton;
{%H-}Shift: TShiftState; X, Y: Integer);
procedure ItemsTreeViewSelectionChanged(Sender: TObject);
procedure MoveDownBitBtnClick(Sender: TObject);
procedure MoveUpBitBtnClick(Sender: TObject);
private
FAvailableItems: TStrings;
FItems: TStrings;
FOptions: TSmOrdSetEditOptions;
function GetHeaderCaption: TTranslateString;
procedure SetAvailableItems(const AValue: TStrings);
procedure SetHeaderCaption(const AValue: TTranslateString);
procedure SetItems(const AValue: TStrings);
function SetList(List, NewList: TStrings; ErrorOnDuplicate: boolean): boolean;
procedure UpdateButtonState;
protected
procedure SetOptions(const AValue: TSmOrdSetEditOptions); virtual;
function IndexOf(List: TStrings; Value: string): integer; virtual;
procedure UpdateShowing; override;
procedure ToggleNode(Node: TTreeNode); virtual;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure Init; virtual;
property Options: TSmOrdSetEditOptions read FOptions write SetOptions;
property HeaderCaption: TTranslateString read GetHeaderCaption write SetHeaderCaption;
property Items: TStrings read FItems write SetItems;
property AvailableItems: TStrings read FAvailableItems write SetAvailableItems;
end;
function ShowListEditor(aCaption: string; Items, AvailableItems: TStrings): TModalResult;
implementation
function ShowListEditor(aCaption: string; Items, AvailableItems: TStrings
): TModalResult;
var
Dlg: TSmallOrderedSetEditDlg;
begin
Dlg:=TSmallOrderedSetEditDlg.Create(nil);
try
Dlg.Caption:=aCaption;
Dlg.Items:=Items;
Dlg.AvailableItems:=AvailableItems;
Dlg.Init;
Result:=Dlg.ShowModal;
if Result=mrOK then
Items.Assign(Dlg.Items);
finally
Dlg.Free;
end;
end;
{$R *.lfm}
{ TSmallOrderedSetEditDlg }
procedure TSmallOrderedSetEditDlg.ItemsTreeViewAdvancedCustomDrawItem(
Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
Stage: TCustomDrawStage; var PaintImages, DefaultDraw: Boolean);
var
Selected: Boolean;
R: TRect;
Details: TThemedElementDetails;
begin
Selected:=Node.ImageIndex>0;
if Stage=cdPrePaint then
PaintImages:=false
else if Stage=cdPostPaint then
begin
R:=Node.DisplayRect(false);
R.Left := Node.DisplayIconLeft;
if Selected then
Details := ThemeServices.GetElementDetails(tbCheckBoxCheckedNormal)
else
Details := ThemeServices.GetElementDetails(tbCheckBoxUncheckedNormal);
R.Right:=R.Left+ThemeServices.GetDetailSize(Details).cx;
ThemeServices.DrawElement(ItemsTreeView.Canvas.Handle, Details, R, nil);
end;
end;
procedure TSmallOrderedSetEditDlg.ItemsTreeViewMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Node: TTreeNode;
begin
Node:=ItemsTreeView.GetNodeAt(X,Y);
if Node=nil then exit;
ToggleNode(Node);
end;
procedure TSmallOrderedSetEditDlg.ItemsTreeViewSelectionChanged(Sender: TObject);
begin
UpdateButtonState;
end;
procedure TSmallOrderedSetEditDlg.MoveDownBitBtnClick(Sender: TObject);
var
SelNode: TTreeNode;
begin
SelNode:=ItemsTreeView.Selected;
if (SelNode=nil) or (SelNode.Index>=ItemsTreeView.Items.TopLvlCount-1) then exit;
SelNode.Index:=SelNode.Index+1;
UpdateButtonState;
end;
procedure TSmallOrderedSetEditDlg.MoveUpBitBtnClick(Sender: TObject);
var
SelNode: TTreeNode;
begin
SelNode:=ItemsTreeView.Selected;
if (SelNode=nil) or (SelNode.Index<1) then exit;
SelNode.Index:=SelNode.Index-1;
UpdateButtonState;
end;
function TSmallOrderedSetEditDlg.GetHeaderCaption: TTranslateString;
begin
Result:=HeaderLabel.Caption;
end;
procedure TSmallOrderedSetEditDlg.SetAvailableItems(const AValue: TStrings);
begin
SetList(FAvailableItems,AValue,oseoErrorDuplicateAvailable in Options);
end;
procedure TSmallOrderedSetEditDlg.SetHeaderCaption(const AValue: TTranslateString);
begin
if HeaderCaption=AValue then Exit;
HeaderLabel.Caption:=AValue;
HeaderLabel.Visible:=HeaderLabel.Caption<>'';
end;
procedure TSmallOrderedSetEditDlg.SetItems(const AValue: TStrings);
begin
SetList(FItems,AValue,oseoErrorDuplicateItems in Options);
end;
procedure TSmallOrderedSetEditDlg.UpdateButtonState;
var
SelNode: TTreeNode;
begin
SelNode:=ItemsTreeView.Selected;
MoveUpBitBtn.Enabled:=(SelNode<>nil) and (SelNode.Index>0);
MoveDownBitBtn.Enabled:=(SelNode<>nil) and (SelNode.Index<ItemsTreeView.Items.TopLvlCount-1);
end;
procedure TSmallOrderedSetEditDlg.SetOptions(const AValue: TSmOrdSetEditOptions);
begin
if FOptions=AValue then Exit;
FOptions:=AValue;
MoveUpBitBtn.Visible:=not (oseoHideUpDown in Options);
MoveDownBitBtn.Visible:=not (oseoHideUpDown in Options);
end;
function TSmallOrderedSetEditDlg.IndexOf(List: TStrings; Value: string): integer;
begin
Result:=List.IndexOf(Value);
end;
function TSmallOrderedSetEditDlg.SetList(List, NewList: TStrings;
ErrorOnDuplicate: boolean): boolean;
var
CleanList: TStringList;
i: Integer;
s: String;
begin
CleanList:=TStringList.Create;
try
for i:=0 to NewList.Count-1 do
begin
s:=NewList[i];
if IndexOf(CleanList,s)>=0 then
begin
if ErrorOnDuplicate then
raise EListError.Create(DbgSName(Self)+': duplicate item '+IntToStr(i)+' "'+s+'"');
continue;
end;
CleanList.Add(s);
end;
if List.Equals(CleanList) then exit(false);
Result:=true;
List.Assign(CleanList);
finally
CleanList.Free;
end;
end;
procedure TSmallOrderedSetEditDlg.UpdateShowing;
var
CheckedDetails, UnCheckedDetails: TThemedElementDetails;
CheckedSize, UnCheckedSize: TSize;
Bmp: TBitmap;
begin
inherited UpdateShowing;
if Visible and (ImageList1.Count=0) then begin
CheckedDetails := ThemeServices.GetElementDetails(tbCheckBoxCheckedNormal);
UnCheckedDetails := ThemeServices.GetElementDetails(tbCheckBoxCheckedNormal);
CheckedSize:=ThemeServices.GetDetailSize(CheckedDetails);
UnCheckedSize:=ThemeServices.GetDetailSize(UnCheckedDetails);
ImageList1.Width:=Max(CheckedSize.cx,UnCheckedSize.cx);
ImageList1.Height:=Max(CheckedSize.cy,UnCheckedSize.cy);
Bmp:=TBitmap.Create;
Bmp.SetSize(ImageList1.Width,ImageList1.Height);
ImageList1.Add(Bmp,nil);
ImageList1.Add(Bmp,nil);
Bmp.Free;
end;
end;
procedure TSmallOrderedSetEditDlg.ToggleNode(Node: TTreeNode);
var
i, j: Integer;
begin
Node.ImageIndex:=1-Node.ImageIndex;
Node.SelectedIndex:=Node.ImageIndex;
if Node.ImageIndex=0 then
begin
i:=IndexOf(Items,Node.Text);
Items.Delete(i);
end else begin
j:=0;
for i:=0 to Node.Index-1 do
begin
if ItemsTreeView.Items[i].ImageIndex>0 then
inc(j);
end;
Items.Insert(j,Node.Text);
end;
end;
constructor TSmallOrderedSetEditDlg.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FItems:=TStringList.Create;
FAvailableItems:=TStringList.Create;
end;
destructor TSmallOrderedSetEditDlg.Destroy;
begin
FreeAndNil(FItems);
FreeAndNil(FAvailableItems);
inherited Destroy;
end;
procedure TSmallOrderedSetEditDlg.Init;
var
i: Integer;
s: String;
Node: TTreeNode;
begin
for i:=FItems.Count-1 downto 0 do
begin
s:=FItems[i];
if IndexOf(AvailableItems,s)<0 then
begin
if oseoErrorItemsContainNotAvailable in Options then
raise EListError.Create(DbgSName(Self)+': item '+IntToStr(i)+' "'+s+'" is not in AvailableItems');
FAvailableItems.Insert(0,s);
end;
end;
ItemsTreeView.BeginUpdate;
ItemsTreeView.Items.Clear;
for i:=0 to AvailableItems.Count-1 do
begin
s:=AvailableItems[i];
Node:=ItemsTreeView.Items.Add(nil,s);
if IndexOf(Items,s)>=0 then
Node.ImageIndex:=1
else
Node.ImageIndex:=0;
Node.SelectedIndex:=Node.ImageIndex;
end;
ItemsTreeView.EndUpdate;
UpdateButtonState;
end;
end.