Improve ListFilterEdit component.

git-svn-id: trunk@31492 -
This commit is contained in:
juha 2011-07-02 11:14:49 +00:00
parent 3c82aaa518
commit 2dbcbcd191
2 changed files with 79 additions and 49 deletions

View File

@ -33,17 +33,14 @@
</Files> </Files>
<LazDoc Paths="docs"/> <LazDoc Paths="docs"/>
<Type Value="RunAndDesignTime"/> <Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="3"> <RequiredPkgs Count="2">
<Item1> <Item1>
<PackageName Value="CodeTools"/> <PackageName Value="LCL"/>
</Item1> </Item1>
<Item2> <Item2>
<PackageName Value="LCL"/>
</Item2>
<Item3>
<PackageName Value="FCL"/> <PackageName Value="FCL"/>
<MinVersion Major="1" Valid="True"/> <MinVersion Major="1" Valid="True"/>
</Item3> </Item2>
</RequiredPkgs> </RequiredPkgs>
<UsageOptions> <UsageOptions>
<UnitPath Value="$(PkgOutDir)\"/> <UnitPath Value="$(PkgOutDir)\"/>

View File

@ -6,7 +6,7 @@ interface
uses uses
Classes, SysUtils, Forms, LResources, Graphics, StdCtrls, ComCtrls, EditBtn, Classes, SysUtils, Forms, LResources, Graphics, StdCtrls, ComCtrls, EditBtn,
CodeToolsStructs; FileUtil, AvgLvlTree;
resourcestring resourcestring
lisCEFilter = '(Filter)'; lisCEFilter = '(Filter)';
@ -29,14 +29,19 @@ type
fIdleConnected: boolean; fIdleConnected: boolean;
fSelectedPart: TObject; // Select this node on next update fSelectedPart: TObject; // Select this node on next update
fSelectionList: TStringList; // or store/restore the old selections here. fSelectionList: TStringList; // or store/restore the old selections here.
fShowDirHierarchy: Boolean; fShowDirHierarchy: Boolean; // Show direcories / files as a tree structure.
fSortData: Boolean; fSortData: Boolean; // Data needs to be sorted.
fStoreFilenameInNode: boolean; // Full filename in node data is needed when showing the directory hierarchy.
// It is stored automatically if the map is populated by MapShortToFullFilename.
fFilenameMap: TStringToStringTree; fFilenameMap: TStringToStringTree;
fTVNodeStack: TFPList; fTVNodeStack: TFPList;
// Data to be filtered. Objects property can contain data, too. // Data supplied by caller through Data property.
fData: TStringList; // Objects property is passed to OnGetImageIndex.
fOriginalData: TStringList;
// Data sorted for viewing.
fSortedData: TStringList;
fRootNode: TTreeNode; // The filtered items are under this node. fRootNode: TTreeNode; // The filtered items are under this node.
// A control showing the (filtered) data. These are exclusive, only one is used.
fFilteredTreeview: TTreeview; fFilteredTreeview: TTreeview;
fFilteredListbox: TListbox; fFilteredListbox: TListbox;
fOnGetImageIndex: TImageIndexEvent; fOnGetImageIndex: TImageIndexEvent;
@ -50,6 +55,8 @@ type
procedure FreeTVNodeData(Node: TTreeNode); procedure FreeTVNodeData(Node: TTreeNode);
procedure TVDeleteUnneededNodes(p: integer); procedure TVDeleteUnneededNodes(p: integer);
procedure TVClearUnneededAndCreateHierachy(Filename: string); procedure TVClearUnneededAndCreateHierachy(Filename: string);
function CompareFNs(AFilename1,AFilename2: string): integer;
procedure SortForView;
procedure ApplyFilterToTreeview; procedure ApplyFilterToTreeview;
procedure SetIdleConnected(const AValue: boolean); procedure SetIdleConnected(const AValue: boolean);
protected protected
@ -69,8 +76,7 @@ type
property SelectedPart: TObject read fSelectedPart write fSelectedPart; property SelectedPart: TObject read fSelectedPart write fSelectedPart;
property ShowDirHierarchy: Boolean read fShowDirHierarchy write fShowDirHierarchy; property ShowDirHierarchy: Boolean read fShowDirHierarchy write fShowDirHierarchy;
property SortData: Boolean read fSortData write fSortData; property SortData: Boolean read fSortData write fSortData;
property StoreFilenameInNode: boolean read fStoreFilenameInNode write fStoreFilenameInNode; property Data: TStringList read fOriginalData;
property Data: TStringList read fData;
property RootNode: TTreeNode read fRootNode write fRootNode; property RootNode: TTreeNode read fRootNode write fRootNode;
published published
// TListFilterEdit properties. // TListFilterEdit properties.
@ -81,7 +87,6 @@ type
property ButtonWidth; property ButtonWidth;
property DirectInput; property DirectInput;
property ButtonOnlyWhenFocused; property ButtonOnlyWhenFocused;
// property Glyph;
property NumGlyphs; property NumGlyphs;
property Flat; property Flat;
// Other properties // Other properties
@ -162,9 +167,11 @@ end;
constructor TListFilterEdit.Create(AOwner: TComponent); constructor TListFilterEdit.Create(AOwner: TComponent);
begin begin
inherited Create(AOwner); inherited Create(AOwner);
fData:=TStringList.Create; fOriginalData:=TStringList.Create;
fSortedData:=TStringList.Create;
fSelectionList:=TStringList.Create; fSelectionList:=TStringList.Create;
fFilenameMap:=TStringToStringTree.Create(True); fFilenameMap:=TStringToStringTree.Create(True);
fImageIndexDirectory := -1;
Button.Enabled:=False; Button.Enabled:=False;
Font.Color:=clBtnShadow; Font.Color:=clBtnShadow;
Text:=lisCEFilter; Text:=lisCEFilter;
@ -178,7 +185,8 @@ begin
FreeTVNodeData(fRootNode); FreeTVNodeData(fRootNode);
fFilenameMap.Free; fFilenameMap.Free;
fSelectionList.Free; fSelectionList.Free;
fData.Free; fSortedData.Free;
fOriginalData.Free;
inherited Destroy; inherited Destroy;
end; end;
@ -355,10 +363,7 @@ begin
p:=0; p:=0;
while Filename<>'' do begin while Filename<>'' do begin
// get the next file name part // get the next file name part
if fShowDirHierarchy then DelimPos:=System.Pos(PathDelim,Filename);
DelimPos:=System.Pos(PathDelim,Filename)
else
DelimPos:=0;
if DelimPos>0 then begin if DelimPos>0 then begin
FilePart:=copy(Filename,1,DelimPos-1); FilePart:=copy(Filename,1,DelimPos-1);
Filename:=copy(Filename,DelimPos+1,length(Filename)); Filename:=copy(Filename,DelimPos+1,length(Filename));
@ -406,57 +411,86 @@ begin
end; end;
end; end;
function TListFilterEdit.CompareFNs(AFilename1,AFilename2: string): integer;
begin
if fSortData then
Result:=CompareFilenames(AFilename1, AFilename2)
else if fShowDirHierarchy then
Result:=CompareFilenames(ExtractFilePath(AFilename1), ExtractFilePath(AFilename2))
else
Result:=0;
end;
procedure TListFilterEdit.SortForView;
// Copy data from fOriginalData to fSortedData in sorted order
var
Origi, i: Integer;
FileN: string;
begin
fSortedData.Clear;
for Origi:=0 to fOriginalData.Count-1 do begin
FileN:=fOriginalData[Origi];
i:=fSortedData.Count-1;
while i>=0 do begin
if CompareFNs(FileN,fSortedData[i])>=0 then break;
dec(i);
end;
fSortedData.InsertObject(i+1,FileN, fOriginalData.Objects[Origi]);
end;
end;
procedure TListFilterEdit.ApplyFilterToTreeview; procedure TListFilterEdit.ApplyFilterToTreeview;
var var
TVNode: TTreeNode; TVNode: TTreeNode;
ImgIndex, i: Integer; ImgIndex, i: Integer;
s: string; FileN, s: string;
begin begin
fNeedUpdate:=false; fNeedUpdate:=false;
ImgIndex:=-1; ImgIndex:=-1;
fData.Sorted:=SortData; SortForView;
fFilteredTreeview.BeginUpdate;
if fSelectedPart=Nil then if fSelectedPart=Nil then
StoreTreeSelection; StoreTreeSelection;
if Assigned(fRootNode) then begin if fFilenameMap.Count > 0 then
if fStoreFilenameInNode then FreeTVNodeData(fRootNode); // Free node data now, it will be filled later.
FreeTVNodeData(fRootNode); if Assigned(fRootNode) then // Delete old tree nodes.
fRootNode.DeleteChildren; fRootNode.DeleteChildren
fTVNodeStack:=TFPList.Create;
end
else else
fFilteredTreeview.Items.Clear; fFilteredTreeview.Items.Clear;
for i:=0 to fData.Count-1 do if fShowDirHierarchy then
if PassesFilter(fData[i]) then begin fTVNodeStack:=TFPList.Create;
if Assigned(fRootNode) then begin fFilteredTreeview.BeginUpdate;
TVClearUnneededAndCreateHierachy(fData[i]); for i:=0 to fSortedData.Count-1 do begin
FileN:=fSortedData[i];
if PassesFilter(FileN) then begin
if fShowDirHierarchy then begin
TVClearUnneededAndCreateHierachy(FileN);
TVNode:=TTreeNode(fTVNodeStack[fTVNodeStack.Count-1]); TVNode:=TTreeNode(fTVNodeStack[fTVNodeStack.Count-1]);
end end
else begin else if Assigned(fRootNode) then
TVNode:=fFilteredTreeview.Items.Add(nil,fData[i]); TVNode:=fFilteredTreeview.Items.AddChild(fRootNode,FileN)
end; else
if fStoreFilenameInNode then begin TVNode:=fFilteredTreeview.Items.Add(Nil,FileN);
s:=fData[i]; if fFilenameMap.Count > 0 then begin
if fFilenameMap.Contains(fData[i]) then s:=FileN;
s:=fFilenameMap[fData[i]]; // Full file name. if fFilenameMap.Contains(FileN) then
s:=fFilenameMap[FileN]; // Full file name.
TVNode.Data:=TFileNameItem.Create(s); TVNode.Data:=TFileNameItem.Create(s);
end; end;
if Assigned(OnGetImageIndex) then if Assigned(OnGetImageIndex) then
ImgIndex:=OnGetImageIndex(fData[i], fData.Objects[i]); ImgIndex:=OnGetImageIndex(FileN, fSortedData.Objects[i]);
TVNode.ImageIndex:=ImgIndex; TVNode.ImageIndex:=ImgIndex;
TVNode.SelectedIndex:=ImgIndex; TVNode.SelectedIndex:=ImgIndex;
if Assigned(fSelectedPart) then if Assigned(fSelectedPart) then
TVNode.Selected:=fSelectedPart=fData.Objects[i]; TVNode.Selected:=fSelectedPart=fSortedData.Objects[i];
end; end;
if Assigned(fRootNode) then begin
TVDeleteUnneededNodes(0);
fTVNodeStack.Free;
fRootNode.Expanded:=True;
end; end;
if fShowDirHierarchy then // TVDeleteUnneededNodes(0); ?
fTVNodeStack.Free;
if Assigned(fRootNode) then
fRootNode.Expanded:=True;
if fSelectedPart=Nil then if fSelectedPart=Nil then
RestoreTreeSelection; RestoreTreeSelection;
fFilteredTreeview.EndUpdate; fFilteredTreeview.EndUpdate;
fData.Sorted:=False;
end; end;
procedure TListFilterEdit.ApplyFilter(Immediately: Boolean); procedure TListFilterEdit.ApplyFilter(Immediately: Boolean);
@ -482,6 +516,5 @@ begin
IdleConnected:=true; IdleConnected:=true;
end; end;
end. end.