diff --git a/MainViewModel.cs b/MainViewModel.cs index fbc4c90..4d7373e 100644 --- a/MainViewModel.cs +++ b/MainViewModel.cs @@ -1162,13 +1162,35 @@ namespace CtrEditor OnPropertyChanged(nameof(SelectedItemOsList)); } + // Diccionario para manejar ventanas de biblioteca múltiples + private Dictionary _libraryWindows = new(); + 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 libraryViewModel = new PopUps.LibraryWindowViewModel(this); libraryWindow.DataContext = libraryViewModel; 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(); } } diff --git a/PopUps/LibraryWindowViewModel.cs b/PopUps/LibraryWindowViewModel.cs index 1a18cd9..ff36eed 100644 --- a/PopUps/LibraryWindowViewModel.cs +++ b/PopUps/LibraryWindowViewModel.cs @@ -75,7 +75,7 @@ namespace CtrEditor.PopUps AddLibraryDirectoryCommand = new RelayCommand(AddLibraryDirectory); RemoveLibraryDirectoryCommand = new RelayCommand(RemoveLibraryDirectory, () => SelectedLibraryDirectory != null); 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); CreateNewLibraryCommand = new RelayCommand(CreateNewLibrary, () => SelectedLibraryDirectory != null); @@ -92,6 +92,34 @@ namespace CtrEditor.PopUps 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 GetSelectedObjects() { var selected = new List(); @@ -457,7 +485,9 @@ namespace CtrEditor.PopUps { try { - _clipboardObjects.Clear(); + // Usar el mismo sistema de portapapeles que MainWindow + // Crear copias usando la misma lógica que DuplicarObjeto + var objectsCopy = new List(); var settings = new JsonSerializerSettings { @@ -471,20 +501,24 @@ namespace CtrEditor.PopUps // Prepare object for serialization 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 copiedObject = JsonConvert.DeserializeObject(serializedData, settings); if (copiedObject != null) { - _clipboardObjects.Add(copiedObject); + objectsCopy.Add(copiedObject); } // Restore object state 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(); } catch (Exception ex) @@ -496,11 +530,64 @@ namespace CtrEditor.PopUps private void PasteObject() { - if (SelectedLibrary != null && _clipboardObjects.Any()) + if (SelectedLibrary != null) { try { - foreach (var objToPaste in _clipboardObjects) + List objectsToPaste = new List(); + + // 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>(jsonString, settings); + } + catch + { + // Si falla, intentar como objeto individual + try + { + var singleObject = JsonConvert.DeserializeObject(jsonString, settings); + if (singleObject != null) + { + objectsToPaste = new List { 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 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(); 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) { @@ -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() { var objectsToDelete = GetSelectedObjects(); @@ -624,13 +737,6 @@ namespace CtrEditor.PopUps try { - var simulationData = new SimulationData - { - ObjetosSimulables = new ObservableCollection(library.Objects), - UnitConverter = PixelToMeter.Instance.calc, - PLC_ConnectionData = new LibS7Adv.PLCViewModel() - }; - var settings = new JsonSerializerSettings { Formatting = Formatting.Indented, @@ -638,7 +744,29 @@ namespace CtrEditor.PopUps 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(library.Objects), + UnitConverter = PixelToMeter.Instance.calc, + PLC_ConnectionData = new LibS7Adv.PLCViewModel() + }; + json = JsonConvert.SerializeObject(simulationData, settings); + } + File.WriteAllText(library.FilePath, json); } catch (Exception ex)