Se implementó una nueva ventana de configuración de escala que permite a los usuarios ajustar la escala de simulación de manera modeless. Se añadió un temporizador para aplicar automáticamente los cambios de escala después de 0.5 segundos. Además, se mejoró la gestión de la escala en el ViewModel principal y se actualizaron los bindings de posición en osBase para asegurar una correcta visualización. Se incluyó un botón de "Aplicar" en la interfaz de usuario para facilitar la aplicación de cambios.

This commit is contained in:
Miguel 2025-06-18 21:23:39 +02:00
parent b48dbeb76e
commit 58781c13a3
4 changed files with 109 additions and 35 deletions

View File

@ -1236,34 +1236,49 @@ namespace CtrEditor
OnPropertyChanged(nameof(SelectedItemOsList));
}
// Diccionario para manejar la ventana de configuración de escala
private PopUps.ScaleConfigWindow? _scaleConfigWindow;
// Método para configurar la escala desde el menú contextual
public void ConfigureScale()
{
var currentScale = PixelToMeter.Instance.calc.Scale;
var scaleWindow = new PopUps.ScaleConfigWindow(currentScale);
scaleWindow.Owner = MainWindow;
if (scaleWindow.ShowDialog() == true)
// Verificar si ya existe una ventana de configuración de escala
if (_scaleConfigWindow != null && _scaleConfigWindow.IsVisible)
{
var newScale = scaleWindow.NewScale;
// Detener simulaciones antes de cambiar la escala
StopSimulation();
StopFluidSimulation();
DisconnectPLC();
// Actualizar la escala en el UnitConverter
PixelToMeter.Instance.calc.SetScale(newScale);
// Forzar redibujo completo del canvas y todos los objetos
ForceCanvasRedraw();
// Marcar como cambios no guardados ya que esto afecta la configuración de la imagen
HasUnsavedChanges = true;
// Limpiar historial de undo después de cambiar la escala
MainWindow?.ClearUndoHistory();
_scaleConfigWindow.Activate();
return;
}
var currentScale = PixelToMeter.Instance.calc.Scale;
_scaleConfigWindow = new PopUps.ScaleConfigWindow(currentScale, this);
_scaleConfigWindow.Owner = MainWindow;
// Manejar el cierre de la ventana
_scaleConfigWindow.Closed += (s, e) => _scaleConfigWindow = null;
// Mostrar como modeless (no modal)
_scaleConfigWindow.Show();
}
// Método público para aplicar la escala desde la ventana modeless
public void ApplyScale(float newScale)
{
// Detener simulaciones antes de cambiar la escala
StopSimulation();
StopFluidSimulation();
DisconnectPLC();
// Actualizar la escala en el UnitConverter
PixelToMeter.Instance.calc.SetScale(newScale);
// Forzar redibujo completo del canvas y todos los objetos
ForceCanvasRedraw();
// Marcar como cambios no guardados ya que esto afecta la configuración de la imagen
HasUnsavedChanges = true;
// Limpiar historial de undo después de cambiar la escala
MainWindow?.ClearUndoHistory();
}
// Método para forzar el redibujo completo del canvas

View File

@ -1202,10 +1202,8 @@ namespace CtrEditor.ObjetosSim
public void ForceUpdatePositionBindings()
{
// Para Left y Top, actualizar directamente el Canvas ya que tienen lógica especial en OnChanged
OnPropertyChanged(nameof(Left));
OnPropertyChanged(nameof(Top));
// CanvasSetLeftinMeter(Left);
// CanvasSetTopinMeter(Top);
CanvasSetLeftinMeter(Left);
CanvasSetTopinMeter(Top);
// Para Ancho y Alto, disparar PropertyChanged para que los bindings se actualicen
OnPropertyChanged(nameof(Ancho));

View File

@ -80,6 +80,8 @@
<Run Text="• Valores mayores = objetos más grandes en pantalla"/>
<LineBreak/>
<Run Text="• Ejemplo: 0.01 significa que 1 píxel = 1 centímetro"/>
<LineBreak/>
<Run Text="• Los cambios se aplican automáticamente después de 0.5 segundos"/>
</TextBlock>
</StackPanel>
</Border>
@ -88,6 +90,11 @@
<StackPanel Grid.Row="6"
Orientation="Horizontal"
HorizontalAlignment="Right">
<Button Content="Aplicar"
Command="{Binding ApplyCommand}"
Width="80"
Height="30"
Margin="0,0,10,0"/>
<Button Content="Aceptar"
Command="{Binding AcceptCommand}"
Width="80"

View File

@ -1,7 +1,9 @@
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@ -9,10 +11,10 @@ namespace CtrEditor.PopUps
{
public partial class ScaleConfigWindow : Window
{
public ScaleConfigWindow(float currentScale)
public ScaleConfigWindow(float currentScale, MainViewModel mainViewModel)
{
InitializeComponent();
DataContext = new ScaleConfigViewModel(currentScale, this);
DataContext = new ScaleConfigViewModel(currentScale, this, mainViewModel);
}
public float NewScale => ((ScaleConfigViewModel)DataContext).NewScale;
@ -21,6 +23,9 @@ namespace CtrEditor.PopUps
public partial class ScaleConfigViewModel : ObservableObject
{
private readonly ScaleConfigWindow _window;
private readonly MainViewModel _mainViewModel;
private float _originalScale;
private DispatcherTimer _autoApplyTimer;
[ObservableProperty]
private float currentScale;
@ -31,16 +36,34 @@ namespace CtrEditor.PopUps
public ICommand SetPresetCommand { get; }
public ICommand AcceptCommand { get; }
public ICommand CancelCommand { get; }
public ICommand ApplyCommand { get; }
public ScaleConfigViewModel(float currentScale, ScaleConfigWindow window)
public ScaleConfigViewModel(float currentScale, ScaleConfigWindow window, MainViewModel mainViewModel)
{
_window = window;
_mainViewModel = mainViewModel;
_originalScale = currentScale;
CurrentScale = currentScale;
NewScale = currentScale;
// Inicializar timer para aplicación automática
_autoApplyTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(500) // 500ms de delay
};
_autoApplyTimer.Tick += (s, e) =>
{
_autoApplyTimer.Stop();
if (NewScale > 0 && NewScale != CurrentScale)
{
Apply();
}
};
SetPresetCommand = new RelayCommand<object>(SetPreset);
AcceptCommand = new RelayCommand(Accept, CanAccept);
CancelCommand = new RelayCommand(Cancel);
ApplyCommand = new RelayCommand(Apply, CanAccept);
}
private void SetPreset(object parameter)
@ -70,16 +93,37 @@ namespace CtrEditor.PopUps
return;
}
// Debugging: mostrar mensaje para confirmar que se ejecuta
// MessageBox.Show($"Accept ejecutado con escala: {NewScale}", "Debug", MessageBoxButton.OK, MessageBoxImage.Information);
// Aplicar la escala una última vez antes de cerrar
Apply();
_window.DialogResult = true;
// No necesitamos llamar Close() ya que establecer DialogResult automáticamente cierra la ventana
// Cerrar la ventana
_window.Close();
}
private void Apply()
{
if (NewScale <= 0)
{
MessageBox.Show("La escala debe ser un valor positivo mayor que cero.",
"Error de Validación",
MessageBoxButton.OK,
MessageBoxImage.Warning);
return;
}
// Aplicar la escala inmediatamente
_mainViewModel.ApplyScale(NewScale);
// Actualizar la escala actual para reflejar el cambio
CurrentScale = NewScale;
}
private void Cancel()
{
_window.DialogResult = false;
// Restaurar la escala original
_mainViewModel.ApplyScale(_originalScale);
// Cerrar la ventana
_window.Close();
}
@ -87,6 +131,16 @@ namespace CtrEditor.PopUps
{
// Forzar la re-evaluación del comando Accept cuando el valor cambia
CommandManager.InvalidateRequerySuggested();
// Reiniciar el timer para aplicación automática (verificar que esté inicializado)
if (_autoApplyTimer != null)
{
_autoApplyTimer.Stop();
if (value > 0 && value != CurrentScale)
{
_autoApplyTimer.Start();
}
}
}
}
}