Creado BuscarCoincidencias, implementando logica

This commit is contained in:
Miguel 2024-06-06 16:53:00 +02:00
parent 84725cc8d6
commit 0305ae2506
11 changed files with 528 additions and 368 deletions

View File

@ -2,6 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CtrEditor" xmlns:local="clr-namespace:CtrEditor"
xmlns:os="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos"
StartupUri="MainWindow.xaml"> StartupUri="MainWindow.xaml">
<Application.Resources> <Application.Resources>
@ -17,6 +18,8 @@
<local:SumConverter x:Key="SumConverter" /> <local:SumConverter x:Key="SumConverter" />
<local:ColorToBrushConverter x:Key="ColorToBrushConverter"/> <local:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<local:StringToBrushConverter x:Key="StringToBrushConverter"/> <local:StringToBrushConverter x:Key="StringToBrushConverter"/>
<local:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<local:SubclassFilterConverter x:Key="SubclassFilterConverter" TargetType="{x:Type os:osBuscarCoincidencias}" />
</Application.Resources> </Application.Resources>
</Application> </Application>

View File

@ -66,6 +66,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Aether.Physics2D" Version="2.1.0" /> <PackageReference Include="Aether.Physics2D" Version="2.1.0" />
<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.runtime.windows" Version="4.9.0.5494" />
<PackageReference Include="Emgu.CV.UI" Version="4.9.0.5494" />
<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.122" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.122" />

View File

@ -178,8 +178,7 @@
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="2" Margin="5" x:Name="PanelEdicion" AutoGenerateProperties="False">
SelectedObject="{Binding}">
<xctk:PropertyGrid.EditorDefinitions> <xctk:PropertyGrid.EditorDefinitions>
<!-- String --> <!-- String -->
@ -231,6 +230,21 @@
</xctk:EditorTemplateDefinition.EditingTemplate> </xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition> </xctk:EditorTemplateDefinition>
<!-- osBase -->
<xctk:EditorTemplateDefinition>
<xctk:EditorTemplateDefinition.TargetProperties>
<xctk:TargetPropertyType Type="{x:Type ObjetosSim:osBase}" />
</xctk:EditorTemplateDefinition.TargetProperties>
<xctk:EditorTemplateDefinition.EditingTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.ObjetosSimulables,
RelativeSource={RelativeSource AncestorType=Window},
Converter={StaticResource SubclassFilterConverter}}"
SelectedItem="{Binding Value}" DisplayMemberPath="Nombre" />
</DataTemplate>
</xctk:EditorTemplateDefinition.EditingTemplate>
</xctk:EditorTemplateDefinition>
</xctk:PropertyGrid.EditorDefinitions> </xctk:PropertyGrid.EditorDefinitions>
</xctk:PropertyGrid> </xctk:PropertyGrid>

View File

@ -0,0 +1,23 @@
<UserControl x:Class="CtrEditor.ObjetosSim.Extraccion_Datos.ucBuscarCoincidencias"
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"
Visibility="{Binding Show_on_this_page, Converter={StaticResource BoolToVisibilityConverter}}">
<UserControl.DataContext>
<vm:osBuscarCoincidencias />
</UserControl.DataContext>
<Canvas>
<Rectangle x:Name="Area" Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}"
Opacity="{Binding Opacity_oculto}" Fill="Yellow" Stroke="Black">
<Rectangle.RenderTransform>
<RotateTransform Angle="{Binding Angulo}" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
</UserControl>

View File

@ -0,0 +1,354 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CtrEditor.Simulacion;
using System.IO;
using System.Windows.Media.Imaging;
using Tesseract;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV;
using System.Drawing;
using Image = System.Windows.Controls.Image;
using Point = System.Drawing.Point;
using Rectangle = System.Windows.Shapes.Rectangle;
using Size = System.Drawing.Size;
using Ookii.Dialogs.Wpf;
namespace CtrEditor.ObjetosSim.Extraccion_Datos
{
/// <summary>
/// Interaction logic for ucBuscarCoincidencias.xaml
/// </summary>
///
public partial class osBuscarCoincidencias : osBase, IosBase
{
private osBase _osMotor = null;
private simTransporte SimGeometria;
public static string NombreClase()
{
return "Search Templates";
}
private string nombre = NombreClase();
public override string Nombre
{
get => nombre;
set => SetProperty(ref nombre, value);
}
[ObservableProperty]
bool search_templates;
partial void OnSearch_templatesChanged(bool oldValue, bool newValue)
{
if (Search_templates)
BuscarCoincidencias();
Search_templates = false;
}
public override void TopChanged(float value)
{
base.TopChanged(value);
Search_templates = false;
}
public override void LeftChanged(float value)
{
base.LeftChanged(value);
Search_templates = false;
}
[ObservableProperty]
public float ancho;
partial void OnAnchoChanged(float value)
{
Search_templates = false;
}
[ObservableProperty]
public float alto;
partial void OnAltoChanged(float value)
{
Search_templates = false;
}
public override void OnTimerAfterMovement()
{
}
[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;
[ObservableProperty]
float opacity_oculto;
[ObservableProperty]
bool show_debug_ocr;
[ObservableProperty]
float threshold;
public osBuscarCoincidencias()
{
Ancho = 1;
Alto = 1;
Angulo = 0;
Opacity_oculto = 0.1f;
}
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 async void BuscarCoincidencias()
{
var progressDialog = new ProgressDialog
{
WindowTitle = "Procesando",
Text = "Buscando coincidencias...",
ShowTimeRemaining = true,
ShowCancelButton = false
};
progressDialog.DoWork += (sender, e) => BuscarCoincidenciasAsync(progressDialog);
progressDialog.RunWorkerCompleted += (sender, e) =>
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
};
progressDialog.Show();
}
private void BuscarCoincidenciasAsync(ProgressDialog progressDialog)
{
// Reset the Canvas children
Application.Current.Dispatcher.Invoke(() =>
{
var clearShapes = _mainViewModel.MainCanvas.Children.OfType<System.Windows.Shapes.Shape>().Where(s => s.Tag as string == "BuscarCoincidencias").ToList();
foreach (var shape in clearShapes)
{
_mainViewModel.MainCanvas.Children.Remove(shape);
}
if (_mainViewModel?.MainCanvas.Children[0] is Image imagenDeFondo)
{
// Asegurarse de que la imagen origen está disponible
if (imagenDeFondo.Source is BitmapSource bitmapSource)
{
progressDialog.ReportProgress(10);
// 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));
// Convertir CroppedBitmap a Mat directamente
Mat templateMat = BitmapSourceToMat(croppedBitmap);
int scale = 4;
// Convertir la plantilla a escala de grises y redimensionarla
Mat templateGray = new Mat();
CvInvoke.CvtColor(templateMat, templateGray, ColorConversion.Bgr2Gray);
Mat templateGrayResized = new Mat();
CvInvoke.Resize(templateGray, templateGrayResized, new Size(templateGray.Width / scale, templateGray.Height / scale), 0, 0, Inter.Linear);
progressDialog.ReportProgress(20);
// Cargar la imagen principal completa en un Mat
Mat mainImageMat = BitmapSourceToMat(bitmapSource);
// Convertir la imagen principal a escala de grises y redimensionarla
Mat mainImageGray = new Mat();
CvInvoke.CvtColor(mainImageMat, mainImageGray, ColorConversion.Bgr2Gray);
Mat mainImageGrayResized = new Mat();
CvInvoke.Resize(mainImageGray, mainImageGrayResized, new Size(mainImageGray.Width / scale, mainImageGray.Height / scale), 0, 0, Inter.Linear);
progressDialog.ReportProgress(50);
// Realizar la coincidencia de plantillas
Mat result = new Mat();
CvInvoke.MatchTemplate(mainImageGray, templateGray, result, TemplateMatchingType.CcoeffNormed);
// Establecer un umbral de coincidencia
if (Threshold < 0.4)
Threshold = 0.4f;
double threshold = Threshold;
int ConteoPositivos = 0;
// Obtener los puntos que superan el umbral
float[] resultArray = result.GetData(false) as float[];
if (resultArray != null)
{
for (int i = 0; i < resultArray.Length; i++)
{
if (resultArray[i] >= threshold)
{
int row = i / result.Cols;
int col = i % result.Cols;
// Crear y agregar el rectángulo al Canvas (ajustando por la escala)
Rectangle matchRect = new Rectangle
{
Stroke = new SolidColorBrush(Colors.Red),
StrokeThickness = 2,
Width = width / scaleFactorX,
Height = height / scaleFactorY,
Tag = "BuscarCoincidencias"
};
Canvas.SetLeft(matchRect, col / scaleFactorX);
Canvas.SetTop(matchRect, row / scaleFactorY);
Canvas.SetZIndex(matchRect, 40);
_mainViewModel.MainCanvas.Children.Add(matchRect);
ConteoPositivos++;
progressDialog.ReportProgress(90);
if (ConteoPositivos > 20)
return;
}
}
}
}
}
});
}
// Método para convertir BitmapSource a Mat
private Mat BitmapSourceToMat(BitmapSource bitmapSource)
{
Bitmap bitmap;
using (MemoryStream outStream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapSource));
enc.Save(outStream);
bitmap = new Bitmap(outStream);
}
return bitmap.ToMat();
}
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 ucBuscarCoincidencias : UserControl, IDataContainer
{
public osBase? Datos { get; set; }
public ucBuscarCoincidencias()
{
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 osBuscarCoincidencias 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 osBuscarCoincidencias datos)
datos.Angulo = Angle;
}
public void Highlight(bool State) { }
public int ZIndex()
{
return 1;
}
}
}

View File

@ -5,16 +5,17 @@
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" xmlns:vm="clr-namespace:CtrEditor.ObjetosSim.Extraccion_Datos"
mc:Ignorable="d"> mc:Ignorable="d"
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="Transporte" <Rectangle x:Name="Area"
Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}" Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}" Opacity="0.1" Fill="Green" Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}" Opacity="{Binding Opacity_oculto}" Fill="Green"
Stroke="Black" Stroke="Black"
> >

View File

@ -78,16 +78,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
} }
[ObservableProperty] [ObservableProperty]
public int n_Repeat_X; osBase search_Templates;
[ObservableProperty]
public int n_Repeat_Y;
[ObservableProperty]
public float offset_Repeat_X;
[ObservableProperty]
public float offset_Repeat_Y;
[ObservableProperty] [ObservableProperty]
public float angulo; public float angulo;
@ -101,11 +92,19 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
[ObservableProperty] [ObservableProperty]
string tag_name; string tag_name;
[ObservableProperty]
float opacity_oculto;
[ObservableProperty]
bool show_debug_ocr;
public osExtraccionTag() public osExtraccionTag()
{ {
Ancho = 1; Ancho = 1;
Alto = 1; Alto = 1;
Angulo = 0; Angulo = 0;
Opacity_oculto = 0.1f;
} }
private void ShowPreviewWindow(Stream imageStream) private void ShowPreviewWindow(Stream imageStream)
@ -170,7 +169,7 @@ namespace CtrEditor.ObjetosSim.Extraccion_Datos
memoryStream.Seek(0, SeekOrigin.Begin); memoryStream.Seek(0, SeekOrigin.Begin);
// Mostrar la imagen recortada en una ventana de previsualización // Mostrar la imagen recortada en una ventana de previsualización
// ShowPreviewWindow(memoryStream); if (show_debug_ocr) ShowPreviewWindow(memoryStream);
// Cargar la imagen en Tesseract desde el MemoryStream // Cargar la imagen en Tesseract desde el MemoryStream
using (var img = Pix.LoadFromMemory(memoryStream.ToArray())) using (var img = Pix.LoadFromMemory(memoryStream.ToArray()))

View File

@ -40,8 +40,8 @@ namespace CtrEditor.ObjetosSim
// crear el objeto de simulacion // crear el objeto de simulacion
ActualizarLeftTop(); ActualizarLeftTop();
if (_visualRepresentation is ucConsensGeneric uc) //if (_visualRepresentation is ucConsensGeneric uc)
Tags = UserControlFactory.CargarPropiedadesosDatosTags(Consensos, uc.PanelEdicion, null); // Tags = UserControlFactory.CargarPropiedadesosDatosTags(Consensos, uc.PanelEdicion, null);
} }
} }

View File

@ -16,6 +16,7 @@ using System.Diagnostics;
using System.Globalization; using System.Globalization;
using Xceed.Wpf.Toolkit; using Xceed.Wpf.Toolkit;
using Xceed.Wpf.Toolkit.PropertyGrid.Editors; using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
using CtrEditor.ObjetosSim.Extraccion_Datos;
namespace CtrEditor.ObjetosSim namespace CtrEditor.ObjetosSim
{ {
@ -93,7 +94,7 @@ namespace CtrEditor.ObjetosSim
var properties = TypeDescriptor.GetProperties(selectedObject) var properties = TypeDescriptor.GetProperties(selectedObject)
.Cast<PropertyDescriptor>() .Cast<PropertyDescriptor>()
.Where(prop => !prop.Attributes.OfType<HiddenAttribute>().Any()).OrderBy(prop => prop.Name); .Where(prop => !prop.Attributes.OfType<HiddenAttribute>().Any()).OrderBy(prop => prop.Name);
foreach (var property in properties) foreach (var property in properties)
{ {
var displayNameAttr = property.Attributes.OfType<DisplayNameAttribute>().FirstOrDefault(); var displayNameAttr = property.Attributes.OfType<DisplayNameAttribute>().FirstOrDefault();
@ -113,7 +114,7 @@ namespace CtrEditor.ObjetosSim
propertyDefinition.DisplayName = property.Name.Replace("_", " "); propertyDefinition.DisplayName = property.Name.Replace("_", " ");
} }
if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int) || if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int) ||
property.PropertyType == typeof(bool) || property.PropertyType == typeof(Color)) property.PropertyType == typeof(bool) || property.PropertyType == typeof(osBase) || property.PropertyType == typeof(Color) )
{ {
propertyGrid.PropertyDefinitions.Add(propertyDefinition); propertyGrid.PropertyDefinitions.Add(propertyDefinition);
} }
@ -123,341 +124,6 @@ namespace CtrEditor.ObjetosSim
propertyGrid.SelectedObject = selectedObject; propertyGrid.SelectedObject = selectedObject;
} }
public static void CargarPropiedadesosDatosex(Object selectedObject, StackPanel PanelEdicion, ResourceDictionary Resources)
{
PanelEdicion.Children.Clear();
var properties = selectedObject.GetType().GetProperties().OrderBy(p => p.Name); // Ordenar alfabéticamente
foreach (var property in properties)
{
if (Attribute.IsDefined(property, typeof(HiddenAttribute)))
continue;
if (property.Name.EndsWith("_oculto"))
continue;
var grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
var label = new Label
{
Content = property.Name.Replace("_", " ") + ":",
Margin = new Thickness(0, 0, 5, 0),
VerticalAlignment = VerticalAlignment.Center
};
Grid.SetColumn(label, 0);
grid.Children.Add(label);
if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int))
{
var textBox = new TextBox
{
Margin = new Thickness(0),
MinWidth = 200,
VerticalContentAlignment = VerticalAlignment.Center
};
var binding = new Binding(property.Name)
{
Source = selectedObject,
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus
};
if (property.PropertyType == typeof(float))
{
if (Application.Current.Resources.Contains("floatFormatter"))
{
binding.Converter = Application.Current.Resources["floatFormatter"] as IValueConverter;
}
}
if (property.PropertyType == typeof(double))
{
if (Application.Current.Resources.Contains("doubleFormatter"))
{
binding.Converter = Application.Current.Resources["doubleFormatter"] as IValueConverter;
}
}
textBox.SetBinding(TextBox.TextProperty, binding);
textBox.KeyDown += (sender, e) =>
{
if (e.Key == Key.Enter || e.Key == Key.Down)
{
var request = new TraversalRequest(FocusNavigationDirection.Next);
request.Wrapped = true;
textBox.MoveFocus(request);
}
else if (e.Key == Key.Up)
{
var request = new TraversalRequest(FocusNavigationDirection.Previous);
request.Wrapped = true;
textBox.MoveFocus(request);
}
};
Grid.SetColumn(textBox, 1);
grid.Children.Add(textBox);
}
else if (property.PropertyType == typeof(bool))
{
var checkBox = new CheckBox
{
Margin = new Thickness(5, 0, 0, 0),
VerticalAlignment = VerticalAlignment.Center
};
var binding = new Binding(property.Name)
{
Source = selectedObject,
Mode = BindingMode.TwoWay
};
checkBox.SetBinding(CheckBox.IsCheckedProperty, binding);
checkBox.KeyDown += (sender, e) =>
{
if (e.Key == Key.Enter || e.Key == Key.Down)
{
var request = new TraversalRequest(FocusNavigationDirection.Next);
request.Wrapped = true;
checkBox.MoveFocus(request);
}
else if (e.Key == Key.Up)
{
var request = new TraversalRequest(FocusNavigationDirection.Previous);
request.Wrapped = true;
checkBox.MoveFocus(request);
}
};
Grid.SetColumn(checkBox, 1);
grid.Children.Add(checkBox);
}
else if (property.PropertyType == typeof(Brush))
{
var comboBox = new ComboBox
{
ItemsSource = new List<Tuple<string, SolidColorBrush>>
{
Tuple.Create("Rojo", Brushes.Red),
Tuple.Create("Azul", Brushes.Blue),
Tuple.Create("Negro", Brushes.Black),
Tuple.Create("Verde", Brushes.Green),
Tuple.Create("Gris", Brushes.Gray)
},
SelectedValuePath = "Item2",
Margin = new Thickness(0),
MinWidth = 200
};
var binding = new Binding(property.Name)
{
Source = selectedObject,
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
comboBox.SetBinding(ComboBox.SelectedValueProperty, binding);
comboBox.KeyDown += (sender, e) =>
{
if (e.Key == Key.Enter || e.Key == Key.Down)
{
var request = new TraversalRequest(FocusNavigationDirection.Next);
request.Wrapped = true;
comboBox.MoveFocus(request);
}
else if (e.Key == Key.Up)
{
var request = new TraversalRequest(FocusNavigationDirection.Previous);
request.Wrapped = true;
comboBox.MoveFocus(request);
}
};
var template = new DataTemplate();
var stackPanelFactory = new FrameworkElementFactory(typeof(StackPanel));
stackPanelFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
var rectangleFactory = new FrameworkElementFactory(typeof(Rectangle));
rectangleFactory.SetValue(Rectangle.WidthProperty, 16.0);
rectangleFactory.SetValue(Rectangle.HeightProperty, 16.0);
rectangleFactory.SetBinding(Rectangle.FillProperty, new Binding("Item2"));
stackPanelFactory.AppendChild(rectangleFactory);
var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
textBlockFactory.SetBinding(TextBlock.TextProperty, new Binding("Item1"));
stackPanelFactory.AppendChild(textBlockFactory);
template.VisualTree = stackPanelFactory;
comboBox.ItemTemplate = template;
Grid.SetColumn(comboBox, 1);
grid.Children.Add(comboBox);
}
PanelEdicion.Children.Add(grid);
}
} }
public static List<string> CargarPropiedadesosDatosTags(Object selectedObject, StackPanel PanelEdicion, ResourceDictionary Resources)
{
PanelEdicion.Children.Clear();
var properties = selectedObject.GetType().GetProperties();
List<string> tags = new List<string>();
foreach (var property in properties)
{
if (Attribute.IsDefined(property, typeof(HiddenAttribute)))
continue;
if (property.Name.EndsWith("_oculto"))
continue;
var grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
var label = new Label
{
Content = property.Name.Replace("_", " ") + ":",
Margin = new Thickness(0, 0, 5, 0),
VerticalAlignment = VerticalAlignment.Center
};
Grid.SetColumn(label, 0);
grid.Children.Add(label);
if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int))
{
var textBox = new TextBox
{
Margin = new Thickness(0),
MinWidth = 200,
VerticalContentAlignment = VerticalAlignment.Center
};
var binding = new Binding(property.Name)
{
Source = selectedObject,
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus
};
if (property.PropertyType == typeof(float))
{
if (Resources != null)
binding.Converter = (FloatToFormattedStringConverter)Resources["floatFormatter"];
}
if (property.PropertyType == typeof(double))
{
if (Resources != null)
binding.Converter = (DoubleToFormattedStringConverter)Resources["doubleFormatter"];
}
textBox.SetBinding(TextBox.TextProperty, binding);
Grid.SetColumn(textBox, 1);
grid.Children.Add(textBox);
var tagTextBox = new TextBox
{
Margin = new Thickness(0),
MinWidth = 100,
VerticalContentAlignment = VerticalAlignment.Center
};
// Add an empty string to the tags list and get the index
tags.Add(string.Empty);
int tagIndex = tags.Count - 1;
// Event handler to update the tags list when the text changes
tagTextBox.TextChanged += (sender, args) =>
{
tags[tagIndex] = tagTextBox.Text;
};
Grid.SetColumn(tagTextBox, 2);
grid.Children.Add(tagTextBox);
}
else if (property.PropertyType == typeof(bool))
{
var checkBox = new CheckBox
{
Margin = new Thickness(5, 0, 0, 0),
VerticalAlignment = VerticalAlignment.Center
};
var binding = new Binding(property.Name)
{
Source = selectedObject,
Mode = BindingMode.TwoWay
};
checkBox.SetBinding(CheckBox.IsCheckedProperty, binding);
Grid.SetColumn(checkBox, 1);
grid.Children.Add(checkBox);
}
else if (property.PropertyType == typeof(Brush))
{
var listBox = new ListBox
{
ItemsSource = new List<string> { "Rojo", "Azul", "Negro", "Verde", "Gris" },
Margin = new Thickness(0),
MinWidth = 200
};
listBox.SelectionChanged += (sender, e) =>
{
if (listBox.SelectedItem != null)
{
switch (listBox.SelectedItem.ToString())
{
case "Rojo":
property.SetValue(selectedObject, Brushes.Red);
break;
case "Azul":
property.SetValue(selectedObject, Brushes.Blue);
break;
case "Negro":
property.SetValue(selectedObject, Brushes.Black);
break;
case "Verde":
property.SetValue(selectedObject, Brushes.Green);
break;
case "Gris":
property.SetValue(selectedObject, Brushes.Gray);
break;
}
}
};
var binding = new Binding(property.Name)
{
Source = selectedObject,
Mode = BindingMode.TwoWay,
Converter = new BrushToColorNameConverter()
};
listBox.SetBinding(ListBox.SelectedItemProperty, binding);
Grid.SetColumn(listBox, 1);
grid.Children.Add(listBox);
}
PanelEdicion.Children.Add(grid);
}
return tags;
}
}
} }

View File

@ -62,7 +62,7 @@ namespace CtrEditor.ObjetosSim
[JsonIgnore] [JsonIgnore]
private Storyboard _storyboard; private Storyboard _storyboard;
private System.Threading.Timer timer = null; private System.Threading.Timer timer = null;
[ObservableProperty] [ObservableProperty]
private float left; private float left;
@ -83,14 +83,6 @@ namespace CtrEditor.ObjetosSim
[ObservableProperty] [ObservableProperty]
private float top; private float top;
[ObservableProperty]
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);
@ -104,6 +96,66 @@ 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) { }
// Group
[ObservableProperty]
private string group_Panel;
// All Pages Objects
[NotifyPropertyChangedFor(nameof(Show_on_this_page))]
[ObservableProperty]
private bool enable_on_all_pages;
partial void OnEnable_on_all_pagesChanged(bool value)
{
if (!value)
Show_on_this_page = true;
}
private List<string> Show_on_this_pages_oculto;
private bool show_on_this_page;
public bool Show_on_this_page
{
get
{
// Not global object
if (!enable_on_all_pages)
{
if (Show_on_this_pages_oculto != null)
Show_on_this_pages_oculto.Clear();
Show_on_this_pages_oculto = null;
show_on_this_page = true;
}
else
{
// Global Object
if (Show_on_this_pages_oculto == null)
Show_on_this_pages_oculto = new List<string>();
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;
}
set
{
// global object?
if (enable_on_all_pages)
{
// Global Object
if (Show_on_this_pages_oculto == null)
Show_on_this_pages_oculto = new List<string>();
if (_mainViewModel == null || _mainViewModel.SelectedImage == null) return;
if (value && !Show_on_this_pages_oculto.Contains(_mainViewModel.SelectedImage))
Show_on_this_pages_oculto.Add(_mainViewModel.SelectedImage);
else if (!value && Show_on_this_pages_oculto.Contains(_mainViewModel.SelectedImage))
Show_on_this_pages_oculto.Remove(_mainViewModel.SelectedImage);
}
SetProperty(ref show_on_this_page, value);
}
}
private async void TimerCallback(object state) private async void TimerCallback(object state)
{ {
await Task.Delay(500); // Esperar 0.5 segundos antes de ejecutar la función await Task.Delay(500); // Esperar 0.5 segundos antes de ejecutar la función
@ -111,7 +163,7 @@ namespace CtrEditor.ObjetosSim
{ {
// Realiza tus cambios en la interfaz de usuario aquí // Realiza tus cambios en la interfaz de usuario aquí
OnTimerAfterMovement(); OnTimerAfterMovement();
}); });
} }
/// <summary> /// <summary>
/// Este timer se usa para llamar a OnTimerAfterMovement luego de que han pasado 500ms sin que se /// Este timer se usa para llamar a OnTimerAfterMovement luego de que han pasado 500ms sin que se
@ -122,7 +174,7 @@ namespace CtrEditor.ObjetosSim
/// </summary> /// </summary>
public void ResetTimer() public void ResetTimer()
{ {
if (timer == null) if (timer == null)
timer = new System.Threading.Timer(TimerCallback, null, Timeout.Infinite, Timeout.Infinite); timer = new System.Threading.Timer(TimerCallback, null, Timeout.Infinite, Timeout.Infinite);
timer.Change(500, Timeout.Infinite); timer.Change(500, Timeout.Infinite);
@ -446,7 +498,7 @@ namespace CtrEditor.ObjetosSim
public Vector2 PixelsToMeters(Vector2 pixel) public Vector2 PixelsToMeters(Vector2 pixel)
{ {
return new Vector2(PixelsToMeters(pixel.X),PixelsToMeters(pixel.Y)); return new Vector2(PixelsToMeters(pixel.X), PixelsToMeters(pixel.Y));
} }
public float MeterToPixels(float meter) public float MeterToPixels(float meter)
@ -476,7 +528,7 @@ namespace CtrEditor.ObjetosSim
return transformGroup; return transformGroup;
} }
public (Vector2 TopLeft, Vector2 BottomRight) GetRectangleCoordinatesInMeter(Rectangle rect) public (Vector2 TopLeft, Vector2 BottomRight) GetRectangleCoordinatesInMeter(Rectangle rect)
{ {
if (rect != null) if (rect != null)

View File

@ -7,10 +7,55 @@ using System.Reflection;
using Xceed.Wpf.Toolkit.PropertyGrid.Editors; using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
using Xceed.Wpf.Toolkit; using Xceed.Wpf.Toolkit;
using Xceed.Wpf.Toolkit.PropertyGrid; using Xceed.Wpf.Toolkit.PropertyGrid;
using CtrEditor.ObjetosSim.Extraccion_Datos;
using CtrEditor.ObjetosSim;
using System.Collections.ObjectModel;
namespace CtrEditor namespace CtrEditor
{ {
public class SubclassFilterConverter : IValueConverter
{
public Type TargetType { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is ObservableCollection<osBase> collection && TargetType != null)
{
var filteredCollection = new ObservableCollection<osBase>(collection.Where(x => x.GetType() == TargetType));
return filteredCollection;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class BoolToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolValue)
{
return boolValue ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility visibility)
{
return visibility == Visibility.Visible;
}
return false;
}
}
public class DecimalEditor : ITypeEditor public class DecimalEditor : ITypeEditor
{ {
public FrameworkElement ResolveEditor(PropertyItem propertyItem) public FrameworkElement ResolveEditor(PropertyItem propertyItem)