Added: Sort by Name / Sort by Type option

Added: optionally include descendants in non-wildcard filters
Changed: filter checkboxes now work in reverse; checking them shows that particular group, unchecking hides it (makes more sense)
This commit is contained in:
Mark van Renswoude 2007-12-12 10:18:59 +00:00
parent cfff9522ab
commit 450baa3705
6 changed files with 201 additions and 116 deletions

Binary file not shown.

View File

@ -73,12 +73,6 @@ begin
end;
function SortByName(Item1, Item2: Pointer): Integer;
begin
Result := CompareText(TCmpSwComponent(Item1).Name, TCmpSwComponent(Item2).Name)
end;
procedure TComponentSwitcherHook.NewExecute(Sender: TObject);
var
editor: IOTAEditor;
@ -108,19 +102,6 @@ begin
if itemList.Count > 0 then
begin
itemList.Sort(SortByName);
(*
ps := (borlandideservices as IOTAPackageServices);
for pi := 0 to Pred(ps.PackageCount) do
begin
for ci := 0 to Pred(ps.ComponentCount[pi]) do
begin
itemList.Add(TTestItem.Create(ps.PackageNames[pi] + ' - ' + ps.ComponentNames[pi, ci]));
end;
end;
*)
selectedItems := TfrmCmpSwDialog.Execute(itemList);
if Assigned(selectedItems) then

View File

