using System; using System.Collections.Generic; using System.Linq; using Avalonia; using Avalonia.PropertyGrid.Services; using JetBrains.Annotations; using PropertyModels.ComponentModel; using StabilityMatrix.Core.Extensions; namespace StabilityMatrix.Avalonia.Controls; /// [PublicAPI] public class BetterPropertyGrid : global::Avalonia.PropertyGrid.Controls.PropertyGrid { protected override Type StyleKeyOverride => typeof(global::Avalonia.PropertyGrid.Controls.PropertyGrid); public static readonly StyledProperty> ExcludedCategoriesProperty = AvaloniaProperty.Register< BetterPropertyGrid, IEnumerable >("ExcludedCategories"); public IEnumerable ExcludedCategories { get => GetValue(ExcludedCategoriesProperty); set => SetValue(ExcludedCategoriesProperty, value); } public static readonly StyledProperty> IncludedCategoriesProperty = AvaloniaProperty.Register< BetterPropertyGrid, IEnumerable >("IncludedCategories"); public IEnumerable IncludedCategories { get => GetValue(IncludedCategoriesProperty); set => SetValue(IncludedCategoriesProperty, value); } static BetterPropertyGrid() { // Register factories CellEditFactoryService.Default.AddFactory(new ToggleSwitchCellEditFactory()); // Initialize localization and name resolver LocalizationService.Default.AddExtraService(new PropertyGridLocalizationService()); ExcludedCategoriesProperty .Changed .AddClassHandler( (grid, args) => { if (args.NewValue is IEnumerable excludedCategories) { grid.FilterExcludeCategories(excludedCategories); } } ); IncludedCategoriesProperty .Changed .AddClassHandler( (grid, args) => { if (args.NewValue is IEnumerable includedCategories) { grid.FilterIncludeCategories(includedCategories); } } ); } public void FilterExcludeCategories(IEnumerable excludedCategories) { // Get internal property `ViewModel` of internal type `PropertyGridViewModel` var gridVm = this.GetProtectedProperty("ViewModel")!; // Get public property `CategoryFilter` var categoryFilter = gridVm.GetProtectedProperty("CategoryFilter")!; categoryFilter.BeginUpdate(); // Uncheck All, then check all except All categoryFilter.UnCheck(categoryFilter.All); foreach (var mask in categoryFilter.Masks.Where(m => m != categoryFilter.All)) { categoryFilter.Check(mask); } // Uncheck excluded categories foreach (var mask in excludedCategories) { categoryFilter.UnCheck(mask); } categoryFilter.EndUpdate(); } public void FilterIncludeCategories(IEnumerable includeCategories) { // Get internal property `ViewModel` of internal type `PropertyGridViewModel` var gridVm = this.GetProtectedProperty("ViewModel")!; // Get public property `CategoryFilter` var categoryFilter = gridVm.GetProtectedProperty("CategoryFilter")!; categoryFilter.BeginUpdate(); // Uncheck non-included categories foreach (var mask in categoryFilter.Masks.Where(m => !includeCategories.Contains(m))) { categoryFilter.UnCheck(mask); } categoryFilter.UnCheck(categoryFilter.All); // Check included categories foreach (var mask in includeCategories) { categoryFilter.Check(mask); } categoryFilter.EndUpdate(); } }