CtrEditor/ObjectManipulationManager.cs

985 lines
37 KiB
C#
Raw Permalink Normal View History

using CtrEditor.FuncionesBase;
using CtrEditor.ObjetosSim;
using System.Collections.ObjectModel;
using System.Windows;
2025-02-18 14:08:55 -03:00
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using Color = System.Windows.Media.Color;
namespace CtrEditor
{
2025-02-18 17:52:27 -03:00
public enum AlignmentType
{
Left,
Right,
Top,
Bottom,
CenterHorizontally,
CenterVertically,
DistributeHorizontally,
DistributeVertically,
EqualWidth,
EqualHeight,
EqualAngle,
JoinHorizontally,
JoinVertically
2025-02-18 17:52:27 -03:00
}
2025-02-18 14:08:55 -03:00
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<Rectangle> _resizeRectangles = new List<Rectangle>();
private List<Rectangle> _highlightRectangles = new List<Rectangle>();
private System.Threading.Timer _timerRemoveHighlight = null;
private Rectangle _currentDraggingRectangle;
private dataDebug _dataDebug = new dataDebug();
private ObservableCollection<osBase> _selectedObjects = new ObservableCollection<osBase>();
private List<Rectangle> _selectionHighlightRectangles = new List<Rectangle>(); // 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;
2025-02-18 14:08:55 -03:00
public ObjectManipulationManager(MainWindow mainWindow, Canvas canvas)
{
_mainWindow = mainWindow;
_canvas = canvas;
_scrollViewer = mainWindow.ImagenEnTrabajoScrollViewer; // Add this line
_backgroundImage = mainWindow.ImagenDeFondo; // Add this line
2025-02-18 14:08:55 -03:00
}
private void PurgeDeletedObjects()
{
var deletedObjects = _selectedObjects.Where(obj =>
obj.VisualRepresentation == null ||
!_canvas.Children.Contains(obj.VisualRepresentation)).ToList();
foreach (var obj in deletedObjects)
{
DeselectObject(obj);
}
}
2025-02-18 14:08:55 -03:00
public ObservableCollection<osBase> SelectedObjects
{
get
{
PurgeDeletedObjects();
return _selectedObjects;
}
2025-02-18 14:08:55 -03:00
private set
{
_selectedObjects = value;
UpdateSelectionVisuals();
}
}
2025-02-18 17:52:27 -03:00
public void UpdateSelectionVisuals()
2025-02-18 14:08:55 -03:00
{
PurgeDeletedObjects();
// Asegurarse de que el canvas haya actualizado su layout
_canvas.UpdateLayout();
2025-02-18 14:08:55 -03:00
RemoveResizeRectangles();
if (_selectedObjects.Any())
{
// Verificar si la simulación está activa
if (_mainWindow.DataContext is MainViewModel viewModel && !viewModel.IsSimulationRunning)
{
AddResizeRectangles(_selectedObjects);
UpdateSelectionHighlights();
}
2025-02-18 14:08:55 -03:00
}
}
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<osBase> selectedObjects)
{
double rectHighlightSize = 1;
RemoveResizeRectangles();
// Calcular el bounding box que contenga todos los objetos seleccionados
Rect boundingBox = CalculateTotalBoundingBox(selectedObjects);
2025-02-18 14:08:55 -03:00
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<osBase> 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)
2025-02-18 14:08:55 -03:00
{
// 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.");
}
2025-02-18 14:08:55 -03:00
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;
}
2025-02-24 07:37:52 -03:00
private void AddResizeHandles(FuncionesBase.MutableRect rectBox, double defaultRectSize,
2025-02-18 14:08:55 -03:00
Cursor rotationCursorRx, Cursor rotationCursorSx)
{
2025-02-24 07:37:52 -03:00
// 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;
2025-02-18 14:08:55 -03:00
var positions = new List<(Point Position, string Tag, Cursor Cursor, Brush Stroke)>
{
2025-02-24 07:37:52 -03:00
// 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)
2025-02-18 14:08:55 -03:00
};
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();
2025-02-18 14:08:55 -03:00
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)
{
2025-02-26 07:37:19 -03:00
if (_mainWindow.DataContext is MainViewModel vm)
2025-02-18 14:08:55 -03:00
{
2025-02-26 07:37:19 -03:00
// Add new object if not already selected
if (!_selectedObjects.Contains(obj))
{
2025-02-26 07:37:19 -03:00
// If not in multi-selection mode, clear existing selection first
if (!vm.IsMultiSelectionActive)
ClearSelection();
2025-02-26 07:37:19 -03:00
_selectedObjects.Add(obj);
obj.IsSelected = true;
// Add highlight visual only if in multi-selection mode
if (vm.IsMultiSelectionActive)
{
AddSelectionHighlight(obj.VisualRepresentation);
}
UpdateSelectionVisuals();
}
2025-02-18 14:08:55 -03:00
}
}
public void DeselectObject(osBase obj)
{
if (_selectedObjects.Contains(obj))
{
_selectedObjects.Remove(obj);
obj.IsSelected = false;
RemoveSelectionHighlight(obj.VisualRepresentation);
2025-02-18 14:08:55 -03:00
}
}
public void ClearSelection()
{
foreach (var obj in _selectedObjects.ToList())
{
DeselectObject(obj);
}
RemoveAllSelectionHighlights();
2025-02-18 14:08:55 -03:00
RemoveResizeRectangles();
2025-02-18 14:08:55 -03:00
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;
}
}
2025-02-18 14:08:55 -03:00
}
}
private void UpdateSelectionHighlights()
{
UpdateAllSelectionHighlights();
}
2025-02-18 14:08:55 -03:00
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();
2025-02-18 14:08:55 -03:00
var dx = currentPosition.X - _startPointUserControl.X;
var dy = currentPosition.Y - _startPointUserControl.Y;
RemoveAllSelectionHighlights(); // Remover antes de mover
2025-02-18 14:08:55 -03:00
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();
2025-02-18 14:08:55 -03:00
}
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
2025-02-18 14:08:55 -03:00
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);
}
}
2025-02-18 14:08:55 -03:00
_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
2025-02-18 14:08:55 -03:00
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();
2025-02-18 14:08:55 -03:00
}
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
2025-02-18 14:08:55 -03:00
// 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();
2025-02-18 14:08:55 -03:00
}
2025-02-18 17:52:27 -03:00
public void AlignObjects(AlignmentType alignmentType)
{
PurgeDeletedObjects();
2025-02-18 17:52:27 -03:00
if (_selectedObjects.Count <= 1) return;
var alignment = new ObjectAlignment(_selectedObjects, _selectedObjects.FirstOrDefault());
2025-02-18 17:52:27 -03:00
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;
2025-02-18 17:52:27 -03:00
}
// 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<UserControl>().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);
}
}
2025-02-18 14:08:55 -03:00
}
}