From d8add7306267e274d48cd97103c46b940076c19f Mon Sep 17 00:00:00 2001 From: juha Date: Wed, 10 Dec 2014 00:38:19 +0000 Subject: [PATCH] New component ListViewFilterEdit. git-svn-id: trunk@47159 - --- .gitattributes | 1 + components/lazcontrols/listviewfilteredit.pas | 230 ++++++++++++++++++ 2 files changed, 231 insertions(+) create mode 100644 components/lazcontrols/listviewfilteredit.pas diff --git a/.gitattributes b/.gitattributes index e3857746a7..53a5cfb314 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2048,6 +2048,7 @@ components/lazcontrols/lazcontrols.pas svneol=native#text/pascal components/lazcontrols/lazcontrols.res -text components/lazcontrols/lazctrls.bat svneol=native#text/plain 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/treefilteredit.pas svneol=native#text/plain diff --git a/components/lazcontrols/listviewfilteredit.pas b/components/lazcontrols/listviewfilteredit.pas new file mode 100644 index 0000000000..0171e8976c --- /dev/null +++ b/components/lazcontrols/listviewfilteredit.pas @@ -0,0 +1,230 @@ +{ ListViewFilterEdit + + Copyright (C) 2012 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. + +} +unit ListViewFilterEdit; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Forms, LResources, Graphics, Controls, StdCtrls, ComCtrls, + LCLProc, LCLType, EditBtn, CheckLst, FileUtil, LazUTF8, AvgLvlTree, fgl; + +type + + //TImageIndexEvent = function (Str: String; Data: TObject; + // var IsEnabled: Boolean): Integer of object; + TStringArray = array of string; + TListViewDataList = specialize TFPGList; + + { TListViewFilterEdit } + + TListViewFilterEdit = class(TCustomControlFilterEdit) + private + fFilteredListview: TCustomListView; // A control showing the (filtered) data. + fSelectionList: TStringList; // Store/restore the old selections here. + // Data supplied by caller through Data property. + fOriginalData: TListViewDataList; + // Data sorted for viewing. + fFilteredData: TListViewDataList; + function MatchesFilter(aData: TStringArray): Boolean; + procedure SetFilteredListview(const AValue: TCustomListView); + protected + procedure MoveNext; override; + procedure MovePrev; override; + function ReturnKeyHandled: Boolean; override; + procedure SortAndFilter; override; + procedure ApplyFilterCore; override; + function GetDefaultGlyph: TBitmap; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure StoreSelection; override; + procedure RestoreSelection; override; + public + property SelectionList: TStringList read fSelectionList; + property Items: TListViewDataList read fOriginalData; + published + property FilteredListview: TCustomListView read fFilteredListview write SetFilteredListview; + end; + +var + ListFilterGlyph: TBitmap; + +procedure Register; + +implementation + +procedure Register; +begin + RegisterComponents('LazControls',[TListViewFilterEdit]); +end; + +{ TListViewFilterEdit } + +constructor TListViewFilterEdit.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + fOriginalData:=TListViewDataList.Create; + fSelectionList:=TStringList.Create; + fFilteredData:=TListViewDataList.Create; +end; + +destructor TListViewFilterEdit.Destroy; +begin + fFilteredData.Free; + fSelectionList.Free; + fOriginalData.Free; + inherited Destroy; +end; + +function TListViewFilterEdit.GetDefaultGlyph: TBitmap; +begin + Result := ListFilterGlyph; +end; + +function ListItem2Data(AItem: TListItem): TStringArray; +var + i: Integer; +begin + SetLength(Result, AItem.SubItems.Count+1); + Result[0] := AItem.Caption; + for i := 0 to AItem.SubItems.Count-1 do + Result[i+1] := AItem.SubItems[i]; +end; + +procedure Data2ListItem(AData: TStringArray; AItem: TListItem); +var + i: Integer; +begin + AItem.Caption := AData[0]; + for i := 1 to Length(AData)-1 do + AItem.SubItems.Add(AData[i]); +end; + +procedure TListViewFilterEdit.SetFilteredListview(const AValue: TCustomListView); +var + i: Integer; +begin + if fFilteredListview = AValue then Exit; + fFilteredListview:=AValue; + if Assigned(fFilteredListview) then + for i := 0 to fFilteredListview.Items.Count-1 do + fOriginalData.Add(ListItem2Data(fFilteredListview.Items[i])); +end; + +function TListViewFilterEdit.MatchesFilter(aData: TStringArray): Boolean; +var + i: Integer; +begin + if Filter='' then + Exit(True); + for i := 0 to Pred(Length(aData)) do begin + Result := Pos(Filter,UTF8LowerCase(aData[i]))>0; + if Result then + Exit; + end; + Result := False; +end; + +procedure TListViewFilterEdit.SortAndFilter; +// Copy data from fOriginalData to fSortedData in sorted order +var + Origi: Integer; + Data: TStringArray; +begin + fFilteredData.Clear; + for Origi:=0 to fOriginalData.Count-1 do begin + Data:=fOriginalData[Origi]; + if MatchesFilter(Data) then + fFilteredData.Add(Data); + end; +end; + +procedure TListViewFilterEdit.ApplyFilterCore; +var + i: Integer; +begin + if fFilteredListview = nil then + exit; + fFilteredListview.Clear; + fFilteredListview.Items.BeginUpdate; + for i:=0 to fFilteredData.Count-1 do + Data2ListItem(fFilteredData[i], fFilteredListview.Items.Add); + fFilteredListview.AlphaSort; // Always sorted. + fFilteredListview.Items.EndUpdate; +end; + +procedure TListViewFilterEdit.StoreSelection; +var + i: Integer; +begin + if fFilteredListview = nil then + exit; + fSelectionList.Clear; + if fFilteredListview.SelCount > 0 then + for i := 0 to fFilteredListview.Items.Count-1 do + if fFilteredListview.Items[i].Selected then + fSelectionList.Add(fFilteredListview.Items[i].Caption); +end; + +procedure TListViewFilterEdit.RestoreSelection; +var + i: Integer; +begin + if fSelectionList.Count > 0 then + for i := 0 to fFilteredListview.Items.Count-1 do + if fSelectionList.IndexOf(fFilteredListview.Items[i].Caption) > -1 then + fFilteredListview.Items[i].Selected:=True; +end; + +procedure TListViewFilterEdit.MoveNext; +var + i: Integer; +begin + i := fFilteredListview.ItemIndex + 1; + if fFilteredListview.Items.Count > 0 then begin + if i < fFilteredListview.Items.Count then + fFilteredListview.ItemIndex := i + else + fFilteredListview.ItemIndex := 0; + end; +end; + +procedure TListViewFilterEdit.MovePrev; +var + i: Integer; +begin + i := fFilteredListview.ItemIndex - 1; + if fFilteredListview.Items.Count > 0 then begin + if i >= 0 then + fFilteredListview.ItemIndex := i + else + fFilteredListview.ItemIndex := fFilteredListview.Items.Count-1; + end; +end; + +function TListViewFilterEdit.ReturnKeyHandled: Boolean; +// Retuns true if the Return press was forwarded to the ListView +var + Key: Char; +begin + if fFilteredListview = nil then + exit(false); + Key:=Char(VK_RETURN); + Result:=Assigned(fFilteredListview.OnKeyPress); + if Result then + fFilteredListview.OnKeyPress(fFilteredListview, Key); +end; + +end. +