IDE: Turn ProcedureList into a proper IDE window. Position and size are remembered. Issue #13570.

git-svn-id: trunk@50908 -
This commit is contained in:
juha 2015-12-18 17:45:49 +00:00
parent 21889249ce
commit 2c80e0baa3
4 changed files with 201 additions and 417 deletions

View File

@ -88,7 +88,8 @@ type
nmiwCodeBrowser, nmiwCodeBrowser,
nmiwIssueBrowser, nmiwIssueBrowser,
nmiwJumpHistory, nmiwJumpHistory,
nmiwComponentList nmiwComponentList,
nmiwProcedureList
); );
const const
@ -124,7 +125,8 @@ const
'CodeBrowser', 'CodeBrowser',
'IssueBrowser', 'IssueBrowser',
'JumpHistory', 'JumpHistory',
'ComponentList' 'ComponentList',
'ProcedureList'
); );
type type

View File

@ -659,6 +659,8 @@ type
procedure ShowDesignerForm(AForm: TCustomForm); procedure ShowDesignerForm(AForm: TCustomForm);
procedure DoViewAnchorEditor(State: TIWGetFormState = iwgfShowOnTop); procedure DoViewAnchorEditor(State: TIWGetFormState = iwgfShowOnTop);
procedure DoViewTabOrderEditor(State: TIWGetFormState = iwgfShowOnTop); procedure DoViewTabOrderEditor(State: TIWGetFormState = iwgfShowOnTop);
// ProcedureList
procedure DoViewProcedureList(State: TIWGetFormState = iwgfShowOnTop);
// editor and environment options // editor and environment options
procedure LoadDesktopSettings(TheEnvironmentOptions: TEnvironmentOptions); procedure LoadDesktopSettings(TheEnvironmentOptions: TEnvironmentOptions);
procedure SaveDesktopSettings(TheEnvironmentOptions: TEnvironmentOptions); procedure SaveDesktopSettings(TheEnvironmentOptions: TEnvironmentOptions);
@ -919,8 +921,7 @@ type
// message view // message view
function GetSelectedCompilerMessage: TMessageLine; override; function GetSelectedCompilerMessage: TMessageLine; override;
function DoJumpToCompilerMessage(FocusEditor: boolean; Msg: TMessageLine = nil function DoJumpToCompilerMessage(FocusEditor: boolean; Msg: TMessageLine = nil): boolean; override;
): boolean; override;
procedure DoJumpToNextCompilerMessage(aMinUrgency: TMessageLineUrgency; DirectionDown: boolean); override; procedure DoJumpToNextCompilerMessage(aMinUrgency: TMessageLineUrgency; DirectionDown: boolean); override;
procedure DoShowMessagesView(BringToFront: boolean = true); override; procedure DoShowMessagesView(BringToFront: boolean = true); override;
@ -3005,7 +3006,7 @@ end;
procedure TMainIDE.mnuSearchProcedureList(Sender: TObject); procedure TMainIDE.mnuSearchProcedureList(Sender: TObject);
begin begin
ProcedureList.ExecuteProcedureList(Sender); DoViewProcedureList;
end; end;
procedure TMainIDE.mnuSetFreeBookmark(Sender: TObject); procedure TMainIDE.mnuSetFreeBookmark(Sender: TObject);
@ -3515,7 +3516,7 @@ procedure TMainIDE.DoViewAnchorEditor(State: TIWGetFormState);
begin begin
if AnchorDesigner=nil then if AnchorDesigner=nil then
IDEWindowCreators.CreateForm(AnchorDesigner,TAnchorDesigner, IDEWindowCreators.CreateForm(AnchorDesigner,TAnchorDesigner,
State=iwgfDisabled,LazarusIDE.OwningComponent) State=iwgfDisabled, LazarusIDE.OwningComponent)
else if State=iwgfDisabled then else if State=iwgfDisabled then
AnchorDesigner.DisableAlign; AnchorDesigner.DisableAlign;
if State>=iwgfShow then if State>=iwgfShow then
@ -3526,13 +3527,24 @@ procedure TMainIDE.DoViewTabOrderEditor(State: TIWGetFormState);
begin begin
if TabOrderDialog=nil then if TabOrderDialog=nil then
IDEWindowCreators.CreateForm(TabOrderDialog,TTabOrderDialog, IDEWindowCreators.CreateForm(TabOrderDialog,TTabOrderDialog,
State=iwgfDisabled,LazarusIDE.OwningComponent) State=iwgfDisabled, LazarusIDE.OwningComponent)
else if State=iwgfDisabled then else if State=iwgfDisabled then
TabOrderDialog.DisableAlign; TabOrderDialog.DisableAlign;
if State>=iwgfShow then if State>=iwgfShow then
IDEWindowCreators.ShowForm(TabOrderDialog,State=iwgfShowOnTop); IDEWindowCreators.ShowForm(TabOrderDialog,State=iwgfShowOnTop);
end; end;
procedure TMainIDE.DoViewProcedureList(State: TIWGetFormState);
begin
if ProcListView=nil then
IDEWindowCreators.CreateForm(ProcListView,TProcedureListForm,
State=iwgfDisabled, LazarusIDE.OwningComponent)
else if State=iwgfDisabled then
ProcListView.DisableAlign;
if State>=iwgfShow then
IDEWindowCreators.ShowForm(ProcListView, State=iwgfShowOnTop);
end;
procedure TMainIDE.SetToolStatus(const AValue: TIDEToolStatus); procedure TMainIDE.SetToolStatus(const AValue: TIDEToolStatus);
begin begin
if ToolStatus=AValue then exit; if ToolStatus=AValue then exit;

