csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.5 KiB
175 lines
4.5 KiB
using System;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Controls.ApplicationLifetimes;
|
|
using Avalonia.Controls.Platform;
|
|
using Avalonia.Dialogs;
|
|
using Avalonia.Native.Interop;
|
|
using Avalonia.Native.Interop.Impl;
|
|
using Avalonia.Threading;
|
|
|
|
namespace Avalonia.Native
|
|
{
|
|
class AvaloniaNativeMenuExporter : ITopLevelNativeMenuExporter
|
|
{
|
|
private IAvaloniaNativeFactory _factory;
|
|
private bool _resetQueued = true;
|
|
private bool _exported = false;
|
|
private IAvnWindow _nativeWindow;
|
|
private NativeMenu _menu;
|
|
private __MicroComIAvnMenuProxy _nativeMenu;
|
|
|
|
public AvaloniaNativeMenuExporter(IAvnWindow nativeWindow, IAvaloniaNativeFactory factory)
|
|
{
|
|
_factory = factory;
|
|
_nativeWindow = nativeWindow;
|
|
|
|
DoLayoutReset();
|
|
}
|
|
|
|
public AvaloniaNativeMenuExporter(IAvaloniaNativeFactory factory)
|
|
{
|
|
_factory = factory;
|
|
|
|
DoLayoutReset();
|
|
}
|
|
|
|
public bool IsNativeMenuExported => _exported;
|
|
|
|
public event EventHandler OnIsNativeMenuExportedChanged;
|
|
|
|
public void SetNativeMenu(NativeMenu menu)
|
|
{
|
|
_menu = menu == null ? new NativeMenu() : menu;
|
|
DoLayoutReset(true);
|
|
}
|
|
|
|
internal void UpdateIfNeeded()
|
|
{
|
|
if (_resetQueued)
|
|
{
|
|
DoLayoutReset();
|
|
}
|
|
}
|
|
|
|
private static NativeMenu CreateDefaultAppMenu()
|
|
{
|
|
var result = new NativeMenu();
|
|
|
|
var aboutItem = new NativeMenuItem
|
|
{
|
|
Header = "About Avalonia",
|
|
};
|
|
|
|
aboutItem.Click += async (sender, e) =>
|
|
{
|
|
var dialog = new AboutAvaloniaDialog();
|
|
|
|
var mainWindow = (Application.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow;
|
|
|
|
await dialog.ShowDialog(mainWindow);
|
|
};
|
|
|
|
result.Add(aboutItem);
|
|
|
|
return result;
|
|
}
|
|
|
|
private void DoLayoutReset(bool forceUpdate = false)
|
|
{
|
|
if (_resetQueued || forceUpdate)
|
|
{
|
|
_resetQueued = false;
|
|
|
|
if (_nativeWindow is null)
|
|
{
|
|
var appMenu = NativeMenu.GetMenu(Application.Current);
|
|
|
|
if (appMenu == null)
|
|
{
|
|
appMenu = CreateDefaultAppMenu();
|
|
NativeMenu.SetMenu(Application.Current, appMenu);
|
|
}
|
|
|
|
SetMenu(appMenu);
|
|
}
|
|
else
|
|
{
|
|
if (_menu != null)
|
|
{
|
|
SetMenu(_nativeWindow, _menu);
|
|
}
|
|
}
|
|
|
|
_exported = true;
|
|
}
|
|
}
|
|
|
|
internal void QueueReset()
|
|
{
|
|
if (_resetQueued)
|
|
return;
|
|
_resetQueued = true;
|
|
Dispatcher.UIThread.Post(() => DoLayoutReset(), DispatcherPriority.Background);
|
|
}
|
|
|
|
private void SetMenu(NativeMenu menu)
|
|
{
|
|
var menuItem = menu.Parent;
|
|
|
|
var appMenuHolder = menuItem?.Parent;
|
|
|
|
if (menu.Parent is null)
|
|
{
|
|
menuItem = new NativeMenuItem();
|
|
}
|
|
|
|
if (appMenuHolder is null)
|
|
{
|
|
appMenuHolder = new NativeMenu();
|
|
|
|
appMenuHolder.Add(menuItem);
|
|
}
|
|
|
|
menuItem.Menu = menu;
|
|
|
|
var setMenu = false;
|
|
|
|
if (_nativeMenu is null)
|
|
{
|
|
_nativeMenu = (__MicroComIAvnMenuProxy)__MicroComIAvnMenuProxy.Create(_factory);
|
|
|
|
_nativeMenu.Initialise(this, appMenuHolder, "");
|
|
|
|
setMenu = true;
|
|
}
|
|
|
|
_nativeMenu.Update(_factory, appMenuHolder);
|
|
|
|
if (setMenu)
|
|
{
|
|
_factory.SetAppMenu(_nativeMenu);
|
|
}
|
|
}
|
|
|
|
private void SetMenu(IAvnWindow avnWindow, NativeMenu menu)
|
|
{
|
|
var setMenu = false;
|
|
|
|
if (_nativeMenu is null)
|
|
{
|
|
_nativeMenu = __MicroComIAvnMenuProxy.Create(_factory);
|
|
|
|
_nativeMenu.Initialise(this, menu, "");
|
|
|
|
setMenu = true;
|
|
}
|
|
|
|
_nativeMenu.Update(_factory, menu);
|
|
|
|
if(setMenu)
|
|
{
|
|
avnWindow.SetMainMenu(_nativeMenu);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|