Creada las opciones de datos locales para las posiciones de los objetos globales
This commit is contained in:
parent
211c518be6
commit
98c5f2e6ff
|
@ -1011,11 +1011,15 @@ namespace CtrEditor
|
|||
_objectManager.UpdateSelectionVisuals();
|
||||
}
|
||||
}
|
||||
|
||||
public class SimulationData
|
||||
{
|
||||
public ObservableCollection<osBase>? ObjetosSimulables { get; set; }
|
||||
public UnitConverter? UnitConverter { get; set; }
|
||||
public PLCViewModel? PLC_ConnectionData { get; set; }
|
||||
|
||||
// Nueva propiedad para almacenar los datos locales de objetos globales
|
||||
public ObservableCollection<DatosLocales>? DatosLocalesObjetos { get; set; }
|
||||
}
|
||||
|
||||
public class TipoSimulable
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CtrEditor.FuncionesBase;
|
||||
using CtrEditor.Serialization;
|
||||
using CtrEditor.Simulacion;
|
||||
using LibS7Adv;
|
||||
using nkast.Aether.Physics2D.Common;
|
||||
|
@ -449,10 +450,151 @@ namespace CtrEditor.ObjetosSim
|
|||
[property: Category("Layout:")]
|
||||
private bool enable_On_All_Pages;
|
||||
|
||||
|
||||
partial void OnEnable_On_All_PagesChanged(bool value)
|
||||
{
|
||||
// Si se está desactivando el modo global
|
||||
if (!value)
|
||||
{
|
||||
// Limpiar los datos locales
|
||||
_datosLocales = null;
|
||||
_snapshotGlobal = null;
|
||||
|
||||
// Desactivar datos locales
|
||||
Enable_Local_Data = false;
|
||||
|
||||
Show_On_This_Page = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Local Data for Global Objects
|
||||
[NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
|
||||
[ObservableProperty]
|
||||
[property: Description("Enable local data of this global Object on all pages.")]
|
||||
[property: Category("Layout:")]
|
||||
private bool enable_Local_Data_for_All;
|
||||
|
||||
partial void OnEnable_Local_Data_for_AllChanged(bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
// Activar datos locales
|
||||
Enable_Local_Data = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Local Data for Global Objects
|
||||
[NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
|
||||
[ObservableProperty]
|
||||
[property: Description("Enable local data of this global Object on this page.")]
|
||||
[property: Category("Layout:")]
|
||||
[property: JsonIgnore]
|
||||
private bool enable_Local_Data;
|
||||
|
||||
// Añadir estas propiedades y métodos a la clase osBase
|
||||
|
||||
[JsonIgnore]
|
||||
private DatosLocales _snapshotGlobal;
|
||||
|
||||
[JsonIgnore]
|
||||
private DatosLocales _datosLocales;
|
||||
|
||||
/// <summary>
|
||||
/// Crea un snapshot de los datos globales actuales
|
||||
/// </summary>
|
||||
public void CrearSnapshotGlobal()
|
||||
{
|
||||
if (Enable_On_All_Pages) // No verificamos Enable_Local_Data aquí
|
||||
{
|
||||
_snapshotGlobal = new DatosLocales(Id);
|
||||
_snapshotGlobal.CopiarDesdeObjeto(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restaura los datos globales desde el snapshot
|
||||
/// </summary>
|
||||
public void RestaurarDesdeSnapshotGlobal()
|
||||
{
|
||||
if (Enable_On_All_Pages && Enable_Local_Data && _snapshotGlobal != null)
|
||||
{
|
||||
// Guarda los datos locales actuales antes de restaurar
|
||||
if (_datosLocales == null)
|
||||
{
|
||||
_datosLocales = new DatosLocales(Id);
|
||||
}
|
||||
_datosLocales.CopiarDesdeObjeto(this);
|
||||
|
||||
// Restaura desde el snapshot
|
||||
_snapshotGlobal.AplicarAObjeto(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restaura los datos locales después de guardar
|
||||
/// </summary>
|
||||
public void RestaurarDatosLocales()
|
||||
{
|
||||
if (Enable_On_All_Pages && Enable_Local_Data && _datosLocales != null)
|
||||
{
|
||||
_datosLocales.AplicarAObjeto(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtiene los datos locales del objeto
|
||||
/// </summary>
|
||||
public DatosLocales ObtenerDatosLocales()
|
||||
{
|
||||
if (!Enable_On_All_Pages)
|
||||
return null;
|
||||
|
||||
DatosLocales datos = new DatosLocales(Id);
|
||||
datos.CopiarDesdeObjeto(this);
|
||||
return datos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aplica datos locales al objeto
|
||||
/// </summary>
|
||||
public void AplicarDatosLocales(DatosLocales datos)
|
||||
{
|
||||
if (Enable_On_All_Pages && datos != null && datos.Id_GlobalObject.Value == Id.Value)
|
||||
{
|
||||
Enable_Local_Data = true; // Activar datos locales si se encuentran
|
||||
|
||||
datos.AplicarAObjeto(this);
|
||||
|
||||
// Actualiza la visualización
|
||||
ActualizarLeftTop();
|
||||
OnAnchoChanged(Ancho);
|
||||
OnAltoChanged(Alto);
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnEnable_Local_DataChanged(bool value)
|
||||
{
|
||||
// Si se está desactivando los datos locales y teníamos un snapshot
|
||||
if (!value && _snapshotGlobal != null && Enable_On_All_Pages)
|
||||
{
|
||||
// Restaurar los valores globales
|
||||
_snapshotGlobal.AplicarAObjeto(this);
|
||||
|
||||
// Limpiar los datos locales
|
||||
_datosLocales = null;
|
||||
_snapshotGlobal = null;
|
||||
|
||||
// Actualizar la visualización
|
||||
ActualizarLeftTop();
|
||||
OnAnchoChanged(Ancho);
|
||||
OnAltoChanged(Alto);
|
||||
}
|
||||
// Si se está activando, crear el snapshot
|
||||
else if (value && Enable_On_All_Pages)
|
||||
{
|
||||
CrearSnapshotGlobal();
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
using CtrEditor.ObjetosSim;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CtrEditor.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Almacena datos locales para un objeto global
|
||||
/// </summary>
|
||||
public class DatosLocales
|
||||
{
|
||||
/// <summary>
|
||||
/// ID del objeto global al que pertenecen estos datos locales
|
||||
/// </summary>
|
||||
public UniqueId Id_GlobalObject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Posición vertical local
|
||||
/// </summary>
|
||||
public float? Top { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Posición horizontal local
|
||||
/// </summary>
|
||||
public float? Left { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ancho local
|
||||
/// </summary>
|
||||
public float? Ancho { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Alto local
|
||||
/// </summary>
|
||||
public float? Alto { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Diccionario para almacenar propiedades dinámicas adicionales
|
||||
/// </summary>
|
||||
public Dictionary<string, object> PropiedadesAdicionales { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor por defecto necesario para deserialización
|
||||
/// </summary>
|
||||
public DatosLocales()
|
||||
{
|
||||
PropiedadesAdicionales = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor con ID del objeto global
|
||||
/// </summary>
|
||||
public DatosLocales(UniqueId idGlobalObject)
|
||||
{
|
||||
Id_GlobalObject = idGlobalObject;
|
||||
PropiedadesAdicionales = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copia los datos relevantes desde un objeto global
|
||||
/// </summary>
|
||||
public void CopiarDesdeObjeto(osBase objeto)
|
||||
{
|
||||
if (objeto == null) return;
|
||||
|
||||
Id_GlobalObject = objeto.Id;
|
||||
Top = objeto.Top;
|
||||
Left = objeto.Left;
|
||||
Ancho = objeto.Ancho;
|
||||
Alto = objeto.Alto;
|
||||
|
||||
// Aquí puedes añadir más propiedades si es necesario
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aplica los datos locales al objeto global
|
||||
/// </summary>
|
||||
public void AplicarAObjeto(osBase objeto)
|
||||
{
|
||||
if (objeto == null || objeto.Id.Value != Id_GlobalObject.Value) return;
|
||||
|
||||
if (Left.HasValue) objeto.Left = Left.Value;
|
||||
if (Top.HasValue) objeto.Top = Top.Value;
|
||||
if (Ancho.HasValue) objeto.Ancho = Ancho.Value;
|
||||
if (Alto.HasValue) objeto.Alto = Alto.Value;
|
||||
|
||||
// Aquí puedes aplicar más propiedades si es necesario
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
using CtrEditor.ObjetosSim;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace CtrEditor.Serialization
|
||||
{
|
||||
/// <summary>
|
||||
/// Clase para gestionar qué propiedades deben ser locales en objetos globales
|
||||
/// </summary>
|
||||
public static class PropiedadesLocalesManager
|
||||
{
|
||||
// Definición de propiedades por defecto que se guardan localmente para todos los objetos
|
||||
private static readonly List<string> PropiedadesPorDefecto = new List<string>
|
||||
{
|
||||
"Left", "Top", "Ancho", "Alto"
|
||||
};
|
||||
|
||||
// Diccionario que contiene conjuntos de propiedades locales por tipo de objeto
|
||||
private static readonly Dictionary<Type, List<string>> PropiedadesPorTipo = new Dictionary<Type, List<string>>();
|
||||
|
||||
/// <summary>
|
||||
/// Registra un conjunto de propiedades locales para un tipo específico de objeto
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Tipo de objeto (debe heredar de osBase)</typeparam>
|
||||
/// <param name="propiedades">Lista de nombres de propiedades a registrar como locales</param>
|
||||
public static void RegistrarPropiedadesParaTipo<T>(List<string> propiedades) where T : osBase
|
||||
{
|
||||
PropiedadesPorTipo[typeof(T)] = propiedades;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtiene la lista de propiedades que deben ser locales para un objeto concreto
|
||||
/// </summary>
|
||||
/// <param name="objeto">Objeto del que obtener las propiedades locales</param>
|
||||
/// <returns>Lista de nombres de propiedades</returns>
|
||||
public static List<string> ObtenerPropiedadesLocales(osBase objeto)
|
||||
{
|
||||
var resultado = new List<string>(PropiedadesPorDefecto);
|
||||
|
||||
if (objeto != null && PropiedadesPorTipo.TryGetValue(objeto.GetType(), out var propiedadesExtra))
|
||||
{
|
||||
foreach (var prop in propiedadesExtra)
|
||||
{
|
||||
if (!resultado.Contains(prop))
|
||||
resultado.Add(prop);
|
||||
}
|
||||
}
|
||||
|
||||
return resultado;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crea un objeto dinámico que permite acceder a las propiedades locales de un objeto
|
||||
/// </summary>
|
||||
/// <param name="objeto">Objeto del que crear una vista dinámica</param>
|
||||
/// <returns>Objeto dinámico con propiedades locales</returns>
|
||||
public static dynamic CrearAccesoDinamico(osBase objeto)
|
||||
{
|
||||
return new PropiedadesLocalesDinamicas(objeto);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clase interna que implementa un acceso dinámico a propiedades
|
||||
/// </summary>
|
||||
private class PropiedadesLocalesDinamicas : DynamicObject
|
||||
{
|
||||
private readonly osBase _objeto;
|
||||
private readonly List<string> _propiedadesLocales;
|
||||
|
||||
public PropiedadesLocalesDinamicas(osBase objeto)
|
||||
{
|
||||
_objeto = objeto;
|
||||
_propiedadesLocales = ObtenerPropiedadesLocales(objeto);
|
||||
}
|
||||
|
||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||
{
|
||||
var nombrePropiedad = binder.Name;
|
||||
|
||||
if (_propiedadesLocales.Contains(nombrePropiedad))
|
||||
{
|
||||
var propInfo = _objeto.GetType().GetProperty(nombrePropiedad);
|
||||
if (propInfo != null && propInfo.CanRead)
|
||||
{
|
||||
result = propInfo.GetValue(_objeto);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||
{
|
||||
var nombrePropiedad = binder.Name;
|
||||
|
||||
if (_propiedadesLocales.Contains(nombrePropiedad))
|
||||
{
|
||||
var propInfo = _objeto.GetType().GetProperty(nombrePropiedad);
|
||||
if (propInfo != null && propInfo.CanWrite)
|
||||
{
|
||||
try
|
||||
{
|
||||
var valorConvertido = Convert.ChangeType(value, propInfo.PropertyType);
|
||||
propInfo.SetValue(_objeto, valorConvertido);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Silenciar errores de conversión
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetDynamicMemberNames()
|
||||
{
|
||||
return _propiedadesLocales;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ using System.Collections.ObjectModel;
|
|||
using System.Windows;
|
||||
using CtrEditor.Simulacion;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace CtrEditor.Serialization
|
||||
{
|
||||
|
@ -30,36 +31,68 @@ namespace CtrEditor.Serialization
|
|||
|
||||
var objetosSimulables = new ObservableCollection<osBase>();
|
||||
var objetosSimulablesAllPages = new ObservableCollection<osBase>();
|
||||
var datosLocalesObjetos = new ObservableCollection<DatosLocales>();
|
||||
|
||||
// Paso 1: Preparar objetos globales y locales
|
||||
foreach (var obj in _mainViewModel.ObjetosSimulables)
|
||||
{
|
||||
// Para objetos globales con datos locales
|
||||
if (obj.Enable_On_All_Pages && obj.Enable_Local_Data)
|
||||
{
|
||||
// Guarda los datos locales independientemente de Show_On_This_Page
|
||||
var datosLocales = obj.ObtenerDatosLocales();
|
||||
if (datosLocales != null)
|
||||
{
|
||||
datosLocalesObjetos.Add(datosLocales);
|
||||
}
|
||||
|
||||
// Restaura datos globales para guardar
|
||||
obj.RestaurarDesdeSnapshotGlobal();
|
||||
}
|
||||
|
||||
// Prepara para serialización
|
||||
obj.SalvarDatosNoSerializables();
|
||||
|
||||
// Separa objetos globales y locales
|
||||
if (!obj.Enable_On_All_Pages)
|
||||
{
|
||||
objetosSimulables.Add(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
objetosSimulablesAllPages.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
// Save current page objects
|
||||
// Paso 2: Guardar datos de la página actual
|
||||
var dataToSerialize = new SimulationData
|
||||
{
|
||||
ObjetosSimulables = objetosSimulables,
|
||||
ObjetosSimulables = objetosSimulables.Count > 0 ? objetosSimulables : null,
|
||||
UnitConverter = PixelToMeter.Instance.calc,
|
||||
PLC_ConnectionData = _mainViewModel.PLCViewModel
|
||||
PLC_ConnectionData = _mainViewModel.PLCViewModel,
|
||||
DatosLocalesObjetos = datosLocalesObjetos.Count > 0 ? datosLocalesObjetos : null
|
||||
};
|
||||
|
||||
var path = _datosDeTrabajo.ObtenerPathImagenConExtension(selectedImage, ".json");
|
||||
if (path != null)
|
||||
SerializeAndSave(dataToSerialize, path);
|
||||
|
||||
// Save all pages objects
|
||||
// Paso 3: Guardar objetos globales
|
||||
path = _datosDeTrabajo.ObtenerPathAllPages(".json");
|
||||
if (path != null)
|
||||
SerializeAndSave(objetosSimulablesAllPages, path);
|
||||
|
||||
// Restore original properties
|
||||
// Paso 4: Restaurar estado para seguir trabajando
|
||||
foreach (var obj in _mainViewModel.ObjetosSimulables)
|
||||
{
|
||||
obj.RestaurarDatosNoSerializables();
|
||||
|
||||
// Para objetos globales, restaura los datos locales
|
||||
if (obj.Enable_On_All_Pages && obj.Enable_Local_Data)
|
||||
{
|
||||
obj.RestaurarDatosLocales();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,10 +108,47 @@ namespace CtrEditor.Serialization
|
|||
if (selectedImage != null)
|
||||
{
|
||||
var settings = GetJsonSerializerSettings();
|
||||
LoadCurrentPageState(selectedImage, settings);
|
||||
|
||||
// Paso 1: Cargar objetos globales
|
||||
LoadAllPagesState(settings);
|
||||
|
||||
// Create UserControls for all loaded objects
|
||||
// Paso 2: Cargar datos de la página actual
|
||||
var simulationData = LoadCurrentPageState(selectedImage, settings);
|
||||
|
||||
// Paso 3: Crear snapshots de los objetos globales
|
||||
// Nota: No filtramos por Enable_Local_Data aquí ya que se establecerá después
|
||||
foreach (var obj in _mainViewModel.ObjetosSimulables)
|
||||
{
|
||||
if (obj.Enable_On_All_Pages)
|
||||
{
|
||||
obj.CrearSnapshotGlobal();
|
||||
}
|
||||
}
|
||||
|
||||
// Paso 4: Aplicar datos locales a objetos globales
|
||||
if (simulationData?.DatosLocalesObjetos != null)
|
||||
{
|
||||
// Primero, desactivar Enable_Local_Data en todos los objetos globales
|
||||
foreach (var obj in _mainViewModel.ObjetosSimulables.Where(o => o.Enable_On_All_Pages))
|
||||
{
|
||||
obj.Enable_Local_Data = false;
|
||||
}
|
||||
|
||||
// Luego aplicar los datos locales, esto activará Enable_Local_Data automáticamente
|
||||
foreach (var datosLocales in simulationData.DatosLocalesObjetos)
|
||||
{
|
||||
var objetoGlobal = _mainViewModel.ObjetosSimulables.FirstOrDefault(
|
||||
o => o.Enable_On_All_Pages &&
|
||||
o.Id.Value == datosLocales.Id_GlobalObject.Value);
|
||||
|
||||
if (objetoGlobal != null)
|
||||
{
|
||||
objetoGlobal.AplicarDatosLocales(datosLocales);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Paso 5: Crear controles visuales
|
||||
foreach (var objetoSimulable in _mainViewModel.ObjetosSimulables)
|
||||
{
|
||||
if (objetoSimulable != null)
|
||||
|
@ -95,17 +165,21 @@ namespace CtrEditor.Serialization
|
|||
}
|
||||
}
|
||||
|
||||
private void LoadCurrentPageState(string selectedImage, JsonSerializerSettings settings)
|
||||
private SimulationData LoadCurrentPageState(string selectedImage, JsonSerializerSettings settings)
|
||||
{
|
||||
SimulationData simulationData = null;
|
||||
string jsonPath = _datosDeTrabajo.ObtenerPathImagenConExtension(selectedImage, ".json");
|
||||
if (File.Exists(jsonPath))
|
||||
{
|
||||
string jsonString = File.ReadAllText(jsonPath);
|
||||
var simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings);
|
||||
simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings);
|
||||
if (simulationData != null)
|
||||
{
|
||||
if (simulationData.ObjetosSimulables is not null)
|
||||
_mainViewModel.ObjetosSimulables = simulationData.ObjetosSimulables;
|
||||
{
|
||||
foreach (var obj in simulationData.ObjetosSimulables)
|
||||
_mainViewModel.ObjetosSimulables.Add(obj);
|
||||
}
|
||||
|
||||
if (simulationData.PLC_ConnectionData is not null)
|
||||
_mainViewModel.PLCViewModel = simulationData.PLC_ConnectionData;
|
||||
|
@ -115,6 +189,7 @@ namespace CtrEditor.Serialization
|
|||
PixelToMeter.Instance.calc = simulationData.UnitConverter;
|
||||
}
|
||||
}
|
||||
return simulationData;
|
||||
}
|
||||
|
||||
private void LoadAllPagesState(JsonSerializerSettings settings)
|
||||
|
@ -158,5 +233,4 @@ namespace CtrEditor.Serialization
|
|||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue