123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852 |
- using Avalonia;
- using Avalonia.Controls;
- using Avalonia.Controls.Shapes;
- using Avalonia.Data;
- using Avalonia.Input;
- using Avalonia.Interactivity;
- using Avalonia.Markup.Xaml;
- using Avalonia.Media;
- using Avalonia.Media.Imaging;
- using Avalonia.Layout;
- using Avalonia.Skia.Helpers;
- using CommunityToolkit.Mvvm.Input;
- using FluentResults;
- using InABox.Avalonia.Components.ImageEditing;
- using InABox.Avalonia.Converters;
- using InABox.Core;
- using SkiaSharp;
- using System.Collections.ObjectModel;
- using System.Threading.Tasks;
- using Avalonia.LogicalTree;
- using CommunityToolkit.Mvvm.ComponentModel;
- namespace InABox.Avalonia.Components;
- public enum ImageEditingMode
- {
- Polyline,
- Rectangle,
- Ellipse,
- Text,
- Dimension
- }
- public partial class ImageEditorModeButton(ImageEditingMode mode, Control? content, bool active) : ObservableObject
- {
- public ImageEditingMode Mode { get; set; } = mode;
- public Control? Content { get; set; } = content;
- [ObservableProperty]
- private bool _active = active;
- }
- public class ImageEditorTransparentImageBrushConverter : AbstractConverter<IBrush?, IBrush?>
- {
- public static readonly ImageEditorTransparentImageBrushConverter Instance = new ImageEditorTransparentImageBrushConverter();
- protected override IBrush? Convert(IBrush? value, object? parameter = null)
- {
- if (value is SolidColorBrush solid && solid.Color.A == 255) return solid;
- var brush = new VisualBrush
- {
- TileMode = TileMode.Tile,
- DestinationRect = new(0, 0, 10, 10, RelativeUnit.Absolute)
- };
- var canvas = new Canvas
- {
- Width = 10,
- Height = 10
- };
- var rect1 = new Rectangle { Width = 5, Height = 5 };
- var rect2 = new Rectangle { Width = 5, Height = 5 };
- Canvas.SetLeft(rect2, 5);
- Canvas.SetTop(rect2, 5);
- rect1.Fill = new SolidColorBrush(Colors.LightGray);
- rect2.Fill = new SolidColorBrush(Colors.LightGray);
- var rect3 = new Rectangle { Width = 10, Height = 10 };
- rect3.Fill = value;
- canvas.Children.Add(rect1);
- canvas.Children.Add(rect2);
- canvas.Children.Add(rect3);
- brush.Visual = canvas;
- return brush;
- }
- }
- public class ImageEditorRemoveOpacityConverter : AbstractConverter<IBrush?, IBrush?>
- {
- public static readonly ImageEditorRemoveOpacityConverter Instance = new();
-
- protected override IBrush? Convert(IBrush? value, object? parameter = null)
- {
- if (value is SolidColorBrush solid)
- {
- return new SolidColorBrush(new Color(255, solid.Color.R, solid.Color.G, solid.Color.B));
- }
- return value;
- }
- }
- // TODO: Make it so we don't re-render everything everytime 'Objects' changes.
- public partial class ImageEditor : UserControl
- {
- public static readonly StyledProperty<IImage?> SourceProperty =
- AvaloniaProperty.Register<ImageEditor, IImage?>(nameof(Source));
- public static readonly StyledProperty<IBrush?> PrimaryBrushProperty =
- AvaloniaProperty.Register<ImageEditor, IBrush?>(nameof(PrimaryBrush), new SolidColorBrush(Colors.Black));
- public static readonly StyledProperty<IBrush?> SecondaryBrushProperty =
- AvaloniaProperty.Register<ImageEditor, IBrush?>(nameof(SecondaryBrush), new SolidColorBrush(Colors.White));
- public static readonly StyledProperty<double> LineThicknessProperty =
- AvaloniaProperty.Register<ImageEditor, double>(nameof(LineThickness), 3.0);
- public static readonly StyledProperty<int> ImageWidthProperty =
- AvaloniaProperty.Register<ImageEditor, int>(nameof(ImageWidth), 100);
- public static readonly StyledProperty<int> ImageHeightProperty =
- AvaloniaProperty.Register<ImageEditor, int>(nameof(ImageHeight), 100);
- public static readonly StyledProperty<ImageEditingMode> ModeProperty =
- AvaloniaProperty.Register<ImageEditor, ImageEditingMode>(nameof(Mode), ImageEditingMode.Polyline);
- public static readonly StyledProperty<bool> ShowButtonsProperty =
- AvaloniaProperty.Register<ImageEditor, bool>(nameof(ShowButtons), true);
- public IImage? Source
- {
- get => GetValue(SourceProperty);
- set => SetValue(SourceProperty, value);
- }
- public int ImageWidth
- {
- get => GetValue(ImageWidthProperty);
- set => SetValue(ImageWidthProperty, value);
- }
- public int ImageHeight
- {
- get => GetValue(ImageHeightProperty);
- set => SetValue(ImageHeightProperty, value);
- }
- public bool ShowButtons
- {
- get => GetValue(ShowButtonsProperty);
- set => SetValue(ShowButtonsProperty, value);
- }
- #region Editing Properties
- public ImageEditingMode Mode
- {
- get => GetValue(ModeProperty);
- set => SetValue(ModeProperty, value);
- }
- public IBrush? PrimaryBrush
- {
- get => GetValue(PrimaryBrushProperty);
- set => SetValue(PrimaryBrushProperty, value);
- }
- public IBrush? SecondaryBrush
- {
- get => GetValue(SecondaryBrushProperty);
- set => SetValue(SecondaryBrushProperty, value);
- }
- public double LineThickness
- {
- get => GetValue(LineThicknessProperty);
- set => SetValue(LineThicknessProperty, value);
- }
- #endregion
- #region Events
- public event EventHandler? Changed;
- #endregion
- #region Private Properties
- public ObservableCollection<ImageEditorModeButton> ModeButtons { get; set; } = new();
- private ObservableCollection<IImageEditorObject> Objects = new();
- private IImageEditorObject? _currentObject;
- private IImageEditorObject? CurrentObject
- {
- get => _currentObject;
- set
- {
- _currentObject?.SetActive(false);
- _currentObject = value;
- }
- }
- private Stack<IImageEditorObject> RedoStack = new();
- private double ScaleFactor = 1.0;
- #endregion
- static ImageEditor()
- {
- SourceProperty.Changed.AddClassHandler<ImageEditor>(Source_Changed);
- }
- private static void Source_Changed(ImageEditor editor, AvaloniaPropertyChangedEventArgs args)
- {
- if(editor.Source is not null)
- {
- editor.ImageWidth = (int)Math.Floor(editor.Source.Size.Width);
- editor.ImageHeight = (int)Math.Floor(editor.Source.Size.Height);
- editor.PositionImage();
- }
- }
- public ImageEditor()
- {
- InitializeComponent();
- Objects.CollectionChanged += Objects_CollectionChanged;
- AddModeButtons();
- SetMode(Mode);
- OuterCanvas.LayoutUpdated += OuterCanvas_LayoutUpdated;
- }
- #region Layout
- private void OuterCanvas_LayoutUpdated(object? sender, EventArgs e)
- {
- PositionImage();
- }
- protected override void OnLoaded(RoutedEventArgs e)
- {
- base.OnLoaded(e);
- PositionImage();
- }
- private void PositionImage()
- {
- var canvasWidth = OuterCanvas.Bounds.Width;
- var canvasHeight = OuterCanvas.Bounds.Height;
- var scaleFactor = Math.Min(canvasWidth / ImageWidth, canvasHeight / ImageHeight);
- ScaleFactor = scaleFactor;
- var imageWidth = ImageWidth * scaleFactor;
- var imageHeight = ImageHeight * scaleFactor;
- ImageBorder.Width = imageWidth;
- ImageBorder.Height = imageHeight;
- Canvas.SetLeft(ImageBorder, OuterCanvas.Bounds.Width / 2 - imageWidth / 2);
- Canvas.SetTop(ImageBorder, OuterCanvas.Bounds.Height / 2 - imageHeight / 2);
- Canvas.RenderTransform = new ScaleTransform(ScaleFactor, ScaleFactor);
- Canvas.Width = ImageWidth;
- Canvas.Height = ImageHeight;
- }
- #endregion
- #region Editing Commands
- private void UpdateUndoRedoButtons()
- {
- UndoButton.IsEnabled = Objects.Count > 0;
- RedoButton.IsEnabled = RedoStack.Count > 0;
- }
- [RelayCommand]
- private void Undo()
- {
- if (Objects.Count == 0) return;
- RedoStack.Push(Objects[^1]);
- Objects.RemoveAt(Objects.Count - 1);
- UpdateUndoRedoButtons();
- Changed?.Invoke(this, new EventArgs());
- }
- [RelayCommand]
- private void Redo()
- {
- if (!RedoStack.TryPop(out var top)) return;
- Objects.Add(top);
- UpdateUndoRedoButtons();
- Changed?.Invoke(this, new EventArgs());
- }
- private void AddObject(IImageEditorObject obj)
- {
- Objects.Add(obj);
- RedoStack.Clear();
- UpdateUndoRedoButtons();
- Changed?.Invoke(this, new EventArgs());
- }
- [RelayCommand]
- private void SetMode(ImageEditingMode mode)
- {
- foreach(var button in ModeButtons)
- {
- button.Active = button.Mode == mode;
- }
- Mode = mode;
- // ShapeButton.Content = CreateModeButtonContent(mode);
- SecondaryColour.IsVisible = HasSecondaryColour();
- LineThicknessButton.IsVisible = HasLineThickness();
- }
- private bool HasSecondaryColour()
- {
- return Mode == ImageEditingMode.Rectangle || Mode == ImageEditingMode.Ellipse;
- }
- private bool HasLineThickness()
- {
- return Mode == ImageEditingMode.Rectangle
- || Mode == ImageEditingMode.Ellipse
- || Mode == ImageEditingMode.Polyline
- || Mode == ImageEditingMode.Dimension;
- }
- #endregion
- #region Mode Buttons
- private void AddModeButtons()
- {
- AddModeButton(ImageEditingMode.Polyline);
- AddModeButton(ImageEditingMode.Rectangle);
- AddModeButton(ImageEditingMode.Ellipse);
- AddModeButton(ImageEditingMode.Text);
- AddModeButton(ImageEditingMode.Dimension);
- }
- private void AddModeButton(ImageEditingMode mode)
- {
- ModeButtons.Add(new(mode, CreateModeButtonContent(mode), mode == Mode));
- }
- private Control? CreateModeButtonContent(ImageEditingMode mode, bool bindColour = false)
- {
- switch (mode)
- {
- case ImageEditingMode.Polyline:
- var canvas = new Canvas();
- {
- var points = new Point[] { new(0, 0), new(20, 8), new(5, 16), new(25, 25) };
- var line1 = new Polyline { Points = points, Width = 25, Height = 25 };
- var line2 = new Polyline { Points = points, Width = 25, Height = 25 };
- line1.StrokeThickness = 4;
- line1.StrokeLineCap = PenLineCap.Round;
- line1.StrokeJoin = PenLineJoin.Round;
- line1.Stroke = new SolidColorBrush(Colors.Black);
- canvas.Children.Add(line1);
- if (bindColour)
- {
- line1.StrokeThickness = 5;
- line2.StrokeThickness = 4;
- line2.StrokeLineCap = PenLineCap.Round;
- line2.StrokeJoin = PenLineJoin.Round;
- line2.Bind(Polyline.StrokeProperty, new Binding(nameof(PrimaryBrush))
- {
- Source = this,
- Converter = ImageEditorRemoveOpacityConverter.Instance
- });
- canvas.Children.Add(line2);
- }
- }
- return canvas;
- case ImageEditingMode.Rectangle:
- canvas = new Canvas();
- canvas.Width = 25;
- canvas.Height = 25;
- var rectangle = new Rectangle();
- if (bindColour)
- {
- rectangle.Bind(Rectangle.StrokeProperty, new Binding(nameof(PrimaryBrush))
- {
- Source = this,
- Converter = ImageEditorRemoveOpacityConverter.Instance
- });
- rectangle.Bind(Rectangle.FillProperty, new Binding(nameof(SecondaryBrush))
- {
- Source = this,
- Converter = ImageEditorTransparentImageBrushConverter.Instance
- });
- }
- else
- {
- rectangle.Stroke = new SolidColorBrush(Colors.Black);
- rectangle.Fill = new SolidColorBrush(Colors.White);
- }
- rectangle.StrokeThickness = 1.0;
- rectangle.Width = 25;
- rectangle.Height = 25;
- canvas.Children.Add(rectangle);
- return canvas;
- case ImageEditingMode.Ellipse:
- canvas = new Canvas();
- canvas.Width = 25;
- canvas.Height = 25;
- var ellipse = new Ellipse();
- if (bindColour)
- {
- ellipse.Bind(Rectangle.StrokeProperty, new Binding(nameof(PrimaryBrush))
- {
- Source = this,
- Converter = ImageEditorRemoveOpacityConverter.Instance
- });
- ellipse.Bind(Rectangle.FillProperty, new Binding(nameof(SecondaryBrush))
- {
- Source = this,
- Converter = ImageEditorTransparentImageBrushConverter.Instance
- });
- }
- else
- {
- ellipse.Stroke = new SolidColorBrush(Colors.Black);
- ellipse.Fill = new SolidColorBrush(Colors.White);
- }
- ellipse.StrokeThickness = 1.0;
- ellipse.Width = 25;
- ellipse.Height = 25;
- canvas.Children.Add(ellipse);
- return canvas;
- case ImageEditingMode.Text:
- var textBox = new TextBlock();
- textBox.Text = "T";
- textBox.FontSize = 25;
- textBox.TextAlignment = TextAlignment.Center;
- textBox.HorizontalAlignment = HorizontalAlignment.Center;
- textBox.VerticalAlignment = VerticalAlignment.Center;
- if (bindColour)
- {
- textBox.Bind(TextBlock.ForegroundProperty, new Binding(nameof(PrimaryBrush))
- {
- Source = this,
- Converter = ImageEditorRemoveOpacityConverter.Instance
- });
- }
- return textBox;
- case ImageEditingMode.Dimension:
- canvas = new Canvas();
- canvas.Width = 25;
- canvas.Height = 25;
- {
- var dimLines = new List<Line>();
- dimLines.Add(new Line
- {
- StartPoint = new(2, 10),
- EndPoint = new(23, 10),
- StrokeLineCap = PenLineCap.Round
- });
- dimLines.Add(new Line
- {
- StartPoint = new(2, 10),
- EndPoint = new(5, 7),
- StrokeLineCap = PenLineCap.Square
- });
- dimLines.Add(new Line
- {
- StartPoint = new(2, 10),
- EndPoint = new(5, 13),
- StrokeLineCap = PenLineCap.Square
- });
- dimLines.Add(new Line
- {
- StartPoint = new(23, 10),
- EndPoint = new(20, 7),
- StrokeLineCap = PenLineCap.Square
- });
- dimLines.Add(new Line
- {
- StartPoint = new(23, 10),
- EndPoint = new(20, 13),
- StrokeLineCap = PenLineCap.Square
- });
- var dotLines = new List<Line>();
- dotLines.Add(new Line
- {
- StartPoint = new(2, 10),
- EndPoint = new(2, 24),
- StrokeDashArray = [2, 2]
- });
- dotLines.Add(new Line
- {
- StartPoint = new(23, 10),
- EndPoint = new(23, 24),
- StrokeDashArray = [2, 2]
- });
- var number = new TextBlock
- {
- Text = "10",
- FontSize = 9,
- TextAlignment = TextAlignment.Center,
- Width = 25
- };
- Canvas.SetLeft(number, 0);
- Canvas.SetTop(number, -1);
- foreach (var line in dimLines)
- {
- line.StrokeThickness = 2;
- line.Stroke = new SolidColorBrush(Colors.Black);
- }
- foreach (var line in dotLines)
- {
- line.StrokeThickness = 1;
- line.Stroke = new SolidColorBrush(Colors.Black);
- }
- if (bindColour)
- {
- foreach (var line in dimLines)
- {
- line.Bind(Polyline.StrokeProperty, new Binding(nameof(PrimaryBrush))
- {
- Source = this,
- Converter = ImageEditorRemoveOpacityConverter.Instance
- });
- }
- foreach (var line in dotLines)
- {
- line.Bind(Polyline.StrokeProperty, new Binding(nameof(PrimaryBrush))
- {
- Source = this,
- Converter = ImageEditorRemoveOpacityConverter.Instance
- });
- }
- }
- foreach (var line in dimLines)
- {
- canvas.Children.Add(line);
- }
- foreach (var line in dotLines)
- {
- canvas.Children.Add(line);
- }
- canvas.Children.Add(number);
- }
- return canvas;
- default:
- return null;
- }
- }
- #endregion
- #region Public Interface
- public void Reset()
- {
- Objects.Clear();
- RedoStack.Clear();
- UpdateUndoRedoButtons();
- Changed?.Invoke(this, new EventArgs());
- }
- public Bitmap GetImage()
- {
- var renderBitmap = new RenderTargetBitmap(new PixelSize(ImageWidth, ImageHeight));
- renderBitmap.Render(Image);
- using var context = renderBitmap.CreateDrawingContext();
- if(Source is not null)
- {
- context.DrawImage(Source, new(0, 0, ImageWidth, ImageHeight));
- }
- CurrentObject = null;
- foreach (var obj in Objects)
- {
- var control = obj.GetControl();
- Render(context, control);
- }
- return renderBitmap;
- }
- private void Render(DrawingContext context, Control control)
- {
- var left = Canvas.GetLeft(control);
- var top = Canvas.GetTop(control);
- if (double.IsNaN(left)) left = 0;
- if (double.IsNaN(top)) top = 0;
- var matrix = Matrix.CreateTranslation(new(left, top));
- if(control.RenderTransform is not null)
- {
- Vector offset;
- if(control.RenderTransformOrigin.Unit == RelativeUnit.Relative)
- {
- offset = new Vector(
- control.Bounds.Width * control.RenderTransformOrigin.Point.X,
- control.Bounds.Height * control.RenderTransformOrigin.Point.Y);
- }
- else
- {
- offset = new Vector(control.RenderTransformOrigin.Point.X, control.RenderTransformOrigin.Point.Y);
- }
- matrix = (Matrix.CreateTranslation(-offset) * control.RenderTransform.Value * Matrix.CreateTranslation(offset)) * matrix;
- }
- using (context.PushTransform(matrix))
- {
- control.Render(context);
- if(control is Panel panel)
- {
- foreach(var child in panel.Children)
- {
- Render(context, child);
- }
- }
- }
- }
- public byte[] SaveImage()
- {
- var bitmap = GetImage();
- var stream = new MemoryStream();
- bitmap.Save(stream);
- return stream.ToArray();
- }
- #endregion
- #region Editing
- private void RefreshObjects()
- {
- Canvas.Children.Clear();
- foreach(var item in Objects)
- {
- item.Update();
- Canvas.Children.Add(item.GetControl());
- }
- }
- private void Objects_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
- {
- RefreshObjects();
- }
- Point ConvertToImageCoordinates(Point canvasCoordinates)
- {
- return canvasCoordinates;// new(canvasCoordinates.X / ScaleFactor, canvasCoordinates.Y / ScaleFactor);
- }
- private void Canvas_PointerPressed(object? sender, PointerPressedEventArgs e)
- {
- CurrentObject = null;
- var position = ConvertToImageCoordinates(e.GetPosition(Canvas));
- switch (Mode)
- {
- case ImageEditingMode.Polyline:
- CurrentObject = new PolylineObject
- {
- Points = [position],
- PrimaryBrush = PrimaryBrush,
- Thickness = LineThickness
- };
- AddObject(CurrentObject);
- break;
- case ImageEditingMode.Rectangle:
- CurrentObject = new RectangleObject
- {
- Point1 = position,
- Point2 = position,
- PrimaryBrush = PrimaryBrush,
- SecondaryBrush = SecondaryBrush,
- Thickness = LineThickness
- };
- AddObject(CurrentObject);
- break;
- case ImageEditingMode.Ellipse:
- CurrentObject = new EllipseObject
- {
- Point1 = position,
- Point2 = position,
- PrimaryBrush = PrimaryBrush,
- SecondaryBrush = SecondaryBrush,
- Thickness = LineThickness
- };
- AddObject(CurrentObject);
- break;
- case ImageEditingMode.Text:
- CurrentObject = new SelectionObject
- {
- Point1 = position,
- Point2 = position,
- PrimaryBrush = PrimaryBrush
- };
- AddObject(CurrentObject);
- break;
- case ImageEditingMode.Dimension:
- CurrentObject = new DimensionObject
- {
- Point1 = position,
- Point2 = position,
- PrimaryBrush = PrimaryBrush,
- Text = "",
- Offset = 30,
- LineThickness = LineThickness
- };
- AddObject(CurrentObject);
- break;
- }
- }
- private void Canvas_PointerMoved(object? sender, PointerEventArgs e)
- {
- var position = ConvertToImageCoordinates(e.GetPosition(Canvas));
- switch (CurrentObject)
- {
- case PolylineObject polyline:
- polyline.Points.Add(position);
- polyline.Update();
- Changed?.Invoke(this, new EventArgs());
- break;
- case RectangleObject rectangle:
- rectangle.Point2 = position;
- rectangle.Update();
- Changed?.Invoke(this, new EventArgs());
- break;
- case EllipseObject ellipse:
- ellipse.Point2 = position;
- ellipse.Update();
- Changed?.Invoke(this, new EventArgs());
- break;
- case SelectionObject textSelection:
- textSelection.Point2 = position;
- textSelection.Update();
- Changed?.Invoke(this, new EventArgs());
- break;
- case DimensionObject dimension:
- if (!dimension.Complete)
- {
- dimension.Point2 = position;
- dimension.Update();
- Changed?.Invoke(this, new EventArgs());
- }
- break;
- }
- }
- private void Canvas_PointerReleased(object? sender, PointerReleasedEventArgs e)
- {
- var position = ConvertToImageCoordinates(e.GetPosition(Canvas));
- switch (CurrentObject)
- {
- case PolylineObject polyline:
- polyline.Points.Add(position);
- polyline.Update();
- CurrentObject = null;
- Changed?.Invoke(this, new EventArgs());
- break;
- case RectangleObject rectangle:
- rectangle.Point2 = position;
- rectangle.Update();
- CurrentObject = null;
- Changed?.Invoke(this, new EventArgs());
- break;
- case EllipseObject ellipse:
- ellipse.Point2 = position;
- ellipse.Update();
- CurrentObject = null;
- Changed?.Invoke(this, new EventArgs());
- break;
- case SelectionObject selection:
- selection.Point2 = position;
- Objects.Remove(selection);
- CurrentObject = null;
- CreateObjectFromSelection(selection).ContinueWith(task =>
- {
- if(task.Exception != null)
- {
- MobileLogging.LogExceptionMessage(task.Exception);
- }
- });
- break;
- case DimensionObject dimension:
- dimension.Point2 = position;
- if(dimension.Point1 == dimension.Point2)
- {
- Objects.Remove(dimension);
- CurrentObject = null;
- return;
- }
- dimension.Complete = true;
- Navigation.Popup<TextEditViewModel, string?>(x => { }).ContinueWith(task =>
- {
- dimension.Text = task.Result ?? "";
- dimension.Update();
- }, TaskScheduler.FromCurrentSynchronizationContext());
- Changed?.Invoke(this, new EventArgs());
- break;
- }
- }
- private async Task CreateObjectFromSelection(SelectionObject selection)
- {
- switch (Mode)
- {
- case ImageEditingMode.Text:
- var text = await Navigation.Popup<TextEditViewModel, string?>(x => { });
- if(text is null)
- {
- return;
- }
- CurrentObject = new TextObject
- {
- Point = selection.GetTopLeft(),
- Size = selection.GetSize(),
- Text = text,
- PrimaryBrush = selection.PrimaryBrush
- };
- AddObject(CurrentObject);
- break;
- }
- }
- #endregion
- }
|