Se implementó un sistema para gestionar múltiples ventanas de biblioteca, permitiendo la activación de una ventana existente o la creación de una nueva. Además, se mejoró la lógica de pegado de objetos, integrando la validación del contenido del portapapeles y la capacidad de pegar desde el portapapeles del sistema. Se añadió un método para recargar la imagen actual después de pegar en el proyecto actual, mejorando la experiencia del usuario al gestionar objetos en la biblioteca.

This commit is contained in:
Miguel 2025-06-18 11:49:22 +02:00
parent c03f6970d8
commit 9b710fcb00
2 changed files with 167 additions and 17 deletions

View File

@ -1162,13 +1162,35 @@ namespace CtrEditor
OnPropertyChanged(nameof(SelectedItemOsList)); OnPropertyChanged(nameof(SelectedItemOsList));
} }
// Diccionario para manejar ventanas de biblioteca múltiples
private Dictionary<string, PopUps.LibraryWindow> _libraryWindows = new();
private void ShowLibraryManager() private void ShowLibraryManager()
{ {
const string libraryWindowKey = "LibraryManager";
// Verificar si ya existe una ventana de biblioteca
if (_libraryWindows.TryGetValue(libraryWindowKey, out var existingWindow) &&
existingWindow.IsVisible)
{
existingWindow.Activate();
return;
}
// Crear nueva ventana modeless
var libraryWindow = new PopUps.LibraryWindow(); var libraryWindow = new PopUps.LibraryWindow();
var libraryViewModel = new PopUps.LibraryWindowViewModel(this); var libraryViewModel = new PopUps.LibraryWindowViewModel(this);
libraryWindow.DataContext = libraryViewModel; libraryWindow.DataContext = libraryViewModel;
libraryWindow.Owner = MainWindow; libraryWindow.Owner = MainWindow;
libraryWindow.ShowDialog();
// Manejar el cierre de la ventana
libraryWindow.Closed += (s, e) => _libraryWindows.Remove(libraryWindowKey);
// Registrar la ventana
_libraryWindows[libraryWindowKey] = libraryWindow;
// Mostrar como modeless (no modal)
libraryWindow.Show();
} }
} }

View File

@ -75,7 +75,7 @@ namespace CtrEditor.PopUps
AddLibraryDirectoryCommand = new RelayCommand(AddLibraryDirectory); AddLibraryDirectoryCommand = new RelayCommand(AddLibraryDirectory);
RemoveLibraryDirectoryCommand = new RelayCommand(RemoveLibraryDirectory, () => SelectedLibraryDirectory != null); RemoveLibraryDirectoryCommand = new RelayCommand(RemoveLibraryDirectory, () => SelectedLibraryDirectory != null);
CopyObjectCommand = new RelayCommand(CopyObject, () => HasSelectedObjects()); CopyObjectCommand = new RelayCommand(CopyObject, () => HasSelectedObjects());
PasteObjectCommand = new RelayCommand(PasteObject, () => SelectedLibrary != null && _clipboardObjects.Any()); PasteObjectCommand = new RelayCommand(PasteObject, () => SelectedLibrary != null && (HasObjectsAvailableToPaste()));
DeleteObjectCommand = new RelayCommand(DeleteObject, () => HasSelectedObjects() && SelectedLibrary != null && !SelectedLibrary.IsCurrentProject); DeleteObjectCommand = new RelayCommand(DeleteObject, () => HasSelectedObjects() && SelectedLibrary != null && !SelectedLibrary.IsCurrentProject);
CreateNewLibraryCommand = new RelayCommand(CreateNewLibrary, () => SelectedLibraryDirectory != null); CreateNewLibraryCommand = new RelayCommand(CreateNewLibrary, () => SelectedLibraryDirectory != null);
@ -92,6 +92,34 @@ namespace CtrEditor.PopUps
return SelectableObjects?.Any(o => o.IsSelected) == true || SelectedObject != null; return SelectableObjects?.Any(o => o.IsSelected) == true || SelectedObject != null;
} }
private bool HasObjectsAvailableToPaste()
{
// Verificar si hay objetos en el portapapeles interno o en el portapapeles del sistema
return _clipboardObjects.Any() ||
(System.Windows.Clipboard.ContainsText() && IsValidObjectData(System.Windows.Clipboard.GetText()));
}
private bool IsValidObjectData(string text)
{
if (string.IsNullOrWhiteSpace(text)) return false;
try
{
text = text.Trim();
// Validación básica: debe ser JSON que empiece con [ o {
if (!(text.StartsWith("[") || text.StartsWith("{"))) return false;
// Intentar parsearlo rápidamente sin deserializar completamente
var token = Newtonsoft.Json.Linq.JToken.Parse(text);
return token != null;
}
catch
{
return false;
}
}
private List<osBase> GetSelectedObjects() private List<osBase> GetSelectedObjects()
{ {
var selected = new List<osBase>(); var selected = new List<osBase>();
@ -457,7 +485,9 @@ namespace CtrEditor.PopUps
{ {
try try
{ {
_clipboardObjects.Clear(); // Usar el mismo sistema de portapapeles que MainWindow
// Crear copias usando la misma lógica que DuplicarObjeto
var objectsCopy = new List<osBase>();
var settings = new JsonSerializerSettings var settings = new JsonSerializerSettings
{ {
@ -471,20 +501,24 @@ namespace CtrEditor.PopUps
// Prepare object for serialization // Prepare object for serialization
obj.SalvarDatosNoSerializables(); obj.SalvarDatosNoSerializables();
// Serialize and deserialize to create a deep copy // Serialize and deserialize to create a deep copy (same as DuplicarObjeto)
var serializedData = JsonConvert.SerializeObject(obj, settings); var serializedData = JsonConvert.SerializeObject(obj, settings);
var copiedObject = JsonConvert.DeserializeObject<osBase>(serializedData, settings); var copiedObject = JsonConvert.DeserializeObject<osBase>(serializedData, settings);
if (copiedObject != null) if (copiedObject != null)
{ {
_clipboardObjects.Add(copiedObject); objectsCopy.Add(copiedObject);
} }
// Restore object state // Restore object state
obj.RestaurarDatosNoSerializables(); obj.RestaurarDatosNoSerializables();
} }
MessageBox.Show($"{_clipboardObjects.Count} objeto(s) copiado(s) al portapapeles.", "Información", MessageBoxButton.OK, MessageBoxImage.Information); // Copiar al portapapeles del sistema usando el mismo formato que MainWindow
string jsonString = JsonConvert.SerializeObject(objectsCopy, settings);
System.Windows.Clipboard.SetText(jsonString);
MessageBox.Show($"{objectsCopy.Count} objeto(s) copiado(s) al portapapeles del sistema.", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
CommandManager.InvalidateRequerySuggested(); CommandManager.InvalidateRequerySuggested();
} }
catch (Exception ex) catch (Exception ex)
@ -496,11 +530,64 @@ namespace CtrEditor.PopUps
private void PasteObject() private void PasteObject()
{ {
if (SelectedLibrary != null && _clipboardObjects.Any()) if (SelectedLibrary != null)
{ {
try try
{ {
foreach (var objToPaste in _clipboardObjects) List<osBase> objectsToPaste = new List<osBase>();
// Si hay objetos en el portapapeles interno (modo anterior)
if (_clipboardObjects.Any())
{
objectsToPaste = _clipboardObjects.ToList();
}
// Si no, intentar usar el portapapeles del sistema
else if (System.Windows.Clipboard.ContainsText())
{
string jsonString = System.Windows.Clipboard.GetText();
if (!string.IsNullOrWhiteSpace(jsonString))
{
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
NullValueHandling = NullValueHandling.Ignore,
ObjectCreationHandling = ObjectCreationHandling.Replace,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
// Intentar deserializar como lista de objetos
try
{
objectsToPaste = JsonConvert.DeserializeObject<List<osBase>>(jsonString, settings);
}
catch
{
// Si falla, intentar como objeto individual
try
{
var singleObject = JsonConvert.DeserializeObject<osBase>(jsonString, settings);
if (singleObject != null)
{
objectsToPaste = 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 (!objectsToPaste.Any())
{
MessageBox.Show("No hay objetos para pegar.", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
foreach (var objToPaste in objectsToPaste)
{ {
// Create a new unique ID for the pasted object // Create a new unique ID for the pasted object
objToPaste.Id.ObtenerNuevaID(); objToPaste.Id.ObtenerNuevaID();
@ -526,9 +613,15 @@ namespace CtrEditor.PopUps
} }
} }
// Si se pegó en el proyecto actual, recargar la imagen actual
if (SelectedLibrary.IsCurrentProject)
{
ReloadCurrentImage();
}
RefreshLibraries(); RefreshLibraries();
LoadObjectsFromLibrary(); LoadObjectsFromLibrary();
MessageBox.Show($"{_clipboardObjects.Count} objeto(s) pegado(s).", "Información", MessageBoxButton.OK, MessageBoxImage.Information); MessageBox.Show($"{objectsToPaste.Count} objeto(s) pegado(s).", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -537,6 +630,26 @@ namespace CtrEditor.PopUps
} }
} }
// Método para recargar la imagen actual después de pegar en el proyecto actual
private void ReloadCurrentImage()
{
try
{
// Forzar recarga de la imagen actual para reflejar los cambios
var currentImage = _mainViewModel.SelectedImage;
if (!string.IsNullOrEmpty(currentImage))
{
// Temporalmente cambiar a null y luego restaurar para forzar la recarga
_mainViewModel.SelectedImage = null;
_mainViewModel.SelectedImage = currentImage;
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Error al recargar imagen actual: {ex.Message}");
}
}
private void DeleteObject() private void DeleteObject()
{ {
var objectsToDelete = GetSelectedObjects(); var objectsToDelete = GetSelectedObjects();
@ -624,13 +737,6 @@ namespace CtrEditor.PopUps
try try
{ {
var simulationData = new SimulationData
{
ObjetosSimulables = new ObservableCollection<osBase>(library.Objects),
UnitConverter = PixelToMeter.Instance.calc,
PLC_ConnectionData = new LibS7Adv.PLCViewModel()
};
var settings = new JsonSerializerSettings var settings = new JsonSerializerSettings
{ {
Formatting = Formatting.Indented, Formatting = Formatting.Indented,
@ -638,7 +744,29 @@ namespace CtrEditor.PopUps
TypeNameHandling = TypeNameHandling.All TypeNameHandling = TypeNameHandling.All
}; };
string json = JsonConvert.SerializeObject(simulationData, settings); string json;
// Detectar si es formato AllPages.json basándose en el nombre del archivo
var fileName = Path.GetFileName(library.FilePath).ToLowerInvariant();
bool isAllPagesFormat = fileName.Contains("allpages") || fileName.StartsWith("allpages");
if (isAllPagesFormat)
{
// Formato AllPages.json: guardar como array directo de objetos
json = JsonConvert.SerializeObject(library.Objects, settings);
}
else
{
// Formato normal: guardar con wrapper SimulationData
var simulationData = new SimulationData
{
ObjetosSimulables = new ObservableCollection<osBase>(library.Objects),
UnitConverter = PixelToMeter.Instance.calc,
PLC_ConnectionData = new LibS7Adv.PLCViewModel()
};
json = JsonConvert.SerializeObject(simulationData, settings);
}
File.WriteAllText(library.FilePath, json); File.WriteAllText(library.FilePath, json);
} }
catch (Exception ex) catch (Exception ex)