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 UserControl = System.Windows.Controls.UserControl;
|
||||
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
|
||||
{
|
||||
|
@ -646,6 +651,27 @@ namespace CtrEditor
|
|||
|
||||
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
|
||||
var lockSubmenu = new MenuItem { Header = "Bloqueo" };
|
||||
|
||||
|
@ -718,6 +744,16 @@ namespace CtrEditor
|
|||
_objectManager.RemoveResizeRectangles();
|
||||
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())
|
||||
{
|
||||
const float moveDistance = 0.01f;
|
||||
|
@ -745,6 +781,199 @@ namespace CtrEditor
|
|||
}
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue