From 19685eb51646221cd4694009d4fad223c401ff67 Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 11 Nov 2021 23:38:14 +0100 Subject: [PATCH] Shared UI - Added ArtemisIcon Plugins - Added features display --- .../Artemis.UI.Avalonia.Shared.xml | 12 ++ .../Controls/ArtemisIcon.axaml | 8 ++ .../Controls/ArtemisIcon.axaml.cs | 103 ++++++++++++++++++ .../ProfileConfigurationIcon.axaml.cs | 37 ++++--- .../Plugins/Views/PluginFeatureView.axaml | 68 +++++++++++- .../Plugins/Views/PluginFeatureView.axaml.cs | 4 +- .../Plugins/Views/PluginSettingsView.axaml | 15 +-- .../Plugins/Views/PluginSettingsView.axaml.cs | 4 +- 8 files changed, 227 insertions(+), 24 deletions(-) create mode 100644 src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml create mode 100644 src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml.cs diff --git a/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml b/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml index 30012341d..e15cb64cc 100644 --- a/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml +++ b/src/Artemis.UI.Avalonia.Shared/Artemis.UI.Avalonia.Shared.xml @@ -4,6 +4,18 @@ Artemis.UI.Avalonia.Shared + + + Gets or sets the currently displayed icon as either a or an pointing + to an SVG + + + + + Gets or sets the currently displayed icon as either a or an pointing + to an SVG + + Visualizes an with optional per-LED colors diff --git a/src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml b/src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml new file mode 100644 index 000000000..18cabf7e7 --- /dev/null +++ b/src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml @@ -0,0 +1,8 @@ + + Welcome to Avalonia! + diff --git a/src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml.cs b/src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml.cs new file mode 100644 index 000000000..e0914bb4c --- /dev/null +++ b/src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml.cs @@ -0,0 +1,103 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Layout; +using Avalonia.LogicalTree; +using Avalonia.Markup.Xaml; +using Avalonia.Media.Imaging; +using Avalonia.Svg.Skia; +using Material.Icons; +using Material.Icons.Avalonia; + +namespace Artemis.UI.Avalonia.Shared.Controls +{ + public partial class ArtemisIcon : UserControl + { + #region Properties + + /// + /// Gets or sets the currently displayed icon as either a or an pointing + /// to an SVG + /// + public static readonly StyledProperty IconProperty = + AvaloniaProperty.Register(nameof(Icon), notifying: IconChanging); + + private static void IconChanging(IAvaloniaObject sender, bool before) + { + if (before) + ((ArtemisIcon) sender).Update(); + } + + private void Update() + { + try + { + // First look for an enum value instead of a string + if (Icon is MaterialIconKind materialIcon) + Content = new MaterialIcon {Kind = materialIcon, Width = Bounds.Width, Height = Bounds.Height }; + // If it's a string there are several options + else if (Icon is string iconString) + { + // An enum defined as a string + if (Enum.TryParse(iconString, true, out MaterialIconKind parsedIcon)) + Content = new MaterialIcon {Kind = parsedIcon, Width = Bounds.Width, Height = Bounds.Height}; + // An URI pointing to an SVG + else if (iconString.EndsWith(".svg")) + { + SvgSource source = new(); + source.Load(iconString); + Content = new SvgImage {Source = source}; + } + // An URI pointing to a different kind of image + else + Content = new Image {Source = new Bitmap(iconString), Width = Bounds.Width, Height = Bounds.Height }; + } + } + catch + { + Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark, Width = Bounds.Width, Height = Bounds.Height }; + } + } + + /// + /// Gets or sets the currently displayed icon as either a or an pointing + /// to an SVG + /// + public object? Icon + { + get => GetValue(IconProperty); + set => SetValue(IconProperty, value); + } + + #endregion + + public ArtemisIcon() + { + InitializeComponent(); + DetachedFromLogicalTree += OnDetachedFromLogicalTree; + LayoutUpdated += OnLayoutUpdated; + } + + private void OnLayoutUpdated(object? sender, EventArgs e) + { + if (Content is Control contentControl) + { + contentControl.Width = Bounds.Width; + contentControl.Height = Bounds.Height; + } + } + + private void OnDetachedFromLogicalTree(object? sender, LogicalTreeAttachmentEventArgs e) + { + if (Content is SvgImage svgImage) + svgImage.Source?.Dispose(); + else if (Content is Image image) + ((Bitmap) image.Source).Dispose(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia.Shared/Controls/ProfileConfigurationIcon.axaml.cs b/src/Artemis.UI.Avalonia.Shared/Controls/ProfileConfigurationIcon.axaml.cs index 01d1b5d8c..83be72c21 100644 --- a/src/Artemis.UI.Avalonia.Shared/Controls/ProfileConfigurationIcon.axaml.cs +++ b/src/Artemis.UI.Avalonia.Shared/Controls/ProfileConfigurationIcon.axaml.cs @@ -40,29 +40,35 @@ namespace Artemis.UI.Avalonia.Shared.Controls PropertyChanged += OnPropertyChanged; } - private void Update() { if (ConfigurationIcon == null) return; - if (ConfigurationIcon.IconType == ProfileConfigurationIconType.SvgImage && ConfigurationIcon.FileIcon != null) + try { - SvgSource source = new(); - source.Load(ConfigurationIcon.FileIcon); - Content = new SvgImage {Source = source}; + if (ConfigurationIcon.IconType == ProfileConfigurationIconType.SvgImage && ConfigurationIcon.FileIcon != null) + { + SvgSource source = new(); + source.Load(ConfigurationIcon.FileIcon); + Content = new SvgImage {Source = source}; + } + else if (ConfigurationIcon.IconType == ProfileConfigurationIconType.MaterialIcon && ConfigurationIcon.MaterialIcon != null) + { + Content = Enum.TryParse(ConfigurationIcon.MaterialIcon, true, out MaterialIconKind parsedIcon) + ? new MaterialIcon {Kind = parsedIcon!} + : new MaterialIcon {Kind = MaterialIconKind.QuestionMark}; + } + else if (ConfigurationIcon.IconType == ProfileConfigurationIconType.BitmapImage && ConfigurationIcon.FileIcon != null) + Content = new Image {Source = new Bitmap(ConfigurationIcon.FileIcon)}; + else + Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark}; } - else if (ConfigurationIcon.IconType == ProfileConfigurationIconType.MaterialIcon && ConfigurationIcon.MaterialIcon != null) + catch { - Content = Enum.TryParse(typeof(MaterialIconKind), ConfigurationIcon.MaterialIcon, true, out object? parsedIcon) - ? new MaterialIcon {Kind = (MaterialIconKind) parsedIcon!} - : new MaterialIcon {Kind = MaterialIconKind.QuestionMark}; - } - else if (ConfigurationIcon.IconType == ProfileConfigurationIconType.BitmapImage && ConfigurationIcon.FileIcon != null) - Content = new Image {Source = new Bitmap(ConfigurationIcon.FileIcon)}; - else Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark}; + } } private void InitializeComponent() @@ -76,6 +82,11 @@ namespace Artemis.UI.Avalonia.Shared.Controls { if (ConfigurationIcon != null) ConfigurationIcon.PropertyChanged -= IconOnPropertyChanged; + + if (Content is SvgImage svgImage) + svgImage.Source?.Dispose(); + else if (Content is Image image) + ((Bitmap) image.Source).Dispose(); } private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) diff --git a/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginFeatureView.axaml b/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginFeatureView.axaml index fdfffda4e..9100a1af1 100644 --- a/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginFeatureView.axaml +++ b/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginFeatureView.axaml @@ -2,7 +2,71 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:shared="clr-namespace:Artemis.UI.Avalonia.Shared.Controls;assembly=Artemis.UI.Avalonia.Shared" + xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginFeatureView"> - Welcome to Avalonia! - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Feature enabled + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginFeatureView.axaml.cs b/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginFeatureView.axaml.cs index 6abc423e8..845c1489a 100644 --- a/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginFeatureView.axaml.cs +++ b/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginFeatureView.axaml.cs @@ -1,9 +1,11 @@ +using Artemis.UI.Avalonia.Screens.Plugins.ViewModels; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; namespace Artemis.UI.Avalonia.Screens.Plugins.Views { - public partial class PluginFeatureView : UserControl + public partial class PluginFeatureView : ReactiveUserControl { public PluginFeatureView() { diff --git a/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginSettingsView.axaml b/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginSettingsView.axaml index 279feab3c..d3fb1d745 100644 --- a/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginSettingsView.axaml +++ b/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginSettingsView.axaml @@ -4,18 +4,19 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia" xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" + xmlns:shared="clr-namespace:Artemis.UI.Avalonia.Shared.Controls;assembly=Artemis.UI.Avalonia.Shared" mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="450" x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginSettingsView"> - + diff --git a/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginSettingsView.axaml.cs b/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginSettingsView.axaml.cs index e000ea68a..5a4f1c677 100644 --- a/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginSettingsView.axaml.cs +++ b/src/Artemis.UI.Avalonia/Screens/Plugins/Views/PluginSettingsView.axaml.cs @@ -1,9 +1,11 @@ +using Artemis.UI.Avalonia.Screens.Plugins.ViewModels; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using Avalonia.ReactiveUI; namespace Artemis.UI.Avalonia.Screens.Plugins.Views { - public partial class PluginSettingsView : UserControl + public partial class PluginSettingsView : ReactiveUserControl { public PluginSettingsView() {