Browse Source

Refactor window menu composition: simplify by using WPF patterns.

pull/3274/head
tom-englert 9 months ago committed by tom-englert
parent
commit
3b2f44b1f0
  1. 13
      ILSpy/Docking/PaneCollection.cs
  2. 60
      ILSpy/MainWindow.xaml
  3. 2
      ILSpy/Metadata/CorTables/PtrTableTreeNode.cs
  4. 326
      ILSpy/Util/MenuService.cs

13
ILSpy/Docking/PaneCollection.cs

@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -25,10 +26,10 @@ using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Docking namespace ICSharpCode.ILSpy.Docking
{ {
public class PaneCollection<T> : INotifyCollectionChanged, ICollection<T> public class PaneCollection<T> : INotifyCollectionChanged, IList<T>
where T : PaneModel, new() where T : PaneModel, new()
{ {
private ObservableCollection<T> observableCollection = new ObservableCollection<T>(); private readonly ObservableCollection<T> observableCollection = [];
public event NotifyCollectionChangedEventHandler CollectionChanged; public event NotifyCollectionChangedEventHandler CollectionChanged;
@ -46,7 +47,6 @@ namespace ICSharpCode.ILSpy.Docking
item.IsVisible = true; item.IsVisible = true;
item.IsActive = true; item.IsActive = true;
} }
public int Count => observableCollection.Count; public int Count => observableCollection.Count;
public bool IsReadOnly => false; public bool IsReadOnly => false;
public void Clear() => observableCollection.Clear(); public void Clear() => observableCollection.Clear();
@ -55,5 +55,12 @@ namespace ICSharpCode.ILSpy.Docking
public bool Remove(T item) => observableCollection.Remove(item); public bool Remove(T item) => observableCollection.Remove(item);
public IEnumerator<T> GetEnumerator() => observableCollection.GetEnumerator(); public IEnumerator<T> GetEnumerator() => observableCollection.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => observableCollection.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => observableCollection.GetEnumerator();
int IList<T>.IndexOf(T item) => observableCollection.IndexOf(item);
void IList<T>.Insert(int index, T item) => throw new NotImplementedException("Only Add is supported");
void IList<T>.RemoveAt(int index) => observableCollection.RemoveAt(index);
T IList<T>.this[int index] {
get => observableCollection[index];
set => observableCollection[index] = value;
}
} }
} }

60
ILSpy/MainWindow.xaml

@ -1,27 +1,25 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Window <Window x:Class="ICSharpCode.ILSpy.MainWindow"
x:Class="ICSharpCode.ILSpy.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ICSharpCode.ILSpy"
xmlns:tv="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView" xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
xmlns:local="clr-namespace:ICSharpCode.ILSpy" xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:avalondock="https://github.com/Dirkster99/AvalonDock" xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls" xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking" Title="ILSpy"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties" MinWidth="250"
Title="ILSpy" MinHeight="200"
MinWidth="250" UseLayoutRounding="True"
MinHeight="200" TextOptions.TextFormattingMode="Display"
UseLayoutRounding="True" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="500" d:DesignWidth="500"
TextOptions.TextFormattingMode="Display" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="500" d:DesignWidth="500" xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors" xmlns:toms="urn:TomsToolbox"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes" xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
xmlns:toms="urn:TomsToolbox" d:DataContext="{d:DesignInstance local:MainWindowViewModel}">
xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}">
<Window.Resources> <Window.Resources>
<DataTemplate DataType="{x:Type viewModels:TabPageModel}"> <DataTemplate DataType="{x:Type viewModels:TabPageModel}">
@ -78,9 +76,12 @@
<MenuItem Header="{x:Static properties:Resources._File}" Tag="_File" /> <MenuItem Header="{x:Static properties:Resources._File}" Tag="_File" />
<!-- contents of file menu are added using MEF --> <!-- contents of file menu are added using MEF -->
<MenuItem Header="{x:Static properties:Resources._View}" Tag="_View"> <MenuItem Header="{x:Static properties:Resources._View}" Tag="_View">
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" /> <MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True"
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" /> IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" /> <MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True"
IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True"
IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" />
<Separator /> <Separator />
<MenuItem Header="{x:Static properties:Resources.Theme}" ItemsSource="{x:Static themes:ThemeManager.AllThemes}"> <MenuItem Header="{x:Static properties:Resources.Theme}" ItemsSource="{x:Static themes:ThemeManager.AllThemes}">
<MenuItem.ItemContainerStyle> <MenuItem.ItemContainerStyle>
@ -101,9 +102,12 @@
</MenuItem.ItemContainerStyle> </MenuItem.ItemContainerStyle>
</MenuItem> </MenuItem>
<MenuItem Header="{x:Static properties:Resources.UILanguage}"> <MenuItem Header="{x:Static properties:Resources.UILanguage}">
<MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter={x:Null}}" /> <MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True"
<MenuItem Header="English" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=en-US}" /> IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter={x:Null}}" />
<MenuItem Header="中文" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=zh-Hans}" /> <MenuItem Header="English" IsCheckable="True"
IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=en-US}" />
<MenuItem Header="中文" IsCheckable="True"
IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=zh-Hans}" />
</MenuItem> </MenuItem>
</MenuItem> </MenuItem>
<MenuItem Header="{x:Static properties:Resources._Window}" Tag="_Window" /> <MenuItem Header="{x:Static properties:Resources._Window}" Tag="_Window" />

