IDE: Improve SearchResultView's close tabs logic. Issue #36384, patch from BrunoK.

git-svn-id: trunk@62381 -
This commit is contained in:
juha 2019-12-12 20:43:47 +00:00
parent 0bd01ab2ed
commit cd1e5b70a9
2 changed files with 121 additions and 94 deletions

View File

@ -1,12 +1,13 @@
object SearchResultsView: TSearchResultsView
Left = 344
Height = 273
Height = 275
Top = 327
Width = 799
Width = 722
BorderIcons = [biSystemMenu]
Caption = 'SearchResultsView'
ClientHeight = 273
ClientWidth = 799
ClientHeight = 275
ClientWidth = 722
Constraints.MinHeight = 100
Constraints.MinWidth = 400
KeyPreview = True
OnClose = FormClose
@ -15,9 +16,9 @@ object SearchResultsView: TSearchResultsView
LCLVersion = '2.1.0.0'
object ResultsNoteBook: TPageControl
Left = 0
Height = 274
Height = 249
Top = 26
Width = 896
Width = 722
Align = alClient
MultiLine = True
TabOrder = 0
@ -25,17 +26,17 @@ object SearchResultsView: TSearchResultsView
OnCloseTabClicked = ResultsNoteBookClosetabclicked
OnMouseDown = ResultsNoteBookMouseDown
OnResize = ResultsNoteBookResize
Options = [nboShowCloseButtons, nboMultiLine]
Options = [nboShowCloseButtons, nboMultiLine, nboDoChangeOnSetIndex]
end
object ControlBar1: TPanel
Left = 0
Height = 26
Top = 0
Width = 896
Width = 722
Align = alTop
BevelOuter = bvNone
ClientHeight = 26
ClientWidth = 896
ClientWidth = 722
TabOrder = 1
TabStop = True
object ToolBar: TToolBar
@ -69,7 +70,7 @@ object SearchResultsView: TSearchResultsView
Left = 53
Height = 23
Top = 2
Width = 716
Width = 542
ButtonWidth = 23
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Left = 2
@ -82,7 +83,7 @@ object SearchResultsView: TSearchResultsView
OnChange = SearchInListChange
end
object CloseTabs: TToolBar
Left = 774
Left = 600
Height = 22
Top = 3
Width = 118
@ -138,8 +139,8 @@ object SearchResultsView: TSearchResultsView
end
end
object popList: TPopupMenu
left = 190
top = 133
Left = 129
Top = 48
object mniCopyItem: TMenuItem
Caption = 'Copy Item'
OnClick = mniCopyItemClick
@ -165,8 +166,8 @@ object SearchResultsView: TSearchResultsView
end
end
object ActionList: TActionList
left = 93
top = 133
Left = 32
Top = 48
object actClosePage: TAction
ImageIndex = 1
OnExecute = ClosePageButtonClick

View File

