Browse Source

Merge pull request #1725 from icsharpcode/avalondock

Basic AvalonDock support without multiple tabs
pull/1726/head
Christoph Wille 6 years ago committed by GitHub
parent
commit
49dfc5a6af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ILSpy/Analyzers/AnalyzerTreeView.cs
  2. 2
      ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs
  3. 52
      ILSpy/Commands/DecompileInNewViewCommand.cs
  4. 14
      ILSpy/ContextMenuEntry.cs
  5. 76
      ILSpy/Controls/DockedPane.cs
  6. 2
      ILSpy/DebugSteps.xaml.cs
  7. 32
      ILSpy/Docking/DockingHelper.cs
  8. 9
      ILSpy/Docking/PanePosition.cs
  9. 5
      ILSpy/ILSpy.csproj
  10. 143
      ILSpy/MainWindow.xaml
  11. 143
      ILSpy/MainWindow.xaml.cs
  12. 9
      ILSpy/Properties/Resources.Designer.cs
  13. 3
      ILSpy/Properties/Resources.resx
  14. 2
      ILSpy/Search/SearchPane.cs
  15. 91
      ILSpy/themes/generic.xaml

2
ILSpy/Analyzers/AnalyzerTreeView.cs

@ -73,7 +73,7 @@ namespace ICSharpCode.ILSpy.Analyzers
public void Show() public void Show()
{ {
if (!IsVisible) if (!IsVisible)
MainWindow.Instance.ShowInBottomPane("Analyzer", this); MainWindow.Instance.ShowInNewPane("Analyzer", this, PanePosition.Bottom);
} }
public void Show(AnalyzerTreeNode node) public void Show(AnalyzerTreeNode node)

2
ILSpy/Analyzers/RemoveAnalyzeContextMenuEntry.cs

@ -20,7 +20,7 @@ using System.Linq;
namespace ICSharpCode.ILSpy.Analyzers namespace ICSharpCode.ILSpy.Analyzers
{ {
[ExportContextMenuEntry(Header = "Remove", Icon = "images/Delete.png", Category = "Analyze", Order = 200)] [ExportContextMenuEntry(Header = "Remove", Icon = "images/Delete", Category = "Analyze", Order = 200)]
internal sealed class RemoveAnalyzeContextMenuEntry : IContextMenuEntry internal sealed class RemoveAnalyzeContextMenuEntry : IContextMenuEntry
{ {
public bool IsVisible(TextViewContext context) public bool IsVisible(TextViewContext context)

52
ILSpy/Commands/DecompileInNewViewCommand.cs

@ -0,0 +1,52 @@
// 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.Commands
{
// [ExportContextMenuEntry(Header = nameof(Resources.DecompileToNewPanel), Icon = "images/Search", Category = nameof(Resources.Analyze), Order = 90)]
internal sealed class DecompileInNewViewCommand : IContextMenuEntry
{
public bool IsVisible(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return false;
return true;
}
public bool IsEnabled(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return false;
return true;
}
public async 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);
await dtv.DecompileAsync(MainWindow.Instance.CurrentLanguage, nodes, new DecompilationOptions());
}
}
}

14
ILSpy/ContextMenuEntry.cs

@ -222,15 +222,11 @@ namespace ICSharpCode.ILSpy
menuItem.Header = MainWindow.GetResourceString( entryPair.Metadata.Header); menuItem.Header = MainWindow.GetResourceString( entryPair.Metadata.Header);
menuItem.InputGestureText = entryPair.Metadata.InputGestureText; menuItem.InputGestureText = entryPair.Metadata.InputGestureText;
if (!string.IsNullOrEmpty(entryPair.Metadata.Icon)) { if (!string.IsNullOrEmpty(entryPair.Metadata.Icon)) {
object image = Images.Load(entryPair.Value, entryPair.Metadata.Icon); menuItem.Icon = new Image {
if (!(image is Viewbox)) { Width = 16,
image = new Image { Height = 16,
Width = 16, Source = Images.Load(entryPair.Value, entryPair.Metadata.Icon)
Height = 16, };
Source = (ImageSource)image
};
}
menuItem.Icon = image;
} }
if (entryPair.Value.IsEnabled(context)) { if (entryPair.Value.IsEnabled(context)) {
menuItem.Click += delegate { entry.Execute(context); }; menuItem.Click += delegate { entry.Execute(context); };

76
ILSpy/Controls/DockedPane.cs

@ -1,76 +0,0 @@
// 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;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace ICSharpCode.ILSpy.Controls
{
class DockedPane : Control
{
static DockedPane()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DockedPane), new FrameworkPropertyMetadata(typeof(DockedPane)));
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(DockedPane));
public string Title {
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty ContentProperty =
DependencyProperty.Register("Content", typeof(object), typeof(DockedPane));
public object Content {
get { return GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Button closeButton = (Button)this.Template.FindName("PART_Close", this);
if (closeButton != null) {
closeButton.Click += closeButton_Click;
}
}
void closeButton_Click(object sender, RoutedEventArgs e)
{
if (CloseButtonClicked != null)
CloseButtonClicked(this, e);
}
public event EventHandler CloseButtonClicked;
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Key == Key.F4 && e.KeyboardDevice.Modifiers == ModifierKeys.Control || e.Key == Key.Escape) {
if (CloseButtonClicked != null)
CloseButtonClicked(this, e);
e.Handled = true;
}
}
}
}

2
ILSpy/DebugSteps.xaml.cs

@ -79,7 +79,7 @@ namespace ICSharpCode.ILSpy
public static void Show() public static void Show()
{ {
MainWindow.Instance.ShowInTopPane(Properties.Resources.DebugSteps, new DebugSteps()); MainWindow.Instance.ShowInNewPane(Properties.Resources.DebugSteps, new DebugSteps(), PanePosition.Top);
} }
void IPane.Closed() void IPane.Closed()

32
ILSpy/Docking/DockingHelper.cs

@ -0,0 +1,32 @@
using System.Windows;
using System.Windows.Controls;
using Xceed.Wpf.AvalonDock.Layout;
namespace ICSharpCode.ILSpy.Docking
{
public static class DockingHelper
{
public static void DockHorizontal(LayoutContent layoutContent, ILayoutElement paneRelativeTo, GridLength dockHeight, bool dockBefore = false)
{
if (paneRelativeTo is ILayoutDocumentPane parentDocumentPane) {
var parentDocumentGroup = paneRelativeTo.FindParent<LayoutDocumentPaneGroup>();
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);
}
}
}
}

9
ILSpy/Docking/PanePosition.cs

@ -0,0 +1,9 @@
namespace ICSharpCode.ILSpy
{
public enum PanePosition
{
Top,
Bottom,
Document
}
}

5
ILSpy/ILSpy.csproj

@ -49,6 +49,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AvalonEdit" Version="6.0.0" /> <PackageReference Include="AvalonEdit" Version="6.0.0" />
<PackageReference Include="Dirkster.AvalonDock" Version="3.5.12" />
<PackageReference Include="Microsoft.VisualStudio.Composition" Version="15.5.23" /> <PackageReference Include="Microsoft.VisualStudio.Composition" Version="15.5.23" />
<PackageReference Include="Mono.Cecil" Version="0.10.3" /> <PackageReference Include="Mono.Cecil" Version="0.10.3" />
<PackageReference Include="OSVersionHelper" Version="1.0.11" /> <PackageReference Include="OSVersionHelper" Version="1.0.11" />
@ -99,6 +100,7 @@
<Compile Include="AssemblyListManager.cs" /> <Compile Include="AssemblyListManager.cs" />
<Compile Include="AvalonEdit\ITextMarker.cs" /> <Compile Include="AvalonEdit\ITextMarker.cs" />
<Compile Include="AvalonEdit\TextMarkerService.cs" /> <Compile Include="AvalonEdit\TextMarkerService.cs" />
<Compile Include="Commands\DecompileInNewViewCommand.cs" />
<Compile Include="Commands\CheckForUpdatesCommand.cs" /> <Compile Include="Commands\CheckForUpdatesCommand.cs" />
<Compile Include="Commands\BrowseBackCommand.cs" /> <Compile Include="Commands\BrowseBackCommand.cs" />
<Compile Include="Commands\BrowseForwardCommand.cs" /> <Compile Include="Commands\BrowseForwardCommand.cs" />
@ -122,7 +124,6 @@
<Compile Include="Controls\ResourceObjectTable.xaml.cs"> <Compile Include="Controls\ResourceObjectTable.xaml.cs">
<DependentUpon>ResourceObjectTable.xaml</DependentUpon> <DependentUpon>ResourceObjectTable.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\DockedPane.cs" />
<Compile Include="Commands\DecompileAllCommand.cs" /> <Compile Include="Commands\DecompileAllCommand.cs" />
<Compile Include="Commands\ExportCommandAttribute.cs" /> <Compile Include="Commands\ExportCommandAttribute.cs" />
<Compile Include="Controls\ExtensionMethods.cs" /> <Compile Include="Controls\ExtensionMethods.cs" />
@ -136,6 +137,7 @@
<Compile Include="DebugSteps.xaml.cs"> <Compile Include="DebugSteps.xaml.cs">
<DependentUpon>DebugSteps.xaml</DependentUpon> <DependentUpon>DebugSteps.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Docking\DockingHelper.cs" />
<Compile Include="ILSpyTraceListener.cs" /> <Compile Include="ILSpyTraceListener.cs" />
<Compile Include="DecompilationOptions.cs" /> <Compile Include="DecompilationOptions.cs" />
<Compile Include="ExtensionMethods.cs" /> <Compile Include="ExtensionMethods.cs" />
@ -162,6 +164,7 @@
<Compile Include="Languages\Language.cs" /> <Compile Include="Languages\Language.cs" />
<Compile Include="Languages\Languages.cs" /> <Compile Include="Languages\Languages.cs" />
<Compile Include="Options\DecompilerSettingsPanel.xaml.cs" /> <Compile Include="Options\DecompilerSettingsPanel.xaml.cs" />
<Compile Include="Docking\PanePosition.cs" />
<Compile Include="Properties\Resources.Designer.cs"> <Compile Include="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>