View File

@ -1,23 +1,24 @@
object ProcedureListForm: TProcedureListForm object ProcedureListForm: TProcedureListForm
Left = 289 Left = 431
Height = 688 Height = 489
Top = 140 Top = 140
Width = 952 Width = 816
ActiveControl = cbObjects ActiveControl = FilterMethods
Caption = 'Procedure List - ' Caption = 'Procedure List - '
ClientHeight = 688 ClientHeight = 489
ClientWidth = 952 ClientWidth = 816
OnClose = FormClose
OnCreate = FormCreate OnCreate = FormCreate
OnKeyPress = FormKeyPress OnKeyPress = FormKeyPress
OnResize = FormResize OnResize = FormResize
OnShow = FormShow OnShow = FormShow
Position = poScreenCenter LCLVersion = '1.7'
LCLVersion = '1.5' Visible = True
object StatusBar: TStatusBar object StatusBar: TStatusBar
Left = 0 Left = 0
Height = 23 Height = 21
Top = 665 Top = 468
Width = 952 Width = 816
Panels = < Panels = <
item item
Width = 400 Width = 400
@ -31,14 +32,14 @@ object ProcedureListForm: TProcedureListForm
Left = 0 Left = 0
Height = 26 Height = 26
Top = 0 Top = 0
Width = 952 Width = 816
Caption = 'TB' Caption = 'TB'
EdgeBorders = [] EdgeBorders = []
TabOrder = 1 TabOrder = 1
object tbAbout: TToolButton object tbAbout: TToolButton
Left = 136 Left = 85
Hint = 'About' Hint = 'About'
Top = 2 Top = 0
Caption = 'tbAbout' Caption = 'tbAbout'
ImageIndex = 9 ImageIndex = 9
OnClick = tbAboutClick OnClick = tbAboutClick
@ -46,17 +47,17 @@ object ProcedureListForm: TProcedureListForm
ShowHint = True ShowHint = True
end end
object ToolButton2: TToolButton object ToolButton2: TToolButton
Left = 131 Left = 80
Height = 22 Height = 22
Top = 2 Top = 0
Width = 5 Width = 5
Caption = 'ToolButton2' Caption = 'ToolButton2'
Style = tbsDivider Style = tbsDivider
end end
object tbJumpTo: TToolButton object tbJumpTo: TToolButton
Left = 108 Left = 57
Hint = 'Jump To Selection' Hint = 'Jump To Selection'
Top = 2 Top = 0
Caption = 'Goto' Caption = 'Goto'
ImageIndex = 5 ImageIndex = 5
OnClick = LVDblClick OnClick = LVDblClick
@ -64,49 +65,17 @@ object ProcedureListForm: TProcedureListForm
ShowHint = True ShowHint = True
end end
object ToolButton4: TToolButton object ToolButton4: TToolButton
Left = 103 Left = 52
Height = 22 Height = 22
Top = 2 Top = 0
Width = 5 Width = 5
Caption = 'ToolButton4' Caption = 'ToolButton4'
Style = tbsDivider Style = tbsDivider
end end
object tbFilterAny: TToolButton
Left = 80
Hint = 'Filter by matching any part of method'
Top = 2
Caption = 'tbFilterAny'
Down = True
Grouped = True
ImageIndex = 8
ParentShowHint = False
ShowHint = True
Style = tbsCheck
end
object tbFilterStart: TToolButton
Left = 57
Hint = 'Filter by matching with start of method'
Top = 2
Caption = 'tbFilterStart'
Grouped = True
ImageIndex = 7
ParentShowHint = False
ShowHint = True
Style = tbsCheck
end
object ToolButton7: TToolButton
Left = 52
Height = 22
Top = 2
Width = 5
Caption = 'ToolButton7'
Style = tbsDivider
Visible = False
end
object tbChangeFont: TToolButton object tbChangeFont: TToolButton
Left = 29 Left = 29
Hint = 'Change Font' Hint = 'Change Font'
Top = 2 Top = 0
Caption = 'tbChangeFont' Caption = 'tbChangeFont'
ImageIndex = 4 ImageIndex = 4
OnClick = tbChangeFontClick OnClick = tbChangeFontClick
@ -117,7 +86,7 @@ object ProcedureListForm: TProcedureListForm
object ToolButton9: TToolButton object ToolButton9: TToolButton
Left = 24 Left = 24
Height = 22 Height = 22
Top = 2 Top = 0
Width = 5 Width = 5
Caption = 'ToolButton9' Caption = 'ToolButton9'
Style = tbsDivider Style = tbsDivider
@ -125,7 +94,7 @@ object ProcedureListForm: TProcedureListForm
object tbCopy: TToolButton object tbCopy: TToolButton
Left = 1 Left = 1
Hint = 'Copy method name to the clipboard' Hint = 'Copy method name to the clipboard'
Top = 2 Top = 0
Caption = 'tbCopy' Caption = 'tbCopy'
ImageIndex = 6 ImageIndex = 6
OnClick = tbCopyClick OnClick = tbCopyClick
@ -135,85 +104,75 @@ object ProcedureListForm: TProcedureListForm
end end
object pnlHeader: TPanel object pnlHeader: TPanel
Left = 0 Left = 0
Height = 35 Height = 41
Top = 26 Top = 26
Width = 952 Width = 816
Align = alTop Align = alTop
AutoSize = True AutoSize = True
BevelOuter = bvNone BevelOuter = bvNone
ClientHeight = 35 ClientHeight = 41
ClientWidth = 952 ClientWidth = 816
ParentColor = False ParentColor = False
TabOrder = 2 TabOrder = 2
object lblSearch: TLabel
AnchorSideTop.Control = pnlHeader
AnchorSideTop.Side = asrCenter
Left = 6
Height = 15
Top = 10
Width = 35
BorderSpacing.Around = 6
Caption = '&Search'
ParentColor = False
end
object lblObjects: TLabel object lblObjects: TLabel
AnchorSideLeft.Control = edMethods AnchorSideLeft.Control = FilterMethods
AnchorSideLeft.Side = asrBottom AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = pnlHeader AnchorSideTop.Control = pnlHeader
AnchorSideTop.Side = asrCenter AnchorSideTop.Side = asrCenter
Left = 581 Left = 269
Height = 15 Height = 17
Top = 10 Top = 12
Width = 40 Width = 49
BorderSpacing.Left = 12 BorderSpacing.Left = 110
BorderSpacing.Around = 6 BorderSpacing.Around = 6
Caption = '&Objects' Caption = '&Objects'
ParentColor = False ParentColor = False
end end
object edMethods: TEdit
AnchorSideLeft.Control = lblSearch
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = pnlHeader
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = cbObjects
AnchorSideBottom.Side = asrBottom
Left = 47
Height = 23
Top = 6
Width = 516
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Left = 6
BorderSpacing.Top = 6
BorderSpacing.Right = 6
OnChange = edMethodsChange
OnKeyDown = edMethodsKeyDown
OnKeyPress = edMethodsKeyPress
TabOrder = 0
end
object cbObjects: TComboBox object cbObjects: TComboBox
AnchorSideLeft.Control = lblObjects AnchorSideLeft.Control = lblObjects
AnchorSideLeft.Side = asrBottom AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = pnlHeader AnchorSideTop.Control = pnlHeader
AnchorSideRight.Control = pnlHeader AnchorSideRight.Control = pnlHeader
AnchorSideRight.Side = asrBottom AnchorSideRight.Side = asrBottom
Left = 627 Left = 324
Height = 23 Height = 29
Top = 6 Top = 6
Width = 319 Width = 486
Anchors = [akTop, akLeft, akRight] Anchors = [akTop, akLeft, akRight]
BorderSpacing.Around = 6 BorderSpacing.Around = 6
ItemHeight = 15 ItemHeight = 0
OnChange = cbObjectsChange OnChange = cbObjectsChange
Sorted = True Sorted = True
Style = csDropDownList Style = csDropDownList
TabOrder = 0
end
object FilterMethods: TListViewFilterEdit
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = pnlHeader
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = cbObjects
AnchorSideBottom.Side = asrBottom
Left = 6
Height = 29
Top = 6
Width = 147
ButtonWidth = 23
NumGlyphs = 1
Anchors = [akTop, akLeft, akBottom]
BorderSpacing.Left = 6
BorderSpacing.Top = 6
BorderSpacing.Right = 6
MaxLength = 0
TabOrder = 1 TabOrder = 1
FilteredListview = LV
ByAllFields = True
end end
end end
object LV: TListView object LV: TListView
Left = 0 Left = 0
Height = 604 Height = 401
Top = 61 Top = 67
Width = 952 Width = 816
Align = alClient Align = alClient
Columns = < Columns = <
item item
@ -227,7 +186,7 @@ object ProcedureListForm: TProcedureListForm
end end
item item
Caption = 'Line' Caption = 'Line'
Width = 238 Width = 550
end> end>
HideSelection = False HideSelection = False
Items.LazData = { Items.LazData = {

View File

@ -36,19 +36,25 @@ unit ProcedureList;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
interface interface
uses uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, // FCL, LCL
ExtCtrls, StdCtrls, Classes, SysUtils,
CodeTree, CodeToolManager, CodeCache, Forms, Controls, Graphics, Dialogs, ComCtrls, ExtCtrls, StdCtrls, LCLType, Clipbrd,
IDEImagesIntf; // Codetools
CodeTree, CodeToolManager, CodeCache, PascalParserTool, KeywordFuncLists, FileProcs,
// IdeIntf
IDEImagesIntf, SrcEditorIntf, IDEWindowIntf, LazIDEIntf, IDECommands,
ListViewFilterEdit,
// IDE
IDEOptionDefs, LazarusIDEStrConsts;
type type
{ TProcedureListForm } { TProcedureListForm }
TProcedureListForm = class(TForm) TProcedureListForm = class(TForm)
cbObjects: TComboBox; cbObjects: TComboBox;
edMethods: TEdit; FilterMethods: TListViewFilterEdit;
lblObjects: TLabel; lblObjects: TLabel;
lblSearch: TLabel;
LV: TListView; LV: TListView;
pnlHeader: TPanel; pnlHeader: TPanel;
StatusBar: TStatusBar; StatusBar: TStatusBar;
@ -58,16 +64,11 @@ type
ToolButton2: TToolButton; ToolButton2: TToolButton;
tbJumpTo: TToolButton; tbJumpTo: TToolButton;
ToolButton4: TToolButton; ToolButton4: TToolButton;
tbFilterAny: TToolButton;
tbFilterStart: TToolButton;
ToolButton7: TToolButton;
tbChangeFont: TToolButton; tbChangeFont: TToolButton;
ToolButton9: TToolButton; ToolButton9: TToolButton;
procedure cbObjectsChange(Sender: TObject); procedure cbObjectsChange(Sender: TObject);
procedure edMethodsChange(Sender: TObject);
procedure edMethodsKeyDown(Sender: TObject; var Key: Word;
{%H-}Shift: TShiftState);
procedure edMethodsKeyPress(Sender: TObject; var Key: char); procedure edMethodsKeyPress(Sender: TObject; var Key: char);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject); procedure FormCreate(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: char); procedure FormKeyPress(Sender: TObject; var Key: char);
procedure FormResize(Sender: TObject); procedure FormResize(Sender: TObject);
@ -86,11 +87,10 @@ type
{ Move editors focus to selected method. } { Move editors focus to selected method. }
procedure JumpToSelection; procedure JumpToSelection;
{ Populates Listview based on selected Class and user entered filter. } { Populates Listview based on selected Class and user entered filter. }
procedure AddToListView(pCodeTool: TCodeTool; pNode: TCodeTreeNode);
procedure PopulateListview; procedure PopulateListview;
{ Populates only tho cbObjects combo with available classes. } { Populates only tho cbObjects combo with available classes. }
procedure PopulateObjectsCombo; procedure PopulateObjectsCombo;
procedure AddToListView(pCodeTool: TCodeTool; pNode: TCodeTreeNode);
function PassFilter(pSearchAll: boolean; pProcName, pSearchStr: string; pCodeTool: TCodeTool; pNode: TCodeTreeNode): boolean;
public public
property MainFilename: string read FMainFilename; property MainFilename: string read FMainFilename;
property Caret: TCodeXYPosition read FCaret; property Caret: TCodeXYPosition read FCaret;
@ -98,128 +98,70 @@ type
end; end;
var
procedure ExecuteProcedureList(Sender: TObject); ProcListView: TProcedureListForm = nil;
implementation implementation
{$R *.lfm} {$R *.lfm}
uses
SrcEditorIntf
,PascalParserTool
,KeywordFuncLists
,LCLType
,LazIDEIntf
,IDECommands
,Clipbrd
,LazarusIDEStrConsts
;
const const
cAbout = cAbout =
'Procedure List (Lazarus addon)' + #10#10 + 'Procedure List (Lazarus addon)' + #10#10 +
'Author: Graeme Geldenhuys (graemeg@gmail.com)' + #10 + 'Author: Graeme Geldenhuys (graemeg@gmail.com)' + #10 +
'Inspired by: GExperts (www.gexperts.org)'; 'Inspired by: GExperts (www.gexperts.org)';
// ToDo: set a callback notification for source editor page change.
{ This is where it all starts. Gets called from Lazarus. }
procedure ExecuteProcedureList(Sender: TObject);
var
frm: TProcedureListForm;
begin
Assert(Sender<>nil); // removes compiler warning
frm := TProcedureListForm.Create(nil);
try
frm.ShowModal;
if frm.ModalResult = mrOK then // we need to jump
begin
LazarusIDE.DoOpenFileAndJumpToPos(frm.Caret.Code.Filename,
Point(frm.Caret.X, frm.Caret.Y), frm.NewTopLine, -1,-1,
[ofRegularFile,ofUseCache]);
end;
finally
frm.Free;
end;
end;
{ Check, if the given string starts with this substring. Check ignores case. }
function StrStartsWith(sStr, sSubstr: String): Boolean;
begin
sStr := AnsiUpperCase(sStr);
sSubstr := AnsiUpperCase(sSubstr);
Result := Pos(sSubstr, sStr) = 1;
end;
function StrContains(const SubStr, Str: string; CaseSensitive: Boolean): Boolean;
begin
if CaseSensitive then
Result := Pos(SubStr, Str) > 0
else
Result := Pos(AnsiUpperCase(SubStr), AnsiUpperCase(Str)) > 0;
end;
function FilterFits(const SubStr, Str: string): boolean;
var
Src: PChar;
PFilter: PChar;
c: Char;
i: Integer;
begin
Result := SubStr='';
if not Result then
begin
Src := PChar(Str);
PFilter := PChar(SubStr);
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;
{ TProcedureListForm } { TProcedureListForm }
procedure TProcedureListForm.FormCreate(Sender: TObject);
begin
Name:=NonModalIDEWindowNames[nmiwProcedureList];
SetupGUI;
// Very weird: populating Combobox here shows only unique entries, no duplicates.
// Calling the same method in FormShow shows duplicates. Makes no sense ...
//PopulateObjectsCombo;
end;
procedure TProcedureListForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
if Assigned(Parent) then
begin
// Using a dock manager...
CloseAction := caNone;
// Copied from TComponentListForm.FormClose
if Assigned(HostDockSite) and (HostDockSite.DockClientCount <= 1)
and (HostDockSite is TCustomForm) and (HostDockSite.Parent = nil) then
begin
TCustomForm(HostDockSite).Close;
end;
end;
end;
procedure TProcedureListForm.FormShow(Sender: TObject);
begin
if Assigned(SourceEditorManagerIntf.ActiveEditor) then
FMainFilename := SourceEditorManagerIntf.ActiveEditor.Filename
else
FMainFilename := '';
Caption := lisPListProcedureList + ' - ' + ExtractFileName(FMainFilename);
PopulateObjectsCombo;
PopulateListView;
StatusBar.Panels[0].Text := self.MainFilename;
FilterMethods.SetFocus; // ActiveControl gets lost sometimes.
end;
procedure TProcedureListForm.FormResize(Sender: TObject); procedure TProcedureListForm.FormResize(Sender: TObject);
begin begin
StatusBar.Panels[0].Width := self.ClientWidth - 105; StatusBar.Panels[0].Width := self.ClientWidth - 105;
end; end;
procedure TProcedureListForm.FormShow(Sender: TObject);
begin
edMethods.SetFocus;
end;
procedure TProcedureListForm.LVDblClick(Sender: TObject); procedure TProcedureListForm.LVDblClick(Sender: TObject);
begin begin
JumpToSelection; JumpToSelection;
end; end;
procedure TProcedureListForm.LVSelectItem(Sender: TObject; Item: TListItem; procedure TProcedureListForm.LVSelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean); Selected: Boolean);
begin begin
@ -231,7 +173,6 @@ begin
StatusBar.Panels[0].Text := Item.SubItems[4]; StatusBar.Panels[0].Text := Item.SubItems[4];
end; end;
procedure TProcedureListForm.tbAboutClick(Sender: TObject); procedure TProcedureListForm.tbAboutClick(Sender: TObject);
begin begin
ShowMessage(cAbout); ShowMessage(cAbout);
@ -242,27 +183,21 @@ begin
end; end;
procedure TProcedureListForm.tbCopyClick(Sender: TObject); procedure TProcedureListForm.tbCopyClick(Sender: TObject);
begin begin
if Assigned(LV.Selected) then if Assigned(LV.Selected) then
Clipboard.AsText := LV.Selected.SubItems[0]; Clipboard.AsText := LV.Selected.SubItems[0];
end; end;
procedure TProcedureListForm.SetupGUI; procedure TProcedureListForm.SetupGUI;
begin begin
self.KeyPreview := True; self.KeyPreview := True;
self.Position := poScreenCenter; self.Position := poScreenCenter;
// assign resource strings to Captions and Hints // assign resource strings to Captions and Hints
self.Caption := lisPListProcedureList;
lblObjects.Caption := lisPListObjects; lblObjects.Caption := lisPListObjects;
lblSearch.Caption := lisMenuSearch;
tbAbout.Hint := lisMenuTemplateAbout; tbAbout.Hint := lisMenuTemplateAbout;
tbJumpTo.Hint := lisPListJumpToSelection; tbJumpTo.Hint := lisPListJumpToSelection;
tbFilterAny.Hint := lisPListFilterAny;
tbFilterStart.Hint := lisPListFilterStart;
tbChangeFont.Hint := lisPListChangeFont; tbChangeFont.Hint := lisPListChangeFont;
tbCopy.Hint := lisPListCopyMethodToClipboard; tbCopy.Hint := lisPListCopyMethodToClipboard;
LV.Column[1].Caption := lisProcedure; LV.Column[1].Caption := lisProcedure;
@ -275,8 +210,6 @@ begin
tbChangeFont.ImageIndex := IDEImages.LoadImage(16, 'item_font'); tbChangeFont.ImageIndex := IDEImages.LoadImage(16, 'item_font');
tbAbout.ImageIndex := IDEImages.LoadImage(16, 'menu_information'); tbAbout.ImageIndex := IDEImages.LoadImage(16, 'menu_information');
tbJumpTo.ImageIndex := IDEImages.LoadImage(16, 'menu_goto_line'); tbJumpTo.ImageIndex := IDEImages.LoadImage(16, 'menu_goto_line');
tbFilterAny.ImageIndex := IDEImages.LoadImage(16, 'item_filter');
tbFilterStart.ImageIndex := IDEImages.LoadImage(16, 'item_filter');
LV.Column[0].Width := 20; LV.Column[0].Width := 20;
LV.Column[1].Width := 300; LV.Column[1].Width := 300;
@ -289,14 +222,11 @@ begin
LV.SortType := stText; LV.SortType := stText;
LV.HideSelection := False; LV.HideSelection := False;
LV.Items.Clear;
cbObjects.Style := csDropDownList; cbObjects.Style := csDropDownList;
cbObjects.Sorted := True; cbObjects.Sorted := True;
cbObjects.DropDownCount := 8; cbObjects.DropDownCount := 8;
end; end;
procedure TProcedureListForm.JumpToSelection; procedure TProcedureListForm.JumpToSelection;
var var
lItem: TListItem; lItem: TListItem;
@ -324,10 +254,46 @@ begin
if not ACodeTool.CleanPosToCaretAndTopLine(lStartPos, FCaret, FNewTopLine) then if not ACodeTool.CleanPosToCaretAndTopLine(lStartPos, FCaret, FNewTopLine) then
Exit; //==> Exit; //==>
{ This should close the form } LazarusIDE.DoOpenFileAndJumpToPos(Caret.Code.Filename, Point(Caret.X, Caret.Y),
self.ModalResult := mrOK; NewTopLine, -1,-1, [ofRegularFile,ofUseCache]);
Close;
end; end;
procedure TProcedureListForm.AddToListView(pCodeTool: TCodeTool; pNode: TCodeTreeNode);
var
Data: TStringArray;
lNodeText: string;
lCaret: TCodeXYPosition;
begin
SetLength(Data, 6); // Data[0] remains empty
{ procedure name }
Data[1] := pCodeTool.ExtractProcHead(pNode,
[phpWithoutParamList, phpWithoutBrackets, phpWithoutSemicolon]);
{ type }
lNodeText := pCodeTool.ExtractProcHead(pNode,
[phpWithStart, phpWithoutParamList, phpWithoutBrackets, phpWithoutSemicolon]);
if Pos('procedure', lNodeText) > 0 then
Data[2] := 'Procedure'
else
Data[2] := 'Function';
{ line number }
if pCodeTool.CleanPosToCaret(pNode.StartPos, lCaret) then
Data[3] := IntToStr(lCaret.Y);
{ start pos - used by JumpToSelected() }
Data[4] := IntToStr(pNode.StartPos);
{ full procedure name used in statusbar }
Data[5] := pCodeTool.ExtractProcHead(pNode,
[phpWithStart,phpWithVarModifiers,
phpWithParameterNames,phpWithDefaultValues,phpWithResultType,
phpWithOfObject,phpWithCallingSpecs,phpWithProcModifiers]);
FilterMethods.Items.Add(Data);
end;
procedure TProcedureListForm.PopulateListview; procedure TProcedureListForm.PopulateListview;
var var
@ -336,9 +302,8 @@ var
lCodeTool: TCodeTool; lCodeTool: TCodeTool;
lNode: TCodeTreeNode; lNode: TCodeTreeNode;
begin begin
LV.BeginUpdate;
try try
LV.Items.Clear; FilterMethods.Items.Clear;
{ get active source editor } { get active source editor }
lSrcEditor := SourceEditorManagerIntf.ActiveEditor; lSrcEditor := SourceEditorManagerIntf.ActiveEditor;
if lSrcEditor = nil then if lSrcEditor = nil then
@ -349,9 +314,7 @@ begin
CodeToolBoss.Explore(lCodeBuffer,lCodeTool,False); CodeToolBoss.Explore(lCodeBuffer,lCodeTool,False);
{ copy the tree } { copy the tree }
if (lCodeTool = nil) if (lCodeTool = nil) or (lCodeTool.Tree = nil) or (lCodeTool.Tree.Root = nil) then
or (lCodeTool.Tree = nil)
or (lCodeTool.Tree.Root = nil) then
Exit; //==> Exit; //==>
if Assigned(lCodeTool.Tree) then if Assigned(lCodeTool.Tree) then
@ -359,33 +322,28 @@ begin
{ Find the starting point } { Find the starting point }
lNode := lCodeTool.FindImplementationNode; lNode := lCodeTool.FindImplementationNode;
if lNode = nil then if lNode = nil then
begin
{ fall back - guess we are working with a program unit } { fall back - guess we are working with a program unit }
lNode := lCodeTool.Tree.Root; lNode := lCodeTool.Tree.Root;
end;
{ populate the listview here } { populate the listview here }
lNode := lNode.FirstChild; lNode := lNode.FirstChild;
while lNode <> nil do while lNode <> nil do
begin begin
if lNode.Desc = ctnProcedure then if lNode.Desc = ctnProcedure then
begin
AddToListView(lCodeTool, lNode); AddToListView(lCodeTool, lNode);
end;
lNode := lNode.NextBrother; lNode := lNode.NextBrother;
end; end;
end; { if } end; { if }
finally finally
FilterMethods.InvalidateFilter;
if LV.Items.Count > 0 then if LV.Items.Count > 0 then
begin begin
LV.Selected := LV.Items[0]; LV.Selected := LV.Items[0];
LV.ItemFocused := LV.Items[0]; LV.ItemFocused := LV.Items[0];
end; end;
LV.EndUpdate;
end; end;
end; end;
procedure TProcedureListForm.PopulateObjectsCombo; procedure TProcedureListForm.PopulateObjectsCombo;
var var
lSrcEditor: TSourceEditorInterface; lSrcEditor: TSourceEditorInterface;
@ -411,26 +369,27 @@ begin
Exit; //==> Exit; //==>
{ copy the tree } { copy the tree }
if Assigned(lCodeTool.Tree) then { Find the starting point }
lNode := lCodeTool.FindImplementationNode;
if lNode = nil then
begin begin
{ Find the starting point } { fall back - guess we are working with a program unit }
lNode := lCodeTool.FindImplementationNode; lNode := lCodeTool.Tree.Root;
if lNode = nil then end;
{ populate the Combobox here! }
lNode := lNode.FirstChild;
while lNode <> nil do
begin
if lNode.Desc = ctnProcedure then
begin begin
{ fall back - guess we are working with a program unit } lNodeText := lCodeTool.ExtractClassNameOfProcNode(lNode);
lNode := lCodeTool.Tree.Root; if lNodeText <> '' then
end;
{ populate the Combobox here! }
lNode := lNode.FirstChild;
while lNode <> nil do
begin
if lNode.Desc = ctnProcedure then
begin begin
lNodeText := lCodeTool.ExtractClassNameOfProcNode(lNode); DebugLn(['TProcedureListForm.PopulateObjectsCombo: Adding "', lNodeText, '" to combobox items.']);
cbObjects.Items.Add(lNodeText); cbObjects.Items.Add(lNodeText);
end; end;
lNode := lNode.NextBrother;
end; end;
lNode := lNode.NextBrother;
end; end;
cbObjects.Sorted := true; cbObjects.Sorted := true;
cbObjects.Sorted := false; cbObjects.Sorted := false;
@ -443,183 +402,35 @@ begin
end; end;
end; end;
procedure TProcedureListForm.AddToListView(pCodeTool: TCodeTool; pNode: TCodeTreeNode);
var
lItem: TListItem;
lNodeText: string;
lType: string;
lCaret: TCodeXYPosition;
FSearchAll: boolean;
begin
FSearchAll := cbObjects.Text = lisPListAll;
lNodeText := pCodeTool.ExtractProcHead(pNode,
[phpWithoutClassKeyword, phpWithoutParamList, phpWithoutBrackets,
phpWithoutSemicolon, phpWithoutClassName]);
{ Must we add this pNode or not? }
if not PassFilter(FSearchAll, lNodeText, edMethods.Text, pCodeTool, pNode) then
Exit; //==>
{ Add new list item }
lItem := LV.Items.Add;
{ procedure name }
lNodeText := pCodeTool.ExtractProcHead(pNode,
[phpWithoutParamList, phpWithoutBrackets, phpWithoutSemicolon]);
lItem.SubItems.Add(lNodeText);
{ type }
lNodeText := pCodeTool.ExtractProcHead(pNode,
[phpWithStart, phpWithoutParamList, phpWithoutBrackets, phpWithoutSemicolon]);
if Pos('procedure', lNodeText) > 0 then
lType := 'Procedure'
else
lType := 'Function';
lItem.SubItems.Add(lType);
{ line number }
if pCodeTool.CleanPosToCaret(pNode.StartPos, lCaret) then
lItem.SubItems.Add(IntToStr(lCaret.Y));
{ start pos - used by JumpToSelected() }
lItem.SubItems.Add(IntToStr(pNode.StartPos));
{ full procedure name used in statusbar }
lNodeText := pCodeTool.ExtractProcHead(pNode,
[phpWithStart,phpWithVarModifiers,
phpWithParameterNames,phpWithDefaultValues,phpWithResultType,
phpWithOfObject,phpWithCallingSpecs,phpWithProcModifiers]);
lItem.SubItems.Add(lNodeText);
end;
{ Do we pass all the filter tests to continue? }
function TProcedureListForm.PassFilter(pSearchAll: boolean;
pProcName, pSearchStr: string; pCodeTool: TCodeTool; pNode: TCodeTreeNode
): boolean;
var
lClass: string;
function ClassMatches: boolean;
begin
{ lets filter by class selection. }
lClass := pCodeTool.ExtractClassNameOfProcNode(pNode);
if cbObjects.Text = lisPListNone then
Result := lClass = ''
else
Result := lClass = cbObjects.Text;
end;
begin
Result := False;
if (Length(pSearchStr) = 0) then // seach string is empty
begin
if pSearchAll then
Result := True
else
Result := ClassMatches;
end
else if not pSearchAll and tbFilterStart.Down
and SameText(pSearchStr, Copy(pProcName, 1, Length(pSearchStr))) then
Result := True
else if not pSearchAll and tbFilterAny.Down and ClassMatches
and FilterFits(pSearchStr, pProcName) then
Result := True
else if pSearchAll and FilterFits(pSearchStr, pProcName) then
Result := True;
end;
procedure TProcedureListForm.FormKeyPress(Sender: TObject; var Key: char); procedure TProcedureListForm.FormKeyPress(Sender: TObject; var Key: char);
begin begin
if Key = #27 then // Escape key if Key = #27 then // Escape key
begin begin
self.ModalResult := mrCancel; Close;
end; end;
end; end;
procedure TProcedureListForm.cbObjectsChange(Sender: TObject);
procedure TProcedureListForm.FormCreate(Sender: TObject);
begin begin
if SourceEditorManagerIntf.ActiveEditor = nil then // ToDo: populate based on the selected item
begin PopulateListview;
//SetupGUI makes the dialog look as it should, and is clears the listview
//thus preventing a crash when clicking on the LV
SetupGUI;
Exit; //==>
end;
FMainFilename := SourceEditorManagerIntf.ActiveEditor.Filename;
Caption := Caption + ExtractFileName(FMainFilename);
SetupGUI;
PopulateObjectsCombo;
PopulateListView;
StatusBar.Panels[0].Text := self.MainFilename;
end; end;
procedure TProcedureListForm.edMethodsKeyPress(Sender: TObject; var Key: char); procedure TProcedureListForm.edMethodsKeyPress(Sender: TObject; var Key: char);
begin begin
case Key of case Key of
#13: #13:
begin begin
JumpToSelection;
Key := #0; Key := #0;
JumpToSelection;
end; end;
#27: #27:
begin begin
self.ModalResult := mrCancel;
Key := #0; Key := #0;
Close;
end; end;
end; end;
end; end;
procedure TProcedureListForm.edMethodsChange(Sender: TObject);
begin
PopulateListview;
end;
procedure TProcedureListForm.cbObjectsChange(Sender: TObject);
begin
PopulateListview;
end;
procedure TProcedureListForm.edMethodsKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if LV.Items.Count = 0 then
Exit;
if Key = VK_Down then
begin
if (LV.Items.IndexOf(LV.ItemFocused) + 1) < LV.Items.Count then
LV.ItemFocused := LV.Items[(LV.Items.IndexOf(LV.ItemFocused) + 1)];
end
else if Key = VK_Up then
begin
if (LV.Items.IndexOf(LV.ItemFocused) - 1) >= 0 then
LV.ItemFocused := LV.Items[(LV.Items.IndexOf(LV.ItemFocused) - 1)];
end
else if Key = VK_Home then
begin
LV.ItemFocused := LV.Items[0];
end
else if Key = VK_End then
begin
LV.ItemFocused := LV.Items[LV.Items.Count - 1];
end;
if LV.ItemFocused<>nil then
begin
LV.Selected := LV.ItemFocused;
if Assigned(LV.Selected) then
LV.Selected.MakeVisible(True);
end;
end;
end. end.