-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
Copy pathNativeMenu.cs
106 lines (90 loc) · 3.46 KB
/
NativeMenu.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using Avalonia.Collections;
using Avalonia.Metadata;
namespace Avalonia.Controls
{
public partial class NativeMenu : AvaloniaObject,
IEnumerable<NativeMenuItemBase>,
INativeMenuExporterEventsImplBridge,
IAvaloniaListItemValidator<NativeMenuItemBase>
{
private readonly AvaloniaList<NativeMenuItemBase> _items =
new AvaloniaList<NativeMenuItemBase> { ResetBehavior = ResetBehavior.Remove };
private NativeMenuItem? _parent;
[Content]
public IList<NativeMenuItemBase> Items => _items;
/// <summary>
/// Raised when the menu requests an update.
/// </summary>
/// <remarks>
/// Use this event to add, remove or modify menu items before a menu is
/// shown or a hotkey is pressed.
/// </remarks>
public event EventHandler<EventArgs>? NeedsUpdate;
/// <summary>
/// Raised before the menu is opened.
/// </summary>
/// <remarks>
/// Do not update the menu in this event; use <see cref="NeedsUpdate"/>.
/// </remarks>
public event EventHandler<EventArgs>? Opening;
/// <summary>
/// Raised after the menu is closed.
/// </summary>
/// <remarks>
/// Do not update the menu in this event; use <see cref="NeedsUpdate"/>.
/// </remarks>
public event EventHandler<EventArgs>? Closed;
public NativeMenu()
{
_items.Validator = this;
_items.CollectionChanged += ItemsChanged;
}
void INativeMenuExporterEventsImplBridge.RaiseNeedsUpdate()
{
NeedsUpdate?.Invoke(this, EventArgs.Empty);
}
void INativeMenuExporterEventsImplBridge.RaiseOpening()
{
Opening?.Invoke(this, EventArgs.Empty);
}
void INativeMenuExporterEventsImplBridge.RaiseClosed()
{
Closed?.Invoke(this, EventArgs.Empty);
}
void IAvaloniaListItemValidator<NativeMenuItemBase>.Validate(NativeMenuItemBase item)
{
if (item.Parent is { } parent)
{
throw new InvalidOperationException(
$"The menu item {item.DebugDisplay} already has a parent {parent.DebugDisplay} " +
$"while trying to add it as a child of {DebugDisplay}.");
}
}
private void ItemsChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
foreach (NativeMenuItemBase i in e.OldItems)
i.Parent = null;
if (e.NewItems != null)
foreach (NativeMenuItemBase i in e.NewItems)
i.Parent = this;
}
public static readonly DirectProperty<NativeMenu, NativeMenuItem?> ParentProperty =
AvaloniaProperty.RegisterDirect<NativeMenu, NativeMenuItem?>(nameof(Parent), o => o.Parent);
public NativeMenuItem? Parent
{
get => _parent;
internal set => SetAndRaise(ParentProperty, ref _parent, value);
}
public void Add(NativeMenuItemBase item) => _items.Add(item);
public IEnumerator<NativeMenuItemBase> GetEnumerator() => _items.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}