Compare commits

...

5 Commits

21 changed files with 1548 additions and 186 deletions

View File

@ -27,22 +27,27 @@
<ItemGroup> <ItemGroup>
<None Remove="app2.png" /> <None Remove="app2.png" />
<None Remove="CtrEditorE.png" /> <None Remove="CtrEditorE.png" />
<None Remove="Icons\allselect.png" />
<None Remove="Icons\analyze.png" />
<None Remove="Icons\app.256x256.ico" /> <None Remove="Icons\app.256x256.ico" />
<None Remove="Icons\app.png" /> <None Remove="Icons\app.png" />
<None Remove="Icons\app2.128x128.ico" /> <None Remove="Icons\app2.128x128.ico" />
<None Remove="Icons\app2.256x256.ico" /> <None Remove="Icons\app2.256x256.ico" />
<None Remove="Icons\app2.png" /> <None Remove="Icons\app2.png" />
<None Remove="Icons\borrar.png" /> <None Remove="Icons\borrar.png" />
<None Remove="Icons\choose.png" />
<None Remove="Icons\connect.png" /> <None Remove="Icons\connect.png" />
<None Remove="Icons\CtrEditorA.png" /> <None Remove="Icons\CtrEditorA.png" />
<None Remove="Icons\CtrEditorC.png" /> <None Remove="Icons\CtrEditorC.png" />
<None Remove="Icons\CtrEditorE.png" /> <None Remove="Icons\CtrEditorE.png" />
<None Remove="Icons\disconnect.png" /> <None Remove="Icons\disconnect.png" />
<None Remove="Icons\duplicate.png" /> <None Remove="Icons\duplicate.png" />
<None Remove="Icons\extract.png" />
<None Remove="Icons\fotocelula.png" /> <None Remove="Icons\fotocelula.png" />
<None Remove="Icons\save.png" /> <None Remove="Icons\save.png" />
<None Remove="Icons\start.png" /> <None Remove="Icons\start.png" />
<None Remove="Icons\stop.png" /> <None Remove="Icons\stop.png" />
<None Remove="Icons\unselect.png" />
<None Remove="imagenes\filler.png" /> <None Remove="imagenes\filler.png" />
<None Remove="imagenes\gear.png" /> <None Remove="imagenes\gear.png" />
<None Remove="imagenes\motorNegro.png" /> <None Remove="imagenes\motorNegro.png" />
@ -65,6 +70,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Aether.Physics2D" Version="2.1.0" /> <PackageReference Include="Aether.Physics2D" Version="2.1.0" />
<PackageReference Include="ClosedXML" Version="0.104.0-preview2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="Emgu.CV" Version="4.9.0.5494" /> <PackageReference Include="Emgu.CV" Version="4.9.0.5494" />
<PackageReference Include="Emgu.CV.runtime.windows" Version="4.9.0.5494" /> <PackageReference Include="Emgu.CV.runtime.windows" Version="4.9.0.5494" />
@ -88,19 +94,26 @@
<ItemGroup> <ItemGroup>
<Resource Include="app2.png" /> <Resource Include="app2.png" />
<Resource Include="CtrEditorE.png" /> <Resource Include="CtrEditorE.png" />
<Resource Include="Icons\allselect.png" />
<Resource Include="Icons\analyze.png" />
<Resource Include="Icons\app.png" /> <Resource Include="Icons\app.png" />
<Resource Include="Icons\app2.png" /> <Resource Include="Icons\app2.png" />
<Resource Include="Icons\borrar.png" /> <Resource Include="Icons\borrar.png" />
<Resource Include="Icons\choose.png" />
<Resource Include="Icons\connect.png" /> <Resource Include="Icons\connect.png" />
<Resource Include="Icons\CtrEditorA.png" /> <Resource Include="Icons\CtrEditorA.png" />
<Resource Include="Icons\CtrEditorC.png" /> <Resource Include="Icons\CtrEditorC.png" />
<Resource Include="Icons\CtrEditorE.png" /> <Resource Include="Icons\CtrEditorE.png" />
<Resource Include="Icons\disconnect.png" /> <Resource Include="Icons\disconnect.png" />
<Resource Include="Icons\duplicate.png" /> <Resource Include="Icons\duplicate.png" />
<Resource Include="Icons\extract.png">
<CopyToOutputDirectory></CopyToOutputDirectory>
</Resource>
<Resource Include="Icons\fotocelula.png" /> <Resource Include="Icons\fotocelula.png" />
<Resource Include="Icons\save.png" /> <Resource Include="Icons\save.png" />
<Resource Include="Icons\start.png" /> <Resource Include="Icons\start.png" />
<Resource Include="Icons\stop.png" /> <Resource Include="Icons\stop.png" />
<Resource Include="Icons\unselect.png" />
<Resource Include="imagenes\filler.png" /> <Resource Include="imagenes\filler.png" />
<Resource Include="imagenes\gear.png" /> <Resource Include="imagenes\gear.png" />
<Resource Include="imagenes\motorNegro.png" /> <Resource Include="imagenes\motorNegro.png" />

BIN
Icons/allselect.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
Icons/analyze.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
Icons/choose.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
Icons/extract.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
Icons/unselect.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -17,7 +17,12 @@ 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; using System.Windows.Data;
using CtrEditor.ObjetosSim.Extraccion_Datos;
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using CommunityToolkit.Mvvm.Input;
using CtrEditor.PopUps;
using CtrEditor.ObjetosSim.UserControls;
namespace CtrEditor namespace CtrEditor
{ {
@ -56,12 +61,21 @@ namespace CtrEditor
public ICommand TBSaveCommand { get; } public ICommand TBSaveCommand { get; }
public ICommand TBConnectPLCCommand { get; } public ICommand TBConnectPLCCommand { get; }
public ICommand TBDisconnectPLCCommand { get; } public ICommand TBDisconnectPLCCommand { get; }
public ICommand TBExtractTagsCommand { get; }
public ICommand TBEliminarUserControlCommand { get; } public ICommand TBEliminarUserControlCommand { get; }
public ICommand TBDuplicarUserControlCommand { get; } public ICommand TBDuplicarUserControlCommand { get; }
public ICommand OpenWorkDirectoryCommand { 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 // Evento que se dispara cuando se selecciona una nueva imagen
public event EventHandler<string> ImageSelected; public event EventHandler<string> ImageSelected;
public event EventHandler<TickSimulacionEventArgs> TickSimulacion; public event EventHandler<TickSimulacionEventArgs> TickSimulacion;
@ -140,11 +154,11 @@ namespace CtrEditor
} }
[ObservableProperty] [ObservableProperty]
private osBase selectedItemOsList; private TreeItemViewModel selectedItemOsList;
partial void OnSelectedItemOsListChanged(osBase value) partial void OnSelectedItemOsListChanged(TreeItemViewModel value)
{ {
if (value != null) if (value.Item != null)
habilitarEliminarUserControl = true; habilitarEliminarUserControl = true;
else else
habilitarEliminarUserControl = false; habilitarEliminarUserControl = false;
@ -170,6 +184,8 @@ namespace CtrEditor
datosDeTrabajo = new DatosDeTrabajo(); datosDeTrabajo = new DatosDeTrabajo();
ObjetosSimulables = new ObservableCollection<osBase>(); ObjetosSimulables = new ObservableCollection<osBase>();
TypeDecorationManager.AddExpandableIListConverter<osBase>(objetosSimulables.GetType());
ListaOsBase = new ObservableCollection<TipoSimulable>(); ListaOsBase = new ObservableCollection<TipoSimulable>();
@ -197,6 +213,15 @@ namespace CtrEditor
TBEliminarUserControlCommand = new RelayCommand(EliminarUserControl, () => habilitarEliminarUserControl); TBEliminarUserControlCommand = new RelayCommand(EliminarUserControl, () => habilitarEliminarUserControl);
TBDuplicarUserControlCommand = new RelayCommand(DuplicarUserControl, () => habilitarEliminarUserControl); 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);
stopwatch_Sim = new Stopwatch(); stopwatch_Sim = new Stopwatch();
stopwatch_Sim.Start(); stopwatch_Sim.Start();
} }
@ -252,6 +277,8 @@ namespace CtrEditor
// Asignar los datos al UserControl // Asignar los datos al UserControl
UserControlFactory.AssignDatos(userControl, osObjeto, simulationManager); UserControlFactory.AssignDatos(userControl, osObjeto, simulationManager);
osObjeto._mainViewModel = this; osObjeto._mainViewModel = this;
if (osObjeto.Id == null) // Para los objetos salvados antes de usar UniqueID
osObjeto.Id = new UniqueId().ObtenerNuevaID();
MainWindow.AgregarRegistrarUserControlCanvas(userControl); MainWindow.AgregarRegistrarUserControlCanvas(userControl);
@ -272,11 +299,17 @@ namespace CtrEditor
private void DuplicarUserControl() private void DuplicarUserControl()
{ {
if (SelectedItemOsList is osBase objDuplicar) if (SelectedItemOsList.Item is osBase objDuplicar)
DuplicarObjeto(objDuplicar, 0.5f, 0.5f);
}
public osBase DuplicarObjeto(osBase objDuplicar, float OffsetX, float OffsetY)
{ {
StopSimulation(); StopSimulation();
DisconnectPLC(); DisconnectPLC();
osBase? NuevoObjetoDuplicado = null;
objDuplicar.SalvarDatosNoSerializables(); objDuplicar.SalvarDatosNoSerializables();
var settings = new JsonSerializerSettings var settings = new JsonSerializerSettings
@ -291,33 +324,15 @@ namespace CtrEditor
// Serializar // Serializar
var serializedData = JsonConvert.SerializeObject(objDuplicar, settings); var serializedData = JsonConvert.SerializeObject(objDuplicar, settings);
// Duplicar // Duplicar
var NuevoObjetoDuplicado = JsonConvert.DeserializeObject<osBase>(serializedData, settings); NuevoObjetoDuplicado = JsonConvert.DeserializeObject<osBase>(serializedData, settings);
if (NuevoObjetoDuplicado != null) if (NuevoObjetoDuplicado != null)
{ {
string nombre = NuevoObjetoDuplicado.Nombre; NuevoObjetoDuplicado.Id.ObtenerNuevaID();
string nombre = NuevoObjetoDuplicado.Nombre + "_" + NuevoObjetoDuplicado.Id.Value;
// Expresión regular para identificar un nombre que termina con _número
Regex regex = new Regex(@"_(\d+)$");
if (regex.IsMatch(nombre))
{
// Extraer el número actual y sumarle 1
var match = regex.Match(nombre);
int numeroActual = int.Parse(match.Groups[1].Value);
int nuevoNumero = numeroActual + 1;
// Reemplazar el número en el nombre
nombre = regex.Replace(nombre, $"_{nuevoNumero}");
}
else
{
// Si no termina con _número, añadir _1
nombre += "_1";
}
NuevoObjetoDuplicado.Nombre = nombre; NuevoObjetoDuplicado.Nombre = nombre;
NuevoObjetoDuplicado.Left += 0.5f; NuevoObjetoDuplicado.Left += OffsetX;
NuevoObjetoDuplicado.Top += 0.5f; NuevoObjetoDuplicado.Top += OffsetY;
ObjetosSimulables.Add(NuevoObjetoDuplicado); ObjetosSimulables.Add(NuevoObjetoDuplicado);
CrearUserControlDesdeObjetoSimulable(NuevoObjetoDuplicado); CrearUserControlDesdeObjetoSimulable(NuevoObjetoDuplicado);
} }
@ -330,18 +345,262 @@ namespace CtrEditor
{ {
objDuplicar.RestaurarDatosNoSerializables(); objDuplicar.RestaurarDatosNoSerializables();
} }
return NuevoObjetoDuplicado;
} }
}
private void EliminarUserControl() private void EliminarUserControl()
{ {
if (SelectedItemOsList is osBase objEliminar) if (SelectedItemOsList.Item is osBase objEliminar)
{ {
RemoverObjetoSimulable(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();
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()
{
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();
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()
{
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)
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.
int rowOffset = lastRowUsed == null ? 2 : lastRowUsed.RowNumber() + 1;
// Determina la columna fija más alta.
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)
{
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;
}
// 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;
}
int RowToRender = 0;
// Cloned Tag - Asignar las mismas columnas
foreach (var oFrom in osExtraccionTagBaseGrouped_List)
foreach (var oCloned in osExtraccionTagCloned_List)
{
if (oCloned.Cloned_from == oFrom.Id)
oCloned.Collumn_number = oFrom.Collumn_number;
RowToRender = Math.Max(RowToRender, oCloned.Copy_Number);
}
// 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
{
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;
}
}
}
// 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() private void InitializeTipoSimulableList()
{ {
var baseType = typeof(osBase); var baseType = typeof(osBase);
@ -484,7 +743,7 @@ namespace CtrEditor
{ {
// Guardar referencias temporales // Guardar referencias temporales
obj.SalvarDatosNoSerializables(); obj.SalvarDatosNoSerializables();
if (!obj.Enable_on_all_pages) if (!obj.Enable_On_All_Pages)
_objetosSimulables.Add(obj); _objetosSimulables.Add(obj);
else else
_objetosSimulablesAllPages.Add(obj); _objetosSimulablesAllPages.Add(obj);

View File

@ -91,35 +91,55 @@
<Button Command="{Binding TBStartSimulationCommand}" ToolTip="Iniciar Simulación" <Button Command="{Binding TBStartSimulationCommand}" ToolTip="Iniciar Simulación"
Style="{StaticResource StartStopButtonStyle}"> Style="{StaticResource StartStopButtonStyle}">
<StackPanel> <StackPanel>
<Image Source="Icons/start.png" Width="16" Height="16" /> <Image Source="Icons/start.png" Width="24" Height="24" />
<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="24" Height="24" />
<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="24" Height="24" />
<TextBlock Text="Guardar" /> <TextBlock Text="Guardar" />
</StackPanel> </StackPanel>
</Button> </Button>
<Button Command="{Binding TBConnectPLCCommand}" ToolTip="Conectar PLC" <Button Command="{Binding TBConnectPLCCommand}" ToolTip="Conectar PLC"
Style="{StaticResource ConnectDisconnectButtonStyle}"> Style="{StaticResource ConnectDisconnectButtonStyle}">
<StackPanel> <StackPanel>
<Image Source="Icons/connect.png" Width="16" Height="16" /> <Image Source="Icons/connect.png" Width="24" Height="24" />
<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="24" Height="24" />
<TextBlock Text="Desconectar" /> <TextBlock Text="Desconectar" />
</StackPanel> </StackPanel>
</Button> </Button>
<Button Command="{Binding TBExtractTagsCommand}" ToolTip="Extraer Tags">
<StackPanel>
<Image Source="Icons/extract.png" Width="24" Height="24" />
<TextBlock Text="Extraer Tags" />
</StackPanel>
</Button>
<Button Command="{Binding TBMultiPageExtractTagsCommand}" ToolTip="Extraer Tags in multiple pages.">
<StackPanel>
<Image Source="Icons/extract.png" Width="24" Height="24" />
<TextBlock Text="Multi Page Extract" />
</StackPanel>
</Button>a
<Button Command="{Binding TBMultiPageAnalizeCommand}"
ToolTip="Analyze Tags in multiple pages.">
<StackPanel>
<Image Source="Icons/analyze.png" Width="24" Height="24" />
<TextBlock Text="Multi Page Analyze" />
</StackPanel>
</Button>
</ToolBar> </ToolBar>
</ToolBarTray> </ToolBarTray>
@ -143,6 +163,7 @@
<!-- Tercera Columna --> <!-- Tercera Columna -->
<Grid Grid.Column="2"> <Grid Grid.Column="2">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" MinHeight="100" /> <RowDefinition Height="*" MinHeight="100" />
<!-- ListBox1 --> <!-- ListBox1 -->
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
@ -153,36 +174,47 @@
<!-- ToolBarTray --> <!-- ToolBarTray -->
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- ListBox --> <ToolBarTray Grid.Row="0">
<ListBox x:Name="ListaOs" Grid.Row="0" Margin="5" ItemsSource="{Binding ObjetosSimulables}" <ToolBar>
SelectedItem="{Binding SelectedItemOsList, Mode=TwoWay}" <Button Command="{Binding TBEliminarTodosCommand}" ToolTip="Eliminar Todos">
SelectionChanged="ListaOs_SelectionChanged"> <StackPanel>
<ListBox.ItemTemplate> <Image Source="Icons/borrar.png" Width="16" Height="16" />
<DataTemplate> <TextBlock Text="All Objects" />
<TextBlock Text="{Binding Nombre}"> </StackPanel>
<TextBlock.Style> </Button>
<Style TargetType="TextBlock"> <Button Command="{Binding TBEliminarAutoCreatedCommand}" ToolTip="Eliminar Auto">
<Style.Triggers> <StackPanel>
<DataTrigger Binding="{Binding Path=Enable_on_all_pages}" Value="True"> <Image Source="Icons/borrar.png" Width="16" Height="16" />
<Setter Property="Foreground" Value="Blue" /> <TextBlock Text="Auto Created" />
</DataTrigger> </StackPanel>
<DataTrigger Binding="{Binding Path=Enable_on_all_pages}" Value="False"> </Button>
<Setter Property="Foreground" Value="Black" /> <Button Command="{Binding TBEliminarClonedCommand}" ToolTip="Eliminar Cloned for tag Extraction">
</DataTrigger> <StackPanel>
</Style.Triggers> <Image Source="Icons/borrar.png" Width="16" Height="16" />
</Style> <TextBlock Text="Cloned" />
</TextBlock.Style> </StackPanel>
</TextBlock> </Button>
</DataTemplate> <Button Command="{Binding TBAssingPagesCommand}" ToolTip="Assing Pages">
</ListBox.ItemTemplate> <StackPanel>
</ListBox> <Image Source="Icons/choose.png" Width="16" Height="16" />
<TextBlock Text="Assing Pages" />
</StackPanel>
</Button>
</ToolBar>
</ToolBarTray>
<uc:TreeListControlOS x:Name="ListaOS" Grid.Row="1" Margin="5" ItemsSource="{Binding DataContext.ObjetosSimulables,
RelativeSource={RelativeSource AncestorType=Window}}"
SelectedItem="{Binding SelectedItemOsList, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=Window}}"
SelectionChanged="TreeListControl_SelectionChanged" />
<!-- GridSplitter --> <!-- GridSplitter -->
<GridSplitter Grid.Row="1" Height="5" HorizontalAlignment="Stretch" Background="Gray" <GridSplitter Grid.Row="2" Height="5" HorizontalAlignment="Stretch" Background="Gray"
ResizeDirection="Rows" VerticalAlignment="Center" /> ResizeDirection="Rows" VerticalAlignment="Center" />
<!-- PanelEdicion --> <!-- PanelEdicion -->
<xctk:PropertyGrid Grid.Row="2" Margin="5" x:Name="PanelEdicion" AutoGenerateProperties="False" <xctk:PropertyGrid Grid.Row="3" Margin="5" x:Name="PanelEdicion" AutoGenerateProperties="False"
ShowDescriptionByTooltip="True"> ShowDescriptionByTooltip="True">
<xctk:PropertyGrid.EditorDefinitions> <xctk:PropertyGrid.EditorDefinitions>
@ -282,7 +314,7 @@
</xctk:PropertyGrid.EditorDefinitions> </xctk:PropertyGrid.EditorDefinitions>
</xctk:PropertyGrid> </xctk:PropertyGrid>
<ToolBarTray Grid.Row="3"> <ToolBarTray Grid.Row="4">
<ToolBar> <ToolBar>
<Button Command="{Binding TBEliminarUserControlCommand}" ToolTip="Eliminar Control"> <Button Command="{Binding TBEliminarUserControlCommand}" ToolTip="Eliminar Control">
<StackPanel> <StackPanel>

View File

@ -9,6 +9,8 @@ using UserControl = System.Windows.Controls.UserControl;
using CtrEditor.ObjetosSim; using CtrEditor.ObjetosSim;
using System.Windows.Threading; using System.Windows.Threading;
using System.Diagnostics; using System.Diagnostics;
using CtrEditor.ObjetosSim.UserControls;
using DocumentFormat.OpenXml.Spreadsheet;
namespace CtrEditor namespace CtrEditor
@ -144,7 +146,7 @@ namespace CtrEditor
var viewModel = DataContext as MainViewModel; var viewModel = DataContext as MainViewModel;
if (viewModel != null) if (viewModel != null)
{ {
viewModel.SelectedItemOsList = datos; // Esto desencadenará ListaOs_SelectionChanged ListaOS.SelectedItem = ListaOS.FindViewModelForItem(datos); // Esto desencadenará ListaOs_SelectionChanged
} }
} }
@ -460,15 +462,6 @@ namespace CtrEditor
tt.Y = relativeY - cursorPosition.Y * st.ScaleY; tt.Y = relativeY - cursorPosition.Y * st.ScaleY;
} }
private void ListaOs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//PanelEdicion.Children.Clear(); // Limpiar el panel existente
UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion);
if (e.AddedItems.Count > 0 && e.AddedItems[0] is osBase selectedObject)
CargarPropiedadesosDatos(selectedObject);
}
private void CargarPropiedadesosDatos(osBase selectedObject) private void CargarPropiedadesosDatos(osBase selectedObject)
{ {
if (DataContext is MainViewModel viewModel) if (DataContext is MainViewModel viewModel)
@ -483,6 +476,14 @@ namespace CtrEditor
} }
} }
private void TreeListControl_SelectionChanged(object sender, ObjetosSim.UserControls.SelectionChangedEventArgs e)
{
//PanelEdicion.Children.Clear(); // Limpiar el panel existente
UserControlFactory.LimpiarPropiedadesosDatos(PanelEdicion);
if (e.SelectedItem.Item != null && e.SelectedItem.Item is osBase selectedObject)
CargarPropiedadesosDatos(selectedObject);
}
} }
public class FloatValidationRule : ValidationRule public class FloatValidationRule : ValidationRule

View File

@ -5,7 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos" mc:Ignorable="d" xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos" mc:Ignorable="d"
Visibility="{Binding Show_on_this_page, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding Show_On_This_Page, Converter={StaticResource BoolToVisibilityConverter}}">
<UserControl.DataContext> <UserControl.DataContext>
<vm:osBuscarCoincidencias /> <vm:osBuscarCoincidencias />

View File

@ -18,6 +18,12 @@ using Ookii.Dialogs.Wpf;
using Rect = System.Windows.Rect; using Rect = System.Windows.Rect;
using System.ComponentModel; using System.ComponentModel;
using Newtonsoft.Json; using Newtonsoft.Json;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using System.ComponentModel;
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Spreadsheet;
using Colors = System.Windows.Media.Colors;
using DocumentFormat.OpenXml.Drawing.Charts;
namespace CtrEditor.ObjetosSim.Extraccion_Datos namespace CtrEditor.ObjetosSim.Extraccion_Datos
{ {
@ -49,6 +55,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
} }
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
bool search_templates; bool search_templates;
partial void OnSearch_templatesChanged(bool oldValue, bool newValue) partial void OnSearch_templatesChanged(bool oldValue, bool newValue)
@ -59,9 +66,11 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
} }
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
bool export_ocr; bool export_ocr;
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
string text_export_ocr; string text_export_ocr;
partial void OnExport_ocrChanged(bool value) partial void OnExport_ocrChanged(bool value)
@ -98,38 +107,45 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
[ObservableProperty] [ObservableProperty]
[property: Description("Width of the object.")] [property: Description("Width of the object.")]
[property: Category("Position:")] [property: Category("Layout:")]
public float ancho; public float ancho;
[ObservableProperty] [ObservableProperty]
[property: Description("Height of the object.")] [property: Description("Height of the object.")]
[property: Category("Position:")] [property: Category("Layout:")]
public float alto; public float alto;
[ObservableProperty] [ObservableProperty]
[property: Category("Layout:")]
public float angulo; public float angulo;
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
string tag_extract; string tag_extract;
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
string clase; string clase;
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
string tag_name; string tag_name;
[ObservableProperty] [ObservableProperty]
float opacity_oculto; float opacity_oculto;
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
bool show_debug_ocr; bool show_debug_ocr;
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
float threshold; float threshold;
[ObservableProperty] [ObservableProperty]
float coincidencias; [property: Category("Tag Extraction:")]
[property: ReadOnly(true)]
int coincidencias;
public osBuscarCoincidencias() public osBuscarCoincidencias()
{ {
@ -158,7 +174,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
previewWindow.ShowDialog(); previewWindow.ShowDialog();
} }
private async void BuscarCoincidencias() public async void BuscarCoincidencias()
{ {
var progressDialog = new ProgressDialog var progressDialog = new ProgressDialog
{ {
@ -179,8 +195,6 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
progressDialog.Show(); progressDialog.Show();
} }
private void BuscarCoincidenciasAsync(ProgressDialog progressDialog) private void BuscarCoincidenciasAsync(ProgressDialog progressDialog)
{ {
// Reset the Canvas children // Reset the Canvas children
@ -258,13 +272,14 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
int ConteoPositivos = 0; int ConteoPositivos = 0;
// Lista para mantener áreas ya aceptadas // Lista para mantener áreas ya aceptadas
List<Rectangle> acceptedRectangles = new List<Rectangle>();
if (search_rectangles != null) if (search_rectangles != null)
search_rectangles.Clear(); search_rectangles.Clear();
else else
search_rectangles = new List<Rect>(); search_rectangles = new List<Rect>();
// Añadir el rectángulo usado por croppedBitmap a search_rectangles
//search_rectangles.Add(new Rect(x / scaleFactorX, y / scaleFactorY, width / scaleFactorX, height / scaleFactorY));
// Obtener los puntos que superan el umbral // Obtener los puntos que superan el umbral
float[] resultArray = result.GetData(false) as float[]; float[] resultArray = result.GetData(false) as float[];
if (resultArray != null) if (resultArray != null)
@ -296,17 +311,15 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
Canvas.SetTop(matchRect, newRect.Y); Canvas.SetTop(matchRect, newRect.Y);
// Verificar si la coincidencia actual está dentro de algún rectángulo aceptado // Verificar si la coincidencia actual está dentro de algún rectángulo aceptado
bool isOverlap = acceptedRectangles.Any(r => bool isOverlap = search_rectangles.Any(r =>
new Rect(Canvas.GetLeft(r), Canvas.GetTop(r), r.Width, r.Height).IntersectsWith( r.IntersectsWith(newRect)
new Rect(Canvas.GetLeft(matchRect), Canvas.GetTop(matchRect), matchRect.Width, matchRect.Height) );
));
// Si no hay superposición, agregar el rectángulo al Canvas y a la lista de aceptados // Si no hay superposición, agregar el rectángulo al Canvas y a la lista de aceptados
if (!isOverlap) if (!isOverlap)
{ {
Canvas.SetZIndex(matchRect, 40); Canvas.SetZIndex(matchRect, 40);
_mainViewModel.MainCanvas.Children.Add(matchRect); _mainViewModel.MainCanvas.Children.Add(matchRect);
acceptedRectangles.Add(matchRect);
search_rectangles.Add(newRect); search_rectangles.Add(newRect);
ConteoPositivos++; ConteoPositivos++;
@ -317,6 +330,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
} }
} }
} }
PopularTagExtraction();
} }
} }
} }
@ -324,6 +338,57 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
} }
public void PopularTagExtraction()
{
var objetosSimulablesCopy = new List<osBase>(_mainViewModel.ObjetosSimulables);
foreach (var obj in objetosSimulablesCopy)
if (obj is osExtraccionTag objExtraccionTag)
if (objExtraccionTag.Id_Search_Templates == this.Nombre && objExtraccionTag.Cloned)
_mainViewModel.ObjetosSimulables.Remove(objExtraccionTag);
var objetosSimulables2Copy = new List<osBase>(_mainViewModel.ObjetosSimulables);
// Saltar el primer rectángulo en el foreach
int Row = 0;
foreach (var rectangle in search_rectangles) //.Skip(1))
{
float offsetX = PixelsToMeters((float)rectangle.X) - Left;
float offsetY = PixelsToMeters((float)rectangle.Y) - Top;
osExtraccionTag newObj = null;
foreach (var eTag in objetosSimulables2Copy)
{
if (eTag is osExtraccionTag objExtraccionTag)
{
if (objExtraccionTag.Id_Search_Templates == this.Nombre)
{
newObj = (osExtraccionTag)_mainViewModel.DuplicarObjeto(objExtraccionTag, offsetX, offsetY);
if (newObj != null)
{
newObj.Cloned = true;
newObj.Cloned_from = objExtraccionTag.Id;
newObj.Copy_Number = Row;
newObj.Enable_On_All_Pages = false;
if (newObj.Extraer)
objExtraccionTag.CaptureImageAreaAndDoOCR();
}
}
}
}
Row++;
if (newObj != null)
newObj.New_Row = true;
}
}
public static int FindFirstEmptyRow(IXLWorksheet worksheet)
{
var lastRowUsed = worksheet.LastRowUsed();
return lastRowUsed == null ? 1 : lastRowUsed.RowNumber() + 1;
}
// Método para convertir BitmapSource a Mat // Método para convertir BitmapSource a Mat
private Mat BitmapSourceToMat(BitmapSource bitmapSource) private Mat BitmapSourceToMat(BitmapSource bitmapSource)
{ {

View File

@ -6,22 +6,30 @@
xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos" xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos"
mc:Ignorable="d" mc:Ignorable="d"
Visibility="{Binding Show_on_this_page, Converter={StaticResource BoolToVisibilityConverter}}"> Visibility="{Binding Show_On_This_Page, Converter={StaticResource BoolToVisibilityConverter}}">
<UserControl.DataContext> <UserControl.DataContext>
<vm:osExtraccionTag/> <vm:osExtraccionTag/>
</UserControl.DataContext> </UserControl.DataContext>
<Canvas> <Canvas>
<Rectangle x:Name="Area" <Rectangle x:Name="Area" Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}" Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}"
Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}" Opacity="{Binding Opacity_oculto}" Fill="Green" Opacity="{Binding Opacity_oculto}" Fill="Green" Stroke="Black">
Stroke="Black"
>
<Rectangle.RenderTransform>
<RotateTransform Angle="{Binding Angulo}"/>
</Rectangle.RenderTransform>
</Rectangle> </Rectangle>
<Viewbox Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}"
Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}">
<Label Content="{Binding Angulo}" VerticalAlignment="Top" HorizontalAlignment="Center"
RenderTransformOrigin="0.5,0.5" Opacity="0.1">
<Label.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="{Binding Angulo}" />
<TranslateTransform />
</TransformGroup>
</Label.RenderTransform>
</Label>
</Viewbox>
</Canvas> </Canvas>
</UserControl> </UserControl>

View File

@ -4,7 +4,9 @@ using System.Windows.Navigation;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.Simulacion; using CtrEditor.Simulacion;
using Newtonsoft.Json; using Newtonsoft.Json;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using System.ComponentModel;
using ClosedXML.Excel;
namespace CtrEditor.ObjetosSim.Extraccion_Datos namespace CtrEditor.ObjetosSim.Extraccion_Datos
{ {
@ -15,10 +17,6 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
public partial class osExtraccionTag : osBase, IosBase public partial class osExtraccionTag : osBase, IosBase
{ {
private osBase _osMotor = null;
private simTransporte SimGeometria;
public static string NombreClase() public static string NombreClase()
{ {
return "Extraccion Tags"; return "Extraccion Tags";
@ -31,8 +29,12 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
} }
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
bool extraer; bool extraer;
[ObservableProperty]
bool new_Row;
public override void TopChanged(float value) public override void TopChanged(float value)
{ {
base.TopChanged(value); base.TopChanged(value);
@ -51,6 +53,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
} }
[ObservableProperty] [ObservableProperty]
[property: Category("Layout:")]
public float ancho; public float ancho;
partial void OnAnchoChanged(float value) partial void OnAnchoChanged(float value)
@ -59,6 +62,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
} }
[ObservableProperty] [ObservableProperty]
[property: Category("Layout:")]
public float alto; public float alto;
partial void OnAltoChanged(float value) partial void OnAltoChanged(float value)
@ -66,25 +70,77 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
ResetTimer(); ResetTimer();
} }
[ObservableProperty]
[property: Category("Layout:")]
public float angulo;
partial void OnAnguloChanged(float value)
{
ResetTimer();
}
public override void OnTimerAfterMovement() { public override void OnTimerAfterMovement() {
Angulo = (float)Math.Round(Angulo / 90) * 90;
if (Extraer) if (Extraer)
CaptureImageAreaAndDoOCR(); CaptureImageAreaAndDoOCR();
} }
[ObservableProperty]
osBuscarCoincidencias search_Templates; private osBuscarCoincidencias Search_Templates;
[ObservableProperty] [ObservableProperty]
public float angulo; [property: Description("Link to Search Templates")]
[property: Category("Tag Extraction:")]
[property: ItemsSource(typeof(osBaseItemsSource<osBuscarCoincidencias>))]
string id_Search_Templates;
partial void OnId_Search_TemplatesChanged(string value)
{
if (Search_Templates != null)
Search_Templates.PropertyChanged -= OnMotorPropertyChanged;
if (_mainViewModel != null && value != null && value.Length > 0)
{
Search_Templates = (osBuscarCoincidencias)_mainViewModel.ObjetosSimulables.FirstOrDefault(s => (s is osBuscarCoincidencias && s.Nombre == value), null);
if (Search_Templates != null)
Search_Templates.PropertyChanged += OnMotorPropertyChanged;
}
}
private void OnMotorPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(osBuscarCoincidencias.Nombre))
{
Id_Search_Templates = ((osBuscarCoincidencias)sender).Nombre;
}
}
[ObservableProperty] [ObservableProperty]
[property: Category("Tag Extraction:")]
string tag_extract; string tag_extract;
[ObservableProperty] [ObservableProperty]
[property: Category("Export:")]
string clase; string clase;
[ObservableProperty] [ObservableProperty]
string tag_name; [property: Category("Export:")]
string collumn_name;
[ObservableProperty]
[property: Description("Excel collumn.")]
[property: Category("Export:")]
int collumn_number;
[ObservableProperty]
[property: Category("Tag Extraction:")]
[property: ReadOnly(true)]
int copy_Number;
[ObservableProperty]
[property: Category("Tag Extraction:")]
bool show_Debug_Window;
[ObservableProperty] [ObservableProperty]
float opacity_oculto; float opacity_oculto;
@ -99,15 +155,23 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
public void CaptureImageAreaAndDoOCR() public void CaptureImageAreaAndDoOCR()
{ {
Tag_extract = CaptureImageAreaAndDoOCR(Left, Top, Ancho, Alto); Tag_extract = CaptureImageAreaAndDoOCR(Left, Top, Ancho, Alto, Angulo, Show_Debug_Window);
} }
public int ExportToExcel(IXLWorksheet worksheet, int row, int colBase)
{
// Agregar Tag
worksheet.Cell(row + 2, Collumn_number + colBase).Value = Tag_extract;
return Collumn_number + colBase;
}
public override void ucLoaded() public override void ucLoaded()
{ {
// El UserControl ya se ha cargado y podemos obtener las coordenadas para // El UserControl ya se ha cargado y podemos obtener las coordenadas para
// crear el objeto de simulacion // crear el objeto de simulacion
base.ucLoaded(); base.ucLoaded();
OnId_Search_TemplatesChanged(Id_Search_Templates); // Actualizar Link
} }
} }

