280 lines
9.7 KiB
C#
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;
|
|
}
|
|
}
|
|
} |