using CtrEditor.FuncionesBase; using CtrEditor.ObjetosSim; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; using Color = System.Windows.Media.Color; namespace CtrEditor { public enum AlignmentType { Left, Right, Top, Bottom, CenterHorizontally, CenterVertically, DistributeHorizontally, DistributeVertically, EqualWidth, EqualHeight, EqualAngle, JoinHorizontally, JoinVertically } public class ObjectManipulationManager { private enum ResizeMode { None, Move, Rotate, ResizeWidth, ResizeHeight, ResizeBoth } private enum HandleMode { None, Move, ResizeWidth, ResizeHeight, ResizeBoth, Rotate } private ResizeMode _currentResizeMode; private readonly MainWindow _mainWindow; private readonly Canvas _canvas; private Point _lastMousePosition; private bool _isDrawingCanvas = false; private bool _isDraggingUserControl = false; private bool _isMovingUserControl = false; private UserControl _currentDraggingControl; private Point _startPointUserControl; private Point _transformedBoundingBoxCenter; private float _lastAngle; private List _resizeRectangles = new List(); private List _highlightRectangles = new List(); private System.Threading.Timer _timerRemoveHighlight = null; private Rectangle _currentDraggingRectangle; private dataDebug _dataDebug = new dataDebug(); private ObservableCollection _selectedObjects = new ObservableCollection(); private List _selectionHighlightRectangles = new List(); // Add this line private List<(UserControl Control, Rectangle Highlight)> _selectionHighlightPairs = new List<(UserControl, Rectangle)>(); private Point _rectangleStart; public Rectangle _selectionRectangle; // Cambiado a private private ScrollViewer _scrollViewer; // Add this line private Image _backgroundImage; // Add this line internal bool IsDraggingCanvas { get; set; } private bool _isRectangleSelectionActive; public bool IsRectangleSelectionActive { get => _isRectangleSelectionActive; set { _isRectangleSelectionActive = value; if (value) { // Al activar la selección por rectángulo, desactivar el panning IsDraggingCanvas = false; } } } // Propiedad pública para verificar si hay un rectángulo de selección activo public bool HasActiveSelectionRectangle => _selectionRectangle != null; public ObjectManipulationManager(MainWindow mainWindow, Canvas canvas) { _mainWindow = mainWindow; _canvas = canvas; _scrollViewer = mainWindow.ImagenEnTrabajoScrollViewer; // Add this line _backgroundImage = mainWindow.ImagenDeFondo; // Add this line } private void PurgeDeletedObjects() { var deletedObjects = _selectedObjects.Where(obj => obj.VisualRepresentation == null || !_canvas.Children.Contains(obj.VisualRepresentation)).ToList(); foreach (var obj in deletedObjects) { DeselectObject(obj); } } public ObservableCollection SelectedObjects { get { PurgeDeletedObjects(); return _selectedObjects; } private set { _selectedObjects = value; UpdateSelectionVisuals(); } } public void UpdateSelectionVisuals() { PurgeDeletedObjects(); // Asegurarse de que el canvas haya actualizado su layout _canvas.UpdateLayout(); RemoveResizeRectangles(); if (_selectedObjects.Any()) { // Verificar si la simulación está activa if (_mainWindow.DataContext is MainViewModel viewModel && !viewModel.IsSimulationRunning) { AddResizeRectangles(_selectedObjects); UpdateSelectionHighlights(); } } } public void SuscribirEventos(UserControl userControl) { userControl.MouseEnter += UserControl_MouseEnter; userControl.MouseLeave += UserControl_MouseLeave; userControl.Cursor = Cursors.Hand; userControl.MouseLeftButtonDown += UserControl_MouseLeftButtonDown; userControl.MouseLeftButtonUp += UserControl_MouseLeftButtonUp; userControl.MouseMove += UserControl_MouseMove; } private void UserControl_MouseEnter(object sender, MouseEventArgs e) { if (sender is UserControl userControl && userControl is IDataContainer dataContainer) { dataContainer.Highlight(true); if (_mainWindow.DataContext is MainViewModel viewModel) { var selectedObject = viewModel.SelectedItemOsList; if (selectedObject?.VisualRepresentation != userControl) { AddHighlightRectangles(userControl); } } } } private void UserControl_MouseLeave(object sender, MouseEventArgs e) { if (sender is UserControl userControl && userControl is IDataContainer dataContainer) dataContainer.Highlight(false); } public void AddResizeRectangles(IEnumerable selectedObjects) { double rectHighlightSize = 1; RemoveResizeRectangles(); // Calcular el bounding box que contenga todos los objetos seleccionados Rect boundingBox = CalculateTotalBoundingBox(selectedObjects); FuncionesBase.MutableRect rectBox = new FuncionesBase.MutableRect(boundingBox); rectBox.Left -= (float)rectHighlightSize; rectBox.Right += (float)rectHighlightSize; rectBox.Top -= (float)rectHighlightSize; rectBox.Bottom += (float)rectHighlightSize; _transformedBoundingBoxCenter = new Point( boundingBox.Left + boundingBox.Width / 2, boundingBox.Top + boundingBox.Height / 2 ); // Selection rectangle Rectangle selectionRect = CreateSelectionRectangle(rectBox, rectHighlightSize); _resizeRectangles.Add(selectionRect); _canvas.Children.Add(selectionRect); // Load rotation cursors Cursor rotationCursorRx = new Cursor(Application.GetResourceStream( new Uri("pack://application:,,,/CtrEditor;component/Icons/rotationRx.cur")).Stream); Cursor rotationCursorSx = new Cursor(Application.GetResourceStream( new Uri("pack://application:,,,/CtrEditor;component/Icons/rotationSx.cur")).Stream); // Add resize/rotation handles AddResizeHandles(rectBox, 10, rotationCursorRx, rotationCursorSx); } private Rect CalculateTotalBoundingBox(IEnumerable selectedObjects) { double left = double.MaxValue; double top = double.MaxValue; double right = double.MinValue; double bottom = double.MinValue; foreach (var obj in selectedObjects) { if (obj.VisualRepresentation != null) { // Obtener el bounding box del objeto actual Rect objectBounds = VisualTreeHelper.GetDescendantBounds(obj.VisualRepresentation); GeneralTransform transform = obj.VisualRepresentation.TransformToAncestor(_canvas); Rect transformedBounds = transform.TransformBounds(objectBounds); // Actualizar los límites del bounding box total left = Math.Min(left, transformedBounds.Left); top = Math.Min(top, transformedBounds.Top); right = Math.Max(right, transformedBounds.Right); bottom = Math.Max(bottom, transformedBounds.Bottom); } } return new Rect( new Point(left, top), new Point(right, bottom) ); } private Rectangle CreateSelectionRectangle(FuncionesBase.MutableRect rectBox, double rectHighlightSize) { if (double.IsInfinity(rectBox.Width) || double.IsInfinity(rectBox.Height) || double.IsNaN(rectBox.Width) || double.IsNaN(rectBox.Height)) { throw new ArgumentException("Invalid dimensions for selection rectangle."); } var rect = new Rectangle { Width = rectBox.Width + (rectHighlightSize * 2), Height = rectBox.Height + (rectHighlightSize * 2), Fill = Brushes.Transparent, Stroke = new SolidColorBrush(Color.FromArgb(180, 0, 120, 215)), StrokeThickness = 1.5, Tag = "Selection", IsHitTestVisible = false, StrokeDashArray = new DoubleCollection(new double[] { 3, 3 }) }; Canvas.SetLeft(rect, rectBox.Left - rectHighlightSize); Canvas.SetTop(rect, rectBox.Top - rectHighlightSize); Canvas.SetZIndex(rect, ((int)ZIndexEnum.RectangulosPropiead - 1)); return rect; } private void AddResizeHandles(FuncionesBase.MutableRect rectBox, double defaultRectSize, Cursor rotationCursorRx, Cursor rotationCursorSx) { // Calcular el tamaño apropiado para los manejadores basado en el tamaño del objeto double minObjectDimension = Math.Min(rectBox.Width, rectBox.Height); double rectSize = Math.Min(defaultRectSize, minObjectDimension / 3); // Asegurar un tamaño mínimo para los manejadores rectSize = Math.Max(rectSize, 6); // Calcular el offset para posicionar los manejadores fuera del rectángulo double offset = rectSize / 2; var positions = new List<(Point Position, string Tag, Cursor Cursor, Brush Stroke)> { // Esquinas - mover hacia afuera del rectángulo (new Point(rectBox.Left - offset, rectBox.Top - offset), "TopLeft", Cursors.Arrow, Brushes.Gray), (new Point(rectBox.Right + offset, rectBox.Top - offset), "TopRight", rotationCursorRx, Brushes.Red), (new Point(rectBox.Left - offset, rectBox.Bottom + offset), "BottomLeft", rotationCursorSx, Brushes.DarkRed), (new Point(rectBox.Right + offset, rectBox.Bottom + offset), "BottomRight", Cursors.SizeNWSE, Brushes.Blue), // Centros de los bordes - mover hacia afuera del rectángulo (new Point(rectBox.Left + rectBox.Width / 2, rectBox.Top - offset), "TopCenter", Cursors.Arrow, Brushes.Gray), (new Point(rectBox.Left + rectBox.Width / 2, rectBox.Bottom + offset), "BottomCenter", Cursors.SizeNS, Brushes.Blue), (new Point(rectBox.Left - offset, rectBox.Top + rectBox.Height / 2), "CenterLeft", rotationCursorRx, Brushes.Red), (new Point(rectBox.Right + offset, rectBox.Top + rectBox.Height / 2), "CenterRight", Cursors.SizeWE, Brushes.Blue) }; foreach (var (Position, Tag, Cursor, Stroke) in positions) { var handle = CreateResizeHandle(rectSize, Tag, Cursor, Stroke); SetHandlePosition(handle, Position, rectSize); _resizeRectangles.Add(handle); _canvas.Children.Add(handle); } } private Rectangle CreateResizeHandle(double rectSize, string tag, Cursor cursor, Brush stroke) { var handle = new Rectangle { Width = rectSize, Height = rectSize, Fill = Brushes.Transparent, Stroke = stroke, StrokeThickness = 1, Tag = tag, Cursor = cursor }; handle.MouseLeftButtonDown += UserControl_MouseLeftButtonDown; handle.MouseMove += UserControl_MouseMove; handle.MouseLeftButtonUp += UserControl_MouseLeftButtonUp; handle.MouseLeave += ResizeRectangle_MouseLeave; Canvas.SetZIndex(handle, (int)ZIndexEnum.RectangulosPropiead); return handle; } private void SetHandlePosition(Rectangle handle, Point position, double rectSize) { if (!double.IsInfinity(position.X) && !double.IsNaN(position.X)) Canvas.SetLeft(handle, position.X - rectSize / 2); if (!double.IsInfinity(position.Y) && !double.IsNaN(position.Y)) Canvas.SetTop(handle, position.Y - rectSize / 2); } public void RemoveResizeRectangles() { if (_resizeRectangles == null || _resizeRectangles.Count == 0) return; foreach (var rect in _resizeRectangles) { _canvas.Children.Remove(rect); } _resizeRectangles.Clear(); } public void MakeResizeRectanglesTransparent() { if (_resizeRectangles == null || _resizeRectangles.Count == 0) return; foreach (var rect in _resizeRectangles) { rect.Opacity = 0; } } public void MakeResizeRectanglesNormal() { if (_resizeRectangles == null || _resizeRectangles.Count == 0) return; foreach (var rect in _resizeRectangles) { rect.Opacity = 1; } } private void HandleObjectSelection(UserControl userControl, osBase datos) { PurgeDeletedObjects(); var viewModel = _mainWindow.DataContext as MainViewModel; if (viewModel == null) return; bool isControlPressed = Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl); if (viewModel.IsMultiSelectionActive) { if (isControlPressed) { // Deseleccionar objeto si está presionada la tecla Ctrl if (_selectedObjects.Contains(datos)) { DeselectObject(datos); } } else if (!_selectedObjects.Contains(datos)) { // Seleccionar objeto si no está ya seleccionado SelectObject(datos); } } else { // Modo selección única ClearSelection(); SelectObject(datos); } viewModel.SelectedItemOsList = datos; UpdateSelectionVisuals(); } public void SelectObject(osBase obj) { if (_mainWindow.DataContext is MainViewModel vm) { // Add new object if not already selected if (!_selectedObjects.Contains(obj)) { // If not in multi-selection mode, clear existing selection first if (!vm.IsMultiSelectionActive) ClearSelection(); _selectedObjects.Add(obj); obj.IsSelected = true; // Add highlight visual only if in multi-selection mode if (vm.IsMultiSelectionActive) { AddSelectionHighlight(obj.VisualRepresentation); } UpdateSelectionVisuals(); } } } public void DeselectObject(osBase obj) { if (_selectedObjects.Contains(obj)) { _selectedObjects.Remove(obj); obj.IsSelected = false; RemoveSelectionHighlight(obj.VisualRepresentation); } } public void ClearSelection() { foreach (var obj in _selectedObjects.ToList()) { DeselectObject(obj); } RemoveAllSelectionHighlights(); RemoveResizeRectangles(); if (_mainWindow.DataContext is MainViewModel viewModel) { viewModel.SelectedItemOsList = null; } } public void OnMultiSelectionModeChanged(bool isActive) { if (!isActive) { // Mantener solo el último objeto seleccionado if (_selectedObjects.Count > 1) { var lastSelected = _selectedObjects.Last(); ClearSelection(); SelectObject(lastSelected); } RemoveAllSelectionHighlights(); } else { UpdateAllSelectionHighlights(); } } private void AddSelectionHighlight(UserControl userControl, bool isReference = false) { if (userControl == null) return; RemoveSelectionHighlight(userControl); Rect boundingBox = VisualTreeHelper.GetDescendantBounds(userControl); GeneralTransform transform = userControl.TransformToAncestor(_canvas); Rect transformedBoundingBox = transform.TransformBounds(boundingBox); Rectangle highlightRect = new Rectangle { Width = transformedBoundingBox.Width, Height = transformedBoundingBox.Height, Fill = Brushes.Transparent, Stroke = new SolidColorBrush(isReference ? Color.FromArgb(180, 128, 0, 128) : // Purple for reference Color.FromArgb(180, 255, 0, 0)), // Red for others StrokeThickness = isReference ? 3 : 2, // Más grueso para el de referencia Tag = "SelectionHighlight", IsHitTestVisible = false }; Canvas.SetLeft(highlightRect, transformedBoundingBox.Left); Canvas.SetTop(highlightRect, transformedBoundingBox.Top); Canvas.SetZIndex(highlightRect, (int)ZIndexEnum.RectangulosPropiead - 1); _selectionHighlightPairs.Add((userControl, highlightRect)); _canvas.Children.Add(highlightRect); } private void RemoveSelectionHighlight(UserControl userControl) { var pairsToRemove = _selectionHighlightPairs.Where(p => p.Control == userControl).ToList(); foreach (var pair in pairsToRemove) { _canvas.Children.Remove(pair.Highlight); _selectionHighlightPairs.Remove(pair); } } public void RemoveAllSelectionHighlights() { foreach (var pair in _selectionHighlightPairs) { _canvas.Children.Remove(pair.Highlight); } _selectionHighlightPairs.Clear(); } private void UpdateAllSelectionHighlights() { if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.IsMultiSelectionActive) { RemoveAllSelectionHighlights(); bool isFirst = true; foreach (var selectedObject in _selectedObjects) { if (selectedObject.VisualRepresentation != null) { AddSelectionHighlight(selectedObject.VisualRepresentation, isFirst); isFirst = false; } } } } private void UpdateSelectionHighlights() { UpdateAllSelectionHighlights(); } private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (!_isDrawingCanvas) { if (_resizeRectangles != null && _resizeRectangles.Contains(sender)) { _currentDraggingRectangle = sender as Rectangle; _lastMousePosition = e.GetPosition(_canvas); _currentDraggingRectangle.CaptureMouse(); _isMovingUserControl = true; _startPointUserControl = e.GetPosition(_canvas); e.Handled = true; return; } var userControl = sender as UserControl; if (userControl != null) { if (userControl.DataContext is osBase datos) { HandleObjectSelection(userControl, datos); } // Solo iniciar el arrastre si no se presionó Ctrl if (!(Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))) { userControl.CaptureMouse(); _currentDraggingControl = userControl; _isMovingUserControl = true; InitializeDrag(e); } } } } private void InitializeDrag(MouseButtonEventArgs e) { _isDraggingUserControl = true; _startPointUserControl = e.GetPosition(_canvas); } private void UserControl_MouseMove(object sender, MouseEventArgs e) { if (_isMovingUserControl) { var currentPosition = e.GetPosition(_canvas); MakeResizeRectanglesTransparent(); if (_isDraggingUserControl) { HandleDrag(currentPosition); } else if (_currentDraggingRectangle != null) { string resizeDirection = _currentDraggingRectangle.Tag as string; if (resizeDirection != null) { var mode = DetermineHandleMode(resizeDirection); switch (mode) { case HandleMode.Rotate: HandleRotation(currentPosition); break; case HandleMode.ResizeWidth: case HandleMode.ResizeHeight: case HandleMode.ResizeBoth: HandleResize(currentPosition, mode); break; } } } } } private void HandleDrag(Point currentPosition) { PurgeDeletedObjects(); var dx = currentPosition.X - _startPointUserControl.X; var dy = currentPosition.Y - _startPointUserControl.Y; RemoveAllSelectionHighlights(); // Remover antes de mover foreach (var selectedObject in _selectedObjects) { var newX = Canvas.GetLeft(selectedObject.VisualRepresentation) + dx; var newY = Canvas.GetTop(selectedObject.VisualRepresentation) + dy; selectedObject.Move((float)newX, (float)newY); } _startPointUserControl = currentPosition; UpdateAllSelectionHighlights(); } private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (_isMovingUserControl) { if (sender is UserControl userControl) { userControl.ReleaseMouseCapture(); } else if (sender is Rectangle rectangle) { rectangle.ReleaseMouseCapture(); } RemoveAllSelectionHighlights(); // Remover antes de actualizar UpdateSelectionVisuals(); UpdateAllSelectionHighlights(); // Restaurar los rectángulos de selección si es necesario if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.IsMultiSelectionActive) { foreach (var selectedObject in _selectedObjects) { AddSelectionHighlight(selectedObject.VisualRepresentation); } } _isDraggingUserControl = false; _isMovingUserControl = false; _currentDraggingRectangle = null; _currentResizeMode = ResizeMode.None; _lastAngle = 0; } MarkUnsavedChanges(); } private void MarkUnsavedChanges() { if (_mainWindow.DataContext is MainViewModel viewModel) { if (_isMovingUserControl || _isDraggingUserControl) { viewModel.HasUnsavedChanges = true; } } } private void ResizeRectangle_MouseLeave(object sender, MouseEventArgs e) { var rect = sender as Rectangle; if (rect != null) { rect.Fill = Brushes.Transparent; } } public void AddHighlightRectangles(UserControl userControl) { double rectSize = 1; RemoveHighlightRectangles(); if (userControl is IDataContainer dataContainer && dataContainer.Datos is osBase mvBase && mvBase.Show_On_This_Page) { Rect boundingBox = VisualTreeHelper.GetDescendantBounds(userControl); GeneralTransform transform = userControl.TransformToAncestor(_canvas); Rect transformedBoundingBox = transform.TransformBounds(boundingBox); FuncionesBase.MutableRect rectBox = new FuncionesBase.MutableRect(transformedBoundingBox); rectBox.Left -= (float)rectSize; rectBox.Right += (float)rectSize; rectBox.Top -= (float)rectSize; rectBox.Bottom += (float)rectSize; Rectangle highlightRect = new Rectangle { Width = rectBox.Width, Height = rectBox.Height, Fill = Brushes.Transparent, Stroke = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)), StrokeThickness = 1, Tag = "Highlight", IsHitTestVisible = false, StrokeDashArray = new DoubleCollection(new double[] { 2, 2 }) }; Canvas.SetLeft(highlightRect, rectBox.Left); Canvas.SetTop(highlightRect, rectBox.Top); // Corregido: usando rectBox.Top en lugar de highlightRect.Top _highlightRectangles.Add(highlightRect); _canvas.Children.Add(highlightRect); Canvas.SetZIndex(highlightRect, ((int)ZIndexEnum.RectangulosPropiead)); if (_timerRemoveHighlight == null) _timerRemoveHighlight = new System.Threading.Timer(TimerCallbackRemoveHighlight, null, Timeout.Infinite, Timeout.Infinite); _timerRemoveHighlight.Change(2000, Timeout.Infinite); } } private void TimerCallbackRemoveHighlight(object state) { if (Application.Current != null) { Application.Current.Dispatcher.Invoke(RemoveHighlightRectangles); } } public void RemoveHighlightRectangles() { if (_highlightRectangles == null || _highlightRectangles.Count == 0) return; foreach (var rect in _highlightRectangles) { _canvas.Children.Remove(rect); } _highlightRectangles.Clear(); } private HandleMode DetermineHandleMode(string resizeDirection) { return resizeDirection switch { "TopLeft" => HandleMode.None, "TopRight" or "BottomLeft" or "CenterLeft" => HandleMode.Rotate, "BottomRight" => HandleMode.ResizeBoth, "TopCenter" => HandleMode.None, "BottomCenter" => HandleMode.ResizeHeight, "CenterRight" => HandleMode.ResizeWidth, _ => HandleMode.None }; } private void HandleResize(Point currentPosition, HandleMode mode) { PurgeDeletedObjects(); RemoveAllSelectionHighlights(); // Remover antes de redimensionar foreach (var selectedObject in _selectedObjects) { bool resizeWidth = mode == HandleMode.ResizeWidth || mode == HandleMode.ResizeBoth; bool resizeHeight = mode == HandleMode.ResizeHeight || mode == HandleMode.ResizeBoth; HandleResizeForObject(selectedObject, currentPosition, resizeWidth, resizeHeight); } _startPointUserControl = currentPosition; UpdateAllSelectionHighlights(); } private void HandleResizeForObject(osBase obj, Point currentPosition, bool activateSizeWidth, bool activateSizeHeight) { double widthChange = activateSizeWidth ? currentPosition.X - _startPointUserControl.X : 0; double heightChange = activateSizeHeight ? currentPosition.Y - _startPointUserControl.Y : 0; obj.Resize(widthChange, heightChange); } private void HandleRotation(Point currentPosition) { PurgeDeletedObjects(); RemoveAllSelectionHighlights(); // Remover antes de rotar // Calcular el ángulo respecto al centro del bounding box que contiene todos los objetos seleccionados double deltaX = currentPosition.X - _transformedBoundingBoxCenter.X; double deltaY = currentPosition.Y - _transformedBoundingBoxCenter.Y; double angle = Math.Atan2(deltaY, deltaX) * (180 / Math.PI); if ((_lastAngle == 0 && angle != 0) || Math.Abs(angle - _lastAngle) > 45) { _lastAngle = (float)angle; } else { double deltaAngle = angle - _lastAngle; foreach (var selectedObject in _selectedObjects) { selectedObject.Rotate(deltaAngle); } _lastAngle = (float)angle; } UpdateAllSelectionHighlights(); } public void AlignObjects(AlignmentType alignmentType) { PurgeDeletedObjects(); if (_selectedObjects.Count <= 1) return; var alignment = new ObjectAlignment(_selectedObjects, _selectedObjects.FirstOrDefault()); switch (alignmentType) { case AlignmentType.Left: alignment.AlignLeft(); break; case AlignmentType.Right: alignment.AlignRight(); break; case AlignmentType.Top: alignment.AlignTop(); break; case AlignmentType.Bottom: alignment.AlignBottom(); break; case AlignmentType.CenterHorizontally: alignment.AlignCenterHorizontally(); break; case AlignmentType.CenterVertically: alignment.AlignCenterVertically(); break; case AlignmentType.DistributeHorizontally: alignment.DistributeHorizontally(); break; case AlignmentType.DistributeVertically: alignment.DistributeVertically(); break; case AlignmentType.EqualWidth: alignment.EqualWidth(); break; case AlignmentType.EqualHeight: alignment.EqualHeight(); break; case AlignmentType.EqualAngle: alignment.EqualAngle(); break; case AlignmentType.JoinHorizontally: alignment.JoinHorizontally(); break; case AlignmentType.JoinVertically: alignment.JoinVertically(); break; } // Update the selection visuals after alignment UpdateSelectionVisuals(); } public void EliminarObjetosSeleccionados() { if (_selectedObjects.Count == 0) return; var viewModel = _mainWindow.DataContext as MainViewModel; if (viewModel == null) return; // Crear una copia de la lista para evitar modificaciones durante la iteración var objectsToRemove = _selectedObjects.ToList(); foreach (var obj in objectsToRemove) { viewModel.RemoverObjetoSimulable(obj); } // Limpiar la selección y actualizar la interfaz ClearSelection(); RemoveResizeRectangles(); RemoveAllSelectionHighlights(); // Actualizar el estado de cambios sin guardar if (viewModel != null) { viewModel.HasUnsavedChanges = true; } } public void StartRectangleSelection(Point startPoint) { _rectangleStart = startPoint; _selectionRectangle = new Rectangle { Stroke = Brushes.Blue, StrokeThickness = 1, Fill = new SolidColorBrush(Color.FromArgb(50, 0, 0, 255)) }; Canvas.SetLeft(_selectionRectangle, startPoint.X); Canvas.SetTop(_selectionRectangle, startPoint.Y); Canvas.SetZIndex(_selectionRectangle, (int)ZIndexEnum.RectangulosPropiead); _canvas.Children.Add(_selectionRectangle); } private void UpdateSelectionRectangle(Point currentPoint) { double left = Math.Min(_rectangleStart.X, currentPoint.X); double top = Math.Min(_rectangleStart.Y, currentPoint.Y); double width = Math.Abs(currentPoint.X - _rectangleStart.X); double height = Math.Abs(currentPoint.Y - _rectangleStart.Y); _selectionRectangle.Width = width; _selectionRectangle.Height = height; Canvas.SetLeft(_selectionRectangle, left); Canvas.SetTop(_selectionRectangle, top); } public void FinishRectangleSelection(Point currentPoint) { if (_selectionRectangle != null) { var left = Canvas.GetLeft(_selectionRectangle); var top = Canvas.GetTop(_selectionRectangle); var right = left + _selectionRectangle.Width; var bottom = top + _selectionRectangle.Height; var selectionBounds = new Rect(new Point(left, top), new Point(right, bottom)); var itemsToProcess = _canvas.Children.OfType().Where(child => child is IDataContainer).ToList(); foreach (var child in itemsToProcess) { var childBounds = GetElementBounds(child); if (selectionBounds.Contains(childBounds) || selectionBounds.IntersectsWith(childBounds)) { if (child.DataContext is osBase osObject) { SelectObject(osObject); } } } _canvas.Children.Remove(_selectionRectangle); _selectionRectangle = null; UpdateSelectionVisuals(); } } private Rect GetElementBounds(FrameworkElement element) { var bounds = VisualTreeHelper.GetDescendantBounds(element); var transform = element.TransformToAncestor(_canvas); return transform.TransformBounds(bounds); } public void UpdateRectangleSelection(Point currentPoint) { if (_selectionRectangle != null) { UpdateSelectionRectangle(currentPoint); } } } }