CtrEditor/MainViewModel.cs

906 lines
35 KiB
C#
Raw Normal View History

2024-05-23 14:56:14 -03:00
using System.ComponentModel;
2024-05-02 11:06:45 -03:00
using System.Runtime.CompilerServices;
using System.Windows.Controls;
using System.Windows.Input;
using Ookii.Dialogs.Wpf;
using System.Collections.ObjectModel;
2024-05-03 05:13:25 -03:00
using System.Windows.Threading;
using CtrEditor.ObjetosSim;
using CtrEditor.Siemens;
using System.IO;
using Newtonsoft.Json;
using System.Windows;
using CtrEditor.Simulacion;
using System.Diagnostics;
using System.Reflection;
2024-05-25 07:53:34 -03:00
using CommunityToolkit.Mvvm.ComponentModel;
2024-06-02 04:13:01 -03:00
using Xceed.Wpf.Toolkit.PropertyGrid;
2024-06-04 12:33:00 -03:00
using System.Text.RegularExpressions;
using System.Windows.Data;
using CtrEditor.ObjetosSim.Extraccion_Datos;
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using CommunityToolkit.Mvvm.Input;
using CtrEditor.PopUps;
2024-05-02 11:06:45 -03:00
namespace CtrEditor
{
2024-05-03 05:13:25 -03:00
2024-05-25 07:53:34 -03:00
public partial class MainViewModel : ObservableObject
2024-05-02 11:06:45 -03:00
{
2024-05-25 07:53:34 -03:00
public Stopwatch stopwatch_Sim;
private double stopwatch_SimPLC_last;
private double stopwatch_SimModel_last;
private float TiempoDesdeStartSimulacion;
private bool Debug_SimulacionCreado = false;
2024-05-16 13:45:14 -03:00
public SimulationManagerFP simulationManager = new SimulationManagerFP();
2024-05-06 12:31:45 -03:00
2024-05-03 05:13:25 -03:00
private readonly DispatcherTimer _timerSimulacion;
2024-05-31 14:25:24 -03:00
public Canvas MainCanvas;
2024-05-25 07:53:34 -03:00
[ObservableProperty]
private DatosDeTrabajo datosDeTrabajo;
[ObservableProperty]
private ObservableCollection<string> listaImagenes; // Publicación de las claves del diccionario
[ObservableProperty]
public ObservableCollection<TipoSimulable> listaOsBase;
public ICommand StartSimulationCommand { get; }
public ICommand StopSimulationCommand { get; }
public ICommand ItemDoubleClickCommand { get; private set; }
2024-05-15 06:20:09 -03:00
public ICommand TBStartSimulationCommand { get; }
public ICommand TBStopSimulationCommand { get; }
public ICommand TBSaveCommand { get; }
public ICommand TBConnectPLCCommand { get; }
public ICommand TBDisconnectPLCCommand { get; }
public ICommand TBExtractTagsCommand { get; }
2024-05-02 11:06:45 -03:00
public ICommand TBEliminarUserControlCommand { get; }
2024-05-20 09:05:34 -03:00
public ICommand TBDuplicarUserControlCommand { get; }
public ICommand OpenWorkDirectoryCommand { get; }
public ICommand TBEliminarTodosCommand { get; }
public ICommand TBEliminarAutoCreatedCommand { get; }
public ICommand TBEliminarClonedCommand { get; }
public ICommand TBAssingPagesCommand { get; }
public ICommand TBMultiPageExtractTagsCommand { get; }
public ICommand TBMultiPageAnalizeCommand { get; }
// Evento que se dispara cuando se selecciona una nueva imagen
public event EventHandler<string> ImageSelected;
2024-05-03 05:13:25 -03:00
public event EventHandler<TickSimulacionEventArgs> TickSimulacion;
2024-05-02 11:06:45 -03:00
// Propiedades
private bool habilitarEliminarUserControl;
2024-05-25 07:53:34 -03:00
private MainWindow mainWindow;
public MainWindow MainWindow { get => mainWindow; set => mainWindow = value; }
2024-05-25 07:53:34 -03:00
[ObservableProperty]
private float canvasLeft;
[ObservableProperty]
private float canvasTop;
[ObservableProperty]
private bool isSimulationRunning;
partial void OnIsSimulationRunningChanged(bool value)
{
2024-05-25 07:53:34 -03:00
CommandManager.InvalidateRequerySuggested(); // Notificar que el estado de los comandos ha cambiado
}
2024-05-25 07:53:34 -03:00
[ObservableProperty]
private bool isConnected;
partial void OnIsConnectedChanged(bool value)
{
2024-05-25 07:53:34 -03:00
CommandManager.InvalidateRequerySuggested();
}
public string directorioTrabajo
{
get => EstadoPersistente.Instance.directorio;
set
{
if (value != null)
{
EstadoPersistente.Instance.directorio = value; // Actualizar el estado persistente
EstadoPersistente.Instance.GuardarEstado(); // Guardar el estado actualizado
2024-05-25 07:53:34 -03:00
DatosDeTrabajo.CargarImagenes();
ListaImagenes = new ObservableCollection<string>(DatosDeTrabajo.Imagenes.Keys); // Actualizar claves
SelectedImage = null;
2024-06-10 06:07:25 -03:00
if (EstadoPersistente.Instance.imagen != null && EstadoPersistente.Instance.imagen.Length > 0)
SelectedImage = EstadoPersistente.Instance.imagen;
else if (ListaImagenes.FirstOrDefault() != null)
2024-05-25 07:53:34 -03:00
SelectedImage = ListaImagenes.FirstOrDefault();
OnPropertyChanged(nameof(directorioTrabajo)); // Notificar el cambio de propiedad
2024-05-25 07:53:34 -03:00
OnPropertyChanged(nameof(ListaImagenes)); // Notificar que la lista de imágenes ha cambiado
}
}
}
2024-05-25 07:53:34 -03:00
[ObservableProperty]
private PLCViewModel pLCViewModel;
2024-05-25 07:53:34 -03:00
[ObservableProperty]
private string selectedImage;
2024-05-25 07:53:34 -03:00
partial void OnSelectedImageChanged(string value)
{
2024-05-25 07:53:34 -03:00
if (value != null)
{
2024-05-25 07:53:34 -03:00
StopSimulation();
// SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
ImageSelected?.Invoke(this, datosDeTrabajo.Imagenes[value]); // Dispara el evento con la nueva ruta de imagen
LoadStateObjetosSimulables();
EstadoPersistente.Instance.imagen = value;
EstadoPersistente.Instance.GuardarEstado();
}
}
2024-05-25 07:53:34 -03:00
[ObservableProperty]
private osBase selectedItemOsList;
2024-05-25 07:53:34 -03:00
partial void OnSelectedItemOsListChanged(osBase value)
{
2024-05-25 07:53:34 -03:00
if (value != null)
habilitarEliminarUserControl = true;
else
habilitarEliminarUserControl = false;
}
2024-05-25 07:53:34 -03:00
[ObservableProperty]
private TipoSimulable selectedItem;
public ICollectionView ObjetosSimulablesFiltered { get; }
public ICollectionView ObjetosSimulablesAllPages { get; }
2024-05-25 07:53:34 -03:00
[ObservableProperty]
public ObservableCollection<osBase> objetosSimulables;
2024-05-27 05:34:20 -03:00
//
// Constructor
//
2024-05-02 11:06:45 -03:00
public MainViewModel()
{
OpenWorkDirectoryCommand = new RelayCommand(OpenWorkDirectory);
datosDeTrabajo = new DatosDeTrabajo();
2024-05-25 07:53:34 -03:00
ObjetosSimulables = new ObservableCollection<osBase>();
2024-05-25 07:53:34 -03:00
ListaOsBase = new ObservableCollection<TipoSimulable>();
// Inicializa el PLCViewModel
2024-05-25 07:53:34 -03:00
PLCViewModel = new PLCViewModel();
PLCViewModel.RefreshEvent += OnRefreshEvent;
InitializeTipoSimulableList();
ItemDoubleClickCommand = new ParameterizedRelayCommand(ExecuteDoubleClick);
2024-05-03 05:13:25 -03:00
_timerSimulacion = new DispatcherTimer();
_timerSimulacion.Interval = TimeSpan.FromMilliseconds(1); // ajusta el intervalo según sea necesario
2024-05-03 05:13:25 -03:00
_timerSimulacion.Tick += OnTickSimulacion;
StartSimulationCommand = new RelayCommand(StartSimulation);
StopSimulationCommand = new RelayCommand(StopSimulation);
2024-05-15 06:20:09 -03:00
TBStartSimulationCommand = new RelayCommand(StartSimulation, () => !IsSimulationRunning);
TBStopSimulationCommand = new RelayCommand(StopSimulation, () => IsSimulationRunning);
TBSaveCommand = new RelayCommand(Save);
TBConnectPLCCommand = new RelayCommand(ConnectPLC, () => !IsConnected);
TBDisconnectPLCCommand = new RelayCommand(DisconnectPLC, () => IsConnected);
TBEliminarUserControlCommand = new RelayCommand(EliminarUserControl, () => habilitarEliminarUserControl);
2024-05-20 09:05:34 -03:00
TBDuplicarUserControlCommand = new RelayCommand(DuplicarUserControl, () => habilitarEliminarUserControl);
TBExtractTagsCommand = new RelayCommand(ExtraerTags);
TBEliminarTodosCommand = new RelayCommand(EliminarTodosCommand);
TBEliminarAutoCreatedCommand = new RelayCommand(EliminarAutoCreatedCommand);
TBEliminarClonedCommand = new RelayCommand(EliminarClonedCommand);
TBAssingPagesCommand = new RelayCommand(AssingPagesCommand);
TBMultiPageExtractTagsCommand = new RelayCommand(MultiPageExtractTagsCommand);
TBMultiPageAnalizeCommand = new RelayCommand(MultiPageAnalizeCommand);
2024-05-25 07:53:34 -03:00
stopwatch_Sim = new Stopwatch();
stopwatch_Sim.Start();
}
public void LoadInitialData()
{
// Suponiendo que "SelectedImage" es una propiedad que al establecerse dispara "ImageSelected"
directorioTrabajo = EstadoPersistente.Instance.directorio;
}
// Crear un nuevo Objeto
private void ExecuteDoubleClick(object parameter)
{
if (parameter is TipoSimulable tipoSimulable)
{
CrearObjetoSimulableEnCentroCanvas(tipoSimulable.Tipo);
}
}
public void CrearObjetoSimulableEnCentroCanvas(Type tipoSimulable)
{
var CentroCanvas = MainWindow.ObtenerCentroCanvasMeters();
2024-05-27 05:34:20 -03:00
CrearObjetoSimulable(tipoSimulable, CentroCanvas.X, CentroCanvas.Y);
}
2024-05-27 05:34:20 -03:00
public osBase CrearObjetoSimulable(Type tipoSimulable, float Left, float Top)
{
// Crear una nueva instancia del osBase correspondiente
osBase? NuevoOsBase = UserControlFactory.GetInstanceForType(tipoSimulable);
NuevoOsBase.Left = Left;
NuevoOsBase.Top = Top;
if (NuevoOsBase != null)
{
if (CrearUserControlDesdeObjetoSimulable(NuevoOsBase))
// Añadir el nuevo osBase a la colección de objetos simulables
ObjetosSimulables.Add(NuevoOsBase);
}
return NuevoOsBase;
}
// Crear UserControl desde osBase : Nuevo o desde Deserealizacion
private bool CrearUserControlDesdeObjetoSimulable(osBase osObjeto)
{
Type tipoObjeto = osObjeto.GetType();
// Obtén el UserControl correspondiente para el tipo de objeto
UserControl? userControl = UserControlFactory.GetControlForType(tipoObjeto);
if (userControl != null)
{
// Asignar los datos al UserControl
UserControlFactory.AssignDatos(userControl, osObjeto, simulationManager);
osObjeto._mainViewModel = this;
if (osObjeto.Id == null) // Para los objetos salvados antes de usar UniqueID
osObjeto.Id = new UniqueId().ObtenerNuevaID();
MainWindow.AgregarRegistrarUserControlCanvas(userControl);
return true;
}
return false;
}
public void RemoverObjetoSimulable(osBase osObjeto)
{
if (osObjeto != null && ObjetosSimulables.Contains(osObjeto))
{
ObjetosSimulables.Remove(osObjeto);
if (osObjeto.VisualRepresentation != null)
MainWindow.EliminarUserControlDelCanvas(osObjeto.VisualRepresentation);
}
}
2024-05-20 09:05:34 -03:00
private void DuplicarUserControl()
{
if (SelectedItemOsList is osBase objDuplicar)
2024-06-10 06:07:25 -03:00
DuplicarObjeto(objDuplicar, 0.5f, 0.5f);
}
2024-05-20 09:05:34 -03:00
2024-06-10 06:07:25 -03:00
public osBase DuplicarObjeto(osBase objDuplicar, float OffsetX, float OffsetY)
{
StopSimulation();
DisconnectPLC();
2024-05-20 09:05:34 -03:00
2024-06-10 06:07:25 -03:00
osBase? NuevoObjetoDuplicado = null;
2024-05-20 09:05:34 -03:00
2024-06-10 06:07:25 -03:00
objDuplicar.SalvarDatosNoSerializables();
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.All
};
try
{
// Serializar
var serializedData = JsonConvert.SerializeObject(objDuplicar, settings);
// Duplicar
NuevoObjetoDuplicado = JsonConvert.DeserializeObject<osBase>(serializedData, settings);
if (NuevoObjetoDuplicado != null)
2024-05-27 05:34:20 -03:00
{
2024-06-10 06:07:25 -03:00
NuevoObjetoDuplicado.Id.ObtenerNuevaID();
string nombre = NuevoObjetoDuplicado.Nombre + "_" + NuevoObjetoDuplicado.Id.Value;
NuevoObjetoDuplicado.Nombre = nombre;
NuevoObjetoDuplicado.Left += OffsetX;
NuevoObjetoDuplicado.Top += OffsetY;
ObjetosSimulables.Add(NuevoObjetoDuplicado);
CrearUserControlDesdeObjetoSimulable(NuevoObjetoDuplicado);
2024-05-20 09:05:34 -03:00
}
}
2024-06-10 06:07:25 -03:00
catch
{
// Log error or handle it accordingly
}
finally
{
objDuplicar.RestaurarDatosNoSerializables();
2024-06-10 06:07:25 -03:00
}
return NuevoObjetoDuplicado;
2024-05-20 09:05:34 -03:00
}
2024-06-10 06:07:25 -03:00
private void EliminarUserControl()
{
if (SelectedItemOsList is osBase objEliminar)
{
RemoverObjetoSimulable(objEliminar);
}
}
private void EliminarTodosCommand()
{
var objetosSimulablesCopy = new List<osBase>(ObjetosSimulables);
foreach (var obj in objetosSimulablesCopy)
RemoverObjetoSimulable(obj);
}
private void EliminarAutoCreatedCommand()
{
var objetosSimulablesCopy = new List<osBase>(ObjetosSimulables);
foreach (var obj in objetosSimulablesCopy)
if (obj.AutoCreated)
RemoverObjetoSimulable(obj);
}
private void EliminarClonedCommand()
{
var objetosSimulablesCopy = new List<osBase>(ObjetosSimulables);
foreach (var obj in objetosSimulablesCopy)
if (obj is osExtraccionTag TEobj && TEobj.Cloned)
RemoverObjetoSimulable(obj);
}
private void AssingPagesCommand()
{
var assignImagesWindow = new AssignImagesWindow();
var assignImagesViewModel = new AssignImagesViewModel();
assignImagesViewModel.Initialize(this, assignImagesWindow);
assignImagesWindow.DataContext = assignImagesViewModel;
assignImagesWindow.ShowDialog();
2024-06-11 07:30:27 -03:00
if (assignImagesWindow.DataContext is AssignImagesViewModel dialog && dialog.CloseOK)
SaveStateObjetosSimulables();
}
private async Task WaitForUIUpdateAsync()
{
await Task.Yield();
Application.Current.Dispatcher.Invoke(() => { }, DispatcherPriority.ApplicationIdle);
}
private async void MultiPageExtractTagsCommand()
{
2024-06-11 07:30:27 -03:00
var ImagenesSeleccionadas = new ObservableCollection<string>
{
SelectedImage
};
StopSimulation();
var selectPagesWindow = new SelectPages();
var selectPagesViewModel = new SelectPagesViewModel();
selectPagesViewModel.Initialize(this, selectPagesWindow, ref ImagenesSeleccionadas);
selectPagesWindow.DataContext = selectPagesViewModel;
selectPagesWindow.ShowDialog();
2024-06-11 07:30:27 -03:00
if (selectPagesWindow.DataContext is SelectPagesViewModel dialog && dialog.CloseOK)
foreach (var page in ImagenesSeleccionadas)
{
SelectedImage = page;
await WaitForUIUpdateAsync(); // Espera a que la UI se actualice
ExtraerTags();
}
}
private async void MultiPageAnalizeCommand()
{
2024-06-11 07:30:27 -03:00
var ImagenesSeleccionadas = new ObservableCollection<string>
{
SelectedImage
};
StopSimulation();
var selectPagesWindow = new SelectPages();
var selectPagesViewModel = new SelectPagesViewModel();
selectPagesViewModel.Initialize(this, selectPagesWindow, ref ImagenesSeleccionadas);
selectPagesWindow.DataContext = selectPagesViewModel;
selectPagesWindow.ShowDialog();
SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
foreach (var page in ImagenesSeleccionadas)
{
SelectedImage = page;
await WaitForUIUpdateAsync(); // Espera a que la UI se actualice
AnalizePageCommand();
await WaitForUIUpdateAsync(); // Espera a que la UI se actualice
SaveStateObjetosSimulables(); // Guarda el estado antes de cambiar la imagen
}
}
private void AnalizePageCommand()
{
foreach (var obj in ObjetosSimulables)
if (obj is osBuscarCoincidencias objBC)
2024-06-11 07:30:27 -03:00
if (objBC.Show_On_This_Page)
objBC.BuscarCoincidencias();
}
/// <summary>
/// Extrae y formatea las etiquetas de los objetos simulables y las guarda en un archivo Excel.
/// </summary>
private void ExtraerTags()
{
// Obtiene la ruta del archivo Excel donde se guardarán los datos.
var filePath = DatosDeTrabajo.ObtenerPathAllPages(".xlsx");
try
{
// Crea o abre un libro de Excel.
XLWorkbook workbook = File.Exists(filePath) ? new XLWorkbook(filePath) : new XLWorkbook();
var sheetName = "TagsExtracted";
// Obtiene o crea la hoja de trabajo "TagsExtracted".
var worksheet = workbook.Worksheets.Contains(sheetName) ? workbook.Worksheet(sheetName) : workbook.Worksheets.Add(sheetName);
var lastRowUsed = worksheet.LastRowUsed();
// Determina la fila en la que se empezarán a escribir los datos.
2024-06-11 07:30:27 -03:00
int rowOffset = lastRowUsed == null ? 2 : lastRowUsed.RowNumber() + 1;
// Determina la columna fija más alta.
2024-06-11 07:30:27 -03:00
List<int> columnasOcupadas = new List<int>();
int actualMaxCol = 0;
int col = 0;
// Filtrar los objetos de tipo osExtraccionTag y crear una nueva lista
var osBuscarCoincidencias_List = ObjetosSimulables.OfType<osBuscarCoincidencias>().ToList();
var osExtraccionTagBaseGrouped_List = ObjetosSimulables
.OfType<osExtraccionTag>()
.Where(tag => !tag.Cloned && tag.Id_Search_Templates != null && tag.Id_Search_Templates != "")
.ToList();
var osExtraccionTagBaseFix_List = ObjetosSimulables
.OfType<osExtraccionTag>()
.Where(tag => !tag.Cloned && (tag.Id_Search_Templates == null || tag.Id_Search_Templates == ""))
.ToList();
var osExtraccionTagCloned_List = ObjetosSimulables
.OfType<osExtraccionTag>()
.Where(tag => tag.Cloned)
.ToList();
// Columnas Fijas para los Tags no agrupados que no son clonados
foreach (var objExtraccionTag in osExtraccionTagBaseFix_List)
if ((string.IsNullOrEmpty(objExtraccionTag.Id_Search_Templates)) && !objExtraccionTag.Cloned)
{
2024-06-11 07:30:27 -03:00
col = objExtraccionTag.Collumn_number;
if (col == 0 || columnasOcupadas.Contains(col))
col = ++actualMaxCol;
else
actualMaxCol = Math.Max(actualMaxCol, col);
columnasOcupadas.Add(col);
objExtraccionTag.Collumn_number = col;
}
2024-06-11 07:30:27 -03:00
// Tags Agrupados no Clonados
foreach (var objBC in osBuscarCoincidencias_List)
foreach (var objExtraccionTag in osExtraccionTagBaseGrouped_List)
if (objExtraccionTag.Id_Search_Templates == objBC.Nombre && !objExtraccionTag.Cloned)
{
col = objExtraccionTag.Collumn_number;
if (col == 0 || columnasOcupadas.Contains(col))
col = ++actualMaxCol;
else
actualMaxCol = Math.Max(actualMaxCol, col);
columnasOcupadas.Add(col);
objExtraccionTag.Collumn_number = col;
}
2024-06-11 07:30:27 -03:00
int RowToRender = 0;
// Cloned Tag - Asignar las mismas columnas
foreach (var oFrom in osExtraccionTagBaseGrouped_List)
foreach (var oCloned in osExtraccionTagCloned_List)
{
2024-06-11 07:30:27 -03:00
if (oCloned.Cloned_from == oFrom.Id)
oCloned.Collumn_number = oFrom.Collumn_number;
RowToRender = Math.Max(RowToRender, oCloned.Copy_Number);
}
2024-06-11 07:30:27 -03:00
// Render Rows
for (int row = 0; row < RowToRender; row++)
{
// Render Fix tags
foreach (var TagFixs in osExtraccionTagBaseFix_List)
{
col = TagFixs.Collumn_number;
if (worksheet.Cell(1, col).IsEmpty())
worksheet.Cell(1, col).Value = TagFixs.Collumn_name;
TagFixs.CaptureImageAreaAndDoOCR();
worksheet.Cell(row + rowOffset, col).Value = TagFixs.Tag_extract;
}
// Render Cloned tags
foreach (var TagCloned in osExtraccionTagCloned_List)
{
if (TagCloned.Copy_Number == row) // Estamos en la fila correcta
{
2024-06-11 07:30:27 -03:00
col = TagCloned.Collumn_number;
if (worksheet.Cell(1, col).IsEmpty())
worksheet.Cell(1, col).Value = TagCloned.Collumn_name;
TagCloned.CaptureImageAreaAndDoOCR();
worksheet.Cell(row + rowOffset, col).Value = TagCloned.Tag_extract;
}
}
}
2024-06-11 07:30:27 -03:00
// Formatear los títulos en la fila 1
var titleRow = worksheet.Row(1);
titleRow.Style.Font.Bold = true;
titleRow.Style.Fill.BackgroundColor = XLColor.LightGray;
titleRow.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
// Auto dimensionado de las columnas utilizadas
worksheet.Columns().AdjustToContents();
// Guarda el libro de Excel.
workbook.SaveAs(filePath);
}
catch (IOException ex)
{
// Muestra un diálogo de error si ocurre una excepción de IO.
var dialog = new TaskDialog
{
WindowTitle = "IOException",
MainInstruction = "Error al acceder al archivo",
Content = $"El proceso no puede acceder al archivo '{filePath}' porque está siendo utilizado por otro proceso.",
ExpandedInformation = ex.ToString(),
MainIcon = TaskDialogIcon.Error,
ButtonStyle = TaskDialogButtonStyle.Standard
};
dialog.Buttons.Add(new TaskDialogButton(ButtonType.Ok));
dialog.ShowDialog();
}
}
private void InitializeTipoSimulableList()
{
var baseType = typeof(osBase);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.Where(type => type.IsSubclassOf(baseType) && !type.IsAbstract && typeof(IosBase).IsAssignableFrom(type));
foreach (var type in types)
{
var methodInfo = type.GetMethod("NombreClase", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
string nombre = methodInfo != null ? methodInfo.Invoke(null, null)?.ToString() : "Nombre no encontrado";
ListaOsBase.Add(new TipoSimulable { Nombre = nombre, Tipo = type });
}
2024-05-03 05:13:25 -03:00
}
2024-05-03 05:13:25 -03:00
private void StartSimulation()
{
IsSimulationRunning = true;
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.UpdateGeometryStart();
simulationManager.Debug_DrawInitialBodies();
TiempoDesdeStartSimulacion = 0;
Debug_SimulacionCreado = true;
2024-05-03 05:13:25 -03:00
_timerSimulacion.Start();
}
private void StopSimulation()
{
IsSimulationRunning = false;
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.SimulationStop();
if (Debug_SimulacionCreado)
{
simulationManager.Debug_ClearSimulationShapes();
Debug_SimulacionCreado = false;
}
2024-05-03 05:13:25 -03:00
_timerSimulacion.Stop();
2024-05-02 11:06:45 -03:00
}
2024-05-03 05:13:25 -03:00
private void OnTickSimulacion(object sender, EventArgs e)
{
2024-05-16 13:45:14 -03:00
// Detener el cronómetro y obtener el tiempo transcurrido en milisegundos
2024-05-25 07:53:34 -03:00
var elapsedMilliseconds = stopwatch_Sim.Elapsed.TotalMilliseconds - stopwatch_SimModel_last;
stopwatch_SimModel_last = stopwatch_Sim.Elapsed.TotalMilliseconds;
2024-05-16 13:45:14 -03:00
// Eliminar el diseño de Debug luego de 2 segundos
2024-05-31 14:25:24 -03:00
if (TiempoDesdeStartSimulacion > 12000)
simulationManager.Debug_ClearSimulationShapes();
else
2024-05-25 07:53:34 -03:00
TiempoDesdeStartSimulacion += (float)elapsedMilliseconds;
2024-05-03 05:13:25 -03:00
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.UpdateGeometryStep();
simulationManager.Step();
2024-05-06 12:31:45 -03:00
var objetosSimulablesCopy = new List<osBase>(ObjetosSimulables);
foreach (var objetoSimulable in objetosSimulablesCopy)
{
if (!objetoSimulable.RemoverDesdeSimulacion)
objetoSimulable.UpdateControl((int)elapsedMilliseconds);
else
RemoverObjetoSimulable(objetoSimulable);
}
2024-05-06 12:31:45 -03:00
2024-05-03 05:13:25 -03:00
}
2024-05-02 11:06:45 -03:00
2024-05-15 06:20:09 -03:00
private void ConnectPLC()
{
2024-05-25 07:53:34 -03:00
PLCViewModel.Connect();
2024-05-15 06:20:09 -03:00
}
private void DisconnectPLC()
{
2024-05-25 07:53:34 -03:00
PLCViewModel.Disconnect();
2024-05-15 06:20:09 -03:00
IsConnected = false;
2024-05-23 14:56:14 -03:00
foreach (var objetoSimulable in ObjetosSimulables)
objetoSimulable.SetPLC(null);
2024-05-15 06:20:09 -03:00
}
private void OnRefreshEvent(object sender, EventArgs e)
{
2024-05-25 07:53:34 -03:00
if (PLCViewModel.IsConnected)
{
2024-05-15 06:20:09 -03:00
if (!isConnected)
2024-05-23 14:56:14 -03:00
{
2024-05-15 06:20:09 -03:00
IsConnected = true;
2024-05-23 14:56:14 -03:00
foreach (var objetoSimulable in ObjetosSimulables)
2024-05-25 07:53:34 -03:00
objetoSimulable.SetPLC(PLCViewModel.PLCInterface);
2024-05-23 14:56:14 -03:00
}
// Detener el cronómetro y obtener el tiempo transcurrido en milisegundos
2024-05-25 07:53:34 -03:00
var elapsedMilliseconds = stopwatch_Sim.Elapsed.TotalMilliseconds - stopwatch_SimPLC_last;
stopwatch_SimPLC_last = stopwatch_Sim.Elapsed.TotalMilliseconds;
2024-05-25 07:53:34 -03:00
// Reiniciar el cronómetro para la próxima medición
foreach (var objetoSimulable in ObjetosSimulables)
2024-05-27 05:34:20 -03:00
objetoSimulable.UpdatePLC(PLCViewModel.PLCInterface, (int)elapsedMilliseconds);
}
}
2024-05-02 11:06:45 -03:00
private void OpenWorkDirectory()
{
var dialog = new VistaFolderBrowserDialog();
if (dialog.ShowDialog() == true) // Mostrar el diálogo y comprobar si el resultado es positivo
{
directorioTrabajo = dialog.SelectedPath; // Actualizar la propiedad que también actualiza el estado persistente
2024-05-02 11:06:45 -03:00
}
}
//
// Lista de osBase
//
2024-05-27 05:34:20 -03:00
public void Save()
{
SaveStateObjetosSimulables();
}
public void SaveStateObjetosSimulables()
{
2024-05-25 07:53:34 -03:00
if (SelectedImage != null)
{
StopSimulation();
2024-05-20 09:05:34 -03:00
DisconnectPLC();
ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>();
ObservableCollection<osBase> _objetosSimulablesAllPages = new ObservableCollection<osBase>();
2024-05-20 09:05:34 -03:00
foreach (var obj in ObjetosSimulables)
{
2024-05-20 09:05:34 -03:00
// Guardar referencias temporales
obj.SalvarDatosNoSerializables();
if (!obj.Enable_On_All_Pages)
_objetosSimulables.Add(obj);
else
_objetosSimulablesAllPages.Add(obj);
}
2024-05-20 09:05:34 -03:00
// Salvar los objetos de la pagina actual
// Crear un objeto que incluya tanto los ObjetosSimulables como el UnitConverter y PLC_ConnectionData
var dataToSerialize = new SimulationData
{
ObjetosSimulables = _objetosSimulables,
UnitConverter = PixelToMeter.Instance.calc,
PLC_ConnectionData = PLCViewModel
};
// Ruta del archivo a ser guardado
var path = DatosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json");
if (path != null)
SerializarYSalvar(dataToSerialize, path);
// Salvar los objetos de todas las paginas
// Ruta del archivo a ser guardado
path = DatosDeTrabajo.ObtenerPathAllPages(".json");
if (path != null)
SerializarYSalvar(_objetosSimulablesAllPages, path);
// Restaurar las propiedades originales de los objetos
foreach (var obj in ObjetosSimulables)
2024-05-20 09:05:34 -03:00
obj.RestaurarDatosNoSerializables();
}
}
private void SerializarYSalvar(object listaObjetos, string path)
{
// Verificar si el archivo ya existe y crear un respaldo
if (File.Exists(path))
{
var backupPath = Path.ChangeExtension(path, ".bak");
File.Copy(path, backupPath, true); // Copia el archivo existente a un nuevo archivo .bak, sobrescribiendo si es necesario
}
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
2024-06-10 06:07:25 -03:00
// PreserveReferencesHandling = PreserveReferencesHandling.Objects,
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto
};
// Serializar
var serializedData = JsonConvert.SerializeObject(listaObjetos, settings);
File.WriteAllText(path, serializedData); // Escribir el nuevo archivo JSON
}
public void LoadStateObjetosSimulables()
{
try
{
StopSimulation();
2024-05-20 09:05:34 -03:00
DisconnectPLC();
ObjetosSimulables.Clear();
simulationManager.Clear();
2024-05-25 07:53:34 -03:00
if (SelectedImage != null)
{
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
// PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
2024-05-25 07:53:34 -03:00
string jsonPath = datosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json");
if (File.Exists(jsonPath))
{
string jsonString = File.ReadAllText(jsonPath);
var simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings);
if (simulationData != null)
{
if (simulationData.ObjetosSimulables is not null)
ObjetosSimulables = simulationData.ObjetosSimulables;
if (simulationData.PLC_ConnectionData is not null)
PLCViewModel = simulationData.PLC_ConnectionData;
else
PLCViewModel = new PLCViewModel();
PixelToMeter.Instance.calc = simulationData.UnitConverter;
// Re-register to the events
2024-05-25 07:53:34 -03:00
PLCViewModel.RefreshEvent += OnRefreshEvent;
}
}
jsonPath = DatosDeTrabajo.ObtenerPathAllPages(".json");
if (File.Exists(jsonPath))
{
string jsonString = File.ReadAllText(jsonPath);
ObservableCollection<osBase> _objetosSimulablesAllPages = new ObservableCollection<osBase>();
_objetosSimulablesAllPages = JsonConvert.DeserializeObject<ObservableCollection<osBase>>(jsonString, settings);
if (_objetosSimulablesAllPages != null)
foreach (var obj in _objetosSimulablesAllPages)
ObjetosSimulables.Add(obj);
}
// Recorrer la colección de objetos simulables
foreach (var objetoSimulable in ObjetosSimulables)
if (objetoSimulable != null) CrearUserControlDesdeObjetoSimulable(objetoSimulable);
}
}
catch { /* Consider logging the error or handling it appropriately */ }
}
2024-05-02 11:06:45 -03:00
2024-05-22 06:19:31 -03:00
// Se cargan los datos de cada UserControl en el StackPanel
2024-06-02 04:13:01 -03:00
public void CargarPropiedadesosDatos(osBase selectedObject, PropertyGrid PanelEdicion, ResourceDictionary Resources)
2024-05-22 06:19:31 -03:00
{
2024-06-02 04:13:01 -03:00
UserControlFactory.CargarPropiedadesosDatos(selectedObject, PanelEdicion);
2024-05-22 06:19:31 -03:00
}
private RelayCommand saveCommand;
public ICommand SaveCommand => saveCommand ??= new RelayCommand(Save);
private void Save(object commandParameter)
{
}
private RelayCommand exitCommand;
public ICommand ExitCommand => exitCommand ??= new RelayCommand(Exit);
private void Exit()
{
Save();
Application.Current.Shutdown();
}
}
public class SimulationData
{
2024-05-25 07:53:34 -03:00
public ObservableCollection<osBase>? ObjetosSimulables { get; set; }
public UnitConverter? UnitConverter { get; set; }
2024-05-27 05:34:20 -03:00
public PLCViewModel? PLC_ConnectionData { get; set; }
}
public class TipoSimulable
{
2024-05-25 07:53:34 -03:00
public string? Nombre { get; set; }
public Type? Tipo { get; set; }
}
public class TickSimulacionEventArgs : EventArgs
{
// Aquí puedes agregar propiedades o campos para pasar información adicional
// en el evento TickSimulacion
2024-05-02 11:06:45 -03:00
}
}