using System; 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.Threading; using Avalonia.Visuals.Media.Imaging; using Material.Icons; using Material.Icons.Avalonia; namespace Artemis.UI.Shared { /// /// Represents a control that can display the icon of a specific . /// public class ProfileConfigurationIcon : UserControl, IDisposable { private Stream? _stream; /// /// Creates a new instance of the class. /// public ProfileConfigurationIcon() { InitializeComponent(); DetachedFromLogicalTree += OnDetachedFromLogicalTree; PropertyChanged += OnPropertyChanged; } private void Update() { if (ConfigurationIcon == null) return; Dispose(); try { if (ConfigurationIcon.IconType == ProfileConfigurationIconType.MaterialIcon) { Content = Enum.TryParse(ConfigurationIcon.IconName, true, out MaterialIconKind parsedIcon) ? new MaterialIcon {Kind = parsedIcon!} : new MaterialIcon {Kind = MaterialIconKind.QuestionMark}; } else { Stream? stream = ConfigurationIcon.GetIconStream(); if (stream == null) Content = new MaterialIcon {Kind = MaterialIconKind.QuestionMark}; else LoadFromBitmap(ConfigurationIcon, stream); } } 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); } private void OnDetachedFromLogicalTree(object? sender, LogicalTreeAttachmentEventArgs e) { if (ConfigurationIcon != null) ConfigurationIcon.IconUpdated -= ConfigurationIconOnIconUpdated; Dispose(); } private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e) { if (e.Property != ConfigurationIconProperty) return; if (e.OldValue is Core.ProfileConfigurationIcon oldIcon) oldIcon.IconUpdated -= ConfigurationIconOnIconUpdated; if (e.NewValue is Core.ProfileConfigurationIcon newIcon) newIcon.IconUpdated += ConfigurationIconOnIconUpdated; Dispatcher.UIThread.Post(Update, DispatcherPriority.ApplicationIdle); } private void ConfigurationIconOnIconUpdated(object? sender, EventArgs e) { Dispatcher.UIThread.Post(Update, DispatcherPriority.ApplicationIdle); } #region Properties /// /// Gets or sets the to display /// public static readonly StyledProperty ConfigurationIconProperty = AvaloniaProperty.Register(nameof(ConfigurationIcon)); /// /// Gets or sets the to display /// public Core.ProfileConfigurationIcon? ConfigurationIcon { get => GetValue(ConfigurationIconProperty); set => SetValue(ConfigurationIconProperty, value); } #endregion /// public void Dispose() { if (Content is Image {Source: IDisposable d}) { d.Dispose(); Content = null; } _stream?.Dispose(); } } }