From f687b0fc769d6aebf2f4c14cb100648e426e265b Mon Sep 17 00:00:00 2001 From: Eusebiu Marcu Date: Sat, 5 Mar 2011 18:06:36 +0200 Subject: [PATCH] Use MEF for debugger controls; Modify the export command attribute for menuitems. --- .../AvalonEdit/IconBarMargin.cs | 2 ++ .../AvalonEdit/TextMarkerService.cs | 18 +++++++----- Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj | 3 ++ ILSpy/App.xaml.cs | 1 + ILSpy/Commands/DebuggerCommands.cs | 8 ++++++ ILSpy/ExportCommandAttribute.cs | 9 ++++++ ILSpy/MainWindow.xaml.cs | 5 +++- ILSpy/TextView/DecompilerTextView.cs | 28 ++++++++++++------- 8 files changed, 56 insertions(+), 18 deletions(-) diff --git a/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs b/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs index f87bf6c51..915bd7e0d 100644 --- a/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs +++ b/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel.Composition; using System.Windows; using System.Windows.Input; using System.Windows.Media; @@ -17,6 +18,7 @@ using Mono.Cecil; namespace ILSpy.Debugger.AvalonEdit { + [Export("IconMargin"), PartCreationPolicy(CreationPolicy.Shared)] public class IconBarMargin : AbstractMargin, IDisposable { public IconBarMargin() diff --git a/Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs b/Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs index 7df2da927..2e7191f32 100644 --- a/Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs +++ b/Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel.Composition; using System.Linq; using System.Windows; using System.Windows.Media; @@ -18,20 +19,23 @@ namespace ILSpy.Debugger.AvalonEdit /// /// Handles the text markers for a code editor. /// + [Export("TextMarkerService"), PartCreationPolicy(CreationPolicy.Shared)] public sealed class TextMarkerService : DocumentColorizingTransformer, IBackgroundRenderer, ITextMarkerService { - readonly TextEditor codeEditor; + TextEditor codeEditor; + TextSegmentCollection markers = new TextSegmentCollection(); - public TextMarkerService(TextEditor codeEditor) - { - if (codeEditor == null) - throw new ArgumentNullException("codeEditor"); - this.codeEditor = codeEditor; - + public TextMarkerService() + { BookmarkManager.Added += new BookmarkEventHandler(BookmarkManager_Added); BookmarkManager.Removed += new BookmarkEventHandler(BookmarkManager_Removed); } + + public TextEditor CodeEditor { + get { return codeEditor; } + set { codeEditor = value; } + } void BookmarkManager_Removed(object sender, BookmarkEventArgs e) { diff --git a/Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj b/Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj index 9888ae8d5..dcc668a3a 100644 --- a/Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj +++ b/Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj @@ -38,6 +38,9 @@ 3.0 + + 4.0 + 3.5 diff --git a/ILSpy/App.xaml.cs b/ILSpy/App.xaml.cs index 9f9cac6eb..168cfb4c1 100644 --- a/ILSpy/App.xaml.cs +++ b/ILSpy/App.xaml.cs @@ -46,6 +46,7 @@ namespace ICSharpCode.ILSpy var catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(typeof(App).Assembly)); catalog.Catalogs.Add(new DirectoryCatalog(".", "*.Plugin.dll")); + catalog.Catalogs.Add(new DirectoryCatalog(".", "*.Debugger.dll")); compositionContainer = new CompositionContainer(catalog); diff --git a/ILSpy/Commands/DebuggerCommands.cs b/ILSpy/Commands/DebuggerCommands.cs index c2e082630..f1853bba8 100644 --- a/ILSpy/Commands/DebuggerCommands.cs +++ b/ILSpy/Commands/DebuggerCommands.cs @@ -104,6 +104,9 @@ namespace ICSharpCode.ILSpy.Commands var items = menuItems.OfType().Where(m => (m.Header as string) == "_Debugger"); foreach (var item in items.First().Items.OfType()) { string header = (string)item.Header; + + if (header.StartsWith("Remove")) continue; + if (header.StartsWith("Attach") || header.StartsWith("Debug")) item.IsEnabled = enable; else @@ -165,6 +168,7 @@ namespace ICSharpCode.ILSpy.Commands MenuIcon = "ILSpy.Debugger;component/Images/ContinueDebugging.png", MenuCategory = "Debugger1", Header = "Continue debugging", + IsEnabled = false, MenuOrder = 1)] internal sealed class ContinueDebuggingCommand : DebuggerCommands { @@ -179,6 +183,7 @@ namespace ICSharpCode.ILSpy.Commands MenuIcon = "ILSpy.Debugger;component/Images/StepInto.png", MenuCategory = "Debugger1", Header = "Step into", + IsEnabled = false, MenuOrder = 2)] internal sealed class StepIntoCommand : DebuggerCommands { @@ -193,6 +198,7 @@ namespace ICSharpCode.ILSpy.Commands MenuIcon = "ILSpy.Debugger;component/Images/StepOver.png", MenuCategory = "Debugger1", Header = "Step over", + IsEnabled = false, MenuOrder = 3)] internal sealed class StepOverCommand : DebuggerCommands { @@ -207,6 +213,7 @@ namespace ICSharpCode.ILSpy.Commands MenuIcon = "ILSpy.Debugger;component/Images/StepOut.png", MenuCategory = "Debugger1", Header = "Step out", + IsEnabled = false, MenuOrder = 4)] internal sealed class StepOutCommand : DebuggerCommands { @@ -220,6 +227,7 @@ namespace ICSharpCode.ILSpy.Commands [ExportMainMenuCommand(Menu = "_Debugger", MenuCategory = "Debugger1", Header = "_Detach from running application", + IsEnabled = false, MenuOrder = 5)] internal sealed class DetachCommand : DebuggerCommands { diff --git a/ILSpy/ExportCommandAttribute.cs b/ILSpy/ExportCommandAttribute.cs index 54e9f67b6..8ca1ffb0c 100644 --- a/ILSpy/ExportCommandAttribute.cs +++ b/ILSpy/ExportCommandAttribute.cs @@ -42,6 +42,8 @@ namespace ICSharpCode.ILSpy string Menu { get; } string MenuCategory { get; } + bool IsEnabled { get; } + double MenuOrder { get; } } @@ -49,6 +51,8 @@ namespace ICSharpCode.ILSpy [AttributeUsage(AttributeTargets.Class, AllowMultiple=false)] public class ExportMainMenuCommandAttribute : ExportAttribute { + bool isEnabled = true; + public ExportMainMenuCommandAttribute() : base("MainMenuCommand", typeof(ICommand)) { @@ -58,6 +62,11 @@ namespace ICSharpCode.ILSpy public string Header { get; set; } public string Menu { get; set; } public string MenuCategory { get; set; } + + public bool IsEnabled { + get { return isEnabled; } + set { isEnabled = value; } + } public double MenuOrder { get; set; } } #endregion diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 94c4ee61d..684abcbce 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -176,6 +176,9 @@ namespace ICSharpCode.ILSpy Source = Images.LoadImage(entry.Value, entry.Metadata.MenuIcon) }; } + + menuItem.IsEnabled = entry.Metadata.IsEnabled; + topLevelMenuItem.Items.Add(menuItem); } } @@ -421,7 +424,7 @@ namespace ICSharpCode.ILSpy void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e) { - if (!System.Diagnostics.Debugger.IsAttached) { + if (!DebuggerService.CurrentDebugger.IsDebugging) { e.Handled = true; var path = GetPathForNode(treeView.SelectedItem as SharpTreeNode); ShowAssemblyList(assemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName)); diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 8939dcfaf..586bc26fd 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -65,8 +65,11 @@ namespace ICSharpCode.ILSpy.TextView DefinitionLookup definitionLookup; CancellationTokenSource currentCancellationTokenSource; - IconBarMargin iconMargin; - TextMarkerService textMarkerService; + [Import("IconMargin")] + IconBarMargin iconMargin = null; + + [Import("TextMarkerService")] + TextMarkerService textMarkerService = null; #region Constructor public DecompilerTextView() @@ -82,6 +85,7 @@ namespace ICSharpCode.ILSpy.TextView }); InitializeComponent(); + this.referenceElementGenerator = new ReferenceElementGenerator(this.JumpToReference, this.IsLink); textEditor.TextArea.TextView.ElementGenerators.Add(referenceElementGenerator); this.uiElementGenerator = new UIElementGenerator(); @@ -90,19 +94,23 @@ namespace ICSharpCode.ILSpy.TextView textEditor.TextArea.TextView.MouseHover += TextViewMouseHover; textEditor.TextArea.TextView.MouseHoverStopped += TextViewMouseHoverStopped; + // wire the events + TextEditorWeakEventManager.MouseHover.AddListener(textEditor, TextEditorListener.Instance); + TextEditorWeakEventManager.MouseHoverStopped.AddListener(textEditor, TextEditorListener.Instance); + TextEditorWeakEventManager.MouseDown.AddListener(textEditor, TextEditorListener.Instance); + textEditor.TextArea.TextView.VisualLinesChanged += (s, e) => iconMargin.InvalidateVisual(); + + this.Loaded += new RoutedEventHandler(DecompilerTextView_Loaded); + } + + void DecompilerTextView_Loaded(object sender, RoutedEventArgs e) + { // add marker service & margin - textMarkerService = new TextMarkerService(textEditor); + textMarkerService.CodeEditor = textEditor; textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService); textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService); - iconMargin = new IconBarMargin(); textEditor.TextArea.LeftMargins.Add(iconMargin); - - // wire the mouse events - TextEditorWeakEventManager.MouseHover.AddListener(textEditor, TextEditorListener.Instance); - TextEditorWeakEventManager.MouseHoverStopped.AddListener(textEditor, TextEditorListener.Instance); - TextEditorWeakEventManager.MouseDown.AddListener(textEditor, TextEditorListener.Instance); - textEditor.TextArea.TextView.VisualLinesChanged += (s, e) => iconMargin.InvalidateVisual(); } #endregion