using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Controls.Shapes; using Avalonia.Input; using Avalonia.Media; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; namespace InABox.Avalonia.Components.ImageEditing; internal class DimensionObject : IImageEditorObject { public IBrush? PrimaryBrush { get; set; } public Point Point1 { get; set; } public Point Point2 { get; set; } public double LineThickness { get; set; } public string Text { get; set; } = ""; public double Offset { get; set; } = 10; public bool Complete { get; set; } = false; private Canvas Control = new(); private Thumb? Thumb; private bool _active = true; public Control GetControl() => Control; private Vector GetMainVec() { var p1 = new Vector(Point1.X, Point1.Y); var p2 = new Vector(Point2.X, Point2.Y); var mainVec = p2 - p1; var length = mainVec.Length; if(length == 0) { mainVec = new Vector(0, 0); } else { mainVec /= length; } return mainVec; } private Vector GetPerpVec() { var mainVec = GetMainVec(); return new Vector(mainVec.Y, -mainVec.X); } public void Update() { Control.Children.RemoveAll(Control.Children.Where(x => !(x is Thumb))); Point Point(Vector v) => new(v.X, v.Y); var p1 = new Vector(Point1.X, Point1.Y); var p2 = new Vector(Point2.X, Point2.Y); var mainVec = p2 - p1; var length = mainVec.Length; if(length == 0) { mainVec = new Vector(0, 0); } else { mainVec /= length; } var perpVec = new Vector(mainVec.Y, -mainVec.X); var arrowLength = LineThickness * 2; var offset = perpVec * Offset; var mainLines = new List() { new() { StartPoint = Point(p1 + offset), EndPoint = Point(p2 + offset), StrokeLineCap = PenLineCap.Round }, new() { StartPoint = Point(p1 + offset), EndPoint = Point(p1 + mainVec * arrowLength + perpVec * arrowLength + offset), StrokeLineCap = PenLineCap.Square }, new() { StartPoint = Point(p1 + offset), EndPoint = Point(p1 + mainVec * arrowLength - perpVec * arrowLength + offset), StrokeLineCap = PenLineCap.Square }, new() { StartPoint = Point(p2 + offset), EndPoint = Point(p2 - mainVec * arrowLength + perpVec * arrowLength + offset), StrokeLineCap = PenLineCap.Square }, new() { StartPoint = Point(p2 + offset), EndPoint = Point(p2 - mainVec * arrowLength - perpVec * arrowLength + offset), StrokeLineCap = PenLineCap.Square } }; var dotLines = new List() { new() { StartPoint = Point(p1), EndPoint = Point(p1 + offset) }, new() { StartPoint = Point(p2), EndPoint = Point(p2 + offset) }, }; foreach (var line in dotLines) { line.StrokeThickness = LineThickness; line.Stroke = PrimaryBrush; line.StrokeDashArray = [2, 2]; Control.Children.Add(line); } foreach (var line in mainLines) { line.StrokeThickness = LineThickness; line.Stroke = PrimaryBrush; Control.Children.Add(line); } var textHeight = 20; var text = new TextBlock { Text = Text, FontSize = textHeight, TextAlignment = TextAlignment.Center, Width = length, Foreground = PrimaryBrush }; text.RenderTransform = new RotateTransform(Math.Atan2(mainVec.Y, mainVec.X) * 180 / Math.PI); var textPos = p1 + offset + mainVec * length / 2 + perpVec * (textHeight / 2 + 5); Canvas.SetLeft(text, textPos.X - length / 2); Canvas.SetTop(text, textPos.Y - textHeight / 2); Control.Children.Add(text); if(Thumb is null && _active && length > 0) { Thumb = new(); Thumb.Width = 10; Thumb.Height = 10; Thumb.Cursor = new(StandardCursorType.SizeAll); Thumb.DragDelta += Thumb_DragDelta; Thumb.ZIndex = 1; Control.Children.Add(Thumb); } if(Thumb is not null) { Thumb.RenderTransform = new RotateTransform(Math.Atan2(mainVec.Y, mainVec.X) * 180 / Math.PI); var thumbPos = p1 + offset + mainVec * length / 2; Canvas.SetLeft(Thumb, thumbPos.X - 5); Canvas.SetTop(Thumb, thumbPos.Y - 5); } } private Vector Rotate(Vector v, double angle) { angle = Math.Atan2(v.Y, v.X) + angle; var length = v.Length; return new Vector( length * Math.Cos(angle), length * Math.Sin(angle)); } private void Thumb_DragDelta(object? sender, VectorEventArgs e) { var main = GetMainVec(); var v = Vector.Dot(Rotate(e.Vector, Math.Atan2(main.Y, main.X)), GetPerpVec()); Offset += v; Update(); } public void SetActive(bool active) { _active = active; if(Thumb is not null) { Control.Children.Remove(Thumb); Thumb = null; } } }