| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- unit IDE.MainForm.NavigationHelper;
- {
- Inno Setup
- Copyright (C) 1997-2025 Jordan Russell
- Portions by Martijn Laan
- For conditions of distribution and use, see LICENSE.TXT.
- Compiler form - Navigation helper which has the UAH helper as ancestor
- Not used by MainForm: it uses IDE.MainForm.FinalHelper instead
- }
- interface
- uses
- Messages,
- Menus,
- IDE.MainForm, IDE.MainForm.UAHHelper,
- IDE.IDEScintEdit;
- type
- TMainFormNavigationHelper = class helper(TMainFormUAHHelper) for TMainForm
- procedure RemoveMemoFromNavigation(const AMemo: TIDEScintEdit);
- procedure RemoveMemoBadLinesFromNavigation(const AMemo: TIDEScintEdit);
- procedure UpdateNavigationButtons;
- procedure NavigateBack;
- procedure NavigateForward;
- procedure HandleNavigationAppCommand(var Message: TMessage);
- procedure UpdateNavigationMenu(const Menu: TMenuItem);
- procedure UpdateBackNavigationStack;
- { Private }
- procedure _NavigationMenuItemClick(Sender: TObject);
- end;
- implementation
- uses
- Windows,
- SysUtils, TypInfo, ComCtrls,
- IDE.HelperFunc, IDE.ScintStylerInnoSetup;
- procedure TMainFormNavigationHelper.RemoveMemoFromNavigation(const AMemo: TIDEScintEdit);
- begin
- if FNavStacks.RemoveMemo(AMemo) then
- UpdateNavigationButtons;
- if FCurrentNavItem.Memo = AMemo then
- FCurrentNavItem.Invalidate;
- end;
- procedure TMainFormNavigationHelper.RemoveMemoBadLinesFromNavigation(const AMemo: TIDEScintEdit);
- begin
- if FNavStacks.RemoveMemoBadLines(AMemo) then
- UpdateNavigationButtons;
- { We do NOT update FCurrentNav here so it might point to a line that's
- deleted until next UpdateCaretPosPanelAndBackStack by UpdateMemoUI }
- end;
- procedure TMainFormNavigationHelper.UpdateNavigationButtons;
- begin
- ForwardNavButton.Enabled := FNavStacks.Forward.Count > 0;
- BackNavButton.Enabled := (FNavStacks.Back.Count > 0) or
- ForwardNavButton.Enabled; { for the dropdown }
- end;
- procedure TMainFormNavigationHelper.NavigateBack;
- begin
- { Delphi does not support BTNS_WHOLEDROPDOWN so we can't be like VS which
- can have a disabled back nav button with an enabled dropdown. To avoid
- always showing two dropdowns we keep the back button enabled when we need
- the dropdown. So we need to check for this. }
- if FNavStacks.Back.Count = 0 then begin
- Beep;
- Exit;
- end;
- FNavStacks.Forward.Add(FCurrentNavItem);
- var NewNavItem := FNavStacks.Back.ExtractAt(FNavStacks.Back.Count-1);
- UpdateNavigationButtons;
- FCurrentNavItem := NewNavItem; { Must be done *before* moving }
- MoveCaretAndActivateMemo(NewNavItem.Memo,
- NewNavItem.Memo.GetPositionFromLineColumn(NewNavItem.Line, NewNavItem.Column), False, True, NewNavItem.VirtualSpace);
- end;
- procedure TMainFormNavigationHelper.NavigateForward;
- begin
- FNavStacks.Back.Add(FCurrentNavItem);
- var NewNavItem := FNavStacks.Forward.ExtractAt(FNavStacks.Forward.Count-1);
- UpdateNavigationButtons;
- FCurrentNavItem := NewNavItem; { Must be done *before* moving }
- MoveCaretAndActivateMemo(NewNavItem.Memo,
- NewNavItem.Memo.GetPositionFromLineColumn(NewNavItem.Line, NewNavItem.Column), False, True, NewNavItem.VirtualSpace);
- end;
- procedure TMainFormNavigationHelper.HandleNavigationAppCommand(var Message: TMessage);
- begin
- var Command := GET_APPCOMMAND_LPARAM(Message.LParam);
- if Command = APPCOMMAND_BROWSER_BACKWARD then begin
- if BackNavButton.Enabled then
- BackNavButton.Click;
- Message.Result := 1;
- end else if Command = APPCOMMAND_BROWSER_FORWARD then begin
- if ForwardNavButton.Enabled then
- ForwardNavButton.Click;
- Message.Result := 1;
- end;
- end;
- procedure TMainFormNavigationHelper._NavigationMenuItemClick(Sender: TObject);
- begin
- var MenuItem := Sender as TMenuItem;
- var Clicks := Abs(MenuItem.Tag);
- if Clicks > 0 then begin
- var ButtonToClick: TToolButton;
- if MenuItem.Tag > 0 then
- ButtonToClick := ForwardNavButton
- else
- ButtonToClick := BackNavButton;
- while Clicks > 0 do begin
- if not ButtonToClick.Enabled then
- raise Exception.Create('not ButtonToClick.Enabled');
- ButtonToClick.Click;
- Dec(Clicks);
- end;
- end;
- end;
- procedure TMainFormNavigationHelper.UpdateNavigationMenu(const Menu: TMenuItem);
- procedure AddNavItemToMenu(const NavItem: TIDEScintEditNavItem; const Checked: Boolean;
- const ClicksNeeded: Integer; const Menu: TMenuItem);
- begin
- if NavItem.Line >= NavItem.Memo.Lines.Count then
- raise Exception.Create('NavItem.Line >= NavItem.Memo.Lines.Count');
- var LineInfo := NavItem.Memo.Lines[NavItem.Line];
- if LineInfo.Trim = '' then
- LineInfo := Format('Line %d', [NavItem.Line+1]);
- var Caption: String;
- if MemosTabSet.Visible then
- Caption := Format('%s: %s', [MemosTabSet.Tabs[MemoToTabIndex(NavItem.Memo)], LineInfo])
- else
- Caption := LineInfo;
- var MenuItem := TMenuItem.Create(Menu);
- MenuItem.Caption := DoubleAmp(Caption);
- MenuItem.Checked := Checked;
- MenuItem.RadioItem := True;
- MenuItem.Tag := ClicksNeeded;
- MenuItem.OnClick := _NavigationMenuItemClick;
- Menu.Add(MenuItem);
- end;
- begin
- Menu.Clear;
- { Setup dropdown. The result should end up being just like Visual Studio 2022
- which means from top to bottom:
- - Furthest (=oldest) forward item
- - ...
- - Closest (=next) forward item
- - Current position in the active memo, checked
- - Closest (=next) back item
- - ...
- - Furthest (=oldest) back item
- The Tag parameter should be set to the amount of clicks needed to get to
- the item, positive for forward and negative for back }
- for var I := 0 to FNavStacks.Forward.Count-1 do
- AddNavItemToMenu(FNavStacks.Forward[I], False, FNavStacks.Forward.Count-I, Menu);
- AddNavItemToMenu(FCurrentNavItem, True, 0, Menu);
- for var I := FNavStacks.Back.Count-1 downto 0 do
- AddNavItemToMenu(FNavStacks.Back[I], False, -(FNavStacks.Back.Count-I), Menu);
- end;
- procedure TMainFormNavigationHelper.UpdateBackNavigationStack;
- begin
- { Update NavStacks.Back if needed and remember new position }
- var NewNavItem := TIDEScintEditNavItem.Create(FActiveMemo); { This is a record so no need to free }
- if FCurrentNavItem.Valid and FNavStacks.AddNewBackForJump(FCurrentNavItem, NewNavItem) then
- UpdateNavigationButtons;
- FCurrentNavItem := NewNavItem;
- end;
- end.
|