using CSScripting; using OxyPlot.Utilities; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using WpfShapes = System.Windows.Shapes; using WpfPoint = System.Windows.Point; using netDxf.Entities; namespace TeamAAS_VP.DxfModule { public class InteractionController { private readonly Canvas _canvas; private readonly HashSet _selectedElements = new HashSet(); private WpfPoint _selectionStartPoint; private WpfShapes.Rectangle _selectionRectangle; private bool _isSelecting = false; public event EventHandler SelectionChanged; public InteractionController(Canvas canvas) { _canvas = canvas; AttachEvents(); } private void AttachEvents() { _canvas.MouseLeftButtonDown += Canvas_MouseLeftButtonDown; _canvas.MouseLeftButtonUp += Canvas_MouseLeftButtonUp; _canvas.MouseMove += Canvas_MouseMove; _canvas.MouseRightButtonDown += Canvas_MouseRightButtonDown; } private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { _selectionStartPoint = e.GetPosition(_canvas); _isSelecting = true; // Check if clicking on an element var hitElement = GetElementAtPoint(_selectionStartPoint); if (hitElement != null) { // Single selection if (!Keyboard.IsKeyDown(Key.LeftCtrl) && !Keyboard.IsKeyDown(Key.RightCtrl)) { ClearSelection(); } ToggleSelection(hitElement); } else { // Start box selection if (!Keyboard.IsKeyDown(Key.LeftCtrl) && !Keyboard.IsKeyDown(Key.RightCtrl)) { ClearSelection(); } _selectionRectangle = new WpfShapes.Rectangle { Stroke = Brushes.Blue, StrokeThickness = 1, StrokeDashArray = new DoubleCollection { 4, 2 }, Fill = new SolidColorBrush(Color.FromArgb(30, 0, 0, 255)) }; _canvas.Children.Add(_selectionRectangle); } } private void Canvas_MouseMove(object sender, MouseEventArgs e) { if (_isSelecting && _selectionRectangle != null) { var currentPoint = e.GetPosition(_canvas); var x = Math.Min(_selectionStartPoint.X, currentPoint.X); var y = Math.Min(_selectionStartPoint.Y, currentPoint.Y); var width = Math.Abs(_selectionStartPoint.X - currentPoint.X); var height = Math.Abs(_selectionStartPoint.Y - currentPoint.Y); Canvas.SetLeft(_selectionRectangle, x); Canvas.SetTop(_selectionRectangle, y); _selectionRectangle.Width = width; _selectionRectangle.Height = height; } } private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (_isSelecting && _selectionRectangle != null) { var endPoint = e.GetPosition(_canvas); var rect = new Rect(_selectionStartPoint, endPoint); // Select elements within the rectangle foreach (UIElement element in _canvas.Children) { if (element == _selectionRectangle) continue; if (IsElementIntersecting(element, rect)) { AddToSelection(element); } } _canvas.Children.Remove(_selectionRectangle); _selectionRectangle = null; } _isSelecting = false; } private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { // Clear selection on right-click ClearSelection(); } private UIElement GetElementAtPoint(WpfPoint point) { HitTestResult result = VisualTreeHelper.HitTest(_canvas, point); if (result != null && result.VisualHit is UIElement element) { // Make sure it's not the canvas itself if (element != _canvas && element.GetType() != typeof(WpfShapes.Rectangle)) { return element; } } return null; } private bool IsElementIntersecting(UIElement element, Rect selectionRect) { try { var elementBounds = GetElementBounds(element); return selectionRect.IntersectsWith(elementBounds); } catch { return false; } } private Rect GetElementBounds(UIElement element) { if (element is WpfShapes.Line line) { var x1 = line.X1; var y1 = line.Y1; var x2 = line.X2; var y2 = line.Y2; return new Rect( new WpfPoint(Math.Min(x1, x2), Math.Min(y1, y2)), new WpfPoint(Math.Max(x1, x2), Math.Max(y1, y2)) ); } else if (element is WpfShapes.Ellipse ellipse) { var left = Canvas.GetLeft(ellipse); var top = Canvas.GetTop(ellipse); return new Rect(left, top, ellipse.Width, ellipse.Height); } else if (element is WpfShapes.Shape shape) { return shape.RenderedGeometry.Bounds; } else if (element is FrameworkElement fe) { var left = Canvas.GetLeft(fe); var top = Canvas.GetTop(fe); return new Rect(left, top, fe.ActualWidth, fe.ActualHeight); } return Rect.Empty; } private void ToggleSelection(UIElement element) { if (_selectedElements.Contains(element)) { RemoveFromSelection(element); } else { AddToSelection(element); } } private void AddToSelection(UIElement element) { if (element is FrameworkElement fe && fe.Tag is EntityObject) { _selectedElements.Add(element); GraphicsRenderer.HighlightElement(element, true); OnSelectionChanged(); } } private void RemoveFromSelection(UIElement element) { if (_selectedElements.Contains(element)) { _selectedElements.Remove(element); GraphicsRenderer.HighlightElement(element, false); OnSelectionChanged(); } } public void ClearSelection() { foreach (var element in _selectedElements.ToList()) { GraphicsRenderer.HighlightElement(element, false); } _selectedElements.Clear(); OnSelectionChanged(); } public List GetSelectedEntities() { return _selectedElements .OfType() .Where(e => e.Tag is EntityObject) .Select(e => (EntityObject)e.Tag) .ToList(); } public int SelectedCount => _selectedElements.Count; private void OnSelectionChanged() { SelectionChanged?.Invoke(this, new SelectionChangedEventArgs(GetSelectedEntities())); } public void Detach() { _canvas.MouseLeftButtonDown -= Canvas_MouseLeftButtonDown; _canvas.MouseLeftButtonUp -= Canvas_MouseLeftButtonUp; _canvas.MouseMove -= Canvas_MouseMove; _canvas.MouseRightButtonDown -= Canvas_MouseRightButtonDown; } } public class SelectionChangedEventArgs : EventArgs { public List SelectedEntities { get; } public SelectionChangedEventArgs(List selectedEntities) { SelectedEntities = selectedEntities; } } }