using System.Collections.ObjectModel; using System.ComponentModel; // Add this for PropertyChangedEventHandler and PropertyChangedEventArgs using System.Reflection; using System.Text.Json.Serialization; using System.Windows; using System.Windows.Controls; using CommunityToolkit.Mvvm.ComponentModel; using CtrEditor.ObjetosSim; namespace CtrEditor.Controls { public class FilterChangedEventArgs : EventArgs { public osVisFilterViewModel FilterViewModel { get; private set; } public FilterChangedEventArgs(osVisFilterViewModel viewModel) { FilterViewModel = viewModel; } } /// /// Interaction logic for osVisFilter.xaml /// public partial class osVisFilter : UserControl { public osVisFilter() { InitializeComponent(); DataContext = FilterViewModel = new osVisFilterViewModel { Parent = this }; // Set the Parent property } public osVisFilterViewModel FilterViewModel { get; private set; } public event EventHandler FilterChanged; public virtual void OnFilterChanged() // Changed from protected to public { FilterChanged?.Invoke(this, new FilterChangedEventArgs(FilterViewModel)); } /// /// Updates the type filters based on the provided types /// public void UpdateAvailableTypes(IEnumerable types) { FilterViewModel.UpdateTypeFilters(types); } /// /// Updates the tag filters based on the provided objects /// public void UpdateAvailableTags(IEnumerable objects) { FilterViewModel.UpdateTagFilters(objects); } } /// /// ViewModel for the osVisFilter control /// public partial class osVisFilterViewModel : ObservableObject { [ObservableProperty] private bool showAll = true; [ObservableProperty] private bool showCloned; [ObservableProperty] private bool showAutoCreated; [ObservableProperty] private bool showEnableOnAllPages; [ObservableProperty] private bool showOnThisPage; [ObservableProperty] private ObservableCollection typeFilters = new ObservableCollection(); [ObservableProperty] private ObservableCollection tagFilters = new ObservableCollection(); [ObservableProperty] private string searchTags = ""; partial void OnShowAllChanged(bool value) { NotifyFilterChanged(); } partial void OnShowClonedChanged(bool value) { NotifyFilterChanged(); } partial void OnShowAutoCreatedChanged(bool value) { NotifyFilterChanged(); } partial void OnShowEnableOnAllPagesChanged(bool value) { NotifyFilterChanged(); } partial void OnShowOnThisPageChanged(bool value) { NotifyFilterChanged(); } partial void OnTypeFiltersChanged(ObservableCollection value) { if (value != null) { foreach (var filter in value) { filter.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(TypeFilterItem.IsSelected)) { NotifyFilterChanged(); } }; } } } partial void OnTagFiltersChanged(ObservableCollection value) { if (value != null) { foreach (var filter in value) { filter.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(TagFilterItem.IsSelected)) { NotifyFilterChanged(); } }; } } } partial void OnSearchTagsChanged(string value) { NotifyFilterChanged(); } private void NotifyFilterChanged() { if (this.Parent is osVisFilter filter) { filter.OnFilterChanged(); } } [JsonIgnore] public osVisFilter Parent { get; set; } public osVisFilterViewModel() { // PropertyChanged listeners could be added here if needed if (this.Parent is osVisFilter filter) { filter.OnFilterChanged(); } } /// /// Updates the type filters based on the provided types /// public void UpdateTypeFilters(IEnumerable types) { // Remove types that are no longer present var typesToRemove = TypeFilters .Where(tf => !types.Contains(tf.Type)) .ToList(); foreach (var item in typesToRemove) { UnsubscribeFromTypeFilter(item); TypeFilters.Remove(item); } // Add new types that aren't already in the list foreach (var type in types) { if (!TypeFilters.Any(tf => tf.Type == type)) { var newFilter = new TypeFilterItem(type) { DisplayName = GetTypeDisplayName(type), IsSelected = true }; SubscribeToTypeFilter(newFilter); TypeFilters.Add(newFilter); } } } /// /// Updates the tag filters based on the provided objects /// public void UpdateTagFilters(IEnumerable objects) { // Get all unique tags from all objects var allTags = objects .SelectMany(obj => obj.ListaEtiquetas) .Distinct() .OrderBy(tag => tag) .ToList(); // Remove tags that are no longer present var tagsToRemove = TagFilters .Where(tf => !allTags.Contains(tf.TagName)) .ToList(); foreach (var item in tagsToRemove) { UnsubscribeFromTagFilter(item); TagFilters.Remove(item); } // Add new tags that aren't already in the list foreach (var tag in allTags) { if (!TagFilters.Any(tf => tf.TagName == tag)) { var newFilter = new TagFilterItem(tag) { IsSelected = true }; SubscribeToTagFilter(newFilter); TagFilters.Add(newFilter); } } } private void SubscribeToTypeFilter(TypeFilterItem filter) { filter.PropertyChanged += TypeFilter_PropertyChanged; } private void UnsubscribeFromTypeFilter(TypeFilterItem filter) { filter.PropertyChanged -= TypeFilter_PropertyChanged; } private void SubscribeToTagFilter(TagFilterItem filter) { filter.PropertyChanged += TagFilter_PropertyChanged; } private void UnsubscribeFromTagFilter(TagFilterItem filter) { filter.PropertyChanged -= TagFilter_PropertyChanged; } private void TypeFilter_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(TypeFilterItem.IsSelected)) { NotifyFilterChanged(); } } private void TagFilter_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(TagFilterItem.IsSelected)) { NotifyFilterChanged(); } } /// /// Gets the display name for a type, using the NombreClase static method if available /// private string GetTypeDisplayName(Type type) { var methodInfo = type.GetMethod("NombreClase", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); return methodInfo != null ? methodInfo.Invoke(null, null)?.ToString() : type.Name; } } /// /// Represents a type filter item with selection state /// public partial class TypeFilterItem : ObservableObject { [ObservableProperty] private bool isSelected = true; [ObservableProperty] private string displayName; public Type Type { get; } public TypeFilterItem(Type type) { Type = type; DisplayName = type?.Name ?? "Unknown Type"; } partial void OnIsSelectedChanged(bool value) { OnPropertyChanged(nameof(IsSelected)); } } /// /// Represents a tag filter item with selection state /// public partial class TagFilterItem : ObservableObject { [ObservableProperty] private bool isSelected; public string TagName { get; } public string DisplayName => "#" + TagName; public TagFilterItem(string tagName) { TagName = tagName; } partial void OnIsSelectedChanged(bool value) { // Could add logic here if needed when selection changes } } }