From 97009de7940e6cbc9e67fc6ece58a839e3ba5c5f Mon Sep 17 00:00:00 2001
From: jkuehner <jochen.kuehner@kardex.com>
Date: Tue, 3 Sep 2019 15:10:01 +0200
Subject: [PATCH] support multiple decompilations

---
 ILSpy/Commands/DecompileInNewViewCommand.cs | 48 +++++++++++++++++++++
 ILSpy/Docking/PanePosition.cs               |  3 +-
 ILSpy/ILSpy.csproj                          |  1 +
 ILSpy/MainWindow.xaml                       | 36 ++++++----------
 ILSpy/MainWindow.xaml.cs                    | 46 ++++----------------
 ILSpy/Properties/Resources.Designer.cs      |  9 ++++
 ILSpy/Properties/Resources.resx             |  3 ++
 7 files changed, 83 insertions(+), 63 deletions(-)
 create mode 100644 ILSpy/Commands/DecompileInNewViewCommand.cs

diff --git a/ILSpy/Commands/DecompileInNewViewCommand.cs b/ILSpy/Commands/DecompileInNewViewCommand.cs
new file mode 100644
index 000000000..b088ae1ad
--- /dev/null
+++ b/ILSpy/Commands/DecompileInNewViewCommand.cs
@@ -0,0 +1,48 @@
+// Copyright (c) 2011 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.Linq;
+using ICSharpCode.ILSpy.Properties;
+using ICSharpCode.ILSpy.TextView;
+using ICSharpCode.ILSpy.TreeNodes;
+
+namespace ICSharpCode.ILSpy.Analyzers
+{
+	[ExportContextMenuEntry(Header = nameof(Resources.DecompileToNewPanel), Icon = "images/Search.png", Category = nameof(Resources.Analyze), Order = 90)]
+	internal sealed class DecompileInNewViewCommand : IContextMenuEntry
+	{
+		public bool IsVisible(TextViewContext context)
+		{
+			return true;			
+		}
+
+		public bool IsEnabled(TextViewContext context)
+		{
+			return true;			
+		}
+
+		public void Execute(TextViewContext context)
+		{
+			var dtv = new DecompilerTextView();
+			var nodes = context.SelectedTreeNodes.Cast<ILSpyTreeNode>().ToArray();
+			var title = string.Join(", ", nodes.Select(x => x.ToString()));
+			MainWindow.Instance.ShowInNewPane(title, dtv, PanePosition.Document);
+			dtv.Decompile(MainWindow.Instance.CurrentLanguage, nodes, new DecompilationOptions());
+		}
+	}
+}
diff --git a/ILSpy/Docking/PanePosition.cs b/ILSpy/Docking/PanePosition.cs
index d0ff28370..d162d5d7b 100644
--- a/ILSpy/Docking/PanePosition.cs
+++ b/ILSpy/Docking/PanePosition.cs
@@ -3,6 +3,7 @@
 	public enum PanePosition
 	{
 		Top,
-		Bottom
+		Bottom,
+		Document
 	}
 }
diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj
index 6c58619d0..79a5c8023 100644
--- a/ILSpy/ILSpy.csproj
+++ b/ILSpy/ILSpy.csproj
@@ -101,6 +101,7 @@
     <Compile Include="AssemblyListManager.cs" />
     <Compile Include="AvalonEdit\ITextMarker.cs" />
     <Compile Include="AvalonEdit\TextMarkerService.cs" />
+    <Compile Include="Commands\DecompileInNewViewCommand.cs" />
     <Compile Include="Commands\CheckForUpdatesCommand.cs" />
     <Compile Include="Commands\BrowseBackCommand.cs" />
     <Compile Include="Commands\BrowseForwardCommand.cs" />
diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml
index 75ef145a4..c99cbd82b 100644
--- a/ILSpy/MainWindow.xaml
+++ b/ILSpy/MainWindow.xaml
@@ -97,6 +97,15 @@
 			          ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
 			          SelectedItem="{Binding FilterSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/>
 		</ToolBar>
+		<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1" Name="updatePanel" Visibility="Collapsed">
+			<DockPanel KeyboardNavigation.TabNavigation="Contained">
+				<Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button>
+				<StackPanel Orientation="Horizontal">
+					<TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center"  Text="{x:Static properties:Resources.ILSpyVersionAvailable}" />
+					<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick" Content="{x:Static properties:Resources.Download}"/>
+				</StackPanel>
+			</DockPanel>
+		</Border>
 		<!-- Status bar -->
 		<StatusBar x:Name="statusBar" DockPanel.Dock="Bottom" Height="26" Visibility="Collapsed">
 			<StatusBarItem DockPanel.Dock="Right">
@@ -117,7 +126,7 @@
 					<avalondock:LayoutPanel Orientation="Horizontal">
 						<avalondock:LayoutAnchorablePaneGroup DockWidth="200" Orientation="Vertical">
 							<avalondock:LayoutAnchorablePane DockHeight="*">
-								<avalondock:LayoutAnchorable x:Name="Tree" Title="Project Explorer">
+								<avalondock:LayoutAnchorable x:Name="Tree" Title="Project Explorer" CanClose="False">
 									<!-- Left pane: Tree View of assemblies and classes -->
 									<tv:SharpTreeView
 										Name="treeView"
