NativeMenu.Export.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System;
  2. using Avalonia.Controls.Platform;
  3. using Avalonia.Reactive;
  4. using Avalonia.Platform;
  5. namespace Avalonia.Controls
  6. {
  7. public partial class NativeMenu
  8. {
  9. public static readonly AttachedProperty<bool> IsNativeMenuExportedProperty =
  10. AvaloniaProperty.RegisterAttached<NativeMenu, TopLevel, bool>("IsNativeMenuExported");
  11. public static bool GetIsNativeMenuExported(TopLevel tl) => tl.GetValue(IsNativeMenuExportedProperty);
  12. private static readonly AttachedProperty<NativeMenuInfo> s_nativeMenuInfoProperty =
  13. AvaloniaProperty.RegisterAttached<NativeMenu, TopLevel, NativeMenuInfo>("___NativeMenuInfo");
  14. class NativeMenuInfo
  15. {
  16. public bool ChangingIsExported { get; set; }
  17. public ITopLevelNativeMenuExporter? Exporter { get; }
  18. public NativeMenuInfo(TopLevel target)
  19. {
  20. Exporter = target.PlatformImpl?.TryGetFeature<ITopLevelNativeMenuExporter>();
  21. if (Exporter != null)
  22. {
  23. Exporter.OnIsNativeMenuExportedChanged += delegate
  24. {
  25. SetIsNativeMenuExported(target, Exporter.IsNativeMenuExported);
  26. };
  27. }
  28. }
  29. }
  30. static NativeMenuInfo GetInfo(TopLevel target)
  31. {
  32. var rv = target.GetValue(s_nativeMenuInfoProperty);
  33. if (rv == null)
  34. {
  35. target.SetValue(s_nativeMenuInfoProperty, rv = new NativeMenuInfo(target));
  36. SetIsNativeMenuExported(target, rv.Exporter?.IsNativeMenuExported ?? false);
  37. }
  38. return rv;
  39. }
  40. static void SetIsNativeMenuExported(TopLevel tl, bool value)
  41. {
  42. GetInfo(tl).ChangingIsExported = true;
  43. tl.SetValue(IsNativeMenuExportedProperty, value);
  44. }
  45. public static readonly AttachedProperty<NativeMenu> MenuProperty
  46. = AvaloniaProperty.RegisterAttached<NativeMenu, AvaloniaObject, NativeMenu>("Menu");
  47. public static void SetMenu(AvaloniaObject o, NativeMenu menu) => o.SetValue(MenuProperty, menu);
  48. public static NativeMenu GetMenu(AvaloniaObject o) => o.GetValue(MenuProperty);
  49. static NativeMenu()
  50. {
  51. // This is needed because of the lack of attached direct properties
  52. IsNativeMenuExportedProperty.Changed.Subscribe(args =>
  53. {
  54. var info = GetInfo((TopLevel)args.Sender);
  55. if (!info.ChangingIsExported)
  56. throw new InvalidOperationException("IsNativeMenuExported property is read-only");
  57. info.ChangingIsExported = false;
  58. });
  59. MenuProperty.Changed.Subscribe(args =>
  60. {
  61. if (args.Sender is TopLevel tl)
  62. {
  63. GetInfo(tl).Exporter?.SetNativeMenu(args.NewValue.GetValueOrDefault());
  64. }
  65. else if(args.Sender is INativeMenuExporterProvider provider)
  66. {
  67. provider.NativeMenuExporter?.SetNativeMenu(args.NewValue.GetValueOrDefault());
  68. }
  69. });
  70. }
  71. }
  72. }