Browse Source

subscript to events and notify of changes.

pull/3762/head
Dan Walmsley 6 years ago
parent
commit
aa94dc476c
  1. 143
      src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

143
src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

@ -14,11 +14,18 @@ namespace Avalonia.Native.Interop
public partial class IAvnAppMenuItem
{
private IAvnAppMenu _subMenu;
private AvaloniaNativeMenuExporter _exporter;
public NativeMenuItemBase Managed { get; set; }
public void Update(IAvaloniaNativeFactory factory, NativeMenuItem item)
internal void Update(AvaloniaNativeMenuExporter exporter, IAvaloniaNativeFactory factory, NativeMenuItem item)
{
_exporter = exporter;
Managed = item;
Managed.PropertyChanged += Item_PropertyChanged;
using (var buffer = new Utf8Buffer(item.Header))
{
Title = buffer.DangerousGetHandle();
@ -49,20 +56,35 @@ namespace Avalonia.Native.Interop
_subMenu = factory.CreateMenu();
}
_subMenu.Update(factory, item.Menu);
_subMenu.Update(exporter, factory, item.Menu);
}
if (item.Menu == null && _subMenu != null)
{
_subMenu.Remove();
// todo remove submenu.
// needs implementing on native side also.
}
}
private void Item_PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{
_exporter.QueueReset();
}
internal void Remove()
{
_exporter = null;
Managed = null;
Managed.PropertyChanged -= Item_PropertyChanged;
}
}
public partial class IAvnAppMenu
{
private AvaloniaNativeMenuExporter _exporter;
private NativeMenu _menu;
private List<IAvnAppMenuItem> _menuItems = new List<IAvnAppMenuItem>();
private Dictionary<NativeMenuItemBase, IAvnAppMenuItem> _menuItemLookup = new Dictionary<NativeMenuItemBase, IAvnAppMenuItem>();
@ -71,10 +93,18 @@ namespace Avalonia.Native.Interop
{
_menuItemLookup.Remove(item.Managed);
_menuItems.Remove(item);
item.Remove();
RemoveItem(item);
}
internal void Remove()
{
((INotifyCollectionChanged)_menu.Items).CollectionChanged -= IAvnAppMenu_CollectionChanged;
_exporter = null;
_menu = null;
}
private void InsertAt(int index, IAvnAppMenuItem item)
{
if (item.Managed == null)
@ -96,7 +126,7 @@ namespace Avalonia.Native.Interop
return nativeItem;
}
public void Update(IAvaloniaNativeFactory factory, NativeMenu menu, string title = "")
internal void Update(AvaloniaNativeMenuExporter exporter, IAvaloniaNativeFactory factory, NativeMenu menu, string title = "")
{
if (_menu == null)
{
@ -107,6 +137,10 @@ namespace Avalonia.Native.Interop
throw new Exception("Cannot update a menu from another instance");
}
_exporter = exporter;
((INotifyCollectionChanged)_menu.Items).CollectionChanged += IAvnAppMenu_CollectionChanged;
if (!string.IsNullOrWhiteSpace(title))
{
using (var buffer = new Utf8Buffer(title))
@ -134,7 +168,7 @@ namespace Avalonia.Native.Interop
if (menu.Items[i] is NativeMenuItem nmi)
{
nativeItem.Update(factory, nmi);
nativeItem.Update(exporter, factory, nmi);
}
}
@ -143,6 +177,11 @@ namespace Avalonia.Native.Interop
_menuItems.Remove(_menuItems[i]);
}
}
private void IAvnAppMenu_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
_exporter.QueueReset();
}
}
}
@ -181,11 +220,10 @@ namespace Avalonia.Native
class AvaloniaNativeMenuExporter : ITopLevelNativeMenuExporter
{
private IAvaloniaNativeFactory _factory;
private NativeMenu _menu;
private bool _resetQueued;
private bool _exported = false;
private IAvnWindow _nativeWindow;
private List<NativeMenuItem> _menuItems = new List<NativeMenuItem>();
private NativeMenu _menu;
public AvaloniaNativeMenuExporter(IAvnWindow nativeWindow, IAvaloniaNativeFactory factory)
{
@ -199,8 +237,6 @@ namespace Avalonia.Native
{
_factory = factory;
_menu = NativeMenu.GetMenu(Application.Current);
DoLayoutReset();
}
@ -210,13 +246,8 @@ namespace Avalonia.Native
public void SetNativeMenu(NativeMenu menu)
{
if (menu == null)
menu = new NativeMenu();
if (_menu != null)
((INotifyCollectionChanged)_menu.Items).CollectionChanged -= OnMenuItemsChanged;
_menu = menu;
((INotifyCollectionChanged)_menu.Items).CollectionChanged += OnMenuItemsChanged;
if (_menu == null)
_menu = new NativeMenu();
DoLayoutReset();
}
@ -244,50 +275,29 @@ namespace Avalonia.Native
return result;
}
private void OnItemPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{
QueueReset();
}
private void OnMenuItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
QueueReset();
}
void DoLayoutReset()
{
_resetQueued = false;
foreach (var i in _menuItems)
{
i.PropertyChanged -= OnItemPropertyChanged;
if (i.Menu != null)
((INotifyCollectionChanged)i.Menu.Items).CollectionChanged -= OnMenuItemsChanged;
}
_menuItems.Clear();
if (_nativeWindow is null)
{
_menu = NativeMenu.GetMenu(Application.Current);
var appMenu = NativeMenu.GetMenu(Application.Current);
if (_menu != null)
{
SetMenu(_menu);
}
else
if (appMenu == null)
{
SetMenu(CreateDefaultAppMenu());
appMenu = CreateDefaultAppMenu();
SetMenu(appMenu);
}
}
else
{
SetMenu(_nativeWindow, _menu?.Items);
SetMenu(_nativeWindow, _menu);
}
_exported = true;
}
private void QueueReset()
internal void QueueReset()
{
if (_resetQueued)
return;
@ -295,27 +305,6 @@ namespace Avalonia.Native
Dispatcher.UIThread.Post(DoLayoutReset, DispatcherPriority.Background);
}
private IAvnAppMenu CreateSubmenu(ICollection<NativeMenuItemBase> children)
{
var menu = _factory.CreateMenu();
//SetChildren(menu, children);
return menu;
}
private void AddMenuItem(NativeMenuItem item)
{
if (item.Menu?.Items != null)
{
((INotifyCollectionChanged)item.Menu.Items).CollectionChanged += OnMenuItemsChanged;
}
}
private void SetMenu(NativeMenu menu)
{
var appMenu = _factory.ObtainAppMenu();
@ -323,41 +312,23 @@ namespace Avalonia.Native
if (appMenu is null)
{
appMenu = _factory.CreateMenu();
_factory.SetAppMenu(appMenu);
}
var menuItem = menu.Parent;
if (menu.Parent is null)
{
menuItem = new NativeMenuItem();
}
menuItem.Menu = menu;
//appMenu.Clear();
//AddItemsToMenu(appMenu, new List<NativeMenuItemBase> { menuItem });
_factory.SetAppMenu(appMenu);
appMenu.Update(this, _factory, menu);
}
private void SetMenu(IAvnWindow avnWindow, ICollection<NativeMenuItemBase> menuItems)
private void SetMenu(IAvnWindow avnWindow, NativeMenu menu)
{
if (menuItems is null)
{
menuItems = new List<NativeMenuItemBase>();
}
var appMenu = avnWindow.ObtainMainMenu();
if (appMenu is null)
{
appMenu = _factory.CreateMenu();
avnWindow.SetMainMenu(appMenu);
}
//appMenu.Clear();
//AddItemsToMenu(appMenu, menuItems);
avnWindow.SetMainMenu(appMenu);
appMenu.Update(this, _factory, menu);
}
}
}

Loading…
Cancel
Save