@@ -134,29 +143,8 @@
 						<avalondock:LayoutDocumentPaneGroup DockWidth="*">
 							<avalondock:LayoutDocumentPane x:Name="adDocumentPane">
 								<avalondock:LayoutDocument Title="Decompilation">
-									<Grid>
-										<Grid.ColumnDefinitions>
-											<ColumnDefinition Width="*" />
-										</Grid.ColumnDefinitions>
-										<Grid.RowDefinitions>
-											<RowDefinition Height="Auto" />
-											<RowDefinition Height="0" />
-											<RowDefinition Height="0.7*" MinHeight="100" Name="textViewRow" />
-											<RowDefinition Height="0" />
-										</Grid.RowDefinitions>
-										<Border BorderBrush="Black" BorderThickness="1" Name="updatePanel" Visibility="Collapsed">
-											<DockPanel KeyboardNavigation.TabNavigation="Contained">
-												<Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button>
-												<StackPanel Orientation="Horizontal">
-													<TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center"  Text="{x:Static properties:Resources.ILSpyVersionAvailable}" />
-													<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick" Content="{x:Static properties:Resources.Download}"/>
-												</StackPanel>
-											</DockPanel>
-										</Border>
-
-										<!-- decompilerTextView is into the mainPane by code -->
-										<ContentPresenter Name="mainPane" Grid.Row="2"/>
-									</Grid>
+									<!-- decompilerTextView is into the mainPane by code -->
+									<ContentPresenter Name="mainPane" />
 								</avalondock:LayoutDocument>
 							</avalondock:LayoutDocumentPane>
 						</avalondock:LayoutDocumentPaneGroup>
diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs
index 5f564205b..a27d07558 100644
--- a/ILSpy/MainWindow.xaml.cs
+++ b/ILSpy/MainWindow.xaml.cs
@@ -1051,49 +1051,19 @@ namespace ICSharpCode.ILSpy
 
 		#region Top/Bottom Pane management
 
-		/// <summary>
-		///   When grid is resized using splitter, row height value could become greater than 1.
-		///   As result, when a new pane is shown, both textView and pane could become very small.
-		///   This method normalizes two rows and ensures that height is less then 1.
-		/// </summary>
-		void NormalizePaneRowHeightValues(RowDefinition pane1Row, RowDefinition pane2Row)
-		{
-			var pane1Height = pane1Row.Height;
-			var pane2Height = pane2Row.Height;
-
-			//only star height values are normalized.
-			if (!pane1Height.IsStar || !pane2Height.IsStar) {
-				return;
-			}
-
-			var totalHeight = pane1Height.Value + pane2Height.Value;
-			if (totalHeight == 0) {
-				return;
-			}
-
-			pane1Row.Height = new GridLength(pane1Height.Value / totalHeight, GridUnitType.Star);
-			pane2Row.Height = new GridLength(pane2Height.Value / totalHeight, GridUnitType.Star);
-		}				
-
-		public void ShowInNewPane(string title, object content, PanePosition panePosition)
+		public void ShowInNewPane(string title, object content, PanePosition panePosition, string toolTip = null)
 		{
-			var layoutAnchorable = new LayoutAnchorable() { Title = title, Content = content };
+			if (panePosition == PanePosition.Document) {
+				var layoutDocument = new LayoutDocument() { Title = title, Content = content, ToolTip = toolTip };
 			var documentPane = this.DockManager.Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
+				documentPane.Children.Add(layoutDocument);
+			} else {
+				var layoutAnchorable = new LayoutAnchorable() { Title = title, Content = content, ToolTip = toolTip };
+				var documentPane = this.DockManager.Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
 			Docking.DockingHelper.DockHorizontal(layoutAnchorable, documentPane, new GridLength(100), panePosition == PanePosition.Top);
 		}
+		}
 
-		//void BottomPane_CloseButtonClicked(object sender, EventArgs e)
-		//{
-		//	sessionSettings.BottomPaneSplitterPosition = bottomPaneRow.Height.Value / (bottomPaneRow.Height.Value + textViewRow.Height.Value);
-		//	bottomPaneRow.MinHeight = 0;
-		//	bottomPaneRow.Height = new GridLength(0);
-		//	bottomPane.Visibility = Visibility.Collapsed;
-
-		//	IPane pane = bottomPane.Content as IPane;
-		//	bottomPane.Content = null;
-		//	if (pane != null)
-		//		pane.Closed();
-		//}
 		#endregion
 
 		public void UnselectAll()
diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs
index c5a662290..3283a7103 100644
--- a/ILSpy/Properties/Resources.Designer.cs
+++ b/ILSpy/Properties/Resources.Designer.cs
@@ -1008,6 +1008,15 @@ namespace ICSharpCode.ILSpy.Properties {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Decompile to new tab.
+        /// </summary>
+        public static string DecompileToNewPanel {
+            get {
+                return ResourceManager.GetString("DecompileToNewPanel", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Decompiling....
         /// </summary>
diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx
index 1a97f770f..eb20f2e6e 100644
--- a/ILSpy/Properties/Resources.resx
+++ b/ILSpy/Properties/Resources.resx
@@ -766,4 +766,7 @@ Are you sure you want to continue?</value>
   <data name="Assembly" xml:space="preserve">
     <value>Assembly</value>
   </data>
+  <data name="DecompileToNewPanel" xml:space="preserve">
+    <value>Decompile to new tab</value>
+  </data>
 </root>
\ No newline at end of file