mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-01-01 02:03:32 +00:00
Shared UI - Added ArtemisIcon
Plugins - Added features display
This commit is contained in:
parent
7954012e31
commit
19685eb516
@ -4,6 +4,18 @@
|
|||||||
<name>Artemis.UI.Avalonia.Shared</name>
|
<name>Artemis.UI.Avalonia.Shared</name>
|
||||||
</assembly>
|
</assembly>
|
||||||
<members>
|
<members>
|
||||||
|
<member name="F:Artemis.UI.Avalonia.Shared.Controls.ArtemisIcon.IconProperty">
|
||||||
|
<summary>
|
||||||
|
Gets or sets the currently displayed icon as either a <see cref="T:Material.Icons.MaterialIconKind" /> or an <see cref="T:System.Uri" /> pointing
|
||||||
|
to an SVG
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="P:Artemis.UI.Avalonia.Shared.Controls.ArtemisIcon.Icon">
|
||||||
|
<summary>
|
||||||
|
Gets or sets the currently displayed icon as either a <see cref="T:Material.Icons.MaterialIconKind" /> or an <see cref="T:System.Uri" /> pointing
|
||||||
|
to an SVG
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="T:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer">
|
<member name="T:Artemis.UI.Avalonia.Shared.Controls.DeviceVisualizer">
|
||||||
<summary>
|
<summary>
|
||||||
Visualizes an <see cref="T:Artemis.Core.ArtemisDevice" /> with optional per-LED colors
|
Visualizes an <see cref="T:Artemis.Core.ArtemisDevice" /> with optional per-LED colors
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
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"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Avalonia.Shared.Controls.ArtemisIcon">
|
||||||
|
Welcome to Avalonia!
|
||||||
|
</UserControl>
|
||||||
103
src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml.cs
Normal file
103
src/Artemis.UI.Avalonia.Shared/Controls/ArtemisIcon.axaml.cs
Normal file
@ -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
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the currently displayed icon as either a <see cref="MaterialIconKind" /> or an <see cref="Uri" /> pointing
|
||||||
|
/// to an SVG
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<object?> IconProperty =
|
||||||
|
AvaloniaProperty.Register<ArtemisIcon, object?>(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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the currently displayed icon as either a <see cref="MaterialIconKind" /> or an <see cref="Uri" /> pointing
|
||||||
|
/// to an SVG
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -40,29 +40,35 @@ namespace Artemis.UI.Avalonia.Shared.Controls
|
|||||||
PropertyChanged += OnPropertyChanged;
|
PropertyChanged += OnPropertyChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
{
|
{
|
||||||
if (ConfigurationIcon == null)
|
if (ConfigurationIcon == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ConfigurationIcon.IconType == ProfileConfigurationIconType.SvgImage && ConfigurationIcon.FileIcon != null)
|
try
|
||||||
{
|
{
|
||||||
SvgSource source = new();
|
if (ConfigurationIcon.IconType == ProfileConfigurationIconType.SvgImage && ConfigurationIcon.FileIcon != null)
|
||||||
source.Load(ConfigurationIcon.FileIcon);
|
{
|
||||||
Content = new SvgImage {Source = source};
|
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};
|
Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
@ -76,6 +82,11 @@ namespace Artemis.UI.Avalonia.Shared.Controls
|
|||||||
{
|
{
|
||||||
if (ConfigurationIcon != null)
|
if (ConfigurationIcon != null)
|
||||||
ConfigurationIcon.PropertyChanged -= IconOnPropertyChanged;
|
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)
|
private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
||||||
|
|||||||
@ -2,7 +2,71 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginFeatureView">
|
x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginFeatureView">
|
||||||
Welcome to Avalonia!
|
<Grid ColumnDefinitions="30,*,Auto">
|
||||||
</UserControl>
|
<Grid.ContextFlyout>
|
||||||
|
<MenuFlyout>
|
||||||
|
<MenuItem Header="Install prerequisites" Command="{Binding InstallPrerequisites}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="CheckAll" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem Header="Remove prerequisites" Command="{Binding RemovePrerequisites}">
|
||||||
|
<MenuItem.Icon>
|
||||||
|
<avalonia:MaterialIcon Kind="Delete" />
|
||||||
|
</MenuItem.Icon>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuFlyout>
|
||||||
|
</Grid.ContextFlyout>
|
||||||
|
|
||||||
|
<!-- Icon column -->
|
||||||
|
<shared:ArtemisIcon Grid.Column="0"
|
||||||
|
Icon="{Binding FeatureInfo.ResolvedIcon}"
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
|
||||||
|
IsVisible="{Binding LoadException, Converter={x:Static ObjectConverters.IsNull}}" />
|
||||||
|
|
||||||
|
<Button Grid.Column="0"
|
||||||
|
Margin="-8"
|
||||||
|
|
||||||
|
IsVisible="{Binding LoadException, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||||
|
Foreground="#E74C4C"
|
||||||
|
ToolTip.Tip="An exception occurred while enabling this feature, click to view"
|
||||||
|
Command="{Binding ViewLoadException}">
|
||||||
|
<avalonia:MaterialIcon Kind="AlertCircle" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Display name column -->
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
Text="{Binding FeatureInfo.Name}"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
ToolTip.Tip="{Binding FeatureInfo.Description}" />
|
||||||
|
|
||||||
|
<!-- Enable toggle column -->
|
||||||
|
<StackPanel Grid.Column="2"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
IsVisible="{Binding !Enabling}"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
ToolTip.Tip="This feature cannot be disabled without disabling the whole plugin">
|
||||||
|
<avalonia:MaterialIcon Kind="ShieldHalfFull"
|
||||||
|
ToolTip.Tip="Plugin requires admin rights"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0 0 5 0"
|
||||||
|
IsVisible="{Binding ShowShield}" />
|
||||||
|
|
||||||
|
<CheckBox IsChecked="{Binding IsEnabled}" IsEnabled="{Binding CanToggleEnabled}">
|
||||||
|
Feature enabled
|
||||||
|
</CheckBox>
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="7" IsVisible="{Binding Enabling}">
|
||||||
|
<ProgressBar Value="0" IsIndeterminate="True" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@ -1,9 +1,11 @@
|
|||||||
|
using Artemis.UI.Avalonia.Screens.Plugins.ViewModels;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia.Screens.Plugins.Views
|
namespace Artemis.UI.Avalonia.Screens.Plugins.Views
|
||||||
{
|
{
|
||||||
public partial class PluginFeatureView : UserControl
|
public partial class PluginFeatureView : ReactiveUserControl<PluginFeatureViewModel>
|
||||||
{
|
{
|
||||||
public PluginFeatureView()
|
public PluginFeatureView()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -4,18 +4,19 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
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"
|
mc:Ignorable="d" d:DesignWidth="900" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginSettingsView">
|
x:Class="Artemis.UI.Avalonia.Screens.Plugins.Views.PluginSettingsView">
|
||||||
<Border Classes="card" Width="900" Padding="15" Margin="0 5">
|
<Border Classes="card" Width="900" Padding="15" Margin="0 5">
|
||||||
<Grid RowDefinitions="*,Auto" ColumnDefinitions="4*,5*">
|
<Grid RowDefinitions="*,Auto" ColumnDefinitions="4*,5*">
|
||||||
<Grid Grid.Row="0" RowDefinitions="Auto,Auto,*" ColumnDefinitions="80,*">
|
<Grid Grid.Row="0" RowDefinitions="Auto,Auto,*" ColumnDefinitions="80,*">
|
||||||
<avalonia:MaterialIcon Kind="{Binding Plugin.Info.ResolvedIcon}"
|
<shared:ArtemisIcon Icon="{Binding Plugin.Info.ResolvedIcon}"
|
||||||
Width="48"
|
Width="48"
|
||||||
Height="48"
|
Height="48"
|
||||||
Margin="0 5 0 0"
|
Margin="0 5 0 0"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.RowSpan="3"
|
Grid.RowSpan="3"
|
||||||
VerticalAlignment="Top" />
|
VerticalAlignment="Top" />
|
||||||
|
|
||||||
<TextBlock Grid.Column="1" Grid.Row="0" Classes="h5 no-margin" Text="{Binding Plugin.Info.Name}" />
|
<TextBlock Grid.Column="1" Grid.Row="0" Classes="h5 no-margin" Text="{Binding Plugin.Info.Name}" />
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
|
using Artemis.UI.Avalonia.Screens.Plugins.ViewModels;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Avalonia.Screens.Plugins.Views
|
namespace Artemis.UI.Avalonia.Screens.Plugins.Views
|
||||||
{
|
{
|
||||||
public partial class PluginSettingsView : UserControl
|
public partial class PluginSettingsView : ReactiveUserControl<PluginSettingsViewModel>
|
||||||
{
|
{
|
||||||
public PluginSettingsView()
|
public PluginSettingsView()
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user