@ -53,7 +53,6 @@ inherited frmCmpSwDialog: TfrmCmpSwDialog
Width = 342
Height = 65
Align = alClient
Caption = ' Filter '
TabOrder = 0
DesignSize = (
342
@ -75,6 +74,18 @@ inherited frmCmpSwDialog: TfrmCmpSwDialog
Caption = '&Filter selected class(es)'
Enabled = False
end
object actSortByName: TAction
Caption = 'Sort by &Name'
GroupIndex = 1
ShortCut = 49230
OnExecute = SortExecute
end
object actSortByType: TAction
Caption = 'Sort by &Type'
GroupIndex = 1
ShortCut = 49236
OnExecute = SortExecute
end
end
inherited pmnItems: TPopupMenu
object pmnItemsFilters: TMenuItem [0]
@ -86,6 +97,15 @@ inherited frmCmpSwDialog: TfrmCmpSwDialog
object pmnItemsSep1: TMenuItem [2]
Caption = '-'
end
object pmnItemsSortByName: TMenuItem [3]
Action = actSortByName
end
object pmnItemsSortByType: TMenuItem [4]
Action = actSortByType
end
object pmnItemsSep2: TMenuItem [5]
Caption = '-'
end
end
object pmnMoreFilters: TPopupMenu
Left = 192

View File

@ -17,7 +17,7 @@ uses
BaseSwDialog,
BaseSwObjects,
CmpSwFilters;
CmpSwFilters, UnSwDialog;
type
@ -46,25 +46,36 @@ type
gbFilters: TGroupBox;
btnMoreFilters: TButton;
pmnMoreFilters: TPopupMenu;
actSortByName: TAction;
actSortByType: TAction;
pmnItemsSortByName: TMenuItem;
pmnItemsSortByType: TMenuItem;
pmnItemsSep2: TMenuItem;
procedure btnMoreFiltersClick(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure SortExecute(Sender: TObject);
private
FClassFilteredList: TBaseSwItemList;
FClassFilter: TCmpSwComponentClassFilter;
FFilterCheckBoxes: TObjectList;
FOtherGroup: TCmpSwFilterGroup;
protected
function InternalExecute(): TBaseSwItemList; override;
function CreateStyleVisitor(): TBaseSwStyleVisitor; override;
function GetBaseItemList(): TBaseSwItemList; override;
function AllowEmptyResult(): Boolean; override;
function ColorsEnabled(): Boolean; override;
procedure LoadSettings(); override;
procedure SaveSettings(); override;
procedure DrawItemText(ACanvas: TCanvas; AItem: TBaseSwItem; ARect: TRect); override;
procedure UpdateClassFilter();
procedure SortList();
procedure BuildFilterCheckboxes();
function CreateFilterMenuItem(AParent: TMenuItem; AGroup: TCmpSwFilterGroup; AItemIndex: Integer): TMenuItem;
@ -72,7 +83,8 @@ type
procedure FilterCheckBoxClick(Sender: TObject);
procedure FilterMenuItemClick(Sender: TObject);
property ClassFilter: TCmpSwComponentClassFilter read FClassFilter;
property ClassFilter: TCmpSwComponentClassFilter read FClassFilter;
property ClassFilteredList: TBaseSwItemList read FClassFilteredList;
end;
@ -233,9 +245,15 @@ begin
FClassFilteredList := TBaseSwItemList.Create();
FClassFilter := TCmpSwComponentClassFilter.Create();
FFilterCheckBoxes := TObjectList.Create();
FOtherGroup := TCmpSwFilterGroup.Create(nil);
try
Result := inherited InternalExecute();
FOtherGroup.Name := 'Other';
FOtherGroup.Enabled := False;
FOtherGroup.Visible := False;
Result := inherited InternalExecute();
finally
FreeAndNil(FOtherGroup);
FreeAndNil(FFilterCheckBoxes);
FreeAndNil(FClassFilter);
FreeAndNil(FClassFilteredList);
@ -271,7 +289,7 @@ begin
DT_LEFT or DT_VCENTER or DT_END_ELLIPSIS or DT_CALCRECT);
textRect.Left := textRect.Right;
textRect.Right := ARect.Right;
textRect.Right := ARect.Right - 2;
{ Draw component class text }
ACanvas.Font.Color := clGrayText;
@ -288,62 +306,6 @@ var
itemIndex: Integer;
begin
if ClassFilter.Groups.Count = 0 then
begin
with ClassFilter.Groups.Add() do
begin
Name := 'Actions';
Filter.Add('TAction');
Visible := True;
end;
with ClassFilter.Groups.Add() do
begin
Name := 'Menu items';
Filter.Add('TMenuItem');
Visible := True;
end;
with ClassFilter.Groups.Add() do
begin
Name := 'Dataset fields';
Filter.Add('TField');
Filter.Add('T*Field');
Visible := True;
end;
with ClassFilter.Groups.Add() do
begin
Name := 'DevEx Grid columns';
Filter.Add('TcxGridDBColumn');
Filter.Add('TcxGridColumn');
end;
// with ClassFilter.Groups.Add() do
// begin
// Name := 'Toolbar2000 items';
// Enabled := True;
//
// Filter.Add('TTBXItem');
// Filter.Add('TTBItem');
// Filter.Add('TTBXSeparatorItem');
// Filter.Add('TTBXNoPrefixItem');
// Filter.Add('TTBXNoPrefixSubmenuItem');
// Filter.Add('TTBXSubmenuItem');
// end;
// with ClassFilter.Groups.Add() do
// begin
// Name := 'X2Software items';
// Enabled := True;
//
// Filter.Add('TX2GraphicContainerItem');
// end;
end;
pnlFilters.Visible := (ClassFilter.Groups.Count > 0);
@ -358,6 +320,9 @@ begin
end;
end;
CreateFilterMenuItem(pmnItemsFilters, FOtherGroup, itemIndex);
Inc(itemIndex);
{ Remove excess menu items }
for groupIndex := Pred(pmnItemsFilters.Count) downto itemIndex do
pmnItemsFilters.Delete(groupIndex);
@ -374,6 +339,9 @@ begin
end;
end;
CreateFilterMenuItem(pmnMoreFilters.Items, FOtherGroup, itemIndex);
Inc(itemIndex);
for groupIndex := Pred(pmnMoreFilters.Items.Count) downto itemIndex do
pmnMoreFilters.Items.Delete(groupIndex);
@ -381,14 +349,17 @@ begin
BuildFilterCheckboxes();
btnMoreFilters.Visible := (pmnMoreFilters.Items.Count > 0);
FClassFilteredList.Clone(ItemList);
ClassFilter.FilterList(FClassFilteredList);
ClassFilteredList.Clone(ItemList);
ClassFilter.FilterUnmatched := FOtherGroup.Enabled;
ClassFilter.FilterList(ClassFilteredList);
SortList();
end;
function TfrmCmpSwDialog.GetBaseItemList(): TBaseSwItemList;
begin
Result := FClassFilteredList;
Result := ClassFilteredList;
end;
@ -418,7 +389,7 @@ begin
checkBox.Top := checkBoxTop;
checkBox.Left := 12;
checkBox.Caption := StringReplace(group.Name, '&', '&&', [rfReplaceAll]);
checkBox.Checked := group.Enabled;
checkBox.Checked := not group.Enabled;
checkBox.Tag := Integer(group);
checkBox.OnClick := FilterCheckBoxClick;
checkBox.Parent := gbFilters;
@ -443,7 +414,7 @@ begin
Result := AParent[AItemIndex];
Result.Caption := StringReplace(AGroup.Name, '&', '&&', [rfReplaceAll]);
Result.Checked := AGroup.Enabled;
Result.Checked := not AGroup.Enabled;
Result.Tag := Integer(AGroup);
end;
@ -457,9 +428,9 @@ begin
checkBox := (Sender as TCheckBox);
group := TCmpSwFilterGroup(checkBox.Tag);
if checkBox.Checked <> group.Enabled then
if checkBox.Checked = group.Enabled then
begin
group.Enabled := checkBox.Checked;
group.Enabled := not checkBox.Checked;
UpdateClassFilter();
UpdateSubFilters();
@ -476,8 +447,8 @@ begin
menuItem := (Sender as TMenuItem);
group := TCmpSwFilterGroup(menuItem.Tag);
menuItem.Checked := not menuItem.Checked;
group.Enabled := menuItem.Checked;
menuItem.Checked := not menuItem.Checked;
UpdateClassFilter();
UpdateSubFilters();
@ -508,6 +479,8 @@ end;
procedure TfrmCmpSwDialog.SaveSettings();
begin
// #ToDo2 (MvR) 12-12-2007: save 'sort by ...'
Settings.Dialog.Width := Self.ClientWidth;
Settings.Dialog.Height := Self.ClientHeight;
Settings.Dialog.MRUList.Assign(MRUList);
@ -518,4 +491,46 @@ begin
inherited SaveSettings();
end;
function TfrmCmpSwDialog.AllowEmptyResult(): Boolean;
begin
Result := True;
end;
function TfrmCmpSwDialog.ColorsEnabled(): Boolean;
begin
Result := inherited ColorsEnabled();
end;
procedure TfrmCmpSwDialog.SortExecute(Sender: TObject);
begin
(Sender as TAction).Checked := True;
SortList();
UpdateSubFilters();
end;
function SortByName(Item1, Item2: Pointer): Integer;
begin
Result := CompareText(TCmpSwComponent(Item1).Name, TCmpSwComponent(Item2).Name);
end;
function SortByType(Item1, Item2: Pointer): Integer;
begin
Result := CompareText(TCmpSwComponent(Item1).ComponentClass, TCmpSwComponent(Item2).ComponentClass);
end;
procedure TfrmCmpSwDialog.SortList();
begin
if actSortByType.Checked then
ClassFilteredList.Sort(SortByType)
else
ClassFilteredList.Sort(SortByName);
end;
end.

View File

@ -10,16 +10,15 @@ uses
type
// #ToDo3 (MvR) 11-12-2007: "Include descendants" option
TCmpSwFilterGroup = class(TCollectionItem)
private
FEnabled: Boolean;
FFilter: TStrings;
FFilterChanged: Boolean;
FFilterMasks: TObjectList;
FName: String;
FVisible: Boolean;
FEnabled: Boolean;
FFilter: TStrings;
FFilterChanged: Boolean;
FFilterMasks: TObjectList;
FIncludeDescendants: Boolean;
FName: String;
FVisible: Boolean;
protected
procedure FilterChange(Sender: TObject);
@ -33,13 +32,16 @@ type
function Matches(const AValue: String): Boolean;
property Enabled: Boolean read FEnabled write FEnabled;
property Filter: TStrings read FFilter;
property Name: String read FName write FName;
property Visible: Boolean read FVisible write FVisible;
property Enabled: Boolean read FEnabled write FEnabled;
property Filter: TStrings read FFilter;
property IncludeDescendants: Boolean read FIncludeDescendants write FIncludeDescendants;
property Name: String read FName write FName;
property Visible: Boolean read FVisible write FVisible;
end;
TCmpSwMatchResult = (mrNoMatch, mrDisabledMatch, mrMatch);
TCmpSwFilterGroups = class(TCollection)
private
function GetItem(Index: Integer): TCmpSwFilterGroup;
@ -48,7 +50,7 @@ type
constructor Create();
function Add(): TCmpSwFilterGroup;
function Matches(const AValue: String): Boolean;
function Matches(const AValue: String; AMatchDisabled: Boolean): TCmpSwMatchResult;
property Items[Index: Integer]: TCmpSwFilterGroup read GetItem write SetItem; default;
end;
@ -56,14 +58,16 @@ type
TCmpSwComponentClassFilter = class(TBaseSwItemFilter)
private
FGroups: TCmpSwFilterGroups;
FFilterUnmatched: Boolean;
FGroups: TCmpSwFilterGroups;
protected
procedure VisitItem(const AItem: TBaseSwItem); override;
public
constructor Create();
destructor Destroy(); override;
property Groups: TCmpSwFilterGroups read FGroups;
property FilterUnmatched: Boolean read FFilterUnmatched write FFilterUnmatched;
property Groups: TCmpSwFilterGroups read FGroups;
end;
@ -72,7 +76,7 @@ uses
Masks,
SysUtils,
CmpSwObjects;
CmpSwObjects, Dialogs;
const
@ -105,6 +109,8 @@ end;
function TCmpSwFilterGroup.Matches(const AValue: String): Boolean;
var
filterIndex: Integer;
valueClass: TClass;
filterClass: TClass;
begin
Result := False;
@ -113,10 +119,24 @@ begin
for filterIndex := Pred(Filter.Count) downto 0 do
begin
if Assigned(Filter.Objects[filterIndex]) then
Result := TMask(Filter.Objects[filterIndex]).Matches(AValue)
else
begin
Result := TMask(Filter.Objects[filterIndex]).Matches(AValue);
end else
begin
Result := SameText(Filter[filterIndex], AValue);
if (not Result) and IncludeDescendants then
begin
filterClass := GetClass(Filter[filterIndex]);
if Assigned(filterClass) then
begin
valueClass := GetClass(AValue);
if Assigned(valueClass) then
Result := valueClass.InheritsFrom(filterClass);
end;
end;
end;
if Result then
Break;
end;
@ -197,20 +217,26 @@ begin
end;
function TCmpSwFilterGroups.Matches(const AValue: String): Boolean;
function TCmpSwFilterGroups.Matches(const AValue: String; AMatchDisabled: Boolean): TCmpSwMatchResult;
var
itemIndex: Integer;
begin
Result := False;
Result := mrNoMatch;
for itemIndex := Pred(Count) downto 0 do
begin
if Items[itemIndex].Enabled then
if AMatchDisabled or Items[itemIndex].Enabled then
begin
Result := Items[itemIndex].Matches(AValue);
if Result then
if Items[itemIndex].Matches(AValue) then
begin
if Items[itemIndex].Enabled then
Result := mrMatch
else
Result := mrDisabledMatch;
Break;
end;
end;
end;
end;
@ -235,8 +261,13 @@ end;
procedure TCmpSwComponentClassFilter.VisitItem(const AItem: TBaseSwItem);
begin
if Groups.Matches(TCmpSwComponent(AItem).ComponentClass) then
FilterItem(AItem);
case Groups.Matches(TCmpSwComponent(AItem).ComponentClass, FilterUnmatched) of
mrMatch:
FilterItem(AItem);
mrNoMatch:
if FilterUnmatched then
FilterItem(AItem);
end;
end;
end.

View File

@ -240,6 +240,42 @@ begin
CloseKey();
end;
end;
end else
begin
{ Fill default groups }
with AGroups.Add() do
begin
Name := 'Actions';
Filter.Add('TAction');
IncludeDescendants := True;
Visible := True;
end;
with AGroups.Add() do
begin
Name := 'Menu items';
Filter.Add('TMenuItem');
Visible := True;
end;
with AGroups.Add() do
begin
Name := 'Dataset fields';
Filter.Add('TField');
IncludeDescendants := True;
Visible := True;
end;
with AGroups.Add() do
begin
Name := 'DevEx Grid columns';
Filter.Add('TcxGridDBColumn');
Filter.Add('TcxGridColumn');
end;
end;
finally
Free();
@ -300,9 +336,10 @@ var
filterText: String;
begin
AGroup.Name := ARegistry.ReadString('Name');
AGroup.Enabled := ARegistry.ReadBool('Enabled');
AGroup.Visible := ARegistry.ReadBool('Visible');
AGroup.Name := ARegistry.ReadString('Name');
AGroup.Enabled := ARegistry.ReadBool('Enabled');
AGroup.IncludeDescendants := ARegistry.ReadBool('IncludeDescendants');
AGroup.Visible := ARegistry.ReadBool('Visible');
if ARegistry.ValueExists('Filter') then
begin
@ -323,6 +360,7 @@ var
begin
ARegistry.WriteString('Name', AGroup.Name);
ARegistry.WriteBool('Enabled', AGroup.Enabled);
ARegistry.WriteBool('IncludeDescendants', AGroup.IncludeDescendants);
ARegistry.WriteBool('Visible', AGroup.Visible);
if AGroup.Filter.Count > 0 then