Compare commits

..

2 Commits

11 changed files with 494 additions and 121 deletions

View File

@ -68,9 +68,11 @@
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.6.0" /> <PackageReference Include="Extended.Wpf.Toolkit" Version="4.6.0" />
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc2" /> <PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc2" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.122" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" /> <PackageReference Include="Ookii.Dialogs.Wpf" Version="5.0.1" />
<PackageReference Include="Tesseract" Version="5.2.0" />
<PackageReference Include="Tesseract.Drawing" Version="5.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -116,6 +118,15 @@
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None> </None>
<None Update="Tesseract\eng.traineddata">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tesseract\ita.traineddata">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Tesseract\spa.traineddata">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -28,6 +28,16 @@ namespace CtrEditor
return null; return null;
} }
public string? ObtenerPathAllPages(string extension)
{
string folderPath = EstadoPersistente.Instance.directorio; // Usar directamente desde el Singleton
if (Directory.Exists(folderPath))
return Path.ChangeExtension(folderPath + "\\allpages", extension);
else return null;
}
public void CargarImagenes() public void CargarImagenes()
{ {
Imagenes.Clear(); Imagenes.Clear();

View File

@ -16,6 +16,7 @@ using System.Reflection;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using Xceed.Wpf.Toolkit.PropertyGrid; using Xceed.Wpf.Toolkit.PropertyGrid;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows.Data;
namespace CtrEditor namespace CtrEditor
@ -147,9 +148,13 @@ namespace CtrEditor
[ObservableProperty] [ObservableProperty]
private TipoSimulable selectedItem; private TipoSimulable selectedItem;
public ICollectionView ObjetosSimulablesFiltered { get; }
public ICollectionView ObjetosSimulablesAllPages { get; }
[ObservableProperty] [ObservableProperty]
public ObservableCollection<osBase> objetosSimulables; public ObservableCollection<osBase> objetosSimulables;
// //
// Constructor // Constructor
// //
@ -160,6 +165,7 @@ namespace CtrEditor
datosDeTrabajo = new DatosDeTrabajo(); datosDeTrabajo = new DatosDeTrabajo();
ObjetosSimulables = new ObservableCollection<osBase>(); ObjetosSimulables = new ObservableCollection<osBase>();
ListaOsBase = new ObservableCollection<TipoSimulable>(); ListaOsBase = new ObservableCollection<TipoSimulable>();
// Inicializa el PLCViewModel // Inicializa el PLCViewModel
@ -463,38 +469,40 @@ namespace CtrEditor
StopSimulation(); StopSimulation();
DisconnectPLC(); DisconnectPLC();
// Ruta del archivo a ser guardado ObservableCollection<osBase> _objetosSimulables = new ObservableCollection<osBase>();
var path = DatosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json"); ObservableCollection<osBase> _objetosSimulablesAllPages = new ObservableCollection<osBase>();
// 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
}
foreach (var obj in ObjetosSimulables) foreach (var obj in ObjetosSimulables)
{
// Guardar referencias temporales // Guardar referencias temporales
obj.SalvarDatosNoSerializables(); obj.SalvarDatosNoSerializables();
if (!obj.Enable_on_all_pages)
_objetosSimulables.Add(obj);
else
_objetosSimulablesAllPages.Add(obj);
}
var settings = new JsonSerializerSettings // Salvar los objetos de la pagina actual
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto
};
// Crear un objeto que incluya tanto los ObjetosSimulables como el UnitConverter y PLC_ConnectionData // Crear un objeto que incluya tanto los ObjetosSimulables como el UnitConverter y PLC_ConnectionData
var dataToSerialize = new SimulationData var dataToSerialize = new SimulationData
{ {
ObjetosSimulables = ObjetosSimulables, ObjetosSimulables = _objetosSimulables,
UnitConverter = PixelToMeter.Instance.calc, UnitConverter = PixelToMeter.Instance.calc,
PLC_ConnectionData = PLCViewModel PLC_ConnectionData = PLCViewModel
}; };
// Serializar // Ruta del archivo a ser guardado
var serializedData = JsonConvert.SerializeObject(dataToSerialize, settings); var path = DatosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json");
File.WriteAllText(path, serializedData); // Escribir el nuevo archivo 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 // Restaurar las propiedades originales de los objetos
foreach (var obj in ObjetosSimulables) foreach (var obj in ObjetosSimulables)
@ -502,6 +510,29 @@ namespace CtrEditor
} }
} }
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,
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() public void LoadStateObjetosSimulables()
{ {
try try
@ -511,18 +542,20 @@ namespace CtrEditor
ObjetosSimulables.Clear(); ObjetosSimulables.Clear();
simulationManager.Clear(); simulationManager.Clear();
if (SelectedImage != null) if (SelectedImage != null)
{ {
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
string jsonPath = datosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json"); string jsonPath = datosDeTrabajo.ObtenerPathImagenConExtension(SelectedImage, ".json");
if (File.Exists(jsonPath)) if (File.Exists(jsonPath))
{ {
string jsonString = File.ReadAllText(jsonPath); string jsonString = File.ReadAllText(jsonPath);
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace,
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};
var simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings); var simulationData = JsonConvert.DeserializeObject<SimulationData>(jsonString, settings);
if (simulationData != null) if (simulationData != null)
@ -540,11 +573,24 @@ namespace CtrEditor
// Re-register to the events // Re-register to the events
PLCViewModel.RefreshEvent += OnRefreshEvent; PLCViewModel.RefreshEvent += OnRefreshEvent;
// Recorrer la colección de objetos simulables
foreach (var objetoSimulable in ObjetosSimulables)
CrearUserControlDesdeObjetoSimulable(objetoSimulable);
} }
} }
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)
CrearUserControlDesdeObjetoSimulable(objetoSimulable);
} }
} }
catch { /* Consider logging the error or handling it appropriately */ } catch { /* Consider logging the error or handling it appropriately */ }

View File

@ -1,43 +1,38 @@
<Window <Window xmlns:ctreditor="clr-namespace:CtrEditor" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:ctreditor="clr-namespace:CtrEditor" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:Siemens="clr-namespace:CtrEditor.Siemens" xmlns:local="clr-namespace:CtrEditor"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Siemens="clr-namespace:CtrEditor.Siemens"
xmlns:local="clr-namespace:CtrEditor"
xmlns:uc="clr-namespace:CtrEditor.ObjetosSim.UserControls" xmlns:uc="clr-namespace:CtrEditor.ObjetosSim.UserControls"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:ObjetosSim="clr-namespace:CtrEditor.ObjetosSim" x:Class="CtrEditor.MainWindow" Height="900" Width="1600"
xmlns:ObjetosSim="clr-namespace:CtrEditor.ObjetosSim" x:Class="CtrEditor.MainWindow" WindowState="Maximized" ResizeMode="CanResize" Title="{Binding directorioTrabajo}" Icon="/app2.png">
Height="900" Width="1600" WindowState="Maximized"
ResizeMode="CanResize" Title="{Binding directorioTrabajo}" Icon="/app2.png">
<Window.DataContext> <Window.DataContext>
<ctreditor:MainViewModel/> <ctreditor:MainViewModel />
</Window.DataContext> </Window.DataContext>
<Window.Resources> <Window.Resources>
<!-- Style for Start/Stop Button --> <!-- Style for Start/Stop Button -->
<Style x:Key="StartStopButtonStyle" TargetType="Button"> <Style x:Key="StartStopButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent" />
<Style.Triggers> <Style.Triggers>
<DataTrigger Binding="{Binding IsSimulationRunning}" Value="True"> <DataTrigger Binding="{Binding IsSimulationRunning}" Value="True">
<Setter Property="Background" Value="LightGreen"/> <Setter Property="Background" Value="LightGreen" />
</DataTrigger> </DataTrigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>
<!-- Style for Connect/Disconnect Button --> <!-- Style for Connect/Disconnect Button -->
<Style x:Key="ConnectDisconnectButtonStyle" TargetType="Button"> <Style x:Key="ConnectDisconnectButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent" />
<Style.Triggers> <Style.Triggers>
<DataTrigger Binding="{Binding IsConnected}" Value="True"> <DataTrigger Binding="{Binding IsConnected}" Value="True">
<Setter Property="Background" Value="LightGreen"/> <Setter Property="Background" Value="LightGreen" />
</DataTrigger> </DataTrigger>
</Style.Triggers> </Style.Triggers>
</Style> </Style>
</Window.Resources> </Window.Resources>
<Grid> <Grid>
@ -55,27 +50,30 @@
<Grid Margin="0,20,0,0"> <Grid Margin="0,20,0,0">
<!-- Margen superior para el menú --> <!-- Margen superior para el menú -->
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="100"/> <ColumnDefinition Width="1*" MinWidth="100" />
<ColumnDefinition Width="8*" MinWidth="200"/> <ColumnDefinition Width="8*" MinWidth="200" />
<ColumnDefinition Width="2*" MinWidth="100"/> <ColumnDefinition Width="2*" MinWidth="100" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- Primera Columna --> <!-- Primera Columna -->
<Grid Grid.Column="0"> <Grid Grid.Column="0">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="1*"/> <RowDefinition Height="1*" />
<RowDefinition Height="2*"/> <RowDefinition Height="2*" />
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<ListBox x:Name="ListaImagenes" Grid.Row="0" Margin="5" ItemsSource="{Binding ListaImagenes}" SelectedItem="{Binding SelectedImage}" /> <ListBox x:Name="ListaImagenes" Grid.Row="0" Margin="5" ItemsSource="{Binding ListaImagenes}"
<ListBox x:Name="ListaFunciones" Grid.Row="1" Margin="5" ItemsSource="{Binding ListaOsBase}" DisplayMemberPath="Nombre" SelectedItem="{Binding SelectedItem}"> SelectedItem="{Binding SelectedImage}" />
<ListBox x:Name="ListaFunciones" Grid.Row="1" Margin="5" ItemsSource="{Binding ListaOsBase}"
DisplayMemberPath="Nombre" SelectedItem="{Binding SelectedItem}">
<i:Interaction.Triggers> <i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick"> <i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding ItemDoubleClickCommand}" CommandParameter="{Binding SelectedItem}"/> <i:InvokeCommandAction Command="{Binding ItemDoubleClickCommand}"
CommandParameter="{Binding SelectedItem}" />
</i:EventTrigger> </i:EventTrigger>
</i:Interaction.Triggers> </i:Interaction.Triggers>
</ListBox> </ListBox>
<Siemens:PLCControl x:Name="PLCSim" Grid.Row="2" Margin="5" DataContext="{Binding PLCViewModel}"/> <Siemens:PLCControl x:Name="PLCSim" Grid.Row="2" Margin="5" DataContext="{Binding PLCViewModel}" />
</Grid> </Grid>
<!-- GridSplitter --> <!-- GridSplitter -->
<GridSplitter Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" Width="5" Background="LightGray" /> <GridSplitter Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" Width="5" Background="LightGray" />
@ -89,44 +87,47 @@
<ToolBarTray Grid.Row="0"> <ToolBarTray Grid.Row="0">
<ToolBar> <ToolBar>
<Button Command="{Binding TBStartSimulationCommand}" ToolTip="Iniciar Simulación" Style="{StaticResource StartStopButtonStyle}"> <Button Command="{Binding TBStartSimulationCommand}" ToolTip="Iniciar Simulación"
Style="{StaticResource StartStopButtonStyle}">
<StackPanel> <StackPanel>
<Image Source="Icons/start.png" Width="16" Height="16"/> <Image Source="Icons/start.png" Width="16" Height="16" />
<TextBlock Text="Iniciar"/> <TextBlock Text="Iniciar" />
</StackPanel> </StackPanel>
</Button> </Button>
<Button Command="{Binding TBStopSimulationCommand}" ToolTip="Detener Simulación"> <Button Command="{Binding TBStopSimulationCommand}" ToolTip="Detener Simulación">
<StackPanel> <StackPanel>
<Image Source="Icons/stop.png" Width="16" Height="16"/> <Image Source="Icons/stop.png" Width="16" Height="16" />
<TextBlock Text="Detener"/> <TextBlock Text="Detener" />
</StackPanel> </StackPanel>
</Button> </Button>
<Button Command="{Binding TBSaveCommand}" ToolTip="Guardar"> <Button Command="{Binding TBSaveCommand}" ToolTip="Guardar">
<StackPanel> <StackPanel>
<Image Source="Icons/save.png" Width="16" Height="16"/> <Image Source="Icons/save.png" Width="16" Height="16" />
<TextBlock Text="Guardar"/> <TextBlock Text="Guardar" />
</StackPanel> </StackPanel>
</Button> </Button>
<Button Command="{Binding TBConnectPLCCommand}" ToolTip="Conectar PLC" Style="{StaticResource ConnectDisconnectButtonStyle}"> <Button Command="{Binding TBConnectPLCCommand}" ToolTip="Conectar PLC"
Style="{StaticResource ConnectDisconnectButtonStyle}">
<StackPanel> <StackPanel>
<Image Source="Icons/connect.png" Width="16" Height="16"/> <Image Source="Icons/connect.png" Width="16" Height="16" />
<TextBlock Text="Conectar"/> <TextBlock Text="Conectar" />
</StackPanel> </StackPanel>
</Button> </Button>
<Button Command="{Binding TBDisconnectPLCCommand}" ToolTip="Desconectar PLC"> <Button Command="{Binding TBDisconnectPLCCommand}" ToolTip="Desconectar PLC">
<StackPanel> <StackPanel>
<Image Source="Icons/disconnect.png" Width="16" Height="16"/> <Image Source="Icons/disconnect.png" Width="16" Height="16" />
<TextBlock Text="Desconectar"/> <TextBlock Text="Desconectar" />
</StackPanel> </StackPanel>
</Button> </Button>
</ToolBar> </ToolBar>
</ToolBarTray> </ToolBarTray>
<ScrollViewer Grid.Row="1" x:Name="ImagenEnTrabajoScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" PanningMode="Both"> <ScrollViewer Grid.Row="1" x:Name="ImagenEnTrabajoScrollViewer" HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" PanningMode="Both">
<Canvas x:Name="ImagenEnTrabajoCanvas" Margin="400"> <Canvas x:Name="ImagenEnTrabajoCanvas" Margin="400">
<!-- El Margin puede ser ajustado según el espacio adicional que quieras proporcionar --> <!-- El Margin puede ser ajustado según el espacio adicional que quieras proporcionar -->
<Canvas.LayoutTransform> <Canvas.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="1"/> <ScaleTransform ScaleX="1" ScaleY="1" />
</Canvas.LayoutTransform> </Canvas.LayoutTransform>
</Canvas> </Canvas>
</ScrollViewer> </ScrollViewer>
@ -138,37 +139,49 @@
<!-- Tercera Columna --> <!-- Tercera Columna -->
<Grid Grid.Column="2"> <Grid Grid.Column="2">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*" /> <RowDefinition Height="*" MinHeight="100" />
<!-- Altura ajustable para el ListBox --> <!-- ListBox1 -->
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<!-- Espacio para el GridSplitter --> <!-- GridSplitter -->
<RowDefinition Height="*" /> <RowDefinition Height="*" MinHeight="200" />
<!-- Altura ajustable para el PanelEdicion --> <!-- StackPanel -->
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<!-- ToolBarTray -->
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- ListBox --> <!-- ListBox -->
<ListBox x:Name="ListaOs" <ListBox x:Name="ListaOs" Grid.Row="0" Margin="5" ItemsSource="{Binding ObjetosSimulables}"
Grid.Row="0" SelectedItem="{Binding SelectedItemOsList, Mode=TwoWay}"
Margin="5" SelectionChanged="ListaOs_SelectionChanged">
ItemsSource="{Binding ObjetosSimulables}" <ListBox.ItemTemplate>
DisplayMemberPath="Nombre" <DataTemplate>
SelectedItem="{Binding SelectedItemOsList, Mode=TwoWay}" <TextBlock Text="{Binding Nombre}">
SelectionChanged="ListaOs_SelectionChanged"/> <TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Enable_on_all_pages}" Value="True">
<Setter Property="Foreground" Value="Blue" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=Enable_on_all_pages}" Value="False">
<Setter Property="Foreground" Value="Black" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!-- GridSplitter --> <!-- GridSplitter -->
<GridSplitter Grid.Row="1" <GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" Background="Gray"
Height="5" ResizeDirection="Rows" VerticalAlignment="Center" />
HorizontalAlignment="Stretch"
Background="Gray"
ResizeDirection="Rows"
VerticalAlignment="Center"/>
<!-- PanelEdicion --> <!-- PanelEdicion -->
<xctk:PropertyGrid Grid.Row="2" Margin="5" x:Name="PanelEdicion" AutoGenerateProperties="False" SelectedObject="{Binding}"> <xctk:PropertyGrid Grid.Row="2" Margin="5" x:Name="PanelEdicion" AutoGenerateProperties="False"
SelectedObject="{Binding}">
<xctk:PropertyGrid.EditorDefinitions> <xctk:PropertyGrid.EditorDefinitions>
<!-- String --> <!-- String -->
<xctk:EditorTemplateDefinition> <xctk:EditorTemplateDefinition>
<xctk:EditorTemplateDefinition.TargetProperties> <xctk:EditorTemplateDefinition.TargetProperties>
@ -176,7 +189,8 @@
</xctk:EditorTemplateDefinition.TargetProperties> </xctk:EditorTemplateDefinition.TargetProperties>
<xctk:EditorTemplateDefinition.EditingTemplate> <xctk:EditorTemplateDefinition.EditingTemplate>
<DataTemplate> <DataTemplate>
<TextBox Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Text="{Binding Value}" /> <TextBox Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
Text="{Binding Value}" />
</DataTemplate> </DataTemplate>
</xctk:EditorTemplateDefinition.EditingTemplate> </xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition> </xctk:EditorTemplateDefinition>
@ -185,7 +199,9 @@
<xctk:EditorTemplateDefinition TargetProperties="VelocidadActual"> <xctk:EditorTemplateDefinition TargetProperties="VelocidadActual">
<xctk:EditorTemplateDefinition.EditingTemplate> <xctk:EditorTemplateDefinition.EditingTemplate>
<DataTemplate> <DataTemplate>
<xctk:SingleUpDown Increment="0.01" Background="Beige" Text="{Binding Value, Converter={StaticResource floatFormatter}}" FontWeight="Bold"/> <xctk:SingleUpDown Increment="0.01" Background="Beige"
Text="{Binding Value, Converter={StaticResource floatFormatter}}"
FontWeight="Bold" />
</DataTemplate> </DataTemplate>
</xctk:EditorTemplateDefinition.EditingTemplate> </xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition> </xctk:EditorTemplateDefinition>
@ -197,11 +213,12 @@
</xctk:EditorTemplateDefinition.TargetProperties> </xctk:EditorTemplateDefinition.TargetProperties>
<xctk:EditorTemplateDefinition.EditingTemplate> <xctk:EditorTemplateDefinition.EditingTemplate>
<DataTemplate> <DataTemplate>
<xctk:SingleUpDown Increment="0.01" Text="{Binding Value, Converter={StaticResource floatFormatter}}" /> <xctk:SingleUpDown Increment="0.01"
Text="{Binding Value, Converter={StaticResource floatFormatter}}" />
</DataTemplate> </DataTemplate>
</xctk:EditorTemplateDefinition.EditingTemplate> </xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition> </xctk:EditorTemplateDefinition>
<!-- Double --> <!-- Double -->
<xctk:EditorTemplateDefinition> <xctk:EditorTemplateDefinition>
<xctk:EditorTemplateDefinition.TargetProperties> <xctk:EditorTemplateDefinition.TargetProperties>
@ -209,7 +226,7 @@
</xctk:EditorTemplateDefinition.TargetProperties> </xctk:EditorTemplateDefinition.TargetProperties>
<xctk:EditorTemplateDefinition.EditingTemplate> <xctk:EditorTemplateDefinition.EditingTemplate>
<DataTemplate> <DataTemplate>
<TextBox Text="{Binding Value, Converter={StaticResource doubleFormatter}}"/> <TextBox Text="{Binding Value, Converter={StaticResource doubleFormatter}}" />
</DataTemplate> </DataTemplate>
</xctk:EditorTemplateDefinition.EditingTemplate> </xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition> </xctk:EditorTemplateDefinition>
@ -217,19 +234,18 @@
</xctk:PropertyGrid.EditorDefinitions> </xctk:PropertyGrid.EditorDefinitions>
</xctk:PropertyGrid> </xctk:PropertyGrid>
<ToolBarTray Grid.Row="3"> <ToolBarTray Grid.Row="3">
<ToolBar> <ToolBar>
<Button Command="{Binding TBEliminarUserControlCommand}" ToolTip="Eliminar Control"> <Button Command="{Binding TBEliminarUserControlCommand}" ToolTip="Eliminar Control">
<StackPanel> <StackPanel>
<Image Source="Icons/borrar.png" Width="16" Height="16"/> <Image Source="Icons/borrar.png" Width="16" Height="16" />
<TextBlock Text="Eliminar"/> <TextBlock Text="Eliminar" />
</StackPanel> </StackPanel>
</Button> </Button>
<Button Command="{Binding TBDuplicarUserControlCommand}" ToolTip="Duplicar Control"> <Button Command="{Binding TBDuplicarUserControlCommand}" ToolTip="Duplicar Control">
<StackPanel> <StackPanel>
<Image Source="Icons/duplicate.png" Width="16" Height="16"/> <Image Source="Icons/duplicate.png" Width="16" Height="16" />
<TextBlock Text="Duplicar"/> <TextBlock Text="Duplicar" />
</StackPanel> </StackPanel>
</Button> </Button>
</ToolBar> </ToolBar>

