Icons - Dropped SVG support and fixed filling

This commit is contained in:
Robert committed 2022-06-06 20:54:39 +02:00
1 parent dd40bdd544
commit 0d3890e560
30 files changed
+163 -571

No files matched your search

@@ -17,7 +17,6 @@
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.13" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.13" />
<PackageReference Include="Avalonia.Svg.Skia" Version="0.10.12" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.13.3" />
<PackageReference Include="DynamicData" Version="7.5.4" />
<PackageReference Include="FluentAvaloniaUI" Version="1.3.4" />
@@ -1,10 +1,12 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Svg.Skia;
using Avalonia.Visuals.Media.Imaging;
using Material.Icons;
using Material.Icons.Avalonia;
@@ -45,20 +47,29 @@ namespace Artemis.UI.Shared
{
// 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 Image {Source = new SvgImage {Source = source}};
}
// An URI pointing to a different kind of image
// An URI pointing to an image
else
{
Content = new Image {Source = new Bitmap(iconString), Width = Bounds.Width, Height = Bounds.Height};
if (!Fill)
{
Content = new Image
{
Source = new Bitmap(iconString),
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch
};
}
else
{
Content = new Border
{
Background = TextBlock.GetForeground(this),
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch,
OpacityMask = new ImageBrush(new Bitmap(iconString)) {BitmapInterpolationMode = BitmapInterpolationMode.MediumQuality}
};
}
}
}
}
@@ -108,6 +119,23 @@ namespace Artemis.UI.Shared
set => SetValue(IconProperty, value);
}
/// <summary>
/// Gets or sets a boolean indicating whether or not the icon should be filled in with the primary text color of the
/// theme
/// </summary>
public static readonly StyledProperty<bool> FillProperty =
AvaloniaProperty.Register<ArtemisIcon, bool>(nameof(Icon), defaultValue: true, notifying: IconChanging);
/// <summary>
/// Gets or sets a boolean indicating whether or not the icon should be filled in with the primary text color of the
/// theme
/// </summary>
public bool Fill
{
get => GetValue(FillProperty);
set => SetValue(FillProperty, value);
}
#endregion
}
}
@@ -3,10 +3,13 @@ using System.IO;
using Artemis.Core;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Svg.Skia;
using Avalonia.Threading;
using Avalonia.Visuals.Media.Imaging;
using Material.Icons;
using Material.Icons.Avalonia;
@@ -15,8 +18,10 @@ namespace Artemis.UI.Shared
/// <summary>
/// Represents a control that can display the icon of a specific <see cref="ProfileConfiguration"/>.
/// </summary>
public class ProfileConfigurationIcon : UserControl
public class ProfileConfigurationIcon : UserControl, IDisposable
{
private Stream? _stream;
/// <summary>
/// Creates a new instance of the <see cref="ProfileConfigurationIcon" /> class.
/// </summary>
@@ -27,11 +32,11 @@ namespace Artemis.UI.Shared
PropertyChanged += OnPropertyChanged;
}
private void Update()
{
if (ConfigurationIcon == null)
return;
Dispose();
try
{
@@ -40,37 +45,40 @@ namespace Artemis.UI.Shared
Content = Enum.TryParse(ConfigurationIcon.IconName, true, out MaterialIconKind parsedIcon)
? new MaterialIcon {Kind = parsedIcon!}
: new MaterialIcon {Kind = MaterialIconKind.QuestionMark};
return;
}
Stream? stream = ConfigurationIcon.GetIconStream();
if (stream == null)
{
Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark};
return;
}
if (ConfigurationIcon.IconType == ProfileConfigurationIconType.SvgImage)
{
SvgSource source = new();
source.Load(stream);
Content = new Image {Source = new SvgImage {Source = source}};
}
else if (ConfigurationIcon.IconType == ProfileConfigurationIconType.BitmapImage)
{
Content = new Image {Source = new Bitmap(ConfigurationIcon.GetIconStream())};
}
else
{
Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark};
Stream? stream = ConfigurationIcon.GetIconStream();
if (stream == null)
Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark};
else
LoadFromBitmap(ConfigurationIcon, stream);
}
}
catch
catch (Exception)
{
Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark};
}
}
private void LoadFromBitmap(Core.ProfileConfigurationIcon configurationIcon, Stream stream)
{
_stream = stream;
if (!configurationIcon.Fill)
{
Content = new Image {Source = new Bitmap(stream)};
return;
}
Content = new Border
{
Background = TextBlock.GetForeground(this),
VerticalAlignment = VerticalAlignment.Stretch,
HorizontalAlignment = HorizontalAlignment.Stretch,
OpacityMask = new ImageBrush(new Bitmap(stream)) {BitmapInterpolationMode = BitmapInterpolationMode.MediumQuality}
};
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
@@ -81,8 +89,7 @@ namespace Artemis.UI.Shared
if (ConfigurationIcon != null)
ConfigurationIcon.IconUpdated -= ConfigurationIconOnIconUpdated;
if (Content is Image image && image.Source is IDisposable disposable)
disposable.Dispose();
Dispose();
}
private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
@@ -95,12 +102,12 @@ namespace Artemis.UI.Shared
if (e.NewValue is Core.ProfileConfigurationIcon newIcon)
newIcon.IconUpdated += ConfigurationIconOnIconUpdated;
Update();
Dispatcher.UIThread.Post(Update, DispatcherPriority.ApplicationIdle);
}
private void ConfigurationIconOnIconUpdated(object? sender, EventArgs e)
{
Update();
Dispatcher.UIThread.Post(Update, DispatcherPriority.ApplicationIdle);
}
#region Properties
@@ -111,6 +118,7 @@ namespace Artemis.UI.Shared
public static readonly StyledProperty<Core.ProfileConfigurationIcon?> ConfigurationIconProperty =
AvaloniaProperty.Register<ProfileConfigurationIcon, Core.ProfileConfigurationIcon?>(nameof(ConfigurationIcon));
/// <summary>
/// Gets or sets the <see cref="Core.ProfileConfigurationIcon" /> to display
/// </summary>
@@ -121,5 +129,17 @@ namespace Artemis.UI.Shared
}
#endregion
/// <inheritdoc />
public void Dispose()
{
if (Content is Image {Source: IDisposable d})
{
d.Dispose();
Content = null;
}
_stream?.Dispose();
}
}
}
-62
View File
@@ -28,18 +28,6 @@
"System.Reactive": "5.0.0"
}
},
"Avalonia.Svg.Skia": {
"type": "Direct",
"requested": "[0.10.12, )",
"resolved": "0.10.12",
"contentHash": "qsXKdm5eWpfoVPe0xgtxhbOYlhG8QdbYNJZTTihg/c4iPFYuh1G7DldiNskuVFuGiGxLVZ0g6ebql7ZkwbO1pA==",
"dependencies": {
"Avalonia": "0.10.12",
"Avalonia.Skia": "0.10.12",
"SkiaSharp": "2.88.0-preview.178",
"Svg.Skia": "0.5.12"
}
},
"Avalonia.Xaml.Behaviors": {
"type": "Direct",
"requested": "[0.10.13.3, )",
@@ -257,11 +245,6 @@
"Unosquare.Swan.Lite": "3.0.0"
}
},
"Fizzler": {
"type": "Transitive",
"resolved": "1.2.0",
"contentHash": "CPxuWF8EPvM0rwAtMTR5G+7EuLoGNXsEfqyx06upN9JyVALZ73KgbGn3SLFwGosifiUAXrvNHtXlUwGGytdECg=="
},
"HarfBuzzSharp": {
"type": "Transitive",
"resolved": "2.8.2-preview.178",
@@ -694,20 +677,6 @@
"Serilog": "2.10.0"
}
},
"ShimSkiaSharp": {
"type": "Transitive",
"resolved": "0.5.12",
"contentHash": "oUGM7gQHRzbGPRs3E1pe5e8VwML21YyEz9xdo+r2ov1mAqSDPyXErVQP6pN4gnfYMVf5ADR7BVkVzt4R9Iz3gQ=="
},
"SkiaSharp.HarfBuzz": {
"type": "Transitive",
"resolved": "2.88.0-preview.178",
"contentHash": "qTf3PbRJsTVOttQkYWOCswa1QnkH0dEOqMSgr3iXZQuKPNlj1qpGY8+OGPs25WKgUEqOpv2nog/AYQ/bpyOXzA==",
"dependencies": {
"HarfBuzzSharp": "2.8.2-preview.178",
"SkiaSharp": "2.88.0-preview.178"
}
},
"SkiaSharp.NativeAssets.Linux": {
"type": "Transitive",
"resolved": "2.88.0-preview.178",
@@ -736,37 +705,6 @@
"resolved": "14.1.45",
"contentHash": "ayHdfTUklD5ci0s9m4uYMccjtkKVjZ9fVPT5q3PN+SnvyD6bjQVRozOfUHwdwh4LAz9ETZjR/tAgrm+IapXKrw=="
},
"Svg.Custom": {
"type": "Transitive",
"resolved": "0.5.12",
"contentHash": "kmjLQf5U5WC7tRGBedUhtrOUCR0NaNL2auzOA2a/oMwEA0Bjrpd6qvMTpJUS3HITxi8vJazGl270K+i0JvdJog==",
"dependencies": {
"Fizzler": "1.2.0",
"System.Memory": "4.5.3",
"System.ObjectModel": "4.3.0",
"System.ValueTuple": "4.5.0"
}
},
"Svg.Model": {
"type": "Transitive",
"resolved": "0.5.12",
"contentHash": "/CPiXIugg4oVyYlQr26fB1X9iQfICALF8AJXbTWnXGoP2WZa1t6aZbAXPk3HoPApA0w5waf3XXkBiYYnWwawaQ==",
"dependencies": {
"ShimSkiaSharp": "0.5.12",
"Svg.Custom": "0.5.12"
}
},
"Svg.Skia": {
"type": "Transitive",
"resolved": "0.5.12",
"contentHash": "KjKpjz0FKge+WpRzjD1bqywAW3vZhXwpR5c7Ej5OuP4xDrQjBwtFeB0iZ+yEJMzwXf/Rs4ImuN8m3bmBDJvMHg==",
"dependencies": {
"SkiaSharp": "2.88.0-preview.178",
"SkiaSharp.HarfBuzz": "2.88.0-preview.178",
"Svg.Custom": "0.5.12",
"Svg.Model": "0.5.12"
}
},
"System.AppContext": {
"type": "Transitive",
"resolved": "4.3.0",