diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 90c83b900..dfb909610 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -94,6 +94,7 @@ + OpenFromGacDialog.xaml Code diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index 6688e44e7..7d1f59090 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -26,6 +26,14 @@ + + @@ -78,6 +86,13 @@ + + + @@ -115,7 +130,7 @@ + Text="{Binding FilterSettings.SearchTerm, UpdateSourceTrigger=PropertyChanged}" /> partial class MainWindow : Window { + NavigationHistory history = new NavigationHistory(); ILSpySettings spySettings; SessionSettings sessionSettings; AssemblyListManager assemblyListManager; @@ -134,11 +136,14 @@ namespace ICSharpCode.ILSpy void ShowAssemblyList(AssemblyList assemblyList) { + history.Clear(); this.assemblyList = assemblyList; + assemblyList.Assemblies.CollectionChanged += assemblyList_Assemblies_CollectionChanged; + assemblyListTreeNode = new AssemblyListTreeNode(assemblyList); assemblyListTreeNode.FilterSettings = sessionSettings.FilterSettings.Clone(); - assemblyListTreeNode.Select = SelectNode; + assemblyListTreeNode.Select = node => SelectNode(node); treeView.Root = assemblyListTreeNode; if (assemblyList.ListName == AssemblyListManager.DefaultListName) @@ -146,6 +151,13 @@ namespace ICSharpCode.ILSpy else this.Title = "ILSpy - " + assemblyList.ListName; } + + void assemblyList_Assemblies_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (e.OldItems != null) + foreach (AssemblyTreeNode node in e.OldItems) + history.RemoveAll(n => n.AncestorsAndSelf().Contains(node)); + } void LoadInitialAssemblies() { @@ -186,9 +198,13 @@ namespace ICSharpCode.ILSpy get { return assemblyList; } } - internal void SelectNode(SharpTreeNode obj) + #region Node Selection + internal void SelectNode(SharpTreeNode obj, bool recordNavigationInHistory = true) { if (obj != null) { + SharpTreeNode oldNode = treeView.SelectedItem as SharpTreeNode; + if (oldNode != null && recordNavigationInHistory) + history.Record(oldNode); // Set both the selection and focus to ensure that keyboard navigation works as expected. treeView.FocusNode(obj); treeView.SelectedItem = obj; @@ -232,6 +248,7 @@ namespace ICSharpCode.ILSpy path.Reverse(); return path.ToArray(); } + #endregion #region Debugging CFG #if DEBUG @@ -293,6 +310,7 @@ namespace ICSharpCode.ILSpy #endif #endregion + #region Open/Refresh void OpenCommandExecuted(object sender, ExecutedRoutedEventArgs e) { e.Handled = true; @@ -317,7 +335,7 @@ namespace ICSharpCode.ILSpy } } if (lastNode != null) - treeView.ScrollIntoView(lastNode); + treeView.FocusNode(lastNode); } void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e) @@ -328,6 +346,17 @@ namespace ICSharpCode.ILSpy SelectNode(FindNodeByPath(path, true)); } + void OpenFromGac_Click(object sender, RoutedEventArgs e) + { + OpenFromGacDialog dlg = new OpenFromGacDialog(); + dlg.Owner = this; + if (dlg.ShowDialog() == true) { + OpenFiles(dlg.SelectedFileNames); + } + } + #endregion + + #region Exit/About void ExitClick(object sender, RoutedEventArgs e) { Close(); @@ -337,16 +366,9 @@ namespace ICSharpCode.ILSpy { AboutPage.Display(decompilerTextView); } + #endregion - void OpenFromGac_Click(object sender, RoutedEventArgs e) - { - OpenFromGacDialog dlg = new OpenFromGacDialog(); - dlg.Owner = this; - if (dlg.ShowDialog() == true) { - OpenFiles(dlg.SelectedFileNames); - } - } - + #region Decompile / Save void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (treeView.SelectedItems.Count == 1) { @@ -370,6 +392,37 @@ namespace ICSharpCode.ILSpy treeView.GetTopLevelSelection().OfType(), new DecompilationOptions()); } + #endregion + + #region Back/Forward navigation + void BackCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) + { + e.Handled = true; + e.CanExecute = history.CanNavigateBack; + } + + void BackCommandExecuted(object sender, ExecutedRoutedEventArgs e) + { + if (history.CanNavigateBack) { + e.Handled = true; + SelectNode(history.GoBack(treeView.SelectedItem as SharpTreeNode), false); + } + } + + void ForwardCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) + { + e.Handled = true; + e.CanExecute = history.CanNavigateForward; + } + + void ForwardCommandExecuted(object sender, ExecutedRoutedEventArgs e) + { + if (history.CanNavigateForward) { + e.Handled = true; + SelectNode(history.GoForward(treeView.SelectedItem as SharpTreeNode), false); + } + } + #endregion protected override void OnStateChanged(EventArgs e) { diff --git a/ILSpy/NavigationHistory.cs b/ILSpy/NavigationHistory.cs new file mode 100644 index 000000000..521780af1 --- /dev/null +++ b/ILSpy/NavigationHistory.cs @@ -0,0 +1,64 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.TreeView; + +namespace ICSharpCode.ILSpy +{ + /// + /// Stores the navigation history. + /// + public class NavigationHistory + { + List back = new List(); + List forward = new List(); + + public bool CanNavigateBack { + get { return back.Count > 0; } + } + + public bool CanNavigateForward { + get { return forward.Count > 0; } + } + + public SharpTreeNode GoBack(SharpTreeNode oldNode) + { + if (oldNode != null) + forward.Add(oldNode); + + SharpTreeNode node = back[back.Count - 1]; + back.RemoveAt(back.Count - 1); + return node; + } + + public SharpTreeNode GoForward(SharpTreeNode oldNode) + { + if (oldNode != null) + back.Add(oldNode); + + SharpTreeNode node = forward[forward.Count - 1]; + forward.RemoveAt(forward.Count - 1); + return node; + } + + public void RemoveAll(Predicate predicate) + { + back.RemoveAll(predicate); + forward.RemoveAll(predicate); + } + + public void Clear() + { + back.Clear(); + forward.Clear(); + } + + public void Record(SharpTreeNode node) + { + forward.Clear(); + back.Add(node); + } + } +} diff --git a/SharpTreeView/SharpTreeView.cs b/SharpTreeView/SharpTreeView.cs index 7a949b618..43ec4141a 100644 --- a/SharpTreeView/SharpTreeView.cs +++ b/SharpTreeView/SharpTreeView.cs @@ -198,6 +198,9 @@ namespace ICSharpCode.TreeView base.OnKeyDown(e); } + /// + /// Scrolls the specified node in view and sets keyboard focus on it. + /// public void FocusNode(SharpTreeNode node) { if (node == null)