diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs index 790dbdad2..ede66930e 100644 --- a/ILSpy/Docking/DockWorkspace.cs +++ b/ILSpy/Docking/DockWorkspace.cs @@ -100,9 +100,14 @@ namespace ICSharpCode.ILSpy.Docking if (state != null) { if (state.DecompiledNodes != null) - MainWindow.Instance.SelectNodes(state.DecompiledNodes); + { + MainWindow.Instance.SelectNodes(state.DecompiledNodes, + inNewTabPage: false, setFocus: true, changingActiveTab: true); + } else + { MainWindow.Instance.NavigateTo(new RequestNavigateEventArgs(state.ViewedUri, null)); + } } RaisePropertyChanged(nameof(ActiveTabPage)); diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 8ac8d7b93..96089f230 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -68,7 +68,7 @@ namespace ICSharpCode.ILSpy /// partial class MainWindow : Window { - bool refreshInProgress; + bool refreshInProgress, changingActiveTab; readonly NavigationHistory history = new NavigationHistory(); ILSpySettings spySettingsForMainWindow_Loaded; internal SessionSettings sessionSettings; @@ -747,8 +747,12 @@ namespace ICSharpCode.ILSpy void ShowAssemblyList(AssemblyList assemblyList) { history.Clear(); - this.assemblyList = assemblyList; + if (this.assemblyList != null) + { + this.assemblyList.CollectionChanged -= assemblyList_Assemblies_CollectionChanged; + } + this.assemblyList = assemblyList; assemblyList.CollectionChanged += assemblyList_Assemblies_CollectionChanged; assemblyListTreeNode = new AssemblyListTreeNode(assemblyList); @@ -886,27 +890,48 @@ namespace ICSharpCode.ILSpy public void SelectNodes(IEnumerable nodes, bool inNewTabPage, bool setFocus) { - if (nodes.Any() && nodes.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden))) + SelectNodes(nodes, inNewTabPage, setFocus, false); + } + + internal void SelectNodes(IEnumerable nodes, bool inNewTabPage, + bool setFocus, bool changingActiveTab) + { + if (inNewTabPage) { - if (inNewTabPage) - { - DockWorkspace.Instance.TabPages.Add( - new TabPageModel() { - Language = CurrentLanguage, - LanguageVersion = CurrentLanguageVersion - }); - DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last(); - } + DockWorkspace.Instance.TabPages.Add( + new TabPageModel() { + Language = CurrentLanguage, + LanguageVersion = CurrentLanguageVersion + }); + DockWorkspace.Instance.ActiveTabPage = DockWorkspace.Instance.TabPages.Last(); + } + + // Ensure nodes exist + var nodesList = nodes.Select(n => FindNodeByPath(GetPathForNode(n), true)) + .Where(n => n != null).ToArray(); + + if (!nodesList.Any() || !nodesList.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden))) + { + return; + } + this.changingActiveTab = changingActiveTab || inNewTabPage; + try + { if (setFocus) { - AssemblyTreeView.FocusNode(nodes.First()); + AssemblyTreeView.FocusNode(nodesList[0]); } else { - AssemblyTreeView.ScrollIntoView(nodes.First()); + AssemblyTreeView.ScrollIntoView(nodesList[0]); } - AssemblyTreeView.SetSelectedNodes(nodes); + + AssemblyTreeView.SetSelectedNodes(nodesList); + } + finally + { + this.changingActiveTab = false; } } @@ -1158,7 +1183,12 @@ namespace ICSharpCode.ILSpy #region Decompile (TreeView_SelectionChanged) void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e) { - DecompileSelectedNodes(); + DecompilerTextViewState state = null; + if (refreshInProgress || changingActiveTab) + { + state = DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState; + } + DecompileSelectedNodes(state); SelectionChanged?.Invoke(sender, e); } @@ -1176,10 +1206,11 @@ namespace ICSharpCode.ILSpy if (recordHistory) { - var currentState = DockWorkspace.Instance.ActiveTabPage.GetState(); + var tabPage = DockWorkspace.Instance.ActiveTabPage; + var currentState = tabPage.GetState(); if (currentState != null) - history.UpdateCurrent(new NavigationState(currentState)); - history.Record(new NavigationState(AssemblyTreeView.SelectedItems.OfType())); + history.UpdateCurrent(new NavigationState(tabPage, currentState)); + history.Record(new NavigationState(tabPage, AssemblyTreeView.SelectedItems.OfType())); } DockWorkspace.Instance.ActiveTabPage.SupportsLanguageSwitching = true; @@ -1195,7 +1226,10 @@ namespace ICSharpCode.ILSpy NavigateTo(new RequestNavigateEventArgs(newState.ViewedUri, null), recordHistory: false); return; } - decompilationTask = DockWorkspace.Instance.ActiveTabPage.ShowTextViewAsync(textView => textView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, new DecompilationOptions() { TextViewState = newState })); + var options = new DecompilationOptions() { TextViewState = newState }; + decompilationTask = DockWorkspace.Instance.ActiveTabPage.ShowTextViewAsync( + textView => textView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, options) + ); } void SaveCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) @@ -1267,13 +1301,15 @@ namespace ICSharpCode.ILSpy void NavigateHistory(bool forward) { - var state = DockWorkspace.Instance.ActiveTabPage.GetState(); + TabPageModel tabPage = DockWorkspace.Instance.ActiveTabPage; + var state = tabPage.GetState(); if (state != null) - history.UpdateCurrent(new NavigationState(state)); + history.UpdateCurrent(new NavigationState(tabPage, state)); var newState = forward ? history.GoForward() : history.GoBack(); ignoreDecompilationRequests = true; AssemblyTreeView.SelectedItems.Clear(); + DockWorkspace.Instance.ActiveTabPage = newState.TabPage; foreach (var node in newState.TreeNodes) { AssemblyTreeView.SelectedItems.Add(node); @@ -1332,13 +1368,14 @@ namespace ICSharpCode.ILSpy { if (!recordHistory) return; - var currentState = DockWorkspace.Instance.ActiveTabPage.GetState(); + TabPageModel tabPage = DockWorkspace.Instance.ActiveTabPage; + var currentState = tabPage.GetState(); if (currentState != null) - history.UpdateCurrent(new NavigationState(currentState)); + history.UpdateCurrent(new NavigationState(tabPage, currentState)); ignoreDecompilationRequests = true; UnselectAll(); ignoreDecompilationRequests = false; - history.Record(new NavigationState(new ViewState { ViewedUri = e.Uri })); + history.Record(new NavigationState(tabPage, new ViewState { ViewedUri = e.Uri })); } } diff --git a/ILSpy/NavigationState.cs b/ILSpy/NavigationState.cs index 0b9eceafd..23ba9a1b4 100644 --- a/ILSpy/NavigationState.cs +++ b/ILSpy/NavigationState.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Diagnostics; using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy @@ -30,17 +31,20 @@ namespace ICSharpCode.ILSpy { private readonly HashSet treeNodes; - public IEnumerable TreeNodes { get { return treeNodes; } } + public IEnumerable TreeNodes => treeNodes; public ViewState ViewState { get; private set; } + public TabPageModel TabPage { get; private set; } - public NavigationState(ViewState viewState) + public NavigationState(TabPageModel tabPage, ViewState viewState) { + this.TabPage = tabPage; this.treeNodes = new HashSet((IEnumerable)viewState.DecompiledNodes ?? Array.Empty()); ViewState = viewState; } - public NavigationState(IEnumerable treeNodes) + public NavigationState(TabPageModel tabPage, IEnumerable treeNodes) { + this.TabPage = tabPage; this.treeNodes = new HashSet(treeNodes); } diff --git a/SharpTreeView/SharpTreeView.cs b/SharpTreeView/SharpTreeView.cs index c2b1ebe61..da4983a50 100644 --- a/SharpTreeView/SharpTreeView.cs +++ b/SharpTreeView/SharpTreeView.cs @@ -825,7 +825,8 @@ namespace ICSharpCode.TreeView public void SetSelectedNodes(IEnumerable nodes) { - this.SetSelectedItems(nodes.ToList()); + bool success = this.SetSelectedItems(nodes.ToList()); + Debug.Assert(success); } } }