Skip to content

Commit a8def5b

Browse files
committed
Navigate visible history
1 parent e214742 commit a8def5b

19 files changed

+193
-19
lines changed

ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ public virtual object? Text {
126126
get { return null; }
127127
}
128128

129+
public virtual object? NavigationText
130+
{
131+
get { return Text; }
132+
}
133+
129134
public virtual object? Icon {
130135
get { return null; }
131136
}

ILSpy/AssemblyTree/AssemblyTreeModel.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -853,15 +853,24 @@ public void RefreshDecompiledView()
853853

854854
#endregion
855855

856-
public void NavigateHistory(bool forward)
856+
public void NavigateHistory(bool forward, NavigationState? toState = null)
857857
{
858858
try
859859
{
860-
TabPageModel tabPage = DockWorkspace.ActiveTabPage;
861-
var state = tabPage.GetState();
862-
if (state != null)
863-
history.UpdateCurrent(new NavigationState(tabPage, state));
864-
var newState = forward ? history.GoForward() : history.GoBack();
860+
TabPageModel tabPage = DockWorkspace.ActiveTabPage;
861+
var currentState = tabPage.GetState();
862+
if (currentState != null)
863+
history.UpdateCurrent(new NavigationState(tabPage, currentState));
864+
865+
NavigationState newState;
866+
do
867+
{
868+
newState = forward ? history.GoForward() : history.GoBack();
869+
} while (newState != null && toState != null && toState != newState);
870+
871+
if (newState == null)
872+
return;
873+
865874
navigatingToState = newState;
866875

867876
TabPageModel activeTabPage = newState.TabPage;
@@ -884,6 +893,8 @@ public void NavigateHistory(bool forward)
884893
}
885894
}
886895

896+
public NavigationState[] GetNavigateHistory(bool forward) => forward ? history.ForwardList : history.BackList;
897+
887898
public bool CanNavigateBack => history.CanNavigateBack;
888899

889900
public bool CanNavigateForward => history.CanNavigateForward;

ILSpy/Commands/BrowseBackCommand.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1717
// DEALINGS IN THE SOFTWARE.
1818

19+
using System.Collections;
1920
using System.Composition;
21+
using System.Linq;
2022
using System.Windows.Input;
2123

2224
using ICSharpCode.ILSpy.AssemblyTree;
@@ -26,7 +28,7 @@ namespace ICSharpCode.ILSpy
2628
{
2729
[ExportToolbarCommand(ToolTip = nameof(Resources.Back), ToolbarIcon = "Images/Back", ToolbarCategory = nameof(Resources.Navigation), ToolbarOrder = 0)]
2830
[Shared]
29-
sealed class BrowseBackCommand : CommandWrapper
31+
sealed class BrowseBackCommand : CommandWrapper, IProvideParameterList
3032
{
3133
readonly AssemblyTreeModel assemblyTreeModel;
3234

@@ -49,8 +51,15 @@ protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
4951
if (assemblyTreeModel.CanNavigateBack)
5052
{
5153
e.Handled = true;
52-
assemblyTreeModel.NavigateHistory(false);
54+
assemblyTreeModel.NavigateHistory(false, e.Parameter as NavigationState);
5355
}
5456
}
57+
58+
public IEnumerable ParameterList => assemblyTreeModel.GetNavigateHistory(false).Reverse();
59+
60+
public object GetParamaterText(object parameter)
61+
{
62+
return (parameter as NavigationState)?.NavigationText;
63+
}
5564
}
5665
}

ILSpy/Commands/BrowseForwardCommand.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
1717
// DEALINGS IN THE SOFTWARE.
1818

19+
using System.Collections;
1920
using System.Composition;
2021
using System.Windows.Input;
2122

