IDE: Add buttons into SearchResultsView window to close tabs. Issue #36384, patch from BrunoK.

git-svn-id: trunk@62364 -
This commit is contained in:
juha 2019-12-09 17:42:11 +00:00
parent 04b39226b6
commit 2a2559a1fd
19 changed files with 360 additions and 67 deletions

12
.gitattributes vendored
View File

@ -7751,6 +7751,18 @@ images/actions/restore_default_200.png -text svneol=unset#image/png
images/actions/restore_defaults.png -text svneol=unset#image/png
images/actions/restore_defaults_150.png -text svneol=unset#image/png
images/actions/restore_defaults_200.png -text svneol=unset#image/png
images/actions/tab_close_All.png -text svneol=unset#image/png
images/actions/tab_close_All_150.png -text svneol=unset#image/png
images/actions/tab_close_All_200.png -text svneol=unset#image/png
images/actions/tab_close_L.png -text svneol=unset#image/png
images/actions/tab_close_LR.png -text svneol=unset#image/png
images/actions/tab_close_LR_150.png -text svneol=unset#image/png
images/actions/tab_close_LR_200.png -text svneol=unset#image/png
images/actions/tab_close_L_150.png -text svneol=unset#image/png
images/actions/tab_close_L_200.png -text svneol=unset#image/png
images/actions/tab_close_R.png -text svneol=unset#image/png
images/actions/tab_close_R_150.png -text svneol=unset#image/png
images/actions/tab_close_R_200.png -text svneol=unset#image/png
images/bookmark.res -text
images/bookmark.sh svneol=native#text/plain
images/bookmark_images.bat svneol=native#text/plain

View File

@ -1042,7 +1042,7 @@ resourcestring
lisTheOutputDirectoryIsMissing = 'The output directory "%s" is missing.';
lisCreateIt = 'Create it';
lisInvalidFileName = 'Invalid file name';
lisTheTargetFileNameIsADirectory = 'The target file name is a directory.';
lisTheTargetFileNameIsADirectory = '\"%s\"\nThe target file name is a directory.';
lisNotAValidFppkgPrefix ='Free Pascal compiler not found at the given prefix.';
lisIncorrectFppkgConfiguration = 'there is a problem with the Fppkg configuration. (%s)';
lisFppkgCompilerProblem = 'there is a problem with the Free Pascal compiler executable, ';
@ -5481,6 +5481,10 @@ resourcestring
rsStartANewSearch = 'Start a new search';
rsCloseCurrentPage = 'Close current page';
rsFilterTheListWithString = 'Filter the lines in list with a string';
rsCloseLeft = 'Close tab(s) on the left';
rsCloseRight = 'Close tab(s) on the right';
rsCloseOthers = 'Close other tab(s)';
rsCloseAll = 'Close all tabs';
// Application Bundle
lisErrorLoadingFrom = 'Error loading %s from%s%s%s%s';

View File

@ -7,78 +7,139 @@ object SearchResultsView: TSearchResultsView
Caption = 'SearchResultsView'
ClientHeight = 273
ClientWidth = 799
Constraints.MinWidth = 400
KeyPreview = True
OnClose = FormClose
OnCreate = Form1Create
OnKeyDown = FormKeyDown
LCLVersion = '1.9.0.0'
LCLVersion = '2.1.0.0'
object ResultsNoteBook: TPageControl
AnchorSideTop.Control = ToolBar
AnchorSideTop.Side = asrBottom
Left = 0
Height = 251
Top = 22
Width = 799
Anchors = [akTop, akLeft, akRight, akBottom]
Height = 274
Top = 26
Width = 896
Align = alClient
MultiLine = True
TabOrder = 1
TabOrder = 0
OnChange = ResultsNoteBookPageChanged
OnChanging = ResultsNoteBookChanging
OnCloseTabClicked = ResultsNoteBookClosetabclicked
OnMouseDown = ResultsNoteBookMouseDown
OnResize = ResultsNoteBookResize
Options = [nboShowCloseButtons, nboMultiLine]
end
object ToolBar: TToolBar
object ControlBar1: TPanel
Left = 0
Height = 22
Height = 26
Top = 0
Width = 55
Align = alNone
AutoSize = True
EdgeBorders = []
TabOrder = 2
object SearchAgainButton: TToolButton
Left = 1
Top = 0
Caption = 'SearchAgainButton'
OnClick = SearchAgainButtonClick
end
object ClosePageButton: TToolButton
Left = 24
Top = 0
Caption = 'ClosePageButton'
OnClick = ClosePageButtonClick
end
object ToolButton3: TToolButton
Left = 47
Width = 896
Align = alTop
BevelOuter = bvNone
ClientHeight = 26
ClientWidth = 896
TabOrder = 1
TabStop = True
object ToolBar: TToolBar
Left = 3
Height = 22
Top = 0
Caption = 'ToolButton3'
Style = tbsSeparator
Top = 2
Width = 47
Align = alNone
Anchors = [akTop, akLeft, akBottom]
AutoSize = True
EdgeInner = esNone
EdgeOuter = esNone
TabOrder = 0
object SearchAgainButton: TToolButton
Left = 1
Top = 0
AutoSize = True
Caption = 'SearchAgainButton'
ImageIndex = 0
OnClick = SearchAgainButtonClick
end
object ClosePageButton: TToolButton
Left = 24
Top = 0
Caption = 'ClosePageButton'
ImageIndex = 1
OnClick = ClosePageButtonClick
end
end
object SearchInListEdit: TTreeFilterEdit
Left = 53
Height = 23
Top = 2
Width = 716
ButtonWidth = 23
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Left = 2
BorderSpacing.Bottom = 1
BorderSpacing.Around = 2
AutoSize = False
NumGlyphs = 1
MaxLength = 0
TabOrder = 1
OnChange = SearchInListChange
end
object CloseTabs: TToolBar
Left = 774
Height = 22
Top = 3
Width = 118
Align = alNone
Anchors = [akTop, akRight, akBottom]
BorderSpacing.Around = 2
EdgeBorders = []
EdgeInner = esNone
EdgeOuter = esNone
Indent = 2
TabOrder = 2
Wrapable = False
object tbbCloseLeft: TToolButton
AnchorSideRight.Control = ToolButton1
Left = 2
Top = 0
Action = actCloseLeft
end
object tbbCloseRight: TToolButton
Left = 64
Top = 0
Action = actCloseRight
end
object tbbCloseOthers: TToolButton
Left = 33
Top = 0
Action = actCloseOthers
end
object ToolButton1: TToolButton
Left = 25
Height = 22
Top = 0
Style = tbsSeparator
end
object ToolButton3: TToolButton
Left = 87
Height = 22
Top = 0
Style = tbsSeparator
end
object tbbCloseAll: TToolButton
Left = 95
Top = 0
Action = actCloseAll
end
object ToolButton2: TToolButton
Left = 56
Height = 22
Top = 0
Caption = 'ToolButton2'
Style = tbsSeparator
end
end
end
object SearchInListEdit: TTreeFilterEdit
AnchorSideLeft.Control = ToolBar
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = ToolBar
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 61
Height = 23
Top = 0
Width = 738
ButtonWidth = 23
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Left = 6
NumGlyphs = 1
MaxLength = 0
TabOrder = 0
OnChange = SearchInListChange
end
object popList: TPopupMenu
Left = 190
Top = 133
left = 190
top = 133
object mniCopyItem: TMenuItem
Caption = 'Copy Item'
OnClick = mniCopyItemClick
@ -104,9 +165,10 @@ object SearchResultsView: TSearchResultsView
end
end
object ActionList: TActionList
Left = 93
Top = 133
left = 93
top = 133
object actClosePage: TAction
ImageIndex = 1
OnExecute = ClosePageButtonClick
ShortCut = 16499
end
@ -118,5 +180,22 @@ object SearchResultsView: TSearchResultsView
OnExecute = actPrevPageExecute
ShortCut = 24585
end
object actCloseLeft: TAction
ImageIndex = 5
OnExecute = tbbCloseLeftClick
end
object actCloseOthers: TAction
ImageIndex = 6
OnExecute = tbbCloseOthersClick
end
object actCloseRight: TAction
ImageIndex = 7
OnExecute = tbbCloseRightClick
end
object actCloseAll: TAction
ImageIndex = 8
OnExecute = tbbCloseAllClick
ShortCut = 24691
end
end
end

View File

@ -40,7 +40,7 @@ uses
Classes, SysUtils, strutils, Laz_AVL_Tree,
// LCL
LCLProc, LCLType, LCLIntf, Forms, Controls, Graphics, ComCtrls, Menus, Clipbrd,
ActnList,
ActnList, ExtCtrls,
// LazControls
TreeFilterEdit,
// LazUtils
@ -53,7 +53,7 @@ uses
type
{ TLazSearchMatchPos }
TLazSearchMatchPos = class(TObject)
private
FFileEndPos: TPoint;
@ -131,29 +131,47 @@ type
function ItemsAsStrings: TStrings;
end;
{ TSearchResultsView }
TSearchResultsView = class(TForm)
actClosePage: TAction;
actCloseLeft: TAction;
actCloseOthers: TAction;
actCloseRight: TAction;
actCloseAll: TAction;
actNextPage: TAction;
actPrevPage: TAction;
ActionList: TActionList;
ClosePageButton1: TToolButton;
ControlBar1: TPanel;
MenuItem1: TMenuItem;
mniCollapseAll: TMenuItem;
mniExpandAll: TMenuItem;
mniCopySelected: TMenuItem;
mniCopyAll: TMenuItem;
mniCopyItem: TMenuItem;
pnlToolBars: TPanel;
popList: TPopupMenu;
ResultsNoteBook: TPageControl;
tbbCloseLeft: TToolButton;
tbbCloseOthers: TToolButton;
tbbCloseRight: TToolButton;
ToolBar: TToolBar;
SearchAgainButton: TToolButton;
ToolButton3: TToolButton;
CloseTabs: TToolBar;
ToolButton1: TToolButton;
ClosePageButton: TToolButton;
SearchInListEdit: TTreeFilterEdit;
ToolButton2: TToolButton;
ToolButton3: TToolButton;
tbbCloseAll: TToolButton;
procedure actNextPageExecute(Sender: TObject);
procedure actPrevPageExecute(Sender: TObject);
procedure ResultsNoteBookResize(Sender: TObject);
procedure tbbCloseAllClick(Sender: TObject);
procedure tbbCloseLeftClick(Sender: TObject);
procedure tbbCloseOthersClick(Sender: TObject);
procedure tbbCloseRightClick(Sender: TObject);
procedure ClosePageButtonClick(Sender: TObject);
procedure Form1Create(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
@ -182,6 +200,9 @@ type
procedure SearchInListChange(Sender: TObject );
procedure TreeViewMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
type
TOnSide = (osLeft, osOthers, osRight); { Handling of multi tab closure }
private
FMaxItems: integer;
FFocusTreeViewInOnChange: Boolean;
@ -196,6 +217,9 @@ type
function GetItems(Index: integer): TStrings;
procedure SetMaxItems(const AValue: integer);
procedure UpdateToolbar;
function GetPagesOnActiveLine:TFPlist;
procedure ClosePageOnSides(aOnSide : TOnSide);
procedure UpdateCloseTabs(aState : boolean);
protected
procedure Loaded; override;
procedure ActivateControl(aWinControl: TWinControl);
@ -268,7 +292,7 @@ begin
Dest.ShownFilename := Src.ShownFilename;
Result := True;
end;
function GetTreeSelectedItemsAsText(ATreeView: TCustomTreeView): string;
var
sl: TStringList;
@ -285,6 +309,7 @@ begin
sl.Free;
end;
{ TSearchResultsView }
procedure TSearchResultsView.Form1Create(Sender: TObject);
@ -301,6 +326,12 @@ begin
SearchAgainButton.Hint:=rsStartANewSearch;
ClosePageButton.Hint := rsCloseCurrentPage;
SearchInListEdit.Hint:=rsFilterTheListWithString;
{ Close tabs buttons }
actCloseLeft.Hint:=rsCloseLeft;
actCloseRight.Hint:=rsCloseRight;
actCloseOthers.Hint:=rsCloseOthers;
actCloseAll.Hint:=rsCloseAll;
CloseCommand := IDECommandList.FindIDECommand(ecClose);
if CloseCommand <> nil then
begin
@ -325,6 +356,13 @@ begin
ClosePageButton.ImageIndex := IDEImages.LoadImage('menu_close');
ActionList.Images := IDEImages.Images_16;
actClosePage.ImageIndex := IDEImages.LoadImage('menu_close');
{ Close tabs buttons }
CloseTabs.Images := IDEImages.Images_16;
actCloseLeft.ImageIndex := IDEImages.LoadImage('tab_close_L');
actCloseOthers.ImageIndex := IDEImages.LoadImage('tab_close_LR');
actCloseRight.ImageIndex := IDEImages.LoadImage('tab_close_R');
actCloseAll.ImageIndex := IDEImages.LoadImage('tab_close_All');
UpdateCloseTabs(False);
end;
procedure TSearchResultsView.FormClose(Sender: TObject; var CloseAction: TCloseAction);
@ -345,14 +383,14 @@ begin
end;
end;
procedure TSearchResultsView.FormKeyDown(Sender: TObject; var Key: Word;
procedure TSearchResultsView.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key = VK_ESCAPE) then
begin
Key := VK_UNKNOWN;
Close;
end;
end;
end;
procedure TSearchResultsView.mniCopyAllClick(Sender: TObject);
@ -422,11 +460,79 @@ end;
procedure TSearchResultsView.actNextPageExecute(Sender: TObject);
begin
ResultsNoteBook.SelectNextPage(True);
UpdateCloseTabs(True);
end;
procedure TSearchResultsView.actPrevPageExecute(Sender: TObject);
begin
ResultsNoteBook.SelectNextPage(False);
UpdateCloseTabs(True);
end;
procedure TSearchResultsView.ResultsNoteBookResize(Sender: TObject);
begin
UpdateCloseTabs(ResultsNoteBook.PageCount>0);
end;
{ Handling of tabs closure. Only tabs on pages at the level of active page in
multiline ResultsNoteBook will be closed by Left / Others and Right }
procedure TSearchResultsView.ClosePageOnSides(aOnSide: TOnSide);
var
lvPageList: TFPList = nil;
lCurTabSheet: TTabSheet;
ix: integer;
lTabSheet: TTabSheet;
lNeedsRefresh : boolean = false;
lCurTV:TLazSearchResultTV;
begin
lvPageList := GetPagesOnActiveLine;
with ResultsNoteBook do begin
lCurTabSheet := ActivePage;
if aOnSide = osLeft then
ix := lvPageList.IndexOf(lCurTabSheet)-1
else
ix := lvPageList.Count - 1;
while ix >= 0 do begin
lTabSheet := TTabSheet(lvPageList[ix]);
if lTabSheet = lCurTabSheet then begin
if aOnSide = osRight then
break;
end
else begin
ClosePage(lTabSheet.TabIndex);
lNeedsRefresh := True;
end;
Dec(ix);
end;
end;
lvPageList.Free;
if lNeedsRefresh then begin { ~bk force realign alClient }
lCurTV := GetTreeView(ResultsNoteBook.PageIndex);
if assigned(lCurTV) then
lCurTV.Height:=lCurTV.Height+1;
end;
end;
procedure TSearchResultsView.tbbCloseLeftClick(Sender: TObject);
begin
ClosePageOnSides(osLeft);
end;
procedure TSearchResultsView.tbbCloseOthersClick(Sender: TObject);
begin
ClosePageOnSides(osOthers);
end;
procedure TSearchResultsView.tbbCloseRightClick(Sender: TObject);
begin
ClosePageOnSides(osRight);
end;
procedure TSearchResultsView.tbbCloseAllClick(Sender: TObject);
begin
with ResultsNoteBook do
while PageCount>0 do
ClosePage(PageCount-1);
end;
{Keeps track of the Index of the Item the mouse is over, Sets ShowHint to true
@ -684,7 +790,9 @@ begin
ResultsNoteBook.Pages[PageIndex].Free;
end;
if ResultsNoteBook.PageCount = 0 then
Close;
Close
else
UpdateCloseTabs(True);
end;
{Sets the Items from the treeview on the currently selected page in the TNoteBook}
@ -737,6 +845,68 @@ begin
SearchAgainButton.Enabled := state;
ClosePageButton.Enabled := state;
SearchInListEdit.Enabled := state;
if state then
UpdateCloseTabs(state);
end;
// <wp> a good tip as usual
// https://forum.lazarus.freepascal.org/index.php/
// topic,39500.msg271287.html?PHPSESSID=t8cr445mhbtlnqm2jq0ckj2ul6#msg271287
{ Returns a list of all pages on the same line of Tabs as the ActivaPage }
function TSearchResultsView.GetPagesOnActiveLine: TFPlist;
var
lRect: TRect;
lActiveMidX: integer;
lActiveMidY: integer;
ix: integer;
begin
Result := TFPList.Create;
with ResultsNoteBook do begin
if ActivePage = Nil then Exit;
lRect := TabRect(ActivePage.TabIndex);
lActiveMidX := (lRect.Right - lRect.Left) div 2;
lActiveMidY := (lRect.Bottom - lRect.Top) div 2;
// Some widgetsets returned a negative value from Bottom-Top calculation
// although they might be fixed now.
if lActiveMidY < 0 then begin
DebugLn(['TSearchResultsView.GetPagesOnActiveLine: TabRect Bottom-Top calculation'+
' for ActivePage returned a negative value "', lActiveMidY, '".']);
lActiveMidY := -lActiveMidY;
end;
//DebugLn(['Width=',Width, ' MidX=',lActiveMidX, ' MidY=',lActiveMidY]);
//DebugLn(['Rect(TabIndex)=[',dbgs(lRect), ']']);
for ix := 0 to PageCount - 1 do begin
lRect := TabRect(ix);
//DebugLn(['Rect=[',dbgs(lRect), ']']);
if (lRect.Top < lActiveMidY) and (lRect.Bottom > lActiveMidY)
and (lRect.Right > lActiveMidX) and (lRect.Left < Width - lActiveMidX) then
Result.Add(Pages[ix]);
end;
end;
end;
procedure TSearchResultsView.UpdateCloseTabs(aState: boolean);
var
lPageList: TFPlist = nil;
lActiveIx : integer = -1;
begin
if aState and (ResultsNoteBook.PageCount>0) then begin
lPageList := GetPagesOnActiveLine;
if lPageList.Count>0 then
repeat
inc(lActiveIx);
if lPageList[lActiveIx]=Pointer(ResultsNoteBook.ActivePage) then
Break;
until lActiveIx>=lPageList.Count -1
else
FreeAndNil(lPageList);
end;
aState := aState and Assigned(lPageList);
actCloseLeft.Enabled := aState and (lActiveIx>0);
actCloseOthers.Enabled:= aState and (lPageList.Count>1);
actCloseRight.Enabled := aState and (lActiveIx<lPageList.Count-1);
actCloseAll.Enabled := aState;
lPageList.Free;
end;
procedure TSearchResultsView.ResultsNoteBookClosetabclicked(Sender: TObject);
@ -769,7 +939,7 @@ begin
Key:=VK_UNKNOWN;
if Assigned(FOnSelectionChanged) then
FOnSelectionChanged(Self);
end;
end;
end;
{ Add Result will create a tab in the Results view window with an new

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

View File

@ -106,6 +106,18 @@ actions/restore_default_200.png
actions/restore_defaults.png
actions/restore_defaults_150.png
actions/restore_defaults_200.png
actions/tab_close_All.png
actions/tab_close_All_150.png
actions/tab_close_All_200.png
actions/tab_close_L.png
actions/tab_close_L_150.png
actions/tab_close_L_200.png
actions/tab_close_LR.png
actions/tab_close_LR_150.png
actions/tab_close_LR_200.png
actions/tab_close_R.png
actions/tab_close_R_150.png
actions/tab_close_R_200.png
codecompletion/cc_class.png
codecompletion/cc_class_150.png
codecompletion/cc_class_200.png

View File

@ -20878,9 +20878,25 @@ msgstr "&Construction :"
msgid "Character set:"
msgstr "Jeu de caractères :"
#: lazarusidestrconsts.rscloseall
msgid "Close all tabs"
msgstr "Fermer tous les onglets"
#: lazarusidestrconsts.rsclosecurrentpage
msgid "Close current page"
msgstr "Fermer la page en cours"
msgstr "Fermer l'onglet actif"
#: lazarusidestrconsts.rscloseleft
msgid "Close tab(s) on the left"
msgstr "Fermer le(s) onglet(s) de gauche"
#: lazarusidestrconsts.rscloseothers
msgid "Close other tab(s)"
msgstr "Fermer tous les autre(s) onglet(s)"
#: lazarusidestrconsts.rscloseright
msgid "Close tab(s) on the right"
msgstr "Fermer le(s) onglet(s) de droite"
#: lazarusidestrconsts.rsconditionaldefines
msgid "Conditional defines"