Skip to content

Commit

Permalink
Add support for existing IImage loading in AdvancedImage. Close #17
Browse files Browse the repository at this point in the history
  • Loading branch information
SKProCH committed Aug 8, 2023
1 parent e4b1e2b commit 0f3272e
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 14 deletions.
23 changes: 23 additions & 0 deletions AsyncImageLoader.Avalonia.Demo/Converters/GetClassNameConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Globalization;
using Avalonia.Data.Converters;

namespace AsyncImageLoader.Avalonia.Demo.Converters;

public class GetClassNameConverter : IValueConverter {
public static GetClassNameConverter Instance { get; } = new();

/// <inheritdoc />
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) {
if (value is null) {
return "null";
}

return value.GetType().Name;
}

/// <inheritdoc />
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) {
throw new NotSupportedException();
}
}
31 changes: 28 additions & 3 deletions AsyncImageLoader.Avalonia.Demo/Pages/AdvancedImagePage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:asyncImageLoader="clr-namespace:AsyncImageLoader;assembly=AsyncImageLoader.Avalonia"
xmlns:services="clr-namespace:AsyncImageLoader.Avalonia.Demo.Services"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:converters="clr-namespace:AsyncImageLoader.Avalonia.Demo.Converters"
mc:Ignorable="d" d:DesignWidth="800"
x:Class="AsyncImageLoader.Avalonia.Demo.Pages.AdvancedImagePage">
<Grid ColumnDefinitions="* 8 150 150" RowDefinitions="Auto Auto Auto Auto Auto"
<Grid ColumnDefinitions="* 8 150 150" RowDefinitions="Auto Auto Auto Auto Auto Auto"
HorizontalAlignment="Center">
<TextBlock Grid.Column="2" Grid.Row="0" HorizontalAlignment="Center" Text="AdvancedImage" />
<TextBlock Grid.Column="3" Grid.Row="0" HorizontalAlignment="Center" Text="Image" />
Expand Down Expand Up @@ -60,8 +61,32 @@
<asyncImageLoader:AdvancedImage Grid.Row="4" Grid.Column="2"
Width="150" Height="150" CornerRadius="5 10 15 20"
Source="/Assets/cat5.jpg" />
<Border Grid.Row="4" Grid.Column="3" CornerRadius="5 10 15 20" ClipToBounds="True" Width="150" Height="150">
<Border Grid.Row="4" Grid.Column="3" CornerRadius="5 10 15 20" ClipToBounds="True" Width="150" Height="150">
<Image Source="/Assets/cat5.jpg" Width="150" Height="150" />
</Border>

<StackPanel Grid.Row="5" Grid.Column="0" HorizontalAlignment="Left">
<TextBlock TextWrapping="Wrap">
<TextBlock.Text>
You can set CurrentImage property by youself. This sets Source back to null.
</TextBlock.Text>
</TextBlock>
<TextBlock>
<Run>Source: </Run>
<Run Text="{Binding #CurrentImageExample.Source}"></Run>
</TextBlock>
<TextBlock>
<Run>CurrentImage: </Run>
<Run Text="{Binding #CurrentImageExample.CurrentImage, Converter={x:Static converters:GetClassNameConverter.Instance}, Mode=OneWay}" />
</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Click="SetSourceButton_OnClick">Set Source</Button>
<Button Click="SetCurrentImageButton_OnClick">Set CurrentImage</Button>
</StackPanel>
</StackPanel>
<asyncImageLoader:AdvancedImage Grid.Row="5" Grid.Column="2"
Name="CurrentImageExample"
Width="150" Height="150"
Source="/Assets/cat5.jpg" />
</Grid>
</UserControl>
23 changes: 15 additions & 8 deletions AsyncImageLoader.Avalonia.Demo/Pages/AdvancedImagePage.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
using Avalonia;
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
using Avalonia.Platform;

