From ad436d2657291f9f531082cc96d3e7ac3b9d1b02 Mon Sep 17 00:00:00 2001 From: mattias Date: Wed, 14 Dec 2005 01:34:07 +0000 Subject: [PATCH] implemented incremental search in codeexplorer git-svn-id: trunk@8310 - --- ide/codeexplorer.lfm | 25 +++++++-- ide/codeexplorer.lrs | 45 ++++++++------- ide/codeexplorer.pas | 109 ++++++++++++++++++++++++++++++++++-- ide/lazarusidestrconsts.pas | 1 + lcl/include/treeview.inc | 13 ----- 5 files changed, 151 insertions(+), 42 deletions(-) diff --git a/ide/codeexplorer.lfm b/ide/codeexplorer.lfm index 75d08f5066..108d0c0e3c 100644 --- a/ide/codeexplorer.lfm +++ b/ide/codeexplorer.lfm @@ -1,4 +1,5 @@ object CodeExplorerView: TCodeExplorerView + ActiveControl = RefreshButton Caption = 'CodeExplorerView' ClientHeight = 505 ClientWidth = 206 @@ -15,7 +16,7 @@ object CodeExplorerView: TCodeExplorerView Top = 175 Width = 206 object RefreshButton: TButton - BorderSpacing.OnChange = nil + BorderSpacing.InnerBorder = 2 Caption = 'Refresh' OnClick = RefreshButtonCLICK TabOrder = 0 @@ -23,7 +24,7 @@ object CodeExplorerView: TCodeExplorerView Width = 96 end object OptionsButton: TButton - BorderSpacing.OnChange = nil + BorderSpacing.InnerBorder = 2 Caption = 'Options' OnClick = OptionsButtonClick TabOrder = 1 @@ -33,7 +34,8 @@ object CodeExplorerView: TCodeExplorerView end object CodeTreeview: TTreeView Align = alBottom - BorderSpacing.OnChange = nil + Anchors = [akTop, akLeft, akRight, akBottom] + BorderSpacing.Top = 1 DefaultItemHeight = 16 HideSelection = False Images = Imagelist1 @@ -45,7 +47,22 @@ object CodeExplorerView: TCodeExplorerView OnDeletion = CodeTreeviewDELETION OnKeyUp = CodeTreeviewKeyUp Options = [tvoAutoItemHeight, tvoKeepCollapsedNodes, tvoRightClickSelect, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips] - Height = 480 + AnchorSideTop.Control = FilterEdit + Height = 456 + Top = 49 + Width = 206 + end + object FilterEdit: TEdit + Anchors = [akTop, akLeft, akRight] + OnChange = FilterEditChange + TabOrder = 3 + Text = 'FilterEdit' + AnchorSideLeft.Control = Owner + AnchorSideLeft.Side = asrTop + AnchorSideTop.Control = RefreshButton + AnchorSideRight.Control = Owner + AnchorSideRight.Side = asrBottom + Height = 23 Top = 25 Width = 206 end diff --git a/ide/codeexplorer.lrs b/ide/codeexplorer.lrs index 0bef619a7e..b7e23103a8 100644 --- a/ide/codeexplorer.lrs +++ b/ide/codeexplorer.lrs @@ -1,25 +1,32 @@ { This is an automatically generated lazarus resource file } LazarusResources.Add('TCodeExplorerView','FORMDATA',[ - 'TPF0'#17'TCodeExplorerView'#16'CodeExplorerView'#7'Caption'#6#16'CodeExplore' - +'rView'#12'ClientHeight'#3#249#1#11'ClientWidth'#3#206#0#10'KeyPreview'#9#7 - +'OnClose'#7#21'CodeExplorerViewCLOSE'#8'OnCreate'#7#22'CodeExplorerViewCREAT' - +'E'#9'OnDestroy'#7#23'CodeExplorerViewDestroy'#8'OnResize'#7#22'CodeExplorer' - +'ViewRESIZE'#13'PixelsPerInch'#2'p'#18'HorzScrollBar.Page'#3#205#0#18'VertSc' - +'rollBar.Page'#3#248#1#4'Left'#3'z'#1#6'Height'#3#249#1#3'Top'#3#175#0#5'Wid' - +'th'#3#206#0#0#7'TButton'#13'RefreshButton'#22'BorderSpacing.OnChange'#13#7 - +'Caption'#6#7'Refresh'#7'OnClick'#7#18'RefreshButtonCLICK'#8'TabOrder'#2#0#6 - +'Height'#2#25#5'Width'#2'`'#0#0#7'TButton'#13'OptionsButton'#22'BorderSpacin' - +'g.OnChange'#13#7'Caption'#6#7'Options'#7'OnClick'#7#18'OptionsButtonClick'#8 - +'TabOrder'#2#1#4'Left'#2'n'#6'Height'#2#25#5'Width'#2'`'#0#0#9'TTreeView'#12 - +'CodeTreeview'#5'Align'#7#8'alBottom'#22'BorderSpacing.OnChange'#13#17'Defau' - +'ltItemHeight'#2#16#13'HideSelection'#8#6'Images'#7#10'Imagelist1'#11'Parent' - +'Ctl3D'#8#9'PopupMenu'#7#13'TreePopupmenu'#16'RightClickSelect'#9#8'TabOrder' - +#2#2#10'OnDblClick'#7#20'CodeTreeviewDBLCLICK'#10'OnDeletion'#7#20'CodeTreev' - +'iewDELETION'#7'OnKeyUp'#7#17'CodeTreeviewKeyUp'#7'Options'#11#17'tvoAutoIte' - +'mHeight'#21'tvoKeepCollapsedNodes'#19'tvoRightClickSelect'#14'tvoShowButton' - +'s'#12'tvoShowLines'#11'tvoShowRoot'#11'tvoToolTips'#0#6'Height'#3#224#1#3'T' - +'op'#2#25#5'Width'#3#206#0#0#0#10'TImageList'#10'Imagelist1'#4'left'#2'@'#3 + 'TPF0'#17'TCodeExplorerView'#16'CodeExplorerView'#13'ActiveControl'#7#13'Refr' + +'eshButton'#7'Caption'#6#16'CodeExplorerView'#12'ClientHeight'#3#249#1#11'Cl' + +'ientWidth'#3#206#0#10'KeyPreview'#9#7'OnClose'#7#21'CodeExplorerViewCLOSE'#8 + +'OnCreate'#7#22'CodeExplorerViewCREATE'#9'OnDestroy'#7#23'CodeExplorerViewDe' + +'stroy'#8'OnResize'#7#22'CodeExplorerViewRESIZE'#13'PixelsPerInch'#2'p'#18'H' + +'orzScrollBar.Page'#3#205#0#18'VertScrollBar.Page'#3#248#1#4'Left'#3'z'#1#6 + +'Height'#3#249#1#3'Top'#3#175#0#5'Width'#3#206#0#0#7'TButton'#13'RefreshButt' + +'on'#25'BorderSpacing.InnerBorder'#2#2#7'Caption'#6#7'Refresh'#7'OnClick'#7 + +#18'RefreshButtonCLICK'#8'TabOrder'#2#0#6'Height'#2#25#5'Width'#2'`'#0#0#7'T' + +'Button'#13'OptionsButton'#25'BorderSpacing.InnerBorder'#2#2#7'Caption'#6#7 + +'Options'#7'OnClick'#7#18'OptionsButtonClick'#8'TabOrder'#2#1#4'Left'#2'n'#6 + +'Height'#2#25#5'Width'#2'`'#0#0#9'TTreeView'#12'CodeTreeview'#5'Align'#7#8'a' + +'lBottom'#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#8'akBottom'#0#17'Borde' + +'rSpacing.Top'#2#1#17'DefaultItemHeight'#2#16#13'HideSelection'#8#6'Images'#7 + +#10'Imagelist1'#11'ParentCtl3D'#8#9'PopupMenu'#7#13'TreePopupmenu'#16'RightC' + +'lickSelect'#9#8'TabOrder'#2#2#10'OnDblClick'#7#20'CodeTreeviewDBLCLICK'#10 + +'OnDeletion'#7#20'CodeTreeviewDELETION'#7'OnKeyUp'#7#17'CodeTreeviewKeyUp'#7 + +'Options'#11#17'tvoAutoItemHeight'#21'tvoKeepCollapsedNodes'#19'tvoRightClic' + +'kSelect'#14'tvoShowButtons'#12'tvoShowLines'#11'tvoShowRoot'#11'tvoToolTips' + +#0#21'AnchorSideTop.Control'#7#10'FilterEdit'#6'Height'#3#200#1#3'Top'#2'1'#5 + +'Width'#3#206#0#0#0#5'TEdit'#10'FilterEdit'#7'Anchors'#11#5'akTop'#6'akLeft' + +#7'akRight'#0#8'OnChange'#7#16'FilterEditChange'#8'TabOrder'#2#3#4'Text'#6#10 + +'FilterEdit'#22'AnchorSideLeft.Control'#7#5'Owner'#19'AnchorSideLeft.Side'#7 + +#6'asrTop'#21'AnchorSideTop.Control'#7#13'RefreshButton'#23'AnchorSideRight.' + +'Control'#7#5'Owner'#20'AnchorSideRight.Side'#7#9'asrBottom'#6'Height'#2#23#3 + +'Top'#2#25#5'Width'#3#206#0#0#0#10'TImageList'#10'Imagelist1'#4'left'#2'@'#3 +'top'#2' '#0#0#10'TPopupMenu'#13'TreePopupmenu'#4'left'#2'@'#3'top'#2'H'#0#0 +#0 ]); diff --git a/ide/codeexplorer.pas b/ide/codeexplorer.pas index 940e883efc..da24452326 100644 --- a/ide/codeexplorer.pas +++ b/ide/codeexplorer.pas @@ -37,11 +37,12 @@ uses Dialogs, Buttons, ComCtrls, Menus, // CodeTools CodeToolManager, CodeAtom, CodeCache, CodeTree, PascalParserTool, + KeywordFuncLists, // IDE Intf IDECommands, MenuIntf, // IDE LazarusIDEStrConsts, EnvironmentOpts, IDEOptionDefs, InputHistory, IDEProcs, - CodeExplOpts; + CodeExplOpts, StdCtrls; type TCodeExplorerView = class; @@ -60,6 +61,7 @@ type { TCodeExplorerView } TCodeExplorerView = class(TForm) + FilterEdit: TEdit; Imagelist1: TImageList; TreePopupmenu: TPopupMenu; RefreshButton: TButton; @@ -74,6 +76,7 @@ type procedure CodeTreeviewDeletion(Sender: TObject; Node: TTreeNode); procedure CodeTreeviewKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); + procedure FilterEditChange(Sender: TObject); procedure JumpToMenuitemClick(Sender: TObject); procedure OptionsButtonClick(Sender: TObject); procedure RefreshButtonClick(Sender: TObject); @@ -100,11 +103,14 @@ type ImgIDClass: Integer; ImgIDProc: Integer; ImgIDProperty: Integer; + FLastFilter: string; + function GetFilter: string; function GetNodeDescription(ACodeTool: TCodeTool; CodeNode: TCodeTreeNode): string; function GetNodeImage(CodeNode: TCodeTreeNode): integer; procedure CreateNodes(ACodeTool: TCodeTool; CodeNode: TCodeTreeNode; ParentViewNode, InFrontViewNode: TTreeNode; CreateSiblings: boolean); + procedure SetFilter(const AValue: string); protected procedure KeyUp(var Key: Word; Shift: TShiftState); override; public @@ -113,11 +119,15 @@ type procedure Refresh; procedure JumpToSelection; procedure CurrentCodeBufferChanged; + procedure FilterChanged; + function FilterNode(ANode: TTreeNode; const TheFilter: string): boolean; + function FilterFits(const NodeText, TheFilter: string): boolean; virtual; public property OnGetCodeTree: TOnGetCodeTree read FOnGetCodeTree write FOnGetCodeTree; property OnJumpToCode: TOnJumpToCode read FOnJumpToCode write FOnJumpToCode; property MainFilename: string read FMainFilename; + property Filter: string read GetFilter write SetFilter; end; const @@ -210,6 +220,7 @@ begin RefreshButton.Caption:=dlgUnitDepRefresh; OptionsButton.Caption:=dlgFROpts; + FilterEdit.Text:=lisCEFilter; ImgIDDefault:=0; AddResImg(Imagelist1,'ce_default'); @@ -259,16 +270,11 @@ begin end; procedure TCodeExplorerView.CodeExplorerViewRESIZE(Sender: TObject); -var - y: Integer; begin RefreshButton.Width:=ClientWidth div 2; with OptionsButton do SetBounds(RefreshButton.Width,Top, Parent.ClientWidth-RefreshButton.Width,Height); - y:=RefreshButton.Top+RefreshButton.Height; - with CodeTreeview do - SetBounds(0,y,Parent.ClientWidth,Parent.ClientHeight-y); end; procedure TCodeExplorerView.CodeTreeviewDBLCLICK(Sender: TObject); @@ -290,6 +296,12 @@ begin JumpToSelection; end; +procedure TCodeExplorerView.FilterEditChange(Sender: TObject); +begin + if Sender=nil then ; + FilterChanged; +end; + procedure TCodeExplorerView.CodeExplorerViewCLOSE(Sender: TObject; var CloseAction: TCloseAction); begin @@ -348,6 +360,12 @@ begin end; end; +function TCodeExplorerView.GetFilter: string; +begin + Result:=FilterEdit.Text; + if Result=lisCEFilter then Result:=''; +end; + function TCodeExplorerView.GetNodeImage(CodeNode: TCodeTreeNode): integer; begin case CodeNode.Desc of @@ -454,6 +472,13 @@ begin end; end; +procedure TCodeExplorerView.SetFilter(const AValue: string); +begin + if Filter=AValue then exit; + FilterEdit.Text:=AValue; + FilterChanged; +end; + procedure TCodeExplorerView.KeyUp(var Key: Word; Shift: TShiftState); begin inherited KeyUp(Key, Shift); @@ -547,6 +572,78 @@ begin Refresh; end; +procedure TCodeExplorerView.FilterChanged; +var + TheFilter: String; + ANode: TTreeNode; +begin + if FUpdateCount>0 then begin + Include(FFlags,cevRefreshNeeded); + exit; + end; + TheFilter:=FilterEdit.Text; + if FLastFilter=TheFilter then exit; + FLastFilter:=TheFilter; + CodeTreeview.BeginUpdate; + CodeTreeview.Options:=CodeTreeview.Options+[tvoAllowMultiselect]; + ANode:=CodeTreeview.Items.GetFirstNode; + while ANode<>nil do begin + FilterNode(ANode,TheFilter); + ANode:=ANode.GetNextSibling; + end; + CodeTreeview.EndUpdate; +end; + +function TCodeExplorerView.FilterNode(ANode: TTreeNode; const TheFilter: string + ): boolean; +var + ChildNode: TTreeNode; + HasVisibleChilds: Boolean; +begin + if ANode=nil then exit; + ChildNode:=ANode.GetFirstChild; + HasVisibleChilds:=false; + while ChildNode<>nil do begin + if FilterNode(ChildNode,TheFilter) then + HasVisibleChilds:=true; + ChildNode:=ChildNode.GetNextSibling; + end; + ANode.Expanded:=HasVisibleChilds; + ANode.Selected:=FilterFits(ANode.Text,TheFilter); + Result:=ANode.Expanded or ANode.Selected; +end; + +function TCodeExplorerView.FilterFits(const NodeText, TheFilter: string + ): boolean; +var + Src: PChar; + PFilter: PChar; + c: Char; + i: Integer; +begin + if TheFilter='' then begin + Result:=true; + end else begin + Src:=PChar(NodeText); + PFilter:=PChar(TheFilter); + repeat + c:=Src^; + if c<>#0 then begin + if UpChars[Src^]=UpChars[PFilter^] then begin + i:=1; + while (UpChars[Src[i]]=UpChars[PFilter[i]]) and (PFilter[i]<>#0) do + inc(i); + if PFilter[i]=#0 then begin + exit(true); + end; + end; + end else + exit(false); + inc(Src); + until false; + end; +end; + initialization {$I codeexplorer.lrs} CodeExplorerView:=nil; diff --git a/ide/lazarusidestrconsts.pas b/ide/lazarusidestrconsts.pas index 41fad15f2b..89ff90a6e1 100644 --- a/ide/lazarusidestrconsts.pas +++ b/ide/lazarusidestrconsts.pas @@ -1130,6 +1130,7 @@ resourcestring dlgTextToFing = '&Text to Find'; dlgReplaceWith = '&Replace With'; dlgFROpts = 'Options'; + lisCEFilter = '(Filter)'; dlgCaseSensitive = 'Case Sensitive'; lisDistinguishBigAndSmallLettersEGAAndA = 'Distinguish big and small ' +'letters e.g. A and a'; diff --git a/lcl/include/treeview.inc b/lcl/include/treeview.inc index 9e6a6fe3ab..4aa63676c2 100644 --- a/lcl/include/treeview.inc +++ b/lcl/include/treeview.inc @@ -447,21 +447,8 @@ begin end; function TTreeNode.CompareCount(CompareMe: Integer): Boolean; -{var - ACount: integer; - Node: TTreeNode;} Begin Result:=(CompareMe=Count); - { - ACount := 0; - Result := False; - Node := GetFirstChild; - while Node <> nil do begin - Inc(ACount); - Node := Node.GetNextChild(Node); - if ACount > CompareMe then Exit; - end; - if ACount = CompareMe then Result := True;} end; function TTreeNode.DoCanExpand(ExpandIt: Boolean): Boolean;