Rectangulo de seleccion funcionando para seleccionar multiples objetos
This commit is contained in:
parent
061007158d
commit
d06607ccc6
|
@ -6,6 +6,7 @@ using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Shapes;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
||||||
using UserControl = System.Windows.Controls.UserControl;
|
using UserControl = System.Windows.Controls.UserControl;
|
||||||
|
@ -61,6 +62,9 @@ namespace CtrEditor
|
||||||
|
|
||||||
// Importante: Agregar el evento para el menú contextual
|
// Importante: Agregar el evento para el menú contextual
|
||||||
ImagenEnTrabajoCanvas.MouseRightButtonDown += Canvas_MouseRightButtonDown;
|
ImagenEnTrabajoCanvas.MouseRightButtonDown += Canvas_MouseRightButtonDown;
|
||||||
|
|
||||||
|
// Asegurarse de que estos eventos estén conectados
|
||||||
|
ImagenEnTrabajoCanvas.MouseUp += Canvas_MouseUp_Panning;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
@ -147,20 +151,36 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (e.LeftButton == MouseButtonState.Pressed && !_isDrawingCanvas)
|
if (e.LeftButton == MouseButtonState.Pressed && !_isDrawingCanvas)
|
||||||
{
|
{
|
||||||
// Solo permitir el panning si el clic fue en el canvas o en la imagen de fondo
|
// Verificar si el clic fue en el canvas, imagen de fondo o en el rectángulo de selección
|
||||||
// y no en otros controles
|
if (e.Source == ImagenEnTrabajoCanvas ||
|
||||||
if (e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo)
|
e.Source == imagenDeFondo ||
|
||||||
|
(e.Source is Rectangle rect && rect == _objectManager._selectionRectangle))
|
||||||
{
|
{
|
||||||
ImagenEnTrabajoCanvas.Focus(); // Asegurar que el canvas tiene el foco
|
ImagenEnTrabajoCanvas.Focus();
|
||||||
_isDraggingCanvas = true;
|
|
||||||
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
|
||||||
ImagenEnTrabajoCanvas.CaptureMouse();
|
|
||||||
Mouse.OverrideCursor = Cursors.Hand;
|
|
||||||
|
|
||||||
if (DataContext is MainViewModel viewModel)
|
if (_objectManager.IsRectangleSelectionActive)
|
||||||
{
|
{
|
||||||
viewModel.SelectedItemOsList = null;
|
if (!_objectManager.HasActiveSelectionRectangle)
|
||||||
_objectManager.RemoveResizeRectangles();
|
{
|
||||||
|
_objectManager.StartRectangleSelection(e.GetPosition(ImagenEnTrabajoCanvas));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_objectManager.FinishRectangleSelection(e.GetPosition(ImagenEnTrabajoCanvas));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_isDraggingCanvas = true;
|
||||||
|
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
||||||
|
ImagenEnTrabajoCanvas.CaptureMouse();
|
||||||
|
Mouse.OverrideCursor = Cursors.Hand;
|
||||||
|
|
||||||
|
if (DataContext is MainViewModel viewModel)
|
||||||
|
{
|
||||||
|
viewModel.SelectedItemOsList = null;
|
||||||
|
_objectManager.RemoveResizeRectangles();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
@ -169,7 +189,12 @@ namespace CtrEditor
|
||||||
|
|
||||||
private void Canvas_MouseMove_Panning(object sender, MouseEventArgs e)
|
private void Canvas_MouseMove_Panning(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
if (_isDraggingCanvas && e.LeftButton == MouseButtonState.Pressed)
|
if (_objectManager.IsRectangleSelectionActive && _objectManager.HasActiveSelectionRectangle)
|
||||||
|
{
|
||||||
|
var currentPoint = e.GetPosition(ImagenEnTrabajoCanvas);
|
||||||
|
_objectManager.UpdateRectangleSelection(currentPoint);
|
||||||
|
}
|
||||||
|
else if (_isDraggingCanvas && e.LeftButton == MouseButtonState.Pressed)
|
||||||
{
|
{
|
||||||
var currentPosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
var currentPosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
||||||
var dx = currentPosition.X - _lastMousePosition.X;
|
var dx = currentPosition.X - _lastMousePosition.X;
|
||||||
|
@ -436,59 +461,116 @@ namespace CtrEditor
|
||||||
private void ShowContextMenu(Point position)
|
private void ShowContextMenu(Point position)
|
||||||
{
|
{
|
||||||
var contextMenu = new ContextMenu();
|
var contextMenu = new ContextMenu();
|
||||||
var multiSelectMenuItem = new MenuItem
|
|
||||||
{
|
|
||||||
Header = "Modo Multi-Selección",
|
|
||||||
IsCheckable = true,
|
|
||||||
StaysOpenOnClick = false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (DataContext is MainViewModel viewModel)
|
if (DataContext is MainViewModel viewModel)
|
||||||
{
|
{
|
||||||
multiSelectMenuItem.IsChecked = viewModel.IsMultiSelectionActive;
|
// Multi-selection checkbox
|
||||||
|
var multiSelectMenuItem = new MenuItem
|
||||||
|
{
|
||||||
|
Header = "Modo Multi-Selección",
|
||||||
|
IsCheckable = true,
|
||||||
|
StaysOpenOnClick = false,
|
||||||
|
IsChecked = viewModel.IsMultiSelectionActive
|
||||||
|
};
|
||||||
|
|
||||||
multiSelectMenuItem.Click += (s, e) =>
|
multiSelectMenuItem.Click += (s, e) =>
|
||||||
{
|
{
|
||||||
viewModel.IsMultiSelectionActive = multiSelectMenuItem.IsChecked;
|
viewModel.IsMultiSelectionActive = multiSelectMenuItem.IsChecked;
|
||||||
|
|
||||||
|
// Si se desactiva la multi-selección, desactivar también la selección por rectángulo
|
||||||
|
if (!multiSelectMenuItem.IsChecked)
|
||||||
|
_objectManager.IsRectangleSelectionActive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Solo mostrar opciones de alineación si hay objetos seleccionados
|
contextMenu.Items.Add(multiSelectMenuItem);
|
||||||
if (_objectManager.SelectedObjects.Count > 1)
|
|
||||||
|
// Mostrar opción de selección por rectángulo solo cuando multi-selección está activa
|
||||||
|
if (viewModel.IsMultiSelectionActive)
|
||||||
{
|
{
|
||||||
var alignmentMenu = new MenuItem { Header = "Alinear" };
|
var rectangleSelectMenuItem = new MenuItem
|
||||||
var sizeMenu = new MenuItem { Header = "Igualar Tamaño" };
|
{
|
||||||
var joinMenu = new MenuItem { Header = "Unir" };
|
Header = "Selección por Rectángulo",
|
||||||
|
IsCheckable = true,
|
||||||
|
IsChecked = _objectManager.IsRectangleSelectionActive,
|
||||||
|
StaysOpenOnClick = false
|
||||||
|
};
|
||||||
|
|
||||||
// Opciones de alineación
|
rectangleSelectMenuItem.Click += (s, e) =>
|
||||||
alignmentMenu.Items.Add(new MenuItem { Header = "Alinear a la Izquierda", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.Left)) });
|
{
|
||||||
alignmentMenu.Items.Add(new MenuItem { Header = "Alinear a la Derecha", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.Right)) });
|
_objectManager.IsRectangleSelectionActive = rectangleSelectMenuItem.IsChecked;
|
||||||
alignmentMenu.Items.Add(new MenuItem { Header = "Alinear Arriba", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.Top)) });
|
_objectManager.IsDraggingCanvas = false; // Desactivar panning cuando se activa la selección por rectángulo
|
||||||
alignmentMenu.Items.Add(new MenuItem { Header = "Alinear Abajo", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.Bottom)) });
|
};
|
||||||
alignmentMenu.Items.Add(new Separator());
|
|
||||||
alignmentMenu.Items.Add(new MenuItem { Header = "Centrar Horizontalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.CenterHorizontally)) });
|
|
||||||
alignmentMenu.Items.Add(new MenuItem { Header = "Centrar Verticalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.CenterVertically)) });
|
|
||||||
alignmentMenu.Items.Add(new Separator());
|
|
||||||
alignmentMenu.Items.Add(new MenuItem { Header = "Distribuir Horizontalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.DistributeHorizontally)) });
|
|
||||||
alignmentMenu.Items.Add(new MenuItem { Header = "Distribuir Verticalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.DistributeVertically)) });
|
|
||||||
|
|
||||||
// Opciones de igualar tamaño
|
contextMenu.Items.Add(rectangleSelectMenuItem);
|
||||||
sizeMenu.Items.Add(new MenuItem { Header = "Igualar Ancho", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.EqualWidth)) });
|
|
||||||
sizeMenu.Items.Add(new MenuItem { Header = "Igualar Alto", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.EqualHeight)) });
|
|
||||||
sizeMenu.Items.Add(new MenuItem { Header = "Igualar Ángulo", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.EqualAngle)) });
|
|
||||||
|
|
||||||
// Opciones de unir
|
|
||||||
joinMenu.Items.Add(new MenuItem { Header = "Unir Horizontalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.JoinHorizontally)) });
|
|
||||||
joinMenu.Items.Add(new MenuItem { Header = "Unir Verticalmente", Command = new RelayCommand(() => _objectManager.AlignObjects(AlignmentType.JoinVertically)) });
|
|
||||||
|
|
||||||
contextMenu.Items.Add(alignmentMenu);
|
|
||||||
contextMenu.Items.Add(sizeMenu);
|
|
||||||
contextMenu.Items.Add(joinMenu);
|
|
||||||
contextMenu.Items.Add(new Separator());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
contextMenu.Items.Add(multiSelectMenuItem);
|
// Si hay objetos seleccionados, agregar opciones de alineación
|
||||||
|
if (_objectManager.SelectedObjects.Count > 1)
|
||||||
|
{
|
||||||
|
contextMenu.Items.Add(new Separator());
|
||||||
|
|
||||||
|
var alignSubmenu = new MenuItem { Header = "Alinear" };
|
||||||
|
|
||||||
|
// Alineación horizontal
|
||||||
|
var alignLeftItem = new MenuItem { Header = "Izquierda" };
|
||||||
|
alignLeftItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.Left);
|
||||||
|
alignSubmenu.Items.Add(alignLeftItem);
|
||||||
|
|
||||||
|
var alignRightItem = new MenuItem { Header = "Derecha" };
|
||||||
|
alignRightItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.Right);
|
||||||
|
alignSubmenu.Items.Add(alignRightItem);
|
||||||
|
|
||||||
|
var alignCenterHItem = new MenuItem { Header = "Centro Horizontal" };
|
||||||
|
alignCenterHItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.CenterHorizontally);
|
||||||
|
alignSubmenu.Items.Add(alignCenterHItem);
|
||||||
|
|
||||||
|
// Alineación vertical
|
||||||
|
alignSubmenu.Items.Add(new Separator());
|
||||||
|
|
||||||
|
var alignTopItem = new MenuItem { Header = "Arriba" };
|
||||||
|
alignTopItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.Top);
|
||||||
|
alignSubmenu.Items.Add(alignTopItem);
|
||||||
|
|
||||||
|
var alignBottomItem = new MenuItem { Header = "Abajo" };
|
||||||
|
alignBottomItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.Bottom);
|
||||||
|
alignSubmenu.Items.Add(alignBottomItem);
|
||||||
|
|
||||||
|
var alignCenterVItem = new MenuItem { Header = "Centro Vertical" };
|
||||||
|
alignCenterVItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.CenterVertically);
|
||||||
|
alignSubmenu.Items.Add(alignCenterVItem);
|
||||||
|
|
||||||
|
// Distribución
|
||||||
|
alignSubmenu.Items.Add(new Separator());
|
||||||
|
|
||||||
|
var distributeHItem = new MenuItem { Header = "Distribuir Horizontalmente" };
|
||||||
|
distributeHItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.DistributeHorizontally);
|
||||||
|
alignSubmenu.Items.Add(distributeHItem);
|
||||||
|
|
||||||
|
var distributeVItem = new MenuItem { Header = "Distribuir Verticalmente" };
|
||||||
|
distributeVItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.DistributeVertically);
|
||||||
|
alignSubmenu.Items.Add(distributeVItem);
|
||||||
|
|
||||||
|
// Igualar tamaños
|
||||||
|
alignSubmenu.Items.Add(new Separator());
|
||||||
|
|
||||||
|
var equalWidthItem = new MenuItem { Header = "Igualar Ancho" };
|
||||||
|
equalWidthItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.EqualWidth);
|
||||||
|
alignSubmenu.Items.Add(equalWidthItem);
|
||||||
|
|
||||||
|
var equalHeightItem = new MenuItem { Header = "Igualar Alto" };
|
||||||
|
equalHeightItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.EqualHeight);
|
||||||
|
alignSubmenu.Items.Add(equalHeightItem);
|
||||||
|
|
||||||
|
var equalAngleItem = new MenuItem { Header = "Igualar Ángulo" };
|
||||||
|
equalAngleItem.Click += (s, e) => _objectManager.AlignObjects(AlignmentType.EqualAngle);
|
||||||
|
alignSubmenu.Items.Add(equalAngleItem);
|
||||||
|
|
||||||
|
contextMenu.Items.Add(alignSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
contextMenu.IsOpen = true;
|
||||||
contextMenu.PlacementTarget = ImagenEnTrabajoCanvas;
|
contextMenu.PlacementTarget = ImagenEnTrabajoCanvas;
|
||||||
contextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;
|
contextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;
|
||||||
contextMenu.IsOpen = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,6 +635,8 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Image ImagenDeFondo => imagenDeFondo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FloatValidationRule : ValidationRule
|
public class FloatValidationRule : ValidationRule
|
||||||
|
|
|
@ -68,11 +68,35 @@ namespace CtrEditor
|
||||||
private ObservableCollection<osBase> _selectedObjects = new ObservableCollection<osBase>();
|
private ObservableCollection<osBase> _selectedObjects = new ObservableCollection<osBase>();
|
||||||
private List<Rectangle> _selectionHighlightRectangles = new List<Rectangle>(); // Add this line
|
private List<Rectangle> _selectionHighlightRectangles = new List<Rectangle>(); // Add this line
|
||||||
private List<(UserControl Control, Rectangle Highlight)> _selectionHighlightPairs = new List<(UserControl, Rectangle)>();
|
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)
|
public ObjectManipulationManager(MainWindow mainWindow, Canvas canvas)
|
||||||
{
|
{
|
||||||
_mainWindow = mainWindow;
|
_mainWindow = mainWindow;
|
||||||
_canvas = canvas;
|
_canvas = canvas;
|
||||||
|
_scrollViewer = mainWindow.ImagenEnTrabajoScrollViewer; // Add this line
|
||||||
|
_backgroundImage = mainWindow.ImagenDeFondo; // Add this line
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PurgeDeletedObjects()
|
private void PurgeDeletedObjects()
|
||||||
|
@ -843,5 +867,81 @@ namespace CtrEditor
|
||||||
viewModel.HasUnsavedChanges = true;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue