Skip to content

Commit

Permalink
Merge branch 'main' into MultiWindowSnackbarFix
Browse files Browse the repository at this point in the history
  • Loading branch information
ne0rrmatrix authored Feb 4, 2025
2 parents 1acb8a6 + 4c2ce41 commit 08325e4
Show file tree
Hide file tree
Showing 17 changed files with 337 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
Title="DrawingView">

<ScrollView>
<Grid RowDefinitions="40,40,40,40,40,40,40,40,40,200,200,100" ColumnDefinitions="*,*" RowSpacing="12" >
<Grid RowDefinitions="40,40,40,40,40,40,40,40,40,40,200,200,100" ColumnDefinitions="*,*" RowSpacing="12" >
<Label Grid.Row="0" Grid.Column="0" Text="Clear on Finish" Margin="0,0,5,0" HorizontalOptions="End" HorizontalTextAlignment="End"/>
<Switch Grid.Row="0" Grid.Column="1" x:Name="ClearOnFinishSwitch" HorizontalOptions="Start" />
<Label Grid.Row="1" Grid.Column="0" Text="Multi-Line Mode" Margin="0,0,5,0" HorizontalOptions="End" HorizontalTextAlignment="End"/>
Expand Down Expand Up @@ -52,20 +52,28 @@
Text="Generate Image with Random Lines"
TextColor="Black" />

<Button
<Label
Grid.Row="7" Grid.Column="0"
Text="Output" />
<Picker
Grid.Row="7" Grid.Column="1"
ItemsSource="{Binding AvailableOutputOptions}"
SelectedItem="{Binding SelectedOutputOption}" />

<Button
Grid.Row="8" Grid.Column="0"
Grid.ColumnSpan="2"
BackgroundColor="White"
Command="{Binding SaveCommand, Mode=OneTime}"
Text="Save image"
TextColor="Black" />

<Label Text="DrawingView"
Grid.Row="8" Grid.Column="0"
Grid.Row="9" Grid.Column="0"
Grid.ColumnSpan="2"/>
<mct:DrawingView x:Name="DrawingViewControl"
Margin="0,0,0,10"
Grid.Row="9" Grid.Column="0"
Grid.Row="10" Grid.Column="0"
Grid.ColumnSpan="2"
LineColor="Green"
LineWidth="5"
Expand All @@ -75,8 +83,10 @@
DrawingLineStartedCommand="{Binding DrawingLineStartedCommand, Mode=OneTime}"
DrawingLineCancelledCommand="{Binding DrawingLineCancelledCommand, Mode=OneTime}"
PointDrawnCommand="{Binding PointDrawnCommand, Mode=OneTime}"
ShouldClearOnFinish="{Binding Source={x:Reference ClearOnFinishSwitch}, Path=IsToggled, x:DataType=Switch}"
IsMultiLineModeEnabled="{Binding Source={x:Reference MultiLineModeSwitch}, Path=IsToggled, x:DataType=Switch}">
ShouldClearOnFinish="{Binding Source={x:Reference ClearOnFinish}, Path=IsToggled, x:DataType=Switch}"
IsMultiLineModeEnabled="{Binding Source={x:Reference MultiLineMode}, Path=IsToggled, x:DataType=Switch}"
Height="{Binding CanvasHeight}"
Width="{Binding CanvasWidth}">
<mct:DrawingView.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
Expand All @@ -89,12 +99,12 @@
</mct:DrawingView>

<Image
Grid.Row="10" Grid.Column="0"
Grid.Row="11" Grid.Column="0"
Grid.ColumnSpan="2"
x:Name="GestureImage"
Margin="0,0,0,10"/>

