Browse Source

#1803: Properly implement tool pane logic. Ground work for multiple docking layouts.

pull/1820/head
Siegfried Pammer 6 years ago
parent
commit
05c21c5a08
  1. 2
      ILSpy/Analyzers/AnalyzerTreeView.cs
  2. 2
      ILSpy/Commands/ShowDebugSteps.cs
  3. 2
      ILSpy/DebugSteps.xaml.cs
  4. 36
      ILSpy/Docking/DockLayoutSettings.cs
  5. 46
      ILSpy/Docking/DockWorkspace.cs
  6. 150
      ILSpy/Docking/LayoutUpdateStrategy.cs
  7. 1
      ILSpy/ILSpy.csproj
  8. 20
      ILSpy/MainWindow.xaml
  9. 12
      ILSpy/MainWindow.xaml.cs
  10. 2
      ILSpy/Search/SearchPane.cs
  11. 2
      ILSpy/ViewModels/PaneModel.cs

2
ILSpy/Analyzers/AnalyzerTreeView.cs

@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy.Analyzers
public void Show()
{
DockWorkspace.Instance.ToolPanes.Add(AnalyzerPaneModel.Instance);
AnalyzerPaneModel.Instance.IsVisible = true;
}
public void Show(AnalyzerTreeNode node)

2
ILSpy/Commands/ShowDebugSteps.cs

@ -11,7 +11,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -11,7 +11,7 @@ namespace ICSharpCode.ILSpy.Commands
{
public override void Execute(object parameter)
{
DockWorkspace.Instance.ToolPanes.Add(DebugStepsPaneModel.Instance);
DebugStepsPaneModel.Instance.IsVisible = true;
}
}
}

2
ILSpy/DebugSteps.xaml.cs

@ -81,7 +81,7 @@ namespace ICSharpCode.ILSpy @@ -81,7 +81,7 @@ namespace ICSharpCode.ILSpy
public static void Show()
{
DockWorkspace.Instance.ToolPanes.Add(DebugStepsPaneModel.Instance);
DebugStepsPaneModel.Instance.IsVisible = true;
}
void IPane.Closed()

36
ILSpy/Docking/DockLayoutSettings.cs

@ -27,6 +27,38 @@ namespace ICSharpCode.ILSpy.Docking @@ -27,6 +27,38 @@ namespace ICSharpCode.ILSpy.Docking
{
public class DockLayoutSettings
{
/// <remarks>NOTE: do NOT remove any of the (empty) sections, the deserializer is not very resilient and expects this exact order of elements!</remarks>
private const string DefaultLayout = @"
<LayoutRoot>
<RootPanel Orientation=""Horizontal"">
<LayoutAnchorablePaneGroup Orientation=""Horizontal"" DockWidth=""300"">
<LayoutAnchorablePane>
<LayoutAnchorable ContentId=""assemblyListPane"" />
</LayoutAnchorablePane>
</LayoutAnchorablePaneGroup>
<LayoutPanel Orientation=""Vertical"">
<LayoutAnchorablePaneGroup Orientation=""Horizontal"" DockHeight=""225"">
<LayoutAnchorablePane Id=""3ce12a2b-e6be-47cd-9787-fbf74bb9f157"" />
</LayoutAnchorablePaneGroup>
<LayoutDocumentPane />
<LayoutAnchorablePaneGroup Orientation=""Horizontal"" DockHeight=""225"">
<LayoutAnchorablePane Id=""8858bc50-019a-480e-b402-30a890e7c68f"" />
</LayoutAnchorablePaneGroup>
</LayoutPanel>
</RootPanel>
<TopSide />
<RightSide />
<LeftSide />
<BottomSide />
<FloatingWindows />
<Hidden>
<LayoutAnchorable ContentId=""debugStepsPane"" PreviousContainerId=""3ce12a2b-e6be-47cd-9787-fbf74bb9f157"" PreviousContainerIndex=""0"" />
<LayoutAnchorable ContentId=""searchPane"" PreviousContainerId=""3ce12a2b-e6be-47cd-9787-fbf74bb9f157"" PreviousContainerIndex=""0"" />
<LayoutAnchorable ContentId=""analyzerPane"" PreviousContainerId=""8858bc50-019a-480e-b402-30a890e7c68f"" PreviousContainerIndex=""0"" />
</Hidden>
</LayoutRoot>
";
private string rawSettings;
public bool Valid => rawSettings != null;
@ -50,11 +82,11 @@ namespace ICSharpCode.ILSpy.Docking @@ -50,11 +82,11 @@ namespace ICSharpCode.ILSpy.Docking
public void Deserialize(XmlLayoutSerializer serializer)
{
if (!Valid)
rawSettings = "<LayoutRoot />";
rawSettings = DefaultLayout;
try {
Deserialize(rawSettings);
} catch (Exception) {
Deserialize("<LayoutRoot />");
Deserialize(DefaultLayout);
}
void Deserialize(string settings)

46
ILSpy/Docking/DockWorkspace.cs

@ -17,8 +17,11 @@ @@ -17,8 +17,11 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
@ -44,12 +47,29 @@ namespace ICSharpCode.ILSpy.Docking @@ -44,12 +47,29 @@ namespace ICSharpCode.ILSpy.Docking
public PaneCollection<DocumentModel> Documents { get; } = new PaneCollection<DocumentModel>();
public PaneCollection<ToolPaneModel> ToolPanes { get; } = new PaneCollection<ToolPaneModel>();
private ToolPaneModel[] toolPanes;
public IEnumerable<ToolPaneModel> ToolPanes {
get {
if (toolPanes == null) {
toolPanes = new ToolPaneModel[] {
AssemblyListPaneModel.Instance,
SearchPaneModel.Instance,
AnalyzerPaneModel.Instance,
#if DEBUG
DebugStepsPaneModel.Instance,
#endif
};
}
return toolPanes;
}
}
public void Remove(PaneModel model)
{
Documents.Remove(model as DocumentModel);
ToolPanes.Remove(model as ToolPaneModel);
if (model is DocumentModel document)
Documents.Remove(document);
if (model is ToolPaneModel tool)
tool.IsVisible = false;
}
private DocumentModel _activeDocument = null;
@ -69,7 +89,20 @@ namespace ICSharpCode.ILSpy.Docking @@ -69,7 +89,20 @@ namespace ICSharpCode.ILSpy.Docking
}
}
internal void LayoutSerializationCallback(object sender, LayoutSerializationCallbackEventArgs e)
public void InitializeLayout(Xceed.Wpf.AvalonDock.DockingManager manager)
{
XmlLayoutSerializer serializer = new XmlLayoutSerializer(manager);
serializer.LayoutSerializationCallback += LayoutSerializationCallback;
try {
sessionSettings.DockLayout.Deserialize(serializer);
} finally {
serializer.LayoutSerializationCallback -= LayoutSerializationCallback;
}
EnsureUnclosablePanes();
}
void LayoutSerializationCallback(object sender, LayoutSerializationCallbackEventArgs e)
{
switch (e.Model) {
case LayoutAnchorable la:
@ -93,7 +126,8 @@ namespace ICSharpCode.ILSpy.Docking @@ -93,7 +126,8 @@ namespace ICSharpCode.ILSpy.Docking
break;
}
if (!e.Cancel) {
ToolPanes.Add((ToolPaneModel)e.Content);
e.Cancel = ((ToolPaneModel)e.Content).IsVisible;
((ToolPaneModel)e.Content).IsVisible = true;
}
break;
default:
@ -104,7 +138,7 @@ namespace ICSharpCode.ILSpy.Docking @@ -104,7 +138,7 @@ namespace ICSharpCode.ILSpy.Docking
internal void EnsureUnclosablePanes()
{
ToolPanes.Add(AssemblyListPaneModel.Instance);
AssemblyListPaneModel.Instance.IsVisible = true;
}
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)

150
ILSpy/Docking/LayoutUpdateStrategy.cs

@ -1,150 +0,0 @@ @@ -1,150 +0,0 @@
// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using ICSharpCode.ILSpy.ViewModels;
using Xceed.Wpf.AvalonDock.Layout;
namespace ICSharpCode.ILSpy.Docking
{
public class LayoutUpdateStrategy : ILayoutUpdateStrategy
{
public bool BeforeInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableToShow, ILayoutContainer destinationContainer)
{
if (destinationContainer?.FindParent<LayoutFloatingWindow>() != null)
return false;
PanePosition targetPosition = anchorableToShow.Content is PaneModel model ? model.DefaultPosition : PanePosition.Document;
switch (targetPosition) {
case PanePosition.Top:
case PanePosition.Bottom:
case PanePosition.Left:
case PanePosition.Right:
var pane = GetOrCreatePane(layout, targetPosition.ToString());
if (pane == null)
return false;
anchorableToShow.CanDockAsTabbedDocument = false;
pane.Children.Add(anchorableToShow);
return true;
case PanePosition.Document:
var documentPane = GetOrCreateDocumentPane(layout);
if (documentPane == null)
return false;
documentPane.Children.Add(anchorableToShow);
return true;
default:
throw new NotSupportedException($"Enum value {targetPosition} is not supported");
}
}
private LayoutAnchorablePane GetOrCreatePane(LayoutRoot layout, string name)
{
var pane = layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault(p => p.Name == name + "Pane");
if (pane != null)
return pane;
var layoutPanel = layout.Children.OfType<LayoutPanel>().FirstOrDefault();
if (layoutPanel == null) {
layout.RootPanel = new LayoutPanel() { Orientation = Orientation.Horizontal };
}
if (layoutPanel.Orientation != Orientation.Horizontal) {
layoutPanel.Orientation = Orientation.Horizontal;
}
LayoutAnchorablePane result = null;
switch (name) {
case "Top":
case "Bottom":
var centerLayoutPanel = layoutPanel.Children.OfType<LayoutPanel>().FirstOrDefault();
if (centerLayoutPanel == null) {
centerLayoutPanel = new LayoutPanel() { Orientation = Orientation.Vertical };
var documentPanel = layoutPanel.Children.OfType<LayoutDocumentPane>().FirstOrDefault();
if (documentPanel != null) {
layoutPanel.ReplaceChild(documentPanel, centerLayoutPanel);
centerLayoutPanel.Children.Add(documentPanel);
} else {
layoutPanel.Children.Insert(0, centerLayoutPanel);
}
}
if (centerLayoutPanel.Orientation != Orientation.Vertical) {
centerLayoutPanel.Orientation = Orientation.Vertical;
}
if (name == "Top")
centerLayoutPanel.Children.Insert(0, result = new LayoutAnchorablePane { Name = name + "Pane", DockMinHeight = 250 });
else
centerLayoutPanel.Children.Add(result = new LayoutAnchorablePane { Name = name + "Pane", DockMinHeight = 250 });
return result;
case "Left":
case "Right":
if (name == "Left")
layoutPanel.Children.Insert(0, result = new LayoutAnchorablePane { Name = name + "Pane", DockMinWidth = 250 });
else
layoutPanel.Children.Add(result = new LayoutAnchorablePane { Name = name + "Pane", DockMinWidth = 250 });
return result;
default:
throw new NotImplementedException();
}
}
public void AfterInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableShown)
{
}
public bool BeforeInsertDocument(LayoutRoot layout, LayoutDocument anchorableToShow, ILayoutContainer destinationContainer)
{
if (destinationContainer?.FindParent<LayoutFloatingWindow>() != null)
return false;
var documentPane = GetOrCreateDocumentPane(layout);
if (documentPane == null)
return false;
documentPane.Children.Add(anchorableToShow);
return true;
}
private LayoutDocumentPane GetOrCreateDocumentPane(LayoutRoot layout)
{
var pane = layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
if (pane != null)
return pane;
var layoutPanel = layout.Children.OfType<LayoutPanel>().FirstOrDefault();
if (layoutPanel == null) {
layout.RootPanel = new LayoutPanel() { Orientation = Orientation.Horizontal };
}
if (layoutPanel.Orientation != Orientation.Horizontal) {
layoutPanel.Orientation = Orientation.Horizontal;
}
var centerLayoutPanel = layoutPanel.Children.OfType<LayoutPanel>().FirstOrDefault();
if (centerLayoutPanel == null) {
layoutPanel.Children.Insert(0, centerLayoutPanel = new LayoutPanel() { Orientation = Orientation.Vertical });
}
if (centerLayoutPanel.Orientation != Orientation.Vertical) {
centerLayoutPanel.Orientation = Orientation.Vertical;
}
LayoutDocumentPane result;
centerLayoutPanel.Children.Add(result = new LayoutDocumentPane());
return result;
}
public void AfterInsertDocument(LayoutRoot layout, LayoutDocument anchorableShown)
{
}
}
}

1
ILSpy/ILSpy.csproj

@ -143,7 +143,6 @@ @@ -143,7 +143,6 @@
<Compile Include="ViewModels\AssemblyListPaneModel.cs" />
<Compile Include="Docking\DockLayoutSettings.cs" />
<Compile Include="ViewModels\DocumentModel.cs" />
<Compile Include="Docking\LayoutUpdateStrategy.cs" />
<Compile Include="Docking\PaneCollection.cs" />
<Compile Include="ViewModels\PaneModel.cs" />
<Compile Include="Docking\PaneStyleSelector.cs" />

20
ILSpy/MainWindow.xaml

@ -22,10 +22,9 @@ @@ -22,10 +22,9 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<controls:BoolToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<docking:ActiveDocumentConverter x:Key="ActiveDocumentConverter"/>
<avalondock:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<tv:SharpTreeView x:Key="TreeView"
AutomationProperties.Name="Assemblies and Classes"
SelectionChanged="TreeView_SelectionChanged"
@ -165,17 +164,6 @@ @@ -165,17 +164,6 @@
DocumentsSource="{Binding Documents}"
ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}"
AllowMixedOrientation="True">
<avalondock:LayoutRoot>
<avalondock:LayoutPanel Orientation="Horizontal">
<avalondock:LayoutAnchorablePane DockMinWidth="150" Name="LeftPane" />
<avalondock:LayoutPanel Orientation="Vertical">
<avalondock:LayoutAnchorablePane DockMinHeight="150" Name="TopPane" />
<avalondock:LayoutDocumentPane />
<avalondock:LayoutAnchorablePane DockMinHeight="150" Name="BottomPane" />
</avalondock:LayoutPanel>
<avalondock:LayoutAnchorablePane DockMinWidth="150" Name="RightPane" />
</avalondock:LayoutPanel>
</avalondock:LayoutRoot>
<avalondock:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
@ -187,10 +175,6 @@ @@ -187,10 +175,6 @@
</DataTemplate.Triggers>
</DataTemplate>
</avalondock:DockingManager.DocumentHeaderTemplate>
<avalondock:DockingManager.LayoutUpdateStrategy>
<docking:LayoutUpdateStrategy />
</avalondock:DockingManager.LayoutUpdateStrategy>
<avalondock:DockingManager.LayoutItemTemplateSelector>
<docking:PaneTemplateSelector>

12
ILSpy/MainWindow.xaml.cs

@ -120,15 +120,7 @@ namespace ICSharpCode.ILSpy @@ -120,15 +120,7 @@ namespace ICSharpCode.ILSpy
InitializeComponent();
XmlLayoutSerializer serializer = new XmlLayoutSerializer(DockManager);
serializer.LayoutSerializationCallback += DockWorkspace.Instance.LayoutSerializationCallback;
try {
sessionSettings.DockLayout.Deserialize(serializer);
} finally {
serializer.LayoutSerializationCallback -= DockWorkspace.Instance.LayoutSerializationCallback;
}
DockWorkspace.Instance.EnsureUnclosablePanes();
DockWorkspace.Instance.InitializeLayout(DockManager);
sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged;
@ -925,7 +917,7 @@ namespace ICSharpCode.ILSpy @@ -925,7 +917,7 @@ namespace ICSharpCode.ILSpy
void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
DockWorkspace.Instance.ToolPanes.Add(SearchPaneModel.Instance);
SearchPaneModel.Instance.IsVisible = true;
}
#endregion

2
ILSpy/Search/SearchPane.cs

@ -105,7 +105,7 @@ namespace ICSharpCode.ILSpy @@ -105,7 +105,7 @@ namespace ICSharpCode.ILSpy
public void Show()
{
if (!IsVisible) {
DockWorkspace.Instance.ToolPanes.Add(SearchPaneModel.Instance);
SearchPaneModel.Instance.IsVisible = true;
if (runSearchOnNextShow) {
runSearchOnNextShow = false;
StartSearch(this.SearchTerm);

2
ILSpy/ViewModels/PaneModel.cs

@ -82,7 +82,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -82,7 +82,7 @@ namespace ICSharpCode.ILSpy.ViewModels
}
}
private bool isVisible = true;
private bool isVisible;
public bool IsVisible {
get { return isVisible; }
set {

Loading…
Cancel
Save