143
ILSpy/MainWindow.xaml

@ -4,7 +4,7 @@
x:ClassModifier="public" x:ClassModifier="public"
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="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:local="clr-namespace:ICSharpCode.ILSpy"
xmlns:textView="clr-namespace:ICSharpCode.ILSpy.TextView" xmlns:avalondock="http://schemas.xceed.com/wpf/xaml/avalondock"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls" xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties" xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
Title="ILSpy" Title="ILSpy"
@ -51,7 +51,8 @@
<DockPanel> <DockPanel>
<!-- Main menu --> <!-- Main menu -->
<Menu DockPanel.Dock="Top" Name="mainMenu" Height="23" KeyboardNavigation.TabNavigation="None"> <Menu DockPanel.Dock="Top" Name="mainMenu" Height="23" KeyboardNavigation.TabNavigation="None">
<MenuItem Header="{x:Static properties:Resources._File}" /> <!-- contents of file menu are added using MEF --> <MenuItem Header="{x:Static properties:Resources._File}" />
<!-- contents of file menu are added using MEF -->
<MenuItem Header="{x:Static properties:Resources._View}"> <MenuItem Header="{x:Static properties:Resources._View}">
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding FilterSettings.ApiVisPublicOnly}" /> <MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding FilterSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding FilterSettings.ApiVisPublicAndInternal}" /> <MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding FilterSettings.ApiVisPublicAndInternal}" />
@ -96,6 +97,15 @@
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding FilterSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/> SelectedItem="{Binding FilterSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}"/>
</ToolBar> </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 --> <!-- Status bar -->
<StatusBar x:Name="statusBar" DockPanel.Dock="Bottom" Height="26" Visibility="Collapsed"> <StatusBar x:Name="statusBar" DockPanel.Dock="Bottom" Height="26" Visibility="Collapsed">
<StatusBarItem DockPanel.Dock="Right"> <StatusBarItem DockPanel.Dock="Right">
@ -107,99 +117,40 @@
</StatusBarItem> </StatusBarItem>
</StatusBar> </StatusBar>
<!-- Main grid separating left pane (treeView) from main pane (textEditor) --> <!-- Main grid separating left pane (treeView) from main pane (textEditor) -->
<Grid>
<Grid.ColumnDefinitions> <avalondock:DockingManager x:Name="DockManager"
<ColumnDefinition AllowMixedOrientation="True" Grid.ColumnSpan="2">
Name="leftColumn"
MinWidth="100" <avalondock:LayoutRoot x:Name="LayoutRoot" >
Width="0.4*" /> <avalondock:LayoutPanel Orientation="Vertical">
<ColumnDefinition <avalondock:LayoutPanel Orientation="Horizontal">
Width="3" /> <avalondock:LayoutAnchorablePaneGroup DockWidth="200" Orientation="Vertical">
<ColumnDefinition <avalondock:LayoutAnchorablePane DockHeight="*">
Name="rightColumn" <avalondock:LayoutAnchorable x:Name="Tree" Title="Project Explorer" CanHide="False" CanClose="False">
MinWidth="100" <!-- Left pane: Tree View of assemblies and classes -->
Width="0.6*" /> <tv:SharpTreeView
</Grid.ColumnDefinitions> Name="treeView"
<Grid.RowDefinitions> AutomationProperties.Name="Assemblies and Classes"
<RowDefinition SelectionChanged="TreeView_SelectionChanged"
Height="*" /> ShowRoot="False"
</Grid.RowDefinitions> AllowDropOrder="True"
<!-- Left pane: Tree View of assemblies and classes --> AllowDrop="True"
<tv:SharpTreeView BorderThickness="0,1,1,1" Visibility="Visible" />
Name="treeView" </avalondock:LayoutAnchorable>
AutomationProperties.Name="Assemblies and Classes" </avalondock:LayoutAnchorablePane>
SelectionChanged="TreeView_SelectionChanged" </avalondock:LayoutAnchorablePaneGroup>
ShowRoot="False"
AllowDropOrder="True" <avalondock:LayoutDocumentPaneGroup DockWidth="*">
AllowDrop="True" <avalondock:LayoutDocumentPane x:Name="adDocumentPane">
BorderThickness="0,1,1,1" Visibility="Visible" /> <avalondock:LayoutDocument Title="MAIN" CanClose="False">
<GridSplitter <!-- decompilerTextView is into the mainPane by code -->
Grid.ZIndex="1" <ContentPresenter Name="mainPane" />
Grid.Column="1" </avalondock:LayoutDocument>
Margin="-5,0" </avalondock:LayoutDocumentPane>
BorderThickness="5,0" </avalondock:LayoutDocumentPaneGroup>
HorizontalAlignment="Center" </avalondock:LayoutPanel>
VerticalAlignment="Stretch" </avalondock:LayoutPanel>
Focusable="False" </avalondock:LayoutRoot>
BorderBrush="Transparent" /> </avalondock:DockingManager>
<!-- Right pane: Text Editor -->
<Grid Grid.Column="2">
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="0" Name="topPaneRow" />
<RowDefinition Height="0" />
<RowDefinition Height="0.7*" MinHeight="100" Name="textViewRow" />
<RowDefinition Height="0" />
<RowDefinition Height="0" Name="bottomPaneRow" />
</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>
<controls:DockedPane x:Name="topPane" Grid.Row="1" Title="Top" Visibility="Collapsed"
AutomationProperties.Name="Close top pane"
CloseButtonClicked="TopPane_CloseButtonClicked" Margin="0,0,0,3"
BorderThickness="1,1,0,1" />
<GridSplitter
Grid.ZIndex="1"
Grid.Row="2"
Margin="0,-2,0,-5"
BorderThickness="0,2,0,5"
BorderBrush="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Focusable="False"
Visibility="{Binding Visibility, ElementName=topPane}" />
<!-- decompilerTextView is into the mainPane by code -->
<ContentPresenter Name="mainPane" Grid.Row="3"/>
<GridSplitter
Grid.ZIndex="1"
Grid.Row="4"
Margin="0,-2,0,-5"
BorderThickness="0,2,0,5"
BorderBrush="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
Focusable="False"
Visibility="{Binding Visibility, ElementName=bottomPane}" />
<controls:DockedPane x:Name="bottomPane" Grid.Row="5" Title="Bottom" Visibility="Collapsed"
AutomationProperties.Name="Close"
CloseButtonClicked="BottomPane_CloseButtonClicked" Margin="0,3,0,0" BorderThickness="1,1,0,1"/>
</Grid>
</Grid>
</DockPanel> </DockPanel>
</Window> </Window>

143
ILSpy/MainWindow.xaml.cs

@ -44,6 +44,7 @@ using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Microsoft.Win32; using Microsoft.Win32;
using OSVersionHelper; using OSVersionHelper;
using Xceed.Wpf.AvalonDock.Layout;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -90,10 +91,11 @@ namespace ICSharpCode.ILSpy
decompilerTextView = App.ExportProvider.GetExportedValue<DecompilerTextView>(); decompilerTextView = App.ExportProvider.GetExportedValue<DecompilerTextView>();
mainPane.Content = decompilerTextView; mainPane.Content = decompilerTextView;
if (sessionSettings.SplitterPosition > 0 && sessionSettings.SplitterPosition < 1) { //todo
leftColumn.Width = new GridLength(sessionSettings.SplitterPosition, GridUnitType.Star); //if (sessionSettings.SplitterPosition > 0 && sessionSettings.SplitterPosition < 1) {
rightColumn.Width = new GridLength(1 - sessionSettings.SplitterPosition, GridUnitType.Star); // leftColumn.Width = new GridLength(sessionSettings.SplitterPosition, GridUnitType.Star);
} // rightColumn.Width = new GridLength(1 - sessionSettings.SplitterPosition, GridUnitType.Star);
//}
sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged; sessionSettings.FilterSettings.PropertyChanged += filterSettings_PropertyChanged;
InitMainMenu(); InitMainMenu();
@ -140,19 +142,15 @@ namespace ICSharpCode.ILSpy
Button MakeToolbarItem(Lazy<ICommand, IToolbarCommandMetadata> command) Button MakeToolbarItem(Lazy<ICommand, IToolbarCommandMetadata> command)
{ {
object image = Images.Load(command.Value, command.Metadata.ToolbarIcon);
if (!(image is Viewbox)) {
image = new Image {
Width = 16,
Height = 16,
Source = (ImageSource)image
};
}
return new Button { return new Button {
Command = CommandWrapper.Unwrap(command.Value), Command = CommandWrapper.Unwrap(command.Value),
ToolTip = Properties.Resources.ResourceManager.GetString(command.Metadata.ToolTip), ToolTip = Properties.Resources.ResourceManager.GetString(command.Metadata.ToolTip),
Tag = command.Metadata.Tag, Tag = command.Metadata.Tag,
Content = image Content = new Image {
Width = 16,
Height = 16,
Source = Images.Load(command.Value, command.Metadata.ToolbarIcon)
}
}; };
} }
#endregion #endregion
@ -178,15 +176,11 @@ namespace ICSharpCode.ILSpy
if (!string.IsNullOrEmpty(GetResourceString(entry.Metadata.Header))) if (!string.IsNullOrEmpty(GetResourceString(entry.Metadata.Header)))
menuItem.Header = GetResourceString(entry.Metadata.Header); menuItem.Header = GetResourceString(entry.Metadata.Header);
if (!string.IsNullOrEmpty(entry.Metadata.MenuIcon)) { if (!string.IsNullOrEmpty(entry.Metadata.MenuIcon)) {
object image = Images.Load(entry.Value, entry.Metadata.MenuIcon); menuItem.Icon = new Image {
if (!(image is Viewbox)) { Width = 16,
image = new Image { Height = 16,
Width = 16, Source = Images.Load(entry.Value, entry.Metadata.MenuIcon)
Height = 16, };
Source = (ImageSource)image
};
}
menuItem.Icon = image;
} }
menuItem.IsEnabled = entry.Metadata.IsEnabled; menuItem.IsEnabled = entry.Metadata.IsEnabled;
@ -1022,11 +1016,12 @@ namespace ICSharpCode.ILSpy
sessionSettings.ActiveTreeViewPath = GetPathForNode(treeView.SelectedItem as SharpTreeNode); sessionSettings.ActiveTreeViewPath = GetPathForNode(treeView.SelectedItem as SharpTreeNode);
sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(treeView.SelectedItem as SharpTreeNode); sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(treeView.SelectedItem as SharpTreeNode);
sessionSettings.WindowBounds = this.RestoreBounds; sessionSettings.WindowBounds = this.RestoreBounds;
sessionSettings.SplitterPosition = leftColumn.Width.Value / (leftColumn.Width.Value + rightColumn.Width.Value); //todo
if (topPane.Visibility == Visibility.Visible) //sessionSettings.SplitterPosition = leftColumn.Width.Value / (leftColumn.Width.Value + rightColumn.Width.Value);
sessionSettings.TopPaneSplitterPosition = topPaneRow.Height.Value / (topPaneRow.Height.Value + textViewRow.Height.Value); //if (topPane.Visibility == Visibility.Visible)
if (bottomPane.Visibility == Visibility.Visible) // sessionSettings.TopPaneSplitterPosition = topPaneRow.Height.Value / (topPaneRow.Height.Value + textViewRow.Height.Value);
sessionSettings.BottomPaneSplitterPosition = bottomPaneRow.Height.Value / (bottomPaneRow.Height.Value + textViewRow.Height.Value); //if (bottomPane.Visibility == Visibility.Visible)
// sessionSettings.BottomPaneSplitterPosition = bottomPaneRow.Height.Value / (bottomPaneRow.Height.Value + textViewRow.Height.Value);
sessionSettings.Save(); sessionSettings.Save();
} }
@ -1048,95 +1043,19 @@ namespace ICSharpCode.ILSpy
#region Top/Bottom Pane management #region Top/Bottom Pane management
/// <summary> public void ShowInNewPane(string title, object content, PanePosition panePosition, string toolTip = null)
/// 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 ShowInTopPane(string title, object content)
{
topPaneRow.MinHeight = 100;
if (sessionSettings.TopPaneSplitterPosition > 0 && sessionSettings.TopPaneSplitterPosition < 1) {
//Ensure all 3 blocks are in fair conditions
NormalizePaneRowHeightValues(bottomPaneRow, textViewRow);
textViewRow.Height = new GridLength(1 - sessionSettings.TopPaneSplitterPosition, GridUnitType.Star);
topPaneRow.Height = new GridLength(sessionSettings.TopPaneSplitterPosition, GridUnitType.Star);
}
topPane.Title = title;
if (topPane.Content != content) {
IPane pane = topPane.Content as IPane;
if (pane != null)
pane.Closed();
topPane.Content = content;
}
topPane.Visibility = Visibility.Visible;
}
void TopPane_CloseButtonClicked(object sender, EventArgs e)
{
sessionSettings.TopPaneSplitterPosition = topPaneRow.Height.Value / (topPaneRow.Height.Value + textViewRow.Height.Value);
topPaneRow.MinHeight = 0;
topPaneRow.Height = new GridLength(0);
topPane.Visibility = Visibility.Collapsed;
IPane pane = topPane.Content as IPane;
topPane.Content = null;
if (pane != null)
pane.Closed();
}
public void ShowInBottomPane(string title, object content)
{ {
bottomPaneRow.MinHeight = 100; if (panePosition == PanePosition.Document) {
if (sessionSettings.BottomPaneSplitterPosition > 0 && sessionSettings.BottomPaneSplitterPosition < 1) { var layoutDocument = new LayoutDocument() { Title = title, Content = content, ToolTip = toolTip, CanClose = true };
//Ensure all 3 blocks are in fair conditions var documentPane = this.DockManager.Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
NormalizePaneRowHeightValues(topPaneRow, textViewRow); documentPane.Children.Add(layoutDocument);
} else {
textViewRow.Height = new GridLength(1 - sessionSettings.BottomPaneSplitterPosition, GridUnitType.Star); var layoutAnchorable = new LayoutAnchorable() { Title = title, Content = content, ToolTip = toolTip, CanClose = true, CanHide = true };
bottomPaneRow.Height = new GridLength(sessionSettings.BottomPaneSplitterPosition, GridUnitType.Star); var documentPane = this.DockManager.Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
} Docking.DockingHelper.DockHorizontal(layoutAnchorable, documentPane, new GridLength(200), panePosition == PanePosition.Top);
bottomPane.Title = title;
if (bottomPane.Content != content) {
IPane pane = bottomPane.Content as IPane;
if (pane != null)
pane.Closed();
bottomPane.Content = content;
} }
bottomPane.Visibility = Visibility.Visible;
} }
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 #endregion
public void UnselectAll() public void UnselectAll()

9
ILSpy/Properties/Resources.Designer.cs generated

@ -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> /// <summary>
/// Looks up a localized string similar to Decompiling.... /// Looks up a localized string similar to Decompiling....
/// </summary> /// </summary>

3
ILSpy/Properties/Resources.resx

@ -766,4 +766,7 @@ Are you sure you want to continue?</value>
<data name="Assembly" xml:space="preserve"> <data name="Assembly" xml:space="preserve">
<value>Assembly</value> <value>Assembly</value>
</data> </data>
<data name="DecompileToNewPanel" xml:space="preserve">
<value>Decompile to new tab</value>
</data>
</root> </root>

2
ILSpy/Search/SearchPane.cs

@ -112,7 +112,7 @@ namespace ICSharpCode.ILSpy
public void Show() public void Show()
{ {
if (!IsVisible) { if (!IsVisible) {
MainWindow.Instance.ShowInTopPane(Properties.Resources.SearchPane_Search, this); MainWindow.Instance.ShowInNewPane(Properties.Resources.SearchPane_Search, this, PanePosition.Top);
if (runSearchOnNextShow) { if (runSearchOnNextShow) {
runSearchOnNextShow = false; runSearchOnNextShow = false;
StartSearch(this.SearchTerm); StartSearch(this.SearchTerm);

91
ILSpy/themes/generic.xaml

@ -10,7 +10,7 @@
Displays an up arrow or down arrow in the column header when the grid is sorted using that column. Displays an up arrow or down arrow in the column header when the grid is sorted using that column.
--> -->
<controls:ColumnSortDirectionToVisibilityConverter x:Key="ColumnSortDirectionToVisibilityConverter"/> <controls:ColumnSortDirectionToVisibilityConverter x:Key="ColumnSortDirectionToVisibilityConverter"/>
<DataTemplate x:Key="{ComponentResourceKey {x:Type controls:SortableGridViewColumn}, ColumnHeaderTemplate}"> <DataTemplate x:Key="{ComponentResourceKey {x:Type controls:SortableGridViewColumn}, ColumnHeaderTemplate}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Center" Text="{Binding}"/> <TextBlock HorizontalAlignment="Center" Text="{Binding}"/>
@ -26,93 +26,4 @@
Data = "M 5,5 L 10,10 L 15,5 L 5,5"/> Data = "M 5,5 L 10,10 L 15,5 L 5,5"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
<SolidColorBrush x:Key="paneBorder" Color="#828790" />
<!-- DockedPane -->
<Style TargetType="{x:Type controls:DockedPane}">
<Style.Resources>
<Style x:Key="CloseButtonStyle" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="{controls:ControlColor 243}" Offset="0"/>
<GradientStop Color="{controls:ControlColor 235}" Offset="0.5"/>
<GradientStop Color="{controls:ControlColor 221}" Offset="0.5"/>
<GradientStop Color="{controls:ControlColor 205}" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<SolidColorBrush Color="{controls:ControlColor 150}"/>
</Setter.Value>
</Setter>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="4"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border SnapsToDevicePixels="true" x:Name="buttonBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2" />
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="buttonBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="{controls:ControlColor 250, Highlight=0.3}" Offset="0"/>
<GradientStop Color="{controls:ControlColor 224, Highlight=0.4}" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="buttonBorder">
<Setter.Value>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="{controls:ControlColor 224}" Offset="0"/>
<GradientStop Color="{controls:ControlColor 248}" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:DockedPane}">
<Border BorderThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness}" BorderBrush="{StaticResource paneBorder}">
<DockPanel>
<Border BorderThickness="0,0,0,0" BorderBrush="{StaticResource paneBorder}"
Background="{DynamicResource {x:Static SystemColors.InactiveCaptionBrushKey}}" DockPanel.Dock="Top">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{TemplateBinding Title}" Margin="3,0"
Foreground="{DynamicResource {x:Static SystemColors.InactiveCaptionTextBrushKey}}" VerticalAlignment="Center"/>
<Button x:Name="PART_Close" Grid.Column="2" VerticalAlignment="Center" Width="16" Height="16" DockPanel.Dock="Right" Style="{DynamicResource CloseButtonStyle}" ToolTip="Close" Margin="1">
<Path x:Name="Path" Stretch="Fill" StrokeThickness="0.5" Stroke="#FF333333" Fill="#FF969696" Data="F1 M 0,1.3333L 1.33333,0L 4,2.6666L 6.6666,0 8,1.3333L 5.3333,4L 8,6.6666L 6.6666,8L 4,5.3333L 1.3333,8L 0,6.6666L 2.6666,4L 0,1.3333 Z " HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Button>
</Grid>
</Border>
<ContentPresenter Content="{TemplateBinding Content}" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Control.BorderBrush" Value="{StaticResource paneBorder}" />
</Style>
</ResourceDictionary> </ResourceDictionary>
Loading…
Cancel
Save