using System.IO; using System.Text; 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.Navigation; using System.Windows.Shapes; using Path = System.IO.Path; namespace ROIEditor { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { private Point? clickPosition = null; private bool _isDrawing = false; private bool _EstaCargandoTrabajo = false; private Point _startPosition; private Rectangle _currentRect = null; private Image imagenDeFondo; private bool _isDragging = false; private Point _lastMousePosition; private ListaPersistente ListaDeROIs; private ItemPersistente EstadoImagenActual; private EstadoTrabajo Estado; // Constructor de MainWindow public MainWindow() { InitializeComponent(); this.Closing += MainWindow_Closing; // Suscribir al evento Closing ListaImagenes.SelectionChanged += ListaImagenes_SelectionChanged; ImagenEnTrabajoCanvas.MouseLeftButtonDown += ImagenEnTrabajoCanvas_MouseLeftButtonDown; ImagenEnTrabajoCanvas.MouseRightButtonDown += ImagenEnTrabajoCanvas_MouseRightButtonDown; ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown; ImagenEnTrabajoCanvas.MouseMove += Canvas_MouseMove; ImagenEnTrabajoScrollViewer.PreviewMouseWheel += ImagenEnTrabajoCanvas_MouseWheel; // En el constructor de MainWindow o un método de inicialización ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown_Panning; ImagenEnTrabajoCanvas.MouseMove += Canvas_MouseMove_Panning; ImagenEnTrabajoCanvas.MouseUp += Canvas_MouseUp_Panning; // Agrega este manejador en el inicializador de tu ventana o control ListaROIs.SelectionChanged += ListaROIs_SelectionChanged; // Agrega este manejador en el inicializador de tu ventana o control Guardar_ROI.Click += Guardar_ROI_Click; Borrar_ROI.Click += Borrar_ROI_Click; // Suscripción a los eventos LostFocus ROI_xy.LostFocus += GuardarCambiosRoi; ROI_dxdy.LostFocus += GuardarCambiosRoi; ROI_descripcion.LostFocus += GuardarCambiosRoi; // Se carga el ultimo estado Estado = EstadoTrabajo.CargarEstado(); DirectorioTrabajo.Text = Estado.strDirectorioTrabajo; ActualizarPorCambioDirTrabajo(); } private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { SalvarEstadoImgen_y_ROIs(); Estado.GuardarEstado(); // Guardar el estado cuando la ventana se cierra } private void SeleccionarDirectorio_Click(object sender, RoutedEventArgs e) { var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog(); if (dialog.ShowDialog(this).GetValueOrDefault()) { DirectorioTrabajo.Text = dialog.SelectedPath; if (Estado.strDirectorioTrabajo != DirectorioTrabajo.Text) { Estado.strDirectorioTrabajo = DirectorioTrabajo.Text; ActualizarPorCambioDirTrabajo(); } } } private void LeerDirectorio_Click(object sender, RoutedEventArgs e) { ActualizarPorCambioDirTrabajo(); } private void ActualizarPorCambioDirTrabajo() { string dbPath = Estado.CarpetaDB(); _EstaCargandoTrabajo = true; ListaDeROIs = new ListaPersistente(dbPath, "ROIs"); EstadoImagenActual = new ItemPersistente(dbPath, "estados"); CargarImagenes(); if (!string.IsNullOrEmpty(Estado.NombreImagenEditando)) { for (int i = 0; i < ListaImagenes.Items.Count; i++) { if ((string)ListaImagenes.Items[i] == Estado.NombreImagenEditando) { ListaImagenes.SelectedIndex = i; // Selecciona el ítem que coincide con el último editado break; } } } _EstaCargandoTrabajo = false; } private void ListaROIs_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (ListaROIs.SelectedItem is Roi selectedRoi) { CargarDatosROI(selectedRoi); } } private void Borrar_ROI_Click(object sender, RoutedEventArgs e) { if (ListaROIs.SelectedItem is Roi selectedRoi) { ListaDeROIs.Remove(selectedRoi); ActualizarListaROIsEnUI(); } } private void Guardar_ROI_Click(object sender, RoutedEventArgs e) { if (ListaROIs.SelectedItem is Roi selectedRoi) { ActualizarDatosROI(selectedRoi); } } private void CargarDatosROI(Roi selectedRoi) { ROI_xy.Text = $"{selectedRoi.X}, {selectedRoi.Y}"; ROI_dxdy.Text = $"{selectedRoi.Width}, {selectedRoi.Height}"; ROI_descripcion.Text = selectedRoi.Descripcion; for (int i = 0; i < ROI_imagen.Items.Count; i++) { if ((string)ROI_imagen.Items[i] == Estado.NombreImagenEditando) { ROI_imagen.SelectedIndex = i; // Selecciona el ítem que coincide con el último editado break; } } } private void ActualizarDatosROI(Roi selectedRoi) { try { // Suponiendo que se validen y parseen adecuadamente los valores var xy = ROI_xy.Text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var dxdy = ROI_dxdy.Text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); selectedRoi.X = int.Parse(xy[0].Trim()); selectedRoi.Y = int.Parse(xy[1].Trim()); selectedRoi.Width = int.Parse(dxdy[0].Trim()); selectedRoi.Height = int.Parse(dxdy[1].Trim()); selectedRoi.Descripcion = ROI_descripcion.Text; // Aquí podrías llamar a un método que realice el guardado específico, si es necesario // Por ejemplo, actualizar la visualización del ROI o guardar en un archivo JSON } catch (Exception ex) { // Manejar posibles errores de parseo o validación MessageBox.Show($"Error al actualizar los datos del ROI: {ex.Message}"); } } private void GuardarCambiosRoi(object sender, RoutedEventArgs e) { if (ListaROIs.SelectedItem is Roi selectedRoi) { ActualizarDatosROI(selectedRoi); // Si se modificaron las coordenadas DibujarROIsEnCanvas(); } } private void CargarImagenes() { // Asumiendo que las imágenes están en una carpeta "Imagenes" dentro del directorio de salida de tu aplicación string folderPath = Estado.PNG_Folther_Path(); if (Directory.Exists(folderPath)) { var archivosImagen = Directory.GetFiles(folderPath, "*.png"); // Asumiendo que buscas archivos .png ListaImagenes.Items.Clear(); ROI_imagen.Items.Clear(); foreach (var archivo in archivosImagen) { // Aquí simplemente añadimos el nombre del archivo a la lista, pero podrías querer añadir un objeto más complejo ListaImagenes.Items.Add(Path.GetFileName(archivo)); ROI_imagen.Items.Add(Path.GetFileName(archivo)); } } else { MessageBox.Show("No se encontró la carpeta de imágenes."); } } private void Canvas_MouseDown_Panning(object sender, MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && !_isDrawing) { // Indica que se inicia el panning _isDragging = true; // Guarda la posición actual del ratón _lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer); //ImagenEnTrabajoScrollViewer.CaptureMouse(); // Importante para capturar el movimiento } } private void Canvas_MouseMove_Panning(object sender, MouseEventArgs e) { if (_isDragging && !_isDrawing) { // Calcula el nuevo desplazamiento basado en el movimiento del ratón var currentPosition = e.GetPosition(ImagenEnTrabajoScrollViewer); var dx = currentPosition.X - _lastMousePosition.X; var dy = currentPosition.Y - _lastMousePosition.Y; // Ajusta el desplazamiento del ScrollViewer ImagenEnTrabajoScrollViewer.ScrollToHorizontalOffset(ImagenEnTrabajoScrollViewer.HorizontalOffset - dx); ImagenEnTrabajoScrollViewer.ScrollToVerticalOffset(ImagenEnTrabajoScrollViewer.VerticalOffset - dy); // Actualiza la posición del ratón para el próximo movimiento _lastMousePosition = currentPosition; } } private void Canvas_MouseUp_Panning(object sender, MouseButtonEventArgs e) { if (_isDragging) { _isDragging = false; ImagenEnTrabajoScrollViewer.ReleaseMouseCapture(); // Finaliza la captura del ratón } } private void Canvas_MouseDown(object sender, MouseButtonEventArgs e) { // Verifica si el botón derecho del ratón fue el que se presionó if (e.ChangedButton == MouseButton.Right) { if (!_isDrawing) { _startPosition = e.GetPosition(ImagenEnTrabajoCanvas); _isDrawing = true; // Inicializar un nuevo rectángulo _currentRect = new Rectangle { Stroke = Brushes.Red, StrokeThickness = 2, Fill = Brushes.Transparent }; Canvas.SetLeft(_currentRect, _startPosition.X); Canvas.SetTop(_currentRect, _startPosition.Y); ImagenEnTrabajoCanvas.Children.Add(_currentRect); } else { // Finaliza el dibujo del rectángulo _isDrawing = false; // Calcula las dimensiones finales y posición del ROI var endPosition = e.GetPosition(ImagenEnTrabajoCanvas); var x = Math.Min(_startPosition.X, endPosition.X); var y = Math.Min(_startPosition.Y, endPosition.Y); var width = Math.Abs(endPosition.X - _startPosition.X); var height = Math.Abs(endPosition.Y - _startPosition.Y); // Crea el nuevo objeto Roi con la información recopilada Roi newRoi = new Roi(EstadoImagenActual.Get().NombreImagen, (int)x, (int)y, (int)width, (int)height); // Agrega el nuevo Roi a la lista de ROIs ListaDeROIs.Add(newRoi); // Elimina el rectángulo temporal del Canvas ImagenEnTrabajoCanvas.Children.Remove(_currentRect); _currentRect = null; // Actualiza la interfaz de usuario con el nuevo ROI ActualizarListaROIsEnUI(); } } } private void ActualizarListaROIsEnUI() { // Aquí actualizas los controles de la interfaz de usuario que muestran los ROIs // Por ejemplo, si tienes una ListBox para los ROIs, actualízala así: ListaROIs.ItemsSource = null; if (ListaDeROIs.Count > 0) { ListaROIs.ItemsSource = ListaDeROIs.GetList(); } DibujarROIsEnCanvas(); } private void Canvas_MouseMove(object sender, MouseEventArgs e) { if (_isDrawing) { var currentPosition = e.GetPosition(ImagenEnTrabajoCanvas); var width = Math.Abs(currentPosition.X - _startPosition.X); var height = Math.Abs(currentPosition.Y - _startPosition.Y); _currentRect.Width = width; _currentRect.Height = height; // Ajusta la posición si el dibujo se hace hacia arriba o hacia la izquierda if (currentPosition.X < _startPosition.X) { Canvas.SetLeft(_currentRect, currentPosition.X); } if (currentPosition.Y < _startPosition.Y) { Canvas.SetTop(_currentRect, currentPosition.Y); } } } private void ImagenEnTrabajoCanvas_MouseWheel(object sender, MouseWheelEventArgs e) { var st = (ScaleTransform)ImagenEnTrabajoCanvas.LayoutTransform; double zoomFactor = e.Delta > 0 ? 1.1 : 0.9; Point cursorPosition = e.GetPosition(ImagenEnTrabajoScrollViewer); // Calcular el punto focal del zoom relativo al contenido del ScrollViewer var absoluteX = ImagenEnTrabajoScrollViewer.HorizontalOffset + cursorPosition.X; var absoluteY = ImagenEnTrabajoScrollViewer.VerticalOffset + cursorPosition.Y; // Aplicar el zoom st.ScaleX *= zoomFactor; st.ScaleY *= zoomFactor; // Calcular el nuevo desplazamiento para que el zoom se centre en la posición del cursor ImagenEnTrabajoScrollViewer.UpdateLayout(); // Asegurarse de que el layout del ScrollViewer esté actualizado var newHorizontalOffset = absoluteX * zoomFactor - cursorPosition.X; var newVerticalOffset = absoluteY * zoomFactor - cursorPosition.Y; // Aplicar el nuevo desplazamiento ImagenEnTrabajoScrollViewer.ScrollToHorizontalOffset(newHorizontalOffset); ImagenEnTrabajoScrollViewer.ScrollToVerticalOffset(newVerticalOffset); e.Handled = true; // Evita el procesamiento adicional del evento } private void ImagenEnTrabajoCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { var mousePos = e.GetPosition(ImagenEnTrabajoCanvas); // Verificar si mousePos está dentro de algún ROI y mostrar el formulario de comentario si es así } private void ImagenEnTrabajoCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var mousePos = e.GetPosition(ImagenEnTrabajoCanvas); // Aquí puedes inicializar la creación de un nuevo ROI basándote en mousePos } private void CargarImagenEnTrabajo(string imagePath) { BitmapImage bitmap = new BitmapImage(new Uri(imagePath, UriKind.Absolute)); if (imagenDeFondo == null) { imagenDeFondo = new Image(); ImagenEnTrabajoCanvas.Children.Add(imagenDeFondo); } imagenDeFondo.Source = bitmap; RenderOptions.SetBitmapScalingMode(imagenDeFondo, BitmapScalingMode.HighQuality); // Elimina solo los ROIs, no la imagen de fondo for (int i = ImagenEnTrabajoCanvas.Children.Count - 1; i >= 0; i--) { if (ImagenEnTrabajoCanvas.Children[i] is Rectangle) { ImagenEnTrabajoCanvas.Children.RemoveAt(i); } } // Ajusta el tamaño del Canvas a la imagen, si es necesario ImagenEnTrabajoCanvas.Width = bitmap.Width; ImagenEnTrabajoCanvas.Height = bitmap.Height; // Posiciona la imagen correctamente dentro del Canvas Canvas.SetLeft(imagenDeFondo, 0); Canvas.SetTop(imagenDeFondo, 0); } private void ListaImagenes_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (ListaImagenes.SelectedItem != null) { SalvarEstadoImgen_y_ROIs(); Estado.NombreImagenEditando = ListaImagenes.SelectedItem.ToString(); ListaDeROIs.Load(Estado.NombreImagenEditando); ActualizarListaROIsEnUI(); CargarImagenEnTrabajo(Estado.PNG_Extension_Path()); CargarEstadoImagen(); } } private void SalvarEstadoImgen_y_ROIs() { if (!_EstaCargandoTrabajo) { // Si es igual es porque es la primera vez que se carga if (Estado.NombreImagenEditando != null) { SalvarEstadoImagen(); } if (ListaDeROIs.Count > 0) { ListaDeROIs.Save(); } } } private void CargarEstadoImagen() { var st = (ScaleTransform)ImagenEnTrabajoCanvas.LayoutTransform; if (EstadoImagenActual.Load(Estado.NombreImagenEditando)) { var EACargado = EstadoImagenActual.Get(); st.ScaleX = EACargado.ZoomScaleX; st.ScaleY = EACargado.ZoomScaleY; // Aplicar el nuevo desplazamiento ImagenEnTrabajoScrollViewer.ScrollToHorizontalOffset(EACargado.HorizontalOffset); ImagenEnTrabajoScrollViewer.ScrollToVerticalOffset(EACargado.VerticalOffset); DibujarROIsEnCanvas(); } else { var EANuevo = EstadoImagenActual.Get(); EANuevo.NombreImagen = ListaImagenes.SelectedItem.ToString(); EANuevo.ZoomScaleX = st.ScaleX; EANuevo.ZoomScaleY = st.ScaleY; EANuevo.HorizontalOffset = EANuevo.HorizontalOffset; EANuevo.VerticalOffset = EANuevo.VerticalOffset; } } private void SalvarEstadoImagen() { var ea = EstadoImagenActual.Get(); var st = (ScaleTransform)ImagenEnTrabajoCanvas.LayoutTransform; ea.ZoomScaleX = st.ScaleX; ea.ZoomScaleY = st.ScaleY; ea.HorizontalOffset = ImagenEnTrabajoScrollViewer.HorizontalOffset; ea.VerticalOffset = ImagenEnTrabajoScrollViewer.VerticalOffset; EstadoImagenActual.Save(Estado.NombreImagenEditando); } private void DibujarROIsEnCanvas() { // Elimina solo los ROIs, no la imagen de fondo for (int i = ImagenEnTrabajoCanvas.Children.Count - 1; i >= 0; i--) { if (ImagenEnTrabajoCanvas.Children[i] is Rectangle) { ImagenEnTrabajoCanvas.Children.RemoveAt(i); } } // Dibuja los ROIs foreach (var roi in ListaDeROIs.GetList()) { Rectangle rect = roi.DibujarRoiEnCanvas(ImagenEnTrabajoCanvas); // Eventos rect.MouseEnter += Rect_MouseEnter; rect.MouseLeave += Rect_MouseLeave; rect.MouseDown += Rect_MouseDown; } } private void Rect_MouseEnter(object sender, MouseEventArgs e) { if (sender is Rectangle rect) { rect.StrokeThickness = 4; // Aumenta el grosor } } private void Rect_MouseLeave(object sender, MouseEventArgs e) { if (sender is Rectangle rect) { rect.StrokeThickness = 2; // Restaura el grosor } } private void Rect_MouseDown(object sender, MouseButtonEventArgs e) { if (sender is Rectangle rect && rect.Tag is Roi roi) { int index = ListaDeROIs.IndexOf(roi); if (index != -1) { ListaROIs.SelectedIndex = index; // Selecciona el ROI en la lista e.Handled = true; // Evita la propagación del evento } } } } }