View File

@ -0,0 +1,26 @@
<UserControl x:Class="CtrEditor.ObjetosSim.Extraccion_Datos.ucExtraccionTag"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos"
mc:Ignorable="d">
<UserControl.DataContext>
<vm:osExtraccionTag/>
</UserControl.DataContext>
<Canvas>
<Rectangle x:Name="Transporte"
Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}" Opacity="0.1" Fill="Green"
Stroke="Black"
>
<Rectangle.RenderTransform>
<RotateTransform Angle="{Binding Angulo}"/>
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
</UserControl>

View File

@ -0,0 +1,247 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.Siemens;
using CtrEditor.Simulacion;
using System.Windows.Input;
using System.IO;
using System.Windows.Media.Imaging;
using Tesseract;
namespace CtrEditor.ObjetosSim.Extraccion_Datos
{
/// <summary>
/// Interaction logic for ucExtraccionTag.xaml
/// </summary>
///
public partial class osExtraccionTag : osBase, IosBase
{
private osBase _osMotor = null;
private simTransporte SimGeometria;
public static string NombreClase()
{
return "Extraccion Tags";
}
private string nombre = NombreClase();
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
[ObservableProperty]
bool extraer;
public override void TopChanged(float value)
{
base.TopChanged(value);
ResetTimer();
}
public override void LeftChanged(float value)
{
base.LeftChanged(value);
ResetTimer();
}
partial void OnExtraerChanged(bool value)
{
ResetTimer();
}
[ObservableProperty]
public float ancho;
partial void OnAnchoChanged(float value)
{
ResetTimer();
}
[ObservableProperty]
public float alto;
partial void OnAltoChanged(float value)
{
ResetTimer();
}
public override void OnTimerAfterMovement() {
if (Extraer)
CaptureImageAreaAndDoOCR();
}
[ObservableProperty]
public int n_Repeat_X;
[ObservableProperty]
public int n_Repeat_Y;
[ObservableProperty]
public float offset_Repeat_X;
[ObservableProperty]
public float offset_Repeat_Y;
[ObservableProperty]
public float angulo;
[ObservableProperty]
string tag_extract;
[ObservableProperty]
string clase;
[ObservableProperty]
string tag_name;
public osExtraccionTag()
{
Ancho = 1;
Alto = 1;
Angulo = 0;
}
private void ShowPreviewWindow(Stream imageStream)
{
// Create a new window for preview
Window previewWindow = new Window
{
Title = "Preview Captured Image",
Width = 500,
Height = 500,
Content = new Image
{
Source = BitmapFrame.Create(imageStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad),
Stretch = Stretch.Uniform
}
};
previewWindow.ShowDialog();
}
private void CaptureImageAreaAndDoOCR()
{
if (_mainViewModel?.MainCanvas.Children[0] is Image imagenDeFondo)
{
// Asegurarse de que la imagen origen está disponible
if (imagenDeFondo.Source is BitmapSource bitmapSource)
{
// Obtener los DPI de la imagen original
float originalDpiX = (float) bitmapSource.DpiX;
float originalDpiY = (float) bitmapSource.DpiY;
// Estándar DPI en el que el Canvas renderiza la imagen
float canvasDpiX = 96; // WPF usually renders at 96 DPI
float canvasDpiY = 96;
// Calcular el ratio de escala entre el Canvas y la imagen original
float scaleFactorX = originalDpiX / canvasDpiX;
float scaleFactorY = originalDpiY / canvasDpiY;
// Ajustar las coordenadas de recorte en función del ratio de escala
int x = (int)MeterToPixels(Left * scaleFactorX);
int y = (int)MeterToPixels(Top * scaleFactorY);
int width = (int)MeterToPixels(Ancho * scaleFactorX);
int height = (int)MeterToPixels(Alto * scaleFactorY);
// Validar y ajustar el tamaño del recorte para que se mantenga dentro de los límites de la imagen
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x + width > bitmapSource.PixelWidth) width = bitmapSource.PixelWidth - x;
if (y + height > bitmapSource.PixelHeight) height = bitmapSource.PixelHeight - y;
// Recortar el área deseada utilizando las coordenadas ajustadas
CroppedBitmap croppedBitmap = new CroppedBitmap(bitmapSource, new Int32Rect(x, y, width, height));
// Codificar el bitmap recortado a un MemoryStream
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(croppedBitmap));
using (MemoryStream memoryStream = new MemoryStream())
{
encoder.Save(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
// Mostrar la imagen recortada en una ventana de previsualización
// ShowPreviewWindow(memoryStream);
// Cargar la imagen en Tesseract desde el MemoryStream
using (var img = Pix.LoadFromMemory(memoryStream.ToArray()))
using (var engine = new TesseractEngine(@"./Tesseract", "eng", EngineMode.Default))
{
var result = engine.Process(img);
Tag_extract = result.GetText();
}
}
}
}
}
public override void ucLoaded()
{
// El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion
base.ucLoaded();
}
}
public partial class ucExtraccionTag : UserControl, IDataContainer
{
public osBase? Datos { get; set; }
public ucExtraccionTag()
{
InitializeComponent();
this.Loaded += OnLoaded;
this.Unloaded += OnUnloaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Datos?.ucLoaded();
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
Datos?.ucUnLoaded();
}
public void Resize(float width, float height)
{
if (Datos is osExtraccionTag datos)
{
datos.Ancho = PixelToMeter.Instance.calc.PixelsToMeters(width);
datos.Alto = PixelToMeter.Instance.calc.PixelsToMeters(height);
}
}
public void Move(float LeftPixels, float TopPixels)
{
if (Datos != null)
{
Datos.Left = PixelToMeter.Instance.calc.PixelsToMeters(LeftPixels);
Datos.Top = PixelToMeter.Instance.calc.PixelsToMeters(TopPixels);
}
}
public void Rotate(float Angle)
{
if (Datos != null)
if (Datos is osExtraccionTag datos)
datos.Angulo = Angle;
}
public void Highlight(bool State) { }
public int ZIndex()
{
return 1;
}
}
}

