Browse Source

Fix #2207: Fix ViewState handling on refresh and tab change. Include active tab in history.

pull/2316/head
Siegfried Pammer 4 years ago
parent
commit
4bef47e454
  1. 7
      ILSpy/Docking/DockWorkspace.cs
  2. 69
      ILSpy/MainWindow.xaml.cs
  3. 10
      ILSpy/NavigationState.cs
  4. 3
      SharpTreeView/SharpTreeView.cs

7
ILSpy/Docking/DockWorkspace.cs

@ -100,10 +100,15 @@ 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));
}

69
ILSpy/MainWindow.xaml.cs

@ -68,7 +68,7 @@ namespace ICSharpCode.ILSpy
/// </summary>
partial class MainWindow : Window
{
bool refreshInProgress;
bool refreshInProgress, changingActiveTab;
readonly NavigationHistory<NavigationState> history = new NavigationHistory<NavigationState>();
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,7 +890,11 @@ namespace ICSharpCode.ILSpy
public void SelectNodes(IEnumerable<SharpTreeNode> 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<SharpTreeNode> nodes, bool inNewTabPage,
bool setFocus, bool changingActiveTab)
{
if (inNewTabPage)
{
@ -898,15 +906,32 @@ namespace ICSharpCode.ILSpy
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(nodesList);
}
AssemblyTreeView.SetSelectedNodes(nodes);
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<SharpTreeNode>()));
history.UpdateCurrent(new NavigationState(tabPage, currentState));
history.Record(new NavigationState(tabPage, AssemblyTreeView.SelectedItems.OfType<SharpTreeNode>()));
}
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 }));
}
}

10
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<SharpTreeNode> treeNodes;
public IEnumerable<SharpTreeNode> TreeNodes { get { return treeNodes; } }
public IEnumerable<SharpTreeNode> 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<SharpTreeNode>((IEnumerable<SharpTreeNode>)viewState.DecompiledNodes ?? Array.Empty<SharpTreeNode>());
ViewState = viewState;
}
public NavigationState(IEnumerable<SharpTreeNode> treeNodes)
public NavigationState(TabPageModel tabPage, IEnumerable<SharpTreeNode> treeNodes)
{
this.TabPage = tabPage;
this.treeNodes = new HashSet<SharpTreeNode>(treeNodes);
}

3
SharpTreeView/SharpTreeView.cs

@ -825,7 +825,8 @@ namespace ICSharpCode.TreeView
public void SetSelectedNodes(IEnumerable<SharpTreeNode> nodes)
{
this.SetSelectedItems(nodes.ToList());
bool success = this.SetSelectedItems(nodes.ToList());
Debug.Assert(success);
}
}
}
Loading…
Cancel
Save