using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; using Azaion.Common.DTO; using Azaion.Common.Extensions; using Annotation = Azaion.Common.Database.Annotation; namespace Azaion.Common.Controls; public class DetectionControl : Border { private readonly Action _resizeStart; private const double RESIZE_RECT_SIZE = 10; private readonly Grid _grid; private readonly DetectionLabelPanel _detectionLabelPanel; public readonly Canvas DetectionLabelContainer; public TimeSpan Time { get; set; } private readonly List _resizedRectangles = new(); private DetectionClass _detectionClass = null!; public DetectionClass DetectionClass { get => _detectionClass; set { var brush = new SolidColorBrush(value.Color.ToConfidenceColor()); BorderBrush = brush; BorderThickness = new Thickness(1); foreach (var rect in _resizedRectangles) rect.Stroke = brush; _detectionLabelPanel.DetectionClass = value; _detectionClass = value; } } private readonly Rectangle _selectionFrame; private bool _isSelected; public bool IsSelected { get => _isSelected; set { _selectionFrame.Visibility = value ? Visibility.Visible : Visibility.Collapsed; _isSelected = value; } } public void UpdateAdornerScale(double scale) { if (Math.Abs(scale) < 0.0001) return; var inverseScale = 1.0 / scale; BorderThickness = new Thickness(4 * inverseScale); foreach (var rect in _resizedRectangles) { rect.Width = 2 * RESIZE_RECT_SIZE * inverseScale; rect.Height = 2 * RESIZE_RECT_SIZE * inverseScale;; rect.Margin = new Thickness(-RESIZE_RECT_SIZE * 0.7); } } public (HorizontalAlignment Horizontal, VerticalAlignment Vertical) DetectionLabelPosition { get => (DetectionLabelContainer.HorizontalAlignment, DetectionLabelContainer.VerticalAlignment); set { DetectionLabelContainer.HorizontalAlignment = value.Horizontal; DetectionLabelContainer.VerticalAlignment = value.Vertical; } } public DetectionControl(DetectionClass detectionClass, TimeSpan time, Action resizeStart, CanvasLabel canvasLabel) { Width = canvasLabel.Width; Height = canvasLabel.Height; Time = time; _resizeStart = resizeStart; DetectionLabelContainer = new Canvas { HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Top, ClipToBounds = false, }; _detectionLabelPanel = new DetectionLabelPanel { Confidence = canvasLabel.Confidence, DetectionClass = Annotation.DetectionClassesDict[canvasLabel.ClassNumber] }; DetectionLabelContainer.Children.Add(_detectionLabelPanel); _selectionFrame = new Rectangle { Margin = new Thickness(-3), HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch, Stroke = new SolidColorBrush(Colors.Black), StrokeThickness = 2, Visibility = Visibility.Collapsed }; _resizedRectangles = [ CreateResizeRect("rLT", HorizontalAlignment.Left, VerticalAlignment.Top, Cursors.SizeNWSE), CreateResizeRect("rCT", HorizontalAlignment.Center, VerticalAlignment.Top, Cursors.SizeNS), CreateResizeRect("rRT", HorizontalAlignment.Right, VerticalAlignment.Top, Cursors.SizeNESW), CreateResizeRect("rLC", HorizontalAlignment.Left, VerticalAlignment.Center, Cursors.SizeWE), CreateResizeRect("rRC", HorizontalAlignment.Right, VerticalAlignment.Center, Cursors.SizeWE), CreateResizeRect("rLB", HorizontalAlignment.Left, VerticalAlignment.Bottom, Cursors.SizeNESW), CreateResizeRect("rCB", HorizontalAlignment.Center, VerticalAlignment.Bottom, Cursors.SizeNS), CreateResizeRect("rRB", HorizontalAlignment.Right, VerticalAlignment.Bottom, Cursors.SizeNWSE) ]; _grid = new Grid { Background = Brushes.Transparent, HorizontalAlignment = HorizontalAlignment.Stretch, VerticalAlignment = VerticalAlignment.Stretch, Children = { _selectionFrame } }; _grid.Children.Add(DetectionLabelContainer); foreach (var rect in _resizedRectangles) _grid.Children.Add(rect); Child = _grid; Cursor = Cursors.SizeAll; DetectionClass = detectionClass; } //small corners private Rectangle CreateResizeRect(string name, HorizontalAlignment ha, VerticalAlignment va, Cursor crs) { var rect = new Rectangle() // small rectangles at the corners and sides { ClipToBounds = false, Margin = new Thickness(-1.1 * RESIZE_RECT_SIZE), HorizontalAlignment = ha, VerticalAlignment = va, Width = RESIZE_RECT_SIZE, Height = RESIZE_RECT_SIZE, Stroke = new SolidColorBrush(Color.FromArgb(230, 20, 20, 20)), // small rectangles color StrokeThickness = 0.8, Fill = new SolidColorBrush(Color.FromArgb(150, 80, 80, 80)), Cursor = crs, Name = name, }; rect.MouseDown += (sender, args) => _resizeStart(sender, args); rect.MouseUp += (sender, args) => { (sender as UIElement)?.ReleaseMouseCapture(); }; return rect; } public CanvasLabel ToCanvasLabel() => new(DetectionClass.YoloId, Canvas.GetLeft(this), Canvas.GetTop(this), Width, Height); public YoloLabel ToYoloLabel(Size canvasSize, Size? videoSize = null) => new(ToCanvasLabel(), canvasSize, videoSize); }