826 lines
34 KiB
C#
826 lines
34 KiB
C#
using System.Globalization;
|
|
using System.Windows;
|
|
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.FuncionesBase;
|
|
|
|
namespace CtrEditor
|
|
{
|
|
/// <summary>
|
|
/// Interaction logic for MainWindow.xaml
|
|
/// </summary>
|
|
///
|
|
public partial class MainWindow : Window
|
|
{
|
|
// Para el Canvas
|
|
private Point _lastMousePosition;
|
|
private bool _isDrawingCanvas = false;
|
|
private bool _isDraggingCanvas = false;
|
|
private Image imagenDeFondo;
|
|
|
|
private List<Rectangle> resizeRectangles = new List<Rectangle>();
|
|
|
|
private DispatcherTimer _zoomTimer;
|
|
private double _targetZoomFactor;
|
|
private double _initialZoomFactor;
|
|
private double _currentZoomStep;
|
|
private Point _zoomCursorPosition;
|
|
private const int ZoomDuration = 500; // Duración del zoom en milisegundos
|
|
private int _ZoomDuration;
|
|
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 double _initialAngleUserControl;
|
|
private TextBlock _angleDisplayTextBlock;
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
|
|
_zoomTimer = new DispatcherTimer();
|
|
_zoomTimer.Interval = TimeSpan.FromMilliseconds(1);
|
|
_zoomTimer.Tick += ZoomTimer_Tick;
|
|
_stopwatch = new Stopwatch();
|
|
|
|
this.Loaded += MainWindow_Loaded;
|
|
ImagenEnTrabajoScrollViewer.PreviewMouseWheel += ImagenEnTrabajoCanvas_MouseWheel;
|
|
ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown_Panning;
|
|
ImagenEnTrabajoCanvas.MouseMove += Canvas_MouseMove_Panning;
|
|
ImagenEnTrabajoCanvas.MouseUp += Canvas_MouseUp_Panning;
|
|
}
|
|
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
if (DataContext is MainViewModel viewModel)
|
|
{
|
|
viewModel.MainWindow = this;
|
|
viewModel.ImageSelected += ViewModel_ImageSelected;
|
|
viewModel?.LoadInitialData(); // Carga la primera imagen por defecto una vez cargada la ventana principal
|
|
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;
|
|
}
|
|
|
|
public void AgregarRegistrarUserControlCanvas(UserControl userControl)
|
|
{
|
|
if (userControl is IDataContainer dataContainer)
|
|
{
|
|
SuscribirEventos(userControl);
|
|
|
|
// Añade el UserControl al Canvas
|
|
Canvas.SetZIndex(userControl, ((int)dataContainer.ZIndex()));
|
|
ImagenEnTrabajoCanvas.Children.Add(userControl);
|
|
}
|
|
}
|
|
|
|
public void EliminarUserControlDelCanvas(UserControl userControl)
|
|
{
|
|
if (ImagenEnTrabajoCanvas.Children.Contains(userControl))
|
|
{
|
|
ImagenEnTrabajoCanvas.Children.Remove(userControl);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
_initialAngleUserControl = rotateTransform.Angle;
|
|
|
|
// 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)
|
|
{
|
|
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")
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
Canvas.SetLeft(rect, position.Item1.X - rectSize / 2);
|
|
Canvas.SetTop(rect, 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 UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
|
{
|
|
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));
|
|
|
|
if (imagenDeFondo == null)
|
|
{
|
|
imagenDeFondo = new Image();
|
|
ImagenEnTrabajoCanvas.Children.Add(imagenDeFondo);
|
|
}
|
|
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--)
|
|
{
|
|
if (ImagenEnTrabajoCanvas.Children[i] is not Image)
|
|
{
|
|
ImagenEnTrabajoCanvas.Children.RemoveAt(i);
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
if (_isDraggingCanvas)
|
|
{
|
|
_isDraggingCanvas = false;
|
|
ImagenEnTrabajoScrollViewer.ReleaseMouseCapture(); // Finaliza la captura del ratón
|
|
}
|
|
}
|
|
|
|
private void Canvas_MouseDown_Panning(object sender, MouseButtonEventArgs e)
|
|
{
|
|
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
|
|
}
|
|
}
|
|
|
|
private void Canvas_MouseMove_Panning(object sender, MouseEventArgs e)
|
|
{
|
|
if (_isDraggingCanvas)
|
|
{
|
|
var currentPosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
|
var dx = currentPosition.X - _lastMousePosition.X;
|
|
var dy = currentPosition.Y - _lastMousePosition.Y;
|
|
|
|
MakeResizeRectanglesTransparent();
|
|
|
|
// Obtener la transformación actual del Canvas
|
|
var transform = (TranslateTransform)((TransformGroup)ImagenEnTrabajoCanvas.RenderTransform).Children.First(t => t is TranslateTransform);
|
|
transform.X += dx;
|
|
transform.Y += dy;
|
|
|
|
_lastMousePosition = currentPosition;
|
|
}
|
|
}
|
|
|
|
private void ImagenEnTrabajoCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
|
|
{
|
|
MakeResizeRectanglesTransparent();
|
|
|
|
_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);
|
|
|
|
_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;
|
|
|
|
_stopwatch.Restart();
|
|
_zoomTimer.Start();
|
|
|
|
e.Handled = true;
|
|
}
|
|
|
|
|
|
private void ZoomTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
double elapsedMilliseconds = _stopwatch.ElapsedMilliseconds;
|
|
|
|
if (elapsedMilliseconds >= _ZoomDuration)
|
|
{
|
|
_zoomTimer.Stop();
|
|
_stopwatch.Stop();
|
|
|
|
// Volver a activar el escalado de alta calidad después de completar el zoom
|
|
RenderOptions.SetBitmapScalingMode(ImagenEnTrabajoCanvas, BitmapScalingMode.HighQuality);
|
|
|
|
return;
|
|
}
|
|
|
|
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);
|
|
|
|
// 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 zoomFactor = _initialZoomFactor + (_targetZoomFactor - _initialZoomFactor) * easeOutT;
|
|
|
|
// Asegúrate de no ir por debajo del zoom mínimo
|
|
zoomFactor = Math.Max(zoomFactor, MinZoomScale);
|
|
|
|
Point cursorPosition = _zoomCursorPosition;
|
|
|
|
var relativeX = cursorPosition.X * st.ScaleX + tt.X;
|
|
var relativeY = cursorPosition.Y * st.ScaleY + tt.Y;
|
|
|
|
st.ScaleX = zoomFactor;
|
|
st.ScaleY = zoomFactor;
|
|
|
|
tt.X = relativeX - cursorPosition.X * st.ScaleX;
|
|
tt.Y = relativeY - cursorPosition.Y * st.ScaleY;
|
|
}
|
|
|
|
public (float X, float Y) ObtenerCentroCanvasPixels()
|
|
{
|
|
// 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);
|
|
|
|
// Obtener el tamaño del ScrollViewer visible
|
|
double visibleWidth = ImagenEnTrabajoScrollViewer.ViewportWidth;
|
|
double visibleHeight = ImagenEnTrabajoScrollViewer.ViewportHeight;
|
|
|
|
// 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);
|
|
}
|
|
|
|
|
|
private void CargarPropiedadesosDatos(osBase selectedObject)
|
|
{
|
|
if (DataContext is MainViewModel viewModel)
|
|
viewModel.CargarPropiedadesosDatos(selectedObject, PanelEdicion, Resources);
|
|
}
|
|
|
|
private void MainWindow_Closed(object sender, EventArgs e)
|
|
{
|
|
if (DataContext is MainViewModel viewModel)
|
|
{
|
|
viewModel.ImageSelected -= ViewModel_ImageSelected;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (selectedObject.VisualRepresentation != null)
|
|
{
|
|
_currentDraggingControl = selectedObject.VisualRepresentation;
|
|
AddResizeRectangles(_currentDraggingControl);
|
|
}
|
|
CargarPropiedadesosDatos(selectedObject);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
public class FloatValidationRule : ValidationRule
|
|
{
|
|
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
|
|
else
|
|
return new ValidationResult(false, "Ingrese un número válido.");
|
|
}
|
|
}
|
|
|
|
} |