From 89745d15bf09cd86a315e970a439e6d319c51005 Mon Sep 17 00:00:00 2001 From: Miguel Date: Mon, 17 Feb 2025 15:16:40 +0100 Subject: [PATCH] Mejorada la seleccion de objetos. --- MainWindow.xaml.cs | 250 +++++++++++++++++++++++++++++++++------------ 1 file changed, 187 insertions(+), 63 deletions(-) diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index a1719f3..f4ef896 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -15,6 +15,7 @@ using System.Windows.Shapes; using System.Numerics; using CommunityToolkit.Mvvm.Input; using CtrEditor.FuncionesBase; +using Color = System.Windows.Media.Color; namespace CtrEditor { @@ -31,6 +32,8 @@ namespace CtrEditor private Image imagenDeFondo; private List resizeRectangles = new List(); + private List highlightRectangles = new List(); // Nueva lista para los rectángulos de resaltado + private System.Threading.Timer timerRemoveHighlight = null; private DispatcherTimer _zoomTimer; private double _targetZoomFactor; @@ -68,6 +71,7 @@ namespace CtrEditor // Agregar el evento KeyDown a la ventana this.KeyDown += MainWindow_KeyDown; + ImagenEnTrabajoCanvas.MouseEnter += Canvas_MouseEnter; } private void MainWindow_Loaded(object sender, RoutedEventArgs e) @@ -92,6 +96,7 @@ namespace CtrEditor { userControl.MouseEnter += UserControl_MouseEnter; userControl.MouseLeave += UserControl_MouseLeave; + userControl.Cursor = Cursors.Hand; // Agregar cursor de mano // Suscribir a eventos de mouse para panning userControl.MouseLeftButtonDown += UserControl_MouseLeftButtonDown; @@ -123,6 +128,7 @@ namespace CtrEditor { if (!_isDrawingCanvas) { + // Si el sender es un rectángulo de redimensionamiento if (resizeRectangles != null && resizeRectangles.Contains(sender)) { _isResizingUserControl = true; @@ -130,27 +136,39 @@ namespace CtrEditor ((Rectangle)sender).CaptureMouse(); _isMovingUserControl = true; lastAngle = 0; + e.Handled = true; // Evitar que el evento se propague + return; } - else + + var userControl = sender as UserControl; + if (userControl != null) { - var userControl = sender as UserControl; - userControl.CaptureMouse(); // Importante para recibir eventos de movimiento incluso fuera del control + // Si hacemos clic en un control diferente al seleccionado, remover los rectángulos anteriores + if (_currentDraggingControl != userControl) + { + RemoveResizeRectangles(); + } + + userControl.CaptureMouse(); _currentDraggingControl = userControl; _isMovingUserControl = true; - RemoveResizeRectangles(); - if (sender is UserControl control && control.DataContext is osBase datos) + // Actualizar la selección en el ViewModel + if (userControl.DataContext is osBase datos) { var viewModel = DataContext as MainViewModel; if (viewModel != null) { - viewModel.SelectedItemOsList = datos; // Esto desencadenará ListaOs_SelectionChanged + viewModel.SelectedItemOsList = datos; + AddResizeRectangles(userControl); } } - // ROTACION + // Resto del código para manejar rotación, tamaño y movimiento if (Keyboard.IsKeyDown(Key.LeftShift)) { + // Código de rotación existente + // ROTACION // Inicializar la rotación _isRotatingUserControl = true; RotateTransform rotateTransform = userControl.RenderTransform as RotateTransform; @@ -183,16 +201,16 @@ namespace CtrEditor _angleDisplayTextBlock.Visibility = Visibility.Visible; Canvas.SetZIndex(_angleDisplayTextBlock, 15); } - // TAMANO else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) { + // Código de cambio de tamaño existente // Inicializar el cambio de tamaño _isResizingUserControl = true; _startPointUserControl = e.GetPosition(ImagenEnTrabajoCanvas); } - // MOVIMIENTO else { + // Código de movimiento existente // Inicializar el movimiento/panning _isDraggingUserControl = true; _startPointUserControl = e.GetPosition(ImagenEnTrabajoCanvas); @@ -217,39 +235,11 @@ namespace CtrEditor private Point transformedBoundingBoxCenter = new Point(); private float lastAngle; - private System.Threading.Timer timerRemoveResizeRectangles = null; - - public void ResetTimerRemoveResizeRectangles() - { - if (timerRemoveResizeRectangles == null) - timerRemoveResizeRectangles = new System.Threading.Timer(TimerCallbackRemoveResizeRectangles, null, Timeout.Infinite, Timeout.Infinite); - - timerRemoveResizeRectangles.Change(2000, Timeout.Infinite); - } - - private async void TimerCallbackRemoveResizeRectangles(object state) - { - if (Application.Current != null) - { - Application.Current.Dispatcher.Invoke(() => - { - // Realiza tus cambios en la interfaz de usuario aquí - MakeResizeRectanglesTransparent(); - }); - } - } - - public void PauseTimerRemoveResizeRectangles() - { - if (timerRemoveResizeRectangles != null) - { - timerRemoveResizeRectangles.Change(Timeout.Infinite, Timeout.Infinite); - } - } private void AddResizeRectangles(UserControl userControl) { double rectSize = 10; + double rectHighlightSize = 1; RemoveResizeRectangles(); if (userControl is IDataContainer dataContainer && dataContainer.Datos is osBase mvBase && mvBase.Show_On_This_Page) @@ -263,14 +253,34 @@ namespace CtrEditor 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; + rectBox.Left -= (float)rectHighlightSize; + rectBox.Right += (float)rectHighlightSize; + rectBox.Top -= (float)rectHighlightSize; + rectBox.Bottom += (float)rectHighlightSize; transformedBoundingBoxCenter.X = transformedBoundingBox.Left + transformedBoundingBox.Width / 2; transformedBoundingBoxCenter.Y = transformedBoundingBox.Top + transformedBoundingBox.Height / 2; + // Agregar primero el rectángulo de selección + Rectangle selectionRect = new Rectangle + { + Width = rectBox.Width + (rectHighlightSize * 2), // Hacer el rectángulo un poco más grande + Height = rectBox.Height + (rectHighlightSize * 2), + Fill = Brushes.Transparent, + Stroke = new SolidColorBrush(Color.FromArgb(180, 0, 120, 215)), // Azul semi-transparente + StrokeThickness = 1.5, + Tag = "Selection", + IsHitTestVisible = false, + StrokeDashArray = new DoubleCollection(new double[] { 3, 3 }) // Borde punteado más visible + }; + + Canvas.SetLeft(selectionRect, rectBox.Left - rectHighlightSize); + Canvas.SetTop(selectionRect, rectBox.Top - rectHighlightSize); + Canvas.SetZIndex(selectionRect, ((int)ZIndexEnum.RectangulosPropiead - 1)); // Un nivel por debajo de los controles de redimensión + + resizeRectangles.Add(selectionRect); + ImagenEnTrabajoCanvas.Children.Add(selectionRect); + // Cargar el cursor personalizado para rotación 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); @@ -357,20 +367,62 @@ namespace CtrEditor resizeRectangles.Add(rect); ImagenEnTrabajoCanvas.Children.Add(rect); Canvas.SetZIndex(rect, ((int)ZIndexEnum.RectangulosPropiead)); - - ResetTimerRemoveResizeRectangles(); } } } + private void AddHighlightRectangles(UserControl userControl) + { + double rectSize = 1; + RemoveHighlightRectangles(); // Eliminar highlight anterior + if (userControl is IDataContainer dataContainer && dataContainer.Datos is osBase mvBase && mvBase.Show_On_This_Page) + { + // Obtener el BoundingBox aproximado del UserControl + Rect boundingBox = VisualTreeHelper.GetDescendantBounds(userControl); + // Transformar el BoundingBox a las coordenadas del Canvas + GeneralTransform transform = userControl.TransformToAncestor(ImagenEnTrabajoCanvas); + 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; + + // Crear un rectángulo de resaltado alrededor del objeto con estilo más sutil + Rectangle highlightRect = new Rectangle + { + Width = rectBox.Width, + Height = rectBox.Height, + Fill = Brushes.Transparent, + Stroke = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)), // Borde semitransparente + StrokeThickness = 1, + Tag = "Highlight", + IsHitTestVisible = false, + StrokeDashArray = new DoubleCollection(new double[] { 2, 2 }) // Borde punteado + }; + + Canvas.SetLeft(highlightRect, rectBox.Left); + Canvas.SetTop(highlightRect, rectBox.Top); + + highlightRectangles.Add(highlightRect); // Usar la nueva lista + ImagenEnTrabajoCanvas.Children.Add(highlightRect); + Canvas.SetZIndex(highlightRect, ((int)ZIndexEnum.RectangulosPropiead)); + + // Reiniciar el timer + if (timerRemoveHighlight == null) + timerRemoveHighlight = new System.Threading.Timer(TimerCallbackRemoveHighlight, null, Timeout.Infinite, Timeout.Infinite); + + timerRemoveHighlight.Change(2000, Timeout.Infinite); + } + } private void ResizeRectangle_MouseLeave(object sender, MouseEventArgs e) { var rect = sender as Rectangle; rect.Fill = Brushes.Transparent; // Volver al color original - ResetTimerRemoveResizeRectangles(); } private void MakeResizeRectanglesTransparent() @@ -408,6 +460,18 @@ namespace CtrEditor resizeRectangles.Clear(); } + private void RemoveHighlightRectangles() + { + if (highlightRectangles == null || highlightRectangles.Count == 0) + return; + + foreach (var rect in highlightRectangles) + { + ImagenEnTrabajoCanvas.Children.Remove(rect); + } + highlightRectangles.Clear(); + } + private Point lastMousePosition; private void MarkUnsavedChanges() @@ -460,11 +524,11 @@ namespace CtrEditor _currentDraggingRectangle = rect; // Asignar el rectángulo actual que se está arrastrando _startPointUserControl = new Point(Canvas.GetLeft(rect), Canvas.GetTop(rect)); MakeResizeRectanglesNormal(); - PauseTimerRemoveResizeRectangles(); } if (_isMovingUserControl && _currentDraggingControl != null) { var currentPosition = e.GetPosition(ImagenEnTrabajoCanvas); + MakeResizeRectanglesTransparent(); // Hacer transparente durante cualquier manipulación if (_isDraggingUserControl) { @@ -607,18 +671,33 @@ namespace CtrEditor private void UserControl_MouseEnter(object sender, MouseEventArgs e) { - if (_currentDraggingControl != null) + if (sender is UserControl userControl && userControl is IDataContainer dataContainer) { - RemoveResizeRectangles(); - } - - if (sender is UserControl userControl) - if (userControl is IDataContainer dataContainer) + dataContainer.Highlight(true); + + if (DataContext is MainViewModel viewModel) { - dataContainer.Highlight(true); - _currentDraggingControl = sender as UserControl; - AddResizeRectangles(_currentDraggingControl); + var selectedObject = viewModel.SelectedItemOsList; + + // Si el control actual no es el seleccionado + if (selectedObject?.VisualRepresentation != userControl) + { + // Siempre mostrar el highlight temporal + AddHighlightRectangles(userControl); + } } + } + } + + private async void TimerCallbackRemoveHighlight(object state) + { + if (Application.Current != null) + { + Application.Current.Dispatcher.Invoke(() => + { + RemoveHighlightRectangles(); + }); + } } private void UserControl_MouseLeave(object sender, MouseEventArgs e) @@ -671,6 +750,12 @@ namespace CtrEditor { _isDraggingCanvas = false; ImagenEnTrabajoScrollViewer.ReleaseMouseCapture(); // Finaliza la captura del ratón + + // Restaurar la visibilidad de los rectángulos de selección si hay un objeto seleccionado + if (DataContext is MainViewModel viewModel && viewModel.SelectedItemOsList != null) + { + MakeResizeRectanglesNormal(); + } } } @@ -678,11 +763,18 @@ namespace CtrEditor { if (e.LeftButton == MouseButtonState.Pressed && !_isDrawingCanvas && !_isMovingUserControl) { - // Indica que se inicia el panning _isDraggingCanvas = true; - // Guarda la posición actual del ratón _lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer); - //ImagenEnTrabajoScrollViewer.CaptureMouse(); // Importante para capturar el movimiento + + // Asegurarnos de que el clic fue directamente en el canvas y no en un elemento hijo + if (e.Source == ImagenEnTrabajoCanvas) + { + if (DataContext is MainViewModel viewModel) + { + viewModel.SelectedItemOsList = null; // Deseleccionar el objeto actual + RemoveResizeRectangles(); // Eliminar los rectángulos después de deseleccionar + } + } } } @@ -694,7 +786,9 @@ namespace CtrEditor var dx = currentPosition.X - _lastMousePosition.X; var dy = currentPosition.Y - _lastMousePosition.Y; + // Ocultar rectángulos y eliminar highlights durante el panning MakeResizeRectanglesTransparent(); + RemoveHighlightRectangles(); // Obtener la transformación actual del Canvas var transform = (TranslateTransform)((TransformGroup)ImagenEnTrabajoCanvas.RenderTransform).Children.First(t => t is TranslateTransform); @@ -707,7 +801,9 @@ namespace CtrEditor private void ImagenEnTrabajoCanvas_MouseWheel(object sender, MouseWheelEventArgs e) { + // Ocultar rectángulos y eliminar highlights MakeResizeRectanglesTransparent(); + RemoveHighlightRectangles(); _initialZoomFactor = ((ScaleTransform)((TransformGroup)ImagenEnTrabajoCanvas.RenderTransform).Children.First(t => t is ScaleTransform)).ScaleX; @@ -748,6 +844,12 @@ namespace CtrEditor // Volver a activar el escalado de alta calidad después de completar el zoom RenderOptions.SetBitmapScalingMode(ImagenEnTrabajoCanvas, BitmapScalingMode.HighQuality); + // Restaurar la visibilidad de los rectángulos de selección si hay un objeto seleccionado + if (DataContext is MainViewModel viewModel && viewModel.SelectedItemOsList != null) + { + MakeResizeRectanglesNormal(); + } + return; } @@ -818,7 +920,6 @@ namespace CtrEditor private void ListaOs_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { - //PanelEdicion.Children.Clear(); // Limpiar el panel existente UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion); if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject) @@ -826,19 +927,42 @@ namespace CtrEditor if (selectedObject.VisualRepresentation != null) { _currentDraggingControl = selectedObject.VisualRepresentation; + RemoveResizeRectangles(); AddResizeRectangles(_currentDraggingControl); } CargarPropiedadesosDatos(selectedObject); - + } + else + { + RemoveResizeRectangles(); } } private void MainWindow_KeyDown(object sender, KeyEventArgs e) { - if (e.Key == Key.Delete && DataContext is MainViewModel viewModel) + if (DataContext is MainViewModel viewModel) { - viewModel.EliminarObjetoSeleccionado(); - e.Handled = true; + if (e.Key == Key.Delete) + { + viewModel.EliminarObjetoSeleccionado(); + e.Handled = true; + } + else if (e.Key == Key.Escape) + { + // Deseleccionar el objeto actual y eliminar los rectángulos de selección + viewModel.SelectedItemOsList = null; + RemoveResizeRectangles(); + e.Handled = true; + } + } + } + + private void Canvas_MouseEnter(object sender, MouseEventArgs e) + { + // Solo remover los rectángulos si el mouse entra directamente al Canvas + if (e.OriginalSource == ImagenEnTrabajoCanvas) + { + // RemoveResizeRectangles(); } } }