@ -210,6 +210,7 @@ type
FWorkedSearchText: string;
FOnSelectionChanged: TNotifyEvent;
FMouseOverIndex: integer;
FClosingTabs: boolean;
function BeautifyPageName(const APageName: string): string;
function GetPageIndex(const APageName: string): integer;
function GetTreeView(APageIndex: integer): TLazSearchResultTV;
@ -217,9 +218,11 @@ type
function GetItems(Index: integer): TStrings;
procedure SetMaxItems(const AValue: integer);
procedure UpdateToolbar;
function GetPagesOnActiveLine:TFPlist;
function GetPagesOnActiveLine(aOnSide : TOnSide = osOthers):TFPlist;
procedure ClosePageOnSides(aOnSide : TOnSide);
procedure UpdateCloseTabs(aState : boolean);
procedure ClosePageBegin;
procedure ClosePageEnd;
procedure UpdateCloseButtons(aEnable : boolean);
protected
procedure Loaded; override;
procedure ActivateControl(aWinControl: TWinControl);
@ -309,7 +312,6 @@ begin
sl.Free;
end;
{ TSearchResultsView }
procedure TSearchResultsView.Form1Create(Sender: TObject);
@ -362,7 +364,7 @@ begin
actCloseOthers.ImageIndex := IDEImages.LoadImage('tab_close_LR');
actCloseRight.ImageIndex := IDEImages.LoadImage('tab_close_R');
actCloseAll.ImageIndex := IDEImages.LoadImage('tab_close_All');
UpdateCloseTabs(False);
UpdateCloseButtons(False);
end;
procedure TSearchResultsView.FormClose(Sender: TObject; var CloseAction: TCloseAction);
@ -460,18 +462,16 @@ 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);
UpdateCloseButtons(ResultsNoteBook.PageCount>0);
end;
{ Handling of tabs closure. Only tabs on pages at the level of active page in
@ -479,38 +479,45 @@ end;
procedure TSearchResultsView.ClosePageOnSides(aOnSide: TOnSide);
var
lvPageList: TFPList = nil;
lCurTabSheet: TTabSheet;
lCurTabSheet, lTabSheet: 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);
lvPageList := GetPagesOnActiveLine(aOnSide);
if lvPageList = Nil then Exit;
ClosePageBegin;
lCurTabSheet := ResultsNoteBook.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;
lvPageList.Free;
if lNeedsRefresh then begin { ~bk force realign alClient }
lCurTV := GetTreeView(ResultsNoteBook.PageIndex);
if assigned(lCurTV) then
lCurTV.Height:=lCurTV.Height+1;
end;
ClosePageEnd;
if lNeedsRefresh then { Force resizing of the active TabSheet }
lCurTabSheet.Height := lCurTabSheet.Height+1;
UpdateToolBar;
end;
procedure TSearchResultsView.ClosePageBegin;
begin
FClosingTabs := True;
end;
procedure TSearchResultsView.ClosePageEnd;
begin
FClosingTabs := False;
end;
procedure TSearchResultsView.tbbCloseLeftClick(Sender: TObject);
@ -538,13 +545,12 @@ end;
{Keeps track of the Index of the Item the mouse is over, Sets ShowHint to true
if the Item length is longer than the TreeView client width.}
procedure TSearchResultsView.LazTVMousemove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
X, Y: Integer);
var
Node: TTreeNode;
begin
if Sender is TLazSearchResultTV then
begin
with Sender as TLazSearchResultTV do
with TLazSearchResultTV(Sender) do
begin
Node := GetNodeAt(X, Y);
if Assigned(Node) then
@ -557,7 +563,6 @@ begin
else
ShowHint:= False;
end;//with
end;//
end;//LazTVMousemove
{Keep track of the mouse position over the treeview when the wheel is used}
@ -792,7 +797,7 @@ begin
if ResultsNoteBook.PageCount = 0 then
Close
else
UpdateCloseTabs(True);
UpdateCloseButtons(True);
end;
{Sets the Items from the treeview on the currently selected page in the TNoteBook}
@ -846,66 +851,87 @@ begin
ClosePageButton.Enabled := state;
SearchInListEdit.Enabled := state;
if state then
UpdateCloseTabs(state);
UpdateCloseButtons(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;
{ Returns a list of all pages (visible tabs) on the same line of Tabs as the ActivaPage }
function TSearchResultsView.GetPagesOnActiveLine(aOnSide: TOnSide {=osOthers}): TFPlist;
var
lRect: TRect;
lActiveMidX: integer;
lActiveMidY: integer;
ix: integer;
lActiveMidY, lActiveIndex, ix, hh: integer;
lActiveRect, lRect, lLastRect: TRect;
begin
Result := TFPList.Create;
Result := nil;
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
Result := TFPList.Create;
lActiveIndex := ResultsNoteBook.ActivePageIndex;
lActiveRect := TabRect(lActiveIndex);
hh := (lActiveRect.Bottom - lActiveRect.Top) div 2;
{ Some widgetsets returned a negative value from Bottom-Top calculation. }
if hh < 0 then begin // Do a sanity check.
DebugLn(['TSearchResultsView.GetPagesOnActiveLine: TabRect Bottom-Top calculation'+
' for ActivePage returned a negative value "', lActiveMidY, '".']);
lActiveMidY := -lActiveMidY;
' for ActivePage returned a negative value "', hh, '".']);
hh := -hh;
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
lActiveMidY := lActiveRect.Top + hh;
{ Search closable tabs left of current tab }
if aOnSide in [osLeft, osOthers] then begin
lLastRect := lActiveRect;
for ix := lActiveIndex-1 downto 0 do begin
lRect := TabRect(ix);
if (lRect.Top >= lActiveMidY) or (lRect.Bottom <= lActiveMidY)
or (lRect.Right > lLastRect.Left) then
break;
Result.Insert(0, Pages[ix]);
lLastRect := lRect;
end;
end;
{ Current tab }
Result.Add(Pages[lActiveIndex]);
{ Search closable tabs right of current tab }
if aOnSide in [osOthers, osRight] then begin
lLastRect := lActiveRect;
for ix := lActiveIndex+1 to PageCount-1 do begin
lRect := TabRect(ix);
if (lRect.Top >= lActiveMidY) or (lRect.Bottom <= lActiveMidY)
or (lRect.Left < lLastRect.Right) then
break;
Result.Add(Pages[ix]);
lLastRect := lRect;
end;
end;
end;
end;
procedure TSearchResultsView.UpdateCloseTabs(aState: boolean);
procedure TSearchResultsView.UpdateCloseButtons(aEnable: boolean);
var
lPageList: TFPlist = nil;
lActiveIx : integer = -1;
lActiveIx: integer = -1;
begin
if aState and (ResultsNoteBook.PageCount>0) then begin
if FClosingTabs then
exit;
Application.ProcessMessages; { UI must be up to date before searching candidate tabs }
if aEnable and (ResultsNoteBook.PageCount>0) then begin
lPageList := GetPagesOnActiveLine;
if lPageList.Count>0 then
if Assigned(lPageList) and (lPageList.Count>0) then
repeat
inc(lActiveIx);
if lPageList[lActiveIx]=Pointer(ResultsNoteBook.ActivePage) then
Break;
until lActiveIx>=lPageList.Count -1
else
FreeAndNil(lPageList);
break;
until lActiveIx>=lPageList.Count -1;
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;
aEnable := aEnable and Assigned(lPageList);
actCloseLeft.Enabled := aEnable and (lActiveIx>0);
if aEnable then begin
actCloseOthers.Enabled:= lPageList.Count>1;
actCloseRight.Enabled := lActiveIx<(lPageList.Count-1);
end
else begin
actCloseOthers.Enabled:= False;
actCloseRight.Enabled := False;
end;
actCloseAll.Enabled := aEnable;
lPageList.Free;
end;
@ -958,10 +984,10 @@ begin
Result:= nil;
if Assigned(ResultsNoteBook) then
begin
FFocusTreeViewInEndUpdate := not (Assigned(ResultsNoteBook.ActivePage)
and SearchInListEdit.IsParentOf(ResultsNoteBook.ActivePage));
with ResultsNoteBook do
begin
FFocusTreeViewInEndUpdate := not (Assigned(ActivePage)
and SearchInListEdit.IsParentOf(ActivePage));
FWorkedSearchText:=BeautifyPageName(ResultsName);
NewPage:= TCustomTabControl(ResultsNoteBook).Pages.Add(FWorkedSearchText);
PageIndex:= NewPage;