CtrEditor/MainWindow.xaml.cs

569 lines
23 KiB
C#
Raw Normal View History

2024-05-11 11:58:55 -03:00
using System.Globalization;
using System.Text;
2024-05-01 14:45:20 -03:00
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
2024-05-04 16:27:04 -03:00
using System.Windows.Forms;
2024-05-01 14:45:20 -03:00
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CtrEditor.ObjetosSim;
2024-05-11 11:58:55 -03:00
using CtrEditor.Convertidores;
using CtrEditor.Siemens;
using static System.Runtime.InteropServices.JavaScript.JSType;
2024-05-04 16:27:04 -03:00
using Binding = System.Windows.Data.Binding;
using Label = System.Windows.Controls.Label;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using TextBox = System.Windows.Controls.TextBox;
using UserControl = System.Windows.Controls.UserControl;
using CheckBox = System.Windows.Controls.CheckBox;
using Orientation = System.Windows.Controls.Orientation;
using ListBox = System.Windows.Controls.ListBox;
2024-05-01 14:45:20 -03:00
2024-05-11 11:58:55 -03:00
2024-05-01 14:45:20 -03:00
namespace CtrEditor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
///
2024-05-01 14:45:20 -03:00
public partial class MainWindow : Window
{
// Para el Canvas
private Point _lastMousePosition;
private bool _isDrawingCanvas = false;
private bool _isDraggingCanvas = false;
private Image imagenDeFondo;
// 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;
2024-05-01 14:45:20 -03:00
public MainWindow()
{
InitializeComponent();
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;
}
}
public (float X, float Y) ObtenerCentroCanvasPixels()
{
var scaleTransform = ImagenEnTrabajoCanvas.LayoutTransform as ScaleTransform;
float scaleX = (float)(scaleTransform?.ScaleX ?? 1.0);
float scaleY = (float)(scaleTransform?.ScaleY ?? 1.0);
// Obtiene el área visible del ScrollViewer
float visibleWidth = (float)ImagenEnTrabajoScrollViewer.ViewportWidth;
float visibleHeight = (float)ImagenEnTrabajoScrollViewer.ViewportHeight;
// Obtiene la posición actual del desplazamiento ajustada por el zoom
float offsetX = (float)ImagenEnTrabajoScrollViewer.HorizontalOffset / scaleX;
float offsetY = (float)ImagenEnTrabajoScrollViewer.VerticalOffset / scaleY;
// Calcula el centro visible ajustado
float centerX = offsetX + (visibleWidth / scaleX) / 2;
float centerY = offsetY + (visibleHeight / scaleY) / 2;
return (centerX, centerY);
}
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, 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)
{
var userControl = sender as UserControl;
_currentDraggingControl = userControl;
userControl.CaptureMouse(); // Importante para recibir eventos de movimiento incluso fuera del control
_isMovingUserControl = true;
2024-05-04 16:27:04 -03:00
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;
}
// MOVIMIENTO
else
{
// Inicializar el movimiento/panning
_isDraggingUserControl = true;
_startPointUserControl = e.GetPosition(ImagenEnTrabajoCanvas);
}
}
}
private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (_isMovingUserControl)
{
var userControl = sender as UserControl;
userControl.ReleaseMouseCapture();
_currentDraggingControl = null;
_isResizingUserControl = _isRotatingUserControl = _isDraggingUserControl = false ;
_isMovingUserControl = false;
// Ocultar el TextBlock de ángulo
if (_angleDisplayTextBlock != null)
{
_angleDisplayTextBlock.Visibility = Visibility.Collapsed;
}
}
}
private void UserControl_MouseMove(object sender, MouseEventArgs e)
{
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)
2024-05-06 12:31:45 -03:00
dataContainer.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)
{
2024-05-04 10:53:47 -03:00
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
2024-05-04 10:53:47 -03:00
if (control is IDataContainer dataContainer)
2024-05-06 12:31:45 -03:00
dataContainer.Rotate((float)angle);
// Actualizar el ángulo mostrado
2024-05-04 10:53:47 -03:00
_angleDisplayTextBlock.Text = $"Ángulo: {angle:F2}°";
PositionAngleDisplay(control);
}
private void PositionAngleDisplay(UserControl control)
{
// Posicionar el TextBlock sobre el control
2024-05-04 10:53:47 -03:00
Canvas.SetLeft(_angleDisplayTextBlock, Canvas.GetLeft(control));
Canvas.SetTop(_angleDisplayTextBlock, Canvas.GetTop(control));
}
private void ResizeControl(UserControl control, Point currentPosition)
{
// Calcular la diferencia en la posición X desde el punto de inicio
double widthChange = currentPosition.X - _startPointUserControl.X;
// Actualizar el ancho del control
2024-05-04 10:53:47 -03:00
double newWidth = Math.Max(control.ActualWidth + widthChange, control.MinWidth);
control.Width = newWidth; // Asegurar que no sea menor que el mínimo
if (control is IDataContainer dataContainer)
2024-05-06 12:31:45 -03:00
dataContainer.Resize((float)newWidth, 0);
// Actualizar el punto de inicio para el próximo evento de movimiento
_startPointUserControl = currentPosition;
}
private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is UserControl userControl)
2024-05-04 16:27:04 -03:00
if (userControl is IDataContainer dataContainer)
dataContainer.Highlight(true);
}
private void UserControl_MouseLeave(object sender, MouseEventArgs e)
{
if (sender is UserControl userControl)
2024-05-04 16:27:04 -03:00
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);
2024-05-01 14:45:20 -03:00
}
2024-05-02 11:06:45 -03:00
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 && !_isDrawingCanvas)
{
// Calcula el nuevo desplazamiento basado en el movimiento del ratón
var currentPosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
var dx = currentPosition.X - _lastMousePosition.X;
var dy = currentPosition.Y - _lastMousePosition.Y;
// Ajusta el desplazamiento del ScrollViewer
ImagenEnTrabajoScrollViewer.ScrollToHorizontalOffset(ImagenEnTrabajoScrollViewer.HorizontalOffset - dx);
ImagenEnTrabajoScrollViewer.ScrollToVerticalOffset(ImagenEnTrabajoScrollViewer.VerticalOffset - dy);
// Actualiza la posición del ratón para el próximo movimiento
_lastMousePosition = currentPosition;
}
}
private void ImagenEnTrabajoCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
var st = (ScaleTransform)ImagenEnTrabajoCanvas.LayoutTransform;
double zoomFactor = e.Delta > 0 ? 1.1 : 0.9;
Point cursorPosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
// Calcular el punto focal del zoom relativo al contenido del ScrollViewer
var absoluteX = ImagenEnTrabajoScrollViewer.HorizontalOffset + cursorPosition.X;
var absoluteY = ImagenEnTrabajoScrollViewer.VerticalOffset + cursorPosition.Y;
// Aplicar el zoom
st.ScaleX *= zoomFactor;
st.ScaleY *= zoomFactor;
// Calcular el nuevo desplazamiento para que el zoom se centre en la posición del cursor
ImagenEnTrabajoScrollViewer.UpdateLayout(); // Asegurarse de que el layout del ScrollViewer esté actualizado
var newHorizontalOffset = absoluteX * zoomFactor - cursorPosition.X;
var newVerticalOffset = absoluteY * zoomFactor - cursorPosition.Y;
// Aplicar el nuevo desplazamiento
ImagenEnTrabajoScrollViewer.ScrollToHorizontalOffset(newHorizontalOffset);
ImagenEnTrabajoScrollViewer.ScrollToVerticalOffset(newVerticalOffset);
e.Handled = true; // Evita el procesamiento adicional del evento
}
private void ListaOs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
PanelEdicion.Children.Clear(); // Limpiar el panel existente
if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject)
CargarPropiedadesosDatos(selectedObject);
}
private void CargarPropiedadesosDatos(osBase selectedObject)
{
2024-05-11 11:58:55 -03:00
PanelEdicion.Children.Clear();
var properties = selectedObject.GetType().GetProperties();
foreach (var property in properties)
{
if (Attribute.IsDefined(property, typeof(HiddenAttribute)))
{
continue;
}
var grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
var label = new Label
{
Content = property.Name + ":",
Margin = new Thickness(0, 0, 5, 0),
VerticalAlignment = VerticalAlignment.Center
};
if (property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int))
{
var textBox = new TextBox
{
Margin = new Thickness(0),
MinWidth = 200,
VerticalContentAlignment = VerticalAlignment.Center
};
2024-05-11 11:58:55 -03:00
var binding = new Binding(property.Name)
{
Source = selectedObject,
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus
2024-05-11 11:58:55 -03:00
};
if (property.PropertyType == typeof(float))
{
binding.Converter = (FloatToFormattedStringConverter)Resources["floatFormatter"];
2024-05-11 11:58:55 -03:00
}
textBox.SetBinding(TextBox.TextProperty, binding);
Grid.SetColumn(label, 0);
Grid.SetColumn(textBox, 1);
grid.Children.Add(label);
grid.Children.Add(textBox);
}
else if (property.PropertyType == typeof(bool))
{
var checkBox = new CheckBox
{
Margin = new Thickness(5, 0, 0, 0),
VerticalAlignment = VerticalAlignment.Center
};
var binding = new Binding(property.Name)
2024-05-11 11:58:55 -03:00
{
Source = selectedObject,
Mode = BindingMode.TwoWay
};
checkBox.SetBinding(CheckBox.IsCheckedProperty, binding);
Grid.SetColumn(label, 0);
Grid.SetColumn(checkBox, 1);
grid.Children.Add(label);
grid.Children.Add(checkBox);
2024-05-11 11:58:55 -03:00
}
else if (property.PropertyType == typeof(Brush))
{
var listBox = new ListBox
{
ItemsSource = new List<string> { "Rojo", "Azul", "Negro", "Verde", "Gris" },
Margin = new Thickness(0),
MinWidth = 200
};
listBox.SelectionChanged += (sender, e) =>
{
if (listBox.SelectedItem != null)
{
switch (listBox.SelectedItem.ToString())
{
case "Rojo":
property.SetValue(selectedObject, Brushes.Red);
break;
case "Azul":
property.SetValue(selectedObject, Brushes.Blue);
break;
case "Negro":
property.SetValue(selectedObject, Brushes.Black);
break;
case "Verde":
property.SetValue(selectedObject, Brushes.Green);
break;
case "Gris":
property.SetValue(selectedObject, Brushes.Gray);
break;
}
}
};
var binding = new Binding(property.Name)
{
Source = selectedObject,
Mode = BindingMode.TwoWay,
Converter = new BrushToColorNameConverter()
};
listBox.SetBinding(ListBox.SelectedItemProperty, binding);
Grid.SetColumn(label, 0);
Grid.SetColumn(listBox, 1);
grid.Children.Add(label);
grid.Children.Add(listBox);
}
PanelEdicion.Children.Add(grid);
2024-05-11 11:58:55 -03:00
}
}
private void MainWindow_Closed(object sender, EventArgs e)
{
if (DataContext is MainViewModel viewModel)
{
viewModel.ImageSelected -= ViewModel_ImageSelected;
}
}
2024-05-02 11:06:45 -03:00
2024-05-01 14:45:20 -03:00
}
2024-05-11 11:58:55 -03:00
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.");
}
}
2024-05-01 14:45:20 -03:00
}