Se mejoró la funcionalidad de renombrado de imágenes en la interfaz, integrando un PropertyGrid para editar propiedades de imágenes, incluyendo etiquetas. Se actualizó la lógica para eliminar entradas vacías y se modificó el diseño de la ventana de renombrado para una mejor experiencia de usuario. Además, se implementó un editor de etiquetas que permite gestionar etiquetas de manera más eficiente.
This commit is contained in:
parent
909e438f5b
commit
354b4a8acf
|
@ -416,37 +416,26 @@ namespace CtrEditor
|
|||
if (string.IsNullOrEmpty(imageName)) return;
|
||||
|
||||
var imageData = GetOrCreateImageData(imageName);
|
||||
var currentCustomName = imageData.CustomName;
|
||||
|
||||
var dialog = new PopUps.RenameImageWindow(imageName, currentCustomName);
|
||||
var dialog = new PopUps.RenameImageWindow(imageName, imageData);
|
||||
dialog.Owner = MainWindow;
|
||||
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
string newName = dialog.NewImageName?.Trim() ?? string.Empty;
|
||||
|
||||
if (newName != currentCustomName)
|
||||
// El dialog ya ha modificado directamente el imageData
|
||||
// Solo necesitamos verificar si debemos remover la entrada si está vacía
|
||||
if (string.IsNullOrEmpty(imageData.CustomName) &&
|
||||
imageData.Tags.Count == 0 &&
|
||||
string.IsNullOrEmpty(imageData.Etiquetas))
|
||||
{
|
||||
if (string.IsNullOrEmpty(newName))
|
||||
{
|
||||
// Si el nuevo nombre está vacío, removemos la entrada personalizada
|
||||
imageData.CustomName = string.Empty;
|
||||
if (string.IsNullOrEmpty(imageData.CustomName) && imageData.Tags.Count == 0)
|
||||
{
|
||||
_imageDataDictionary.Remove(imageName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
imageData.CustomName = newName;
|
||||
}
|
||||
|
||||
// Forzar actualización del UI usando CollectionViewSource
|
||||
var collectionView = System.Windows.Data.CollectionViewSource.GetDefaultView(ListaImagenes);
|
||||
collectionView?.Refresh();
|
||||
|
||||
HasUnsavedChanges = true;
|
||||
_imageDataDictionary.Remove(imageName);
|
||||
}
|
||||
|
||||
// Forzar actualización del UI usando CollectionViewSource
|
||||
var collectionView = System.Windows.Data.CollectionViewSource.GetDefaultView(ListaImagenes);
|
||||
collectionView?.Refresh();
|
||||
|
||||
HasUnsavedChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
</ListBox.ItemTemplate>
|
||||
<ListBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Renombrar" Command="{Binding RenameImageCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
|
||||
<MenuItem Header="Propiedades" Command="{Binding RenameImageCommand}" CommandParameter="{Binding PlacementTarget.SelectedItem, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
|
||||
</ContextMenu>
|
||||
</ListBox.ContextMenu>
|
||||
</ListBox>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using CtrEditor.ObjetosSim;
|
||||
using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
|
||||
using System.Linq;
|
||||
|
||||
namespace CtrEditor.Models
|
||||
{
|
||||
|
@ -8,9 +11,11 @@ namespace CtrEditor.Models
|
|||
{
|
||||
private string _customName;
|
||||
private List<string> _tags;
|
||||
private string _etiquetas;
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
||||
[DisplayName("Nombre personalizado")]
|
||||
public string CustomName
|
||||
{
|
||||
get => _customName;
|
||||
|
@ -21,13 +26,59 @@ namespace CtrEditor.Models
|
|||
}
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
public List<string> Tags
|
||||
{
|
||||
get => _tags ?? new List<string>();
|
||||
set
|
||||
{
|
||||
_tags = value;
|
||||
_etiquetas = string.Join(" ", value.Select(tag => tag.StartsWith("#") ? tag : "#" + tag));
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(Etiquetas));
|
||||
}
|
||||
}
|
||||
|
||||
[DisplayName("Etiquetas")]
|
||||
[property: Editor(typeof(TagPropertyEditor), typeof(TagPropertyEditor))]
|
||||
public string Etiquetas
|
||||
{
|
||||
get => _etiquetas ?? string.Empty;
|
||||
set
|
||||
{
|
||||
_etiquetas = value ?? string.Empty;
|
||||
// Convertir string de etiquetas a List<string>
|
||||
if (string.IsNullOrWhiteSpace(_etiquetas))
|
||||
{
|
||||
_tags = new List<string>();
|
||||
}
|
||||
else
|
||||
{
|
||||
_tags = _etiquetas.Split(' ', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(tag => tag.StartsWith("#") ? tag.Substring(1) : tag)
|
||||
.Where(tag => !string.IsNullOrWhiteSpace(tag))
|
||||
.ToList();
|
||||
}
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(Tags));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lista de etiquetas sin el prefijo #, compatible con osBase
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
public List<string> ListaEtiquetas
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Etiquetas))
|
||||
return new List<string>();
|
||||
|
||||
return Etiquetas.Split(' ', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(tag => tag.StartsWith("#") ? tag.Substring(1) : tag)
|
||||
.Where(tag => !string.IsNullOrWhiteSpace(tag))
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +89,7 @@ namespace CtrEditor.Models
|
|||
FileName = string.Empty;
|
||||
_customName = string.Empty;
|
||||
_tags = new List<string>();
|
||||
_etiquetas = string.Empty;
|
||||
}
|
||||
|
||||
public ImageData(string fileName, string customName = null, List<string> tags = null)
|
||||
|
@ -45,6 +97,7 @@ namespace CtrEditor.Models
|
|||
FileName = fileName;
|
||||
_customName = customName ?? string.Empty;
|
||||
_tags = tags ?? new List<string>();
|
||||
_etiquetas = string.Join(" ", _tags.Select(tag => tag.StartsWith("#") ? tag : "#" + tag));
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Windows.Data;
|
|||
using CtrEditor.PopUps;
|
||||
using Xceed.Wpf.Toolkit.PropertyGrid;
|
||||
using Xceed.Wpf.Toolkit.PropertyGrid.Editors;
|
||||
using CtrEditor.Models;
|
||||
|
||||
namespace CtrEditor.ObjetosSim
|
||||
{
|
||||
|
@ -50,18 +51,18 @@ namespace CtrEditor.ObjetosSim
|
|||
{
|
||||
try
|
||||
{
|
||||
// Obtener el objeto que se está editando
|
||||
if (propertyItem.Instance is osBase osObject)
|
||||
{
|
||||
// Obtener el MainWindow para acceder a todos los objetos
|
||||
var mainWindow = Application.Current.Windows
|
||||
.OfType<MainWindow>()
|
||||
.FirstOrDefault();
|
||||
// Obtener el MainWindow para acceder a todos los objetos
|
||||
var mainWindow = Application.Current.Windows
|
||||
.OfType<MainWindow>()
|
||||
.FirstOrDefault();
|
||||
|
||||
if (mainWindow?.DataContext is MainViewModel mainViewModel)
|
||||
if (mainWindow?.DataContext is MainViewModel mainViewModel)
|
||||
{
|
||||
// Determinar si el objeto es osBase o ImageData
|
||||
if (propertyItem.Instance is osBase osObject)
|
||||
{
|
||||
// Abrir el editor de etiquetas
|
||||
var tagEditor = new TagEditorWindow(osObject, mainViewModel.ObjetosSimulables);
|
||||
// Abrir el editor de etiquetas para osBase
|
||||
var tagEditor = new TagEditorWindow(osObject, mainViewModel.ObjetosSimulables, mainViewModel._imageDataDictionary);
|
||||
tagEditor.Owner = mainWindow;
|
||||
|
||||
if (tagEditor.ShowDialog() == true)
|
||||
|
@ -71,6 +72,22 @@ namespace CtrEditor.ObjetosSim
|
|||
textBox.GetBindingExpression(TextBox.TextProperty)?.UpdateTarget();
|
||||
}
|
||||
}
|
||||
else if (propertyItem.Instance is ImageData imageData)
|
||||
{
|
||||
// Para ImageData, crear un osBase temporal para usar el editor
|
||||
var tempOsBase = new osTextPlate();
|
||||
tempOsBase.Etiquetas = imageData.Etiquetas;
|
||||
|
||||
var tagEditor = new TagEditorWindow(tempOsBase, mainViewModel.ObjetosSimulables, mainViewModel._imageDataDictionary);
|
||||
tagEditor.Owner = mainWindow;
|
||||
|
||||
if (tagEditor.ShowDialog() == true)
|
||||
{
|
||||
// Actualizar ImageData con las nuevas etiquetas
|
||||
imageData.Etiquetas = tempOsBase.Etiquetas;
|
||||
textBox.GetBindingExpression(TextBox.TextProperty)?.UpdateTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<Window x:Class="CtrEditor.PopUps.RenameImageWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Renombrar Imagen" Height="200" Width="400"
|
||||
WindowStartupLocation="CenterOwner" ResizeMode="NoResize">
|
||||
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
|
||||
Title="Editar Información de Imagen" Height="400" Width="500"
|
||||
WindowStartupLocation="CenterOwner" ResizeMode="CanResize">
|
||||
<Grid Margin="20">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
|
@ -13,12 +13,43 @@
|
|||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Text="Archivo original:" FontWeight="Bold" Margin="0,0,0,5"/>
|
||||
<TextBlock Grid.Row="1" x:Name="OriginalNameTextBlock" Margin="0,0,0,10" Foreground="Gray"/>
|
||||
<TextBlock Grid.Row="1" x:Name="OriginalNameTextBlock" Margin="0,0,0,15" Foreground="Gray"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Text="Nombre personalizado:" FontWeight="Bold" Margin="0,0,0,5"/>
|
||||
<TextBox Grid.Row="3" x:Name="NewNameTextBox" Margin="0,0,0,15" VerticalAlignment="Top"/>
|
||||
<GroupBox Grid.Row="2" Header="Propiedades de la Imagen" Margin="0,0,0,15">
|
||||
<xctk:PropertyGrid x:Name="PropertyGridControl"
|
||||
ShowSortOptions="False"
|
||||
ShowSearchBox="False"
|
||||
ShowSummary="True"
|
||||
ShowAdvancedOptions="False"
|
||||
ShowTitle="False"
|
||||
Margin="5">
|
||||
<xctk:PropertyGrid.EditorDefinitions>
|
||||
<xctk:EditorTemplateDefinition TargetProperties="Etiquetas">
|
||||
<xctk:EditorTemplateDefinition.EditingTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0"
|
||||
Text="{Binding Value, UpdateSourceTrigger=PropertyChanged}"
|
||||
VerticalAlignment="Stretch"/>
|
||||
<Button Grid.Column="1"
|
||||
Content="..."
|
||||
Width="25"
|
||||
Margin="2,0,0,0"
|
||||
ToolTip="Abrir editor de etiquetas"
|
||||
Click="TagEditorButton_Click"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</xctk:EditorTemplateDefinition.EditingTemplate>
|
||||
</xctk:EditorTemplateDefinition>
|
||||
</xctk:PropertyGrid.EditorDefinitions>
|
||||
</xctk:PropertyGrid>
|
||||
</GroupBox>
|
||||
|
||||
<StackPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button x:Name="OkButton" Content="Aceptar" Width="80" Margin="0,0,10,0" IsDefault="True" Click="OkButton_Click"/>
|
||||
<Button x:Name="CancelButton" Content="Cancelar" Width="80" IsCancel="True" Click="CancelButton_Click"/>
|
||||
</StackPanel>
|
||||
|
|
|
@ -1,24 +1,72 @@
|
|||
using System.Windows;
|
||||
using CtrEditor.Models;
|
||||
using CtrEditor.ObjetosSim;
|
||||
using Xceed.Wpf.Toolkit.PropertyGrid;
|
||||
|
||||
namespace CtrEditor.PopUps
|
||||
{
|
||||
public partial class RenameImageWindow : Window
|
||||
{
|
||||
public string? NewImageName { get; private set; }
|
||||
public ImageData ImageData { get; private set; }
|
||||
public bool IsOkClicked { get; private set; }
|
||||
|
||||
public RenameImageWindow(string originalName, string currentCustomName = null)
|
||||
public RenameImageWindow(string originalName, ImageData imageData = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
OriginalNameTextBlock.Text = originalName;
|
||||
NewNameTextBox.Text = currentCustomName ?? string.Empty;
|
||||
NewNameTextBox.SelectAll();
|
||||
NewNameTextBox.Focus();
|
||||
|
||||
// Crear o usar ImageData existente
|
||||
ImageData = imageData ?? new ImageData
|
||||
{
|
||||
FileName = originalName,
|
||||
CustomName = string.Empty,
|
||||
Etiquetas = string.Empty
|
||||
};
|
||||
|
||||
// Configurar PropertyGrid
|
||||
PropertyGridControl.SelectedObject = ImageData;
|
||||
|
||||
Focus();
|
||||
}
|
||||
|
||||
private void TagEditorButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Obtener el MainWindow para acceder a todos los objetos
|
||||
var mainWindow = Application.Current.Windows
|
||||
.OfType<MainWindow>()
|
||||
.FirstOrDefault();
|
||||
|
||||
if (mainWindow?.DataContext is MainViewModel mainViewModel)
|
||||
{
|
||||
// Para ImageData, crear un osBase temporal para usar el editor
|
||||
var tempOsBase = new osTextPlate();
|
||||
tempOsBase.Etiquetas = ImageData.Etiquetas;
|
||||
|
||||
var tagEditor = new TagEditorWindow(tempOsBase, mainViewModel.ObjetosSimulables, mainViewModel._imageDataDictionary);
|
||||
tagEditor.Owner = this;
|
||||
|
||||
if (tagEditor.ShowDialog() == true)
|
||||
{
|
||||
// Actualizar ImageData con las nuevas etiquetas
|
||||
ImageData.Etiquetas = tempOsBase.Etiquetas;
|
||||
|
||||
// Forzar actualización del PropertyGrid
|
||||
PropertyGridControl.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show($"Error al abrir el editor de etiquetas: {ex.Message}",
|
||||
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
NewImageName = NewNameTextBox.Text?.Trim();
|
||||
IsOkClicked = true;
|
||||
DialogResult = true;
|
||||
Close();
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Windows.Input;
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CtrEditor.ObjetosSim;
|
||||
using CtrEditor.Models;
|
||||
|
||||
namespace CtrEditor.PopUps
|
||||
{
|
||||
|
@ -13,10 +14,10 @@ namespace CtrEditor.PopUps
|
|||
/// </summary>
|
||||
public partial class TagEditorWindow : Window
|
||||
{
|
||||
public TagEditorWindow(osBase objeto, IEnumerable<osBase> todosLosObjetos)
|
||||
public TagEditorWindow(osBase objeto, IEnumerable<osBase> todosLosObjetos, Dictionary<string, ImageData> imageDataDictionary = null)
|
||||
{
|
||||
InitializeComponent();
|
||||
DataContext = new TagEditorViewModel(objeto, todosLosObjetos, this);
|
||||
DataContext = new TagEditorViewModel(objeto, todosLosObjetos, this, imageDataDictionary);
|
||||
}
|
||||
|
||||
private void TxtNuevaEtiqueta_KeyDown(object sender, KeyEventArgs e)
|
||||
|
@ -46,6 +47,7 @@ namespace CtrEditor.PopUps
|
|||
{
|
||||
private readonly osBase _objeto;
|
||||
private readonly IEnumerable<osBase> _todosLosObjetos;
|
||||
private readonly Dictionary<string, ImageData> _imageDataDictionary;
|
||||
private readonly TagEditorWindow _window;
|
||||
private readonly List<string> _etiquetasOriginales;
|
||||
|
||||
|
@ -64,10 +66,11 @@ namespace CtrEditor.PopUps
|
|||
public ICommand AplicarCommand { get; }
|
||||
public ICommand CancelarCommand { get; }
|
||||
|
||||
public TagEditorViewModel(osBase objeto, IEnumerable<osBase> todosLosObjetos, TagEditorWindow window)
|
||||
public TagEditorViewModel(osBase objeto, IEnumerable<osBase> todosLosObjetos, TagEditorWindow window, Dictionary<string, ImageData> imageDataDictionary = null)
|
||||
{
|
||||
_objeto = objeto;
|
||||
_todosLosObjetos = todosLosObjetos;
|
||||
_imageDataDictionary = imageDataDictionary;
|
||||
_window = window;
|
||||
|
||||
// Guardar las etiquetas originales para poder cancelar
|
||||
|
@ -111,9 +114,22 @@ namespace CtrEditor.PopUps
|
|||
var todasLasEtiquetas = _todosLosObjetos
|
||||
.SelectMany(obj => obj.ListaEtiquetas)
|
||||
.Distinct()
|
||||
.OrderBy(tag => tag)
|
||||
.ToList();
|
||||
|
||||
// Agregar etiquetas de las imágenes si está disponible el diccionario
|
||||
if (_imageDataDictionary != null)
|
||||
{
|
||||
var etiquetasImagenes = _imageDataDictionary.Values
|
||||
.SelectMany(imageData => imageData.ListaEtiquetas)
|
||||
.Distinct();
|
||||
|
||||
todasLasEtiquetas.AddRange(etiquetasImagenes);
|
||||
todasLasEtiquetas = todasLasEtiquetas.Distinct().ToList();
|
||||
}
|
||||
|
||||
// Ordenar todas las etiquetas
|
||||
todasLasEtiquetas = todasLasEtiquetas.OrderBy(tag => tag).ToList();
|
||||
|
||||
// Mostrar solo las que no están en el objeto actual
|
||||
var etiquetasObjetoActual = _objeto.ListaEtiquetas;
|
||||
foreach (var tag in todasLasEtiquetas.Except(etiquetasObjetoActual))
|
||||
|
|
Loading…
Reference in New Issue