From 69a7ffd61a163ed835576f28ce8a6aa3fdc553ce Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 2 Nov 2019 16:18:16 +0100 Subject: [PATCH] Improved docking. --- ILSpy/Docking/DockWorkspace.cs | 2 - ILSpy/Docking/DockingHelper.cs | 72 ----- ILSpy/Docking/LayoutUpdateStrategy.cs | 109 +++++++- ILSpy/ILSpy.csproj | 3 +- ILSpy/MainWindow.xaml | 320 +++++++++++++++++++++- ILSpy/MainWindow.xaml.cs | 20 +- ILSpy/ViewModels/AnalyzerPaneModel.cs | 2 + ILSpy/ViewModels/AssemblyListPaneModel.cs | 2 + ILSpy/ViewModels/DebugStepsPaneModel.cs | 2 + ILSpy/ViewModels/DocumentModel.cs | 2 + ILSpy/ViewModels/PaneModel.cs | 5 +- ILSpy/ViewModels/SearchPaneModel.cs | 2 + ILSpy/ViewModels/ToolPaneModel.cs | 2 +- 13 files changed, 424 insertions(+), 119 deletions(-) delete mode 100644 ILSpy/Docking/DockingHelper.cs diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs index 7d6a5a3f7..71999a01b 100644 --- a/ILSpy/Docking/DockWorkspace.cs +++ b/ILSpy/Docking/DockWorkspace.cs @@ -12,8 +12,6 @@ namespace ICSharpCode.ILSpy.Docking private DockWorkspace() { - Documents.Add(new DocumentModel()); - ToolPanes.Add(AssemblyListPaneModel.Instance); } public PaneCollection Documents { get; } = new PaneCollection(); diff --git a/ILSpy/Docking/DockingHelper.cs b/ILSpy/Docking/DockingHelper.cs deleted file mode 100644 index 7198d9b13..000000000 --- a/ILSpy/Docking/DockingHelper.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using Xceed.Wpf.AvalonDock.Layout; - -namespace ICSharpCode.ILSpy.Docking -{ - public static class DockingHelper - { - public static bool Dock(LayoutRoot root, LayoutContent layoutContent, PanePosition position) - { - var documentPane = root.Descendents().OfType().FirstOrDefault(); - if ((position == PanePosition.Top) || (position == PanePosition.Bottom)) { - return DockHorizontal(layoutContent, documentPane, new GridLength(200), position == PanePosition.Top); - } else if ((position == PanePosition.Left) || (position == PanePosition.Right)) { - return DockVertical(layoutContent as LayoutAnchorable, documentPane, new GridLength(400), position == PanePosition.Left); - } - return false; - } - - public static bool DockHorizontal(LayoutContent layoutContent, ILayoutElement paneRelativeTo, GridLength dockHeight, bool dockBefore = false) - { - if (paneRelativeTo is ILayoutDocumentPane parentDocumentPane) { - var parentDocumentGroup = paneRelativeTo.FindParent(); - if (parentDocumentGroup == null) { - var grandParent = parentDocumentPane.Parent as ILayoutContainer; - parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; - grandParent.ReplaceChild(paneRelativeTo, parentDocumentGroup); - parentDocumentGroup.Children.Add(parentDocumentPane); - } - parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Vertical; - int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); - var layoutDocumentPane = new LayoutDocumentPane(layoutContent) { DockHeight = dockHeight }; - parentDocumentGroup.InsertChildAt(dockBefore ? indexOfParentPane : indexOfParentPane + 1, layoutDocumentPane); - layoutContent.IsActive = true; - layoutContent.Root.CollectGarbage(); - Application.Current.MainWindow.Dispatcher.Invoke( - () => layoutDocumentPane.DockHeight = dockHeight, - System.Windows.Threading.DispatcherPriority.Loaded); - return true; - } - - return false; - } - - public static bool DockVertical(LayoutAnchorable anchorable, ILayoutElement paneRelativeTo, GridLength dockWidth, bool dockBefore = false) - { - if (paneRelativeTo is ILayoutDocumentPane parentDocumentPane) { - var grandParent = parentDocumentPane.Parent as LayoutPanel; - var targetAnchorablePane = grandParent.Children.OfType().FirstOrDefault(); - if (targetAnchorablePane == null) { - targetAnchorablePane = new LayoutAnchorablePane() { - DockWidth = new GridLength(400) - }; - int targetIndex = dockBefore ? 0 : grandParent.ChildrenCount; - grandParent.InsertChildAt(targetIndex, targetAnchorablePane); - } - grandParent.Orientation = Orientation.Horizontal; - targetAnchorablePane.Children.Add(anchorable); - - anchorable.IsActive = true; - anchorable.Root.CollectGarbage(); - Application.Current.MainWindow.Dispatcher.Invoke( - () => targetAnchorablePane.DockWidth = dockWidth, - System.Windows.Threading.DispatcherPriority.Loaded); - return true; - } - - return false; - } - } -} diff --git a/ILSpy/Docking/LayoutUpdateStrategy.cs b/ILSpy/Docking/LayoutUpdateStrategy.cs index c63e2604c..751e6abde 100644 --- a/ILSpy/Docking/LayoutUpdateStrategy.cs +++ b/ILSpy/Docking/LayoutUpdateStrategy.cs @@ -1,5 +1,7 @@ -using System.Linq; +using System; +using System.Linq; using System.Windows; +using System.Windows.Controls; using ICSharpCode.ILSpy.ViewModels; using Xceed.Wpf.AvalonDock.Layout; @@ -9,21 +11,71 @@ namespace ICSharpCode.ILSpy.Docking { public bool BeforeInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableToShow, ILayoutContainer destinationContainer) { - if ((destinationContainer != null) && - (destinationContainer.FindParent() != null)) + if (destinationContainer?.FindParent() != null) return false; - PanePosition targetPosition = PanePosition.Top; - switch (anchorableToShow.Content) { - case AnalyzerPaneModel _: - targetPosition = PanePosition.Bottom; - break; - case AssemblyListPaneModel _: - targetPosition = PanePosition.Left; - break; + 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"); } + } - return DockingHelper.Dock(layout, anchorableToShow, targetPosition); + private LayoutAnchorablePane GetOrCreatePane(LayoutRoot layout, string name) + { + var pane = layout.Descendents().OfType().FirstOrDefault(p => p.Name == name + "Pane"); + if (pane != null) + return pane; + var layoutPanel = layout.Children.OfType().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().FirstOrDefault(); + if (centerLayoutPanel == null) { + layoutPanel.Children.Insert(0, centerLayoutPanel = new LayoutPanel() { Orientation = Orientation.Vertical }); + } + 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) @@ -32,7 +84,38 @@ namespace ICSharpCode.ILSpy.Docking public bool BeforeInsertDocument(LayoutRoot layout, LayoutDocument anchorableToShow, ILayoutContainer destinationContainer) { - return false; + if (destinationContainer?.FindParent() != 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().FirstOrDefault(); + if (pane != null) + return pane; + var layoutPanel = layout.Children.OfType().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().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) diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index c53b9deef..a6fc565f2 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -50,7 +50,7 @@ - + @@ -141,7 +141,6 @@ - diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index a07bc2b93..eaf340173 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -5,6 +5,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:tv="clr-namespace:ICSharpCode.TreeView;assembly=ICSharpCode.TreeView" xmlns:local="clr-namespace:ICSharpCode.ILSpy" xmlns:avalondock="http://schemas.xceed.com/wpf/xaml/avalondock" + xmlns:avalondockproperties="clr-namespace:Xceed.Wpf.AvalonDock.Properties;assembly=Xceed.Wpf.AvalonDock" xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking" xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls" xmlns:analyzers="clr-namespace:ICSharpCode.ILSpy.Analyzers" @@ -22,7 +23,8 @@ - + + - + @@ -42,11 +44,11 @@ - + - + @@ -162,16 +164,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -191,14 +490,13 @@ - @@ -208,7 +506,7 @@ - + diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 1916794ae..bff8bd646 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -460,6 +460,9 @@ namespace ICSharpCode.ILSpy void MainWindow_Loaded(object sender, RoutedEventArgs e) { + DockWorkspace.Instance.ToolPanes.Add(AssemblyListPaneModel.Instance); + DockWorkspace.Instance.Documents.Add(new DocumentModel()); + ILSpySettings spySettings = this.spySettingsForMainWindow_Loaded; this.spySettingsForMainWindow_Loaded = null; var loadPreviousAssemblies = Options.MiscSettingsPanel.CurrentMiscSettings.LoadPreviousAssemblies; @@ -1074,23 +1077,6 @@ namespace ICSharpCode.ILSpy return loadedAssy.FileName; } - //#region Top/Bottom Pane management - - //public void ShowInNewPane(string title, object content, PanePosition panePosition, string toolTip = null) - //{ - // if (panePosition == PanePosition.Document) { - // var layoutDocument = new LayoutDocument() { Title = title, Content = content, ToolTip = toolTip, CanClose = true }; - // var documentPane = this.DockManager.Layout.Descendents().OfType().FirstOrDefault(); - // documentPane.Children.Add(layoutDocument); - // } else { - // var layoutAnchorable = new LayoutAnchorable() { Title = title, Content = content, ToolTip = toolTip, CanClose = true, CanHide = true }; - // var documentPane = this.DockManager.Layout.Descendents().OfType().FirstOrDefault(); - // Docking.DockingHelper.DockHorizontal(layoutAnchorable, documentPane, new GridLength(200), panePosition == PanePosition.Top); - // } - //} - - //#endregion - public void UnselectAll() { treeView.UnselectAll(); diff --git a/ILSpy/ViewModels/AnalyzerPaneModel.cs b/ILSpy/ViewModels/AnalyzerPaneModel.cs index aab12aa13..0eaf9c818 100644 --- a/ILSpy/ViewModels/AnalyzerPaneModel.cs +++ b/ILSpy/ViewModels/AnalyzerPaneModel.cs @@ -6,6 +6,8 @@ public static AnalyzerPaneModel Instance { get; } = new AnalyzerPaneModel(); + public override PanePosition DefaultPosition => PanePosition.Bottom; + private AnalyzerPaneModel() { ContentId = PaneContentId; diff --git a/ILSpy/ViewModels/AssemblyListPaneModel.cs b/ILSpy/ViewModels/AssemblyListPaneModel.cs index 8ec178596..2d465a6a8 100644 --- a/ILSpy/ViewModels/AssemblyListPaneModel.cs +++ b/ILSpy/ViewModels/AssemblyListPaneModel.cs @@ -6,6 +6,8 @@ public static AssemblyListPaneModel Instance { get; } = new AssemblyListPaneModel(); + public override PanePosition DefaultPosition => PanePosition.Left; + private AssemblyListPaneModel() { Title = "Assemblies"; diff --git a/ILSpy/ViewModels/DebugStepsPaneModel.cs b/ILSpy/ViewModels/DebugStepsPaneModel.cs index 503ddf8d5..196e9a7be 100644 --- a/ILSpy/ViewModels/DebugStepsPaneModel.cs +++ b/ILSpy/ViewModels/DebugStepsPaneModel.cs @@ -6,6 +6,8 @@ public static DebugStepsPaneModel Instance { get; } = new DebugStepsPaneModel(); + public override PanePosition DefaultPosition => PanePosition.Top; + private DebugStepsPaneModel() { ContentId = PaneContentId; diff --git a/ILSpy/ViewModels/DocumentModel.cs b/ILSpy/ViewModels/DocumentModel.cs index 0200735e1..2fa9129ab 100644 --- a/ILSpy/ViewModels/DocumentModel.cs +++ b/ILSpy/ViewModels/DocumentModel.cs @@ -2,6 +2,8 @@ { public class DocumentModel : PaneModel { + public override PanePosition DefaultPosition => PanePosition.Document; + public DocumentModel() { ContentId = "document"; diff --git a/ILSpy/ViewModels/PaneModel.cs b/ILSpy/ViewModels/PaneModel.cs index 2a168f9ae..bce2ecc70 100644 --- a/ILSpy/ViewModels/PaneModel.cs +++ b/ILSpy/ViewModels/PaneModel.cs @@ -1,9 +1,12 @@ using System.ComponentModel; +using System.Windows.Input; namespace ICSharpCode.ILSpy.ViewModels { - public class PaneModel : INotifyPropertyChanged + public abstract class PaneModel : INotifyPropertyChanged { + public abstract PanePosition DefaultPosition { get; } + public event PropertyChangedEventHandler PropertyChanged; protected void RaisePropertyChanged(string propertyName) diff --git a/ILSpy/ViewModels/SearchPaneModel.cs b/ILSpy/ViewModels/SearchPaneModel.cs index 585e1b5be..2b3847817 100644 --- a/ILSpy/ViewModels/SearchPaneModel.cs +++ b/ILSpy/ViewModels/SearchPaneModel.cs @@ -6,6 +6,8 @@ public static SearchPaneModel Instance { get; } = new SearchPaneModel(); + public override PanePosition DefaultPosition => PanePosition.Top; + private SearchPaneModel() { ContentId = PaneContentId; diff --git a/ILSpy/ViewModels/ToolPaneModel.cs b/ILSpy/ViewModels/ToolPaneModel.cs index fdb45bf76..e57a18067 100644 --- a/ILSpy/ViewModels/ToolPaneModel.cs +++ b/ILSpy/ViewModels/ToolPaneModel.cs @@ -1,6 +1,6 @@ namespace ICSharpCode.ILSpy.ViewModels { - public class ToolPaneModel : PaneModel + public abstract class ToolPaneModel : PaneModel { }