Se añadió la funcionalidad de gestión de bibliotecas de objetos en la interfaz de usuario, incluyendo un nuevo comando para abrir la ventana de gestión de bibliotecas. Se incorporó una nueva propiedad en la clase EstadoPersistente para almacenar directorios de bibliotecas y se realizaron mejoras en la estructura del código para una mayor claridad y mantenimiento.
This commit is contained in:
parent
67fa5eef3d
commit
c353f6c6ea
|
@ -0,0 +1,110 @@
|
||||||
|
# Biblioteca de Objetos Simulables
|
||||||
|
|
||||||
|
## Descripción
|
||||||
|
|
||||||
|
La biblioteca de objetos simulables es una nueva funcionalidad que permite gestionar y organizar objetos simulables en bibliotecas independientes del proyecto actual. Esto facilita la reutilización de objetos entre diferentes proyectos.
|
||||||
|
|
||||||
|
## Características Principales
|
||||||
|
|
||||||
|
### 1. Gestión de Directorios de Biblioteca
|
||||||
|
- **Agregar directorios**: Permite agregar nuevos directorios que contendrán bibliotecas de objetos
|
||||||
|
- **Eliminar directorios**: Permite remover directorios de la lista de bibliotecas
|
||||||
|
- **Persistencia global**: Los directorios se mantienen independientemente del proyecto actual
|
||||||
|
|
||||||
|
### 2. Bibliotecas de Objetos
|
||||||
|
- **Proyecto actual**: El proyecto actual siempre aparece como una biblioteca
|
||||||
|
- **Archivos JSON**: Cada archivo JSON en los directorios de biblioteca se muestra como una biblioteca independiente
|
||||||
|
- **Visualización jerárquica**: Los objetos se organizan por tipo en un TreeView
|
||||||
|
|
||||||
|
### 3. Sistema de Filtros
|
||||||
|
- **Filtros por tipo**: Permite mostrar/ocultar tipos específicos de objetos
|
||||||
|
- **Filtros por etiquetas**: Filtrado por etiquetas usando # (ej: #motor #bomba)
|
||||||
|
- **Filtros especiales**:
|
||||||
|
- Cloned (objetos clonados)
|
||||||
|
- Auto Created (objetos creados automáticamente)
|
||||||
|
- Enable On All Pages (objetos globales)
|
||||||
|
- Show On This Page (objetos visibles en página actual)
|
||||||
|
|
||||||
|
### 4. Operaciones de Objetos
|
||||||
|
- **Copiar (Ctrl+C)**: Copia objetos seleccionados al portapapeles interno
|
||||||
|
- **Pegar (Ctrl+V)**: Pega objetos del portapapeles a la biblioteca seleccionada
|
||||||
|
- **Eliminar**: Elimina objetos de bibliotecas (no disponible para proyecto actual)
|
||||||
|
- **Visualizar propiedades**: PropertyGrid de solo lectura para inspeccionar objetos
|
||||||
|
|
||||||
|
### 5. Gestión de Bibliotecas
|
||||||
|
- **Crear nueva biblioteca**: Crea un archivo JSON vacío como nueva biblioteca
|
||||||
|
- **Cargar automáticamente**: Las bibliotecas se cargan automáticamente al seleccionar directorios
|
||||||
|
|
||||||
|
## Cómo Usar
|
||||||
|
|
||||||
|
### Acceso
|
||||||
|
1. Haga clic en el botón **"Biblioteca"** en la barra de herramientas principal (al lado de "Assing Pages")
|
||||||
|
2. Se abrirá la ventana modal de gestión de bibliotecas
|
||||||
|
|
||||||
|
### Configurar Directorios de Biblioteca
|
||||||
|
1. En la columna izquierda "Directorios de Biblioteca", haga clic en **"Agregar"**
|
||||||
|
2. Seleccione la carpeta que contendrá sus bibliotecas de objetos
|
||||||
|
3. El directorio se agregará a la lista y se guardará automáticamente
|
||||||
|
|
||||||
|
### Navegar Bibliotecas
|
||||||
|
1. Seleccione un directorio de la lista en la columna izquierda
|
||||||
|
2. En la columna central aparecerán todas las bibliotecas (archivos JSON) encontradas
|
||||||
|
3. Seleccione una biblioteca para ver sus objetos organizados por tipo
|
||||||
|
|
||||||
|
### Filtrar Objetos
|
||||||
|
1. Use la sección "Filtros" para mostrar/ocultar tipos específicos
|
||||||
|
2. Use el campo de búsqueda para filtrar por etiquetas (ej: `#motor #conveyor`)
|
||||||
|
3. Active los filtros especiales según sea necesario
|
||||||
|
|
||||||
|
### Copiar/Pegar Objetos
|
||||||
|
1. **Para copiar**: Seleccione un objeto y presione Ctrl+C o haga clic en "Copiar"
|
||||||
|
2. **Para pegar**: Seleccione la biblioteca destino y presione Ctrl+V o haga clic en "Pegar"
|
||||||
|
3. Los objetos se copiarán con nuevos IDs únicos
|
||||||
|
|
||||||
|
### Crear Nueva Biblioteca
|
||||||
|
1. Seleccione un directorio de biblioteca
|
||||||
|
2. Haga clic en **"Nueva Biblioteca"**
|
||||||
|
3. Elija nombre y ubicación para el archivo JSON
|
||||||
|
4. Se creará una biblioteca vacía lista para usar
|
||||||
|
|
||||||
|
## Casos de Uso
|
||||||
|
|
||||||
|
### Biblioteca de Componentes Estándar
|
||||||
|
- Cree una biblioteca con motores, sensores y actuadores estándar
|
||||||
|
- Reutilice estos componentes en múltiples proyectos
|
||||||
|
- Mantenga configuraciones consistentes entre proyectos
|
||||||
|
|
||||||
|
### Plantillas de Sistemas
|
||||||
|
- Guarde sistemas completos (ej: línea de ensamblaje básica)
|
||||||
|
- Use como punto de partida para nuevos proyectos
|
||||||
|
- Facilite la estandarización de diseños
|
||||||
|
|
||||||
|
### Backup y Versioning
|
||||||
|
- Mantenga copias de objetos importantes en bibliotecas externas
|
||||||
|
- Cree versiones de componentes con diferentes configuraciones
|
||||||
|
- Facilite la colaboración entre equipos
|
||||||
|
|
||||||
|
## Estructura de Archivos
|
||||||
|
|
||||||
|
Las bibliotecas se almacenan como archivos JSON con la misma estructura que los archivos de proyecto:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ObjetosSimulables": [...],
|
||||||
|
"UnitConverter": {...},
|
||||||
|
"PLC_ConnectionData": {...}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notas Técnicas
|
||||||
|
|
||||||
|
- Los directorios de biblioteca se almacenan en `EstadoPersistente.Instance.LibraryDirectories`
|
||||||
|
- Los objetos se serializan usando Newtonsoft.Json con `TypeNameHandling.All`
|
||||||
|
- La funcionalidad es independiente del directorio de trabajo actual
|
||||||
|
- Los filtros utilizan el mismo sistema que la aplicación principal (`osVisFilter`)
|
||||||
|
|
||||||
|
## Limitaciones
|
||||||
|
|
||||||
|
- No se pueden editar objetos directamente en las bibliotecas (solo copia/pegar)
|
||||||
|
- La eliminación solo está disponible para bibliotecas externas (no proyecto actual)
|
||||||
|
- Los archivos JSON deben tener estructura válida de SimulationData
|
|
@ -24,6 +24,7 @@ using System.Text.RegularExpressions;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using CtrEditor.Serialization; // Add this line
|
using CtrEditor.Serialization; // Add this line
|
||||||
using CtrEditor.Controls; // Add this using directive
|
using CtrEditor.Controls; // Add this using directive
|
||||||
|
using CtrEditor.PopUps; // Add this using directive
|
||||||
|
|
||||||
namespace CtrEditor
|
namespace CtrEditor
|
||||||
{
|
{
|
||||||
|
@ -105,6 +106,7 @@ namespace CtrEditor
|
||||||
public ICommand TBMultiPageExtractTagsCommand { get; }
|
public ICommand TBMultiPageExtractTagsCommand { get; }
|
||||||
public ICommand TBMultiPageAnalizeCommand { get; }
|
public ICommand TBMultiPageAnalizeCommand { get; }
|
||||||
public ICommand TBMultiPageMatrixCommand { get; }
|
public ICommand TBMultiPageMatrixCommand { get; }
|
||||||
|
public ICommand TBLibraryManagerCommand { get; }
|
||||||
|
|
||||||
|
|
||||||
public ICommand TBTogglePLCConnectionCommand => new RelayCommand(() =>
|
public ICommand TBTogglePLCConnectionCommand => new RelayCommand(() =>
|
||||||
|
@ -380,6 +382,7 @@ namespace CtrEditor
|
||||||
TBAssingPagesCommand = new RelayCommand(AssingPagesCommand);
|
TBAssingPagesCommand = new RelayCommand(AssingPagesCommand);
|
||||||
TBMultiPageAnalizeCommand = new RelayCommand(MultiPageAnalizeCommand);
|
TBMultiPageAnalizeCommand = new RelayCommand(MultiPageAnalizeCommand);
|
||||||
TBMultiPageMatrixCommand = new RelayCommand(MultiPageMatrixCommand);
|
TBMultiPageMatrixCommand = new RelayCommand(MultiPageMatrixCommand);
|
||||||
|
TBLibraryManagerCommand = new RelayCommand(ShowLibraryManager);
|
||||||
|
|
||||||
stopwatch_Sim = new Stopwatch();
|
stopwatch_Sim = new Stopwatch();
|
||||||
stopwatch_Sim.Start();
|
stopwatch_Sim.Start();
|
||||||
|
@ -1158,6 +1161,15 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(SelectedItemOsList));
|
OnPropertyChanged(nameof(SelectedItemOsList));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ShowLibraryManager()
|
||||||
|
{
|
||||||
|
var libraryWindow = new PopUps.LibraryWindow();
|
||||||
|
var libraryViewModel = new PopUps.LibraryWindowViewModel(this);
|
||||||
|
libraryWindow.DataContext = libraryViewModel;
|
||||||
|
libraryWindow.Owner = MainWindow;
|
||||||
|
libraryWindow.ShowDialog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SimulationData
|
public class SimulationData
|
||||||
|
|
|
@ -251,6 +251,12 @@
|
||||||
<TextBlock Text="Assing Pages" />
|
<TextBlock Text="Assing Pages" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button Command="{Binding TBLibraryManagerCommand}" ToolTip="Gestión de Biblioteca de Objetos">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Source="Icons/app.png" Width="16" Height="16" />
|
||||||
|
<TextBlock Text="Biblioteca" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
|
||||||
</ToolBar>
|
</ToolBar>
|
||||||
</ToolBarTray>
|
</ToolBarTray>
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
<Window x:Class="CtrEditor.PopUps.LibraryWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:controls="clr-namespace:CtrEditor.Controls"
|
||||||
|
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||||
|
xmlns:local="clr-namespace:CtrEditor.PopUps"
|
||||||
|
xmlns:ObjetosSim="clr-namespace:CtrEditor.ObjetosSim"
|
||||||
|
Title="Biblioteca de Objetos Simulables" Height="700" Width="1200"
|
||||||
|
WindowStartupLocation="CenterOwner" ResizeMode="CanResize"
|
||||||
|
Loaded="Window_Loaded">
|
||||||
|
|
||||||
|
<Window.InputBindings>
|
||||||
|
<KeyBinding Key="C" Modifiers="Ctrl" Command="{Binding CopyObjectCommand}" />
|
||||||
|
<KeyBinding Key="V" Modifiers="Ctrl" Command="{Binding PasteObjectCommand}" />
|
||||||
|
<KeyBinding Key="Delete" Command="{Binding DeleteObjectCommand}" />
|
||||||
|
</Window.InputBindings>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="250" MinWidth="200" />
|
||||||
|
<ColumnDefinition Width="5" />
|
||||||
|
<ColumnDefinition Width="300" MinWidth="250" />
|
||||||
|
<ColumnDefinition Width="5" />
|
||||||
|
<ColumnDefinition Width="350" MinWidth="250" />
|
||||||
|
<ColumnDefinition Width="5" />
|
||||||
|
<ColumnDefinition Width="*" MinWidth="300" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- Primera columna: Gestión de directorios de biblioteca -->
|
||||||
|
<Grid Grid.Column="0">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Label Grid.Row="0" Content="Directorios de Biblioteca" FontWeight="Bold" />
|
||||||
|
|
||||||
|
<ListBox Grid.Row="1" Name="LibraryDirectoriesList"
|
||||||
|
ItemsSource="{Binding LibraryDirectories}"
|
||||||
|
SelectedItem="{Binding SelectedLibraryDirectory, Mode=TwoWay}"
|
||||||
|
DisplayMemberPath="DisplayName" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="5">
|
||||||
|
<Button Content="Agregar" Command="{Binding AddLibraryDirectoryCommand}" Margin="2" Padding="5,2" />
|
||||||
|
<Button Content="Eliminar" Command="{Binding RemoveLibraryDirectoryCommand}" Margin="2" Padding="5,2" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- GridSplitter 1 -->
|
||||||
|
<GridSplitter Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"
|
||||||
|
Background="LightGray" Width="5" />
|
||||||
|
|
||||||
|
<!-- Segunda columna: Bibliotecas -->
|
||||||
|
<Grid Grid.Column="2">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Label Grid.Row="0" Content="Bibliotecas" FontWeight="Bold" />
|
||||||
|
<TreeView Grid.Row="1" Name="LibrariesTreeView"
|
||||||
|
ItemsSource="{Binding Libraries}"
|
||||||
|
SelectedItemChanged="LibrariesTreeView_SelectedItemChanged">
|
||||||
|
<TreeView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding DisplayName}" />
|
||||||
|
</DataTemplate>
|
||||||
|
</TreeView.ItemTemplate>
|
||||||
|
</TreeView>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="5">
|
||||||
|
<Button Content="Nueva Biblioteca" Command="{Binding CreateNewLibraryCommand}" Margin="2" Padding="5,2" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- GridSplitter 2 -->
|
||||||
|
<GridSplitter Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Stretch"
|
||||||
|
Background="LightGray" Width="5" />
|
||||||
|
|
||||||
|
<!-- Tercera columna: Objetos -->
|
||||||
|
<Grid Grid.Column="4">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- Filtros -->
|
||||||
|
<Expander Grid.Row="0" Header="Filtros" IsExpanded="True">
|
||||||
|
<controls:osVisFilter x:Name="ObjectFilter" Margin="5"/>
|
||||||
|
</Expander>
|
||||||
|
|
||||||
|
<Label Grid.Row="1" Content="Objetos" FontWeight="Bold" />
|
||||||
|
<TreeView Grid.Row="2" Name="ObjectsTreeView"
|
||||||
|
ItemsSource="{Binding FilteredObjectsByType}"
|
||||||
|
SelectedItemChanged="ObjectsTreeView_SelectedItemChanged">
|
||||||
|
<TreeView.Resources>
|
||||||
|
<!-- Template for object type groups -->
|
||||||
|
<HierarchicalDataTemplate DataType="{x:Type local:ObjectTypeGroup}"
|
||||||
|
ItemsSource="{Binding Objects}">
|
||||||
|
<TextBlock Text="{Binding TypeName}" FontWeight="Bold" />
|
||||||
|
</HierarchicalDataTemplate>
|
||||||
|
|
||||||
|
<!-- Template for individual objects -->
|
||||||
|
<DataTemplate DataType="{x:Type ObjetosSim:osBase}">
|
||||||
|
<TextBlock Text="{Binding Nombre}">
|
||||||
|
<TextBlock.Style>
|
||||||
|
<Style TargetType="TextBlock">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Enable_On_All_Pages}" Value="True">
|
||||||
|
<Setter Property="Foreground" Value="Blue" />
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Cloned}" Value="True">
|
||||||
|
<Setter Property="Foreground" Value="Orange" />
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding AutoCreated}" Value="True">
|
||||||
|
<Setter Property="Foreground" Value="Green" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</TextBlock.Style>
|
||||||
|
</TextBlock>
|
||||||
|
</DataTemplate>
|
||||||
|
</TreeView.Resources>
|
||||||
|
</TreeView>
|
||||||
|
|
||||||
|
<!-- Botones de acción -->
|
||||||
|
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Center" Margin="5">
|
||||||
|
<Button Content="Copiar (Ctrl+C)" Command="{Binding CopyObjectCommand}" Margin="2" Padding="5,2" />
|
||||||
|
<Button Content="Pegar (Ctrl+V)" Command="{Binding PasteObjectCommand}" Margin="2" Padding="5,2" />
|
||||||
|
<Button Content="Eliminar" Command="{Binding DeleteObjectCommand}" Margin="2" Padding="5,2" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- GridSplitter 3 -->
|
||||||
|
<GridSplitter Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Stretch"
|
||||||
|
Background="LightGray" Width="5" />
|
||||||
|
|
||||||
|
<!-- Cuarta columna: Propiedades del objeto seleccionado -->
|
||||||
|
<Grid Grid.Column="6">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Label Grid.Row="0" Content="Propiedades del Objeto" FontWeight="Bold" />
|
||||||
|
|
||||||
|
<xctk:PropertyGrid Grid.Row="1"
|
||||||
|
Name="ObjectPropertyGrid"
|
||||||
|
SelectedObject="{Binding SelectedObject}"
|
||||||
|
IsReadOnly="True"
|
||||||
|
ShowSearchBox="True"
|
||||||
|
ShowSortOptions="True"
|
||||||
|
ShowTitle="False"
|
||||||
|
Margin="5" />
|
||||||
|
|
||||||
|
<!-- Botones de control -->
|
||||||
|
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="5">
|
||||||
|
<Button Content="Cerrar" IsCancel="True" Click="CloseButton_Click"
|
||||||
|
Margin="2" Padding="15,5" MinWidth="75" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
|
@ -0,0 +1,61 @@
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using CtrEditor.ObjetosSim;
|
||||||
|
|
||||||
|
namespace CtrEditor.PopUps
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for LibraryWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class LibraryWindow : Window
|
||||||
|
{
|
||||||
|
public LibraryWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LibrariesTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||||
|
{
|
||||||
|
if (DataContext is LibraryWindowViewModel viewModel)
|
||||||
|
{
|
||||||
|
viewModel.SelectedLibrary = e.NewValue as LibraryItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ObjectsTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
||||||
|
{
|
||||||
|
if (DataContext is LibraryWindowViewModel viewModel)
|
||||||
|
{
|
||||||
|
// Check if the selected item is an osBase object or an ObjectTypeGroup
|
||||||
|
if (e.NewValue is osBase selectedObject)
|
||||||
|
{
|
||||||
|
viewModel.SelectedObject = selectedObject;
|
||||||
|
}
|
||||||
|
else if (e.NewValue is ObjectTypeGroup typeGroup)
|
||||||
|
{
|
||||||
|
// If a type group is selected, clear the selected object
|
||||||
|
viewModel.SelectedObject = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
viewModel.SelectedObject = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
this.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// Setup filter events after window is loaded
|
||||||
|
if (DataContext is LibraryWindowViewModel viewModel)
|
||||||
|
{
|
||||||
|
ObjectFilter.FilterChanged += (s, args) => viewModel.OnFilterChanged(args.FilterViewModel);
|
||||||
|
viewModel.SetObjectFilter(ObjectFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,581 @@
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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; }
|
||||||
|
|
||||||
|
public LibraryWindowViewModel(MainViewModel mainViewModel)
|
||||||
|
{
|
||||||
|
_mainViewModel = mainViewModel;
|
||||||
|
|
||||||
|
LibraryDirectories = new ObservableCollection<LibraryDirectoryItem>();
|
||||||
|
Libraries = new ObservableCollection<LibraryItem>();
|
||||||
|
FilteredObjectsByType = new ObservableCollection<ObjectTypeGroup>();
|
||||||
|
|
||||||
|
// Initialize commands
|
||||||
|
AddLibraryDirectoryCommand = new RelayCommand(AddLibraryDirectory);
|
||||||
|
RemoveLibraryDirectoryCommand = new RelayCommand(RemoveLibraryDirectory, () => SelectedLibraryDirectory != null);
|
||||||
|
CopyObjectCommand = new RelayCommand(CopyObject, () => SelectedObject != null);
|
||||||
|
PasteObjectCommand = new RelayCommand(PasteObject, () => SelectedLibrary != null && _clipboardObjects.Any());
|
||||||
|
DeleteObjectCommand = new RelayCommand(DeleteObject, () => SelectedObject != null && SelectedLibrary != null && !SelectedLibrary.IsCurrentProject);
|
||||||
|
CreateNewLibraryCommand = new RelayCommand(CreateNewLibrary, () => SelectedLibraryDirectory != null);
|
||||||
|
|
||||||
|
LoadLibraryDirectories();
|
||||||
|
RefreshLibraries();
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
IsCurrentProject = true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add saved library directories
|
||||||
|
foreach (var directory in EstadoPersistente.Instance.LibraryDirectories)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
LibraryDirectories.Add(new LibraryDirectoryItem
|
||||||
|
{
|
||||||
|
Path = directory,
|
||||||
|
DisplayName = Path.GetFileName(directory),
|
||||||
|
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);
|
||||||
|
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();
|
||||||
|
|
||||||
|
if (SelectedLibrary == null) return;
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
{
|
||||||
|
if (SelectedObject != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_clipboardObjects.Clear();
|
||||||
|
|
||||||
|
// Prepare object for serialization
|
||||||
|
SelectedObject.SalvarDatosNoSerializables();
|
||||||
|
|
||||||
|
var settings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
Formatting = Formatting.Indented,
|
||||||
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
|
TypeNameHandling = TypeNameHandling.All
|
||||||
|
};
|
||||||
|
|
||||||
|
// Serialize and deserialize to create a deep copy
|
||||||
|
var serializedData = JsonConvert.SerializeObject(SelectedObject, settings);
|
||||||
|
var copiedObject = JsonConvert.DeserializeObject<osBase>(serializedData, settings);
|
||||||
|
|
||||||
|
if (copiedObject != null)
|
||||||
|
{
|
||||||
|
_clipboardObjects.Add(copiedObject);
|
||||||
|
MessageBox.Show("Objeto copiado al portapapeles.", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore object state
|
||||||
|
SelectedObject.RestaurarDatosNoSerializables();
|
||||||
|
CommandManager.InvalidateRequerySuggested();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error al copiar objeto: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PasteObject()
|
||||||
|
{
|
||||||
|
if (SelectedLibrary != null && _clipboardObjects.Any())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var objToPaste in _clipboardObjects)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefreshLibraries();
|
||||||
|
LoadObjectsFromLibrary();
|
||||||
|
MessageBox.Show($"{_clipboardObjects.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeleteObject()
|
||||||
|
{
|
||||||
|
if (SelectedObject != null && SelectedLibrary != null && !SelectedLibrary.IsCurrentProject)
|
||||||
|
{
|
||||||
|
var result = MessageBox.Show(
|
||||||
|
$"¿Está seguro de que desea eliminar el objeto '{SelectedObject.Nombre}'?",
|
||||||
|
"Confirmar eliminación",
|
||||||
|
MessageBoxButton.YesNo,
|
||||||
|
MessageBoxImage.Question);
|
||||||
|
|
||||||
|
if (result == MessageBoxResult.Yes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SelectedLibrary.Objects.Remove(SelectedObject);
|
||||||
|
SaveLibraryToFile(SelectedLibrary);
|
||||||
|
LoadObjectsFromLibrary();
|
||||||
|
SelectedObject = null;
|
||||||
|
MessageBox.Show("Objeto eliminado.", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error al eliminar objeto: {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 simulationData = new SimulationData
|
||||||
|
{
|
||||||
|
ObjetosSimulables = new ObservableCollection<osBase>(library.Objects),
|
||||||
|
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(simulationData, settings);
|
||||||
|
File.WriteAllText(library.FilePath, json);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error al guardar biblioteca: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -42,6 +42,8 @@ namespace CtrEditor
|
||||||
|
|
||||||
public List<ColumnPairMapping> ColumnPairs { get; set; } = new List<ColumnPairMapping>();
|
public List<ColumnPairMapping> ColumnPairs { get; set; } = new List<ColumnPairMapping>();
|
||||||
|
|
||||||
|
public List<string> LibraryDirectories { get; set; } = new List<string>();
|
||||||
|
|
||||||
// Propiedad pública con get y set para controlar el acceso a _strDirectorioTrabajo
|
// Propiedad pública con get y set para controlar el acceso a _strDirectorioTrabajo
|
||||||
public string directorio
|
public string directorio
|
||||||
{
|
{
|
||||||
|
@ -57,15 +59,17 @@ namespace CtrEditor
|
||||||
|
|
||||||
public int newid
|
public int newid
|
||||||
{
|
{
|
||||||
get {
|
get
|
||||||
|
{
|
||||||
_id++;
|
_id++;
|
||||||
return _id; }
|
return _id;
|
||||||
|
}
|
||||||
set { _id = value; }
|
set { _id = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor privado para evitar la instanciación externa
|
// Constructor privado para evitar la instanciación externa
|
||||||
public EstadoPersistente()
|
public EstadoPersistente()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private EstadoPersistente Inizializar()
|
private EstadoPersistente Inizializar()
|
||||||
|
@ -111,9 +115,10 @@ namespace CtrEditor
|
||||||
{
|
{
|
||||||
string json = File.ReadAllText(_filePath);
|
string json = File.ReadAllText(_filePath);
|
||||||
return JsonSerializer.Deserialize<EstadoPersistente>(json);
|
return JsonSerializer.Deserialize<EstadoPersistente>(json);
|
||||||
}
|
}
|
||||||
return new EstadoPersistente().Inizializar(); // Devuelve una nueva instancia si no existe el archivo
|
return new EstadoPersistente().Inizializar(); // Devuelve una nueva instancia si no existe el archivo
|
||||||
} catch
|
}
|
||||||
|
catch
|
||||||
{
|
{
|
||||||
return new EstadoPersistente().Inizializar(); // Devuelve una nueva instancia si no existe el archivo
|
return new EstadoPersistente().Inizializar(); // Devuelve una nueva instancia si no existe el archivo
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue