mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Data model picker - Implemented most of the picker
This commit is contained in:
parent
81ca8c1425
commit
4cd596602f
@ -1,6 +1,8 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Artemis.UI.Shared.Controls">
|
||||
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">
|
||||
<Design.PreviewWith>
|
||||
<controls:DataModelPicker />
|
||||
</Design.PreviewWith>
|
||||
@ -9,7 +11,43 @@
|
||||
<!-- Set Defaults -->
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<TextBlock Text="Templated Control" />
|
||||
<fluent:DropDownButton Name="DataModelButton">
|
||||
<fluent:DropDownButton.DataTemplates>
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelPropertiesViewModel}" ItemsSource="{Binding Children}">
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding DisplayValue}"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</TreeDataTemplate>
|
||||
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||
<ContentControl Grid.Column="1" Content="{Binding DisplayViewModel}" FontFamily="Consolas" />
|
||||
</Grid>
|
||||
</TreeDataTemplate>
|
||||
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelListViewModel}">
|
||||
<Grid ColumnDefinitions="Auto,*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding CountDisplay, Mode=OneWay}"
|
||||
FontFamily="Consolas"
|
||||
HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</TreeDataTemplate>
|
||||
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelEventViewModel}" ItemsSource="{Binding Children}">
|
||||
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||
</TreeDataTemplate>
|
||||
</fluent:DropDownButton.DataTemplates>
|
||||
<fluent:DropDownButton.Flyout>
|
||||
<MenuFlyout Items="{Binding DataModelViewModel.Children, RelativeSource={RelativeSource TemplatedParent}}"/>
|
||||
</fluent:DropDownButton.Flyout>
|
||||
</fluent:DropDownButton>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
@ -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.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<DataModelPath?> DataModelPathProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, DataModelPath?>(nameof(DataModelPath), defaultBindingMode: BindingMode.TwoWay, notifying: DataModelPathPropertyChanged);
|
||||
AvaloniaProperty.Register<DataModelPicker, DataModelPath?>(nameof(DataModelPath), defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<bool> ShowFullPathProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowFullPath), notifying: ShowFullPathPropertyChanged);
|
||||
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowFullPath));
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<ObservableCollection<Module>?> ModulesProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Module>?>(nameof(Modules), new ObservableCollection<Module>(), notifying: ModulesPropertyChanged);
|
||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Module>?>(nameof(Modules), new ObservableCollection<Module>());
|
||||
|
||||
/// <summary>
|
||||
/// The data model view model to show, if not provided one will be retrieved by the control.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<DataModelPropertiesViewModel?> DataModelViewModelProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, DataModelPropertiesViewModel?>(nameof(DataModelViewModel), notifying: DataModelViewModelPropertyChanged);
|
||||
AvaloniaProperty.Register<DataModelPicker, DataModelPropertiesViewModel?>(nameof(DataModelViewModel));
|
||||
|
||||
/// <summary>
|
||||
/// A list of data model view models to show
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<ObservableCollection<DataModelPropertiesViewModel>?> ExtraDataModelViewModelsProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<DataModelPropertiesViewModel>?>(
|
||||
nameof(ExtraDataModelViewModels),
|
||||
new ObservableCollection<DataModelPropertiesViewModel>(),
|
||||
notifying: ExtraDataModelViewModelsPropertyChanged
|
||||
);
|
||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<DataModelPropertiesViewModel>?>(nameof(ExtraDataModelViewModels), new ObservableCollection<DataModelPropertiesViewModel>());
|
||||
|
||||
/// <summary>
|
||||
/// A list of types to filter the selectable paths on.
|
||||
@ -78,6 +76,70 @@ public class DataModelPicker : TemplatedControl
|
||||
public static readonly StyledProperty<ObservableCollection<Type>?> FilterTypesProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Type>?>(nameof(FilterTypes), new ObservableCollection<Type>());
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the data model picker has a value.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<bool> HasValueProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, bool>(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<DataModelPath?> 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<bool> e)
|
||||
{
|
||||
if (e.Sender is DataModelPicker dataModelPicker)
|
||||
dataModelPicker.UpdateValueDisplay();
|
||||
}
|
||||
|
||||
private static void ModulesChanged(AvaloniaPropertyChangedEventArgs<ObservableCollection<Module>?> e)
|
||||
{
|
||||
if (e.Sender is DataModelPicker dataModelPicker)
|
||||
dataModelPicker.GetDataModel();
|
||||
}
|
||||
|
||||
private static void DataModelViewModelPropertyChanged(AvaloniaPropertyChangedEventArgs<DataModelPropertiesViewModel?> e)
|
||||
{
|
||||
if (e.Sender is DataModelPicker && e.OldValue.Value != null)
|
||||
e.OldValue.Value.Dispose();
|
||||
}
|
||||
|
||||
private static void ExtraDataModelViewModelsChanged(AvaloniaPropertyChangedEventArgs<ObservableCollection<DataModelPropertiesViewModel>?> e)
|
||||
{
|
||||
// TODO, the original did nothing here either and I can't remember why
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelPicker" /> class.
|
||||
/// </summary>
|
||||
@ -91,7 +153,10 @@ public class DataModelPicker : TemplatedControl
|
||||
/// </summary>
|
||||
public ReactiveCommand<DataModelVisualizationViewModel, Unit> SelectPropertyCommand { get; }
|
||||
|
||||
internal static IDataModelUIService DataModelUIService
|
||||
/// <summary>
|
||||
/// Internal, don't use.
|
||||
/// </summary>
|
||||
public static IDataModelUIService DataModelUIService
|
||||
{
|
||||
set
|
||||
{
|
||||
@ -182,6 +247,15 @@ public class DataModelPicker : TemplatedControl
|
||||
set => SetValue(FilterTypesProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the data model picker has a value.
|
||||
/// </summary>
|
||||
public bool HasValue
|
||||
{
|
||||
get => GetValue(HasValueProperty);
|
||||
private set => SetValue(HasValueProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a new path has been selected
|
||||
/// </summary>
|
||||
@ -228,18 +302,45 @@ public class DataModelPicker : TemplatedControl
|
||||
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
|
||||
}
|
||||
|
||||
#region Overrides of TemplatedControl
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_dataModelButton = e.NameScope.Find<Button>("DataModelButton");
|
||||
|
||||
GetDataModel();
|
||||
UpdateValueDisplay();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides of Visual
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
_attached = true;
|
||||
if (DataModelPath != null)
|
||||
{
|
||||
DataModelPath.PathInvalidated += PathValidationChanged;
|
||||
DataModelPath.PathValidated += PathValidationChanged;
|
||||
}
|
||||
|
||||
base.OnAttachedToVisualTree(e);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (DataModelPath != null)
|
||||
{
|
||||
DataModelPath.PathInvalidated -= PathValidationChanged;
|
||||
DataModelPath.PathValidated -= PathValidationChanged;
|
||||
}
|
||||
|
||||
DataModelViewModel?.Dispose();
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
}
|
||||
|
||||
@ -247,18 +348,28 @@ public class DataModelPicker : TemplatedControl
|
||||
|
||||
private void UpdateValueDisplay()
|
||||
{
|
||||
ValueDisplay.Visibility = DataModelPath == null || DataModelPath.IsValid ? Visibility.Visible : Visibility.Collapsed;
|
||||
ValuePlaceholder.Visibility = DataModelPath == null || DataModelPath.IsValid ? Visibility.Collapsed : Visibility.Visible;
|
||||
HasValue = DataModelPath != null && DataModelPath.IsValid;
|
||||
|
||||
string? formattedPath = null;
|
||||
if (DataModelPath != null && DataModelPath.IsValid)
|
||||
formattedPath = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
||||
|
||||
DataModelButton.ToolTip = formattedPath;
|
||||
ValueDisplayTextBlock.Text = ShowFullPath
|
||||
if (_dataModelButton != null)
|
||||
{
|
||||
if (!HasValue)
|
||||
{
|
||||
ToolTip.SetTip(_dataModelButton, null);
|
||||
_dataModelButton.Content = Placeholder;
|
||||
}
|
||||
else
|
||||
{
|
||||
ToolTip.SetTip(_dataModelButton, formattedPath);
|
||||
_dataModelButton.Content = ShowFullPath
|
||||
? formattedPath
|
||||
: DataModelPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DataModelOnUpdateRequested(object? sender, EventArgs e)
|
||||
{
|
||||
@ -268,23 +379,8 @@ public class DataModelPicker : TemplatedControl
|
||||
extraDataModelViewModel.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
||||
}
|
||||
|
||||
private static void DataModelPathPropertyChanged(IAvaloniaObject sender, bool before)
|
||||
{
|
||||
}
|
||||
|
||||
private static void ShowFullPathPropertyChanged(IAvaloniaObject sender, bool before)
|
||||
{
|
||||
}
|
||||
|
||||
private static void ModulesPropertyChanged(IAvaloniaObject sender, bool before)
|
||||
{
|
||||
}
|
||||
|
||||
private static void DataModelViewModelPropertyChanged(IAvaloniaObject sender, bool before)
|
||||
{
|
||||
}
|
||||
|
||||
private static void ExtraDataModelViewModelsPropertyChanged(IAvaloniaObject sender, bool before)
|
||||
private void PathValidationChanged(object? sender, EventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(UpdateValueDisplay, DispatcherPriority.DataBind);
|
||||
}
|
||||
}
|
||||
@ -21,7 +21,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
private ObservableCollection<DataModelVisualizationViewModel> _children;
|
||||
private DataModel? _dataModel;
|
||||
private bool _isMatchingFilteredTypes;
|
||||
private bool _isVisualizationExpanded;
|
||||
private bool _isVisualizationExpanded = true;
|
||||
private DataModelVisualizationViewModel? _parent;
|
||||
private DataModelPropertyAttribute? _propertyDescription;
|
||||
private bool _populatedStaticChildren;
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
<!-- Custom controls -->
|
||||
<StyleInclude Source="/Styles/Controls/GradientPicker.axaml" />
|
||||
<StyleInclude Source="/Styles/Controls/GradientPickerButton.axaml" />
|
||||
<StyleInclude Source="/Controls/DataModelPicker.axaml" />
|
||||
|
||||
<!-- Custom styles -->
|
||||
<StyleInclude Source="/Styles/Border.axaml" />
|
||||
|
||||
@ -5,6 +5,7 @@ using Artemis.Core;
|
||||
using Artemis.UI.Exceptions;
|
||||
using Artemis.UI.Ninject;
|
||||
using Artemis.UI.Screens.Root;
|
||||
using Artemis.UI.Shared.Controls;
|
||||
using Artemis.UI.Shared.Ninject;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
using Artemis.VisualScripting.Ninject;
|
||||
@ -42,6 +43,8 @@ namespace Artemis.UI
|
||||
|
||||
_kernel.UseNinjectDependencyResolver();
|
||||
|
||||
DataModelPicker.DataModelUIService = _kernel.Get<IDataModelUIService>();
|
||||
|
||||
return _kernel;
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,8 @@
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="5">
|
||||
<TextBlock Classes="h4">Nodes tests</TextBlock>
|
||||
<ContentControl Content="{CompiledBinding VisualEditorViewModel}" HorizontalAlignment="Stretch" Height="800"></ContentControl>
|
||||
<controls:DataModelPicker ></controls:DataModelPicker>
|
||||
<!-- <ContentControl Content="{CompiledBinding VisualEditorViewModel}" HorizontalAlignment="Stretch" Height="800"></ContentControl> -->
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Classes="card">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user