Compare commits
3 Commits
326c615887
...
061007158d
Author | SHA1 | Date |
---|---|---|
|
061007158d | |
|
0a52c543e6 | |
|
38ca212d9f |
|
@ -10,11 +10,11 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<Optimize>False</Optimize>
|
<Optimize>True</Optimize>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
<Optimize>False</Optimize>
|
<Optimize>True</Optimize>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -30,14 +30,11 @@ namespace CtrEditor
|
||||||
|
|
||||||
public string? ObtenerPathAllPages(string extension)
|
public string? ObtenerPathAllPages(string extension)
|
||||||
{
|
{
|
||||||
string folderPath = EstadoPersistente.Instance.directorio; // Usar directamente desde el Singleton
|
if (!string.IsNullOrEmpty(EstadoPersistente.Instance.directorio))
|
||||||
|
return Path.Combine(EstadoPersistente.Instance.directorio, "AllPages" + extension);
|
||||||
if (Directory.Exists(folderPath))
|
return null;
|
||||||
return Path.ChangeExtension(folderPath + "\\allpages", extension);
|
|
||||||
else return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void CargarImagenes()
|
public void CargarImagenes()
|
||||||
{
|
{
|
||||||
Imagenes.Clear();
|
Imagenes.Clear();
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace CtrEditor.FuncionesBase
|
||||||
{ "Siemens IO Input", "Format: Exxxxx.y (x: 0-65535, y: 0-7)" },
|
{ "Siemens IO Input", "Format: Exxxxx.y (x: 0-65535, y: 0-7)" },
|
||||||
{ "Siemens IO Output", "Format: Axxxxx.y (x: 0-65535, y: 0-7)" },
|
{ "Siemens IO Output", "Format: Axxxxx.y (x: 0-65535, y: 0-7)" },
|
||||||
{ "LETRASNUMEROS", "Format: ABC...123... (1-10 letters + numbers)" },
|
{ "LETRASNUMEROS", "Format: ABC...123... (1-10 letters + numbers)" },
|
||||||
|
{ "LETRASNUMEROSESPACIOS", "Format: ABC...123... (letters, numbers and spaces allowed)" },
|
||||||
{ "Numero", "Numeric value" }
|
{ "Numero", "Numeric value" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ namespace CtrEditor.FuncionesBase
|
||||||
"Siemens IO Input" => ApplySiemensPattern(text, "E"),
|
"Siemens IO Input" => ApplySiemensPattern(text, "E"),
|
||||||
"Siemens IO Output" => ApplySiemensPattern(text, "A"),
|
"Siemens IO Output" => ApplySiemensPattern(text, "A"),
|
||||||
"LETRASNUMEROS" => ApplyLetrasNumerosPattern(text),
|
"LETRASNUMEROS" => ApplyLetrasNumerosPattern(text),
|
||||||
|
"LETRASNUMEROSESPACIOS" => ApplyLetrasNumerosEspaciosPattern(text),
|
||||||
"Numero" => ApplyNumberPattern(text),
|
"Numero" => ApplyNumberPattern(text),
|
||||||
_ => text
|
_ => text
|
||||||
};
|
};
|
||||||
|
@ -77,6 +79,15 @@ namespace CtrEditor.FuncionesBase
|
||||||
return $"{letters.ToUpper()}{numbers}";
|
return $"{letters.ToUpper()}{numbers}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string ApplyLetrasNumerosEspaciosPattern(string text)
|
||||||
|
{
|
||||||
|
// Keep only letters, numbers and spaces
|
||||||
|
var cleanedText = new string(text.Where(c => char.IsLetterOrDigit(c) || char.IsWhiteSpace(c)).ToArray());
|
||||||
|
|
||||||
|
// Convert to uppercase
|
||||||
|
return cleanedText.ToUpper();
|
||||||
|
}
|
||||||
|
|
||||||
private static string ApplyNumberPattern(string text)
|
private static string ApplyNumberPattern(string text)
|
||||||
{
|
{
|
||||||
var match = Regex.Match(text, @"-?\d+\.?\d*");
|
var match = Regex.Match(text, @"-?\d+\.?\d*");
|
||||||
|
|
153
MainViewModel.cs
153
MainViewModel.cs
|
@ -21,13 +21,14 @@ using System.Windows.Data;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using CtrEditor.Serialization; // Add this line
|
||||||
|
|
||||||
namespace CtrEditor
|
namespace CtrEditor
|
||||||
{
|
{
|
||||||
|
|
||||||
public partial class MainViewModel : ObservableObject
|
public partial class MainViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
|
private readonly StateSerializer _stateSerializer;
|
||||||
public Stopwatch stopwatch_Sim;
|
public Stopwatch stopwatch_Sim;
|
||||||
|
|
||||||
private double stopwatch_SimPLC_last;
|
private double stopwatch_SimPLC_last;
|
||||||
|
@ -367,6 +368,7 @@ namespace CtrEditor
|
||||||
OpenRecentDirectoryCommand = new RelayCommand<string>(OpenRecentDirectory);
|
OpenRecentDirectoryCommand = new RelayCommand<string>(OpenRecentDirectory);
|
||||||
|
|
||||||
_stateManager = new StateManager(EstadoPersistente.Instance.directorio, this);
|
_stateManager = new StateManager(EstadoPersistente.Instance.directorio, this);
|
||||||
|
_stateSerializer = new StateSerializer(this, datosDeTrabajo, simulationManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OsListFilter_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
private void OsListFilter_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
|
@ -425,7 +427,7 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear UserControl desde osBase : Nuevo o desde Deserealizacion
|
// Crear UserControl desde osBase : Nuevo o desde Deserealizacion
|
||||||
private bool CrearUserControlDesdeObjetoSimulable(osBase osObjeto)
|
public bool CrearUserControlDesdeObjetoSimulable(osBase osObjeto)
|
||||||
{
|
{
|
||||||
Type tipoObjeto = osObjeto.GetType();
|
Type tipoObjeto = osObjeto.GetType();
|
||||||
|
|
||||||
|
@ -513,25 +515,9 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void EliminarObjetoSeleccionado()
|
|
||||||
{
|
|
||||||
if (SelectedItemOsList is osBase objEliminar)
|
|
||||||
{
|
|
||||||
var result = MessageBox.Show($"¿Está seguro que desea eliminar el objeto '{objEliminar.Nombre}'?",
|
|
||||||
"Confirmar eliminación",
|
|
||||||
MessageBoxButton.YesNo,
|
|
||||||
MessageBoxImage.Question);
|
|
||||||
|
|
||||||
if (result == MessageBoxResult.Yes)
|
|
||||||
{
|
|
||||||
RemoverObjetoSimulable(objEliminar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EliminarUserControl()
|
private void EliminarUserControl()
|
||||||
{
|
{
|
||||||
EliminarObjetoSeleccionado();
|
_objectManager.EliminarObjetosSeleccionados();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -661,7 +647,7 @@ namespace CtrEditor
|
||||||
simulationManager.Start();
|
simulationManager.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StopSimulation()
|
public void StopSimulation()
|
||||||
{
|
{
|
||||||
IsSimulationRunning = false;
|
IsSimulationRunning = false;
|
||||||
|
|
||||||
|
@ -717,7 +703,7 @@ namespace CtrEditor
|
||||||
objetoSimulable.SetPLC(PLCViewModel);
|
objetoSimulable.SetPLC(PLCViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisconnectPLC()
|
public void DisconnectPLC()
|
||||||
{
|
{
|
||||||
PLCViewModel.Disconnect();
|
PLCViewModel.Disconnect();
|
||||||
_timerPLCUpdate.Stop();
|
_timerPLCUpdate.Stop();
|
||||||
|
@ -822,140 +808,19 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (SelectedImage != null)
|
if (SelectedImage != null)
|
||||||
{
|
{
|
||||||
StopSimulation();
|
_stateSerializer.SaveState(SelectedImage);
|
||||||
DisconnectPLC();
|
|
||||||
|
|
||||||
ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>();
|
|
||||||
ObservableCollection<osBase> _objetosSimulablesAllPages = new ObservableCollection<osBase>();
|
|
||||||
|
|
||||||
foreach (var obj in ObjetosSimulables)
|
|
||||||
{
|
|
||||||
// Guardar referencias temporales
|
|
||||||
obj.SalvarDatosNoSerializables();
|
|
||||||
if (!obj.Enable_On_All_Pages)
|
|
||||||
_objetosSimulables.Add(obj);
|
|
||||||
else
|
|
||||||
_objetosSimulablesAllPages.Add(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Salvar los objetos de la pagina actual
|
|
||||||
|
|
||||||
// Crear un objeto que incluya tanto los ObjetosSimulables como el UnitConverter y PLC_ConnectionData
|
|
||||||
var dataToSerialize = new SimulationData
|
|
||||||
{
|
|
||||||
ObjetosSimulables = _objetosSimulables,
|
|
||||||
UnitConverter = PixelToMeter.Instance.calc,
|
|
||||||
PLC_ConnectionData = PLCViewModel
|
|
||||||
};
|
|
||||||
|
|
||||||
// Ruta del archivo a ser guardado
|
|
||||||
var path = DatosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json");
|
|
||||||
if (path != null)
|
|
||||||
SerializarYSalvar(dataToSerialize, path);
|
|
||||||
|
|
||||||
// Salvar los objetos de todas las paginas
|
|
||||||
|
|
||||||
// Ruta del archivo a ser guardado
|
|
||||||
path = DatosDeTrabajo.ObtenerPathAllPages(".json");
|
|
||||||
if (path != null)
|
|
||||||
SerializarYSalvar(_objetosSimulablesAllPages, path);
|
|
||||||
|
|
||||||
// Restaurar las propiedades originales de los objetos
|
|
||||||
foreach (var obj in ObjetosSimulables)
|
|
||||||
obj.RestaurarDatosNoSerializables();
|
|
||||||
|
|
||||||
HasUnsavedChanges = false;
|
HasUnsavedChanges = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SerializarYSalvar(object listaObjetos, string path)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Verificar si el archivo ya existe y crear un respaldo
|
|
||||||
if (File.Exists(path))
|
|
||||||
{
|
|
||||||
var backupPath = Path.ChangeExtension(path, ".bak");
|
|
||||||
File.Copy(path, backupPath, true); // Copia el archivo existente a un nuevo archivo .bak, sobrescribiendo si es necesario
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var settings = new JsonSerializerSettings
|
|
||||||
{
|
|
||||||
Formatting = Formatting.Indented,
|
|
||||||
// PreserveReferencesHandling = PreserveReferencesHandling.Objects,
|
|
||||||
NullValueHandling = NullValueHandling.Ignore,
|
|
||||||
TypeNameHandling = TypeNameHandling.Auto
|
|
||||||
};
|
|
||||||
|
|
||||||
// Serializar
|
|
||||||
var serializedData = JsonConvert.SerializeObject(listaObjetos, settings);
|
|
||||||
File.WriteAllText(path, serializedData); // Escribir el nuevo archivo JSON
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadStateObjetosSimulables()
|
public void LoadStateObjetosSimulables()
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
StopSimulation();
|
|
||||||
DisconnectPLC();
|
|
||||||
ObjetosSimulables.Clear();
|
|
||||||
simulationManager.Clear();
|
|
||||||
if (SelectedImage != null)
|
if (SelectedImage != null)
|
||||||
{
|
{
|
||||||
var settings = new JsonSerializerSettings
|
_stateSerializer.LoadState(SelectedImage);
|
||||||
{
|
|
||||||
TypeNameHandling = TypeNameHandling.Auto,
|
|
||||||
ObjectCreationHandling = ObjectCreationHandling.Replace,
|
|
||||||
// PreserveReferencesHandling = PreserveReferencesHandling.Objects,
|
|
||||||
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
|
|
||||||
};
|
|
||||||
|
|
||||||
string jsonPath = datosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json");
|
|
||||||
if (File.Exists(jsonPath))
|
|
||||||
{
|
|
||||||
string jsonString = File.ReadAllText(jsonPath);
|
|
||||||
|
|
||||||
|
|
||||||
var simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings);
|
|
||||||
if (simulationData != null)
|
|
||||||
{
|
|
||||||
if (simulationData.ObjetosSimulables is not null)
|
|
||||||
ObjetosSimulables = simulationData.ObjetosSimulables;
|
|
||||||
|
|
||||||
if (simulationData.PLC_ConnectionData is not null)
|
|
||||||
PLCViewModel = simulationData.PLC_ConnectionData;
|
|
||||||
else
|
|
||||||
PLCViewModel = new PLCViewModel();
|
|
||||||
|
|
||||||
PixelToMeter.Instance.calc = simulationData.UnitConverter;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonPath = DatosDeTrabajo.ObtenerPathAllPages(".json");
|
|
||||||
if (File.Exists(jsonPath))
|
|
||||||
{
|
|
||||||
string jsonString = File.ReadAllText(jsonPath);
|
|
||||||
|
|
||||||
ObservableCollection<osBase> _objetosSimulablesAllPages = new ObservableCollection<osBase>();
|
|
||||||
|
|
||||||
_objetosSimulablesAllPages = JsonConvert.DeserializeObject<ObservableCollection<osBase>>(jsonString, settings);
|
|
||||||
if (_objetosSimulablesAllPages != null)
|
|
||||||
foreach (var obj in _objetosSimulablesAllPages)
|
|
||||||
ObjetosSimulables.Add(obj);
|
|
||||||
}
|
|
||||||
// Recorrer la colección de objetos simulables
|
|
||||||
foreach (var objetoSimulable in ObjetosSimulables)
|
|
||||||
if (objetoSimulable != null)
|
|
||||||
{
|
|
||||||
objetoSimulable.CheckData();
|
|
||||||
CrearUserControlDesdeObjetoSimulable(objetoSimulable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { /* Consider logging the error or handling it appropriately */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se cargan los datos de cada UserControl en el StackPanel
|
// Se cargan los datos de cada UserControl en el StackPanel
|
||||||
public void CargarPropiedadesosDatos(osBase selectedObject, PropertyGrid PanelEdicion, ResourceDictionary Resources)
|
public void CargarPropiedadesosDatos(osBase selectedObject, PropertyGrid PanelEdicion, ResourceDictionary Resources)
|
||||||
{
|
{
|
||||||
|
|
|
@ -153,9 +153,17 @@
|
||||||
</ToolBar>
|
</ToolBar>
|
||||||
</ToolBarTray>
|
</ToolBarTray>
|
||||||
|
|
||||||
<ScrollViewer Grid.Row="1" x:Name="ImagenEnTrabajoScrollViewer" HorizontalScrollBarVisibility="Auto"
|
<ScrollViewer Grid.Row="1" x:Name="ImagenEnTrabajoScrollViewer"
|
||||||
VerticalScrollBarVisibility="Auto" PanningMode="Both">
|
HorizontalScrollBarVisibility="Auto"
|
||||||
<Canvas x:Name="ImagenEnTrabajoCanvas" Margin="0" Background="Transparent">
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
PanningMode="Both"
|
||||||
|
PreviewKeyDown="ScrollViewer_PreviewKeyDown">
|
||||||
|
<Canvas x:Name="ImagenEnTrabajoCanvas"
|
||||||
|
Margin="0"
|
||||||
|
Background="Transparent"
|
||||||
|
Focusable="True"
|
||||||
|
FocusVisualStyle="{x:Null}"
|
||||||
|
KeyDown="Canvas_KeyDown">
|
||||||
<!-- Agregar Background="Transparent" para que capture los eventos del mouse y -->
|
<!-- Agregar Background="Transparent" para que capture los eventos del mouse y -->
|
||||||
<!-- asegurar que el Canvas reciba los eventos del botón derecho -->
|
<!-- asegurar que el Canvas reciba los eventos del botón derecho -->
|
||||||
<Canvas.RenderTransform>
|
<Canvas.RenderTransform>
|
||||||
|
@ -248,8 +256,12 @@
|
||||||
ResizeDirection="Rows" VerticalAlignment="Center" />
|
ResizeDirection="Rows" VerticalAlignment="Center" />
|
||||||
|
|
||||||
<!-- PanelEdicion -->
|
<!-- PanelEdicion -->
|
||||||
<xctk:PropertyGrid Grid.Row="4" Margin="5" x:Name="PanelEdicion" AutoGenerateProperties="False"
|
<xctk:PropertyGrid Grid.Row="4"
|
||||||
ShowDescriptionByTooltip="True">
|
Margin="5"
|
||||||
|
x:Name="PanelEdicion"
|
||||||
|
AutoGenerateProperties="False"
|
||||||
|
ShowDescriptionByTooltip="True"
|
||||||
|
FocusManager.IsFocusScope="True">
|
||||||
<xctk:PropertyGrid.EditorDefinitions>
|
<xctk:PropertyGrid.EditorDefinitions>
|
||||||
|
|
||||||
<!-- String -->
|
<!-- String -->
|
||||||
|
|
|
@ -151,6 +151,7 @@ namespace CtrEditor
|
||||||
// y no en otros controles
|
// y no en otros controles
|
||||||
if (e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo)
|
if (e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo)
|
||||||
{
|
{
|
||||||
|
ImagenEnTrabajoCanvas.Focus(); // Asegurar que el canvas tiene el foco
|
||||||
_isDraggingCanvas = true;
|
_isDraggingCanvas = true;
|
||||||
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
||||||
ImagenEnTrabajoCanvas.CaptureMouse();
|
ImagenEnTrabajoCanvas.CaptureMouse();
|
||||||
|
@ -259,6 +260,7 @@ namespace CtrEditor
|
||||||
|
|
||||||
private void ListaOs_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
private void ListaOs_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
|
ImagenEnTrabajoCanvas.Focus(); // Asegurar que el canvas tiene el foco
|
||||||
UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion);
|
UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion);
|
||||||
|
|
||||||
if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject)
|
if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject)
|
||||||
|
@ -285,25 +287,73 @@ namespace CtrEditor
|
||||||
|
|
||||||
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
|
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
|
// Only force canvas focus if PanelEdicion doesn't have focus
|
||||||
|
if (!PanelEdicion.IsKeyboardFocusWithin)
|
||||||
|
{
|
||||||
|
if (!ImagenEnTrabajoCanvas.IsFocused)
|
||||||
|
{
|
||||||
|
ImagenEnTrabajoCanvas.Focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (DataContext is MainViewModel viewModel)
|
if (DataContext is MainViewModel viewModel)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.Delete)
|
if (e.Key == Key.Delete)
|
||||||
{
|
{
|
||||||
viewModel.EliminarObjetoSeleccionado();
|
_objectManager.EliminarObjetosSeleccionados();
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
else if (e.Key == Key.Escape)
|
else if (e.Key == Key.Escape)
|
||||||
{
|
{
|
||||||
// Limpiar la selección en el ListBox
|
|
||||||
viewModel.SelectedItemOsList = null;
|
viewModel.SelectedItemOsList = null;
|
||||||
|
|
||||||
// Limpiar la selección múltiple
|
|
||||||
_objectManager.ClearSelection();
|
_objectManager.ClearSelection();
|
||||||
_objectManager.RemoveResizeRectangles();
|
_objectManager.RemoveResizeRectangles();
|
||||||
|
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
else if (_objectManager.SelectedObjects.Any())
|
||||||
|
{
|
||||||
|
const float moveDistance = 0.1f;
|
||||||
|
switch (e.Key)
|
||||||
|
{
|
||||||
|
case Key.Left:
|
||||||
|
MoveSelectedObjects(-moveDistance, 0);
|
||||||
|
e.Handled = true;
|
||||||
|
break;
|
||||||
|
case Key.Right:
|
||||||
|
MoveSelectedObjects(moveDistance, 0);
|
||||||
|
e.Handled = true;
|
||||||
|
break;
|
||||||
|
case Key.Up:
|
||||||
|
MoveSelectedObjects(0, -moveDistance);
|
||||||
|
e.Handled = true;
|
||||||
|
break;
|
||||||
|
case Key.Down:
|
||||||
|
MoveSelectedObjects(0, moveDistance);
|
||||||
|
e.Handled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MoveSelectedObjects(float deltaX, float deltaY)
|
||||||
|
{
|
||||||
|
// Mover todos los objetos primero
|
||||||
|
foreach (var obj in _objectManager.SelectedObjects)
|
||||||
|
{
|
||||||
|
obj.Left += deltaX;
|
||||||
|
obj.Top += deltaY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Forzar una actualización del layout antes de actualizar los visuales
|
||||||
|
ImagenEnTrabajoCanvas.UpdateLayout();
|
||||||
|
|
||||||
|
// Ahora actualizar los visuales de selección
|
||||||
|
_objectManager.UpdateSelectionVisuals();
|
||||||
|
|
||||||
|
if (DataContext is MainViewModel viewModel)
|
||||||
|
{
|
||||||
|
viewModel.HasUnsavedChanges = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,6 +427,7 @@ namespace CtrEditor
|
||||||
if ((e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo || e.Source is UserControl) &&
|
if ((e.Source == ImagenEnTrabajoCanvas || e.Source == imagenDeFondo || e.Source is UserControl) &&
|
||||||
DataContext is MainViewModel viewModel)
|
DataContext is MainViewModel viewModel)
|
||||||
{
|
{
|
||||||
|
ImagenEnTrabajoCanvas.Focus(); // Asegurar que el canvas tiene el foco
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
ShowContextMenu(e.GetPosition(ImagenEnTrabajoCanvas));
|
ShowContextMenu(e.GetPosition(ImagenEnTrabajoCanvas));
|
||||||
}
|
}
|
||||||
|
@ -440,6 +491,68 @@ namespace CtrEditor
|
||||||
contextMenu.IsOpen = true;
|
contextMenu.IsOpen = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Canvas_KeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
// Only handle if PanelEdicion doesn't have focus
|
||||||
|
if (!PanelEdicion.IsKeyboardFocusWithin)
|
||||||
|
{
|
||||||
|
HandleKeyDown(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ScrollViewer_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
// Only handle if PanelEdicion doesn't have focus
|
||||||
|
if (!PanelEdicion.IsKeyboardFocusWithin &&
|
||||||
|
(e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Up || e.Key == Key.Down))
|
||||||
|
{
|
||||||
|
HandleKeyDown(e);
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleKeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataContext is MainViewModel viewModel)
|
||||||
|
{
|
||||||
|
if (e.Key == Key.Delete)
|
||||||
|
{
|
||||||
|
_objectManager.EliminarObjetosSeleccionados(); // Cambiar aquí
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
else if (e.Key == Key.Escape)
|
||||||
|
{
|
||||||
|
viewModel.SelectedItemOsList = null;
|
||||||
|
_objectManager.ClearSelection();
|
||||||
|
_objectManager.RemoveResizeRectangles();
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
else if (_objectManager.SelectedObjects.Any())
|
||||||
|
{
|
||||||
|
const float moveDistance = 0.01f;
|
||||||
|
switch (e.Key)
|
||||||
|
{
|
||||||
|
case Key.Left:
|
||||||
|
MoveSelectedObjects(-moveDistance, 0);
|
||||||
|
e.Handled = true;
|
||||||
|
break;
|
||||||
|
case Key.Right:
|
||||||
|
MoveSelectedObjects(moveDistance, 0);
|
||||||
|
e.Handled = true;
|
||||||
|
break;
|
||||||
|
case Key.Up:
|
||||||
|
MoveSelectedObjects(0, -moveDistance);
|
||||||
|
e.Handled = true;
|
||||||
|
break;
|
||||||
|
case Key.Down:
|
||||||
|
MoveSelectedObjects(0, moveDistance);
|
||||||
|
e.Handled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FloatValidationRule : ValidationRule
|
public class FloatValidationRule : ValidationRule
|
||||||
|
|
|
@ -7,10 +7,12 @@ namespace CtrEditor
|
||||||
public class ObjectAlignment
|
public class ObjectAlignment
|
||||||
{
|
{
|
||||||
private readonly ObservableCollection<osBase> _selectedObjects;
|
private readonly ObservableCollection<osBase> _selectedObjects;
|
||||||
|
private readonly osBase _referenceObject;
|
||||||
|
|
||||||
public ObjectAlignment(ObservableCollection<osBase> selectedObjects)
|
public ObjectAlignment(ObservableCollection<osBase> selectedObjects, osBase referenceObject = null)
|
||||||
{
|
{
|
||||||
_selectedObjects = selectedObjects;
|
_selectedObjects = selectedObjects;
|
||||||
|
_referenceObject = referenceObject ?? selectedObjects.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AlignLeft()
|
public void AlignLeft()
|
||||||
|
@ -83,31 +85,27 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (_selectedObjects.Count <= 2) return;
|
if (_selectedObjects.Count <= 2) return;
|
||||||
|
|
||||||
// Ordenar objetos por su centro X real (considerando rotación)
|
|
||||||
var objectsWithCenters = _selectedObjects
|
var objectsWithCenters = _selectedObjects
|
||||||
.Select(obj => new
|
.Select(obj => new
|
||||||
{
|
{
|
||||||
Object = obj,
|
Object = obj,
|
||||||
Center = GetObjectCenter(obj)
|
Center = GetObjectCenter(obj),
|
||||||
|
Dimensions = GetEffectiveDimensions(obj)
|
||||||
})
|
})
|
||||||
.OrderBy(x => x.Center.X)
|
.OrderBy(x => x.Center.X)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Calcular el espacio total y el espaciado
|
|
||||||
float leftMost = (float)objectsWithCenters.First().Center.X;
|
float leftMost = (float)objectsWithCenters.First().Center.X;
|
||||||
float rightMost = (float)objectsWithCenters.Last().Center.X;
|
float rightMost = (float)objectsWithCenters.Last().Center.X;
|
||||||
float totalWidth = rightMost - leftMost;
|
float totalDistance = rightMost - leftMost;
|
||||||
float spacing = totalWidth / (_selectedObjects.Count - 1);
|
float spacing = totalDistance / (_selectedObjects.Count - 1);
|
||||||
|
|
||||||
// Distribuir objetos basados en sus centros
|
|
||||||
for (int i = 1; i < objectsWithCenters.Count - 1; i++)
|
for (int i = 1; i < objectsWithCenters.Count - 1; i++)
|
||||||
{
|
{
|
||||||
var obj = objectsWithCenters[i].Object;
|
var obj = objectsWithCenters[i];
|
||||||
var targetCenterX = leftMost + (spacing * i);
|
var targetX = leftMost + (spacing * i);
|
||||||
var currentCenter = GetObjectCenter(obj);
|
float deltaX = (float)(targetX - obj.Center.X);
|
||||||
var deltaX = targetCenterX - currentCenter.X;
|
obj.Object.Left += deltaX;
|
||||||
|
|
||||||
obj.Left += (float)deltaX;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,31 +113,27 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (_selectedObjects.Count <= 2) return;
|
if (_selectedObjects.Count <= 2) return;
|
||||||
|
|
||||||
// Ordenar objetos por su centro Y real (considerando rotación)
|
|
||||||
var objectsWithCenters = _selectedObjects
|
var objectsWithCenters = _selectedObjects
|
||||||
.Select(obj => new
|
.Select(obj => new
|
||||||
{
|
{
|
||||||
Object = obj,
|
Object = obj,
|
||||||
Center = GetObjectCenter(obj)
|
Center = GetObjectCenter(obj),
|
||||||
|
Dimensions = GetEffectiveDimensions(obj)
|
||||||
})
|
})
|
||||||
.OrderBy(x => x.Center.Y)
|
.OrderBy(x => x.Center.Y)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Calcular el espacio total y el espaciado
|
|
||||||
float topMost = (float)objectsWithCenters.First().Center.Y;
|
float topMost = (float)objectsWithCenters.First().Center.Y;
|
||||||
float bottomMost = (float)objectsWithCenters.Last().Center.Y;
|
float bottomMost = (float)objectsWithCenters.Last().Center.Y;
|
||||||
float totalHeight = bottomMost - topMost;
|
float totalDistance = bottomMost - topMost;
|
||||||
float spacing = totalHeight / (_selectedObjects.Count - 1);
|
float spacing = totalDistance / (_selectedObjects.Count - 1);
|
||||||
|
|
||||||
// Distribuir objetos basados en sus centros
|
|
||||||
for (int i = 1; i < objectsWithCenters.Count - 1; i++)
|
for (int i = 1; i < objectsWithCenters.Count - 1; i++)
|
||||||
{
|
{
|
||||||
var obj = objectsWithCenters[i].Object;
|
var obj = objectsWithCenters[i];
|
||||||
var targetCenterY = topMost + (spacing * i);
|
var targetY = topMost + (spacing * i);
|
||||||
var currentCenter = GetObjectCenter(obj);
|
float deltaY = (float)(targetY - obj.Center.Y);
|
||||||
var deltaY = targetCenterY - currentCenter.Y;
|
obj.Object.Top += deltaY;
|
||||||
|
|
||||||
obj.Top += (float)deltaY;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,10 +141,11 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (_selectedObjects.Count <= 1) return;
|
if (_selectedObjects.Count <= 1) return;
|
||||||
|
|
||||||
float averageWidth = _selectedObjects.Average(obj => obj.Ancho);
|
float referenceWidth = GetEffectiveDimensions(_referenceObject).Width;
|
||||||
foreach (var obj in _selectedObjects)
|
foreach (var obj in _selectedObjects.Where(o => o != _referenceObject))
|
||||||
{
|
{
|
||||||
obj.Ancho = averageWidth;
|
var currentDims = GetEffectiveDimensions(obj);
|
||||||
|
SetEffectiveDimensions(obj, referenceWidth, currentDims.Height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,10 +153,11 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (_selectedObjects.Count <= 1) return;
|
if (_selectedObjects.Count <= 1) return;
|
||||||
|
|
||||||
float averageHeight = _selectedObjects.Average(obj => obj.Alto);
|
float referenceHeight = GetEffectiveDimensions(_referenceObject).Height;
|
||||||
foreach (var obj in _selectedObjects)
|
foreach (var obj in _selectedObjects.Where(o => o != _referenceObject))
|
||||||
{
|
{
|
||||||
obj.Alto = averageHeight;
|
var currentDims = GetEffectiveDimensions(obj);
|
||||||
|
SetEffectiveDimensions(obj, currentDims.Width, referenceHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,8 +165,8 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
if (_selectedObjects.Count <= 1) return;
|
if (_selectedObjects.Count <= 1) return;
|
||||||
|
|
||||||
float referenceAngle = _selectedObjects.First().Angulo;
|
float referenceAngle = _referenceObject.Angulo;
|
||||||
foreach (var obj in _selectedObjects)
|
foreach (var obj in _selectedObjects.Where(o => o != _referenceObject))
|
||||||
{
|
{
|
||||||
obj.Angulo = referenceAngle;
|
obj.Angulo = referenceAngle;
|
||||||
}
|
}
|
||||||
|
@ -181,14 +177,21 @@ namespace CtrEditor
|
||||||
if (_selectedObjects.Count <= 1) return;
|
if (_selectedObjects.Count <= 1) return;
|
||||||
|
|
||||||
var sortedObjects = _selectedObjects
|
var sortedObjects = _selectedObjects
|
||||||
.OrderBy(obj => obj.Left)
|
.OrderBy(obj => GetObjectCenter(obj).X)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
for (int i = 1; i < sortedObjects.Count; i++)
|
for (int i = 1; i < sortedObjects.Count; i++)
|
||||||
{
|
{
|
||||||
var previousObj = sortedObjects[i - 1];
|
var previousObj = sortedObjects[i - 1];
|
||||||
var currentObj = sortedObjects[i];
|
var currentObj = sortedObjects[i];
|
||||||
currentObj.Left = previousObj.Left + previousObj.Ancho;
|
var previousCenter = GetObjectCenter(previousObj);
|
||||||
|
var currentCenter = GetObjectCenter(currentObj);
|
||||||
|
var previousDims = GetEffectiveDimensions(previousObj);
|
||||||
|
|
||||||
|
float offset = previousDims.Width / 2;
|
||||||
|
float newX = (float)(previousCenter.X + offset);
|
||||||
|
float deltaX = (float)(newX - (currentCenter.X - GetEffectiveDimensions(currentObj).Width / 2));
|
||||||
|
currentObj.Left += deltaX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,14 +200,21 @@ namespace CtrEditor
|
||||||
if (_selectedObjects.Count <= 1) return;
|
if (_selectedObjects.Count <= 1) return;
|
||||||
|
|
||||||
var sortedObjects = _selectedObjects
|
var sortedObjects = _selectedObjects
|
||||||
.OrderBy(obj => obj.Top)
|
.OrderBy(obj => GetObjectCenter(obj).Y)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
for (int i = 1; i < sortedObjects.Count; i++)
|
for (int i = 1; i < sortedObjects.Count; i++)
|
||||||
{
|
{
|
||||||
var previousObj = sortedObjects[i - 1];
|
var previousObj = sortedObjects[i - 1];
|
||||||
var currentObj = sortedObjects[i];
|
var currentObj = sortedObjects[i];
|
||||||
currentObj.Top = previousObj.Top + previousObj.Alto;
|
var previousCenter = GetObjectCenter(previousObj);
|
||||||
|
var currentCenter = GetObjectCenter(currentObj);
|
||||||
|
var previousDims = GetEffectiveDimensions(previousObj);
|
||||||
|
|
||||||
|
float offset = previousDims.Height / 2;
|
||||||
|
float newY = (float)(previousCenter.Y + offset);
|
||||||
|
float deltaY = (float)(newY - (currentCenter.Y - GetEffectiveDimensions(currentObj).Height / 2));
|
||||||
|
currentObj.Top += deltaY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,10 +224,8 @@ namespace CtrEditor
|
||||||
float centerX = obj.Left + (obj.Ancho / 2);
|
float centerX = obj.Left + (obj.Ancho / 2);
|
||||||
float centerY = obj.Top + (obj.Alto / 2);
|
float centerY = obj.Top + (obj.Alto / 2);
|
||||||
|
|
||||||
// Si el objeto está rotado, calcular el centro real
|
|
||||||
if (obj.Angulo != 0)
|
if (obj.Angulo != 0)
|
||||||
{
|
{
|
||||||
// Obtener el centro después de la rotación
|
|
||||||
var rotatedX = obj.Left + (Math.Cos(angleRad) * obj.Ancho / 2 - Math.Sin(angleRad) * obj.Alto / 2);
|
var rotatedX = obj.Left + (Math.Cos(angleRad) * obj.Ancho / 2 - Math.Sin(angleRad) * obj.Alto / 2);
|
||||||
var rotatedY = obj.Top + (Math.Sin(angleRad) * obj.Ancho / 2 + Math.Cos(angleRad) * obj.Alto / 2);
|
var rotatedY = obj.Top + (Math.Sin(angleRad) * obj.Ancho / 2 + Math.Cos(angleRad) * obj.Alto / 2);
|
||||||
|
|
||||||
|
@ -226,5 +234,35 @@ namespace CtrEditor
|
||||||
|
|
||||||
return new Point(centerX, centerY);
|
return new Point(centerX, centerY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsObjectVertical(osBase obj)
|
||||||
|
{
|
||||||
|
double normalizedAngle = obj.Angulo % 180;
|
||||||
|
if (normalizedAngle < 0) normalizedAngle += 180;
|
||||||
|
return normalizedAngle >= 45 && normalizedAngle < 135;
|
||||||
|
}
|
||||||
|
|
||||||
|
private (float Width, float Height) GetEffectiveDimensions(osBase obj)
|
||||||
|
{
|
||||||
|
if (IsObjectVertical(obj))
|
||||||
|
{
|
||||||
|
return (obj.Alto, obj.Ancho);
|
||||||
|
}
|
||||||
|
return (obj.Ancho, obj.Alto);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetEffectiveDimensions(osBase obj, float width, float height)
|
||||||
|
{
|
||||||
|
if (IsObjectVertical(obj))
|
||||||
|
{
|
||||||
|
obj.Alto = width;
|
||||||
|
obj.Ancho = height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obj.Ancho = width;
|
||||||
|
obj.Alto = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,9 +75,25 @@ namespace CtrEditor
|
||||||
_canvas = canvas;
|
_canvas = canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PurgeDeletedObjects()
|
||||||
|
{
|
||||||
|
var deletedObjects = _selectedObjects.Where(obj =>
|
||||||
|
obj.VisualRepresentation == null ||
|
||||||
|
!_canvas.Children.Contains(obj.VisualRepresentation)).ToList();
|
||||||
|
|
||||||
|
foreach (var obj in deletedObjects)
|
||||||
|
{
|
||||||
|
DeselectObject(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ObservableCollection<osBase> SelectedObjects
|
public ObservableCollection<osBase> SelectedObjects
|
||||||
{
|
{
|
||||||
get => _selectedObjects;
|
get
|
||||||
|
{
|
||||||
|
PurgeDeletedObjects();
|
||||||
|
return _selectedObjects;
|
||||||
|
}
|
||||||
private set
|
private set
|
||||||
{
|
{
|
||||||
_selectedObjects = value;
|
_selectedObjects = value;
|
||||||
|
@ -87,10 +103,15 @@ namespace CtrEditor
|
||||||
|
|
||||||
public void UpdateSelectionVisuals()
|
public void UpdateSelectionVisuals()
|
||||||
{
|
{
|
||||||
|
PurgeDeletedObjects();
|
||||||
|
// Asegurarse de que el canvas haya actualizado su layout
|
||||||
|
_canvas.UpdateLayout();
|
||||||
|
|
||||||
RemoveResizeRectangles();
|
RemoveResizeRectangles();
|
||||||
if (_selectedObjects.Any())
|
if (_selectedObjects.Any())
|
||||||
{
|
{
|
||||||
AddResizeRectangles(_selectedObjects);
|
AddResizeRectangles(_selectedObjects);
|
||||||
|
UpdateSelectionHighlights();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,6 +325,7 @@ namespace CtrEditor
|
||||||
|
|
||||||
private void HandleObjectSelection(UserControl userControl, osBase datos)
|
private void HandleObjectSelection(UserControl userControl, osBase datos)
|
||||||
{
|
{
|
||||||
|
PurgeDeletedObjects();
|
||||||
var viewModel = _mainWindow.DataContext as MainViewModel;
|
var viewModel = _mainWindow.DataContext as MainViewModel;
|
||||||
if (viewModel == null) return;
|
if (viewModel == null) return;
|
||||||
|
|
||||||
|
@ -389,22 +411,14 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Agregar destacados de selección para los objetos ya seleccionados
|
UpdateAllSelectionHighlights();
|
||||||
foreach (var obj in _selectedObjects)
|
|
||||||
{
|
|
||||||
if (obj.VisualRepresentation != null)
|
|
||||||
{
|
|
||||||
AddSelectionHighlight(obj.VisualRepresentation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddSelectionHighlight(UserControl userControl)
|
private void AddSelectionHighlight(UserControl userControl, bool isReference = false)
|
||||||
{
|
{
|
||||||
if (userControl == null) return;
|
if (userControl == null) return;
|
||||||
|
|
||||||
// Primero remover cualquier highlight existente para este control
|
|
||||||
RemoveSelectionHighlight(userControl);
|
RemoveSelectionHighlight(userControl);
|
||||||
|
|
||||||
Rect boundingBox = VisualTreeHelper.GetDescendantBounds(userControl);
|
Rect boundingBox = VisualTreeHelper.GetDescendantBounds(userControl);
|
||||||
|
@ -416,8 +430,10 @@ namespace CtrEditor
|
||||||
Width = transformedBoundingBox.Width,
|
Width = transformedBoundingBox.Width,
|
||||||
Height = transformedBoundingBox.Height,
|
Height = transformedBoundingBox.Height,
|
||||||
Fill = Brushes.Transparent,
|
Fill = Brushes.Transparent,
|
||||||
Stroke = new SolidColorBrush(Color.FromArgb(180, 255, 0, 0)),
|
Stroke = new SolidColorBrush(isReference ?
|
||||||
StrokeThickness = 2,
|
Color.FromArgb(180, 128, 0, 128) : // Purple for reference
|
||||||
|
Color.FromArgb(180, 255, 0, 0)), // Red for others
|
||||||
|
StrokeThickness = isReference ? 3 : 2, // Más grueso para el de referencia
|
||||||
Tag = "SelectionHighlight",
|
Tag = "SelectionHighlight",
|
||||||
IsHitTestVisible = false
|
IsHitTestVisible = false
|
||||||
};
|
};
|
||||||
|
@ -449,21 +465,28 @@ namespace CtrEditor
|
||||||
_selectionHighlightPairs.Clear();
|
_selectionHighlightPairs.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSelectionHighlights()
|
private void UpdateAllSelectionHighlights()
|
||||||
{
|
{
|
||||||
if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.IsMultiSelectionActive)
|
if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.IsMultiSelectionActive)
|
||||||
{
|
{
|
||||||
RemoveAllSelectionHighlights();
|
RemoveAllSelectionHighlights();
|
||||||
|
bool isFirst = true;
|
||||||
foreach (var selectedObject in _selectedObjects)
|
foreach (var selectedObject in _selectedObjects)
|
||||||
{
|
{
|
||||||
if (selectedObject.VisualRepresentation != null)
|
if (selectedObject.VisualRepresentation != null)
|
||||||
{
|
{
|
||||||
AddSelectionHighlight(selectedObject.VisualRepresentation);
|
AddSelectionHighlight(selectedObject.VisualRepresentation, isFirst);
|
||||||
|
isFirst = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateSelectionHighlights()
|
||||||
|
{
|
||||||
|
UpdateAllSelectionHighlights();
|
||||||
|
}
|
||||||
|
|
||||||
private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
if (!_isDrawingCanvas)
|
if (!_isDrawingCanvas)
|
||||||
|
@ -540,6 +563,7 @@ namespace CtrEditor
|
||||||
|
|
||||||
private void HandleDrag(Point currentPosition)
|
private void HandleDrag(Point currentPosition)
|
||||||
{
|
{
|
||||||
|
PurgeDeletedObjects();
|
||||||
var dx = currentPosition.X - _startPointUserControl.X;
|
var dx = currentPosition.X - _startPointUserControl.X;
|
||||||
var dy = currentPosition.Y - _startPointUserControl.Y;
|
var dy = currentPosition.Y - _startPointUserControl.Y;
|
||||||
|
|
||||||
|
@ -553,7 +577,7 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
_startPointUserControl = currentPosition;
|
_startPointUserControl = currentPosition;
|
||||||
|
|
||||||
UpdateSelectionHighlights();
|
UpdateAllSelectionHighlights();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||||
|
@ -571,6 +595,7 @@ namespace CtrEditor
|
||||||
|
|
||||||
RemoveAllSelectionHighlights(); // Remover antes de actualizar
|
RemoveAllSelectionHighlights(); // Remover antes de actualizar
|
||||||
UpdateSelectionVisuals();
|
UpdateSelectionVisuals();
|
||||||
|
UpdateAllSelectionHighlights();
|
||||||
|
|
||||||
// Restaurar los rectángulos de selección si es necesario
|
// Restaurar los rectángulos de selección si es necesario
|
||||||
if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.IsMultiSelectionActive)
|
if (_mainWindow.DataContext is MainViewModel viewModel && viewModel.IsMultiSelectionActive)
|
||||||
|
@ -689,6 +714,7 @@ namespace CtrEditor
|
||||||
|
|
||||||
private void HandleResize(Point currentPosition, HandleMode mode)
|
private void HandleResize(Point currentPosition, HandleMode mode)
|
||||||
{
|
{
|
||||||
|
PurgeDeletedObjects();
|
||||||
RemoveAllSelectionHighlights(); // Remover antes de redimensionar
|
RemoveAllSelectionHighlights(); // Remover antes de redimensionar
|
||||||
|
|
||||||
foreach (var selectedObject in _selectedObjects)
|
foreach (var selectedObject in _selectedObjects)
|
||||||
|
@ -699,7 +725,7 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
_startPointUserControl = currentPosition;
|
_startPointUserControl = currentPosition;
|
||||||
|
|
||||||
UpdateSelectionHighlights();
|
UpdateAllSelectionHighlights();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleResizeForObject(osBase obj, Point currentPosition, bool activateSizeWidth, bool activateSizeHeight)
|
private void HandleResizeForObject(osBase obj, Point currentPosition, bool activateSizeWidth, bool activateSizeHeight)
|
||||||
|
@ -712,6 +738,7 @@ namespace CtrEditor
|
||||||
|
|
||||||
private void HandleRotation(Point currentPosition)
|
private void HandleRotation(Point currentPosition)
|
||||||
{
|
{
|
||||||
|
PurgeDeletedObjects();
|
||||||
RemoveAllSelectionHighlights(); // Remover antes de rotar
|
RemoveAllSelectionHighlights(); // Remover antes de rotar
|
||||||
|
|
||||||
// Calcular el ángulo respecto al centro del bounding box que contiene todos los objetos seleccionados
|
// Calcular el ángulo respecto al centro del bounding box que contiene todos los objetos seleccionados
|
||||||
|
@ -733,14 +760,15 @@ namespace CtrEditor
|
||||||
_lastAngle = (float)angle;
|
_lastAngle = (float)angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateSelectionHighlights();
|
UpdateAllSelectionHighlights();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AlignObjects(AlignmentType alignmentType)
|
public void AlignObjects(AlignmentType alignmentType)
|
||||||
{
|
{
|
||||||
|
PurgeDeletedObjects();
|
||||||
if (_selectedObjects.Count <= 1) return;
|
if (_selectedObjects.Count <= 1) return;
|
||||||
|
|
||||||
var alignment = new ObjectAlignment(_selectedObjects);
|
var alignment = new ObjectAlignment(_selectedObjects, _selectedObjects.FirstOrDefault());
|
||||||
|
|
||||||
switch (alignmentType)
|
switch (alignmentType)
|
||||||
{
|
{
|
||||||
|
@ -788,5 +816,32 @@ namespace CtrEditor
|
||||||
// Update the selection visuals after alignment
|
// Update the selection visuals after alignment
|
||||||
UpdateSelectionVisuals();
|
UpdateSelectionVisuals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EliminarObjetosSeleccionados()
|
||||||
|
{
|
||||||
|
if (_selectedObjects.Count == 0) return;
|
||||||
|
|
||||||
|
var viewModel = _mainWindow.DataContext as MainViewModel;
|
||||||
|
if (viewModel == null) return;
|
||||||
|
|
||||||
|
// Crear una copia de la lista para evitar modificaciones durante la iteración
|
||||||
|
var objectsToRemove = _selectedObjects.ToList();
|
||||||
|
|
||||||
|
foreach (var obj in objectsToRemove)
|
||||||
|
{
|
||||||
|
viewModel.RemoverObjetoSimulable(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limpiar la selección y actualizar la interfaz
|
||||||
|
ClearSelection();
|
||||||
|
RemoveResizeRectangles();
|
||||||
|
RemoveAllSelectionHighlights();
|
||||||
|
|
||||||
|
// Actualizar el estado de cambios sin guardar
|
||||||
|
if (viewModel != null)
|
||||||
|
{
|
||||||
|
viewModel.HasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
using CtrEditor.ObjetosSim;
|
||||||
|
using LibS7Adv;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Windows;
|
||||||
|
using CtrEditor.Simulacion;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace CtrEditor.Serialization
|
||||||
|
{
|
||||||
|
public class StateSerializer
|
||||||
|
{
|
||||||
|
private readonly DatosDeTrabajo _datosDeTrabajo;
|
||||||
|
private readonly MainViewModel _mainViewModel;
|
||||||
|
private readonly SimulationManagerFP _simulationManager;
|
||||||
|
|
||||||
|
public StateSerializer(MainViewModel mainViewModel, DatosDeTrabajo datosDeTrabajo, SimulationManagerFP simulationManager)
|
||||||
|
{
|
||||||
|
_mainViewModel = mainViewModel;
|
||||||
|
_datosDeTrabajo = datosDeTrabajo;
|
||||||
|
_simulationManager = simulationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveState(string selectedImage)
|
||||||
|
{
|
||||||
|
if (selectedImage != null)
|
||||||
|
{
|
||||||
|
_mainViewModel.StopSimulation();
|
||||||
|
_mainViewModel.DisconnectPLC();
|
||||||
|
|
||||||
|
var objetosSimulables = new ObservableCollection<osBase>();
|
||||||
|
var objetosSimulablesAllPages = new ObservableCollection<osBase>();
|
||||||
|
|
||||||
|
foreach (var obj in _mainViewModel.ObjetosSimulables)
|
||||||
|
{
|
||||||
|
obj.SalvarDatosNoSerializables();
|
||||||
|
if (!obj.Enable_On_All_Pages)
|
||||||
|
objetosSimulables.Add(obj);
|
||||||
|
else
|
||||||
|
objetosSimulablesAllPages.Add(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save current page objects
|
||||||
|
var dataToSerialize = new SimulationData
|
||||||
|
{
|
||||||
|
ObjetosSimulables = objetosSimulables,
|
||||||
|
UnitConverter = PixelToMeter.Instance.calc,
|
||||||
|
PLC_ConnectionData = _mainViewModel.PLCViewModel
|
||||||
|
};
|
||||||
|
|
||||||
|
var path = _datosDeTrabajo.ObtenerPathImagenConExtension(selectedImage, ".json");
|
||||||
|
if (path != null)
|
||||||
|
SerializeAndSave(dataToSerialize, path);
|
||||||
|
|
||||||
|
// Save all pages objects
|
||||||
|
path = _datosDeTrabajo.ObtenerPathAllPages(".json");
|
||||||
|
if (path != null)
|
||||||
|
SerializeAndSave(objetosSimulablesAllPages, path);
|
||||||
|
|
||||||
|
// Restore original properties
|
||||||
|
foreach (var obj in _mainViewModel.ObjetosSimulables)
|
||||||
|
obj.RestaurarDatosNoSerializables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadState(string selectedImage)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_mainViewModel.StopSimulation();
|
||||||
|
_mainViewModel.DisconnectPLC();
|
||||||
|
_mainViewModel.ObjetosSimulables.Clear();
|
||||||
|
_simulationManager.Clear();
|
||||||
|
|
||||||
|
if (selectedImage != null)
|
||||||
|
{
|
||||||
|
var settings = GetJsonSerializerSettings();
|
||||||
|
LoadCurrentPageState(selectedImage, settings);
|
||||||
|
LoadAllPagesState(settings);
|
||||||
|
|
||||||
|
// Create UserControls for all loaded objects
|
||||||
|
foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
|
||||||
|
{
|
||||||
|
if (objetoSimulable != null)
|
||||||
|
{
|
||||||
|
objetoSimulable.CheckData();
|
||||||
|
_mainViewModel.CrearUserControlDesdeObjetoSimulable(objetoSimulable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error loading state: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadCurrentPageState(string selectedImage, JsonSerializerSettings settings)
|
||||||
|
{
|
||||||
|
string jsonPath = _datosDeTrabajo.ObtenerPathImagenConExtension(selectedImage, ".json");
|
||||||
|
if (File.Exists(jsonPath))
|
||||||
|
{
|
||||||
|
string jsonString = File.ReadAllText(jsonPath);
|
||||||
|
var simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings);
|
||||||
|
if (simulationData != null)
|
||||||
|
{
|
||||||
|
if (simulationData.ObjetosSimulables is not null)
|
||||||
|
_mainViewModel.ObjetosSimulables = simulationData.ObjetosSimulables;
|
||||||
|
|
||||||
|
if (simulationData.PLC_ConnectionData is not null)
|
||||||
|
_mainViewModel.PLCViewModel = simulationData.PLC_ConnectionData;
|
||||||
|
else
|
||||||
|
_mainViewModel.PLCViewModel = new PLCViewModel();
|
||||||
|
|
||||||
|
PixelToMeter.Instance.calc = simulationData.UnitConverter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadAllPagesState(JsonSerializerSettings settings)
|
||||||
|
{
|
||||||
|
string jsonPath = _datosDeTrabajo.ObtenerPathAllPages(".json");
|
||||||
|
if (File.Exists(jsonPath))
|
||||||
|
{
|
||||||
|
string jsonString = File.ReadAllText(jsonPath);
|
||||||
|
var objetosSimulablesAllPages = JsonConvert.DeserializeObject<ObservableCollection<osBase>>(jsonString, settings);
|
||||||
|
if (objetosSimulablesAllPages != null)
|
||||||
|
{
|
||||||
|
foreach (var obj in objetosSimulablesAllPages)
|
||||||
|
_mainViewModel.ObjetosSimulables.Add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SerializeAndSave(object objectToSerialize, string path)
|
||||||
|
{
|
||||||
|
// Create backup if file exists
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
var backupPath = Path.ChangeExtension(path, ".bak");
|
||||||
|
File.Copy(path, backupPath, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var settings = GetJsonSerializerSettings();
|
||||||
|
var serializedData = JsonConvert.SerializeObject(objectToSerialize, settings);
|
||||||
|
File.WriteAllText(path, serializedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonSerializerSettings GetJsonSerializerSettings()
|
||||||
|
{
|
||||||
|
return new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
Formatting = Formatting.Indented,
|
||||||
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
|
TypeNameHandling = TypeNameHandling.Auto,
|
||||||
|
ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||||
|
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue