|
@@ -1,21 +1,18 @@
|
|
-using System.Collections.Generic;
|
|
|
|
-using System.Collections.ObjectModel;
|
|
|
|
-using System.Linq;
|
|
|
|
-using System.Windows.Input;
|
|
|
|
|
|
+using System.Collections.ObjectModel;
|
|
using Avalonia;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Controls.ApplicationLifetimes;
|
|
using Avalonia.Controls.ApplicationLifetimes;
|
|
using Avalonia.Data;
|
|
using Avalonia.Data;
|
|
-using Avalonia.Threading;
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
-using PixiEditor.Models.Commands.XAML;
|
|
|
|
using PixiEditor.Extensions.Common.Localization;
|
|
using PixiEditor.Extensions.Common.Localization;
|
|
|
|
+using PixiEditor.Extensions.CommonApi.Menu;
|
|
using PixiEditor.Extensions.UI;
|
|
using PixiEditor.Extensions.UI;
|
|
using PixiEditor.Models.Commands;
|
|
using PixiEditor.Models.Commands;
|
|
|
|
+using PixiEditor.Models.Commands.Evaluators;
|
|
|
|
+using PixiEditor.Models.ExtensionServices;
|
|
using PixiEditor.OperatingSystem;
|
|
using PixiEditor.OperatingSystem;
|
|
using PixiEditor.ViewModels.SubViewModels;
|
|
using PixiEditor.ViewModels.SubViewModels;
|
|
using PixiEditor.ViewModels.SubViewModels.AdditionalContent;
|
|
using PixiEditor.ViewModels.SubViewModels.AdditionalContent;
|
|
-using PixiEditor.Views;
|
|
|
|
using Command = PixiEditor.Models.Commands.Commands.Command;
|
|
using Command = PixiEditor.Models.Commands.Commands.Command;
|
|
using Commands_Command = PixiEditor.Models.Commands.Commands.Command;
|
|
using Commands_Command = PixiEditor.Models.Commands.Commands.Command;
|
|
using NativeMenu = Avalonia.Controls.NativeMenu;
|
|
using NativeMenu = Avalonia.Controls.NativeMenu;
|
|
@@ -45,6 +42,9 @@ internal class MenuBarViewModel : PixiObservableObject
|
|
private Dictionary<string, MenuTreeItem> menuItems = new();
|
|
private Dictionary<string, MenuTreeItem> menuItems = new();
|
|
private List<NativeMenuItem> nativeMenuItems;
|
|
private List<NativeMenuItem> nativeMenuItems;
|
|
|
|
|
|
|
|
+ private MenuItemBuilder[] menuItemBuilders;
|
|
|
|
+ private CommandController commandController;
|
|
|
|
+
|
|
|
|
|
|
private readonly Dictionary<string, int> menuOrderMultiplier = new Dictionary<string, int>()
|
|
private readonly Dictionary<string, int> menuOrderMultiplier = new Dictionary<string, int>()
|
|
{
|
|
{
|
|
@@ -65,8 +65,14 @@ internal class MenuBarViewModel : PixiObservableObject
|
|
|
|
|
|
public void Init(IServiceProvider serviceProvider, CommandController controller)
|
|
public void Init(IServiceProvider serviceProvider, CommandController controller)
|
|
{
|
|
{
|
|
- MenuItemBuilder[] builders = serviceProvider.GetServices<MenuItemBuilder>().ToArray();
|
|
|
|
|
|
+ menuItemBuilders = serviceProvider.GetServices<MenuItemBuilder>().ToArray();
|
|
|
|
+ commandController = controller;
|
|
|
|
+ BuildMenu(controller);
|
|
|
|
+ controller.Commands.CommandAdded += CommandsOnCommandAdded;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ private void BuildMenu(CommandController controller)
|
|
|
|
+ {
|
|
var commandsWithMenuItems = controller.Commands
|
|
var commandsWithMenuItems = controller.Commands
|
|
.Where(x => !string.IsNullOrEmpty(x.MenuItemPath) && IsValid(x.MenuItemPath)).ToArray();
|
|
.Where(x => !string.IsNullOrEmpty(x.MenuItemPath) && IsValid(x.MenuItemPath)).ToArray();
|
|
|
|
|
|
@@ -78,7 +84,24 @@ internal class MenuBarViewModel : PixiObservableObject
|
|
BuildMenuEntry(command);
|
|
BuildMenuEntry(command);
|
|
}
|
|
}
|
|
|
|
|
|
- BuildMenu(controller, builders);
|
|
|
|
|
|
+ BuildMenu(controller, menuItemBuilders);
|
|
|
|
+
|
|
|
|
+ OnPropertyChanged(nameof(MenuEntries));
|
|
|
|
+ OnPropertyChanged(nameof(NativeMenu));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void CommandsOnCommandAdded(object? sender, Command e)
|
|
|
|
+ {
|
|
|
|
+ RebuildMenu();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void RebuildMenu()
|
|
|
|
+ {
|
|
|
|
+ MenuEntries?.Clear();
|
|
|
|
+ nativeMenuItems?.Clear();
|
|
|
|
+ menuItems.Clear();
|
|
|
|
+
|
|
|
|
+ BuildMenu(commandController);
|
|
}
|
|
}
|
|
|
|
|
|
private int GetCategoryMultiplier(Commands_Command command)
|
|
private int GetCategoryMultiplier(Commands_Command command)
|
|
@@ -92,7 +115,7 @@ internal class MenuBarViewModel : PixiObservableObject
|
|
return argMenuItemPath.Split('/').Length > 1;
|
|
return argMenuItemPath.Split('/').Length > 1;
|
|
}
|
|
}
|
|
|
|
|
|
- private void BuildMenu(CommandController controller, MenuItemBuilder[] builders)
|
|
|
|
|
|
+ private void BuildMenu(CommandController controller, MenuItemBuilder[]? builders)
|
|
{
|
|
{
|
|
if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime)
|
|
if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime)
|
|
{
|
|
{
|
|
@@ -102,9 +125,12 @@ internal class MenuBarViewModel : PixiObservableObject
|
|
if (IOperatingSystem.Current.IsMacOs)
|
|
if (IOperatingSystem.Current.IsMacOs)
|
|
{
|
|
{
|
|
BuildBasicNativeMenuItems(controller, menuItems);
|
|
BuildBasicNativeMenuItems(controller, menuItems);
|
|
- foreach (var builder in builders)
|
|
|
|
|
|
+ if (builders != null)
|
|
{
|
|
{
|
|
- builder.ModifyMenuTree(nativeMenuItems);
|
|
|
|
|
|
+ foreach (var builder in builders)
|
|
|
|
+ {
|
|
|
|
+ builder.ModifyMenuTree(nativeMenuItems);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
NativeMenu = [];
|
|
NativeMenu = [];
|
|
@@ -116,9 +142,12 @@ internal class MenuBarViewModel : PixiObservableObject
|
|
else
|
|
else
|
|
{
|
|
{
|
|
BuildSimpleItems(controller, menuItems);
|
|
BuildSimpleItems(controller, menuItems);
|
|
- foreach (var builder in builders)
|
|
|
|
|
|
+ if (builders != null)
|
|
{
|
|
{
|
|
- builder.ModifyMenuTree(MenuEntries);
|
|
|
|
|
|
+ foreach (var builder in builders)
|
|
|
|
+ {
|
|
|
|
+ builder.ModifyMenuTree(MenuEntries);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -133,7 +162,23 @@ internal class MenuBarViewModel : PixiObservableObject
|
|
{
|
|
{
|
|
MenuItem menuItem = new();
|
|
MenuItem menuItem = new();
|
|
|
|
|
|
- var headerBinding = new Binding(".") { Source = item.Key, Mode = BindingMode.OneWay, };
|
|
|
|
|
|
+ string targetKey = item.Key;
|
|
|
|
+ bool keyHasEntry = new LocalizedString(item.Key).Value != item.Key;
|
|
|
|
+ if (!keyHasEntry)
|
|
|
|
+ {
|
|
|
|
+ var prefix = item.Value.Command.InternalName.Split(":").FirstOrDefault();
|
|
|
|
+ string prefixedKey = (prefix != null ? $"{prefix}:" : "") + item.Key;
|
|
|
|
+
|
|
|
|
+ keyHasEntry = new LocalizedString(prefixedKey).Value != prefixedKey;
|
|
|
|
+
|
|
|
|
+ if (keyHasEntry)
|
|
|
|
+ {
|
|
|
|
+ targetKey = prefixedKey;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var headerBinding = new Binding(".") { Source = targetKey, Mode = BindingMode.OneWay, };
|
|
|
|
+
|
|
|
|
|
|
menuItem.Bind(Translator.KeyProperty, headerBinding);
|
|
menuItem.Bind(Translator.KeyProperty, headerBinding);
|
|
|
|
|
|
@@ -256,6 +301,7 @@ internal class MenuBarViewModel : PixiObservableObject
|
|
|
|
|
|
for (int i = 0; i < path.Length; i++)
|
|
for (int i = 0; i < path.Length; i++)
|
|
{
|
|
{
|
|
|
|
+ string headerKey = path[i];
|
|
if (current == null)
|
|
if (current == null)
|
|
{
|
|
{
|
|
if (!menuItems.ContainsKey(path[i]))
|
|
if (!menuItems.ContainsKey(path[i]))
|