From 4489dd82893aaaf6db2b14c69520e64a9eb767ba Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 30 Apr 2011 23:01:34 +0200 Subject: [PATCH] Create closeable pane for the analyzer. --- ILSpy/AnalyzerTreeView.cs | 83 +++++++++++++ ILSpy/ContextMenuEntry.cs | 4 +- ILSpy/Controls/DockedPane.cs | 117 ++++++++++++++++++ ILSpy/ILSpy.csproj | 4 + ILSpy/MainWindow.xaml | 30 +++-- ILSpy/MainWindow.xaml.cs | 78 +++++++----- ILSpy/SessionSettings.cs | 11 +- .../Analyzer/AnalyzeContextMenuEntry.cs | 10 +- ILSpy/themes/generic.xaml | 90 +++++++++++++- 9 files changed, 375 insertions(+), 52 deletions(-) create mode 100644 ILSpy/AnalyzerTreeView.cs create mode 100644 ILSpy/Controls/DockedPane.cs diff --git a/ILSpy/AnalyzerTreeView.cs b/ILSpy/AnalyzerTreeView.cs new file mode 100644 index 000000000..4f60498f7 --- /dev/null +++ b/ILSpy/AnalyzerTreeView.cs @@ -0,0 +1,83 @@ +// 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.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; + +using ICSharpCode.ILSpy.TreeNodes.Analyzer; +using ICSharpCode.TreeView; + +namespace ICSharpCode.ILSpy +{ + /// + /// Analyzer tree view. + /// + public partial class AnalyzerTreeView : SharpTreeView + { + static AnalyzerTreeView instance; + + public static AnalyzerTreeView Instance { + get { + if (instance == null) { + App.Current.VerifyAccess(); + instance = new AnalyzerTreeView(); + } + return instance; + } + } + + private AnalyzerTreeView() + { + this.ShowRoot = false; + this.Root = new AnalyzerTreeNode { Language = MainWindow.Instance.CurrentLanguage }; + ContextMenuProvider.Add(this); + } + + public void Show() + { + if (!IsVisible) + MainWindow.Instance.ShowInBottomPane("Analyzer", this); + } + + public void Show(AnalyzerTreeNode node) + { + Show(); + + node.IsExpanded = true; + this.Root.Children.Add(node); + this.SelectedItem = node; + this.FocusNode(node); + } + } + + [ExportMainMenuCommand(Menu = "_View", Header = "_Analyzer", MenuCategory = "ShowPane", MenuOrder = 100)] + sealed class ShowAnalyzerCommand : SimpleCommand + { + public override void Execute(object parameter) + { + AnalyzerTreeView.Instance.Show(); + } + } +} \ No newline at end of file diff --git a/ILSpy/ContextMenuEntry.cs b/ILSpy/ContextMenuEntry.cs index 1b50ab88a..f3a6e8b03 100644 --- a/ILSpy/ContextMenuEntry.cs +++ b/ILSpy/ContextMenuEntry.cs @@ -84,8 +84,10 @@ namespace ICSharpCode.ILSpy void treeView_ContextMenuOpening(object sender, ContextMenuEventArgs e) { SharpTreeNode[] selectedNodes = treeView.GetTopLevelSelection().ToArray(); - if (selectedNodes.Length == 0) + if (selectedNodes.Length == 0) { + e.Handled = true; // don't show the menu return; + } ContextMenu menu = new ContextMenu(); foreach (var category in entries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.Category)) { if (menu.Items.Count > 0) { diff --git a/ILSpy/Controls/DockedPane.cs b/ILSpy/Controls/DockedPane.cs new file mode 100644 index 000000000..00eb8afc8 --- /dev/null +++ b/ILSpy/Controls/DockedPane.cs @@ -0,0 +1,117 @@ +// 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; +using System.Windows.Markup; +using System.Windows.Media; + +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(System.Windows.Input.KeyEventArgs e) + { + base.OnKeyDown(e); + if (!e.Handled && e.Key == Key.F4 && e.KeyboardDevice.Modifiers == ModifierKeys.Control) { + if (CloseButtonClicked != null) + CloseButtonClicked(this, e); + e.Handled = true; + } + } + } + + [MarkupExtensionReturnType(typeof(Color))] + class ControlColor : MarkupExtension + { + float val; + + /// + /// Amount of highlight (0..1) + /// + public float Highlight { get; set; } + + /// + /// val: Color value in the range 105..255. + /// + public ControlColor(float val) + { + if (!(val >= 105 && val <= 255)) + throw new ArgumentOutOfRangeException("val"); + this.val = val; + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + if (val > 227) { + return Interpolate(227, SystemColors.ControlLightColor, 255, SystemColors.ControlLightLightColor); + } else if (val > 160) { + return Interpolate(160, SystemColors.ControlDarkColor, 227, SystemColors.ControlLightColor); + } else { + return Interpolate(105, SystemColors.ControlDarkDarkColor, 160, SystemColors.ControlDarkColor); + } + } + + Color Interpolate(float v1, Color c1, float v2, Color c2) + { + float v = (val - v1) / (v2 - v1); + Color c = c1 * (1 - v) + c2 * v; + return c * (1 - Highlight) + SystemColors.HighlightColor * Highlight; + } + } +} diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 75eb44e71..5bde4a3cb 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -84,6 +84,9 @@ + + Code + Code App.xaml @@ -94,6 +97,7 @@ + DecompilerSettingsPanel.xaml Code diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index d46602635..28dd2e537 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -44,7 +44,6 @@ - @@ -115,16 +114,18 @@ VerticalAlignment="Stretch" BorderBrush="Transparent" /> - + + + - + @@ -136,7 +137,7 @@ - + + Visibility="{Binding Visibility, ElementName=bottomPane}" /> + + + + + - - - - + diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 9e4de6143..abcee2b2b 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -81,8 +81,7 @@ namespace ICSharpCode.ILSpy InitializeComponent(); App.CompositionContainer.ComposeParts(this); - Grid.SetRow(decompilerTextView, 1); - rightPane.Children.Add(decompilerTextView); + mainPane.Content = decompilerTextView; if (sessionSettings.SplitterPosition > 0 && sessionSettings.SplitterPosition < 1) { leftColumn.Width = new GridLength(sessionSettings.SplitterPosition, GridUnitType.Star); @@ -93,7 +92,6 @@ namespace ICSharpCode.ILSpy InitMainMenu(); InitToolbar(); ContextMenuProvider.Add(treeView); - ContextMenuProvider.Add(analyzerTree); this.Loaded += new RoutedEventHandler(MainWindow_Loaded); } @@ -601,22 +599,6 @@ namespace ICSharpCode.ILSpy #endregion - #region Analyzer - public void AddToAnalyzer(AnalyzerTreeNode node) - { - if (analyzerTree.Root == null) - analyzerTree.Root = new AnalyzerTreeNode { Language = sessionSettings.FilterSettings.Language }; - - if (!showAnalyzer.IsChecked) - showAnalyzer.IsChecked = true; - - node.IsExpanded = true; - analyzerTree.Root.Children.Add(node); - analyzerTree.SelectedItem = node; - analyzerTree.FocusNode(node); - } - #endregion - protected override void OnStateChanged(EventArgs e) { base.OnStateChanged(e); @@ -632,25 +614,61 @@ namespace ICSharpCode.ILSpy sessionSettings.ActiveTreeViewPath = GetPathForNode(treeView.SelectedItem as SharpTreeNode); sessionSettings.WindowBounds = this.RestoreBounds; sessionSettings.SplitterPosition = leftColumn.Width.Value / (leftColumn.Width.Value + rightColumn.Width.Value); - if (showAnalyzer.IsChecked) - sessionSettings.AnalyzerSplitterPosition = analyzerRow.Height.Value / (analyzerRow.Height.Value + textViewRow.Height.Value); + if (topPane.Visibility == Visibility.Visible) + sessionSettings.BottomPaneSplitterPosition = topPaneRow.Height.Value / (topPaneRow.Height.Value + textViewRow.Height.Value); + if (bottomPane.Visibility == Visibility.Visible) + sessionSettings.BottomPaneSplitterPosition = bottomPaneRow.Height.Value / (bottomPaneRow.Height.Value + textViewRow.Height.Value); sessionSettings.Save(); } - void ShowAnalyzer_Checked(object sender, RoutedEventArgs e) + #region Top/Bottom Pane management + public void ShowInTopPane(string title, object content) + { + topPaneRow.MinHeight = 100; + if (sessionSettings.TopPaneSplitterPosition > 0 && sessionSettings.TopPaneSplitterPosition < 1) { + textViewRow.Height = new GridLength(1 - sessionSettings.TopPaneSplitterPosition, GridUnitType.Star); + topPaneRow.Height = new GridLength(sessionSettings.TopPaneSplitterPosition, GridUnitType.Star); + } + topPane.Title = title; + topPane.Content = content; + topPane.Visibility = Visibility.Visible; + + FrameworkElement fe = content as FrameworkElement; + if (fe != null) + fe.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); + } + + 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; + } + + public void ShowInBottomPane(string title, object content) { - analyzerRow.MinHeight = 100; - if (sessionSettings.AnalyzerSplitterPosition > 0 && sessionSettings.AnalyzerSplitterPosition < 1) { - textViewRow.Height = new GridLength(1 - sessionSettings.AnalyzerSplitterPosition, GridUnitType.Star); - analyzerRow.Height = new GridLength(sessionSettings.AnalyzerSplitterPosition, GridUnitType.Star); + bottomPaneRow.MinHeight = 100; + if (sessionSettings.BottomPaneSplitterPosition > 0 && sessionSettings.BottomPaneSplitterPosition < 1) { + textViewRow.Height = new GridLength(1 - sessionSettings.BottomPaneSplitterPosition, GridUnitType.Star); + bottomPaneRow.Height = new GridLength(sessionSettings.BottomPaneSplitterPosition, GridUnitType.Star); } + bottomPane.Title = title; + bottomPane.Content = content; + bottomPane.Visibility = Visibility.Visible; + + FrameworkElement fe = content as FrameworkElement; + if (fe != null) + fe.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); } - void ShowAnalyzer_Unchecked(object sender, RoutedEventArgs e) + void BottomPane_CloseButtonClicked(object sender, EventArgs e) { - sessionSettings.AnalyzerSplitterPosition = analyzerRow.Height.Value / (analyzerRow.Height.Value + textViewRow.Height.Value); - analyzerRow.MinHeight = 0; - analyzerRow.Height = new GridLength(0); + sessionSettings.BottomPaneSplitterPosition = bottomPaneRow.Height.Value / (bottomPaneRow.Height.Value + textViewRow.Height.Value); + bottomPaneRow.MinHeight = 0; + bottomPaneRow.Height = new GridLength(0); + bottomPane.Visibility = Visibility.Collapsed; } + #endregion } } diff --git a/ILSpy/SessionSettings.cs b/ILSpy/SessionSettings.cs index 11d8346d3..e8ce98f48 100644 --- a/ILSpy/SessionSettings.cs +++ b/ILSpy/SessionSettings.cs @@ -49,7 +49,8 @@ namespace ICSharpCode.ILSpy this.WindowState = FromString((string)doc.Element("WindowState"), WindowState.Normal); this.WindowBounds = FromString((string)doc.Element("WindowBounds"), new Rect(10, 10, 750, 550)); this.SplitterPosition = FromString((string)doc.Element("SplitterPosition"), 0.4); - this.AnalyzerSplitterPosition = FromString((string)doc.Element("AnalyzerSplitterPosition"), 0.3); + this.TopPaneSplitterPosition = FromString((string)doc.Element("TopPaneSplitterPosition"), 0.3); + this.BottomPaneSplitterPosition = FromString((string)doc.Element("BottomPaneSplitterPosition"), 0.3); } public event PropertyChangedEventHandler PropertyChanged; @@ -68,8 +69,11 @@ namespace ICSharpCode.ILSpy public WindowState WindowState = WindowState.Normal; public Rect WindowBounds; + /// + /// position of the left/right splitter + /// public double SplitterPosition; - public double AnalyzerSplitterPosition; + public double TopPaneSplitterPosition, BottomPaneSplitterPosition; public void Save() { @@ -84,7 +88,8 @@ namespace ICSharpCode.ILSpy doc.Add(new XElement("WindowState", ToString(this.WindowState))); doc.Add(new XElement("WindowBounds", ToString(this.WindowBounds))); doc.Add(new XElement("SplitterPosition", ToString(this.SplitterPosition))); - doc.Add(new XElement("AnalyzerSplitterPosition", ToString(this.AnalyzerSplitterPosition))); + doc.Add(new XElement("TopPaneSplitterPosition", ToString(this.TopPaneSplitterPosition))); + doc.Add(new XElement("BottomPaneSplitterPosition", ToString(this.BottomPaneSplitterPosition))); ILSpySettings.SaveSettings(doc); } diff --git a/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs b/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs index 9af10e581..6221bcc37 100644 --- a/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs +++ b/ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs @@ -52,19 +52,19 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer foreach (IMemberTreeNode node in selectedNodes) { TypeDefinition type = node.Member as TypeDefinition; if (type != null) - MainWindow.Instance.AddToAnalyzer(new AnalyzedTypeTreeNode(type)); + AnalyzerTreeView.Instance.Show(new AnalyzedTypeTreeNode(type)); FieldDefinition field = node.Member as FieldDefinition; if (field != null) - MainWindow.Instance.AddToAnalyzer(new AnalyzedFieldTreeNode(field)); + AnalyzerTreeView.Instance.Show(new AnalyzedFieldTreeNode(field)); MethodDefinition method = node.Member as MethodDefinition; if (method != null) - MainWindow.Instance.AddToAnalyzer(new AnalyzedMethodTreeNode(method)); + AnalyzerTreeView.Instance.Show(new AnalyzedMethodTreeNode(method)); var propertyAnalyzer = Analyzer.AnalyzedPropertyTreeNode.TryCreateAnalyzer(node.Member); if (propertyAnalyzer != null) - MainWindow.Instance.AddToAnalyzer(propertyAnalyzer); + AnalyzerTreeView.Instance.Show(propertyAnalyzer); var eventAnalyzer = Analyzer.AnalyzedEventTreeNode.TryCreateAnalyzer(node.Member); if (eventAnalyzer != null) - MainWindow.Instance.AddToAnalyzer(eventAnalyzer); + AnalyzerTreeView.Instance.Show(eventAnalyzer); } } } diff --git a/ILSpy/themes/generic.xaml b/ILSpy/themes/generic.xaml index 5af30034d..ee552e445 100644 --- a/ILSpy/themes/generic.xaml +++ b/ILSpy/themes/generic.xaml @@ -2,6 +2,10 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls" > + + + + @@ -23,7 +27,87 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file