Browse Source

Add WebpAnimation support in ImageBoxView

pull/438/head
ionite34 11 months ago
parent
commit
96f722a9da
No known key found for this signature in database
GPG Key ID: B3404C5F3827849B
  1. 49
      StabilityMatrix.Avalonia/Controls/AdvancedImageBoxView.axaml
  2. 13
      StabilityMatrix.Avalonia/Controls/AdvancedImageBoxView.axaml.cs
  3. 46
      StabilityMatrix.Avalonia/Controls/DataTemplateSelector.cs
  4. 11
      StabilityMatrix.Avalonia/Models/ITemplateKey.cs
  5. 19
      StabilityMatrix.Avalonia/Models/ImageSource.cs
  6. 8
      StabilityMatrix.Avalonia/Models/ImageSourceTemplateType.cs

49
StabilityMatrix.Avalonia/Controls/AdvancedImageBoxView.axaml

@ -8,30 +8,43 @@
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:models="clr-namespace:StabilityMatrix.Avalonia.Models"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:gif="clr-namespace:Avalonia.Gif;assembly=Avalonia.Gif"
d:DataContext="{x:Static mocks:DesignData.SampleImageSource}"
d:DesignHeight="450"
d:DesignWidth="800"
x:DataType="models:ImageSource"
mc:Ignorable="d">
<Grid>
<controls:AdvancedImageBox
Name="ImageBox"
CornerRadius="4"
Image="{Binding BitmapAsync^}"
SizeMode="Fit">
<controls:AdvancedImageBox.ContextFlyout>
<ui:FAMenuFlyout>
<ui:MenuFlyoutItem
x:Name="CopyMenuItem"
CommandParameter="{Binding #ImageBox.Image}"
HotKey="Ctrl+C"
IconSource="Copy"
IsEnabled="{OnPlatform Windows=True,
Default=False}"
Text="Copy" />
</ui:FAMenuFlyout>
</controls:AdvancedImageBox.ContextFlyout>
</controls:AdvancedImageBox>
<ContentPresenter Content="{Binding}">
<ContentPresenter.ContentTemplate>
<controls:DataTemplateSelector x:TypeArguments="models:ImageSourceTemplateType">
<DataTemplate x:Key="{x:Static models:ImageSourceTemplateType.WebpAnimation}" DataType="models:ImageSource">
<gif:GifImage
Stretch="Uniform"
SourceUri="{Binding }"/>
</DataTemplate>
<DataTemplate x:Key="{x:Static models:ImageSourceTemplateType.Image}" DataType="models:ImageSource">
<controls:AdvancedImageBox
CornerRadius="4"
Image="{Binding BitmapAsync^}"
SizeMode="Fit">
<controls:AdvancedImageBox.ContextFlyout>
<ui:FAMenuFlyout>
<ui:MenuFlyoutItem
x:Name="CopyMenuItem"
CommandParameter="{Binding $parent[controls:AdvancedImageBox].Image}"
HotKey="Ctrl+C"
IconSource="Copy"
IsEnabled="{OnPlatform Windows=True, Default=False}"
Text="Copy" />
</ui:FAMenuFlyout>
</controls:AdvancedImageBox.ContextFlyout>
</controls:AdvancedImageBox>
</DataTemplate>
</controls:DataTemplateSelector>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
<!-- Label pill card -->
<Border

13
StabilityMatrix.Avalonia/Controls/AdvancedImageBoxView.axaml.cs

@ -20,14 +20,17 @@ public partial class AdvancedImageBoxView : UserControl
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
var copyMenuItem = this.FindControl<MenuFlyoutItem>("CopyMenuItem")!;
copyMenuItem.Command = new AsyncRelayCommand<Bitmap?>(FlyoutCopy);
if (this.FindControl<MenuFlyoutItem>("CopyMenuItem") is { } copyMenuItem)
{
copyMenuItem.Command = new AsyncRelayCommand<Bitmap?>(FlyoutCopy);
}
}
private static async Task FlyoutCopy(Bitmap? image)
{
if (image is null || !Compat.IsWindows) return;
if (image is null || !Compat.IsWindows)
return;
await Task.Run(() =>
{

46
StabilityMatrix.Avalonia/Controls/DataTemplateSelector.cs

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Metadata;
using JetBrains.Annotations;
using StabilityMatrix.Avalonia.Models;
namespace StabilityMatrix.Avalonia.Controls;
/// <summary>
/// Selector for objects implementing <see cref="ITemplateKey{T}"/>
/// </summary>
[PublicAPI]
public class DataTemplateSelector<TKey> : IDataTemplate
where TKey : notnull
{
/// <summary>
/// Key that is used when no other key matches
/// </summary>
public TKey? DefaultKey { get; set; }
[Content]
public Dictionary<TKey, IDataTemplate> Templates { get; } = new();
public bool Match(object? data) => data is ITemplateKey<TKey>;
/// <inheritdoc />
public Control Build(object? data)
{
if (data is not ITemplateKey<TKey> key)
throw new ArgumentException(null, nameof(data));
if (Templates.TryGetValue(key.TemplateKey, out var template))
{
return template.Build(data)!;
}
if (DefaultKey is not null && Templates.TryGetValue(DefaultKey, out var defaultTemplate))
{
return defaultTemplate.Build(data)!;
}
throw new ArgumentException(null, nameof(data));
}
}

11
StabilityMatrix.Avalonia/Models/ITemplateKey.cs

@ -0,0 +1,11 @@
using StabilityMatrix.Avalonia.Controls;
namespace StabilityMatrix.Avalonia.Models;
/// <summary>
/// Implements a template key for <see cref="DataTemplateSelector"/>
/// </summary>
public interface ITemplateKey<out T>
{
T TemplateKey { get; }
}

19
StabilityMatrix.Avalonia/Models/ImageSource.cs

@ -12,7 +12,7 @@ using StabilityMatrix.Core.Models.FileInterfaces;
namespace StabilityMatrix.Avalonia.Models;
public record ImageSource : IDisposable
public record ImageSource : IDisposable, ITemplateKey<ImageSourceTemplateType>
{
private Hash? contentHashBlake3;
@ -55,6 +55,23 @@ public record ImageSource : IDisposable
Bitmap = bitmap;
}
/// <inheritdoc />
public ImageSourceTemplateType TemplateKey
{
get
{
var ext = LocalFile?.Extension ?? Path.GetExtension(RemoteUrl?.ToString());
if (ext is not null && ext.Equals(".webp", StringComparison.OrdinalIgnoreCase))
{
// TODO: Check if webp is animated
return ImageSourceTemplateType.WebpAnimation;
}
return ImageSourceTemplateType.Image;
}
}
[JsonIgnore]
public Task<Bitmap?> BitmapAsync => GetBitmapAsync();

8
StabilityMatrix.Avalonia/Models/ImageSourceTemplateType.cs

@ -0,0 +1,8 @@
namespace StabilityMatrix.Avalonia.Models;
public enum ImageSourceTemplateType
{
Default,
Image,
WebpAnimation
}
Loading…
Cancel
Save