Skip to content

Commit ac7f780

Browse files
committed
Move menu and tool-bar from MainWindow to separate controls.
1 parent 3746337 commit ac7f780

File tree

7 files changed

+317
-234
lines changed

7 files changed

+317
-234
lines changed

ILSpy/AboutPage.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
using System.Windows.Controls.Primitives;
2727
using System.Windows.Data;
2828
using System.Windows.Input;
29+
using System.Windows.Navigation;
2930

3031
using ICSharpCode.AvalonEdit.Rendering;
3132
using ICSharpCode.Decompiler;
@@ -53,7 +54,7 @@ public AboutPage(SettingsService settingsService, IEnumerable<IAboutPageAddition
5354

5455
public override void Execute(object parameter)
5556
{
56-
MessageBus.Send(this, new NavigateToEventArgs(new(new("resource://aboutpage"), null), inNewTabPage: true));
57+
MessageBus.Send(this, new NavigateToEventArgs(new RequestNavigateEventArgs(new Uri("resource://aboutpage"), null), inNewTabPage: true));
5758
}
5859

5960
private void ShowAboutPage(TabPageModel tabPage)
@@ -74,7 +75,7 @@ private void Display(DecompilerTextView textView)
7475

7576
output.AddUIElement(
7677
delegate {
77-
StackPanel stackPanel = new() {
78+
var stackPanel = new StackPanel {
7879
HorizontalAlignment = HorizontalAlignment.Center,
7980
Orientation = Orientation.Horizontal
8081
};
@@ -87,7 +88,7 @@ private void Display(DecompilerTextView textView)
8788
// we already retrieved the latest version sometime earlier
8889
ShowAvailableVersion(UpdateService.LatestAvailableVersion, stackPanel);
8990
}
90-
CheckBox checkBox = new() {
91+
var checkBox = new CheckBox {
9192
Margin = new Thickness(4),
9293
Content = Resources.AutomaticallyCheckUpdatesEveryWeek
9394
};

ILSpy/Controls/MainMenu.xaml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<UserControl x:Class="ICSharpCode.ILSpy.Controls.MainMenu"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:local="clr-namespace:ICSharpCode.ILSpy.Controls"
7+
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
8+
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
9+
xmlns:composition="urn:TomsToolbox.Composition"
10+
xmlns:toms="urn:TomsToolbox"
11+
xmlns:commands="clr-namespace:ICSharpCode.ILSpy.Commands"
12+
mc:Ignorable="d" d:DesignWidth="800" DataContext="{Binding RelativeSource={RelativeSource Self}}">
13+
<Menu DockPanel.Dock="Top" Name="Menu" Height="23" KeyboardNavigation.TabNavigation="None">
14+
<MenuItem Header="{x:Static properties:Resources._File}" Tag="_File">
15+
<!-- content of file menu is added using MEF -->
16+
</MenuItem>
17+
<MenuItem Header="{x:Static properties:Resources._View}" Tag="_View">
18+
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True"
19+
IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" />
20+
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True"
21+
IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" />
22+
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True"
23+
IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" />
24+
<Separator />
25+
<MenuItem Header="{x:Static properties:Resources.Theme}" ItemsSource="{x:Static themes:ThemeManager.AllThemes}">
26+
<MenuItem.ItemContainerStyle>
27+
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
28+
<Setter Property="Command" Value="{composition:Import commands:SetThemeCommand}" />
29+
<Setter Property="CommandParameter" Value="{Binding}" />
30+
<Setter Property="IsCheckable" Value="True" />
31+
<!-- Required by AvalonDock's MenuItem style to show the checkmark -->
32+
<Setter Property="IsChecked">
33+
<Setter.Value>
34+
<MultiBinding Converter="{x:Static toms:BinaryOperationConverter.Equality}" Mode="OneWay">
35+
<Binding />
36+
<Binding Path="SessionSettings.Theme"
37+
RelativeSource="{RelativeSource FindAncestor, AncestorType=UserControl}" />
38+
</MultiBinding>
39+
</Setter.Value>
40+
</Setter>
41+
</Style>
42+
</MenuItem.ItemContainerStyle>
43+
</MenuItem>
44+
<MenuItem Header="{x:Static properties:Resources.UILanguage}">
45+
<MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True"
46+
IsChecked="{Binding SessionSettings.CurrentCulture, Converter={local:CultureSelectionConverter}, ConverterParameter={x:Null}}" />
47+
<MenuItem Header="English" IsCheckable="True"
48+
IsChecked="{Binding SessionSettings.CurrentCulture, Converter={local:CultureSelectionConverter}, ConverterParameter=en-US}" />
49+
<MenuItem Header="中文" IsCheckable="True"
50+
IsChecked="{Binding SessionSettings.CurrentCulture, Converter={local:CultureSelectionConverter}, ConverterParameter=zh-Hans}" />
51+
</MenuItem>
52+
</MenuItem>
53+
<MenuItem x:Name="WindowMenuItem" Header="{x:Static properties:Resources._Window}" Tag="_Window">
54+
<!-- content of window menu is added using MEF -->
55+
</MenuItem>
56+
</Menu>
57+
</UserControl>
Lines changed: 30 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,43 @@
2222
using System.Linq;
2323
using System.Windows;
2424
using System.Windows.Controls;
25-
using System.Windows.Controls.Primitives;
2625
using System.Windows.Data;
2726
using System.Windows.Input;
2827

2928
using ICSharpCode.ILSpy.Commands;
29+
3030
using ICSharpCode.ILSpy.Docking;
31-
using ICSharpCode.ILSpy.Themes;
3231
using ICSharpCode.ILSpy.ViewModels;
3332

3433
using TomsToolbox.Composition;
3534
using TomsToolbox.ObservableCollections;
35+
using TomsToolbox.Wpf;
3636
using TomsToolbox.Wpf.Converters;
3737

38-
namespace ICSharpCode.ILSpy.Util
38+
namespace ICSharpCode.ILSpy.Controls
3939
{
40+
/// <summary>
41+
/// Interaction logic for MainMenu.xaml
42+
/// </summary>
4043
[Export]
41-
[Shared]
42-
public class MenuService(IExportProvider exportProvider, DockWorkspace dockWorkspace)
44+
[NonShared]
45+
public partial class MainMenu
4346
{
44-
public void Init(Menu mainMenu, ToolBar toolBar, InputBindingCollection inputBindings)
47+
public MainMenu(SettingsService settingsService, IExportProvider exportProvider, DockWorkspace dockWorkspace)
4548
{
46-
InitMainMenu(mainMenu);
47-
InitWindowMenu(mainMenu, inputBindings);
48-
InitToolbar(toolBar);
49+
SessionSettings = settingsService.SessionSettings;
50+
51+
InitializeComponent();
52+
53+
this.BeginInvoke(() => {
54+
InitMainMenu(Menu, exportProvider);
55+
InitWindowMenu(WindowMenuItem, Window.GetWindow(this)!.InputBindings, dockWorkspace);
56+
});
4957
}
5058

51-
void InitMainMenu(Menu mainMenu)
59+
public SessionSettings SessionSettings { get; }
60+
61+
static void InitMainMenu(Menu mainMenu, IExportProvider exportProvider)
5262
{
5363
var mainMenuCommands = exportProvider.GetExports<ICommand, IMainMenuCommandMetadata>("MainMenuCommand");
5464
// Start by constructing the individual flat menus
@@ -106,12 +116,9 @@ void InitMainMenu(Menu mainMenu)
106116
}
107117
}
108118

109-
foreach (var item in parentMenuItems.Values)
119+
foreach (var item in parentMenuItems.Values.Where(item => item.Parent == null))
110120
{
111-
if (item.Parent == null)
112-
{
113-
mainMenu.Items.Add(item);
114-
}
121+
mainMenu.Items.Add(item);
115122
}
116123

117124
MenuItem GetOrAddParentMenuItem(string menuId, string resourceKey)
@@ -137,59 +144,21 @@ MenuItem GetOrAddParentMenuItem(string menuId, string resourceKey)
137144
}
138145
}
139146

140-
void InitWindowMenu(Menu mainMenu, InputBindingCollection inputBindings)
147+
static void InitWindowMenu(MenuItem windowMenuItem, InputBindingCollection inputBindings, DockWorkspace dockWorkspace)
141148
{
142-
var windowMenuItem = mainMenu.Items.OfType<MenuItem>().First(m => (string)m.Tag == nameof(Properties.Resources._Window));
143-
144149
var defaultItems = windowMenuItem.Items.Cast<Control>().ToArray();
145150

146151
windowMenuItem.Items.Clear();
147152

148-
var toolItems = dockWorkspace.ToolPanes.Select(toolPane => CreateMenuItem(toolPane, inputBindings)).ToArray();
149-
var tabItems = dockWorkspace.TabPages.ObservableSelect(tabPage => CreateMenuItem(tabPage));
153+
var toolItems = dockWorkspace.ToolPanes.Select(toolPane => CreateMenuItem(toolPane, inputBindings, dockWorkspace)).ToArray();
154+
var tabItems = dockWorkspace.TabPages.ObservableSelect(tabPage => CreateMenuItem(tabPage, dockWorkspace));
150155

151156
var allItems = new ObservableCompositeCollection<Control>(defaultItems, [new Separator()], toolItems, [new Separator()], tabItems);
152157

153158
windowMenuItem.ItemsSource = allItems;
154159
}
155160

156-
void InitToolbar(ToolBar toolBar)
157-
{
158-
int navigationPos = 0;
159-
int openPos = 1;
160-
var toolbarCommandsByCategory = exportProvider.GetExports<ICommand, IToolbarCommandMetadata>("ToolbarCommand")
161-
.OrderBy(c => c.Metadata?.ToolbarOrder)
162-
.GroupBy(c => c.Metadata?.ToolbarCategory);
163-
164-
foreach (var commandCategory in toolbarCommandsByCategory)
165-
{
166-
if (commandCategory.Key == nameof(Properties.Resources.Navigation))
167-
{
168-
foreach (var command in commandCategory)
169-
{
170-
toolBar.Items.Insert(navigationPos++, CreateToolbarItem(command));
171-
openPos++;
172-
}
173-
}
174-
else if (commandCategory.Key == nameof(Properties.Resources.Open))
175-
{
176-
foreach (var command in commandCategory)
177-
{
178-
toolBar.Items.Insert(openPos++, CreateToolbarItem(command));
179-
}
180-
}
181-
else
182-
{
183-
toolBar.Items.Add(new Separator());
184-
foreach (var command in commandCategory)
185-
{
186-
toolBar.Items.Add(CreateToolbarItem(command));
187-
}
188-
}
189-
}
190-
}
191-
192-
Control CreateMenuItem(TabPageModel pane)
161+
static Control CreateMenuItem(TabPageModel pane, DockWorkspace dockWorkspace)
193162
{
194163
var header = new TextBlock {
195164
MaxWidth = 200,
@@ -200,7 +169,7 @@ Control CreateMenuItem(TabPageModel pane)
200169
Source = pane
201170
});
202171

203-
MenuItem menuItem = new() {
172+
var menuItem = new MenuItem {
204173
Command = new TabPageCommand(pane, dockWorkspace),
205174
Header = header,
206175
IsCheckable = true
@@ -216,16 +185,16 @@ Control CreateMenuItem(TabPageModel pane)
216185
return menuItem;
217186
}
218187

219-
Control CreateMenuItem(ToolPaneModel pane, InputBindingCollection inputBindings)
188+
static Control CreateMenuItem(ToolPaneModel pane, InputBindingCollection inputBindings, DockWorkspace dockWorkspace)
220189
{
221-
MenuItem menuItem = new() {
190+
var menuItem = new MenuItem {
222191
Command = pane.AssociatedCommand ?? new ToolPaneCommand(pane.ContentId, dockWorkspace),
223192
Header = pane.Title
224193
};
225194
var shortcutKey = pane.ShortcutKey;
226195
if (shortcutKey != null)
227196
{
228-
inputBindings.Add(new(menuItem.Command, shortcutKey));
197+
inputBindings.Add(new InputBinding(menuItem.Command, shortcutKey));
229198
menuItem.InputGestureText = shortcutKey.GetDisplayStringForCulture(CultureInfo.CurrentUICulture);
230199
}
231200
if (!string.IsNullOrEmpty(pane.Icon))
@@ -239,29 +208,5 @@ Control CreateMenuItem(ToolPaneModel pane, InputBindingCollection inputBindings)
239208

240209
return menuItem;
241210
}
242-
243-
static Button CreateToolbarItem(IExport<ICommand, IToolbarCommandMetadata> commandExport)
244-
{
245-
var command = commandExport.Value;
246-
247-
Button toolbarItem = new() {
248-
Style = ThemeManager.Current.CreateToolBarButtonStyle(),
249-
Command = CommandWrapper.Unwrap(command),
250-
ToolTip = Properties.Resources.ResourceManager.GetString(commandExport.Metadata?.ToolTip ?? string.Empty),
251-
Tag = commandExport.Metadata?.Tag,
252-
Content = new Image {
253-
Width = 16,
254-
Height = 16,
255-
Source = Images.Load(command, commandExport.Metadata?.ToolbarIcon)
256-
}
257-
};
258-
259-
if (command is IProvideParameterBinding parameterBinding)
260-
{
261-
BindingOperations.SetBinding(toolbarItem, ButtonBase.CommandParameterProperty, parameterBinding.ParameterBinding);
262-
}
263-
264-
return toolbarItem;
265-
}
266211
}
267212
}

ILSpy/Controls/MainToolBar.xaml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<UserControl x:Class="ICSharpCode.ILSpy.Controls.MainToolBar"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:toms="urn:TomsToolbox"
7+
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
8+
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
9+
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
10+
xmlns:composition="urn:TomsToolbox.Composition"
11+
xmlns:ilSpy="clr-namespace:ICSharpCode.ILSpy"
12+
mc:Ignorable="d" d:DesignWidth="800">
13+
<ToolBar Name="ToolBar"
14+
DockPanel.Dock="Top" ToolBarTray.IsLocked="True" KeyboardNavigation.TabNavigation="None">
15+
<ToolBar.Resources>
16+
<!-- Make images transparent if menu command is disabled -->
17+
<Style TargetType="{x:Type Image}">
18+
<Style.Triggers>
19+
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, AncestorLevel=1}, Path=IsEnabled}" Value="False">
20+
<Setter Property="Opacity" Value="0.30" />
21+
</DataTrigger>
22+
</Style.Triggers>
23+
</Style>
24+
<Style TargetType="{x:Type Image}" x:Key="DarkModeAwareImageStyle">
25+
<Setter Property="Effect" Value="{DynamicResource {x:Static themes:ResourceKeys.ThemeAwareButtonEffect}}" />
26+
<Style.Triggers>
27+
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type ButtonBase}, AncestorLevel=1}, Path=IsEnabled}" Value="False">
28+
<Setter Property="Opacity" Value="0.30" />
29+
</DataTrigger>
30+
</Style.Triggers>
31+
</Style>
32+
</ToolBar.Resources>
33+
<!-- 'Navigation' toolbar category is inserted here -->
34+
<Separator />
35+
<!-- 'Open' toolbar category is inserted here -->
36+
<Separator />
37+
<Grid Margin="2,0">
38+
<ItemsControl ItemsSource="{Binding AssemblyListManager.AssemblyLists}" Height="0" Margin="15,0" />
39+
<ComboBox Name="assemblyListComboBox" MaxDropDownHeight="Auto"
40+
ItemsSource="{Binding AssemblyListManager.AssemblyLists}"
41+
ToolTip="{x:Static properties:Resources.SelectAssemblyListDropdownTooltip}"
42+
SelectedItem="{Binding SessionSettings.ActiveAssemblyList}" />
43+
</Grid>
44+
<Button Command="{composition:Import ilSpy:ManageAssemblyListsCommand}"
45+
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
46+
ToolTip="{x:Static properties:Resources.ManageAssemblyLists}">
47+
<Image Width="16" Height="16" Source="{controls:XamlResource Images/AssemblyList}"
48+
Style="{StaticResource DarkModeAwareImageStyle}" />
49+
</Button>
50+
<Separator />
51+
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}"
52+
ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
53+
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPublicOnly}"
54+
Style="{StaticResource DarkModeAwareImageStyle}" />
55+
</CheckBox>
56+
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}"
57+
ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
58+
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPrivateInternal}"
59+
Style="{StaticResource DarkModeAwareImageStyle}" />
60+
</CheckBox>
61+
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}"
62+
ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
63+
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowAll}"
64+
Style="{StaticResource DarkModeAwareImageStyle}" />
65+
</CheckBox>
66+
<Separator />
67+
<Grid Margin="2,0">
68+
<ItemsControl ItemsSource="{Binding LanguageService.AllLanguages}" DisplayMemberPath="Name" Height="0" Margin="15,0" />
69+
<ComboBox Name="languageComboBox" DisplayMemberPath="Name" MaxDropDownHeight="Auto"
70+
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
71+
ItemsSource="{Binding LanguageService.AllLanguages}"
72+
ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
73+
SelectedItem="{Binding LanguageService.Language}" />
74+
</Grid>
75+
<Grid Margin="2,0">
76+
<ItemsControl
77+
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
78+
DisplayMemberPath="DisplayName" Height="0" Margin="15,0" />
79+
<ComboBox Name="languageVersionComboBox" DisplayMemberPath="DisplayName" MaxDropDownHeight="Auto"
80+
ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}"
81+
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}"
82+
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
83+
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
84+
SelectedItem="{Binding LanguageService.LanguageVersion, UpdateSourceTrigger=PropertyChanged}" />
85+
</Grid>
86+
</ToolBar>
87+
</UserControl>

0 commit comments

Comments
 (0)