LCL, LazControls: use DoFilterItem in all filter edits.

git-svn-id: trunk@52266 -
This commit is contained in:
ondrej 2016-05-02 21:57:09 +00:00
parent 67f550a5ef
commit 385bdd0d4e
4 changed files with 69 additions and 52 deletions

View File

@ -160,27 +160,12 @@ procedure TListFilterEdit.SortAndFilter;
var
Origi, i: Integer;
Capt, FilterLC: string;
Pass, Done: Boolean;
begin
Done:=False;
fSortedData.Clear;
FilterLC:=UTF8LowerCase(Filter);
for Origi:=0 to fOriginalData.Count-1 do begin
Capt:=fOriginalData[Origi];
// Filter with event handler if there is one.
if Assigned(fOnFilterItemEx) then
Pass:=fOnFilterItemEx(Capt, fOriginalData.Objects[Origi], Done)
else
Pass:=False;
// Support also the old filter event without a caption.
if (not (Pass and Done)) and Assigned(fOnFilterItem) then
Pass:=fOnFilterItem(fOriginalData.Objects[Origi], Done);
// Filter by item's caption text if needed.
if not (Pass or Done) then
Pass:=(FilterLC='') or (Pos(FilterLC,UTF8LowerCase(Capt))>0);
if Pass then begin
if DoFilterItem(Capt, fOriginalData.Objects[Origi], FilterLC) then begin
i:=fSortedData.Count-1; // Always sort the data.
while i>=0 do begin
if CompareFNs(Capt,fSortedData[i])>=0 then break;

View File

@ -12,6 +12,7 @@
unit ListViewFilterEdit;
{$mode objfpc}{$H+}
{$modeswitch advancedrecords}
interface
@ -24,7 +25,13 @@ type
//TImageIndexEvent = function (Str: String; Data: TObject;
// var IsEnabled: Boolean): Integer of object;
TStringArray = array of string;
TListViewDataList = specialize TFPGList<TStringArray>;
TListViewDataItem = record
Data: Pointer;
StringArray: TStringArray;
class operator =(a,b : TListViewDataItem) : Boolean;
end;
TListViewDataList = specialize TFPGList<TListViewDataItem>;
{ TListViewFilterEdit }
@ -40,7 +47,7 @@ type
fOriginalData: TListViewDataList;
// Data sorted for viewing.
fFilteredData: TListViewDataList;
function MatchesFilter(aData: TStringArray): Boolean;
function MatchesFilter(aData: TListViewDataItem; const FilterLC: string): Boolean;
procedure SetFilteredListview(const AValue: TCustomListView);
protected
procedure MoveTo(AIndex: Integer; ASelect: Boolean);
@ -73,6 +80,13 @@ var
implementation
{ TListViewDataItem }
class operator TListViewDataItem. = (a, b: TListViewDataItem): Boolean;
begin
Result := (a.Data=b.Data) and (a.StringArray=b.StringArray);
end;
{ TListViewFilterEdit }
constructor TListViewFilterEdit.Create(AOwner: TComponent);
@ -104,23 +118,25 @@ begin
Result := -1;
end;
function ListItem2Data(AItem: TListItem): TStringArray;
function ListItem2Data(AItem: TListItem): TListViewDataItem;
var
i: Integer;
begin
SetLength(Result, AItem.SubItems.Count+1);
Result[0] := AItem.Caption;
Result.Data := AItem.Data;
SetLength(Result.StringArray, AItem.SubItems.Count+1);
Result.StringArray[0] := AItem.Caption;
for i := 0 to AItem.SubItems.Count-1 do
Result[i+1] := AItem.SubItems[i];
Result.StringArray[i+1] := AItem.SubItems[i];
end;
procedure Data2ListItem(AData: TStringArray; AItem: TListItem);
procedure Data2ListItem(AData: TListViewDataItem; AItem: TListItem);
var
i: Integer;
begin
AItem.Caption := AData[0];
for i := 1 to Length(AData)-1 do
AItem.SubItems.Add(AData[i]);
AItem.Data := AData.Data;
AItem.Caption := AData.StringArray[0];
for i := 1 to Length(AData.StringArray)-1 do
AItem.SubItems.Add(AData.StringArray[i]);
end;
procedure TListViewFilterEdit.SetFilteredListview(const AValue: TCustomListView);
@ -134,23 +150,18 @@ begin
fOriginalData.Add(ListItem2Data(fFilteredListview.Items[i]));
end;
function TListViewFilterEdit.MatchesFilter(aData: TStringArray): Boolean;
function TListViewFilterEdit.MatchesFilter(aData: TListViewDataItem;
const FilterLC: string): Boolean;
var
i, EndInd: Integer;
FilterLC: string;
begin
if Filter='' then
Exit(True);
FilterLC := UTF8LowerCase(Filter);
if fByAllFields then
EndInd := Pred(Length(aData))
EndInd := Pred(Length(aData.StringArray))
else
EndInd := 0;
for i := 0 to EndInd do begin
// ToDo: Use OnFilterItemEx event.
Result := Pos(FilterLC,UTF8LowerCase(aData[i]))>0;
if Result then
Exit;
if DoFilterItem(aData.StringArray[i], TObject(aData.Data), FilterLC) then
Exit(True);
end;
Result := False;
end;
@ -173,12 +184,14 @@ procedure TListViewFilterEdit.SortAndFilter;
// Copy data from fOriginalData to fSortedData in sorted order
var
Origi: Integer;
Data: TStringArray;
Data: TListViewDataItem;
FilterLC: string;
begin
fFilteredData.Clear;
FilterLC := UTF8LowerCase(Filter);
for Origi:=0 to fOriginalData.Count-1 do begin
Data:=fOriginalData[Origi];
if MatchesFilter(Data) then
if MatchesFilter(Data, FilterLC) then
fFilteredData.Add(Data);
end;
end;

