S7Explorer/ViewModels/MainViewModel.cs

280 lines
9.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Ookii.Dialogs.Wpf;
using S7Explorer.Models;
using S7Explorer.Parsers;
namespace S7Explorer.ViewModels
{
public class MainViewModel : ObservableObject
{
private string _searchText;
private object _selectedObject;
private object _selectedTreeItem;
private S7Project _currentProject;
private ObservableCollection<S7Object> _projectStructure;
private string _projectInfo;
private bool _isLoading;
public string SearchText
{
get => _searchText;
set => SetProperty(ref _searchText, value);
}
public object SelectedObject
{
get => _selectedObject;
set => SetProperty(ref _selectedObject, value);
}
public object SelectedTreeItem
{
get => _selectedTreeItem;
set
{
if (SetProperty(ref _selectedTreeItem, value))
{
// Actualizar el objeto seleccionado para PropertyGrid
SelectedObject = _selectedTreeItem;
// Acciones específicas según el tipo de objeto seleccionado
if (_selectedTreeItem is S7Function fc)
{
// Si el objeto seleccionado es una función, actualizar su interfaz
UpdateFunctionInterface(fc);
}
}
}
}
/// <summary>
/// Actualiza la información de interfaz de una función seleccionada
/// </summary>
private void UpdateFunctionInterface(S7Function fc)
{
try
{
// Aquí podríamos cargar información adicional específica de la función
// Por ejemplo, cargar el código de la función, detalles de parámetros, etc.
// Actualizar estadísticas o análisis de la función
// Por ejemplo, mostrar uso de la función en otros bloques
// Este método se ejecutará cuando el usuario seleccione una FC en el árbol
}
catch (Exception)
{
// Ignorar errores para no interrumpir la experiencia del usuario
}
}
public ObservableCollection<S7Object> ProjectStructure
{
get => _projectStructure;
set => SetProperty(ref _projectStructure, value);
}
public string ProjectInfo
{
get => _projectInfo;
set => SetProperty(ref _projectInfo, value);
}
public bool IsLoading
{
get => _isLoading;
set => SetProperty(ref _isLoading, value);
}
public IRelayCommand OpenProjectCommand { get; }
public IRelayCommand SearchCommand { get; }
public MainViewModel()
{
ProjectStructure = new ObservableCollection<S7Object>();
OpenProjectCommand = new RelayCommand(OpenProject);
SearchCommand = new RelayCommand(SearchInProject);
ProjectInfo = "No hay proyecto abierto";
}
private void OpenProject()
{
var dialog = new VistaOpenFileDialog
{
Title = "Seleccionar archivo de proyecto STEP7",
Filter = "Proyectos STEP7 (*.s7p)|*.s7p|Todos los archivos (*.*)|*.*",
CheckFileExists = true
};
if (dialog.ShowDialog() == true)
{
LoadProjectAsync(dialog.FileName);
}
}
private async void LoadProjectAsync(string filePath)
{
try
{
IsLoading = true;
ProjectInfo = "Cargando proyecto...";
// Reiniciar estado
ProjectStructure.Clear();
_currentProject = null;
// Parsear proyecto
var parser = new S7ProjectParser(filePath);
_currentProject = await parser.ParseProjectAsync();
// Actualizar UI
ProjectStructure.Add(_currentProject);
_currentProject.IsExpanded = true;
// Actualizar info
ProjectInfo = $"Proyecto: {Path.GetFileNameWithoutExtension(filePath)}";
}
catch (Exception ex)
{
MessageBox.Show($"Error al cargar el proyecto: {ex.Message}", "Error",
MessageBoxButton.OK, MessageBoxImage.Error);
ProjectInfo = "Error al cargar el proyecto";
}
finally
{
IsLoading = false;
}
}
private void SearchInProject()
{
if (_currentProject == null || string.IsNullOrWhiteSpace(SearchText))
return;
try
{
// Recopilar todos los objetos en el proyecto
var allObjects = GetAllObjects(_currentProject);
// Lista para almacenar coincidencias
var matchingObjects = new List<S7Object>();
// Buscar en función del texto de búsqueda
string searchText = SearchText.Trim().ToLowerInvariant();
// Buscar objetos que coincidan con el texto
foreach (var obj in allObjects)
{
// Comprobar si el texto de búsqueda parece ser una referencia a FC específica
if (searchText.StartsWith("fc") && searchText.Length >= 3)
{
// Si es una función específica (por ejemplo "fc5")
if (obj is S7Function func &&
func.Number.ToLowerInvariant() == searchText)
{
matchingObjects.Add(func);
}
}
// Comprobar si queremos encontrar todas las FCs
else if (searchText == "fc" || searchText == "función" || searchText == "funcion")
{
if (obj is S7Function)
{
matchingObjects.Add(obj);
}
}
// Búsqueda en parámetros de función
else if (obj is S7Function func)
{
if (func.ContainsText(searchText))
{
matchingObjects.Add(func);
}
else if (func.Parameters != null)
{
// Buscar en los parámetros de la función
foreach (var param in func.Parameters)
{
if (param.Name.ToLowerInvariant().Contains(searchText) ||
param.DataType.ToLowerInvariant().Contains(searchText) ||
(param.Description?.ToLowerInvariant().Contains(searchText) ?? false))
{
matchingObjects.Add(func);
break;
}
}
}
}
// Búsqueda general para otros objetos
else if (obj.ContainsText(searchText))
{
matchingObjects.Add(obj);
}
}
if (matchingObjects.Count == 0)
{
MessageBox.Show($"No se encontraron coincidencias para: {SearchText}",
"Búsqueda", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
// Seleccionar el primer objeto coincidente y expandir su ruta
var firstMatch = matchingObjects.First();
SelectAndExpandToObject(firstMatch);
// Informar al usuario
if (matchingObjects.Count > 1)
{
MessageBox.Show($"Se encontraron {matchingObjects.Count} coincidencias. " +
"Mostrando la primera coincidencia.",
"Búsqueda", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
catch (Exception ex)
{
MessageBox.Show($"Error durante la búsqueda: {ex.Message}",
"Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private IEnumerable<S7Object> GetAllObjects(S7Object root)
{
// Devolver el objeto raíz
yield return root;
// Recursivamente devolver todos los hijos
foreach (var child in root.Children)
{
foreach (var obj in GetAllObjects(child))
{
yield return obj;
}
}
}
private void SelectAndExpandToObject(S7Object obj)
{
// Expandir todos los nodos padres hasta llegar al objeto
var parent = obj.Parent;
while (parent != null)
{
parent.IsExpanded = true;
parent = parent.Parent;
}
// Seleccionar el objeto
SelectedTreeItem = obj;
}
}
}