Compare commits
2 Commits
633cd71d00
...
3dab570f5d
Author | SHA1 | Date |
---|---|---|
|
3dab570f5d | |
|
89745d15bf |
|
@ -112,8 +112,17 @@ namespace CtrEditor
|
|||
private bool habilitarEliminarUserControl;
|
||||
|
||||
private MainWindow mainWindow;
|
||||
private ObjectManipulationManager _objectManager; // Add this line
|
||||
|
||||
public MainWindow MainWindow { get => mainWindow; set => mainWindow = value; }
|
||||
public MainWindow MainWindow
|
||||
{
|
||||
get => mainWindow;
|
||||
set
|
||||
{
|
||||
mainWindow = value;
|
||||
_objectManager = mainWindow._objectManager; // Initialize _objectManager
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
public ICollectionView vistaFiltrada;
|
||||
|
@ -273,6 +282,14 @@ namespace CtrEditor
|
|||
[ObservableProperty]
|
||||
public ObservableCollection<osBase> objetosSimulables;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isMultiSelectionActive;
|
||||
|
||||
partial void OnIsMultiSelectionActiveChanged(bool value)
|
||||
{
|
||||
_objectManager?.OnMultiSelectionModeChanged(value);
|
||||
}
|
||||
|
||||
partial void OnObjetosSimulablesChanged(ObservableCollection<osBase> value)
|
||||
{
|
||||
VistaFiltrada = CollectionViewSource.GetDefaultView(ObjetosSimulables);
|
||||
|
|
|
@ -155,8 +155,9 @@
|
|||
|
||||
<ScrollViewer Grid.Row="1" x:Name="ImagenEnTrabajoScrollViewer" HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto" PanningMode="Both">
|
||||
<Canvas x:Name="ImagenEnTrabajoCanvas" Margin="0">
|
||||
<!-- El Margin puede ser ajustado según el espacio adicional que quieras proporcionar -->
|
||||
<Canvas x:Name="ImagenEnTrabajoCanvas" Margin="0" Background="Transparent">
|
||||
<!-- Agregar Background="Transparent" para que capture los eventos del mouse y -->
|
||||
<!-- asegurar que el Canvas reciba los eventos del botón derecho -->
|
||||
<Canvas.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform x:Name="CanvasScaleTransform" ScaleX="1" ScaleY="1" />
|
||||
|
|
|
@ -4,24 +4,19 @@ using System.Windows.Controls;
|
|||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using CtrEditor.ObjetosSim;
|
||||
using System.Windows.Threading;
|
||||
using System.Diagnostics;
|
||||
using CtrEditor.ObjetosSim.UserControls;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using System.Windows.Shapes;
|
||||
using System.Numerics;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CtrEditor.ObjetosSim;
|
||||
using CtrEditor.FuncionesBase;
|
||||
using Xceed.Wpf.Toolkit.PropertyGrid;
|
||||
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
|
||||
namespace CtrEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
///
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
// Para el Canvas
|
||||
|
@ -29,9 +24,9 @@ namespace CtrEditor
|
|||
private bool _isDrawingCanvas = false;
|
||||
private bool _isDraggingCanvas = false;
|
||||
private Image imagenDeFondo;
|
||||
internal ObjectManipulationManager _objectManager;
|
||||
|
||||
private List<Rectangle> resizeRectangles = new List<Rectangle>();
|
||||
|
||||
// Temporizadores y animación
|
||||
private DispatcherTimer _zoomTimer;
|
||||
private double _targetZoomFactor;
|
||||
private double _initialZoomFactor;
|
||||
|
@ -42,32 +37,32 @@ namespace CtrEditor
|
|||
private const double MinZoomScale = 0.1; // Límite mínimo de zoom
|
||||
private Stopwatch _stopwatch;
|
||||
|
||||
// Para los UserControl
|
||||
private Point _startPointUserControl;
|
||||
private UserControl _currentDraggingControl;
|
||||
private bool _isRotatingUserControl = false;
|
||||
private bool _isResizingUserControl = false;
|
||||
private bool _isDraggingUserControl = false;
|
||||
private bool _isMovingUserControl = false;
|
||||
private TextBlock _angleDisplayTextBlock;
|
||||
private dataDebug dataDebug = new dataDebug();
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_objectManager = new ObjectManipulationManager(this, ImagenEnTrabajoCanvas);
|
||||
|
||||
// Inicializar temporizador de zoom
|
||||
_zoomTimer = new DispatcherTimer();
|
||||
_zoomTimer.Interval = TimeSpan.FromMilliseconds(1);
|
||||
_zoomTimer.Tick += ZoomTimer_Tick;
|
||||
_stopwatch = new Stopwatch();
|
||||
|
||||
// Suscribir eventos
|
||||
this.Loaded += MainWindow_Loaded;
|
||||
ImagenEnTrabajoScrollViewer.PreviewMouseWheel += ImagenEnTrabajoCanvas_MouseWheel;
|
||||
ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown_Panning;
|
||||
ImagenEnTrabajoCanvas.MouseMove += Canvas_MouseMove_Panning;
|
||||
ImagenEnTrabajoCanvas.MouseUp += Canvas_MouseUp_Panning;
|
||||
|
||||
// Agregar el evento KeyDown a la ventana
|
||||
this.KeyDown += MainWindow_KeyDown;
|
||||
ImagenEnTrabajoCanvas.MouseEnter += Canvas_MouseEnter;
|
||||
this.Closed += MainWindow_Closed;
|
||||
|
||||
// Importante: Agregar el evento para el menú contextual
|
||||
ImagenEnTrabajoCanvas.MouseRightButtonDown += Canvas_MouseRightButtonDown;
|
||||
}
|
||||
|
||||
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
|
@ -76,27 +71,15 @@ namespace CtrEditor
|
|||
{
|
||||
viewModel.MainWindow = this;
|
||||
viewModel.ImageSelected += ViewModel_ImageSelected;
|
||||
viewModel?.LoadInitialData(); // Carga la primera imagen por defecto una vez cargada la ventana principal
|
||||
viewModel?.LoadInitialData();
|
||||
viewModel.simulationManager.DebugCanvas = ImagenEnTrabajoCanvas;
|
||||
viewModel.MainCanvas = ImagenEnTrabajoCanvas;
|
||||
}
|
||||
}
|
||||
|
||||
public (float X, float Y) ObtenerCentroCanvasMeters()
|
||||
{
|
||||
var c = ObtenerCentroCanvasPixels();
|
||||
return (PixelToMeter.Instance.calc.PixelsToMeters(c.X), PixelToMeter.Instance.calc.PixelsToMeters(c.Y));
|
||||
}
|
||||
|
||||
public void SuscribirEventos(UserControl userControl)
|
||||
{
|
||||
userControl.MouseEnter += UserControl_MouseEnter;
|
||||
userControl.MouseLeave += UserControl_MouseLeave;
|
||||
|
||||
// Suscribir a eventos de mouse para panning
|
||||
userControl.MouseLeftButtonDown += UserControl_MouseLeftButtonDown;
|
||||
userControl.MouseLeftButtonUp += UserControl_MouseLeftButtonUp;
|
||||
userControl.MouseMove += UserControl_MouseMove;
|
||||
_objectManager.SuscribirEventos(userControl);
|
||||
}
|
||||
|
||||
public void AgregarRegistrarUserControlCanvas(UserControl userControl)
|
||||
|
@ -104,8 +87,6 @@ namespace CtrEditor
|
|||
if (userControl is IDataContainer dataContainer)
|
||||
{
|
||||
SuscribirEventos(userControl);
|
||||
|
||||
// Añade el UserControl al Canvas
|
||||
Canvas.SetZIndex(userControl, ((int)dataContainer.ZIndex_Base() + dataContainer.zIndex_fromFrames));
|
||||
ImagenEnTrabajoCanvas.Children.Add(userControl);
|
||||
}
|
||||
|
@ -119,520 +100,6 @@ namespace CtrEditor
|
|||
}
|
||||
}
|
||||
|
||||
private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (!_isDrawingCanvas)
|
||||
{
|
||||
if (resizeRectangles != null && resizeRectangles.Contains(sender))
|
||||
{
|
||||
_isResizingUserControl = true;
|
||||
lastMousePosition = e.GetPosition(ImagenEnTrabajoCanvas);
|
||||
((Rectangle)sender).CaptureMouse();
|
||||
_isMovingUserControl = true;
|
||||
lastAngle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var userControl = sender as UserControl;
|
||||
userControl.CaptureMouse(); // Importante para recibir eventos de movimiento incluso fuera del control
|
||||
_currentDraggingControl = userControl;
|
||||
_isMovingUserControl = true;
|
||||
RemoveResizeRectangles();
|
||||
|
||||
if (sender is UserControl control && control.DataContext is osBase datos)
|
||||
{
|
||||
var viewModel = DataContext as MainViewModel;
|
||||
if (viewModel != null)
|
||||
{
|
||||
viewModel.SelectedItemOsList = datos; // Esto desencadenará ListaOs_SelectionChanged
|
||||
}
|
||||
}
|
||||
|
||||
// ROTACION
|
||||
if (Keyboard.IsKeyDown(Key.LeftShift))
|
||||
{
|
||||
// Inicializar la rotación
|
||||
_isRotatingUserControl = true;
|
||||
RotateTransform rotateTransform = userControl.RenderTransform as RotateTransform;
|
||||
if (rotateTransform == null)
|
||||
{
|
||||
rotateTransform = new RotateTransform();
|
||||
userControl.RenderTransform = rotateTransform;
|
||||
}
|
||||
|
||||
// Establecer el punto inicial de referencia para el cálculo de rotación
|
||||
_startPointUserControl = new Point(rotateTransform.CenterX, rotateTransform.CenterY);
|
||||
|
||||
// Ajusta el punto inicial al espacio del Canvas
|
||||
_startPointUserControl = userControl.TranslatePoint(_startPointUserControl, ImagenEnTrabajoCanvas);
|
||||
|
||||
// Crear y configurar el TextBlock si no existe
|
||||
if (_angleDisplayTextBlock == null)
|
||||
{
|
||||
_angleDisplayTextBlock = new TextBlock
|
||||
{
|
||||
Foreground = Brushes.Black,
|
||||
Background = Brushes.White,
|
||||
Opacity = 0.8,
|
||||
Padding = new Thickness(5)
|
||||
};
|
||||
ImagenEnTrabajoCanvas.Children.Add(_angleDisplayTextBlock);
|
||||
}
|
||||
|
||||
PositionAngleDisplay(userControl);
|
||||
_angleDisplayTextBlock.Visibility = Visibility.Visible;
|
||||
Canvas.SetZIndex(_angleDisplayTextBlock, 15);
|
||||
}
|
||||
// TAMANO
|
||||
else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
||||
{
|
||||
// Inicializar el cambio de tamaño
|
||||
_isResizingUserControl = true;
|
||||
_startPointUserControl = e.GetPosition(ImagenEnTrabajoCanvas);
|
||||
}
|
||||
// MOVIMIENTO
|
||||
else
|
||||
{
|
||||
// Inicializar el movimiento/panning
|
||||
_isDraggingUserControl = true;
|
||||
_startPointUserControl = e.GetPosition(ImagenEnTrabajoCanvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataDebug dataDebug = new dataDebug();
|
||||
|
||||
public void DebugWindow()
|
||||
{
|
||||
// Crear una instancia de wDebug
|
||||
var debugWindow = new wDebug
|
||||
{
|
||||
Data = dataDebug // Asignar la instancia de Test a la propiedad Data
|
||||
};
|
||||
|
||||
// Mostrar la ventana de depuración
|
||||
debugWindow.Show();
|
||||
}
|
||||
|
||||
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;
|
||||
RemoveResizeRectangles();
|
||||
|
||||
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;
|
||||
|
||||
transformedBoundingBoxCenter.X = transformedBoundingBox.Left + transformedBoundingBox.Width / 2;
|
||||
transformedBoundingBoxCenter.Y = transformedBoundingBox.Top + transformedBoundingBox.Height / 2;
|
||||
|
||||
// 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);
|
||||
|
||||
// Calcular las posiciones de los rectángulos de redimensionamiento
|
||||
var positions = new List<Tuple<Point, string>>()
|
||||
{
|
||||
new Tuple<Point, string>(new Point(rectBox.Left, rectBox.Top), "TopLeft"),
|
||||
new Tuple<Point, string>(new Point(rectBox.Right, rectBox.Top), "TopRight"),
|
||||
new Tuple<Point, string>(new Point(rectBox.Left, rectBox.Bottom), "BottomLeft"),
|
||||
new Tuple<Point, string>(new Point(rectBox.Right, rectBox.Bottom), "BottomRight"),
|
||||
new Tuple<Point, string>(new Point(rectBox.Left + rectBox.Width / 2, rectBox.Top), "TopCenter"),
|
||||
new Tuple<Point, string>(new Point(rectBox.Left + rectBox.Width / 2, rectBox.Bottom), "BottomCenter"),
|
||||
new Tuple<Point, string>(new Point(rectBox.Left, rectBox.Top + rectBox.Height / 2), "CenterLeft"),
|
||||
new Tuple<Point, string>(new Point(rectBox.Right, rectBox.Top + rectBox.Height / 2), "CenterRight")
|
||||
};
|
||||
|
||||
// Add validation before setting Canvas position
|
||||
void SetCanvasPosition(UIElement element, double left, double top)
|
||||
{
|
||||
if (!double.IsInfinity(left) && !double.IsNaN(left))
|
||||
Canvas.SetLeft(element, left);
|
||||
if (!double.IsInfinity(top) && !double.IsNaN(top))
|
||||
Canvas.SetTop(element, top);
|
||||
}
|
||||
|
||||
foreach (var position in positions)
|
||||
{
|
||||
Rectangle rect = new Rectangle
|
||||
{
|
||||
Width = rectSize,
|
||||
Height = rectSize,
|
||||
Fill = Brushes.Transparent,
|
||||
Stroke = Brushes.Black,
|
||||
StrokeThickness = 1,
|
||||
Tag = position.Item2 // Asignar la etiqueta
|
||||
};
|
||||
|
||||
// Establecer el cursor adecuado
|
||||
switch (position.Item2)
|
||||
{
|
||||
case "TopLeft":
|
||||
rect.Cursor = Cursors.Arrow;
|
||||
rect.Stroke = Brushes.Gray;
|
||||
break;
|
||||
case "TopRight":
|
||||
rect.Cursor = rotationCursorRx; // Cursor de rotación
|
||||
rect.Stroke = Brushes.Red;
|
||||
break;
|
||||
case "BottomLeft":
|
||||
rect.Cursor = rotationCursorSx; // Cursor de rotación
|
||||
rect.Stroke = Brushes.DarkRed;
|
||||
break;
|
||||
case "BottomRight":
|
||||
rect.Cursor = Cursors.SizeNWSE; // Cursor de dimensionar altura y anchura
|
||||
rect.Stroke = Brushes.Blue;
|
||||
break;
|
||||
case "TopCenter":
|
||||
rect.Cursor = Cursors.Arrow;
|
||||
rect.Stroke = Brushes.Gray;
|
||||
break;
|
||||
case "BottomCenter":
|
||||
rect.Cursor = Cursors.SizeNS; // Cursor de dimensionar altura
|
||||
rect.Stroke = Brushes.Blue;
|
||||
break;
|
||||
case "CenterLeft":
|
||||
rect.Cursor = rotationCursorRx; // Cursor de rotación
|
||||
rect.Stroke = Brushes.Red;
|
||||
break;
|
||||
case "CenterRight":
|
||||
rect.Cursor = Cursors.SizeWE; // Cursor de dimensionar anchura
|
||||
rect.Stroke = Brushes.Blue;
|
||||
break;
|
||||
}
|
||||
|
||||
// Replace direct Canvas.Set calls with the validation method
|
||||
SetCanvasPosition(rect, position.Item1.X - rectSize / 2, position.Item1.Y - rectSize / 2);
|
||||
|
||||
rect.MouseLeftButtonDown += UserControl_MouseLeftButtonDown;
|
||||
rect.MouseMove += UserControl_MouseMove;
|
||||
rect.MouseLeftButtonUp += UserControl_MouseLeftButtonUp;
|
||||
rect.MouseLeave += ResizeRectangle_MouseLeave;
|
||||
|
||||
resizeRectangles.Add(rect);
|
||||
ImagenEnTrabajoCanvas.Children.Add(rect);
|
||||
Canvas.SetZIndex(rect, ((int)ZIndexEnum.RectangulosPropiead));
|
||||
|
||||
ResetTimerRemoveResizeRectangles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
if (resizeRectangles == null || resizeRectangles.Count == 0)
|
||||
return;
|
||||
|
||||
foreach (var rect in resizeRectangles)
|
||||
{
|
||||
rect.Opacity = 0; // Hacer transparente
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeResizeRectanglesNormal()
|
||||
{
|
||||
if (resizeRectangles == null || resizeRectangles.Count == 0)
|
||||
return;
|
||||
|
||||
foreach (var rect in resizeRectangles)
|
||||
{
|
||||
rect.Opacity = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void RemoveResizeRectangles()
|
||||
{
|
||||
if (resizeRectangles == null || resizeRectangles.Count == 0)
|
||||
return;
|
||||
|
||||
foreach (var rect in resizeRectangles)
|
||||
{
|
||||
ImagenEnTrabajoCanvas.Children.Remove(rect);
|
||||
}
|
||||
resizeRectangles.Clear();
|
||||
}
|
||||
|
||||
private Point lastMousePosition;
|
||||
|
||||
private void MarkUnsavedChanges()
|
||||
{
|
||||
if (DataContext is MainViewModel viewModel)
|
||||
{
|
||||
if (_isMovingUserControl || _isRotatingUserControl || _isResizingUserControl || _isDraggingUserControl)
|
||||
{
|
||||
viewModel.HasUnsavedChanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
MarkUnsavedChanges();
|
||||
if (_isResizingUserControl && resizeRectangles != null && resizeRectangles.Contains(sender))
|
||||
{
|
||||
_isResizingUserControl = false;
|
||||
_isMovingUserControl = false;
|
||||
((Rectangle)sender).ReleaseMouseCapture();
|
||||
AddResizeRectangles(_currentDraggingControl);
|
||||
}
|
||||
else if (_isMovingUserControl)
|
||||
{
|
||||
var userControl = sender as UserControl;
|
||||
|
||||
userControl.ReleaseMouseCapture();
|
||||
// _currentDraggingControl = null;
|
||||
AddResizeRectangles(_currentDraggingControl);
|
||||
_isResizingUserControl = _isRotatingUserControl = _isDraggingUserControl = false;
|
||||
_isMovingUserControl = false;
|
||||
|
||||
// Ocultar el TextBlock de ángulo
|
||||
if (_angleDisplayTextBlock != null)
|
||||
{
|
||||
_angleDisplayTextBlock.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle _currentDraggingRectangle;
|
||||
|
||||
private void UserControl_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (!_isMovingUserControl && resizeRectangles != null && resizeRectangles.Contains(sender))
|
||||
{
|
||||
var rect = sender as Rectangle;
|
||||
rect.Fill = Brushes.Black; // Pintar de negro el rectángulo bajo el ratón
|
||||
_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);
|
||||
|
||||
if (_isDraggingUserControl)
|
||||
{
|
||||
// Código para mover el control
|
||||
var dx = currentPosition.X - _startPointUserControl.X;
|
||||
var dy = currentPosition.Y - _startPointUserControl.Y;
|
||||
var newX = Canvas.GetLeft(_currentDraggingControl) + dx;
|
||||
var newY = Canvas.GetTop(_currentDraggingControl) + dy;
|
||||
|
||||
if (_currentDraggingControl is IDataContainer dataContainer && dataContainer.Datos is osBase mvBase)
|
||||
mvBase.Move((float)newX, (float)newY);
|
||||
|
||||
_startPointUserControl = currentPosition; // Actualiza el punto inicial para el siguiente movimiento
|
||||
}
|
||||
else if (_isRotatingUserControl)
|
||||
{
|
||||
// Código para rotar el control
|
||||
RotateControl(_currentDraggingControl, currentPosition);
|
||||
}
|
||||
else if (_isResizingUserControl)
|
||||
{
|
||||
// Código para cambiar el tamaño del control
|
||||
ResizeControl(_currentDraggingControl, currentPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RotateControl(UserControl control, Point currentPosition)
|
||||
{
|
||||
double deltaX = currentPosition.X - _startPointUserControl.X;
|
||||
double deltaY = currentPosition.Y - _startPointUserControl.Y;
|
||||
double angle = Math.Atan2(deltaY, deltaX) * (180 / Math.PI);
|
||||
|
||||
//RotateTransform rotateTransform = control.RenderTransform as RotateTransform;
|
||||
//rotateTransform.Angle = angle; // - _initialAngleUserControl; // Asegúrate de ajustar esta parte según cómo calcules el ángulo inicial
|
||||
|
||||
if (control is IDataContainer dataContainer && dataContainer.Datos is osBase mvBase)
|
||||
mvBase.Rotate((float)angle);
|
||||
|
||||
// Actualizar el ángulo mostrado
|
||||
_angleDisplayTextBlock.Text = $"Ángulo: {angle:F2}°";
|
||||
PositionAngleDisplay(control);
|
||||
}
|
||||
|
||||
private void PositionAngleDisplay(UserControl control)
|
||||
{
|
||||
// Posicionar el TextBlock sobre el control
|
||||
Canvas.SetLeft(_angleDisplayTextBlock, Canvas.GetLeft(control));
|
||||
Canvas.SetTop(_angleDisplayTextBlock, Canvas.GetTop(control));
|
||||
}
|
||||
|
||||
private void ResizeControl(UserControl control, Point currentPosition)
|
||||
{
|
||||
bool ActivateRotation = false, ActivateSizeWidth = false, ActivateSizeHeight = false, ActivateMove = false;
|
||||
|
||||
if (control is IDataContainer dataContainer && dataContainer.Datos is osBase mvBase)
|
||||
{
|
||||
MakeResizeRectanglesTransparent();
|
||||
|
||||
// Obtener el rectángulo desde el que se inició la redimensión
|
||||
var resizeRect = _currentDraggingRectangle as Rectangle;
|
||||
if (resizeRect == null) return;
|
||||
|
||||
string resizeDirection = resizeRect.Tag as string;
|
||||
if (resizeDirection == null) return;
|
||||
|
||||
switch (resizeDirection)
|
||||
{
|
||||
case "TopLeft":
|
||||
break;
|
||||
case "TopRight":
|
||||
ActivateRotation = true;
|
||||
break;
|
||||
case "BottomLeft":
|
||||
ActivateRotation = true;
|
||||
break;
|
||||
case "BottomRight":
|
||||
ActivateSizeHeight = true;
|
||||
ActivateSizeWidth = true;
|
||||
break;
|
||||
case "TopCenter":
|
||||
break;
|
||||
case "BottomCenter":
|
||||
ActivateSizeHeight = true;
|
||||
break;
|
||||
case "CenterLeft":
|
||||
ActivateRotation = true;
|
||||
break;
|
||||
case "CenterRight":
|
||||
ActivateSizeWidth = true;
|
||||
break;
|
||||
}
|
||||
if (ActivateMove)
|
||||
{
|
||||
// Código para mover el control
|
||||
var dx = currentPosition.X - _startPointUserControl.X;
|
||||
var dy = currentPosition.Y - _startPointUserControl.Y;
|
||||
|
||||
var newX = Canvas.GetLeft(_currentDraggingControl) + dx;
|
||||
var newY = Canvas.GetTop(_currentDraggingControl) + dy;
|
||||
|
||||
mvBase.Move(newX, newY);
|
||||
// dataContainer.Move((float)newX, (float)newY);
|
||||
}
|
||||
if (ActivateRotation)
|
||||
{
|
||||
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
|
||||
{
|
||||
mvBase.Rotate(angle - lastAngle);
|
||||
lastAngle = (float)angle;
|
||||
|
||||
dataDebug.TransformedBoundingBoxCenter = transformedBoundingBoxCenter;
|
||||
dataDebug.LastAngle = lastAngle;
|
||||
dataDebug.CurrentPosition = currentPosition;
|
||||
dataDebug.Angle = (float)angle;
|
||||
}
|
||||
}
|
||||
if (ActivateSizeWidth || ActivateSizeHeight)
|
||||
{
|
||||
// Calcular la diferencia en la posición X desde el punto de inicio
|
||||
double widthChange = currentPosition.X - _startPointUserControl.X;
|
||||
|
||||
// Calcular la diferencia en la posición Y desde el punto de inicio
|
||||
double heightChange = currentPosition.Y - _startPointUserControl.Y;
|
||||
|
||||
if (!ActivateSizeHeight) heightChange = 0;
|
||||
if (!ActivateSizeWidth) widthChange = 0;
|
||||
|
||||
mvBase.Resize(widthChange, heightChange);
|
||||
// dataContainer.Resize((float)widthChange, (float)heightChange);
|
||||
}
|
||||
_startPointUserControl = currentPosition; // Actualiza el punto inicial para el siguiente movimiento
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void UserControl_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_currentDraggingControl != null)
|
||||
{
|
||||
RemoveResizeRectangles();
|
||||
}
|
||||
|
||||
if (sender is UserControl userControl)
|
||||
if (userControl is IDataContainer dataContainer)
|
||||
{
|
||||
dataContainer.Highlight(true);
|
||||
_currentDraggingControl = sender as UserControl;
|
||||
AddResizeRectangles(_currentDraggingControl);
|
||||
}
|
||||
}
|
||||
|
||||
private void UserControl_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (sender is UserControl userControl)
|
||||
if (userControl is IDataContainer dataContainer)
|
||||
dataContainer.Highlight(false);
|
||||
}
|
||||
|
||||
private void ViewModel_ImageSelected(object sender, string imagePath)
|
||||
{
|
||||
LoadImageToCanvas(imagePath);
|
||||
}
|
||||
|
||||
private void LoadImageToCanvas(string imagePath)
|
||||
{
|
||||
BitmapImage bitmap = new BitmapImage(new Uri(imagePath, UriKind.Absolute));
|
||||
|
@ -645,7 +112,6 @@ namespace CtrEditor
|
|||
imagenDeFondo.Source = bitmap;
|
||||
RenderOptions.SetBitmapScalingMode(imagenDeFondo, BitmapScalingMode.HighQuality);
|
||||
|
||||
|
||||
// Elimina solo los ROIs, no la imagen de fondo
|
||||
for (int i = ImagenEnTrabajoCanvas.Children.Count - 1; i >= 0; i--)
|
||||
{
|
||||
|
@ -655,14 +121,11 @@ namespace CtrEditor
|
|||
}
|
||||
}
|
||||
|
||||
// Ajusta el tamaño del Canvas a la imagen, si es necesario
|
||||
ImagenEnTrabajoCanvas.Width = bitmap.Width;
|
||||
ImagenEnTrabajoCanvas.Height = bitmap.Height;
|
||||
|
||||
// Posiciona la imagen correctamente dentro del Canvas
|
||||
Canvas.SetLeft(imagenDeFondo, 0);
|
||||
Canvas.SetTop(imagenDeFondo, 0);
|
||||
|
||||
}
|
||||
|
||||
private void Canvas_MouseUp_Panning(object sender, MouseButtonEventArgs e)
|
||||
|
@ -670,64 +133,79 @@ namespace CtrEditor
|
|||
if (_isDraggingCanvas)
|
||||
{
|
||||
_isDraggingCanvas = false;
|
||||
ImagenEnTrabajoScrollViewer.ReleaseMouseCapture(); // Finaliza la captura del ratón
|
||||
ImagenEnTrabajoCanvas.ReleaseMouseCapture();
|
||||
|
||||
if (DataContext is MainViewModel viewModel && viewModel.SelectedItemOsList != null)
|
||||
{
|
||||
_objectManager.MakeResizeRectanglesNormal();
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Canvas_MouseDown_Panning(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed && !_isDrawingCanvas && !_isMovingUserControl)
|
||||
if (e.LeftButton == MouseButtonState.Pressed && !_isDrawingCanvas)
|
||||
{
|
||||
// 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
|
||||
// Solo activar el panning si el clic fue directamente en el canvas
|
||||
if (e.Source == ImagenEnTrabajoCanvas)
|
||||
{
|
||||
_isDraggingCanvas = true;
|
||||
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
||||
ImagenEnTrabajoCanvas.CaptureMouse();
|
||||
|
||||
if (DataContext is MainViewModel viewModel)
|
||||
{
|
||||
viewModel.SelectedItemOsList = null;
|
||||
_objectManager.RemoveResizeRectangles();
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Canvas_MouseMove_Panning(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (_isDraggingCanvas)
|
||||
if (_isDraggingCanvas && e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
var currentPosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
||||
var dx = currentPosition.X - _lastMousePosition.X;
|
||||
var dy = currentPosition.Y - _lastMousePosition.Y;
|
||||
|
||||
MakeResizeRectanglesTransparent();
|
||||
_objectManager.MakeResizeRectanglesTransparent();
|
||||
_objectManager.RemoveHighlightRectangles();
|
||||
|
||||
// Obtener la transformación actual del Canvas
|
||||
var transform = (TranslateTransform)((TransformGroup)ImagenEnTrabajoCanvas.RenderTransform).Children.First(t => t is TranslateTransform);
|
||||
var transform = (TranslateTransform)((TransformGroup)ImagenEnTrabajoCanvas.RenderTransform)
|
||||
.Children.First(t => t is TranslateTransform);
|
||||
transform.X += dx;
|
||||
transform.Y += dy;
|
||||
|
||||
_lastMousePosition = currentPosition;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ImagenEnTrabajoCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
MakeResizeRectanglesTransparent();
|
||||
_objectManager.MakeResizeRectanglesTransparent();
|
||||
_objectManager.RemoveHighlightRectangles();
|
||||
|
||||
_initialZoomFactor = ((ScaleTransform)((TransformGroup)ImagenEnTrabajoCanvas.RenderTransform).Children.First(t => t is ScaleTransform)).ScaleX;
|
||||
_initialZoomFactor = ((ScaleTransform)((TransformGroup)ImagenEnTrabajoCanvas.RenderTransform)
|
||||
.Children.First(t => t is ScaleTransform)).ScaleX;
|
||||
|
||||
// Calcula el factor de escala mínimo para que toda la imagen sea visible
|
||||
double minZoomFactor = Math.Min(
|
||||
ImagenEnTrabajoScrollViewer.ViewportWidth / ImagenEnTrabajoCanvas.ActualWidth,
|
||||
ImagenEnTrabajoScrollViewer.ViewportHeight / ImagenEnTrabajoCanvas.ActualHeight);
|
||||
|
||||
// Ajusta el targetZoomFactor pero no permite que baje del mínimo
|
||||
_targetZoomFactor = e.Delta > 0 ? _initialZoomFactor * 1.4 : Math.Max(_initialZoomFactor * 0.75, minZoomFactor);
|
||||
_targetZoomFactor = e.Delta > 0 ?
|
||||
_initialZoomFactor * 1.4 :
|
||||
Math.Max(_initialZoomFactor * 0.75, minZoomFactor);
|
||||
|
||||
_zoomCursorPosition = e.GetPosition(ImagenEnTrabajoCanvas);
|
||||
|
||||
// Desactivar el escalado de alta calidad para mejorar el rendimiento
|
||||
RenderOptions.SetBitmapScalingMode(ImagenEnTrabajoCanvas, BitmapScalingMode.LowQuality);
|
||||
|
||||
if (!_zoomTimer.IsEnabled)
|
||||
_ZoomDuration = ZoomDuration;
|
||||
else
|
||||
_ZoomDuration = ZoomDuration / 3;
|
||||
_ZoomDuration = !_zoomTimer.IsEnabled ? ZoomDuration : ZoomDuration / 3;
|
||||
|
||||
_stopwatch.Restart();
|
||||
_zoomTimer.Start();
|
||||
|
@ -735,7 +213,6 @@ namespace CtrEditor
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
|
||||
private void ZoomTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
double elapsedMilliseconds = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
|
@ -745,9 +222,13 @@ namespace CtrEditor
|
|||
_zoomTimer.Stop();
|
||||
_stopwatch.Stop();
|
||||
|
||||
// Volver a activar el escalado de alta calidad después de completar el zoom
|
||||
RenderOptions.SetBitmapScalingMode(ImagenEnTrabajoCanvas, BitmapScalingMode.HighQuality);
|
||||
|
||||
if (DataContext is MainViewModel viewModel && viewModel.SelectedItemOsList != null)
|
||||
{
|
||||
_objectManager.MakeResizeRectanglesNormal();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -755,12 +236,10 @@ namespace CtrEditor
|
|||
var st = (ScaleTransform)tg.Children.First(t => t is ScaleTransform);
|
||||
var tt = (TranslateTransform)tg.Children.First(t => t is TranslateTransform);
|
||||
|
||||
// Interpolación cuadrática para la desaceleración
|
||||
double t = elapsedMilliseconds / _ZoomDuration;
|
||||
double easeOutT = t * (2 - t); // Función de interpolación cuadrática (ease-out)
|
||||
double easeOutT = t * (2 - t);
|
||||
double zoomFactor = _initialZoomFactor + (_targetZoomFactor - _initialZoomFactor) * easeOutT;
|
||||
|
||||
// Asegúrate de no ir por debajo del zoom mínimo
|
||||
zoomFactor = Math.Max(zoomFactor, MinZoomScale);
|
||||
|
||||
Point cursorPosition = _zoomCursorPosition;
|
||||
|
@ -775,37 +254,64 @@ namespace CtrEditor
|
|||
tt.Y = relativeY - cursorPosition.Y * st.ScaleY;
|
||||
}
|
||||
|
||||
public (float X, float Y) ObtenerCentroCanvasPixels()
|
||||
private void ListaOs_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
{
|
||||
// Obtener las transformaciones actuales del Canvas
|
||||
var tg = (TransformGroup)ImagenEnTrabajoCanvas.RenderTransform;
|
||||
var st = (ScaleTransform)tg.Children.First(t => t is ScaleTransform);
|
||||
var tt = (TranslateTransform)tg.Children.First(t => t is TranslateTransform);
|
||||
UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion);
|
||||
|
||||
// Obtener el tamaño del ScrollViewer visible
|
||||
double visibleWidth = ImagenEnTrabajoScrollViewer.ViewportWidth;
|
||||
double visibleHeight = ImagenEnTrabajoScrollViewer.ViewportHeight;
|
||||
if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject)
|
||||
{
|
||||
// Siempre trabajar con selección única para las propiedades
|
||||
CargarPropiedadesosDatos(selectedObject);
|
||||
|
||||
// Obtener el desplazamiento del ScrollViewer
|
||||
double offsetX = ImagenEnTrabajoScrollViewer.HorizontalOffset;
|
||||
double offsetY = ImagenEnTrabajoScrollViewer.VerticalOffset;
|
||||
|
||||
// Calcular las coordenadas del centro visible del ScrollViewer
|
||||
double centerX = offsetX + (visibleWidth / 2);
|
||||
double centerY = offsetY + (visibleHeight / 2);
|
||||
|
||||
// Ajustar las coordenadas del centro para tener en cuenta las transformaciones del Canvas
|
||||
double canvasCenterX = (centerX - tt.X) / st.ScaleX;
|
||||
double canvasCenterY = (centerY - tt.Y) / st.ScaleY;
|
||||
|
||||
return ((float)canvasCenterX, (float)canvasCenterY);
|
||||
// No modificar la selección múltiple aquí, solo actualizar los rectángulos de manipulación
|
||||
// si el objeto seleccionado no está en la selección actual
|
||||
if (!_objectManager.SelectedObjects.Contains(selectedObject))
|
||||
{
|
||||
if (!((MainViewModel)DataContext).IsMultiSelectionActive)
|
||||
{
|
||||
_objectManager.ClearSelection();
|
||||
_objectManager.SelectObject(selectedObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_objectManager.RemoveResizeRectangles();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CargarPropiedadesosDatos(osBase selectedObject)
|
||||
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (DataContext is MainViewModel viewModel)
|
||||
viewModel.CargarPropiedadesosDatos(selectedObject, PanelEdicion, Resources);
|
||||
{
|
||||
if (e.Key == Key.Delete)
|
||||
{
|
||||
viewModel.EliminarObjetoSeleccionado();
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Escape)
|
||||
{
|
||||
// Limpiar la selección en el ListBox
|
||||
viewModel.SelectedItemOsList = null;
|
||||
|
||||
// Limpiar la selección múltiple
|
||||
_objectManager.ClearSelection();
|
||||
_objectManager.RemoveResizeRectangles();
|
||||
|
||||
// Desactivar el modo de selección múltiple
|
||||
viewModel.IsMultiSelectionActive = false;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Canvas_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource == ImagenEnTrabajoCanvas)
|
||||
{
|
||||
//_objectManager.RemoveResizeRectangles();
|
||||
}
|
||||
}
|
||||
|
||||
private void MainWindow_Closed(object sender, EventArgs e)
|
||||
|
@ -816,30 +322,87 @@ namespace CtrEditor
|
|||
}
|
||||
}
|
||||
|
||||
private void ListaOs_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||
private void CargarPropiedadesosDatos(osBase selectedObject)
|
||||
{
|
||||
//PanelEdicion.Children.Clear(); // Limpiar el panel existente
|
||||
UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion);
|
||||
if (DataContext is MainViewModel viewModel)
|
||||
viewModel.CargarPropiedadesosDatos(selectedObject, PanelEdicion, Resources);
|
||||
}
|
||||
|
||||
if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject)
|
||||
public (float X, float Y) ObtenerCentroCanvasMeters()
|
||||
{
|
||||
var c = ObtenerCentroCanvasPixels();
|
||||
return (PixelToMeter.Instance.calc.PixelsToMeters(c.X),
|
||||
PixelToMeter.Instance.calc.PixelsToMeters(c.Y));
|
||||
}
|
||||
|
||||
public (float X, float Y) ObtenerCentroCanvasPixels()
|
||||
{
|
||||
var tg = (TransformGroup)ImagenEnTrabajoCanvas.RenderTransform;
|
||||
var st = (ScaleTransform)tg.Children.First(t => t is ScaleTransform);
|
||||
var tt = (TranslateTransform)tg.Children.First(t => t is TranslateTransform);
|
||||
|
||||
double visibleWidth = ImagenEnTrabajoScrollViewer.ViewportWidth;
|
||||
double visibleHeight = ImagenEnTrabajoScrollViewer.ViewportHeight;
|
||||
|
||||
double offsetX = ImagenEnTrabajoScrollViewer.HorizontalOffset;
|
||||
double offsetY = ImagenEnTrabajoScrollViewer.VerticalOffset;
|
||||
|
||||
double centerX = offsetX + (visibleWidth / 2);
|
||||
double centerY = offsetY + (visibleHeight / 2);
|
||||
|
||||
double canvasCenterX = (centerX - tt.X) / st.ScaleX;
|
||||
double canvasCenterY = (centerY - tt.Y) / st.ScaleY;
|
||||
|
||||
return ((float)canvasCenterX, (float)canvasCenterY);
|
||||
}
|
||||
|
||||
private void ViewModel_ImageSelected(object sender, string imagePath)
|
||||
{
|
||||
LoadImageToCanvas(imagePath);
|
||||
}
|
||||
|
||||
public void DebugWindow()
|
||||
{
|
||||
var debugWindow = new wDebug
|
||||
{
|
||||
if (selectedObject.VisualRepresentation != null)
|
||||
{
|
||||
_currentDraggingControl = selectedObject.VisualRepresentation;
|
||||
AddResizeRectangles(_currentDraggingControl);
|
||||
}
|
||||
CargarPropiedadesosDatos(selectedObject);
|
||||
Data = dataDebug
|
||||
};
|
||||
debugWindow.Show();
|
||||
}
|
||||
|
||||
private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// Aceptar el evento si viene del canvas o de la imagen de fondo
|
||||
if ((e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo) && DataContext is MainViewModel viewModel)
|
||||
{
|
||||
e.Handled = true; // Importante: marcar el evento como manejado
|
||||
ShowContextMenu(e.GetPosition(ImagenEnTrabajoCanvas));
|
||||
}
|
||||
}
|
||||
|
||||
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
|
||||
private void ShowContextMenu(Point position)
|
||||
{
|
||||
if (e.Key == Key.Delete && DataContext is MainViewModel viewModel)
|
||||
var contextMenu = new ContextMenu();
|
||||
var multiSelectMenuItem = new MenuItem
|
||||
{
|
||||
Header = "Modo Multi-Selección",
|
||||
IsCheckable = true,
|
||||
StaysOpenOnClick = false // Cerrar el menú al hacer clic
|
||||
};
|
||||
|
||||
if (DataContext is MainViewModel viewModel)
|
||||
{
|
||||
viewModel.EliminarObjetoSeleccionado();
|
||||
e.Handled = true;
|
||||
multiSelectMenuItem.IsChecked = viewModel.IsMultiSelectionActive;
|
||||
multiSelectMenuItem.Click += (s, e) =>
|
||||
{
|
||||
viewModel.IsMultiSelectionActive = multiSelectMenuItem.IsChecked;
|
||||
};
|
||||
}
|
||||
|
||||
contextMenu.Items.Add(multiSelectMenuItem);
|
||||
contextMenu.PlacementTarget = ImagenEnTrabajoCanvas;
|
||||
contextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;
|
||||
contextMenu.IsOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -847,16 +410,13 @@ namespace CtrEditor
|
|||
{
|
||||
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
|
||||
{
|
||||
// Comprobamos si el valor es nulo o está vacío
|
||||
if (string.IsNullOrEmpty(value?.ToString()))
|
||||
return new ValidationResult(false, "El campo no puede estar vacío.");
|
||||
|
||||
// Intentamos convertir el valor a un tipo float
|
||||
if (float.TryParse(value.ToString(), NumberStyles.Float, cultureInfo, out float result))
|
||||
return ValidationResult.ValidResult; // La validación es exitosa
|
||||
return ValidationResult.ValidResult;
|
||||
else
|
||||
return new ValidationResult(false, "Ingrese un número válido.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,616 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Threading;
|
||||
using CtrEditor.FuncionesBase;
|
||||
using CtrEditor.ObjetosSim;
|
||||
using Color = System.Windows.Media.Color;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace CtrEditor
|
||||
{
|
||||
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>();
|
||||
|
||||
public ObjectManipulationManager(MainWindow mainWindow, Canvas canvas)
|
||||
{
|
||||
_mainWindow = mainWindow;
|
||||
_canvas = canvas;
|
||||
}
|
||||
|
||||
public ObservableCollection<osBase> SelectedObjects
|
||||
{
|
||||
get => _selectedObjects;
|
||||
private set
|
||||
{
|
||||
_selectedObjects = value;
|
||||
UpdateSelectionVisuals();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSelectionVisuals()
|
||||
{
|
||||
RemoveResizeRectangles();
|
||||
if (_selectedObjects.Any())
|
||||
{
|
||||
AddResizeRectangles(_selectedObjects);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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 && obj.Show_On_This_Page)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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 rectSize,
|
||||
Cursor rotationCursorRx, Cursor rotationCursorSx)
|
||||
{
|
||||
var positions = new List<(Point Position, string Tag, Cursor Cursor, Brush Stroke)>
|
||||
{
|
||||
(new Point(rectBox.Left, rectBox.Top), "TopLeft", Cursors.Arrow, Brushes.Gray),
|
||||
(new Point(rectBox.Right, rectBox.Top), "TopRight", rotationCursorRx, Brushes.Red),
|
||||
(new Point(rectBox.Left, rectBox.Bottom), "BottomLeft", rotationCursorSx, Brushes.DarkRed),
|
||||
(new Point(rectBox.Right, rectBox.Bottom), "BottomRight", Cursors.SizeNWSE, Brushes.Blue),
|
||||
(new Point(rectBox.Left + rectBox.Width / 2, rectBox.Top), "TopCenter", Cursors.Arrow, Brushes.Gray),
|
||||
(new Point(rectBox.Left + rectBox.Width / 2, rectBox.Bottom), "BottomCenter", Cursors.SizeNS, Brushes.Blue),
|
||||
(new Point(rectBox.Left, rectBox.Top + rectBox.Height / 2), "CenterLeft", rotationCursorRx, Brushes.Red),
|
||||
(new Point(rectBox.Right, 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)
|
||||
{
|
||||
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 (!_selectedObjects.Contains(obj))
|
||||
{
|
||||
_selectedObjects.Add(obj);
|
||||
obj.IsSelected = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeselectObject(osBase obj)
|
||||
{
|
||||
if (_selectedObjects.Contains(obj))
|
||||
{
|
||||
_selectedObjects.Remove(obj);
|
||||
obj.IsSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearSelection()
|
||||
{
|
||||
foreach (var obj in _selectedObjects.ToList())
|
||||
{
|
||||
DeselectObject(obj);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
var dx = currentPosition.X - _startPointUserControl.X;
|
||||
var dy = currentPosition.Y - _startPointUserControl.Y;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
UpdateSelectionVisuals();
|
||||
_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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -509,6 +509,8 @@ namespace CtrEditor.ObjetosSim
|
|||
[property: Hidden]
|
||||
UniqueId cloned_from;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isSelected;
|
||||
|
||||
private async void TimerCallback(object state)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue