2021-09-20 18:20:01 +02:00

171 lines
5.7 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Input;
using dnSpy.Contracts.Controls;
using dnSpy.Contracts.Extension;
using dnSpy.Contracts.Menus;
using dnSpy.Contracts.MVVM;
using dnSpy.Contracts.ToolWindows;
using dnSpy.Contracts.ToolWindows.App;
// Adds a tool window and a command that will show it. The command is added to the View menu and a
// keyboard shortcut is added to the main window. Keyboard shortcut Ctrl+Alt+Z shows the tool window.
namespace Example2.Extension {
// Adds the 'OpenToolWindow' command to the main window and sets keyboard shortcut to Ctrl+Alt+Z
[ExportAutoLoaded]
sealed class ToolWindowLoader : IAutoLoaded {
public static readonly RoutedCommand OpenToolWindow = new RoutedCommand("OpenToolWindow", typeof(ToolWindowLoader));
[ImportingConstructor]
ToolWindowLoader(IWpfCommandService wpfCommandService, IDsToolWindowService toolWindowService) {
var cmds = wpfCommandService.GetCommands(ControlConstants.GUID_MAINWINDOW);
cmds.Add(OpenToolWindow, new RelayCommand(a => toolWindowService.Show(ToolWindowContentImpl.THE_GUID)));
cmds.Add(OpenToolWindow, ModifierKeys.Control | ModifierKeys.Alt, Key.Z);
}
}
// Adds a menu item to the View menu to show the tool window
[ExportMenuItem(OwnerGuid = MenuConstants.APP_MENU_VIEW_GUID, Header = "Extension Tool Window", InputGestureText = "Ctrl+Alt+Z", Group = MenuConstants.GROUP_APP_MENU_VIEW_WINDOWS, Order = 2000)]
sealed class ViewCommand1 : MenuItemCommand {
ViewCommand1()
: base(ToolWindowLoader.OpenToolWindow) {
}
}
// Dummy dependency "needed" by MainToolWindowContentProvider
[Export]
sealed class DeppDep {
public void Hello() {
}
}
// Called by dnSpy to create the tool window
[Export(typeof(IToolWindowContentProvider))]
sealed class MainToolWindowContentProvider : IToolWindowContentProvider {
// Caches the created tool window
ToolWindowContentImpl ToolWindowContent => myToolWindowContent ??= new ToolWindowContentImpl();
ToolWindowContentImpl? myToolWindowContent;
// Add any deps to the constructor if needed, else remove the constructor
[ImportingConstructor]
MainToolWindowContentProvider(DeppDep deppDep) => deppDep.Hello();
// Lets dnSpy know which tool windows it can create and their default locations
public IEnumerable<ToolWindowContentInfo> ContentInfos {
get { yield return new ToolWindowContentInfo(ToolWindowContentImpl.THE_GUID, ToolWindowContentImpl.DEFAULT_LOCATION, 0, false); }
}
// Called by dnSpy. If it's your tool window guid, return the instance. Make sure it's
// cached since it can be called multiple times.
public ToolWindowContent? GetOrCreate(Guid guid) {
if (guid == ToolWindowContentImpl.THE_GUID)
return ToolWindowContent;
return null;
}
}
sealed class ToolWindowContentImpl : ToolWindowContent {
//TODO: Use your own guid
public static readonly Guid THE_GUID = new Guid("18785447-21A8-41DB-B8AD-0F166AEC0D08");
public const AppToolWindowLocation DEFAULT_LOCATION = AppToolWindowLocation.DefaultHorizontal;
public override Guid Guid => THE_GUID;
public override string Title => "Extension Example";
// This is the object shown in the UI. Return a WPF object or a .NET object with a DataTemplate
public override object? UIObject => toolWindowControl;
// The element inside UIObject that gets the focus when the tool window should be focused.
// If it's not as easy as calling FocusedElement.Focus() to focus it, you must implement
// dnSpy.Contracts.Controls.IFocusable.
public override IInputElement? FocusedElement => toolWindowControl.option1TextBox;
// The element that gets scaled when the user zooms in or out. Return null if zooming isn't
// possible
public override FrameworkElement? ZoomElement => toolWindowControl;
readonly ToolWindowControl toolWindowControl;
readonly ToolWindowVM toolWindowVM;
public ToolWindowContentImpl() {
toolWindowControl = new ToolWindowControl();
toolWindowVM = new ToolWindowVM();
toolWindowControl.DataContext = toolWindowVM;
}
// Gets notified when the content gets hidden, visible, etc. Can be used to tell the view
// model to stop doing stuff when it gets hidden in case it does a lot of work.
public override void OnVisibilityChanged(ToolWindowContentVisibilityEvent visEvent) {
switch (visEvent) {
case ToolWindowContentVisibilityEvent.Added:
toolWindowVM.IsEnabled = true;
break;
case ToolWindowContentVisibilityEvent.Removed:
toolWindowVM.IsEnabled = false;
break;
case ToolWindowContentVisibilityEvent.Visible:
toolWindowVM.IsVisible = true;
break;
case ToolWindowContentVisibilityEvent.Hidden:
toolWindowVM.IsVisible = false;
break;
}
}
}
sealed class ToolWindowVM : ViewModelBase {
public string StringOption1 {
get => stringOption1;
set {
if (stringOption1 != value) {
stringOption1 = value;
OnPropertyChanged(nameof(StringOption1));
}
}
}
string stringOption1 = string.Empty;
public string StringOption2 {
get => stringOption2;
set {
if (stringOption2 != value) {
stringOption2 = value;
OnPropertyChanged(nameof(StringOption2));
}
}
}
string stringOption2 = string.Empty;
public string StringOption3 {
get => stringOption3;
set {
if (stringOption3 != value) {
stringOption3 = value;
OnPropertyChanged(nameof(StringOption3));
}
}
}
string stringOption3 = string.Empty;
public string StringOption4 {
get => stringOption4;
set {
if (stringOption4 != value) {
stringOption4 = value;
OnPropertyChanged(nameof(StringOption4));
}
}
}
string stringOption4 = string.Empty;
public bool IsEnabled { get; set; }
public bool IsVisible { get; set; }
}
}