View File

@ -0,0 +1,20 @@
<UserControl x:Class="CtrEditor.ObjetosSim.UserControls.TreeListControlOS"
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:local="clr-namespace:CtrEditor.ObjetosSim.UserControls"
mc:Ignorable="d"
DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}">
<Grid>
<TreeView x:Name="treeView" ItemsSource="{Binding Items}" SelectedItemChanged="TreeView_SelectedItemChanged"
local:TreeViewSelectedItemExBehavior.SelectedItemEx="{Binding SelectedItemTreeViewSs}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Item.Nombre}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</UserControl>

View File

@ -0,0 +1,365 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Xceed.Wpf.Toolkit.Primitives;
namespace CtrEditor.ObjetosSim.UserControls
{
/// <summary>
/// Interaction logic for TreeListControlOS.xaml
/// </summary>
public partial class TreeListControlOS : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
nameof(ItemsSource), typeof(ObservableCollection<osBase>), typeof(TreeListControlOS), new PropertyMetadata(null, OnItemsSourceChanged));
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
nameof(SelectedItem), typeof(TreeItemViewModel), typeof(TreeListControlOS), new PropertyMetadata(null, OnSelectedItemChanged));
public event EventHandler<SelectionChangedEventArgs> SelectionChanged;
public ObservableCollection<osBase> ItemsSource
{
get => (ObservableCollection<osBase>)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}
public TreeItemViewModel SelectedItem
{
get => (TreeItemViewModel)GetValue(SelectedItemProperty);
set => SetValue(SelectedItemProperty, value);
}
public ObservableCollection<TreeItemViewModel> Items { get; set; } = new ObservableCollection<TreeItemViewModel>();
public TreeListControlOS()
{
InitializeComponent();
DataContext = this;
}
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TreeListControlOS control)
{
control.LoadItems((ObservableCollection<osBase>)e.NewValue);
}
}
private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TreeListControlOS control && e.NewValue is TreeItemViewModel newItem)
{
// Update the TreeView selection if necessary
control.UpdateTreeViewSelection(newItem);
control.OnSelectionChanged(new SelectionChangedEventArgs(newItem));
}
}
private void UpdateTreeViewSelection(TreeItemViewModel selectedItem)
{
if (treeView != null && selectedItem != null)
{
TreeViewSelectedItemExBehavior.SetSelectedItemEx(treeView, selectedItem);
}
}
public TreeItemViewModel FindViewModelForItem(osBase item)
{
foreach (var i in Items)
{
if (i.Item == item)
return i;
foreach (var child in i.Children)
if (child.Item == item)
return child;
}
return null;
}
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if (e.NewValue is TreeItemViewModel selectedItem)
{
SelectedItem = selectedItem;
OnSelectionChanged(new SelectionChangedEventArgs(selectedItem));
}
}
private void OnSelectionChanged(SelectionChangedEventArgs e)
{
SelectionChanged?.Invoke(this, e);
}
private void LoadItems(ObservableCollection<osBase> allItems)
{
Items.Clear();
if (allItems == null) return;
var rootItems = allItems.Where(i => !i.Cloned);
foreach (var item in rootItems)
{
Items.Add(new TreeItemViewModel(item, allItems));
}
}
}
public partial class vmTreeListControlOS : ObservableObject
{
[ObservableProperty]
private object selectedItemTreeViewSs = new object();
[ObservableProperty]
private ObservableCollection<object> selectedItemsTreeViewSs = new ObservableCollection<object>();
[ObservableProperty]
private ObservableCollection<TreeItemViewModel> itemsTreeViewSs = new ObservableCollection<TreeItemViewModel>();
}
public class TreeItemViewModel
{
public osBase Item { get; set; }
public ObservableCollection<TreeItemViewModel> Children { get; set; } = new ObservableCollection<TreeItemViewModel>();
public TreeItemViewModel(osBase item, ObservableCollection<osBase> allItems)
{
Item = item;
LoadChildren(allItems);
}
private void LoadChildren(ObservableCollection<osBase> allItems)
{
foreach (var child in allItems.Where(i => i.Cloned && i.Cloned_from == Item.Id))
{
Children.Add(new TreeItemViewModel(child, allItems));
}
}
}
// Cambia la clase SelectionChangedEventArgs
public class SelectionChangedEventArgs : EventArgs
{
public TreeItemViewModel SelectedItem { get; }
public SelectionChangedEventArgs(TreeItemViewModel selectedItem)
{
SelectedItem = selectedItem;
}
}
public static class TreeViewSelectedItemExBehavior
{
private static List<TreeView> isRegisteredToSelectionChanged = new List<TreeView>();
public static readonly DependencyProperty SelectedItemExProperty =
DependencyProperty.RegisterAttached("SelectedItemEx",
typeof(object),
typeof(TreeViewSelectedItemExBehavior),
new FrameworkPropertyMetadata(new object(), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemExChanged, null));
#region SelectedItemEx
public static object GetSelectedItemEx(TreeView target)
{
return target.GetValue(SelectedItemExProperty);
}
public static void SetSelectedItemEx(TreeView target, object value)
{
target.SetValue(SelectedItemExProperty, value);
var treeViewItemToSelect = GetTreeViewItem(target, value);
if (treeViewItemToSelect == null)
{
if (target.SelectedItem == null)
return;
var treeViewItemToUnSelect = GetTreeViewItem(target, target.SelectedItem);
treeViewItemToUnSelect.IsSelected = false;
}
else
treeViewItemToSelect.IsSelected = true;
}
public static void OnSelectedItemExChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
var treeView = depObj as TreeView;
if (treeView == null)
return;
if (!isRegisteredToSelectionChanged.Contains(treeView))
{
treeView.SelectedItemChanged += TreeView_SelectedItemChanged;
isRegisteredToSelectionChanged.Add(treeView);
}
}
#endregion
private static void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var treeView = (TreeView)sender;
SetSelectedItemEx(treeView, e.NewValue);
}
#region Helper Structures & Methods
public class MyVirtualizingStackPanel : VirtualizingStackPanel
{
/// <summary>
/// Publically expose BringIndexIntoView.
/// </summary>
public void BringIntoView(int index)
{
BringIndexIntoView(index);
}
}
/// <summary>Recursively search for an item in this subtree.</summary>
/// <param name="container">The parent ItemsControl. This can be a TreeView or a TreeViewItem.</param>
/// <param name="item">The item to search for.</param>
/// <returns>The TreeViewItem that contains the specified item.</returns>
private static TreeViewItem GetTreeViewItem(ItemsControl container, object item)
{
if (container != null)
{
if (container.DataContext == item)
{
return container as TreeViewItem;
}
// Expand the current container
if (container is TreeViewItem && !((TreeViewItem)container).IsExpanded)
{
container.SetValue(TreeViewItem.IsExpandedProperty, true);
}
// Try to generate the ItemsPresenter and the ItemsPanel.
// by calling ApplyTemplate. Note that in the
// virtualizing case even if the item is marked
// expanded we still need to do this step in order to
// regenerate the visuals because they may have been virtualized away.
container.ApplyTemplate();
ItemsPresenter itemsPresenter =
(ItemsPresenter)container.Template.FindName("ItemsHost", container);
if (itemsPresenter != null)
{
itemsPresenter.ApplyTemplate();
}
else
{
// The Tree template has not named the ItemsPresenter,
// so walk the descendents and find the child.
itemsPresenter = FindVisualChild<ItemsPresenter>(container);
if (itemsPresenter == null)
{
container.UpdateLayout();
itemsPresenter = FindVisualChild<ItemsPresenter>(container);
}
}
Panel itemsHostPanel = (Panel)VisualTreeHelper.GetChild(itemsPresenter, 0);
// Ensure that the generator for this panel has been created.
UIElementCollection children = itemsHostPanel.Children;
MyVirtualizingStackPanel virtualizingPanel =
itemsHostPanel as MyVirtualizingStackPanel;
for (int i = 0, count = container.Items.Count; i < count; i++)
{
TreeViewItem subContainer;
if (virtualizingPanel != null)
{
// Bring the item into view so
// that the container will be generated.
virtualizingPanel.BringIntoView(i);
subContainer =
(TreeViewItem)container.ItemContainerGenerator.
ContainerFromIndex(i);
}
else
{
subContainer =
(TreeViewItem)container.ItemContainerGenerator.
ContainerFromIndex(i);
// Bring the item into view to maintain the
// same behavior as with a virtualizing panel.
subContainer.BringIntoView();
}
if (subContainer != null)
{
// Search the next level for the object.
TreeViewItem resultContainer = GetTreeViewItem(subContainer, item);
if (resultContainer != null)
{
return resultContainer;
}
else
{
// The object is not under this TreeViewItem
// so collapse it.
subContainer.IsExpanded = false;
}
}
}
}
return null;
}
/// <summary>Search for an element of a certain type in the visual tree.</summary>
/// <typeparam name="T">The type of element to find.</typeparam>
/// <param name="visual">The parent element.</param>
/// <returns></returns>
private static T FindVisualChild<T>(Visual visual) where T : Visual
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
{
Visual child = (Visual)VisualTreeHelper.GetChild(visual, i);
if (child != null)
{
T correctlyTyped = child as T;
if (correctlyTyped != null)
{
return correctlyTyped;
}
T descendent = FindVisualChild<T>(child);
if (descendent != null)
{
return descendent;
}
}
}
return null;
}
#endregion
}
}

