InteractionController.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. using CSScripting;
  2. using OxyPlot.Utilities;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using WpfShapes = System.Windows.Shapes;
  13. using WpfPoint = System.Windows.Point;
  14. using netDxf.Entities;
  15. namespace TeamAAS_VP.DxfModule
  16. {
  17. public class InteractionController
  18. {
  19. private readonly Canvas _canvas;
  20. private readonly HashSet<UIElement> _selectedElements = new HashSet<UIElement>();
  21. private WpfPoint _selectionStartPoint;
  22. private WpfShapes.Rectangle _selectionRectangle;
  23. private bool _isSelecting = false;
  24. public event EventHandler<SelectionChangedEventArgs> SelectionChanged;
  25. public InteractionController(Canvas canvas)
  26. {
  27. _canvas = canvas;
  28. AttachEvents();
  29. }
  30. private void AttachEvents()
  31. {
  32. _canvas.MouseLeftButtonDown += Canvas_MouseLeftButtonDown;
  33. _canvas.MouseLeftButtonUp += Canvas_MouseLeftButtonUp;
  34. _canvas.MouseMove += Canvas_MouseMove;
  35. _canvas.MouseRightButtonDown += Canvas_MouseRightButtonDown;
  36. }
  37. private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  38. {
  39. _selectionStartPoint = e.GetPosition(_canvas);
  40. _isSelecting = true;
  41. // Check if clicking on an element
  42. var hitElement = GetElementAtPoint(_selectionStartPoint);
  43. if (hitElement != null)
  44. {
  45. // Single selection
  46. if (!Keyboard.IsKeyDown(Key.LeftCtrl) && !Keyboard.IsKeyDown(Key.RightCtrl))
  47. {
  48. ClearSelection();
  49. }
  50. ToggleSelection(hitElement);
  51. }
  52. else
  53. {
  54. // Start box selection
  55. if (!Keyboard.IsKeyDown(Key.LeftCtrl) && !Keyboard.IsKeyDown(Key.RightCtrl))
  56. {
  57. ClearSelection();
  58. }
  59. _selectionRectangle = new WpfShapes.Rectangle
  60. {
  61. Stroke = Brushes.Blue,
  62. StrokeThickness = 1,
  63. StrokeDashArray = new DoubleCollection { 4, 2 },
  64. Fill = new SolidColorBrush(Color.FromArgb(30, 0, 0, 255))
  65. };
  66. _canvas.Children.Add(_selectionRectangle);
  67. }
  68. }
  69. private void Canvas_MouseMove(object sender, MouseEventArgs e)
  70. {
  71. if (_isSelecting && _selectionRectangle != null)
  72. {
  73. var currentPoint = e.GetPosition(_canvas);
  74. var x = Math.Min(_selectionStartPoint.X, currentPoint.X);
  75. var y = Math.Min(_selectionStartPoint.Y, currentPoint.Y);
  76. var width = Math.Abs(_selectionStartPoint.X - currentPoint.X);
  77. var height = Math.Abs(_selectionStartPoint.Y - currentPoint.Y);
  78. Canvas.SetLeft(_selectionRectangle, x);
  79. Canvas.SetTop(_selectionRectangle, y);
  80. _selectionRectangle.Width = width;
  81. _selectionRectangle.Height = height;
  82. }
  83. }
  84. private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
  85. {
  86. if (_isSelecting && _selectionRectangle != null)
  87. {
  88. var endPoint = e.GetPosition(_canvas);
  89. var rect = new Rect(_selectionStartPoint, endPoint);
  90. // Select elements within the rectangle
  91. foreach (UIElement element in _canvas.Children)
  92. {
  93. if (element == _selectionRectangle)
  94. continue;
  95. if (IsElementIntersecting(element, rect))
  96. {
  97. AddToSelection(element);
  98. }
  99. }
  100. _canvas.Children.Remove(_selectionRectangle);
  101. _selectionRectangle = null;
  102. }
  103. _isSelecting = false;
  104. }
  105. private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
  106. {
  107. // Clear selection on right-click
  108. ClearSelection();
  109. }
  110. private UIElement GetElementAtPoint(WpfPoint point)
  111. {
  112. HitTestResult result = VisualTreeHelper.HitTest(_canvas, point);
  113. if (result != null && result.VisualHit is UIElement element)
  114. {
  115. // Make sure it's not the canvas itself
  116. if (element != _canvas && element.GetType() != typeof(WpfShapes.Rectangle))
  117. {
  118. return element;
  119. }
  120. }
  121. return null;
  122. }
  123. private bool IsElementIntersecting(UIElement element, Rect selectionRect)
  124. {
  125. try
  126. {
  127. var elementBounds = GetElementBounds(element);
  128. return selectionRect.IntersectsWith(elementBounds);
  129. }
  130. catch
  131. {
  132. return false;
  133. }
  134. }
  135. private Rect GetElementBounds(UIElement element)
  136. {
  137. if (element is WpfShapes.Line line)
  138. {
  139. var x1 = line.X1;
  140. var y1 = line.Y1;
  141. var x2 = line.X2;
  142. var y2 = line.Y2;
  143. return new Rect(
  144. new WpfPoint(Math.Min(x1, x2), Math.Min(y1, y2)),
  145. new WpfPoint(Math.Max(x1, x2), Math.Max(y1, y2))
  146. );
  147. }
  148. else if (element is WpfShapes.Ellipse ellipse)
  149. {
  150. var left = Canvas.GetLeft(ellipse);
  151. var top = Canvas.GetTop(ellipse);
  152. return new Rect(left, top, ellipse.Width, ellipse.Height);
  153. }
  154. else if (element is WpfShapes.Shape shape)
  155. {
  156. return shape.RenderedGeometry.Bounds;
  157. }
  158. else if (element is FrameworkElement fe)
  159. {
  160. var left = Canvas.GetLeft(fe);
  161. var top = Canvas.GetTop(fe);
  162. return new Rect(left, top, fe.ActualWidth, fe.ActualHeight);
  163. }
  164. return Rect.Empty;
  165. }
  166. private void ToggleSelection(UIElement element)
  167. {
  168. if (_selectedElements.Contains(element))
  169. {
  170. RemoveFromSelection(element);
  171. }
  172. else
  173. {
  174. AddToSelection(element);
  175. }
  176. }
  177. private void AddToSelection(UIElement element)
  178. {
  179. if (element is FrameworkElement fe && fe.Tag is EntityObject)
  180. {
  181. _selectedElements.Add(element);
  182. GraphicsRenderer.HighlightElement(element, true);
  183. OnSelectionChanged();
  184. }
  185. }
  186. private void RemoveFromSelection(UIElement element)
  187. {
  188. if (_selectedElements.Contains(element))
  189. {
  190. _selectedElements.Remove(element);
  191. GraphicsRenderer.HighlightElement(element, false);
  192. OnSelectionChanged();
  193. }
  194. }
  195. public void ClearSelection()
  196. {
  197. foreach (var element in _selectedElements.ToList())
  198. {
  199. GraphicsRenderer.HighlightElement(element, false);
  200. }
  201. _selectedElements.Clear();
  202. OnSelectionChanged();
  203. }
  204. public List<EntityObject> GetSelectedEntities()
  205. {
  206. return _selectedElements
  207. .OfType<FrameworkElement>()
  208. .Where(e => e.Tag is EntityObject)
  209. .Select(e => (EntityObject)e.Tag)
  210. .ToList();
  211. }
  212. public int SelectedCount => _selectedElements.Count;
  213. private void OnSelectionChanged()
  214. {
  215. SelectionChanged?.Invoke(this, new SelectionChangedEventArgs(GetSelectedEntities()));
  216. }
  217. public void Detach()
  218. {
  219. _canvas.MouseLeftButtonDown -= Canvas_MouseLeftButtonDown;
  220. _canvas.MouseLeftButtonUp -= Canvas_MouseLeftButtonUp;
  221. _canvas.MouseMove -= Canvas_MouseMove;
  222. _canvas.MouseRightButtonDown -= Canvas_MouseRightButtonDown;
  223. }
  224. }
  225. public class SelectionChangedEventArgs : EventArgs
  226. {
  227. public List<EntityObject> SelectedEntities { get; }
  228. public SelectionChangedEventArgs(List<EntityObject> selectedEntities)
  229. {
  230. SelectedEntities = selectedEntities;
  231. }
  232. }
  233. }