View File

@ -13,6 +13,8 @@ using System.Diagnostics;
using System.Windows.Shapes; using System.Windows.Shapes;
using System.Windows.Controls; using System.Windows.Controls;
using System.ComponentModel; using System.ComponentModel;
using System.Configuration;
using System.Windows.Threading;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -59,7 +61,8 @@ namespace CtrEditor.ObjetosSim
public virtual string Nombre { get; set; } = "osBase"; public virtual string Nombre { get; set; } = "osBase";
[JsonIgnore] [JsonIgnore]
private Storyboard _storyboard; private Storyboard _storyboard;
private System.Threading.Timer timer = null;
[ObservableProperty] [ObservableProperty]
private float left; private float left;
@ -83,6 +86,11 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty] [ObservableProperty]
private string group_Panel; private string group_Panel;
[ObservableProperty]
private bool enable_on_all_pages;
partial void OnTopChanged(float value) partial void OnTopChanged(float value)
{ {
CanvasSetTopinMeter(value); CanvasSetTopinMeter(value);
@ -96,6 +104,32 @@ namespace CtrEditor.ObjetosSim
public virtual void TopChanged(float value) { } public virtual void TopChanged(float value) { }
public virtual void TopChanging(float oldValue, float newValue) { } public virtual void TopChanging(float oldValue, float newValue) { }
private async void TimerCallback(object state)
{
await Task.Delay(500); // Esperar 0.5 segundos antes de ejecutar la función
Application.Current.Dispatcher.Invoke(() =>
{
// Realiza tus cambios en la interfaz de usuario aquí
OnTimerAfterMovement();
});
}
/// <summary>
/// Este timer se usa para llamar a OnTimerAfterMovement luego de que han pasado 500ms sin que se
/// llame a ResetTimer.
/// Esto es util para no actualizar las simulaciones o controles mientras se esta moviendo aun el control.
/// Se debe hacer overrride de OnTimerAfterMovement y dentro de esta funcion llamar a la actualizacion que se
/// requiere hacer una vez terminado el movimiento del control por parte del usuario.
/// </summary>
public void ResetTimer()
{
if (timer == null)
timer = new System.Threading.Timer(TimerCallback, null, Timeout.Infinite, Timeout.Infinite);
timer.Change(500, Timeout.Infinite);
}
public virtual void OnTimerAfterMovement() { }
/// <summary> /// <summary>
/// Usado para saber cuando un objeto fue creado manualmente o por algun generador /// Usado para saber cuando un objeto fue creado manualmente o por algun generador
/// Mas adelante la idea es poder eliminar o tratar de manera diferente a estos objetos /// Mas adelante la idea es poder eliminar o tratar de manera diferente a estos objetos

View File

@ -7,23 +7,6 @@
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim" xmlns:vm="clr-namespace:CtrEditor.ObjetosSim"
mc:Ignorable="d"> mc:Ignorable="d">
<UserControl.Resources>
<!-- Define the VisualBrush for the conveyor belt pattern -->
<VisualBrush x:Key="BeltBrush" TileMode="Tile" Viewport="0,0,20,10" ViewportUnits="Absolute" Viewbox="0,0,20,10" ViewboxUnits="Absolute">
<VisualBrush.Transform>
<TransformGroup>
<TranslateTransform/>
</TransformGroup>
</VisualBrush.Transform>
<VisualBrush.Visual>
<Canvas>
<Rectangle Fill="Gray" Width="10" Height="10"/>
<Rectangle Fill="DarkGray" Width="10" Height="10" Canvas.Left="10"/>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</UserControl.Resources>
<UserControl.DataContext> <UserControl.DataContext>
<vm:osBasicExample Ancho="2"/> <vm:osBasicExample Ancho="2"/>
</UserControl.DataContext> </UserControl.DataContext>

BIN
Tesseract/eng.traineddata Normal file

Binary file not shown.

BIN
Tesseract/ita.traineddata Normal file

Binary file not shown.

BIN
Tesseract/spa.traineddata Normal file

Binary file not shown.