Agregado un nuevo objeto CustomImage
This commit is contained in:
parent
5f680b3a7a
commit
5e95459e3e
|
@ -342,8 +342,26 @@
|
|||
</DataTemplate>
|
||||
</xctk:EditorTemplateDefinition.EditingTemplate>
|
||||
</xctk:EditorTemplateDefinition>
|
||||
|
||||
<!-- File Dialog -->
|
||||
<xctk:EditorTemplateDefinition TargetProperties="ImagePath">
|
||||
<xctk:EditorTemplateDefinition.EditingTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0"
|
||||
Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<Button Grid.Column="1" Content="..." Width="25" Margin="2,0,0,0"
|
||||
Click="ImagePathButton_Click" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</xctk:EditorTemplateDefinition.EditingTemplate>
|
||||
</xctk:EditorTemplateDefinition>
|
||||
|
||||
<!-- osBase -->
|
||||
<!-- osBase -->
|
||||
<xctk:EditorTemplateDefinition>
|
||||
<xctk:EditorTemplateDefinition.TargetProperties>
|
||||
<xctk:TargetPropertyType Type="{x:Type ObjetosSim:osBase}" />
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace CtrEditor
|
|||
private bool _isDraggingCanvas = false;
|
||||
private Image imagenDeFondo;
|
||||
internal ObjectManipulationManager _objectManager;
|
||||
private Rectangle _panningArea;
|
||||
|
||||
// Temporizadores y animación
|
||||
private DispatcherTimer _zoomTimer;
|
||||
|
@ -44,6 +45,12 @@ namespace CtrEditor
|
|||
|
||||
_objectManager = new ObjectManipulationManager(this, ImagenEnTrabajoCanvas);
|
||||
|
||||
_panningArea = new Rectangle
|
||||
{
|
||||
Fill = Brushes.Transparent,
|
||||
IsHitTestVisible = true
|
||||
};
|
||||
|
||||
// Inicializar temporizador de zoom
|
||||
_zoomTimer = new DispatcherTimer();
|
||||
_zoomTimer.Interval = TimeSpan.FromMilliseconds(1);
|
||||
|
@ -53,9 +60,13 @@ namespace CtrEditor
|
|||
// Suscribir eventos
|
||||
this.Loaded += MainWindow_Loaded;
|
||||
ImagenEnTrabajoScrollViewer.PreviewMouseWheel += ImagenEnTrabajoCanvas_MouseWheel;
|
||||
|
||||
ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown_Panning;
|
||||
ImagenEnTrabajoCanvas.MouseMove += Canvas_MouseMove_Panning;
|
||||
ImagenEnTrabajoCanvas.MouseUp += Canvas_MouseUp_Panning;
|
||||
|
||||
_panningArea.MouseDown += Canvas_MouseDown_Panning;
|
||||
_panningArea.MouseRightButtonDown += Canvas_MouseRightButtonDown;
|
||||
this.KeyDown += MainWindow_KeyDown;
|
||||
ImagenEnTrabajoCanvas.MouseEnter += Canvas_MouseEnter;
|
||||
this.Closed += MainWindow_Closed;
|
||||
|
@ -114,20 +125,38 @@ namespace CtrEditor
|
|||
imagenDeFondo.Source = bitmap;
|
||||
RenderOptions.SetBitmapScalingMode(imagenDeFondo, BitmapScalingMode.HighQuality);
|
||||
|
||||
// Elimina solo los ROIs, no la imagen de fondo
|
||||
// Actualizar dimensiones del canvas
|
||||
ImagenEnTrabajoCanvas.Width = bitmap.Width;
|
||||
ImagenEnTrabajoCanvas.Height = bitmap.Height;
|
||||
|
||||
// Configurar el área de panning
|
||||
_panningArea.Width = bitmap.Width * 4;
|
||||
_panningArea.Height = bitmap.Height * 4;
|
||||
|
||||
// Posicionar el área de panning centrada respecto a la imagen
|
||||
Canvas.SetLeft(_panningArea, -bitmap.Width / 4);
|
||||
Canvas.SetTop(_panningArea, -bitmap.Height / 4);
|
||||
Canvas.SetZIndex(_panningArea, -1); // Asegurar que está detrás de todo
|
||||
|
||||
// Asegurarse de que el área de panning está en el canvas
|
||||
if (!ImagenEnTrabajoCanvas.Children.Contains(_panningArea))
|
||||
{
|
||||
ImagenEnTrabajoCanvas.Children.Add(_panningArea);
|
||||
}
|
||||
|
||||
// Posicionar la imagen
|
||||
Canvas.SetLeft(imagenDeFondo, 0);
|
||||
Canvas.SetTop(imagenDeFondo, 0);
|
||||
|
||||
// Eliminar solo los ROIs, no la imagen de fondo ni el área de panning
|
||||
for (int i = ImagenEnTrabajoCanvas.Children.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (ImagenEnTrabajoCanvas.Children[i] is not Image)
|
||||
var child = ImagenEnTrabajoCanvas.Children[i];
|
||||
if (child != imagenDeFondo && child != _panningArea)
|
||||
{
|
||||
ImagenEnTrabajoCanvas.Children.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
ImagenEnTrabajoCanvas.Width = bitmap.Width;
|
||||
ImagenEnTrabajoCanvas.Height = bitmap.Height;
|
||||
|
||||
Canvas.SetLeft(imagenDeFondo, 0);
|
||||
Canvas.SetTop(imagenDeFondo, 0);
|
||||
}
|
||||
|
||||
private void Canvas_MouseUp_Panning(object sender, MouseButtonEventArgs e)
|
||||
|
@ -151,9 +180,10 @@ namespace CtrEditor
|
|||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed && !_isDrawingCanvas)
|
||||
{
|
||||
// Verificar si el clic fue en el canvas, imagen de fondo o en el rectángulo de selección
|
||||
if (e.Source == ImagenEnTrabajoCanvas ||
|
||||
// Permitir el panning cuando se hace clic en el área de panning o en la imagen
|
||||
if (e.Source == _panningArea ||
|
||||
e.Source == imagenDeFondo ||
|
||||
e.Source == ImagenEnTrabajoCanvas ||
|
||||
(e.Source is Rectangle rect && rect == _objectManager._selectionRectangle))
|
||||
{
|
||||
ImagenEnTrabajoCanvas.Focus();
|
||||
|
@ -173,7 +203,7 @@ namespace CtrEditor
|
|||
{
|
||||
_isDraggingCanvas = true;
|
||||
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
|
||||
ImagenEnTrabajoCanvas.CaptureMouse();
|
||||
ImagenEnTrabajoCanvas.CaptureMouse(); // Importante: siempre capturar en el Canvas principal
|
||||
Mouse.OverrideCursor = Cursors.Hand;
|
||||
|
||||
if (DataContext is MainViewModel viewModel)
|
||||
|
@ -223,7 +253,7 @@ namespace CtrEditor
|
|||
|
||||
double minZoomFactor = Math.Min(
|
||||
ImagenEnTrabajoScrollViewer.ViewportWidth / ImagenEnTrabajoCanvas.ActualWidth,
|
||||
ImagenEnTrabajoScrollViewer.ViewportHeight / ImagenEnTrabajoCanvas.ActualHeight);
|
||||
ImagenEnTrabajoScrollViewer.ViewportHeight / ImagenEnTrabajoCanvas.ActualHeight)/1.5;
|
||||
|
||||
_targetZoomFactor = e.Delta > 0 ?
|
||||
_initialZoomFactor * 1.4 :
|
||||
|
@ -310,6 +340,25 @@ namespace CtrEditor
|
|||
}
|
||||
}
|
||||
|
||||
private void ImagePathButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new Ookii.Dialogs.Wpf.VistaOpenFileDialog
|
||||
{
|
||||
Filter = "Image files (*.png;*.jpg;*.bmp)|*.png;*.jpg;*.bmp|All files (*.*)|*.*"
|
||||
};
|
||||
|
||||
if (dlg.ShowDialog() == true)
|
||||
{
|
||||
// El DataContext de este botón es el PropertyItem asociado
|
||||
if ((sender as Button)?.DataContext is Xceed.Wpf.Toolkit.PropertyGrid.PropertyItem propertyItem)
|
||||
{
|
||||
propertyItem.Value = dlg.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void MainWindow_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
// Only force canvas focus if PanelEdicion doesn't have focus
|
||||
|
|
|
@ -259,19 +259,32 @@ namespace CtrEditor
|
|||
return rect;
|
||||
}
|
||||
|
||||
private void AddResizeHandles(FuncionesBase.MutableRect rectBox, double rectSize,
|
||||
private void AddResizeHandles(FuncionesBase.MutableRect rectBox, double defaultRectSize,
|
||||
Cursor rotationCursorRx, Cursor rotationCursorSx)
|
||||
{
|
||||
// Calcular el tamaño apropiado para los manejadores basado en el tamaño del objeto
|
||||
double minObjectDimension = Math.Min(rectBox.Width, rectBox.Height);
|
||||
double rectSize = Math.Min(defaultRectSize, minObjectDimension / 3);
|
||||
|
||||
// Asegurar un tamaño mínimo para los manejadores
|
||||
rectSize = Math.Max(rectSize, 6);
|
||||
|
||||
// Calcular el offset para posicionar los manejadores fuera del rectángulo
|
||||
double offset = rectSize / 2;
|
||||
|
||||
var positions = new List<(Point Position, string Tag, Cursor Cursor, Brush Stroke)>
|
||||
{
|
||||
(new Point(rectBox.Left, rectBox.Top), "TopLeft", Cursors.Arrow, Brushes.Gray),
|
||||
(new Point(rectBox.Right, rectBox.Top), "TopRight", rotationCursorRx, Brushes.Red),
|
||||
(new Point(rectBox.Left, rectBox.Bottom), "BottomLeft", rotationCursorSx, Brushes.DarkRed),
|
||||
(new Point(rectBox.Right, rectBox.Bottom), "BottomRight", Cursors.SizeNWSE, Brushes.Blue),
|
||||
(new Point(rectBox.Left + rectBox.Width / 2, rectBox.Top), "TopCenter", Cursors.Arrow, Brushes.Gray),
|
||||
(new Point(rectBox.Left + rectBox.Width / 2, rectBox.Bottom), "BottomCenter", Cursors.SizeNS, Brushes.Blue),
|
||||
(new Point(rectBox.Left, rectBox.Top + rectBox.Height / 2), "CenterLeft", rotationCursorRx, Brushes.Red),
|
||||
(new Point(rectBox.Right, rectBox.Top + rectBox.Height / 2), "CenterRight", Cursors.SizeWE, Brushes.Blue)
|
||||
// Esquinas - mover hacia afuera del rectángulo
|
||||
(new Point(rectBox.Left - offset, rectBox.Top - offset), "TopLeft", Cursors.Arrow, Brushes.Gray),
|
||||
(new Point(rectBox.Right + offset, rectBox.Top - offset), "TopRight", rotationCursorRx, Brushes.Red),
|
||||
(new Point(rectBox.Left - offset, rectBox.Bottom + offset), "BottomLeft", rotationCursorSx, Brushes.DarkRed),
|
||||
(new Point(rectBox.Right + offset, rectBox.Bottom + offset), "BottomRight", Cursors.SizeNWSE, Brushes.Blue),
|
||||
|
||||
// Centros de los bordes - mover hacia afuera del rectángulo
|
||||
(new Point(rectBox.Left + rectBox.Width / 2, rectBox.Top - offset), "TopCenter", Cursors.Arrow, Brushes.Gray),
|
||||
(new Point(rectBox.Left + rectBox.Width / 2, rectBox.Bottom + offset), "BottomCenter", Cursors.SizeNS, Brushes.Blue),
|
||||
(new Point(rectBox.Left - offset, rectBox.Top + rectBox.Height / 2), "CenterLeft", rotationCursorRx, Brushes.Red),
|
||||
(new Point(rectBox.Right + offset, rectBox.Top + rectBox.Height / 2), "CenterRight", Cursors.SizeWE, Brushes.Blue)
|
||||
};
|
||||
|
||||
foreach (var (Position, Tag, Cursor, Stroke) in positions)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<UserControl x:Class="CtrEditor.ObjetosSim.ucCustomImage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:CtrEditor.ObjetosSim">
|
||||
|
||||
<UserControl.DataContext>
|
||||
<vm:osCustomImage />
|
||||
</UserControl.DataContext>
|
||||
|
||||
<Image Source="{Binding ImageSource_oculta}"
|
||||
Width="{Binding Ancho, Converter={StaticResource MeterToPixelConverter}}"
|
||||
Height="{Binding Alto, Converter={StaticResource MeterToPixelConverter}}" Stretch="Fill" />
|
||||
|
||||
</UserControl>
|
|
@ -0,0 +1,94 @@
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using LibS7Adv;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using CtrEditor.FuncionesBase;
|
||||
using System.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CtrEditor.ObjetosSim
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom image control that can display an image from a file path
|
||||
/// </summary>
|
||||
public partial class osCustomImage : osBase, IosBase
|
||||
{
|
||||
public static string NombreClase()
|
||||
{
|
||||
return "Custom Image";
|
||||
}
|
||||
|
||||
private string nombre = NombreClase();
|
||||
public override string Nombre
|
||||
{
|
||||
get => nombre;
|
||||
set => SetProperty(ref nombre, value);
|
||||
}
|
||||
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ImageSource_oculta))]
|
||||
[property: Description("Path to the image file")]
|
||||
[property: Category("Image:")]
|
||||
private string imagePath;
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
[ObservableProperty]
|
||||
public ImageSource imageSource_oculta;
|
||||
|
||||
partial void OnImagePathChanged(string value)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
ImageSource_oculta = ImageFromPath(value);
|
||||
}
|
||||
}
|
||||
|
||||
public osCustomImage()
|
||||
{
|
||||
Ancho = 0.30f;
|
||||
Alto = 0.30f;
|
||||
}
|
||||
|
||||
public override void ucLoaded()
|
||||
{
|
||||
base.ucLoaded();
|
||||
if (!string.IsNullOrEmpty(ImagePath))
|
||||
{
|
||||
ImageSource_oculta = ImageFromPath(ImagePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ucCustomImage : UserControl, IDataContainer
|
||||
{
|
||||
public osBase? Datos { get; set; }
|
||||
public int zIndex_fromFrames { get; set; }
|
||||
|
||||
public ucCustomImage()
|
||||
{
|
||||
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 Highlight(bool State) { }
|
||||
|
||||
public ZIndexEnum ZIndex_Base()
|
||||
{
|
||||
return ZIndexEnum.Estaticos;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -96,45 +96,52 @@ namespace CtrEditor.ObjetosSim
|
|||
|
||||
public static void CargarPropiedadesosDatos(object selectedObject, PropertyGrid propertyGrid)
|
||||
{
|
||||
// Clear previous properties
|
||||
// Limpia las propiedades previas
|
||||
propertyGrid.SelectedObject = null;
|
||||
propertyGrid.PropertyDefinitions.Clear();
|
||||
|
||||
// Add properties dynamically based on attributes
|
||||
// Obtén las propiedades del objeto (excluyendo las que tengan HiddenAttribute)
|
||||
var properties = TypeDescriptor.GetProperties(selectedObject)
|
||||
.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)
|
||||
{
|
||||
if (property.Name.EndsWith("_oculto"))
|
||||
continue;
|
||||
|
||||
var displayNameAttr = property.Attributes.OfType<DisplayNameAttribute>().FirstOrDefault();
|
||||
var propertyDefinition = new PropertyDefinition
|
||||
{
|
||||
TargetProperties = new[] { property.Name }
|
||||
TargetProperties = new[] { property.Name },
|
||||
DisplayName = displayNameAttr != null
|
||||
? displayNameAttr.DisplayName
|
||||
: property.Name.Replace("_", " ")
|
||||
};
|
||||
|
||||
if (!property.Name.EndsWith("_oculto"))
|
||||
// Aquí se añaden todas las propiedades; para "ImagePath" no se requiere
|
||||
// ninguna configuración adicional, pues el EditorTemplateDefinition en XAML se
|
||||
// aplicará automáticamente.
|
||||
if (property.PropertyType == typeof(double) ||
|
||||
property.PropertyType == typeof(float) ||
|
||||
property.PropertyType == typeof(string) ||
|
||||
property.PropertyType == typeof(int) ||
|
||||
property.PropertyType == typeof(bool) ||
|
||||
property.PropertyType == typeof(osBase) ||
|
||||
property.PropertyType == typeof(osVMmotorSim) ||
|
||||
property.PropertyType == typeof(osBuscarCoincidencias) ||
|
||||
property.PropertyType == typeof(Color))
|
||||
{
|
||||
if (displayNameAttr != null)
|
||||
{
|
||||
propertyDefinition.DisplayName = displayNameAttr.DisplayName;
|
||||
}
|
||||
else
|
||||
{
|
||||
propertyDefinition.DisplayName = property.Name.Replace("_", " ");
|
||||
}
|
||||
if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float) || property.PropertyType == typeof(string) || property.PropertyType == typeof(int) ||
|
||||
property.PropertyType == typeof(bool) || property.PropertyType == typeof(osBase) ||
|
||||
property.PropertyType == typeof(osVMmotorSim) || property.PropertyType == typeof(osBuscarCoincidencias) || property.PropertyType == typeof(Color) )
|
||||
{
|
||||
propertyGrid.PropertyDefinitions.Add(propertyDefinition);
|
||||
}
|
||||
propertyGrid.PropertyDefinitions.Add(propertyDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
propertyGrid.SelectedObject = selectedObject;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue