From 24ea90e2efea68545bbd21060f3f6efb05ad2efb Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 21 Apr 2020 12:31:35 -0300 Subject: [PATCH] working updating menus inside needsupdate event. --- native/Avalonia.Native/inc/avalonia-native.h | 2 +- native/Avalonia.Native/src/OSX/menu.h | 2 + native/Avalonia.Native/src/OSX/menu.mm | 10 ++++- src/Avalonia.Controls/NativeMenu.cs | 7 ++++ .../AvaloniaNativeMenuExporter.cs | 12 +++++- src/Avalonia.Native/IAvnMenu.cs | 42 +++++++++++++++++++ src/Avalonia.Native/IAvnMenuItem.cs | 2 +- 7 files changed, 72 insertions(+), 5 deletions(-) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index 55592aba51..d8d65c2fe6 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -416,7 +416,7 @@ AVNCOM(IAvnMenuEvents, 1A) : IUnknown /** * NeedsUpdate */ - virtual bool NeedUpdate () = 0; + virtual void NeedsUpdate () = 0; }; extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative(); diff --git a/native/Avalonia.Native/src/OSX/menu.h b/native/Avalonia.Native/src/OSX/menu.h index e76605d362..e4353d10ac 100644 --- a/native/Avalonia.Native/src/OSX/menu.h +++ b/native/Avalonia.Native/src/OSX/menu.h @@ -67,6 +67,8 @@ public: AvnMenu* GetNative(); + void RaiseNeedsUpdate (); + virtual HRESULT InsertItem (int index, IAvnMenuItem* item) override; virtual HRESULT RemoveItem (IAvnMenuItem* item) override; diff --git a/native/Avalonia.Native/src/OSX/menu.mm b/native/Avalonia.Native/src/OSX/menu.mm index 9a133b6c0c..66f4944226 100644 --- a/native/Avalonia.Native/src/OSX/menu.mm +++ b/native/Avalonia.Native/src/OSX/menu.mm @@ -167,6 +167,14 @@ AvnMenu* AvnAppMenu::GetNative() return _native; } +void AvnAppMenu::RaiseNeedsUpdate() +{ + if(_baseEvents != nullptr) + { + _baseEvents->NeedsUpdate(); + } +} + HRESULT AvnAppMenu::InsertItem(int index, IAvnMenuItem *item) { auto avnMenuItem = dynamic_cast(item); @@ -231,7 +239,7 @@ HRESULT AvnAppMenu::Clear() - (void)menuNeedsUpdate:(NSMenu *)menu { - printf("NEEDSUPDATE\n"); + _parent->RaiseNeedsUpdate(); } diff --git a/src/Avalonia.Controls/NativeMenu.cs b/src/Avalonia.Controls/NativeMenu.cs index 7c06111a01..91c11f1a58 100644 --- a/src/Avalonia.Controls/NativeMenu.cs +++ b/src/Avalonia.Controls/NativeMenu.cs @@ -15,12 +15,19 @@ namespace Avalonia.Controls [Content] public IList Items => _items; + public event EventHandler NeedsUpdate; + public NativeMenu() { _items.Validate = Validator; _items.CollectionChanged += ItemsChanged; } + public void RaiseNeedsUpdate () + { + NeedsUpdate?.Invoke(this, EventArgs.Empty); + } + private void Validator(NativeMenuItemBase obj) { if (obj.Parent != null) diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs index f44e18daf6..ce6b4c7263 100644 --- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs +++ b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs @@ -43,6 +43,14 @@ namespace Avalonia.Native DoLayoutReset(); } + internal void InvalidateMenu () + { + if(_resetQueued) + { + DoLayoutReset(); + } + } + private static NativeMenu CreateDefaultAppMenu() { var result = new NativeMenu(); @@ -127,7 +135,7 @@ namespace Avalonia.Native if (_nativeMenu is null) { - _nativeMenu = _factory.CreateMenu(); + _nativeMenu = IAvnMenu.Create(_factory); _nativeMenu.Initialise(this, appMenuHolder, ""); @@ -151,7 +159,7 @@ namespace Avalonia.Native if (_nativeMenu is null) { - _nativeMenu = _factory.CreateMenu(); + _nativeMenu = IAvnMenu.Create(_factory); _nativeMenu.Initialise(this, menu, ""); } diff --git a/src/Avalonia.Native/IAvnMenu.cs b/src/Avalonia.Native/IAvnMenu.cs index 1070053d14..354bf6a6b6 100644 --- a/src/Avalonia.Native/IAvnMenu.cs +++ b/src/Avalonia.Native/IAvnMenu.cs @@ -7,15 +7,57 @@ using Avalonia.Platform.Interop; namespace Avalonia.Native.Interop { + class MenuEvents : CallbackBase, IAvnMenuEvents + { + private IAvnMenu _parent; + + public void Initialise(IAvnMenu parent) + { + _parent = parent; + } + + public void NeedsUpdate() + { + _parent?.RaiseNeedsUpdate(); + } + } + public partial class IAvnMenu { + private MenuEvents _events; private AvaloniaNativeMenuExporter _exporter; private List _menuItems = new List(); private Dictionary _menuItemLookup = new Dictionary(); private CompositeDisposable _propertyDisposables = new CompositeDisposable(); + internal void RaiseNeedsUpdate () + { + ManagedMenu.RaiseNeedsUpdate(); + + _exporter.InvalidateMenu(); + } + internal NativeMenu ManagedMenu { get; private set; } + public static IAvnMenu Create (IAvaloniaNativeFactory factory) + { + var events = new MenuEvents(); + + var menu = factory.CreateMenu(events); + + events.Initialise(menu); + + return menu; + } + + protected override void Dispose(bool disposing) + { + if(disposing) + { + _events.Dispose(); + } + } + private void RemoveAndDispose(IAvnMenuItem item) { _menuItemLookup.Remove(item.ManagedMenuItem); diff --git a/src/Avalonia.Native/IAvnMenuItem.cs b/src/Avalonia.Native/IAvnMenuItem.cs index b49387ea9e..dbe8a77ba6 100644 --- a/src/Avalonia.Native/IAvnMenuItem.cs +++ b/src/Avalonia.Native/IAvnMenuItem.cs @@ -114,7 +114,7 @@ namespace Avalonia.Native.Interop { if (_subMenu == null) { - _subMenu = factory.CreateMenu(); + _subMenu = IAvnMenu.Create(factory); _subMenu.Initialise(exporter, item.Menu, item.Header);