@@ -26,7 +27,7 @@ namespace ICSharpCode.ILSpy
2627
{
2728
[ExportToolbarCommand(ToolTip = nameof(Resources.Forward), ToolbarIcon = "Images/Forward", ToolbarCategory = nameof(Resources.Navigation), ToolbarOrder = 1)]
2829
[Shared]
29-
sealed class BrowseForwardCommand : CommandWrapper
30+
sealed class BrowseForwardCommand : CommandWrapper, IProvideParameterList
3031
{
3132
private readonly AssemblyTreeModel assemblyTreeModel;
3233

@@ -49,9 +50,15 @@ protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
4950
if (assemblyTreeModel.CanNavigateForward)
5051
{
5152
e.Handled = true;
52-
assemblyTreeModel.NavigateHistory(true);
53+
assemblyTreeModel.NavigateHistory(true, e.Parameter as NavigationState);
5354
}
5455
}
5556

57+
public IEnumerable ParameterList => assemblyTreeModel.GetNavigateHistory(true);
58+
59+
public object GetParamaterText(object parameter)
60+
{
61+
return (parameter as NavigationState)?.NavigationText;
62+
}
5663
}
5764
}

ILSpy/Commands/SimpleCommand.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
// DEALINGS IN THE SOFTWARE.
1818

1919
using System;
20+
using System.Collections;
2021
using System.Windows.Data;
2122
using System.Windows.Input;
2223

@@ -41,4 +42,10 @@ public interface IProvideParameterBinding
4142
{
4243
Binding ParameterBinding { get; }
4344
}
45+
46+
public interface IProvideParameterList
47+
{
48+
IEnumerable ParameterList { get; }
49+
object GetParamaterText(object parameter);
50+
}
4451
}

ILSpy/Controls/MainToolBar.xaml.cs

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323
using System.Windows.Controls.Primitives;
2424
using System.Windows.Data;
2525
using System.Windows.Input;
26+
using System.Windows.Media;
2627
using System.Windows.Threading;
2728

2829
using ICSharpCode.ILSpy.Themes;
30+
using ICSharpCode.ILSpyX.TreeView;
2931

3032
using TomsToolbox.Composition;
3133

@@ -85,7 +87,8 @@ static void InitToolbar(ToolBar toolBar, IExportProvider exportProvider)
8587
}
8688
}
8789

88-
static Button CreateToolbarItem(IExport<ICommand, IToolbarCommandMetadata> commandExport)
90+
91+
static UIElement CreateToolbarItem(IExport<ICommand, IToolbarCommandMetadata> commandExport)
8992
{
9093
var command = commandExport.Value;
9194

@@ -108,9 +111,93 @@ static Button CreateToolbarItem(IExport<ICommand, IToolbarCommandMetadata> comma
108111
parameterBinding.ParameterBinding);
109112
}
110113

114+
if (command is IProvideParameterList parameterList)
115+
{
116+
toolbarItem.Margin = new Thickness(2, 0, 0, 0);
117+
118+
var dropDownPanel = new StackPanel { Orientation = Orientation.Horizontal };
119+
120+
var contextMenu = new ContextMenu {
121+
PlacementTarget = dropDownPanel,
122+
Tag = command
123+
};
124+
125+
ContextMenuService.SetPlacement(toolbarItem, PlacementMode.Bottom);
126+
toolbarItem.ContextMenu = contextMenu;
127+
toolbarItem.ContextMenuOpening += (_, _) =>
128+
PrepareParameterList(contextMenu);
129+
130+
var dropDownToggle = new ToggleButton {
131+
Style = ThemeManager.Current.CreateToolBarToggleButtonStyle(),
132+
Content = "▾",
133+
Padding = new Thickness(0),
134+
MinWidth = 0,
135+
Margin = new Thickness(0, 0, 2, 0)
136+
};
137+
138+
dropDownToggle.Checked += (_, _) => {
139+
PrepareParameterList(contextMenu);
140+
contextMenu.Placement = PlacementMode.Bottom;
141+
contextMenu.SetCurrentValue(ContextMenu.IsOpenProperty, true);
142+
};
143+
144+
BindingOperations.SetBinding(dropDownToggle, ToggleButton.IsCheckedProperty,
145+
new Binding(nameof(contextMenu.IsOpen)) { Source = contextMenu });
146+
147+
BindingOperations.SetBinding(dropDownToggle, IsEnabledProperty,
148+
new Binding(nameof(IsEnabled)) { Source = toolbarItem });
149+
150+
dropDownPanel.Children.Add(toolbarItem);
151+
dropDownPanel.Children.Add(dropDownToggle);
152+
return dropDownPanel;
153+
}
154+
111155
return toolbarItem;
112156
}
113157

