From 332005b0f6b118e9a745e60dde710a827d3cdfc4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 28 Apr 2020 19:26:58 -0300 Subject: [PATCH 1/4] Add osx backend menu item icon implementation. --- native/Avalonia.Native/inc/avalonia-native.h | 2 ++ native/Avalonia.Native/src/OSX/menu.h | 2 ++ native/Avalonia.Native/src/OSX/menu.mm | 28 ++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/native/Avalonia.Native/inc/avalonia-native.h b/native/Avalonia.Native/inc/avalonia-native.h index 7fde6b3360..b10db08adc 100644 --- a/native/Avalonia.Native/inc/avalonia-native.h +++ b/native/Avalonia.Native/inc/avalonia-native.h @@ -1,5 +1,6 @@ #include "com.h" #include "key.h" +#include "stddef.h" #define AVNCOM(name, id) COMINTERFACE(name, 2e2cda0a, 9ae5, 4f1b, 8e, 20, 08, 1a, 04, 27, 9f, id) @@ -415,6 +416,7 @@ AVNCOM(IAvnMenuItem, 19) : IUnknown virtual HRESULT SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback) = 0; virtual HRESULT SetIsChecked (bool isChecked) = 0; virtual HRESULT SetToggleType (AvnMenuItemToggleType toggleType) = 0; + virtual HRESULT SetIcon (void* data, size_t length) = 0; }; AVNCOM(IAvnMenuEvents, 1A) : IUnknown diff --git a/native/Avalonia.Native/src/OSX/menu.h b/native/Avalonia.Native/src/OSX/menu.h index cd464d2169..bfbc6801f8 100644 --- a/native/Avalonia.Native/src/OSX/menu.h +++ b/native/Avalonia.Native/src/OSX/menu.h @@ -53,6 +53,8 @@ public: virtual HRESULT SetToggleType (AvnMenuItemToggleType toggleType) override; + virtual HRESULT SetIcon (void* data, size_t length) override; + bool EvaluateItemEnabled(); void RaiseOnClicked(); diff --git a/native/Avalonia.Native/src/OSX/menu.mm b/native/Avalonia.Native/src/OSX/menu.mm index 11a8f04ae3..dc1245cd23 100644 --- a/native/Avalonia.Native/src/OSX/menu.mm +++ b/native/Avalonia.Native/src/OSX/menu.mm @@ -192,6 +192,34 @@ HRESULT AvnAppMenuItem::SetToggleType(AvnMenuItemToggleType toggleType) } } +HRESULT AvnAppMenuItem::SetIcon(void *data, size_t length) +{ + @autoreleasepool + { + if(data != nullptr) + { + NSData *imageData = [NSData dataWithBytes:data length:length]; + NSImage *image = [[NSImage alloc] initWithData:imageData]; + + NSSize originalSize = [image size]; + + NSSize size; + size.height = [[NSFont menuFontOfSize:0] pointSize] * 1.333333; + + auto scaleFactor = size.height / originalSize.height; + size.width = originalSize.width * scaleFactor; + + [image setSize: size]; + [_native setImage:image]; + } + else + { + [_native setImage:nullptr]; + } + return S_OK; + } +} + bool AvnAppMenuItem::EvaluateItemEnabled() { if(_predicate != nullptr) From 2a568f632fcbfe1085833546b2501b90295e18d6 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 28 Apr 2020 19:27:26 -0300 Subject: [PATCH 2/4] Add a markup converter for IBitmap type. --- .../XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs index ebe4035ed6..a1fe6976b7 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs @@ -100,6 +100,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions => AddType(typeSystem.GetType(type), typeSystem.GetType(conv)); Add("Avalonia.Media.IImage","Avalonia.Markup.Xaml.Converters.BitmapTypeConverter"); + Add("Avalonia.Media.Imaging.IBitmap","Avalonia.Markup.Xaml.Converters.BitmapTypeConverter"); var ilist = typeSystem.GetType("System.Collections.Generic.IList`1"); AddType(ilist.MakeGenericType(typeSystem.GetType("Avalonia.Point")), typeSystem.GetType("Avalonia.Markup.Xaml.Converters.PointsListTypeConverter")); From 01342b1b6f40bc49aad4c91e6d538132b1406144 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 28 Apr 2020 19:27:43 -0300 Subject: [PATCH 3/4] Add Icon property to nativemenuicon. --- src/Avalonia.Controls/NativeMenuItem.cs | 12 ++++++++++ src/Avalonia.Native/IAvnMenuItem.cs | 29 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/Avalonia.Controls/NativeMenuItem.cs b/src/Avalonia.Controls/NativeMenuItem.cs index 702bd8c90a..4c94d82eb4 100644 --- a/src/Avalonia.Controls/NativeMenuItem.cs +++ b/src/Avalonia.Controls/NativeMenuItem.cs @@ -1,6 +1,7 @@ using System; using System.Windows.Input; using Avalonia.Input; +using Avalonia.Media.Imaging; using Avalonia.Utilities; namespace Avalonia.Controls @@ -13,6 +14,7 @@ namespace Avalonia.Controls private ICommand _command; private bool _isChecked = false; private NativeMenuItemToggleType _toggleType; + private IBitmap _icon; private NativeMenu _menu; @@ -71,6 +73,16 @@ namespace Avalonia.Controls } } + public static readonly DirectProperty IconProperty = + AvaloniaProperty.RegisterDirect(nameof(Icon), o => o.Icon, (o, v) => o.Icon = v); + + + public IBitmap Icon + { + get => _icon; + set => SetAndRaise(IconProperty, ref _icon, value); + } + public static readonly DirectProperty HeaderProperty = AvaloniaProperty.RegisterDirect(nameof(Header), o => o.Header, (o, v) => o.Header = v); diff --git a/src/Avalonia.Native/IAvnMenuItem.cs b/src/Avalonia.Native/IAvnMenuItem.cs index df82f3955a..c8819d1994 100644 --- a/src/Avalonia.Native/IAvnMenuItem.cs +++ b/src/Avalonia.Native/IAvnMenuItem.cs @@ -1,6 +1,8 @@ using System; +using System.IO; using System.Reactive.Disposables; using Avalonia.Controls; +using Avalonia.Media.Imaging; using Avalonia.Platform.Interop; namespace Avalonia.Native.Interop @@ -31,6 +33,28 @@ namespace Avalonia.Native.Interop ToggleType = (AvnMenuItemToggleType)toggleType; } + private unsafe void UpdateIcon (IBitmap icon) + { + if(icon is null) + { + SetIcon(IntPtr.Zero, 0); + } + else + { + using(var ms = new MemoryStream()) + { + icon.Save(ms); + + var imageData = ms.ToArray(); + + fixed(void* ptr = imageData) + { + SetIcon(new IntPtr(ptr), imageData.Length); + } + } + } + } + private void UpdateGesture(Input.KeyGesture gesture) { // todo ensure backend can cope with setting null gesture. @@ -80,6 +104,8 @@ namespace Avalonia.Native.Interop UpdateToggleType(item.ToggleType); + UpdateIcon(item.Icon); + UpdateIsChecked(item.IsChecked); _propertyDisposables.Add(ManagedMenuItem.GetObservable(NativeMenuItem.HeaderProperty) @@ -96,6 +122,9 @@ namespace Avalonia.Native.Interop _propertyDisposables.Add(ManagedMenuItem.GetObservable(NativeMenuItem.IsCheckedProperty) .Subscribe(x => UpdateIsChecked(x))); + + _propertyDisposables.Add(ManagedMenuItem.GetObservable(NativeMenuItem.IconProperty) + .Subscribe(x => UpdateIcon(x))); } } From eff033589e7cff6fe14e9e5c2ab9f1724e5f77a3 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 28 Apr 2020 19:27:56 -0300 Subject: [PATCH 4/4] Add icons to control catalog example. --- samples/ControlCatalog/MainWindow.xaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml index ca20327e1e..bea751ad4c 100644 --- a/samples/ControlCatalog/MainWindow.xaml +++ b/samples/ControlCatalog/MainWindow.xaml @@ -14,9 +14,9 @@ - + - +