瀏覽代碼

working updating menus inside needsupdate event.

Dan Walmsley 5 年之前
父節點
當前提交
24ea90e2ef

+ 1 - 1
native/Avalonia.Native/inc/avalonia-native.h

@@ -416,7 +416,7 @@ AVNCOM(IAvnMenuEvents, 1A) : IUnknown
     /**
     /**
      * NeedsUpdate
      * NeedsUpdate
      */
      */
-    virtual bool NeedUpdate () = 0;
+    virtual void NeedsUpdate () = 0;
 };
 };
 
 
 extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative();
 extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative();

+ 2 - 0
native/Avalonia.Native/src/OSX/menu.h

@@ -67,6 +67,8 @@ public:
         
         
     AvnMenu* GetNative();
     AvnMenu* GetNative();
     
     
+    void RaiseNeedsUpdate ();
+    
     virtual HRESULT InsertItem (int index, IAvnMenuItem* item) override;
     virtual HRESULT InsertItem (int index, IAvnMenuItem* item) override;
     
     
     virtual HRESULT RemoveItem (IAvnMenuItem* item) override;
     virtual HRESULT RemoveItem (IAvnMenuItem* item) override;

+ 9 - 1
native/Avalonia.Native/src/OSX/menu.mm

@@ -167,6 +167,14 @@ AvnMenu* AvnAppMenu::GetNative()
     return _native;
     return _native;
 }
 }
 
 
+void AvnAppMenu::RaiseNeedsUpdate()
+{
+    if(_baseEvents != nullptr)
+    {
+        _baseEvents->NeedsUpdate();
+    }
+}
+
 HRESULT AvnAppMenu::InsertItem(int index, IAvnMenuItem *item)
 HRESULT AvnAppMenu::InsertItem(int index, IAvnMenuItem *item)
 {
 {
     auto avnMenuItem = dynamic_cast<AvnAppMenuItem*>(item);
     auto avnMenuItem = dynamic_cast<AvnAppMenuItem*>(item);
@@ -231,7 +239,7 @@ HRESULT AvnAppMenu::Clear()
 
 
 - (void)menuNeedsUpdate:(NSMenu *)menu
 - (void)menuNeedsUpdate:(NSMenu *)menu
 {
 {
-    printf("NEEDSUPDATE\n");
+    _parent->RaiseNeedsUpdate();
 }
 }
 
 
 
 

+ 7 - 0
src/Avalonia.Controls/NativeMenu.cs

@@ -15,12 +15,19 @@ namespace Avalonia.Controls
         [Content]
         [Content]
         public IList<NativeMenuItemBase> Items => _items;
         public IList<NativeMenuItemBase> Items => _items;
 
 
+        public event EventHandler<EventArgs> NeedsUpdate;
+
         public NativeMenu()
         public NativeMenu()
         {
         {
             _items.Validate = Validator;
             _items.Validate = Validator;
             _items.CollectionChanged += ItemsChanged;
             _items.CollectionChanged += ItemsChanged;
         }
         }
 
 
+        public void RaiseNeedsUpdate ()
+        {
+            NeedsUpdate?.Invoke(this, EventArgs.Empty);
+        }
+
         private void Validator(NativeMenuItemBase obj)
         private void Validator(NativeMenuItemBase obj)
         {
         {
             if (obj.Parent != null)
             if (obj.Parent != null)

+ 10 - 2
src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

@@ -43,6 +43,14 @@ namespace Avalonia.Native
             DoLayoutReset();
             DoLayoutReset();
         }
         }
 
 
+        internal void InvalidateMenu ()
+        {
+            if(_resetQueued)
+            {
+                DoLayoutReset();
+            }
+        }
+
         private static NativeMenu CreateDefaultAppMenu()
         private static NativeMenu CreateDefaultAppMenu()
         {
         {
             var result = new NativeMenu();
             var result = new NativeMenu();
@@ -127,7 +135,7 @@ namespace Avalonia.Native
 
 
                 if (_nativeMenu is null)
                 if (_nativeMenu is null)
                 {
                 {
-                    _nativeMenu = _factory.CreateMenu();
+                    _nativeMenu = IAvnMenu.Create(_factory);
 
 
                     _nativeMenu.Initialise(this, appMenuHolder, "");
                     _nativeMenu.Initialise(this, appMenuHolder, "");
 
 
@@ -151,7 +159,7 @@ namespace Avalonia.Native
 
 
                 if (_nativeMenu is null)
                 if (_nativeMenu is null)
                 {
                 {
-                    _nativeMenu = _factory.CreateMenu();
+                    _nativeMenu = IAvnMenu.Create(_factory);
 
 
                     _nativeMenu.Initialise(this, menu, "");
                     _nativeMenu.Initialise(this, menu, "");
                 }
                 }

+ 42 - 0
src/Avalonia.Native/IAvnMenu.cs

@@ -7,15 +7,57 @@ using Avalonia.Platform.Interop;
 
 
 namespace Avalonia.Native.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
     public partial class IAvnMenu
     {
     {
+        private MenuEvents _events;
         private AvaloniaNativeMenuExporter _exporter;
         private AvaloniaNativeMenuExporter _exporter;
         private List<IAvnMenuItem> _menuItems = new List<IAvnMenuItem>();
         private List<IAvnMenuItem> _menuItems = new List<IAvnMenuItem>();
         private Dictionary<NativeMenuItemBase, IAvnMenuItem> _menuItemLookup = new Dictionary<NativeMenuItemBase, IAvnMenuItem>();
         private Dictionary<NativeMenuItemBase, IAvnMenuItem> _menuItemLookup = new Dictionary<NativeMenuItemBase, IAvnMenuItem>();
         private CompositeDisposable _propertyDisposables = new CompositeDisposable();
         private CompositeDisposable _propertyDisposables = new CompositeDisposable();
 
 
+        internal void RaiseNeedsUpdate ()
+        {
+            ManagedMenu.RaiseNeedsUpdate();
+
+            _exporter.InvalidateMenu();
+        }
+
         internal NativeMenu ManagedMenu { get; private set; }
         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)
         private void RemoveAndDispose(IAvnMenuItem item)
         {
         {
             _menuItemLookup.Remove(item.ManagedMenuItem);
             _menuItemLookup.Remove(item.ManagedMenuItem);

+ 1 - 1
src/Avalonia.Native/IAvnMenuItem.cs

@@ -114,7 +114,7 @@ namespace Avalonia.Native.Interop
             {
             {
                 if (_subMenu == null)
                 if (_subMenu == null)
                 {
                 {
-                    _subMenu = factory.CreateMenu();
+                    _subMenu = IAvnMenu.Create(factory);
 
 
                     _subMenu.Initialise(exporter, item.Menu, item.Header);
                     _subMenu.Initialise(exporter, item.Menu, item.Header);