158+
static void PrepareParameterList(ContextMenu menu)
159+
{
160+
const int maximumParameterListCount = 20;
161+
162+
var command = (ICommand)menu.Tag;
163+
var parameterList = (IProvideParameterList)command;
164+
165+
menu.Items.Clear();
166+
foreach (var parameter in parameterList.ParameterList)
167+
{
168+
MenuItem parameterItem = new MenuItem();
169+
parameterItem.Command = CommandWrapper.Unwrap(command);
170+
parameterItem.CommandParameter = parameter;
171+
parameterItem.CommandTarget = menu.PlacementTarget;
172+
parameterItem.InputGestureText = " ";
173+
174+
var headerPresenter = new ContentPresenter { RecognizesAccessKey = false };
175+
parameterItem.Header = headerPresenter;
176+
177+
var header = parameterList.GetParamaterText(parameter);
178+
switch (header)
179+
{
180+
case SharpTreeNode node:
181+
headerPresenter.Content = node.NavigationText;
182+
if (node.Icon is ImageSource icon)
183+
parameterItem.Icon = new Image {
184+
Width = 16,
185+
Height = 16,
186+
Source = icon
187+
};
188+
break;
189+
190+
default:
191+
headerPresenter.Content = header;
192+
break;
193+
}
194+
195+
menu.Items.Add(parameterItem);
196+
if (menu.Items.Count >= maximumParameterListCount)
197+
break;
198+
}
199+
}
200+
114201
void MainWindow_KeyDown(object sender, KeyEventArgs e)
115202
{
116203
if (e.Handled || e.KeyboardDevice.Modifiers != ModifierKeys.Alt || e.Key != Key.System)

ILSpy/Metadata/MetadataTreeNode.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public MetadataTreeNode(MetadataFile module, string title)
4545

4646
public override object Text => title;
4747

48+
public override object NavigationText => metadataFile.Name + " " + Text;
49+
4850
public override object Icon => Images.Metadata;
4951

5052
public override bool View(TabPageModel tabPage)

ILSpy/NavigationHistory.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ internal sealed class NavigationHistory<T>
3434
List<T> back = new List<T>();
3535
List<T> forward = new List<T>();
3636

37+
public T[] BackList => back.ToArray();
38+
public T[] ForwardList => forward.ToArray();
39+
3740
public bool CanNavigateBack {
3841
get { return back.Count > 0; }
3942
}

ILSpy/NavigationState.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System;
2020
using System.Collections.Generic;
2121
using System.Diagnostics;
22+
using System.Linq;
2223

2324
using ICSharpCode.ILSpy.TextView;
2425
using ICSharpCode.ILSpy.ViewModels;
@@ -62,5 +63,22 @@ public bool Equals(NavigationState other)
6263

6364
return this.ViewState.Equals(other.ViewState);
6465
}
66+
67+
public object NavigationText
68+
{
69+
get
70+
{
71+
if (this.treeNodes.Count == 1)
72+
return this.treeNodes.First();
73+
74+
if (this.treeNodes.Count > 0)
75+
return string.Join(", ", treeNodes.Select(tn => tn.NavigationText));
76+
77+
if (this.ViewState?.ViewedUri is Uri uri)
78+
return uri;
79+
80+
return ToString();
81+
}
82+
}
6583
}
6684
}

ILSpy/Themes/ThemeManager.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using System.Linq;
2525
using System.Windows;
2626
using System.Windows.Controls;
27+
using System.Windows.Controls.Primitives;
2728
using System.Windows.Media;
2829

2930
using ICSharpCode.AvalonEdit.Highlighting;
@@ -81,6 +82,11 @@ public Style CreateToolBarButtonStyle()
8182
return new Style(typeof(Button), (Style)Application.Current.FindResource(ToolBar.ButtonStyleKey));
8283
}
8384

85+
public Style CreateToolBarToggleButtonStyle()
86+
{
87+
return new Style(typeof(ToggleButton), (Style)Application.Current.FindResource(ToolBar.ToggleButtonStyleKey));
88+
}
89+
8490
public void ApplyHighlightingColors(IHighlightingDefinition highlightingDefinition)
8591
{
8692
// Make sure all color values are taken from the theme

0 commit comments

Comments
 (0)