View File

@ -460,26 +460,14 @@ function TTreeFilterEdit.FilterTree(Node: TTreeNode): Boolean;
// Filter all tree branches recursively, setting Node.Visible as needed.
// Returns True if Node or its siblings or child nodes have visible items.
var
Pass, Done: Boolean;
Pass: Boolean;
FilterLC: string;
begin
Result:=False;
Done:=False;
FilterLC:=UTF8LowerCase(Filter);
while Node<>nil do
begin
// Filter with event handler if there is one.
if Assigned(fOnFilterItemEx) then
Pass:=fOnFilterItemEx(Node.Text, TObject(Node.Data), Done)
else
Pass:=False;
// Support also the old filter event without a caption.
if (not (Pass and Done)) and Assigned(fOnFilterItem) then
Pass:=fOnFilterItem(TObject(Node.Data), Done);
// Filter by item's caption text if needed.
if not (Pass or Done) then
Pass:=(FilterLC='') or (Pos(FilterLC,UTF8LowerCase(Node.Text))>0);
Pass := DoFilterItem(Node.Text, TObject(Node.Data), FilterLC);
if Pass and (fFirstPassedNode=Nil) then
fFirstPassedNode:=Node;
// Recursive call for child nodes.

View File

@ -222,6 +222,10 @@ type
fOnFilterItem: TFilterItemEvent;
fOnFilterItemEx: TFilterItemExEvent;
fOnCheckItem: TCheckItemEvent;
function DoFilterItem(const ACaption: string; const Item: TObject;
const FilterLC: string): Boolean; virtual;
function DoDefaultFilterItem(const ACaption: string; const Item: TObject;
const FilterLC: string): Boolean; virtual;
procedure EditKeyDown(var Key: Word; Shift: TShiftState); override;
procedure EditChange; override;
procedure EditEnter; override;
@ -1118,6 +1122,33 @@ begin
inherited Destroy;
end;
function TCustomControlFilterEdit.DoDefaultFilterItem(const ACaption: string;
const Item: TObject; const FilterLC: string): Boolean;
begin
Result := (FilterLC='') or (Pos(FilterLC,UTF8LowerCase(ACaption))>0);
end;
function TCustomControlFilterEdit.DoFilterItem(const ACaption: string;
const Item: TObject; const FilterLC: string): Boolean;
var
Done: Boolean;
begin
Done := False;
// Filter with event handler if there is one.
if Assigned(fOnFilterItemEx) then
Result:=fOnFilterItemEx(ACaption, Item, Done)
else
Result:=False;
// Support also the old filter event without a caption.
if (not (Result and Done)) and Assigned(fOnFilterItem) then
Result:=fOnFilterItem(Item, Done);
// Filter by item's caption text if needed.
if not (Result or Done) then
Result:=DoDefaultFilterItem(ACaption, Item, FilterLC);
end;
procedure TCustomControlFilterEdit.OnIdle(Sender: TObject; var Done: Boolean);
begin
if fNeedUpdate then