namespace AsyncImageLoader.Avalonia.Demo.Pages {
public partial class AdvancedImagePage : UserControl {
public AdvancedImagePage() {
InitializeComponent();
}

private void InitializeComponent() {
AvaloniaXamlLoader.Load(this);
}

private void ReloadButton_OnClick(object? sender, RoutedEventArgs e) {
var advancedImage = this.FindControl<AdvancedImage>("ReloadableAdvancedImage");
advancedImage.Source = null;
advancedImage.Source = "https://github.com/AvaloniaUtils/AsyncImageLoader.Avalonia/raw/master/AsyncImageLoader.Avalonia.Demo/Assets/cat0.jpg";
ReloadableAdvancedImage.Source = null;
ReloadableAdvancedImage.Source = "https://github.com/AvaloniaUtils/AsyncImageLoader.Avalonia/raw/master/AsyncImageLoader.Avalonia.Demo/Assets/cat0.jpg";
}

private void SetSourceButton_OnClick(object? sender, RoutedEventArgs e) {
CurrentImageExample.Source = "/Assets/cat5.jpg";
}

private void SetCurrentImageButton_OnClick(object? sender, RoutedEventArgs e) {
using var stream = AssetLoader.Open(new Uri("avares://AsyncImageLoader.Avalonia.Demo/Assets/cat4.jpg", UriKind.RelativeOrAbsolute));
CurrentImageExample.CurrentImage = new Bitmap(stream);
}
}
}
35 changes: 32 additions & 3 deletions AsyncImageLoader.Avalonia/AdvancedImage.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public bool IsLoading
public IImage? CurrentImage
{
get => _currentImage;
private set => SetAndRaise(CurrentImageProperty, ref _currentImage, value);
set => SetAndRaise(CurrentImageProperty, ref _currentImage, value);
}

/// <summary>
Expand All @@ -169,16 +169,31 @@ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs chang
UpdateImage(change.GetNewValue<string>(), Loader);
else if (change.Property == LoaderProperty && ShouldLoaderChangeTriggerUpdate)
UpdateImage(change.GetNewValue<string>(), Loader);
else if (change.Property == CurrentImageProperty)
ClearSourceIfUserProvideImage();
else if (change.Property == CornerRadiusProperty)
UpdateCornerRadius(change.GetNewValue<CornerRadius>());
else if (change.Property == BoundsProperty && CornerRadius != default) UpdateCornerRadius(CornerRadius);
base.OnPropertyChanged(change);
}

private void ClearSourceIfUserProvideImage() {
if (CurrentImage is not null and not ImageWrapper) {
// User provided image himself
Source = null;
}
}

private async void UpdateImage(string? source, IAsyncImageLoader? loader)
{
_updateCancellationToken?.Cancel();
_updateCancellationToken?.Dispose();
_updateCancellationToken = null;
if (source is null && CurrentImage is not ImageWrapper) {
// User provided image himself
return;
}

var cancellationTokenSource = _updateCancellationToken = new CancellationTokenSource();
IsLoading = true;
CurrentImage = null;
Expand Down Expand Up @@ -219,8 +234,8 @@ private async void UpdateImage(string? source, IAsyncImageLoader? loader)

if (cancellationTokenSource.IsCancellationRequested)
return;
CurrentImage = bitmap;
IsLoading = false;
CurrentImage = bitmap is null ? null : new ImageWrapper(bitmap);
IsLoading = false;
}

private void UpdateCornerRadius(CornerRadius radius)
Expand Down Expand Up @@ -280,4 +295,18 @@ protected override Size ArrangeOverride(Size finalSize)
? Stretch.CalculateSize(finalSize, CurrentImage.Size)
: base.ArrangeOverride(finalSize);
}

public sealed class ImageWrapper : IImage {
public IImage ImageImplementation { get; }
internal ImageWrapper(IImage imageImplementation) {
ImageImplementation = imageImplementation;
}
/// <inheritdoc />
public void Draw(DrawingContext context, Rect sourceRect, Rect destRect) {
ImageImplementation.Draw(context, sourceRect, destRect);
}

/// <inheritdoc />
public Size Size => ImageImplementation.Size;
}
}

0 comments on commit 0f3272e

Please sign in to comment.