<Label Grid.Row="11" Grid.Column="0"
<Label Grid.Row="12" Grid.Column="0"
Grid.ColumnSpan="2"
BackgroundColor="Gray"
TextColor="Black"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void LoadPointsButtonClicked(object sender, EventArgs e)
async void GetCurrentDrawingViewImageClicked(object sender, EventArgs e)
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var stream = await DrawingViewControl.GetImageStream(GestureImage.Width, GestureImage.Height, cts.Token);
var stream = await DrawingViewControl.GetImageStream(GestureImage.Width, GestureImage.Height, DrawingViewOutputOption.Lines, cts.Token);

GestureImage.Source = ImageSource.FromStream(() => stream);
}
Expand All @@ -48,9 +48,12 @@ async Task DrawImage(IEnumerable<DrawingLine> lines, CancellationToken token)
{
var drawingLines = lines.ToList();
var points = drawingLines.SelectMany(x => x.Points).ToList();
var stream = await DrawingView.GetImageStream(drawingLines,
new Size(points.Max(x => x.X) - points.Min(x => x.X), points.Max(x => x.Y) - points.Min(x => x.Y)),
Colors.Gray,
var stream = await DrawingView.GetImageStream(
ImageLineOptions.FullCanvas(
drawingLines.OfType<IDrawingLine>().ToList(),
new Size(points.Max(x => x.X) - points.Min(x => x.X), points.Max(x => x.Y) - points.Min(x => x.Y)),
new SolidPaint(Colors.Gray),
this.DrawingViewControl.Bounds.Size),
token);

GestureImage.Source = ImageSource.FromStream(() => stream);
Expand Down Expand Up @@ -79,7 +82,7 @@ async void OnDrawingLineCompleted(object sender, DrawingLineCompletedEventArgs e
var height = GetSide(GestureImage.Height);

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var stream = await e.LastDrawingLine.GetImageStream(width, height, Colors.Gray.AsPaint(), cts.Token);
var stream = await e.LastDrawingLine.GetImageStream(width, height, Colors.Gray.AsPaint(), this.DrawingViewControl.Bounds.Size, cts.Token);

GestureImage.Source = ImageSource.FromStream(() => stream);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ public partial class DrawingViewViewModel : BaseViewModel
[ObservableProperty]
public partial string Logs { get; private set; } = string.Empty;

[ObservableProperty]
DrawingViewOutputOption selectedOutputOption = DrawingViewOutputOption.Lines;

public List<DrawingViewOutputOption> AvailableOutputOptions { get; } = [DrawingViewOutputOption.Lines, DrawingViewOutputOption.FullCanvas];

public double CanvasHeight { get; set; }

public double CanvasWidth { get; set; }

public DrawingViewViewModel(IFileSaver fileSaver)
{
this.fileSaver = fileSaver;
Expand Down Expand Up @@ -72,7 +81,11 @@ async Task Save(CancellationToken cancellationToken)
{
try
{
await using var stream = await DrawingView.GetImageStream(Lines, new Size(1920, 1080), Brush.Blue, cancellationToken);
var options = SelectedOutputOption == DrawingViewOutputOption.Lines
? ImageLineOptions.JustLines(Lines.ToList(), new Size(1920, 1080), Brush.Blue)
: ImageLineOptions.FullCanvas(Lines.ToList(), new Size(1920, 1080), Brush.Blue, new Size(CanvasWidth, CanvasHeight));

await using var stream = await DrawingView.GetImageStream(options, cancellationToken);

await Permissions.RequestAsync<Permissions.StorageRead>().WaitAsync(cancellationToken);
await Permissions.RequestAsync<Permissions.StorageWrite>().WaitAsync(cancellationToken);
Expand Down
22 changes: 19 additions & 3 deletions src/CommunityToolkit.Maui.Core/Interfaces/IDrawingLine.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,26 @@ public interface IDrawingLine
/// <summary>
/// Retrieves a <see cref="Stream"/> containing an image of this line, based on the <see cref="Points"/> data.
/// </summary>
/// <param name="imageSizeWidth">The desired width of the image that is returned.</param>
/// <param name="imageSizeHeight">Desired height of the image that is returned.</param>
/// <param name="desiredSizeWidth">Desired width of the image that is returned.</param>
/// <param name="desiredSizeHeight">Desired height of the image that is returned.</param>
/// <param name="background">Background of the generated image.</param>
/// <param name="token"> <see cref="CancellationToken"/>.</param>
/// <returns><see cref="ValueTask{Stream}"/> containing the data of the requested image with data that's currently on the <see cref="IDrawingLine"/>.</returns>
ValueTask<Stream> GetImageStream(double desiredSizeWidth, double desiredSizeHeight, Paint background, CancellationToken token = default) =>
GetImageStream(desiredSizeWidth, desiredSizeHeight, background, null, token);

/// <summary>
/// Retrieves a <see cref="Stream"/> containing an image of this line, based on the <see cref="Points"/> data.
/// </summary>
/// <param name="desiredSizeWidth">Desired width of the image that is returned.</param>
/// <param name="desiredSizeHeight">Desired height of the image that is returned.</param>
/// <param name="background">Background of the generated image.</param>
/// <param name="canvasSize">
/// The actual size of the canvas being displayed. This is an optional parameter
/// if a value is provided then the contents of this line inside these dimensions will be included in the output,
/// if <c>null</c> is provided then the resulting output will be the area covered by the top-left to the bottom-right most points.
/// </param>
/// <param name="token"> <see cref="CancellationToken"/>.</param>
ValueTask<Stream> GetImageStream(double imageSizeWidth, double imageSizeHeight, Paint background, CancellationToken token = default);
/// <returns><see cref="ValueTask{Stream}"/> containing the data of the requested image with data that's currently on the <see cref="IDrawingLine"/>.</returns>
ValueTask<Stream> GetImageStream(double desiredSizeWidth, double desiredSizeHeight, Paint background, Size? canvasSize = null, CancellationToken token = default);
}
18 changes: 14 additions & 4 deletions src/CommunityToolkit.Maui.Core/Interfaces/IDrawingView.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,21 @@ public interface IDrawingView : IView
/// <summary>
/// Retrieves a <see cref="Stream"/> containing an image of the <see cref="Lines"/> that are currently drawn on the <see cref="IDrawingView"/>.
/// </summary>
/// <param name="imageSizeWidth">The desired width of the image that is returned. The image will be resized proportionally.</param>
/// <param name="imageSizeHeight">Desired height of the image that is returned. The image will be resized proportionally.</param>
/// <param name="desiredWidth">Desired width of the image that is returned. The image will be resized proportionally.</param>
/// <param name="desiredHeight">Desired height of the image that is returned. The image will be resized proportionally.</param>
/// <param name="token"> <see cref="CancellationToken"/>.</param>
/// <returns><see cref="Task{Stream}"/> containing the data of the requested image with data that's currently on the <see cref="IDrawingView"/>.</returns>
ValueTask<Stream> GetImageStream(double imageSizeWidth, double imageSizeHeight, CancellationToken token = default);
ValueTask<Stream> GetImageStream(double desiredWidth, double desiredHeight, CancellationToken token = default) => GetImageStream(desiredWidth, desiredHeight, DrawingViewOutputOption.Lines, token);

/// <summary>
/// Retrieves a <see cref="Stream"/> containing an image of the <see cref="Lines"/> that are currently drawn on the <see cref="IDrawingView"/>.
/// </summary>
/// <param name="desiredWidth">Desired width of the image that is returned. The image will be resized proportionally.</param>
/// <param name="desiredHeight">Desired height of the image that is returned. The image will be resized proportionally.</param>
/// <param name="imageOutputOption">The <see cref="DrawingViewOutputOption"/> to determine the bounds and the contents of the resulting image.</param>
/// <param name="token"> <see cref="CancellationToken"/>.</param>
/// <returns><see cref="Task{Stream}"/> containing the data of the requested image with data that's currently on the <see cref="IDrawingView"/>.</returns>
ValueTask<Stream> GetImageStream(double desiredWidth, double desiredHeight, DrawingViewOutputOption imageOutputOption, CancellationToken token = default);

/// <summary>
/// Clears the <see cref="Lines"/> that are currently drawn on the <see cref="IDrawingView"/>.
Expand Down Expand Up @@ -76,4 +86,4 @@ public interface IDrawingView : IView
/// </summary>
/// <param name="lastDrawingLine">Last drawing line</param>
void OnDrawingLineCompleted(IDrawingLine lastDrawingLine);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace CommunityToolkit.Maui.Core;

/// <summary>
/// Enumeration of the options available when generating an image stream using the DrawingView.
/// </summary>
public enum DrawingViewOutputOption
{
/// <summary>
/// Outputs the area covered by the top-left to the bottom-right most points.
/// </summary>
Lines,

/// <summary>
/// Outputs the full area displayed within the drawing view.
/// </summary>
FullCanvas
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,33 +39,15 @@ public int Granularity
/// <summary>
/// Retrieves a <see cref="Stream"/> containing an image of the collection of <see cref="Point"/> that is provided as a parameter.
/// </summary>
/// <param name="points">A collection of <see cref="Point"/> that an image is generated from.</param>
/// <param name="imageSize">The desired dimensions of the generated image.</param>
/// <param name="lineWidth">The desired line width to be used in the generated image.</param>
/// <param name="strokeColor">The desired color of the line to be used in the generated image.</param>
/// <param name="background">Background of the generated image.</param>
/// <param name="options">The options controlling how the resulting image is generated.</param>
/// <param name="token"><see cref="CancellationToken"/> </param>
/// <returns><see cref="ValueTask{Stream}"/> containing the data of the requested image with data that's provided through the <paramref name="points"/> parameter.</returns>
public static ValueTask<Stream> GetImageStream(IEnumerable<PointF> points,
Size imageSize,
float lineWidth,
Color strokeColor,
Paint background,
CancellationToken token = default)
{
return DrawingViewService.GetImageStream(points.ToList(), imageSize, lineWidth, strokeColor, background, token);
}

/// <summary>
/// Retrieves a <see cref="Stream"/> containing an image of this line, based on the <see cref="Points"/> data.
/// </summary>
/// <param name="imageSizeWidth">The desired width of the image that is returned.</param>
/// <param name="imageSizeHeight">Desired height of the image that is returned.</param>
/// <param name="background">Background of the generated image.</param>
/// <param name="token"><see cref="CancellationToken"/> </param>
/// <returns><see cref="ValueTask{Stream}"/> containing the data of the requested image with data that's currently on the <see cref="IDrawingView"/>.</returns>
public ValueTask<Stream> GetImageStream(double imageSizeWidth, double imageSizeHeight, Paint background, CancellationToken token = default)
{
return DrawingViewService.GetImageStream([.. Points], new Size(imageSizeWidth, imageSizeHeight), LineWidth, LineColor, background, token);
}
/// <returns><see cref="ValueTask{Stream}"/> containing the data of the requested image with data that's provided through the <paramref name="options"/> parameter.</returns>
public static ValueTask<Stream> GetImageStream(
ImagePointOptions options,
CancellationToken token = default) =>
DrawingViewService.GetImageStream(options, token);

/// <inheritdoc cref="IDrawingLine.GetImageStream(double, double, Paint, Size?, CancellationToken)"/>
public ValueTask<Stream> GetImageStream(double desiredSizeWidth, double desiredSizeHeight, Paint background, Size? canvasSize = null, CancellationToken token = default) =>
DrawingViewService.GetImageStream(new ImagePointOptions([.. Points], new Size(desiredSizeWidth, desiredSizeHeight), LineWidth, LineColor, background, canvasSize), token);
}
Loading

0 comments on commit 08325e4

Please sign in to comment.