View File

@ -179,123 +179,158 @@ namespace CtrEditor.ObjetosSim
} }
public string CaptureImageAreaAndDoOCR(float Left, float Top, float Ancho, float Alto) public string CaptureImageAreaAndDoOCR(float Left, float Top, float Ancho, float Alto, float Angulo = 0, bool ShowPreview = false)
{ {
if (_mainViewModel?.MainCanvas.Children[0] is Image imagenDeFondo) if (_mainViewModel?.MainCanvas.Children[0] is Image imagenDeFondo)
{ {
// Asegurarse de que la imagen origen está disponible
if (imagenDeFondo.Source is BitmapSource bitmapSource) if (imagenDeFondo.Source is BitmapSource bitmapSource)
{ {
// Obtener los DPI de la imagen original
float originalDpiX = (float)bitmapSource.DpiX; float originalDpiX = (float)bitmapSource.DpiX;
float originalDpiY = (float)bitmapSource.DpiY; float originalDpiY = (float)bitmapSource.DpiY;
// Estándar DPI en el que el Canvas renderiza la imagen float canvasDpiX = 96;
float canvasDpiX = 96; // WPF usually renders at 96 DPI
float canvasDpiY = 96; float canvasDpiY = 96;
// Calcular el ratio de escala entre el Canvas y la imagen original
float scaleFactorX = originalDpiX / canvasDpiX; float scaleFactorX = originalDpiX / canvasDpiX;
float scaleFactorY = originalDpiY / canvasDpiY; float scaleFactorY = originalDpiY / canvasDpiY;
// Ajustar las coordenadas de recorte en función del ratio de escala
int x = (int)MeterToPixels(Left * scaleFactorX); int x = (int)MeterToPixels(Left * scaleFactorX);
int y = (int)MeterToPixels(Top * scaleFactorY); int y = (int)MeterToPixels(Top * scaleFactorY);
int width = (int)MeterToPixels(Ancho * scaleFactorX); int width = (int)MeterToPixels(Ancho * scaleFactorX);
int height = (int)MeterToPixels(Alto * scaleFactorY); 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 (x < 0) x = 0;
if (y < 0) y = 0; if (y < 0) y = 0;
if (x + width > bitmapSource.PixelWidth) width = bitmapSource.PixelWidth - x; if (x + width > bitmapSource.PixelWidth) width = bitmapSource.PixelWidth - x;
if (y + height > bitmapSource.PixelHeight) height = bitmapSource.PixelHeight - y; 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)); CroppedBitmap croppedBitmap = new CroppedBitmap(bitmapSource, new Int32Rect(x, y, width, height));
// Codificar el bitmap recortado a un MemoryStream TransformedBitmap transformedBitmap = new TransformedBitmap();
transformedBitmap.BeginInit();
transformedBitmap.Source = croppedBitmap;
if (Angulo != 0)
{
RotateTransform rotateTransform = new RotateTransform(-Angulo);
transformedBitmap.Transform = rotateTransform;
}
transformedBitmap.EndInit();
PngBitmapEncoder encoder = new PngBitmapEncoder(); PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(croppedBitmap)); encoder.Frames.Add(BitmapFrame.Create(transformedBitmap));
using (MemoryStream memoryStream = new MemoryStream()) using (MemoryStream memoryStream = new MemoryStream())
{ {
encoder.Save(memoryStream); encoder.Save(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin); memoryStream.Seek(0, SeekOrigin.Begin);
//ShowPreviewWindow(memoryStream); if (ShowPreview) ShowPreviewWindow(memoryStream);
// Cargar la imagen en Tesseract desde el MemoryStream using (var bmp = new System.Drawing.Bitmap(memoryStream))
using (var img = Pix.LoadFromMemory(memoryStream.ToArray())) {
int targetDpi = 400;
var resizedBmp = new System.Drawing.Bitmap(bmp, new System.Drawing.Size(bmp.Width * targetDpi / (int)originalDpiX, bmp.Height * targetDpi / (int)originalDpiY));
using (var msResized = new MemoryStream())
{
resizedBmp.Save(msResized, System.Drawing.Imaging.ImageFormat.Png);
msResized.Seek(0, SeekOrigin.Begin);
using (var img = Pix.LoadFromMemory(msResized.ToArray()))
using (var engine = new TesseractEngine(@"./Tesseract", "eng", EngineMode.Default)) using (var engine = new TesseractEngine(@"./Tesseract", "eng", EngineMode.Default))
{ {
// Configuraciones para mejorar el OCR de una sola letra
engine.SetVariable("tessedit_char_whitelist", " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-."); // Lista blanca de caracteres
var result = engine.Process(img); var result = engine.Process(img);
return result.GetText(); return result.GetText();
} }
} }
} }
} }
}
}
return ""; return "";
} }
// All Pages Objects // All Pages Objects
[NotifyPropertyChangedFor(nameof(Show_on_this_page))] [NotifyPropertyChangedFor(nameof(Show_On_This_Page))]
[ObservableProperty] [ObservableProperty]
[property: Description("Enable this object to be used in all pages.")] [property: Description("Enable this object to be used in all pages.")]
[property: Category("Layout:")] [property: Category("Layout:")]
private bool enable_on_all_pages; private bool enable_On_All_Pages;
partial void OnEnable_on_all_pagesChanged(bool value) partial void OnEnable_On_All_PagesChanged(bool value)
{ {
if (!value) if (!value)
Show_on_this_page = true; Show_On_This_Page = true;
} }
private List<string> Show_on_this_pages_oculto; [ObservableProperty]
[property: Hidden]
private List<string> showOnThisPagesList;
private bool show_on_this_page; private bool show_On_This_Page;
[property: Category("Layout:")] [property: Category("Layout:")]
public bool Show_on_this_page public bool Show_On_This_Page
{ {
get get
{ {
// Not global object if (!Enable_On_All_Pages)
if (!enable_on_all_pages)
{ {
if (Show_on_this_pages_oculto != null) showOnThisPagesList?.Clear();
Show_on_this_pages_oculto.Clear(); showOnThisPagesList = null;
Show_on_this_pages_oculto = null; show_On_This_Page = true;
show_on_this_page = true;
} }
else else
{ {
// Global Object if (showOnThisPagesList == null)
if (Show_on_this_pages_oculto == null) {
Show_on_this_pages_oculto = new List<string>(); showOnThisPagesList = new List<string> { _mainViewModel?.SelectedImage };
if (_mainViewModel == null || _mainViewModel.SelectedImage == null) show_on_this_page = false;
else show_on_this_page = Show_on_this_pages_oculto.Contains(_mainViewModel.SelectedImage);
} }
return show_on_this_page; show_On_This_Page = _mainViewModel?.SelectedImage != null && showOnThisPagesList.Contains(_mainViewModel.SelectedImage);
}
return show_On_This_Page;
} }
set set
{ {
// global object? if (Enable_On_All_Pages)
if (enable_on_all_pages)
{ {
// Global Object if (showOnThisPagesList == null)
if (Show_on_this_pages_oculto == null) {
Show_on_this_pages_oculto = new List<string>(); showOnThisPagesList = new List<string>();
if (_mainViewModel == null || _mainViewModel.SelectedImage == null) return; }
if (_mainViewModel?.SelectedImage == null) return;
if (value && !Show_on_this_pages_oculto.Contains(_mainViewModel.SelectedImage)) if (value)
Show_on_this_pages_oculto.Add(_mainViewModel.SelectedImage); {
else if (!value && Show_on_this_pages_oculto.Contains(_mainViewModel.SelectedImage)) if (!showOnThisPagesList.Contains(_mainViewModel.SelectedImage))
Show_on_this_pages_oculto.Remove(_mainViewModel.SelectedImage); {
} showOnThisPagesList.Add(_mainViewModel.SelectedImage);
SetProperty(ref show_on_this_page, value);
} }
} }
else
{
showOnThisPagesList.Remove(_mainViewModel.SelectedImage);
}
}
SetProperty(ref show_On_This_Page, value);
}
}
[ObservableProperty]
[property: Description("Autocreated and cloned with Search Templates")]
[property: Category("Tag Extraction:")]
bool cloned;
[ObservableProperty]
[property: Description("Autocreated and cloned with Search Templates")]
[property: Category("Tag Extraction:")]
[property: Hidden]
UniqueId cloned_from;
private async void TimerCallback(object state) private async void TimerCallback(object state)
{ {
@ -392,6 +427,7 @@ namespace CtrEditor.ObjetosSim
{ {
ActualizarLeftTop(); ActualizarLeftTop();
OnGroup_PanelChanged(Group_Panel); // Establece el link y se suscribe a los eventos OnGroup_PanelChanged(Group_Panel); // Establece el link y se suscribe a los eventos
Show_On_This_Page = Show_On_This_Page; // Update data
} }
/// <summary> /// <summary>
@ -810,6 +846,7 @@ namespace CtrEditor.ObjetosSim
public class UniqueId public class UniqueId
{ {
public int Value { get; set; } public int Value { get; set; }
public UniqueId ObtenerNuevaID() public UniqueId ObtenerNuevaID()
{ {
Value = EstadoPersistente.Instance.newid; Value = EstadoPersistente.Instance.newid;
@ -817,13 +854,64 @@ namespace CtrEditor.ObjetosSim
Value++; Value++;
return this; return this;
} }
public void NoId() public void NoId()
{ {
// No ID == NULL // No ID == NULL
Value = 0; Value = 0;
} }
// Sobrecarga del operador ++
public static UniqueId operator ++(UniqueId id)
{
if (id == null)
{
id = new UniqueId();
} }
id.Value = EstadoPersistente.Instance.newid;
if (id.Value == 0)
id.Value++;
return id;
}
// Sobrecarga del operador ==
public static bool operator ==(UniqueId id1, UniqueId id2)
{
if (ReferenceEquals(id1, null) || ReferenceEquals(id2, null))
return false;
return id1.Value == id2.Value;
}
// Sobrecarga del operador !=
public static bool operator !=(UniqueId id1, UniqueId id2)
{
if (ReferenceEquals(id1, null) || ReferenceEquals(id2, null))
return true;
return id1.Value != id2.Value;
}
// Sobrescribir Equals y GetHashCode también es una buena práctica
public override bool Equals(object obj)
{
if (obj is UniqueId id)
{
return Value == id.Value;
}
return false;
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
}
public class osBaseItemsSource<T> : IItemsSource public class osBaseItemsSource<T> : IItemsSource
{ {
public ItemCollection GetValues() public ItemCollection GetValues()

View File

@ -0,0 +1,74 @@
<Window x:Class="CtrEditor.PopUps.AssignImagesWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:local="clr-namespace:CtrEditor.PopUps"
xmlns:viewModels="clr-namespace:CtrEditor.PopUps" xmlns:i1="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d" Title="Assign Pages to MultiPage Object"
Height="450" Width="800">
<Window.DataContext>
<viewModels:AssignImagesViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ToolBarTray Grid.Column="0" Grid.Row="0">
<ToolBar>
<Button Command="{Binding TBSelectAllCommand}" ToolTip="Select All">
<StackPanel>
<Image Source="/Icons/allselect.png" Width="16" Height="16" />
<TextBlock Text="Select All Objects" />
</StackPanel>
</Button>
<Button Command="{Binding TBUnSelectAllCommand}" ToolTip="Unselect All">
<StackPanel>
<Image Source="/Icons/unselect.png" Width="16" Height="16" />
<TextBlock Text="Unselect All Objects" />
</StackPanel>
</Button>
</ToolBar>
</ToolBarTray>
<ToolBarTray Grid.Column="1" Grid.Row="0">
<ToolBar>
<Button Command="{Binding TBSelectAllIamgesCommand}" ToolTip="Select All Images">
<StackPanel>
<Image Source="/Icons/allselect.png" Width="16" Height="16" />
<TextBlock Text="Select All Images" />
</StackPanel>
</Button>
<Button Command="{Binding TBUnSelectAllImagesCommand}" ToolTip="Unselect All">
<StackPanel>
<Image Source="/Icons/unselect.png" Width="16" Height="16" />
<TextBlock Text="Unselect all Images" />
</StackPanel>
</Button>
</ToolBar>
</ToolBarTray>
<!-- Lista de Objetos -->
<xctk:CheckListBox Grid.Row="1" Grid.Column="0" ItemsSource="{Binding ObjetosSimulables}" DisplayMemberPath="Nombre"
SelectedItemsOverride="{Binding SelectedObjetosSimulables, Mode=TwoWay}" />
<!-- Lista de Imágenes con CheckListBox -->
<xctk:CheckListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding ListaImagenes}" DisplayMemberPath="."
SelectedItemsOverride="{Binding SelectedImagenes, Mode=TwoWay}" />
<!-- Botón para guardar cambios -->
<Button Grid.Row="2" Grid.ColumnSpan="2" Content="Save" Command="{Binding AssignImagesCommand}"
Margin="10,10,10,10" />
<TextBlock Grid.Row="3" Grid.ColumnSpan="2" Text="{Binding SelectedObjetosSimulables.Count}" />
</Grid>
</Window>

View File

@ -0,0 +1,126 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CtrEditor.ObjetosSim;
using System.Collections.ObjectModel;
using System.Windows;
using CtrEditor.ObjetosSim.Extraccion_Datos;
namespace CtrEditor.PopUps
{
/// <summary>
/// Interaction logic for AssignImagesWindow.xaml
/// </summary>
public partial class AssignImagesWindow : Window
{
public AssignImagesWindow()
{
InitializeComponent();
}
}
public partial class AssignImagesViewModel : ObservableObject
{
private MainViewModel _mainViewModel;
private Window _window;
private bool _closeOK;
[ObservableProperty]
private ObservableCollection<osBase> objetosSimulables;
[ObservableProperty]
private ObservableCollection<string> listaImagenes;
[ObservableProperty]
private ObservableCollection<osBase> selectedObjetosSimulables;
[ObservableProperty]
private ObservableCollection<string> selectedImagenes;
public AssignImagesViewModel()
{
SelectedObjetosSimulables = new ObservableCollection<osBase>();
SelectedObjetosSimulables.CollectionChanged += SelectedObjetosSimulables_CollectionChanged;
}
public void Initialize(MainViewModel mainViewModel, Window window)
{
_mainViewModel = mainViewModel;
_window = window;
ObjetosSimulables = new ObservableCollection<osBase>(_mainViewModel.ObjetosSimulables.Where(
o => o.Enable_On_All_Pages && ((o is osExtraccionTag ex && !ex.Cloned) || (o is osBuscarCoincidencias))));
ListaImagenes = _mainViewModel.ListaImagenes;
}
private void SelectedObjetosSimulables_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
UpdateSelectedImages();
}
private void UpdateSelectedImages()
{
var selectedImages = new HashSet<string>();
foreach (var objeto in SelectedObjetosSimulables)
{
foreach (var image in objeto.ShowOnThisPagesList)
{
selectedImages.Add(image);
}
}
SelectedImagenes = new ObservableCollection<string>(selectedImages);
}
[RelayCommand]
private void AssignImages()
{
foreach (var objeto in SelectedObjetosSimulables)
{
objeto.ShowOnThisPagesList = new List<string>(SelectedImagenes);
objeto.Show_On_This_Page = objeto.Show_On_This_Page;
}
_closeOK = true;
_window.Close();
}
[RelayCommand]
private void TBSelectAll()
{
SelectedObjetosSimulables.Clear();
foreach (var obj in ObjetosSimulables)
{
SelectedObjetosSimulables.Add(obj);
}
}
[RelayCommand]
private void TBUnSelectAll()
{
SelectedObjetosSimulables.Clear();
}
[RelayCommand]
private void TBSelectAllIamges()
{
SelectedImagenes.Clear();
foreach (var img in ListaImagenes)
{
SelectedImagenes.Add(img);
}
}
[RelayCommand]
private void TBUnSelectAllImages()
{
SelectedImagenes.Clear();
}
public bool CloseOK => _closeOK;
}
}

44
PopUps/SelectPages.xaml Normal file
View File

@ -0,0 +1,44 @@
<Window x:Class="CtrEditor.PopUps.SelectPages" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" xmlns:local="clr-namespace:CtrEditor.PopUps"
xmlns:viewModels="clr-namespace:CtrEditor.PopUps" mc:Ignorable="d" Title="Select Pages to Process..."
Height="450" Width="400">
<Window.DataContext>
<viewModels:AssignImagesViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ToolBarTray Grid.Row="0">
<ToolBar>
<Button Command="{Binding TBSelectAllCommand}" ToolTip="Select All">
<StackPanel>
<Image Source="/Icons/allselect.png" Width="16" Height="16" />
<TextBlock Text="Select All" />
</StackPanel>
</Button>
<Button Command="{Binding TBUnSelectAllCommand}" ToolTip="Unselect All">
<StackPanel>
<Image Source="/Icons/unselect.png" Width="16" Height="16" />
<TextBlock Text="Unselect" />
</StackPanel>
</Button>
</ToolBar>
</ToolBarTray>
<!-- Lista de Imágenes con CheckListBox -->
<xctk:CheckListBox Grid.Row="1" ItemsSource="{Binding ListaImagenes}" DisplayMemberPath="."
SelectedItemsOverride="{Binding SelectedImagenes, Mode=TwoWay}" />
<!-- Botón para guardar cambios -->
<Button Grid.Row="2" Grid.ColumnSpan="1" Content="Run" Command="{Binding AssignImagesCommand}"
Margin="10,10,10,10" />
</Grid>
</Window>

View File

@ -0,0 +1,86 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CtrEditor.ObjetosSim.Extraccion_Datos;
using CtrEditor.ObjetosSim;
using CtrEditor;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace CtrEditor.PopUps
{
/// <summary>
/// Interaction logic for SelectPages.xaml
/// </summary>
public partial class SelectPages : Window
{
public SelectPages()
{
InitializeComponent();
}
}
}
public partial class SelectPagesViewModel : ObservableObject
{
private MainViewModel _mainViewModel;
private Window _window;
private ObservableCollection<string> _imagenesSeleccionadas;
private bool _closeOK;
[ObservableProperty]
private ObservableCollection<string> listaImagenes;
[ObservableProperty]
private ObservableCollection<string> selectedImagenes;
public SelectPagesViewModel() { }
public void Initialize(MainViewModel mainViewModel, Window window, ref ObservableCollection<string> ImagenesSeleccionadas)
{
_mainViewModel = mainViewModel;
_window = window;
_imagenesSeleccionadas = ImagenesSeleccionadas;
ListaImagenes = _mainViewModel.ListaImagenes;
SelectedImagenes = ImagenesSeleccionadas;
}
[RelayCommand]
private void AssignImages()
{
_closeOK = true;
_window.Close();
}
[RelayCommand]
private void TBSelectAll()
{
SelectedImagenes.Clear();
foreach (var img in ListaImagenes)
{
SelectedImagenes.Add(img);
}
}
[RelayCommand]
private void TBUnSelectAll()
{
SelectedImagenes.Clear();
}
public bool CloseOK => _closeOK;
}

View File

@ -10,9 +10,126 @@ using Xceed.Wpf.Toolkit.PropertyGrid;
using CtrEditor.ObjetosSim.Extraccion_Datos; using CtrEditor.ObjetosSim.Extraccion_Datos;
using CtrEditor.ObjetosSim; using CtrEditor.ObjetosSim;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using System.Collections;
namespace CtrEditor namespace CtrEditor
{ {
public class ListItemPropertyDescriptor<T> : PropertyDescriptor
{
private readonly IList<T> owner;
private readonly int index;
public ListItemPropertyDescriptor(IList<T> owner, int index) : base($"[{index}]", null)
{
this.owner = owner;
this.index = index;
}
public override AttributeCollection Attributes
{
get
{
var attributes = TypeDescriptor.GetAttributes(GetValue(null), false);
//If the Xceed expandable object attribute is not applied then apply it
if (!attributes.OfType<ExpandableObjectAttribute>().Any())
{
attributes = AddAttribute(new ExpandableObjectAttribute(), attributes);
}
//set the xceed order attribute
attributes = AddAttribute(new PropertyOrderAttribute(index), attributes);
return attributes;
}
}
private AttributeCollection AddAttribute(Attribute newAttribute, AttributeCollection oldAttributes)
{
Attribute[] newAttributes = new Attribute[oldAttributes.Count + 1];
oldAttributes.CopyTo(newAttributes, 1);
newAttributes[0] = newAttribute;
return new AttributeCollection(newAttributes);
}
public override bool CanResetValue(object component)
{
return false;
}
public override object GetValue(object component)
{
return Value;
}
private T Value
=> owner[index];
public override void ResetValue(object component)
{
throw new NotImplementedException();
}
public override void SetValue(object component, object value)
{
owner[index] = (T)value;
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
public override Type ComponentType
=> owner.GetType();
public override bool IsReadOnly
=> false;
public override Type PropertyType
=> Value?.GetType();
}
public class MyExpandableIListConverter<T> : ExpandableObjectConverter
{
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
if (value is IList<T> list)
{
PropertyDescriptorCollection propDescriptions = new PropertyDescriptorCollection(null);
IEnumerator enumerator = list.GetEnumerator();
int counter = -1;
while (enumerator.MoveNext())
{
counter++;
propDescriptions.Add(new ListItemPropertyDescriptor<T>(list, counter));
}
return propDescriptions;
}
else
{
return base.GetProperties(context, value, attributes);
}
}
}
public static class TypeDecorationManager
{
public static void AddExpandableObjectConverter(Type T)
{
TypeDescriptor.AddAttributes(T, new TypeConverterAttribute(typeof(ExpandableObjectConverter)));
TypeDescriptor.AddAttributes(T, new ExpandableObjectAttribute());
}
public static void AddExpandableIListConverter<I>(Type T)
{
TypeDescriptor.AddAttributes(T, new TypeConverterAttribute(typeof(MyExpandableIListConverter<I>)));
TypeDescriptor.AddAttributes(T, new ExpandableObjectAttribute());
}
}
public class SubclassFilterConverter : IValueConverter public class SubclassFilterConverter : IValueConverter
{ {
public Type TargetType { get; set; } public Type TargetType { get; set; }