2
ILSpy/Metadata/CorTables/PtrTableTreeNode.cs

@ -112,7 +112,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnHandleClick() public void OnHandleClick()
{ {
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, handlePtr.Handle, protocol: "metadata")); MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, handlePtr.Handle, protocol: "metadata")));
} }
string handleTooltip; string handleTooltip;

326
ILSpy/Util/MenuService.cs

@ -1,9 +1,7 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Input; using System.Windows.Input;
@ -14,6 +12,8 @@ using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
using TomsToolbox.Composition; using TomsToolbox.Composition;
using TomsToolbox.ObservableCollections;
using TomsToolbox.Wpf.Converters;
namespace ICSharpCode.ILSpy.Util namespace ICSharpCode.ILSpy.Util
{ {
@ -21,7 +21,16 @@ namespace ICSharpCode.ILSpy.Util
{ {
public static readonly MenuService Instance = new(); public static readonly MenuService Instance = new();
public void InitMainMenu(Menu mainMenu) private readonly DockWorkspace dockWorkspace = DockWorkspace.Instance;
public void Init(Menu mainMenu, ToolBar toolBar, InputBindingCollection inputBindings)
{
InitMainMenu(mainMenu);
InitWindowMenu(mainMenu, inputBindings);
InitToolbar(toolBar);
}
static void InitMainMenu(Menu mainMenu)
{ {
var mainMenuCommands = App.ExportProvider.GetExports<ICommand, IMainMenuCommandMetadata>("MainMenuCommand"); var mainMenuCommands = App.ExportProvider.GetExports<ICommand, IMainMenuCommandMetadata>("MainMenuCommand");
// Start by constructing the individual flat menus // Start by constructing the individual flat menus
@ -48,10 +57,11 @@ namespace ICSharpCode.ILSpy.Util
} }
else else
{ {
MenuItem menuItem = new MenuItem(); var menuItem = new MenuItem {
menuItem.Command = CommandWrapper.Unwrap(entry.Value); Command = CommandWrapper.Unwrap(entry.Value),
menuItem.Tag = entry.Metadata?.MenuID; Tag = entry.Metadata?.MenuID,
menuItem.Header = ResourceHelper.GetString(entry.Metadata?.Header); Header = ResourceHelper.GetString(entry.Metadata?.Header)
};
if (!string.IsNullOrEmpty(entry.Metadata?.MenuIcon)) if (!string.IsNullOrEmpty(entry.Metadata?.MenuIcon))
{ {
menuItem.Icon = new Image { menuItem.Icon = new Image {
@ -62,7 +72,7 @@ namespace ICSharpCode.ILSpy.Util
} }
menuItem.IsEnabled = entry.Metadata?.IsEnabled ?? false; menuItem.IsEnabled = entry.Metadata?.IsEnabled ?? false;
if (entry.Value is ToggleableCommand toggle) if (entry.Value is ToggleableCommand)
{ {
menuItem.IsCheckable = true; menuItem.IsCheckable = true;
menuItem.SetBinding(MenuItem.IsCheckedProperty, new Binding("IsChecked") { Source = entry.Value, Mode = BindingMode.OneWay }); menuItem.SetBinding(MenuItem.IsCheckedProperty, new Binding("IsChecked") { Source = entry.Value, Mode = BindingMode.OneWay });
@ -75,7 +85,7 @@ namespace ICSharpCode.ILSpy.Util
} }
} }
foreach (var (key, item) in parentMenuItems) foreach (var item in parentMenuItems.Values)
{ {
if (item.Parent == null) if (item.Parent == null)
{ {
@ -83,21 +93,22 @@ namespace ICSharpCode.ILSpy.Util
} }
} }
MenuItem GetOrAddParentMenuItem(string menuID, string resourceKey) MenuItem GetOrAddParentMenuItem(string menuId, string resourceKey)
{ {
if (!parentMenuItems.TryGetValue(menuID, out var parentMenuItem)) if (!parentMenuItems.TryGetValue(menuId, out var parentMenuItem))
{ {
var topLevelMenuItem = mainMenu.Items.OfType<MenuItem>().FirstOrDefault(m => (string)m.Tag == menuID); var topLevelMenuItem = mainMenu.Items.OfType<MenuItem>().FirstOrDefault(m => (string)m.Tag == menuId);
if (topLevelMenuItem == null) if (topLevelMenuItem == null)
{ {
parentMenuItem = new MenuItem(); parentMenuItem = new() {
parentMenuItem.Header = ResourceHelper.GetString(resourceKey); Header = ResourceHelper.GetString(resourceKey),
parentMenuItem.Tag = menuID; Tag = menuId
parentMenuItems.Add(menuID, parentMenuItem); };
parentMenuItems.Add(menuId, parentMenuItem);
} }
else else
{ {
parentMenuItems.Add(menuID, topLevelMenuItem); parentMenuItems.Add(menuId, topLevelMenuItem);
parentMenuItem = topLevelMenuItem; parentMenuItem = topLevelMenuItem;
} }
} }
@ -105,219 +116,45 @@ namespace ICSharpCode.ILSpy.Util
} }
} }
public void InitWindowMenu(Menu mainMenu, InputBindingCollection inputBindings) void InitWindowMenu(Menu mainMenu, InputBindingCollection inputBindings)
{ {
var windowMenuItem = mainMenu.Items.OfType<MenuItem>().First(m => (string)m.Tag == nameof(Properties.Resources._Window)); var windowMenuItem = mainMenu.Items.OfType<MenuItem>().First(m => (string)m.Tag == nameof(Properties.Resources._Window));
var separatorBeforeTools = new Separator(); var defaultItems = windowMenuItem.Items.Cast<Control>().ToArray();
var separatorBeforeDocuments = new Separator();
windowMenuItem.Items.Add(separatorBeforeTools);
windowMenuItem.Items.Add(separatorBeforeDocuments);
var dock = DockWorkspace.Instance;
dock.ToolPanes.CollectionChanged += ToolsChanged; windowMenuItem.Items.Clear();
dock.TabPages.CollectionChanged += TabsChanged;
MessageBus<DockWorkspaceActiveTabPageChangedEventArgs>.Subscribers += ActiveTabPageChanged;
ToolsChanged(dock.ToolPanes, new(NotifyCollectionChangedAction.Reset));
TabsChanged(dock.TabPages, new(NotifyCollectionChangedAction.Reset));
void ToolsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
int endIndex = windowMenuItem.Items.IndexOf(separatorBeforeDocuments);
int startIndex = windowMenuItem.Items.IndexOf(separatorBeforeTools) + 1;
int insertionIndex;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
insertionIndex = Math.Min(endIndex, startIndex + e.NewStartingIndex);
foreach (ToolPaneModel pane in e.NewItems)
{
MenuItem menuItem = CreateMenuItem(pane);
windowMenuItem.Items.Insert(insertionIndex, menuItem);
insertionIndex++;
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (ToolPaneModel pane in e.OldItems)
{
for (int i = endIndex - 1; i >= startIndex; i--)
{
MenuItem item = (MenuItem)windowMenuItem.Items[i];
if (pane == item.Tag)
{
windowMenuItem.Items.RemoveAt(i);
item.Tag = null;
endIndex--;
break;
}
}
}
break;
case NotifyCollectionChangedAction.Replace:
break;
case NotifyCollectionChangedAction.Move:
break;
case NotifyCollectionChangedAction.Reset:
for (int i = endIndex - 1; i >= startIndex; i--)
{
MenuItem item = (MenuItem)windowMenuItem.Items[0];
item.Tag = null;
windowMenuItem.Items.RemoveAt(i);
endIndex--;
}
insertionIndex = endIndex;
foreach (ToolPaneModel pane in dock.ToolPanes)
{
MenuItem menuItem = CreateMenuItem(pane);
windowMenuItem.Items.Insert(insertionIndex, menuItem);
insertionIndex++;
}
break;
}
MenuItem CreateMenuItem(ToolPaneModel pane) var toolItems = dockWorkspace.ToolPanes.ObservableSelect(toolPane => CreateMenuItem(toolPane, inputBindings));
{ var tabItems = dockWorkspace.TabPages.ObservableSelect(tabPage => CreateMenuItem(tabPage, dockWorkspace));
MenuItem menuItem = new MenuItem();
menuItem.Command = pane.AssociatedCommand ?? new ToolPaneCommand(pane.ContentId);
menuItem.Header = pane.Title;
menuItem.Tag = pane;
var shortcutKey = pane.ShortcutKey;
if (shortcutKey != null)
{
inputBindings.Add(new InputBinding(menuItem.Command, shortcutKey));
menuItem.InputGestureText = shortcutKey.GetDisplayStringForCulture(CultureInfo.CurrentUICulture);
}
if (!string.IsNullOrEmpty(pane.Icon))
{
menuItem.Icon = new Image {
Width = 16,
Height = 16,
Source = Images.Load(pane, pane.Icon)
};
}
return menuItem; var allItems = new ObservableCompositeCollection<Control>(defaultItems, [new Separator()], toolItems, [new Separator()], tabItems);
}
}
void TabsChanged(object sender, NotifyCollectionChangedEventArgs e) windowMenuItem.ItemsSource = allItems;
{
int endIndex = windowMenuItem.Items.Count;
int startIndex = windowMenuItem.Items.IndexOf(separatorBeforeDocuments) + 1;
int insertionIndex;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
insertionIndex = Math.Min(endIndex, startIndex + e.NewStartingIndex);
foreach (TabPageModel pane in e.NewItems)
{
MenuItem menuItem = CreateMenuItem(pane);
pane.PropertyChanged += TabPageChanged;
windowMenuItem.Items.Insert(insertionIndex, menuItem);
insertionIndex++;
}
break;
case NotifyCollectionChangedAction.Remove:
foreach (TabPageModel pane in e.OldItems)
{
for (int i = endIndex - 1; i >= startIndex; i--)
{
MenuItem item = (MenuItem)windowMenuItem.Items[i];
if (pane == item.Tag)
{
windowMenuItem.Items.RemoveAt(i);
pane.PropertyChanged -= TabPageChanged;
item.Tag = null;
endIndex--;
break;
}
}
}
break;
case NotifyCollectionChangedAction.Replace:
break;
case NotifyCollectionChangedAction.Move:
break;
case NotifyCollectionChangedAction.Reset:
for (int i = endIndex - 1; i >= startIndex; i--)
{
MenuItem item = (MenuItem)windowMenuItem.Items[i];
windowMenuItem.Items.RemoveAt(i);
((TabPageModel)item.Tag).PropertyChanged -= TabPageChanged;
endIndex--;
}
insertionIndex = endIndex;
foreach (TabPageModel pane in dock.TabPages)
{
MenuItem menuItem = CreateMenuItem(pane);
pane.PropertyChanged += TabPageChanged;
windowMenuItem.Items.Insert(insertionIndex, menuItem);
insertionIndex++;
}
break;
}
MenuItem CreateMenuItem(TabPageModel pane)
{
MenuItem menuItem = new MenuItem();
menuItem.Command = new TabPageCommand(pane);
menuItem.Header = pane.Title.Length > 20 ? pane.Title.Substring(20) + "..." : pane.Title;
menuItem.Tag = pane;
menuItem.IsCheckable = true;
menuItem.IsChecked = menuItem.Tag == dock.ActiveTabPage;
return menuItem;
}
}
void TabPageChanged(object sender, PropertyChangedEventArgs e)
{
var windowMenu = mainMenu.Items.OfType<MenuItem>().First(m => (string)m.Tag == nameof(Properties.Resources._Window));
foreach (MenuItem menuItem in windowMenu.Items.OfType<MenuItem>())
{
if (menuItem.IsCheckable && menuItem.Tag == sender)
{
string title = ((TabPageModel)sender).Title;
menuItem.Header = title.Length > 20 ? title.Substring(0, 20) + "..." : title;
}
}
}
void ActiveTabPageChanged(object sender, EventArgs e)
{
foreach (MenuItem menuItem in windowMenuItem.Items.OfType<MenuItem>())
{
if (menuItem.IsCheckable && menuItem.Tag is TabPageModel)
{
menuItem.IsChecked = menuItem.Tag == dock.ActiveTabPage;
}
}
}
} }
public void InitToolbar(ToolBar toolBar) static void InitToolbar(ToolBar toolBar)
{ {
int navigationPos = 0; int navigationPos = 0;
int openPos = 1; int openPos = 1;
var toolbarCommands = App.ExportProvider.GetExports<ICommand, IToolbarCommandMetadata>("ToolbarCommand"); var toolbarCommandsByTitle = App.ExportProvider.GetExports<ICommand, IToolbarCommandMetadata>("ToolbarCommand")
foreach (var commandGroup in toolbarCommands.OrderBy(c => c.Metadata.ToolbarOrder).GroupBy(c => Properties.Resources.ResourceManager.GetString(c.Metadata.ToolbarCategory))) .OrderBy(c => c.Metadata?.ToolbarOrder)
.GroupBy(c => c.Metadata?.ToolbarCategory);
foreach (var commandGroup in toolbarCommandsByTitle)
{ {
if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Navigation")) if (commandGroup.Key == nameof(Properties.Resources.Navigation))
{ {
foreach (var command in commandGroup) foreach (var command in commandGroup)
{ {
toolBar.Items.Insert(navigationPos++, MakeToolbarItem(command)); toolBar.Items.Insert(navigationPos++, CreateToolbarItem(command));
openPos++; openPos++;
} }
} }
else if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Open")) else if (commandGroup.Key == nameof(Properties.Resources.Open))
{ {
foreach (var command in commandGroup) foreach (var command in commandGroup)
{ {
toolBar.Items.Insert(openPos++, MakeToolbarItem(command)); toolBar.Items.Insert(openPos++, CreateToolbarItem(command));
} }
} }
else else
@ -325,33 +162,76 @@ namespace ICSharpCode.ILSpy.Util
toolBar.Items.Add(new Separator()); toolBar.Items.Add(new Separator());
foreach (var command in commandGroup) foreach (var command in commandGroup)
{ {
toolBar.Items.Add(MakeToolbarItem(command)); toolBar.Items.Add(CreateToolbarItem(command));
} }
} }
} }
} }
Button MakeToolbarItem(IExport<ICommand, IToolbarCommandMetadata> command) static Control CreateMenuItem(TabPageModel pane, DockWorkspace dock)
{ {
return new Button { var header = new TextBlock {
MaxWidth = 200,
TextTrimming = TextTrimming.CharacterEllipsis
};
header.SetBinding(TextBlock.TextProperty, new Binding(nameof(pane.Title)) {
Source = pane
});
MenuItem menuItem = new() {
Command = new TabPageCommand(pane),
Header = header,
IsCheckable = true
};
menuItem.SetBinding(MenuItem.IsCheckedProperty, new Binding(nameof(dock.ActiveTabPage)) {
Source = dock,
ConverterParameter = pane,
Converter = BinaryOperationConverter.Equality
});
return menuItem;
}
static Control CreateMenuItem(ToolPaneModel pane, InputBindingCollection inputBindings)
{
MenuItem menuItem = new() {
Command = pane.AssociatedCommand ?? new ToolPaneCommand(pane.ContentId),
Header = pane.Title
};
var shortcutKey = pane.ShortcutKey;
if (shortcutKey != null)
{
inputBindings.Add(new(menuItem.Command, shortcutKey));
menuItem.InputGestureText = shortcutKey.GetDisplayStringForCulture(CultureInfo.CurrentUICulture);
}
if (!string.IsNullOrEmpty(pane.Icon))
{
menuItem.Icon = new Image {
Width = 16,
Height = 16,
Source = Images.Load(pane, pane.Icon)
};
}
return menuItem;
}
static Button CreateToolbarItem(IExport<ICommand, IToolbarCommandMetadata> command)
{
return new() {
Style = ThemeManager.Current.CreateToolBarButtonStyle(), Style = ThemeManager.Current.CreateToolBarButtonStyle(),
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 = new Image { Content = new Image {
Width = 16, Width = 16,
Height = 16, Height = 16,
Source = Images.Load(command.Value, command.Metadata.ToolbarIcon) Source = Images.Load(command.Value, command.Metadata?.ToolbarIcon)
} }
}; };
} }
public void Init(Menu mainMenu, ToolBar toolBar, InputBindingCollection inputBindings)
{
InitMainMenu(mainMenu);
InitWindowMenu(mainMenu, inputBindings);
InitToolbar(toolBar);
}
} }
} }

Loading…
Cancel
Save