Implementada la funcionalidad de copiar y pegar objetos seleccionados como JSON desde el portapapeles, incluyendo opciones para reemplazar IDs existentes. Se agregó manejo de errores y validación del contenido del portapapeles para asegurar la correcta deserialización de los objetos.
This commit is contained in:
parent
883620b69d
commit
16f5131803
|
@ -11,6 +11,11 @@ using System.Windows.Threading;
|
||||||
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
||||||
using UserControl = System.Windows.Controls.UserControl;
|
using UserControl = System.Windows.Controls.UserControl;
|
||||||
using CtrEditor.Controls; // Add this using statement
|
using CtrEditor.Controls; // Add this using statement
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace CtrEditor
|
namespace CtrEditor
|
||||||
{
|
{
|
||||||
|
@ -646,6 +651,27 @@ namespace CtrEditor
|
||||||
|
|
||||||
contextMenu.Items.Add(new Separator());
|
contextMenu.Items.Add(new Separator());
|
||||||
|
|
||||||
|
// Agregar opción de copiar
|
||||||
|
var copyMenuItem = new MenuItem { Header = "Copiar (Ctrl+C)" };
|
||||||
|
copyMenuItem.Click += (s, e) => CopySelectedObjectsAsJson();
|
||||||
|
contextMenu.Items.Add(copyMenuItem);
|
||||||
|
|
||||||
|
contextMenu.Items.Add(new Separator());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Agregar opciones de pegado
|
||||||
|
if (Clipboard.ContainsText())
|
||||||
|
{
|
||||||
|
var pasteMenuItem = new MenuItem { Header = "Pegar (Ctrl+V)" };
|
||||||
|
pasteMenuItem.Click += (s, e) => PasteObjectsFromJson();
|
||||||
|
contextMenu.Items.Add(pasteMenuItem);
|
||||||
|
|
||||||
|
var pasteReplaceMenuItem = new MenuItem { Header = "Pegar con Reemplazo" };
|
||||||
|
pasteReplaceMenuItem.Click += (s, e) => PasteObjectsFromJson(true);
|
||||||
|
contextMenu.Items.Add(pasteReplaceMenuItem);
|
||||||
|
|
||||||
|
contextMenu.Items.Add(new Separator());
|
||||||
|
|
||||||
// Opciones de bloqueo/desbloqueo
|
// Opciones de bloqueo/desbloqueo
|
||||||
var lockSubmenu = new MenuItem { Header = "Bloqueo" };
|
var lockSubmenu = new MenuItem { Header = "Bloqueo" };
|
||||||
|
|
||||||
|
@ -718,6 +744,16 @@ namespace CtrEditor
|
||||||
_objectManager.RemoveResizeRectangles();
|
_objectManager.RemoveResizeRectangles();
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
else if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.C)
|
||||||
|
{
|
||||||
|
CopySelectedObjectsAsJson();
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
else if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.V)
|
||||||
|
{
|
||||||
|
PasteObjectsFromJson();
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
else if (_objectManager.SelectedObjects.Any())
|
else if (_objectManager.SelectedObjects.Any())
|
||||||
{
|
{
|
||||||
const float moveDistance = 0.01f;
|
const float moveDistance = 0.01f;
|
||||||
|
@ -745,6 +781,199 @@ namespace CtrEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
public Image ImagenDeFondo => imagenDeFondo;
|
public Image ImagenDeFondo => imagenDeFondo;
|
||||||
|
|
||||||
|
private void CopySelectedObjectsAsJson()
|
||||||
|
{
|
||||||
|
if (!_objectManager.SelectedObjects.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var objectsToCopy = new List<osBase>();
|
||||||
|
|
||||||
|
// Preparar objetos para serialización
|
||||||
|
foreach (var obj in _objectManager.SelectedObjects)
|
||||||
|
{
|
||||||
|
obj.SalvarDatosNoSerializables();
|
||||||
|
objectsToCopy.Add(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear configuración de serialización igual a la usada en el guardado
|
||||||
|
var settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
Formatting = Formatting.Indented,
|
||||||
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
|
TypeNameHandling = TypeNameHandling.Auto,
|
||||||
|
ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||||
|
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
|
||||||
|
};
|
||||||
|
|
||||||
|
// Serializar objetos
|
||||||
|
string jsonString = JsonConvert.SerializeObject(objectsToCopy, settings);
|
||||||
|
|
||||||
|
// Copiar al portapapeles
|
||||||
|
Clipboard.SetText(jsonString);
|
||||||
|
|
||||||
|
// Mostrar mensaje de confirmación
|
||||||
|
Console.WriteLine($"Copiados {objectsToCopy.Count} objeto(s) al portapapeles");
|
||||||
|
|
||||||
|
// Restaurar datos no serializables
|
||||||
|
foreach (var obj in _objectManager.SelectedObjects)
|
||||||
|
{
|
||||||
|
obj.RestaurarDatosNoSerializables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error al copiar objetos: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PasteObjectsFromJson(bool replaceExistingIds = false)
|
||||||
|
{
|
||||||
|
if (!Clipboard.ContainsText())
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string jsonString = Clipboard.GetText();
|
||||||
|
|
||||||
|
// Validación básica del JSON
|
||||||
|
if (string.IsNullOrWhiteSpace(jsonString) || (!jsonString.TrimStart().StartsWith("[") && !jsonString.TrimStart().StartsWith("{")))
|
||||||
|
{
|
||||||
|
MessageBox.Show("El contenido del portapapeles no parece ser un JSON válido.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear configuración de deserialización
|
||||||
|
var settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
Formatting = Formatting.Indented,
|
||||||
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
|
TypeNameHandling = TypeNameHandling.Auto,
|
||||||
|
ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||||
|
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
|
||||||
|
};
|
||||||
|
|
||||||
|
List<osBase> pastedObjects = null;
|
||||||
|
|
||||||
|
// Intentar deserializar como lista de objetos
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pastedObjects = JsonConvert.DeserializeObject<List<osBase>>(jsonString, settings);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Si falla, intentar como objeto individual
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var singleObject = JsonConvert.DeserializeObject<osBase>(jsonString, settings);
|
||||||
|
if (singleObject != null)
|
||||||
|
{
|
||||||
|
pastedObjects = new List<osBase> { singleObject };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
MessageBox.Show("No se pudo deserializar el contenido del portapapeles como objetos válidos.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pastedObjects == null || !pastedObjects.Any())
|
||||||
|
{
|
||||||
|
MessageBox.Show("No se encontraron objetos válidos en el portapapeles.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener posición del mouse en el canvas
|
||||||
|
var mousePosition = Mouse.GetPosition(ImagenEnTrabajoCanvas);
|
||||||
|
var mousePositionMeters = (
|
||||||
|
PixelToMeter.Instance.calc.PixelsToMeters((float)mousePosition.X),
|
||||||
|
PixelToMeter.Instance.calc.PixelsToMeters((float)mousePosition.Y)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Calcular el centro de los objetos pegados para posicionarlos en el mouse
|
||||||
|
var centerX = pastedObjects.Average(obj => obj.Left);
|
||||||
|
var centerY = pastedObjects.Average(obj => obj.Top);
|
||||||
|
var offsetX = mousePositionMeters.Item1 - centerX;
|
||||||
|
var offsetY = mousePositionMeters.Item2 - centerY;
|
||||||
|
|
||||||
|
if (DataContext is MainViewModel viewModel)
|
||||||
|
{
|
||||||
|
viewModel.StopSimulation();
|
||||||
|
viewModel.DisconnectPLC();
|
||||||
|
|
||||||
|
// Limpiar selección actual
|
||||||
|
_objectManager.ClearSelection();
|
||||||
|
|
||||||
|
var newlyPastedObjects = new List<osBase>();
|
||||||
|
|
||||||
|
foreach (var obj in pastedObjects)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Aplicar offset de posición
|
||||||
|
obj.Left += offsetX;
|
||||||
|
obj.Top += offsetY;
|
||||||
|
|
||||||
|
// Manejar IDs
|
||||||
|
if (!replaceExistingIds)
|
||||||
|
{
|
||||||
|
// Generar nuevo ID (comportamiento por defecto)
|
||||||
|
obj.Id.ObtenerNuevaID();
|
||||||
|
|
||||||
|
// Actualizar nombre si contiene ID
|
||||||
|
if (obj.Nombre.Contains("_"))
|
||||||
|
{
|
||||||
|
var parts = obj.Nombre.Split('_');
|
||||||
|
if (parts.Length > 1 && int.TryParse(parts.Last(), out _))
|
||||||
|
{
|
||||||
|
obj.Nombre = string.Join("_", parts.Take(parts.Length - 1)) + "_" + obj.Id.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Si replaceExistingIds es true, mantener los IDs originales
|
||||||
|
|
||||||
|
// Verificar que el objeto no existe ya si estamos reemplazando IDs
|
||||||
|
if (replaceExistingIds)
|
||||||
|
{
|
||||||
|
var existingObj = viewModel.ObjetosSimulables.FirstOrDefault(o => o.Id.Value == obj.Id.Value);
|
||||||
|
if (existingObj != null)
|
||||||
|
{
|
||||||
|
viewModel.RemoverObjetoSimulable(existingObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.CheckData();
|
||||||
|
viewModel.ObjetosSimulables.Add(obj);
|
||||||
|
viewModel.CrearUserControlDesdeObjetoSimulable(obj);
|
||||||
|
|
||||||
|
newlyPastedObjects.Add(obj);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error al procesar objeto {obj.Nombre}: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seleccionar los objetos pegados
|
||||||
|
foreach (var obj in newlyPastedObjects)
|
||||||
|
{
|
||||||
|
_objectManager.SelectObject(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
_objectManager.UpdateSelectionVisuals();
|
||||||
|
viewModel.HasUnsavedChanges = true;
|
||||||
|
|
||||||
|
Console.WriteLine($"Pegados {newlyPastedObjects.Count} objeto(s) desde el portapapeles");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error al pegar objetos: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FloatValidationRule : ValidationRule
|
public class FloatValidationRule : ValidationRule
|
||||||
|
|
Loading…
Reference in New Issue