902 lines
35 KiB
C#
902 lines
35 KiB
C#
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using CtrEditor.Controls;
|
|
using CtrEditor.ObjetosSim;
|
|
using CtrEditor.Serialization;
|
|
using Newtonsoft.Json;
|
|
using Ookii.Dialogs.Wpf;
|
|
|
|
namespace CtrEditor.PopUps
|
|
{
|
|
public partial class LibraryWindowViewModel : ObservableObject
|
|
{
|
|
private readonly MainViewModel _mainViewModel;
|
|
private List<osBase> _clipboardObjects = new List<osBase>();
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<LibraryDirectoryItem> libraryDirectories;
|
|
|
|
[ObservableProperty]
|
|
private LibraryDirectoryItem selectedLibraryDirectory;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<LibraryItem> libraries;
|
|
|
|
[ObservableProperty]
|
|
private LibraryItem selectedLibrary;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<ObjectTypeGroup> filteredObjectsByType;
|
|
|
|
[ObservableProperty]
|
|
private osBase selectedObject;
|
|
|
|
// Nueva propiedad para el TreeView jerárquico
|
|
[ObservableProperty]
|
|
private ObservableCollection<LibraryTreeNode> libraryTreeNodes;
|
|
|
|
[ObservableProperty]
|
|
private LibraryTreeNode selectedTreeNode;
|
|
|
|
// Nueva propiedad para objetos seleccionados múltiples
|
|
[ObservableProperty]
|
|
private ObservableCollection<SelectableObjectWrapper> selectableObjects;
|
|
|
|
// Commands
|
|
public ICommand AddLibraryDirectoryCommand { get; }
|
|
public ICommand RemoveLibraryDirectoryCommand { get; }
|
|
public ICommand CopyObjectCommand { get; }
|
|
public ICommand PasteObjectCommand { get; }
|
|
public ICommand DeleteObjectCommand { get; }
|
|
public ICommand CreateNewLibraryCommand { get; }
|
|
|
|
// Nuevos comandos para menú contextual
|
|
public ICommand CreateLibraryInDirectoryCommand { get; }
|
|
public ICommand RemoveDirectoryCommand { get; }
|
|
|
|
public LibraryWindowViewModel(MainViewModel mainViewModel)
|
|
{
|
|
_mainViewModel = mainViewModel;
|
|
|
|
LibraryDirectories = new ObservableCollection<LibraryDirectoryItem>();
|
|
Libraries = new ObservableCollection<LibraryItem>();
|
|
FilteredObjectsByType = new ObservableCollection<ObjectTypeGroup>();
|
|
LibraryTreeNodes = new ObservableCollection<LibraryTreeNode>();
|
|
SelectableObjects = new ObservableCollection<SelectableObjectWrapper>();
|
|
|
|
// Initialize commands
|
|
AddLibraryDirectoryCommand = new RelayCommand(AddLibraryDirectory);
|
|
RemoveLibraryDirectoryCommand = new RelayCommand(RemoveLibraryDirectory, () => SelectedLibraryDirectory != null);
|
|
CopyObjectCommand = new RelayCommand(CopyObject, () => HasSelectedObjects());
|
|
PasteObjectCommand = new RelayCommand(PasteObject, () => SelectedLibrary != null && (HasObjectsAvailableToPaste()));
|
|
DeleteObjectCommand = new RelayCommand(DeleteObject, () => HasSelectedObjects() && SelectedLibrary != null && !SelectedLibrary.IsCurrentProject);
|
|
CreateNewLibraryCommand = new RelayCommand(CreateNewLibrary, () => SelectedLibraryDirectory != null);
|
|
|
|
// Nuevos comandos
|
|
CreateLibraryInDirectoryCommand = new RelayCommand(CreateLibraryInDirectory, () => SelectedTreeNode?.IsDirectory == true);
|
|
RemoveDirectoryCommand = new RelayCommand(RemoveDirectory, () => SelectedTreeNode?.IsDirectory == true && !SelectedTreeNode.IsCurrentProject);
|
|
|
|
LoadLibraryDirectories();
|
|
RefreshLibraryTree();
|
|
}
|
|
|
|
private bool HasSelectedObjects()
|
|
{
|
|
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()
|
|
{
|
|
var selected = new List<osBase>();
|
|
|
|
// Primero agregar objetos seleccionados por checkbox
|
|
if (SelectableObjects != null)
|
|
{
|
|
selected.AddRange(SelectableObjects.Where(o => o.IsSelected).Select(o => o.Object));
|
|
}
|
|
|
|
// Si no hay objetos con checkbox seleccionados, usar la selección simple
|
|
if (!selected.Any() && SelectedObject != null)
|
|
{
|
|
selected.Add(SelectedObject);
|
|
}
|
|
|
|
return selected;
|
|
}
|
|
|
|
partial void OnSelectedTreeNodeChanged(LibraryTreeNode value)
|
|
{
|
|
if (value?.IsDirectory == false) // Es una biblioteca
|
|
{
|
|
SelectedLibrary = value.Library;
|
|
LoadObjectsFromLibrary();
|
|
}
|
|
CommandManager.InvalidateRequerySuggested();
|
|
}
|
|
|
|
partial void OnSelectedLibraryDirectoryChanged(LibraryDirectoryItem value)
|
|
{
|
|
RefreshLibraries();
|
|
CommandManager.InvalidateRequerySuggested();
|
|
}
|
|
|
|
partial void OnSelectedLibraryChanged(LibraryItem value)
|
|
{
|
|
LoadObjectsFromLibrary();
|
|
CommandManager.InvalidateRequerySuggested();
|
|
}
|
|
|
|
private osVisFilter _objectFilter;
|
|
public void SetObjectFilter(osVisFilter filter)
|
|
{
|
|
_objectFilter = filter;
|
|
if (SelectedLibrary != null)
|
|
{
|
|
UpdateFilterTypes(filter);
|
|
}
|
|
}
|
|
|
|
private void LoadLibraryDirectories()
|
|
{
|
|
LibraryDirectories.Clear();
|
|
|
|
// Add current project directory
|
|
LibraryDirectories.Add(new LibraryDirectoryItem
|
|
{
|
|
Path = _mainViewModel.directorioTrabajo,
|
|
DisplayName = $"Proyecto Actual ({_mainViewModel.directorioTrabajo})",
|
|
IsCurrentProject = true
|
|
});
|
|
|
|
// Add saved library directories
|
|
foreach (var directory in EstadoPersistente.Instance.LibraryDirectories)
|
|
{
|
|
if (Directory.Exists(directory))
|
|
{
|
|
LibraryDirectories.Add(new LibraryDirectoryItem
|
|
{
|
|
Path = directory,
|
|
DisplayName = directory, // Show full path instead of just folder name
|
|
IsCurrentProject = false
|
|
});
|
|
}
|
|
}
|
|
|
|
if (LibraryDirectories.Any())
|
|
{
|
|
SelectedLibraryDirectory = LibraryDirectories.First();
|
|
}
|
|
}
|
|
|
|
private void RefreshLibraries()
|
|
{
|
|
Libraries.Clear();
|
|
|
|
if (SelectedLibraryDirectory == null) return;
|
|
|
|
if (SelectedLibraryDirectory.IsCurrentProject)
|
|
{
|
|
// Add current project as a library
|
|
Libraries.Add(new LibraryItem
|
|
{
|
|
Name = "Proyecto Actual",
|
|
FilePath = null,
|
|
IsCurrentProject = true,
|
|
Objects = _mainViewModel.ObjetosSimulables.ToList()
|
|
});
|
|
|
|
// Add JSON files from current project directory
|
|
AddJsonFilesFromDirectory(SelectedLibraryDirectory.Path);
|
|
}
|
|
else
|
|
{
|
|
// Add JSON files from selected library directory
|
|
AddJsonFilesFromDirectory(SelectedLibraryDirectory.Path);
|
|
}
|
|
}
|
|
|
|
private void AddJsonFilesFromDirectory(string directoryPath)
|
|
{
|
|
if (!Directory.Exists(directoryPath)) return;
|
|
|
|
var jsonFiles = Directory.GetFiles(directoryPath, "*.json", SearchOption.AllDirectories);
|
|
|
|
foreach (var jsonFile in jsonFiles)
|
|
{
|
|
try
|
|
{
|
|
var relativePath = Path.GetRelativePath(directoryPath, jsonFile);
|
|
var displayName = Path.GetFileNameWithoutExtension(jsonFile);
|
|
|
|
var libraryItem = new LibraryItem
|
|
{
|
|
Name = displayName,
|
|
FilePath = jsonFile,
|
|
IsCurrentProject = false,
|
|
Objects = LoadObjectsFromJsonFile(jsonFile)
|
|
};
|
|
|
|
Libraries.Add(libraryItem);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Log error but continue processing other files
|
|
System.Diagnostics.Debug.WriteLine($"Error loading library {jsonFile}: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
private List<osBase> LoadObjectsFromJsonFile(string filePath)
|
|
{
|
|
var objects = new List<osBase>();
|
|
|
|
try
|
|
{
|
|
var settings = new JsonSerializerSettings
|
|
{
|
|
TypeNameHandling = TypeNameHandling.All,
|
|
NullValueHandling = NullValueHandling.Ignore
|
|
};
|
|
|
|
string json = File.ReadAllText(filePath);
|
|
|
|
// Try to detect format: check if it starts with '[' (AllPages.json format) or '{' (normal format)
|
|
json = json.Trim();
|
|
|
|
if (json.StartsWith("["))
|
|
{
|
|
// AllPages.json format: direct array of objects
|
|
var directObjects = JsonConvert.DeserializeObject<List<osBase>>(json, settings);
|
|
if (directObjects != null)
|
|
{
|
|
objects.AddRange(directObjects);
|
|
}
|
|
}
|
|
else if (json.StartsWith("{"))
|
|
{
|
|
// Normal format: SimulationData wrapper
|
|
var simulationData = JsonConvert.DeserializeObject<SimulationData>(json, settings);
|
|
if (simulationData?.ObjetosSimulables != null)
|
|
{
|
|
objects.AddRange(simulationData.ObjetosSimulables);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"Error loading objects from {filePath}: {ex.Message}");
|
|
}
|
|
|
|
return objects;
|
|
}
|
|
|
|
private void LoadObjectsFromLibrary()
|
|
{
|
|
FilteredObjectsByType.Clear();
|
|
SelectableObjects.Clear();
|
|
|
|
if (SelectedLibrary == null) return;
|
|
|
|
// Crear objetos seleccionables con checkboxes
|
|
foreach (var obj in SelectedLibrary.Objects)
|
|
{
|
|
SelectableObjects.Add(new SelectableObjectWrapper { Object = obj, IsSelected = false });
|
|
}
|
|
|
|
// Update filter types and tags when library changes
|
|
if (_objectFilter != null)
|
|
{
|
|
UpdateFilterTypes(_objectFilter);
|
|
}
|
|
|
|
ApplyFiltering(SelectedLibrary.Objects);
|
|
}
|
|
|
|
public void UpdateFilterTypes(osVisFilter filter)
|
|
{
|
|
if (SelectedLibrary?.Objects != null)
|
|
{
|
|
var types = SelectedLibrary.Objects.Select(o => o.GetType()).Distinct();
|
|
filter.UpdateAvailableTypes(types);
|
|
filter.UpdateAvailableTags(SelectedLibrary.Objects);
|
|
}
|
|
}
|
|
|
|
private void ApplyFiltering(List<osBase> objects)
|
|
{
|
|
// Group objects by type
|
|
var groupedObjects = objects
|
|
.GroupBy(obj => obj.GetType())
|
|
.Select(group => new ObjectTypeGroup
|
|
{
|
|
Type = group.Key,
|
|
TypeName = GetTypeDisplayName(group.Key),
|
|
Objects = new ObservableCollection<osBase>(group.ToList())
|
|
})
|
|
.OrderBy(group => group.TypeName)
|
|
.ToList();
|
|
|
|
FilteredObjectsByType.Clear();
|
|
foreach (var group in groupedObjects)
|
|
{
|
|
FilteredObjectsByType.Add(group);
|
|
}
|
|
}
|
|
|
|
public void OnFilterChanged(osVisFilterViewModel filterViewModel)
|
|
{
|
|
if (SelectedLibrary == null) return;
|
|
|
|
var filteredObjects = new List<osBase>();
|
|
|
|
foreach (var obj in SelectedLibrary.Objects)
|
|
{
|
|
bool isVisible = true;
|
|
|
|
// Apply Show All filter
|
|
if (!filterViewModel.ShowAll)
|
|
{
|
|
// Check type filter
|
|
var typeFilter = filterViewModel.TypeFilters.FirstOrDefault(tf => tf.Type == obj.GetType());
|
|
if (typeFilter == null || !typeFilter.IsSelected)
|
|
{
|
|
isVisible = false;
|
|
}
|
|
|
|
// Check tag filters
|
|
if (filterViewModel.TagFilters.Any() && filterViewModel.TagFilters.Any(tf => tf.IsSelected))
|
|
{
|
|
var selectedTags = filterViewModel.TagFilters.Where(tf => tf.IsSelected).Select(tf => tf.TagName).ToList();
|
|
bool hasMatchingTag = obj.ListaEtiquetas.Any(tag => selectedTags.Contains(tag));
|
|
if (!hasMatchingTag)
|
|
{
|
|
isVisible = false;
|
|
}
|
|
}
|
|
|
|
// Check search tags
|
|
if (!string.IsNullOrWhiteSpace(filterViewModel.SearchTags))
|
|
{
|
|
var searchTags = filterViewModel.SearchTags
|
|
.Split(' ', StringSplitOptions.RemoveEmptyEntries)
|
|
.Where(tag => tag.StartsWith("#") && tag.Length > 1)
|
|
.Select(tag => tag.Substring(1).ToLowerInvariant())
|
|
.ToList();
|
|
|
|
if (searchTags.Any())
|
|
{
|
|
bool hasMatchingSearchTag = searchTags.Any(searchTag => obj.ListaEtiquetas.Contains(searchTag));
|
|
if (!hasMatchingSearchTag)
|
|
{
|
|
isVisible = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check other filters
|
|
if (filterViewModel.ShowCloned && !obj.Cloned)
|
|
isVisible = false;
|
|
|
|
if (filterViewModel.ShowAutoCreated && !obj.AutoCreated)
|
|
isVisible = false;
|
|
|
|
if (filterViewModel.ShowEnableOnAllPages && !obj.Enable_On_All_Pages)
|
|
isVisible = false;
|
|
|
|
if (filterViewModel.ShowOnThisPage && !obj.Show_On_This_Page)
|
|
isVisible = false;
|
|
}
|
|
|
|
if (isVisible)
|
|
{
|
|
filteredObjects.Add(obj);
|
|
}
|
|
}
|
|
|
|
ApplyFiltering(filteredObjects);
|
|
}
|
|
|
|
private string GetTypeDisplayName(Type type)
|
|
{
|
|
try
|
|
{
|
|
var methodInfo = type.GetMethod("NombreClase", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
|
|
return methodInfo != null ? methodInfo.Invoke(null, null)?.ToString() : type.Name;
|
|
}
|
|
catch
|
|
{
|
|
return type.Name;
|
|
}
|
|
}
|
|
|
|
private void AddLibraryDirectory()
|
|
{
|
|
var dialog = new VistaFolderBrowserDialog();
|
|
if (dialog.ShowDialog() == true)
|
|
{
|
|
var path = dialog.SelectedPath;
|
|
if (!EstadoPersistente.Instance.LibraryDirectories.Contains(path))
|
|
{
|
|
EstadoPersistente.Instance.LibraryDirectories.Add(path);
|
|
EstadoPersistente.Instance.GuardarEstado();
|
|
LoadLibraryDirectories();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RemoveLibraryDirectory()
|
|
{
|
|
if (SelectedLibraryDirectory != null && !SelectedLibraryDirectory.IsCurrentProject)
|
|
{
|
|
var result = MessageBox.Show(
|
|
$"¿Está seguro de que desea eliminar el directorio '{SelectedLibraryDirectory.DisplayName}' de la lista de bibliotecas?",
|
|
"Confirmar eliminación",
|
|
MessageBoxButton.YesNo,
|
|
MessageBoxImage.Question);
|
|
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
EstadoPersistente.Instance.LibraryDirectories.Remove(SelectedLibraryDirectory.Path);
|
|
EstadoPersistente.Instance.GuardarEstado();
|
|
LoadLibraryDirectories();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CopyObject()
|
|
{
|
|
var objectsToCopy = GetSelectedObjects();
|
|
if (objectsToCopy.Any())
|
|
{
|
|
try
|
|
{
|
|
// 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
|
|
{
|
|
Formatting = Formatting.Indented,
|
|
NullValueHandling = NullValueHandling.Ignore,
|
|
TypeNameHandling = TypeNameHandling.All
|
|
};
|
|
|
|
foreach (var obj in objectsToCopy)
|
|
{
|
|
// Prepare object for serialization
|
|
obj.SalvarDatosNoSerializables();
|
|
|
|
// Serialize and deserialize to create a deep copy (same as DuplicarObjeto)
|
|
var serializedData = JsonConvert.SerializeObject(obj, settings);
|
|
var copiedObject = JsonConvert.DeserializeObject<osBase>(serializedData, settings);
|
|
|
|
if (copiedObject != null)
|
|
{
|
|
objectsCopy.Add(copiedObject);
|
|
}
|
|
|
|
// Restore object state
|
|
obj.RestaurarDatosNoSerializables();
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
MessageBox.Show($"Error al copiar objeto(s): {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PasteObject()
|
|
{
|
|
if (SelectedLibrary != null)
|
|
{
|
|
try
|
|
{
|
|
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
|
|
objToPaste.Id.ObtenerNuevaID();
|
|
|
|
// Update name to include ID
|
|
string nombre = Regex.IsMatch(objToPaste.Nombre, @"_\d+$")
|
|
? Regex.Replace(objToPaste.Nombre, @"_\d+$", $"_{objToPaste.Id.Value}")
|
|
: objToPaste.Nombre + "_" + objToPaste.Id.Value;
|
|
objToPaste.Nombre = nombre;
|
|
|
|
if (SelectedLibrary.IsCurrentProject)
|
|
{
|
|
// Add to current project
|
|
_mainViewModel.ObjetosSimulables.Add(objToPaste);
|
|
_mainViewModel.CrearUserControlDesdeObjetoSimulable(objToPaste);
|
|
_mainViewModel.HasUnsavedChanges = true;
|
|
}
|
|
else
|
|
{
|
|
// Add to selected library file
|
|
SelectedLibrary.Objects.Add(objToPaste);
|
|
SaveLibraryToFile(SelectedLibrary);
|
|
}
|
|
}
|
|
|
|
// Si se pegó en el proyecto actual, recargar la imagen actual
|
|
if (SelectedLibrary.IsCurrentProject)
|
|
{
|
|
ReloadCurrentImage();
|
|
}
|
|
|
|
RefreshLibraries();
|
|
LoadObjectsFromLibrary();
|
|
MessageBox.Show($"{objectsToPaste.Count} objeto(s) pegado(s).", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Error al pegar objeto: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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();
|
|
if (objectsToDelete.Any() && SelectedLibrary != null && !SelectedLibrary.IsCurrentProject)
|
|
{
|
|
var message = objectsToDelete.Count == 1
|
|
? $"¿Está seguro de que desea eliminar el objeto '{objectsToDelete.First().Nombre}'?"
|
|
: $"¿Está seguro de que desea eliminar {objectsToDelete.Count} objetos?";
|
|
|
|
var result = MessageBox.Show(message, "Confirmar eliminación", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
|
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
try
|
|
{
|
|
foreach (var obj in objectsToDelete)
|
|
{
|
|
SelectedLibrary.Objects.Remove(obj);
|
|
}
|
|
|
|
SaveLibraryToFile(SelectedLibrary);
|
|
LoadObjectsFromLibrary();
|
|
SelectedObject = null;
|
|
|
|
var successMessage = objectsToDelete.Count == 1
|
|
? "Objeto eliminado."
|
|
: $"{objectsToDelete.Count} objetos eliminados.";
|
|
|
|
MessageBox.Show(successMessage, "Información", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Error al eliminar objeto(s): {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CreateNewLibrary()
|
|
{
|
|
if (SelectedLibraryDirectory == null) return;
|
|
|
|
var dialog = new Microsoft.Win32.SaveFileDialog
|
|
{
|
|
DefaultExt = ".json",
|
|
Filter = "JSON files (*.json)|*.json",
|
|
InitialDirectory = SelectedLibraryDirectory.Path,
|
|
Title = "Crear nueva biblioteca"
|
|
};
|
|
|
|
if (dialog.ShowDialog() == true)
|
|
{
|
|
try
|
|
{
|
|
var emptyLibrary = new SimulationData
|
|
{
|
|
ObjetosSimulables = new ObservableCollection<osBase>(),
|
|
UnitConverter = PixelToMeter.Instance.calc,
|
|
PLC_ConnectionData = new LibS7Adv.PLCViewModel()
|
|
};
|
|
|
|
var settings = new JsonSerializerSettings
|
|
{
|
|
Formatting = Formatting.Indented,
|
|
NullValueHandling = NullValueHandling.Ignore,
|
|
TypeNameHandling = TypeNameHandling.All
|
|
};
|
|
|
|
string json = JsonConvert.SerializeObject(emptyLibrary, settings);
|
|
File.WriteAllText(dialog.FileName, json);
|
|
|
|
RefreshLibraries();
|
|
MessageBox.Show("Nueva biblioteca creada.", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Error al crear biblioteca: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SaveLibraryToFile(LibraryItem library)
|
|
{
|
|
if (library.IsCurrentProject || string.IsNullOrEmpty(library.FilePath)) return;
|
|
|
|
try
|
|
{
|
|
var settings = new JsonSerializerSettings
|
|
{
|
|
Formatting = Formatting.Indented,
|
|
NullValueHandling = NullValueHandling.Ignore,
|
|
TypeNameHandling = TypeNameHandling.All
|
|
};
|
|
|
|
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);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Error al guardar biblioteca: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
|
|
private void RefreshLibraryTree()
|
|
{
|
|
LibraryTreeNodes.Clear();
|
|
|
|
foreach (var directory in LibraryDirectories)
|
|
{
|
|
var directoryNode = new LibraryTreeNode
|
|
{
|
|
DisplayName = directory.DisplayName,
|
|
IsDirectory = true,
|
|
IsCurrentProject = directory.IsCurrentProject,
|
|
DirectoryPath = directory.Path,
|
|
Children = new ObservableCollection<LibraryTreeNode>()
|
|
};
|
|
|
|
// Agregar bibliotecas como hijos del directorio
|
|
if (directory.IsCurrentProject)
|
|
{
|
|
// Agregar proyecto actual
|
|
directoryNode.Children.Add(new LibraryTreeNode
|
|
{
|
|
DisplayName = "Proyecto Actual",
|
|
IsDirectory = false,
|
|
Library = new LibraryItem
|
|
{
|
|
Name = "Proyecto Actual",
|
|
IsCurrentProject = true,
|
|
Objects = _mainViewModel.ObjetosSimulables.ToList()
|
|
}
|
|
});
|
|
}
|
|
|
|
// Agregar archivos JSON
|
|
if (Directory.Exists(directory.Path))
|
|
{
|
|
var jsonFiles = Directory.GetFiles(directory.Path, "*.json", SearchOption.AllDirectories);
|
|
foreach (var jsonFile in jsonFiles)
|
|
{
|
|
try
|
|
{
|
|
var displayName = Path.GetFileNameWithoutExtension(jsonFile);
|
|
directoryNode.Children.Add(new LibraryTreeNode
|
|
{
|
|
DisplayName = displayName,
|
|
IsDirectory = false,
|
|
Library = new LibraryItem
|
|
{
|
|
Name = displayName,
|
|
FilePath = jsonFile,
|
|
IsCurrentProject = false,
|
|
Objects = LoadObjectsFromJsonFile(jsonFile)
|
|
}
|
|
});
|
|
}
|
|
catch
|
|
{
|
|
// Ignorar archivos que no se pueden cargar
|
|
}
|
|
}
|
|
}
|
|
|
|
LibraryTreeNodes.Add(directoryNode);
|
|
}
|
|
}
|
|
|
|
private void CreateLibraryInDirectory()
|
|
{
|
|
if (SelectedTreeNode?.IsDirectory != true) return;
|
|
|
|
var oldSelectedDirectory = SelectedLibraryDirectory;
|
|
|
|
// Temporalmente cambiar el directorio seleccionado
|
|
SelectedLibraryDirectory = LibraryDirectories.FirstOrDefault(d => d.Path == SelectedTreeNode.DirectoryPath);
|
|
CreateNewLibrary();
|
|
RefreshLibraryTree();
|
|
|
|
// Restaurar el directorio seleccionado
|
|
SelectedLibraryDirectory = oldSelectedDirectory;
|
|
}
|
|
|
|
private void RemoveDirectory()
|
|
{
|
|
if (SelectedTreeNode?.IsDirectory != true || SelectedTreeNode.IsCurrentProject) return;
|
|
|
|
var result = MessageBox.Show($"¿Eliminar el directorio '{SelectedTreeNode.DisplayName}' de la lista de bibliotecas?",
|
|
"Confirmar eliminación", MessageBoxButton.YesNo, MessageBoxImage.Question);
|
|
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
EstadoPersistente.Instance.LibraryDirectories.Remove(SelectedTreeNode.DirectoryPath);
|
|
EstadoPersistente.Instance.GuardarEstado();
|
|
LoadLibraryDirectories();
|
|
RefreshLibraryTree();
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Support classes
|
|
public class LibraryDirectoryItem
|
|
{
|
|
public string Path { get; set; }
|
|
public string DisplayName { get; set; }
|
|
public bool IsCurrentProject { get; set; }
|
|
}
|
|
|
|
public class LibraryItem
|
|
{
|
|
public string Name { get; set; }
|
|
public string FilePath { get; set; }
|
|
public bool IsCurrentProject { get; set; }
|
|
public List<osBase> Objects { get; set; } = new List<osBase>();
|
|
public string DisplayName => IsCurrentProject ? $"{Name} (Proyecto)" : Name;
|
|
}
|
|
|
|
public class ObjectTypeGroup
|
|
{
|
|
public Type Type { get; set; }
|
|
public string TypeName { get; set; }
|
|
public ObservableCollection<osBase> Objects { get; set; } = new ObservableCollection<osBase>();
|
|
}
|
|
} |