From 4cd596602f6678c9782ffac48beca588b56b883e Mon Sep 17 00:00:00 2001 From: Robert Date: Mon, 21 Mar 2022 23:08:07 +0100 Subject: [PATCH] Data model picker - Implemented most of the picker --- .../Controls/DataModelPicker.axaml | 42 ++++- .../Controls/DataModelPicker.axaml.cs | 164 ++++++++++++++---- .../Shared/DataModelVisualizationViewModel.cs | 2 +- .../Artemis.UI.Shared/Styles/Artemis.axaml | 1 + .../Artemis.UI/ArtemisBootstrapper.cs | 3 + .../Screens/Workshop/WorkshopView.axaml | 3 +- 6 files changed, 177 insertions(+), 38 deletions(-) diff --git a/src/Avalonia/Artemis.UI.Shared/Controls/DataModelPicker.axaml b/src/Avalonia/Artemis.UI.Shared/Controls/DataModelPicker.axaml index 4fee1e71a..56783710c 100644 --- a/src/Avalonia/Artemis.UI.Shared/Controls/DataModelPicker.axaml +++ b/src/Avalonia/Artemis.UI.Shared/Controls/DataModelPicker.axaml @@ -1,6 +1,8 @@ + xmlns:controls="using:Artemis.UI.Shared.Controls" + xmlns:fluent="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" + xmlns:dataModel="clr-namespace:Artemis.UI.Shared.DataModelVisualization.Shared"> @@ -9,7 +11,43 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Avalonia/Artemis.UI.Shared/Controls/DataModelPicker.axaml.cs b/src/Avalonia/Artemis.UI.Shared/Controls/DataModelPicker.axaml.cs index 651d0d48c..b469d9058 100644 --- a/src/Avalonia/Artemis.UI.Shared/Controls/DataModelPicker.axaml.cs +++ b/src/Avalonia/Artemis.UI.Shared/Controls/DataModelPicker.axaml.cs @@ -9,9 +9,11 @@ using Artemis.UI.Shared.DataModelVisualization.Shared; using Artemis.UI.Shared.Events; using Artemis.UI.Shared.Services.Interfaces; using Avalonia; +using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Data; using Avalonia.Media; +using Avalonia.Threading; using ReactiveUI; namespace Artemis.UI.Shared.Controls; @@ -24,7 +26,7 @@ public class DataModelPicker : TemplatedControl /// Gets or sets data model path. /// public static readonly StyledProperty DataModelPathProperty = - AvaloniaProperty.Register(nameof(DataModelPath), defaultBindingMode: BindingMode.TwoWay, notifying: DataModelPathPropertyChanged); + AvaloniaProperty.Register(nameof(DataModelPath), defaultBindingMode: BindingMode.TwoWay); /// /// Gets or sets the placeholder to show when nothing is selected. @@ -42,7 +44,7 @@ public class DataModelPicker : TemplatedControl /// Gets or sets a boolean indicating whether the data model picker should show the full path of the selected value. /// public static readonly StyledProperty ShowFullPathProperty = - AvaloniaProperty.Register(nameof(ShowFullPath), notifying: ShowFullPathPropertyChanged); + AvaloniaProperty.Register(nameof(ShowFullPath)); /// /// Gets or sets the brush to use when drawing the button. @@ -54,23 +56,19 @@ public class DataModelPicker : TemplatedControl /// A list of extra modules to show data models of. /// public static readonly StyledProperty?> ModulesProperty = - AvaloniaProperty.Register?>(nameof(Modules), new ObservableCollection(), notifying: ModulesPropertyChanged); + AvaloniaProperty.Register?>(nameof(Modules), new ObservableCollection()); /// /// The data model view model to show, if not provided one will be retrieved by the control. /// public static readonly StyledProperty DataModelViewModelProperty = - AvaloniaProperty.Register(nameof(DataModelViewModel), notifying: DataModelViewModelPropertyChanged); + AvaloniaProperty.Register(nameof(DataModelViewModel)); /// /// A list of data model view models to show /// public static readonly StyledProperty?> ExtraDataModelViewModelsProperty = - AvaloniaProperty.Register?>( - nameof(ExtraDataModelViewModels), - new ObservableCollection(), - notifying: ExtraDataModelViewModelsPropertyChanged - ); + AvaloniaProperty.Register?>(nameof(ExtraDataModelViewModels), new ObservableCollection()); /// /// A list of types to filter the selectable paths on. @@ -78,6 +76,70 @@ public class DataModelPicker : TemplatedControl public static readonly StyledProperty?> FilterTypesProperty = AvaloniaProperty.Register?>(nameof(FilterTypes), new ObservableCollection()); + /// + /// Gets a boolean indicating whether the data model picker has a value. + /// + public static readonly StyledProperty HasValueProperty = + AvaloniaProperty.Register(nameof(HasValue)); + + private Button? _dataModelButton; + private bool _attached; + + static DataModelPicker() + { + DataModelPathProperty.Changed.Subscribe(DataModelPathChanged); + ShowFullPathProperty.Changed.Subscribe(ShowFullPathChanged); + ModulesProperty.Changed.Subscribe(ModulesChanged); + DataModelViewModelProperty.Changed.Subscribe(DataModelViewModelPropertyChanged); + ExtraDataModelViewModelsProperty.Changed.Subscribe(ExtraDataModelViewModelsChanged); + } + + private static void DataModelPathChanged(AvaloniaPropertyChangedEventArgs e) + { + if (e.Sender is not DataModelPicker dataModelPicker) + return; + + if (e.OldValue.Value != null) + { + e.OldValue.Value.PathInvalidated -= dataModelPicker.PathValidationChanged; + e.OldValue.Value.PathValidated -= dataModelPicker.PathValidationChanged; + e.OldValue.Value.Dispose(); + } + + if (!dataModelPicker._attached) + return; + + dataModelPicker.UpdateValueDisplay(); + if (e.NewValue.Value != null) + { + e.NewValue.Value.PathInvalidated += dataModelPicker.PathValidationChanged; + e.NewValue.Value.PathValidated += dataModelPicker.PathValidationChanged; + } + } + + private static void ShowFullPathChanged(AvaloniaPropertyChangedEventArgs e) + { + if (e.Sender is DataModelPicker dataModelPicker) + dataModelPicker.UpdateValueDisplay(); + } + + private static void ModulesChanged(AvaloniaPropertyChangedEventArgs?> e) + { + if (e.Sender is DataModelPicker dataModelPicker) + dataModelPicker.GetDataModel(); + } + + private static void DataModelViewModelPropertyChanged(AvaloniaPropertyChangedEventArgs e) + { + if (e.Sender is DataModelPicker && e.OldValue.Value != null) + e.OldValue.Value.Dispose(); + } + + private static void ExtraDataModelViewModelsChanged(AvaloniaPropertyChangedEventArgs?> e) + { + // TODO, the original did nothing here either and I can't remember why + } + /// /// Creates a new instance of the class. /// @@ -91,7 +153,10 @@ public class DataModelPicker : TemplatedControl /// public ReactiveCommand SelectPropertyCommand { get; } - internal static IDataModelUIService DataModelUIService + /// + /// Internal, don't use. + /// + public static IDataModelUIService DataModelUIService { set { @@ -182,6 +247,15 @@ public class DataModelPicker : TemplatedControl set => SetValue(FilterTypesProperty, value); } + /// + /// Gets a boolean indicating whether the data model picker has a value. + /// + public bool HasValue + { + get => GetValue(HasValueProperty); + private set => SetValue(HasValueProperty, value); + } + /// /// Occurs when a new path has been selected /// @@ -228,18 +302,45 @@ public class DataModelPicker : TemplatedControl DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested; } + #region Overrides of TemplatedControl + + /// + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + _dataModelButton = e.NameScope.Find