mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Data model picker - Implemented selecting
This commit is contained in:
parent
75a0be0c98
commit
30ec28a9a9
@ -9,9 +9,13 @@ using Artemis.UI.Shared.DataModelVisualization.Shared;
|
|||||||
using Artemis.UI.Shared.Events;
|
using Artemis.UI.Shared.Events;
|
||||||
using Artemis.UI.Shared.Services.Interfaces;
|
using Artemis.UI.Shared.Services.Interfaces;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
|
using Material.Icons;
|
||||||
|
using Material.Icons.Avalonia;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.DataModelPicker;
|
namespace Artemis.UI.Shared.Controls.DataModelPicker;
|
||||||
|
|
||||||
@ -61,9 +65,15 @@ public class DataModelPicker : TemplatedControl
|
|||||||
public static readonly StyledProperty<ObservableCollection<Type>?> FilterTypesProperty =
|
public static readonly StyledProperty<ObservableCollection<Type>?> FilterTypesProperty =
|
||||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Type>?>(nameof(FilterTypes), new ObservableCollection<Type>());
|
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Type>?>(nameof(FilterTypes), new ObservableCollection<Type>());
|
||||||
|
|
||||||
|
private MaterialIcon? _currentPathIcon;
|
||||||
|
private TextBlock? _currentPathDisplay;
|
||||||
|
private TextBlock? _currentPathDescription;
|
||||||
|
private TreeView? _dataModelTreeView;
|
||||||
|
|
||||||
static DataModelPicker()
|
static DataModelPicker()
|
||||||
{
|
{
|
||||||
ModulesProperty.Changed.Subscribe(ModulesChanged);
|
ModulesProperty.Changed.Subscribe(ModulesChanged);
|
||||||
|
DataModelPathProperty.Changed.Subscribe(DataModelPathPropertyChanged);
|
||||||
DataModelViewModelProperty.Changed.Subscribe(DataModelViewModelPropertyChanged);
|
DataModelViewModelProperty.Changed.Subscribe(DataModelViewModelPropertyChanged);
|
||||||
ExtraDataModelViewModelsProperty.Changed.Subscribe(ExtraDataModelViewModelsChanged);
|
ExtraDataModelViewModelsProperty.Changed.Subscribe(ExtraDataModelViewModelsChanged);
|
||||||
}
|
}
|
||||||
@ -114,7 +124,7 @@ public class DataModelPicker : TemplatedControl
|
|||||||
public DataModelPropertiesViewModel? DataModelViewModel
|
public DataModelPropertiesViewModel? DataModelViewModel
|
||||||
{
|
{
|
||||||
get => GetValue(DataModelViewModelProperty);
|
get => GetValue(DataModelViewModelProperty);
|
||||||
set => SetValue(DataModelViewModelProperty, value);
|
private set => SetValue(DataModelViewModelProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -154,9 +164,35 @@ public class DataModelPicker : TemplatedControl
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
{
|
{
|
||||||
GetDataModel();
|
if (_dataModelTreeView != null)
|
||||||
|
_dataModelTreeView.SelectionChanged -= DataModelTreeViewOnSelectionChanged;
|
||||||
|
|
||||||
|
_currentPathIcon = e.NameScope.Find<MaterialIcon>("CurrentPathIcon");
|
||||||
|
_currentPathDisplay = e.NameScope.Find<TextBlock>("CurrentPathDisplay");
|
||||||
|
_currentPathDescription = e.NameScope.Find<TextBlock>("CurrentPathDescription");
|
||||||
|
_dataModelTreeView = e.NameScope.Find<TreeView>("DataModelTreeView");
|
||||||
|
|
||||||
|
if (_dataModelTreeView != null)
|
||||||
|
_dataModelTreeView.SelectionChanged += DataModelTreeViewOnSelectionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Overrides of Visual
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
|
{
|
||||||
|
GetDataModel();
|
||||||
|
UpdateCurrentPath(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
|
{
|
||||||
|
DataModelViewModel?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private static void ModulesChanged(AvaloniaPropertyChangedEventArgs<ObservableCollection<Module>?> e)
|
private static void ModulesChanged(AvaloniaPropertyChangedEventArgs<ObservableCollection<Module>?> e)
|
||||||
@ -165,6 +201,12 @@ public class DataModelPicker : TemplatedControl
|
|||||||
dataModelPicker.GetDataModel();
|
dataModelPicker.GetDataModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void DataModelPathPropertyChanged(AvaloniaPropertyChangedEventArgs<DataModelPath?> e)
|
||||||
|
{
|
||||||
|
if (e.Sender is DataModelPicker dataModelPicker)
|
||||||
|
dataModelPicker.UpdateCurrentPath(false);
|
||||||
|
}
|
||||||
|
|
||||||
private static void DataModelViewModelPropertyChanged(AvaloniaPropertyChangedEventArgs<DataModelPropertiesViewModel?> e)
|
private static void DataModelViewModelPropertyChanged(AvaloniaPropertyChangedEventArgs<DataModelPropertiesViewModel?> e)
|
||||||
{
|
{
|
||||||
if (e.Sender is DataModelPicker && e.OldValue.Value != null)
|
if (e.Sender is DataModelPicker && e.OldValue.Value != null)
|
||||||
@ -215,4 +257,59 @@ public class DataModelPicker : TemplatedControl
|
|||||||
foreach (DataModelPropertiesViewModel extraDataModelViewModel in ExtraDataModelViewModels)
|
foreach (DataModelPropertiesViewModel extraDataModelViewModel in ExtraDataModelViewModels)
|
||||||
extraDataModelViewModel.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
extraDataModelViewModel.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DataModelTreeViewOnSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
// Multi-select isn't a think so grab the first one
|
||||||
|
object? selected = _dataModelTreeView?.SelectedItems[0];
|
||||||
|
if (selected == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (selected is DataModelPropertyViewModel property && property.DataModelPath != null)
|
||||||
|
DataModelPath = new DataModelPath(property.DataModelPath);
|
||||||
|
if (selected is DataModelListViewModel list && list.DataModelPath != null)
|
||||||
|
DataModelPath = new DataModelPath(list.DataModelPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCurrentPath(bool selectCurrentPath)
|
||||||
|
{
|
||||||
|
if (DataModelPath == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_dataModelTreeView != null && selectCurrentPath)
|
||||||
|
{
|
||||||
|
// Expand the path
|
||||||
|
DataModel? start = DataModelPath.Target;
|
||||||
|
DataModelVisualizationViewModel? root = DataModelViewModel?.Children.FirstOrDefault(c => c.DataModel == start);
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
root.ExpandToPath(DataModelPath);
|
||||||
|
_dataModelTreeView.SelectedItem = root.GetViewModelForPath(DataModelPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentPathDisplay != null)
|
||||||
|
_currentPathDisplay.Text = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
||||||
|
if (_currentPathDescription != null)
|
||||||
|
_currentPathDescription.Text = DataModelPath.GetPropertyDescription()?.Description;
|
||||||
|
|
||||||
|
if (_currentPathIcon != null)
|
||||||
|
{
|
||||||
|
Type? type = DataModelPath.GetPropertyType();
|
||||||
|
if (type == null)
|
||||||
|
_currentPathIcon.Kind = MaterialIconKind.QuestionMarkCircle;
|
||||||
|
else if (type.TypeIsNumber())
|
||||||
|
_currentPathIcon.Kind = MaterialIconKind.CalculatorVariantOutline;
|
||||||
|
else if (type.IsEnum)
|
||||||
|
_currentPathIcon.Kind = MaterialIconKind.FormatListBulletedSquare;
|
||||||
|
else if (type == typeof(bool))
|
||||||
|
_currentPathIcon.Kind = MaterialIconKind.CircleHalfFull;
|
||||||
|
else if (type == typeof(string))
|
||||||
|
_currentPathIcon.Kind = MaterialIconKind.Text;
|
||||||
|
else if (type == typeof(SKColor))
|
||||||
|
_currentPathIcon.Kind = MaterialIconKind.Palette;
|
||||||
|
else
|
||||||
|
_currentPathIcon.Kind = MaterialIconKind.Matrix;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -62,12 +62,6 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
public static readonly StyledProperty<ObservableCollection<Module>?> ModulesProperty =
|
public static readonly StyledProperty<ObservableCollection<Module>?> ModulesProperty =
|
||||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Module>?>(nameof(Modules), new ObservableCollection<Module>());
|
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));
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of data model view models to show
|
/// A list of data model view models to show
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -84,7 +78,6 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
private bool _flyoutActive;
|
private bool _flyoutActive;
|
||||||
private Button? _button;
|
private Button? _button;
|
||||||
private DataModelPickerFlyout? _flyout;
|
private DataModelPickerFlyout? _flyout;
|
||||||
private IDisposable? _dataModelPathChanged;
|
|
||||||
|
|
||||||
static DataModelPickerButton()
|
static DataModelPickerButton()
|
||||||
{
|
{
|
||||||
@ -155,15 +148,6 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
set => SetValue(ModulesProperty, value);
|
set => SetValue(ModulesProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The data model view model to show, if not provided one will be retrieved by the control.
|
|
||||||
/// </summary>
|
|
||||||
public DataModelPropertiesViewModel? DataModelViewModel
|
|
||||||
{
|
|
||||||
get => GetValue(DataModelViewModelProperty);
|
|
||||||
set => SetValue(DataModelViewModelProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A list of data model view models to show.
|
/// A list of data model view models to show.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -219,14 +203,6 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
self.UpdateValueDisplay();
|
self.UpdateValueDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FlyoutDataModelPathChanged(AvaloniaPropertyChangedEventArgs<DataModelPath?> e)
|
|
||||||
{
|
|
||||||
if (!ReferenceEquals(e.Sender, _flyout?.DataModelPicker))
|
|
||||||
return;
|
|
||||||
|
|
||||||
DataModelPath = e.NewValue.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PathValidationChanged(object? sender, EventArgs e)
|
private void PathValidationChanged(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.InvokeAsync(UpdateValueDisplay, DispatcherPriority.DataBind);
|
Dispatcher.UIThread.InvokeAsync(UpdateValueDisplay, DispatcherPriority.DataBind);
|
||||||
@ -264,7 +240,6 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
|
|
||||||
// Logic here is taken from Fluent Avalonia's ColorPicker which also reuses the same control since it's large
|
// Logic here is taken from Fluent Avalonia's ColorPicker which also reuses the same control since it's large
|
||||||
_flyout.DataModelPicker.DataModelPath = DataModelPath;
|
_flyout.DataModelPicker.DataModelPath = DataModelPath;
|
||||||
_flyout.DataModelPicker.DataModelViewModel = DataModelViewModel;
|
|
||||||
_flyout.DataModelPicker.ExtraDataModelViewModels = ExtraDataModelViewModels;
|
_flyout.DataModelPicker.ExtraDataModelViewModels = ExtraDataModelViewModels;
|
||||||
_flyout.DataModelPicker.FilterTypes = FilterTypes;
|
_flyout.DataModelPicker.FilterTypes = FilterTypes;
|
||||||
_flyout.DataModelPicker.Modules = Modules;
|
_flyout.DataModelPicker.Modules = Modules;
|
||||||
@ -274,22 +249,9 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
_flyout.ShowAt(_button != null ? _button : this);
|
_flyout.ShowAt(_button != null ? _button : this);
|
||||||
_flyoutActive = true;
|
_flyoutActive = true;
|
||||||
|
|
||||||
_dataModelPathChanged = DataModelPicker.DataModelPathProperty.Changed.Subscribe(FlyoutDataModelPathChanged);
|
|
||||||
FlyoutOpened?.Invoke(this, EventArgs.Empty);
|
FlyoutOpened?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFlyoutClosed(object? sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (_flyoutActive)
|
|
||||||
{
|
|
||||||
FlyoutClosed?.Invoke(this, EventArgs.Empty);
|
|
||||||
_flyoutActive = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dataModelPathChanged?.Dispose();
|
|
||||||
_dataModelPathChanged = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Overrides of TemplatedControl
|
#region Overrides of TemplatedControl
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -314,15 +276,33 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
DataModelPath.PathValidated += PathValidationChanged;
|
DataModelPath.PathValidated += PathValidationChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_flyout == null)
|
_flyout ??= new DataModelPickerFlyout();
|
||||||
{
|
_flyout.Confirmed += FlyoutOnConfirmed;
|
||||||
_flyout = new DataModelPickerFlyout();
|
|
||||||
_flyout.FlyoutPresenterClasses.Add("data-model-picker-presenter");
|
|
||||||
}
|
|
||||||
|
|
||||||
_flyout.Closed += OnFlyoutClosed;
|
_flyout.Closed += OnFlyoutClosed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void FlyoutOnConfirmed(DataModelPickerFlyout sender, object args)
|
||||||
|
{
|
||||||
|
if (_flyoutActive)
|
||||||
|
{
|
||||||
|
FlyoutClosed?.Invoke(this, EventArgs.Empty);
|
||||||
|
_flyoutActive = false;
|
||||||
|
|
||||||
|
if (_flyout != null)
|
||||||
|
DataModelPath = _flyout.DataModelPicker.DataModelPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFlyoutClosed(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_flyoutActive)
|
||||||
|
{
|
||||||
|
FlyoutClosed?.Invoke(this, EventArgs.Empty);
|
||||||
|
_flyoutActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
@ -332,8 +312,6 @@ public class DataModelPickerButton : TemplatedControl
|
|||||||
DataModelPath.PathValidated -= PathValidationChanged;
|
DataModelPath.PathValidated -= PathValidationChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
DataModelViewModel?.Dispose();
|
|
||||||
|
|
||||||
if (_flyout != null)
|
if (_flyout != null)
|
||||||
_flyout.Closed -= OnFlyoutClosed;
|
_flyout.Closed -= OnFlyoutClosed;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,16 @@
|
|||||||
using Avalonia.Controls;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using FluentAvalonia.Core;
|
||||||
|
using FluentAvalonia.UI.Controls;
|
||||||
|
using FluentAvalonia.UI.Controls.Primitives;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Controls.Flyouts;
|
namespace Artemis.UI.Shared.Controls.Flyouts;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a flyout that hosts a data model picker.
|
/// Defines a flyout that hosts a data model picker.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class DataModelPickerFlyout : Flyout
|
public sealed class DataModelPickerFlyout : PickerFlyoutBase
|
||||||
{
|
{
|
||||||
private DataModelPicker.DataModelPicker? _picker;
|
private DataModelPicker.DataModelPicker? _picker;
|
||||||
|
|
||||||
@ -14,11 +19,49 @@ public sealed class DataModelPickerFlyout : Flyout
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DataModelPicker.DataModelPicker DataModelPicker => _picker ??= new DataModelPicker.DataModelPicker();
|
public DataModelPicker.DataModelPicker DataModelPicker => _picker ??= new DataModelPicker.DataModelPicker();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised when the Confirmed button is tapped indicating the new Color should be applied
|
||||||
|
/// </summary>
|
||||||
|
public event TypedEventHandler<DataModelPickerFlyout, object>? Confirmed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised when the Dismiss button is tapped, indicating the new color should not be applied
|
||||||
|
/// </summary>
|
||||||
|
public event TypedEventHandler<DataModelPickerFlyout, object>? Dismissed;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Control CreatePresenter()
|
protected override Control CreatePresenter()
|
||||||
{
|
{
|
||||||
_picker ??= new DataModelPicker.DataModelPicker();
|
_picker ??= new DataModelPicker.DataModelPicker();
|
||||||
FlyoutPresenter presenter = new() {Content = DataModelPicker};
|
PickerFlyoutPresenter presenter = new() {Content = DataModelPicker};
|
||||||
|
presenter.Confirmed += OnFlyoutConfirmed;
|
||||||
|
presenter.Dismissed += OnFlyoutDismissed;
|
||||||
|
|
||||||
return presenter;
|
return presenter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnConfirmed()
|
||||||
|
{
|
||||||
|
Confirmed?.Invoke(this, EventArgs.Empty);
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnOpening(CancelEventArgs args)
|
||||||
|
{
|
||||||
|
base.OnOpening(args);
|
||||||
|
(Popup.Child as PickerFlyoutPresenter)?.Classes.Set(":acceptdismiss", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFlyoutDismissed(PickerFlyoutPresenter sender, object args)
|
||||||
|
{
|
||||||
|
Dismissed?.Invoke(this, EventArgs.Empty);
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFlyoutConfirmed(PickerFlyoutPresenter sender, object args)
|
||||||
|
{
|
||||||
|
OnConfirmed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -9,8 +9,8 @@ using Artemis.Core.Modules;
|
|||||||
using Artemis.UI.Shared.Services.Interfaces;
|
using Artemis.UI.Shared.Services.Interfaces;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
namespace Artemis.UI.Shared.DataModelVisualization.Shared;
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a base class for a view model that visualizes a part of the data model
|
/// Represents a base class for a view model that visualizes a part of the data model
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -22,8 +22,8 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
|||||||
private bool _isMatchingFilteredTypes;
|
private bool _isMatchingFilteredTypes;
|
||||||
private bool _isVisualizationExpanded;
|
private bool _isVisualizationExpanded;
|
||||||
private DataModelVisualizationViewModel? _parent;
|
private DataModelVisualizationViewModel? _parent;
|
||||||
private DataModelPropertyAttribute? _propertyDescription;
|
|
||||||
private bool _populatedStaticChildren;
|
private bool _populatedStaticChildren;
|
||||||
|
private DataModelPropertyAttribute? _propertyDescription;
|
||||||
|
|
||||||
internal DataModelVisualizationViewModel(DataModel? dataModel, DataModelVisualizationViewModel? parent, DataModelPath? dataModelPath)
|
internal DataModelVisualizationViewModel(DataModel? dataModel, DataModelVisualizationViewModel? parent, DataModelPath? dataModelPath)
|
||||||
{
|
{
|
||||||
@ -194,6 +194,66 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
|||||||
IsMatchingFilteredTypes = filteredTypes.Any(t => t == type || t == typeof(Enum) && type.IsEnum);
|
IsMatchingFilteredTypes = filteredTypes.Any(t => t == type || t == typeof(Enum) && type.IsEnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when an update to the property this view model visualizes is requested
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler? UpdateRequested;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expands this view model and any children to expose the provided <paramref name="dataModelPath" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataModelPath">The data model path to expose.</param>
|
||||||
|
public void ExpandToPath(DataModelPath dataModelPath)
|
||||||
|
{
|
||||||
|
if (dataModelPath.Target != DataModel)
|
||||||
|
throw new ArtemisSharedUIException("Can't expand to a path that doesn't belong to this data model.");
|
||||||
|
|
||||||
|
IsVisualizationExpanded = true;
|
||||||
|
DataModelPathSegment current = dataModelPath.Segments.Skip(1).First();
|
||||||
|
Children.FirstOrDefault(c => c.Path == current.Path)?.ExpandToPath(current.Next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the view model that hosts the given path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataModelPath">The path to find</param>
|
||||||
|
/// <returns>The matching view model, may be null if the path doesn't exist or isn't expanded</returns>
|
||||||
|
public DataModelVisualizationViewModel? GetViewModelForPath(DataModelPath dataModelPath)
|
||||||
|
{
|
||||||
|
if (dataModelPath.Target != DataModel)
|
||||||
|
throw new ArtemisSharedUIException("Can't expand to a path that doesn't belong to this data model.");
|
||||||
|
|
||||||
|
if (DataModelPath?.Path == dataModelPath.Path)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
return Children.Select(c => c.GetViewModelForPath(dataModelPath)).FirstOrDefault(match => match != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="UpdateRequested" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnUpdateRequested()
|
||||||
|
{
|
||||||
|
UpdateRequested?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">
|
||||||
|
/// <see langword="true" /> to release both managed and unmanaged resources;
|
||||||
|
/// <see langword="false" /> to release only unmanaged resources.
|
||||||
|
/// </param>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
DataModelPath?.Dispose();
|
||||||
|
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
|
||||||
|
dataModelVisualizationViewModel.Dispose(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal virtual int GetChildDepth()
|
internal virtual int GetChildDepth()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -246,7 +306,6 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
|||||||
// Add missing dynamic children
|
// Add missing dynamic children
|
||||||
object? value = Parent == null || Parent.IsRootViewModel ? DataModel : DataModelPath?.GetValue();
|
object? value = Parent == null || Parent.IsRootViewModel ? DataModel : DataModelPath?.GetValue();
|
||||||
if (value is DataModel dataModel)
|
if (value is DataModel dataModel)
|
||||||
{
|
|
||||||
foreach (string key in dataModel.DynamicChildren.Keys.ToList())
|
foreach (string key in dataModel.DynamicChildren.Keys.ToList())
|
||||||
{
|
{
|
||||||
string childPath = AppendToPath(key);
|
string childPath = AppendToPath(key);
|
||||||
@ -257,7 +316,6 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
|||||||
if (child != null)
|
if (child != null)
|
||||||
Children.Add(child);
|
Children.Add(child);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Remove dynamic children that have been removed from the data model
|
// Remove dynamic children that have been removed from the data model
|
||||||
List<DataModelVisualizationViewModel> toRemoveDynamic = Children.Where(c => c.DataModelPath != null && !c.DataModelPath.IsValid).ToList();
|
List<DataModelVisualizationViewModel> toRemoveDynamic = Children.Where(c => c.DataModelPath != null && !c.DataModelPath.IsValid).ToList();
|
||||||
@ -325,40 +383,13 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
|||||||
OnUpdateRequested();
|
OnUpdateRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Events
|
private void ExpandToPath(DataModelPathSegment? segment)
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when an update to the property this view model visualizes is requested
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler? UpdateRequested;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the <see cref="UpdateRequested" /> event
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnUpdateRequested()
|
|
||||||
{
|
{
|
||||||
UpdateRequested?.Invoke(this, EventArgs.Empty);
|
if (segment == null)
|
||||||
}
|
return;
|
||||||
|
|
||||||
#endregion
|
IsVisualizationExpanded = true;
|
||||||
|
Children.FirstOrDefault(c => c.Path == segment.Path)?.ExpandToPath(segment.Next);
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">
|
|
||||||
/// <see langword="true" /> to release both managed and unmanaged resources;
|
|
||||||
/// <see langword="false" /> to release only unmanaged resources.
|
|
||||||
/// </param>
|
|
||||||
protected virtual void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
DataModelPath?.Dispose();
|
|
||||||
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
|
|
||||||
dataModelVisualizationViewModel.Dispose(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -367,7 +398,4 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
|||||||
Dispose(true);
|
Dispose(true);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -2,7 +2,8 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:dataModel="clr-namespace:Artemis.UI.Shared.DataModelVisualization.Shared"
|
xmlns:dataModel="clr-namespace:Artemis.UI.Shared.DataModelVisualization.Shared"
|
||||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker"
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia">
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<dataModelPicker:DataModelPicker />
|
<dataModelPicker:DataModelPicker />
|
||||||
</Design.PreviewWith>
|
</Design.PreviewWith>
|
||||||
@ -10,19 +11,34 @@
|
|||||||
<Style Selector="dataModelPicker|DataModelPicker">
|
<Style Selector="dataModelPicker|DataModelPicker">
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate>
|
<ControlTemplate>
|
||||||
<Grid RowDefinitions="Auto,Auto,*" Width="600" Height="400">
|
<Grid RowDefinitions="Auto,Auto,*" Width="600" Height="400" Margin="10">
|
||||||
<TextBox Grid.Row="0" Watermark="Search" Name="SearchBox"></TextBox>
|
<TextBox Grid.Row="0" Watermark="Search - not yet implemented 😱" Name="SearchBox" IsEnabled="False" />
|
||||||
|
|
||||||
<Border Grid.Row="1" Classes="card card-condensed" Margin="0 15">
|
<Border Grid.Row="1" Classes="card card-condensed" Margin="0 10">
|
||||||
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,*,*">
|
<Panel>
|
||||||
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" Classes="SubtitleTextBlockStyle">Current selection</TextBlock>
|
<Grid ColumnDefinitions="Auto,*"
|
||||||
<avalonia:MaterialIcon Kind="CalculatorVariantOutline" Grid.Column="0" Grid.Row="1" Grid.RowSpan="2" Height="22" Width="22" Margin="5 0 15 0"></avalonia:MaterialIcon>
|
RowDefinitions="*"
|
||||||
<TextBlock Grid.Row="1" Grid.Column="1" Classes="BodyStrongTextBlockStyle">Cursor Y-position</TextBlock>
|
MinHeight="38"
|
||||||
<TextBlock Grid.Row="2" Grid.Column="1" Classes="BodyTextBlockStyle" Foreground="{DynamicResource TextFillColorSecondary}">The current Y-position of the cursor in pixels</TextBlock>
|
IsVisible="{Binding DataModelPath, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||||
|
<avalonia:MaterialIcon Grid.Column="0" Grid.Row="0" Name="CurrentPathIcon" Kind="QuestionMarkCircle" Height="22" Width="22" Margin="5 0 15 0" />
|
||||||
|
<StackPanel Grid.Column="1" Grid.Row="0" VerticalAlignment="Center">
|
||||||
|
<TextBlock Name="CurrentPathDisplay" Classes="BodyStrongTextBlockStyle" MaxHeight="50" />
|
||||||
|
<TextBlock Name="CurrentPathDescription" Classes="BodyTextBlockStyle" Foreground="{DynamicResource TextFillColorSecondary}" MaxHeight="50" />
|
||||||
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid MinHeight="38"
|
||||||
|
IsVisible="{Binding DataModelPath, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static ObjectConverters.IsNull}}" ColumnDefinitions="*,Auto"
|
||||||
|
RowDefinitions="*,*">
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="0" Classes="BodyStrongTextBlockStyle">Welcome to the data model picker</TextBlock>
|
||||||
|
<TextBlock Grid.Column="0" Grid.Row="1" Foreground="{DynamicResource TextFillColorSecondary}">Select a value from the data model below</TextBlock>
|
||||||
|
<controls:HyperlinkButton Grid.Column="1" Grid.Row="0" Grid.RowSpan="2">Learn more</controls:HyperlinkButton>
|
||||||
|
</Grid>
|
||||||
|
</Panel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<TreeView Grid.Row="2" Items="{Binding DataModelViewModel.Children, RelativeSource={RelativeSource TemplatedParent}}">
|
<TreeView Grid.Row="2"
|
||||||
|
Name="DataModelTreeView"
|
||||||
|
Items="{Binding DataModelViewModel.Children, RelativeSource={RelativeSource TemplatedParent}}">
|
||||||
<TreeView.Styles>
|
<TreeView.Styles>
|
||||||
<Style Selector="TreeViewItem">
|
<Style Selector="TreeViewItem">
|
||||||
<Setter Property="IsExpanded" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
<Setter Property="IsExpanded" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
||||||
|
|||||||
@ -97,13 +97,13 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
NodeViewModel NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node);
|
NodeViewModel NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node);
|
||||||
CableViewModel CableViewModel(NodeScriptViewModel nodeScriptViewModel, IPin from, IPin to);
|
CableViewModel CableViewModel(NodeScriptViewModel nodeScriptViewModel, IPin from, IPin to);
|
||||||
DragCableViewModel DragCableViewModel(PinViewModel pinViewModel);
|
DragCableViewModel DragCableViewModel(PinViewModel pinViewModel);
|
||||||
|
InputPinViewModel InputPinViewModel(IPin inputPin);
|
||||||
|
OutputPinViewModel OutputPinViewModel(IPin outputPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface INodePinVmFactory
|
public interface INodePinVmFactory
|
||||||
{
|
{
|
||||||
PinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
PinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
||||||
PinViewModel InputPinViewModel(IPin inputPin);
|
|
||||||
PinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
PinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
||||||
PinViewModel OutputPinViewModel(IPin outputPin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10,24 +10,15 @@ public class NodePinViewModelInstanceProvider : StandardInstanceProvider
|
|||||||
{
|
{
|
||||||
protected override Type GetType(MethodInfo methodInfo, object[] arguments)
|
protected override Type GetType(MethodInfo methodInfo, object[] arguments)
|
||||||
{
|
{
|
||||||
if (methodInfo.ReturnType != typeof(PinCollectionViewModel) && methodInfo.ReturnType != typeof(PinViewModel))
|
if (methodInfo.ReturnType != typeof(PinCollectionViewModel))
|
||||||
return base.GetType(methodInfo, arguments);
|
return base.GetType(methodInfo, arguments);
|
||||||
|
|
||||||
if (arguments[0] is IPin pin)
|
|
||||||
return CreatePinViewModelType(pin);
|
|
||||||
if (arguments[0] is IPinCollection pinCollection)
|
if (arguments[0] is IPinCollection pinCollection)
|
||||||
return CreatePinCollectionViewModelType(pinCollection);
|
return CreatePinCollectionViewModelType(pinCollection);
|
||||||
|
|
||||||
return base.GetType(methodInfo, arguments);
|
return base.GetType(methodInfo, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type CreatePinViewModelType(IPin pin)
|
|
||||||
{
|
|
||||||
if (pin.Direction == PinDirection.Input)
|
|
||||||
return typeof(InputPinViewModel<>).MakeGenericType(pin.Type);
|
|
||||||
return typeof(OutputPinViewModel<>).MakeGenericType(pin.Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Type CreatePinCollectionViewModelType(IPinCollection pinCollection)
|
private Type CreatePinCollectionViewModelType(IPinCollection pinCollection)
|
||||||
{
|
{
|
||||||
if (pinCollection.Direction == PinDirection.Input)
|
if (pinCollection.Direction == PinDirection.Input)
|
||||||
|
|||||||
@ -27,7 +27,6 @@ namespace Artemis.UI.Screens.Root
|
|||||||
private readonly IDebugService _debugService;
|
private readonly IDebugService _debugService;
|
||||||
private readonly IClassicDesktopStyleApplicationLifetime _lifeTime;
|
private readonly IClassicDesktopStyleApplicationLifetime _lifeTime;
|
||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
private readonly IRegistrationService _registrationService;
|
|
||||||
private readonly ISidebarVmFactory _sidebarVmFactory;
|
private readonly ISidebarVmFactory _sidebarVmFactory;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private SidebarViewModel? _sidebarViewModel;
|
private SidebarViewModel? _sidebarViewModel;
|
||||||
@ -49,7 +48,6 @@ namespace Artemis.UI.Screens.Root
|
|||||||
|
|
||||||
_coreService = coreService;
|
_coreService = coreService;
|
||||||
_settingsService = settingsService;
|
_settingsService = settingsService;
|
||||||
_registrationService = registrationService;
|
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_debugService = debugService;
|
_debugService = debugService;
|
||||||
_assetLoader = assetLoader;
|
_assetLoader = assetLoader;
|
||||||
@ -62,7 +60,14 @@ namespace Artemis.UI.Screens.Root
|
|||||||
|
|
||||||
DisplayAccordingToSettings();
|
DisplayAccordingToSettings();
|
||||||
Router.CurrentViewModel.Subscribe(UpdateTitleBarViewModel);
|
Router.CurrentViewModel.Subscribe(UpdateTitleBarViewModel);
|
||||||
Task.Run(coreService.Initialize);
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
coreService.Initialize();
|
||||||
|
registrationService.RegisterBuiltInDataModelDisplays();
|
||||||
|
registrationService.RegisterBuiltInDataModelInputs();
|
||||||
|
registrationService.RegisterBuiltInPropertyEditors();
|
||||||
|
registrationService.RegisterBuiltInNodeTypes();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateTitleBarViewModel(IRoutableViewModel? viewModel)
|
private void UpdateTitleBarViewModel(IRoutableViewModel? viewModel)
|
||||||
@ -178,11 +183,6 @@ namespace Artemis.UI.Screens.Root
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void OpenMainWindow()
|
public void OpenMainWindow()
|
||||||
{
|
{
|
||||||
_registrationService.RegisterBuiltInDataModelDisplays();
|
|
||||||
_registrationService.RegisterBuiltInDataModelInputs();
|
|
||||||
_registrationService.RegisterBuiltInPropertyEditors();
|
|
||||||
_registrationService.RegisterBuiltInNodeTypes();
|
|
||||||
|
|
||||||
if (_lifeTime.MainWindow == null)
|
if (_lifeTime.MainWindow == null)
|
||||||
{
|
{
|
||||||
SidebarViewModel = _sidebarVmFactory.SidebarViewModel(this);
|
SidebarViewModel = _sidebarVmFactory.SidebarViewModel(this);
|
||||||
|
|||||||
@ -33,7 +33,7 @@ public class NodeViewModel : ActivatableViewModelBase
|
|||||||
private ObservableAsPropertyHelper<bool>? _hasInputPins;
|
private ObservableAsPropertyHelper<bool>? _hasInputPins;
|
||||||
private ObservableAsPropertyHelper<bool>? _hasOutputPins;
|
private ObservableAsPropertyHelper<bool>? _hasOutputPins;
|
||||||
|
|
||||||
public NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node, INodePinVmFactory nodePinVmFactory, INodeEditorService nodeEditorService)
|
public NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node, INodeVmFactory nodeVmFactory, INodePinVmFactory nodePinVmFactory, INodeEditorService nodeEditorService)
|
||||||
{
|
{
|
||||||
NodeScriptViewModel = nodeScriptViewModel;
|
NodeScriptViewModel = nodeScriptViewModel;
|
||||||
_nodeEditorService = nodeEditorService;
|
_nodeEditorService = nodeEditorService;
|
||||||
@ -47,12 +47,12 @@ public class NodeViewModel : ActivatableViewModelBase
|
|||||||
// Create observable collections split up by direction
|
// Create observable collections split up by direction
|
||||||
nodePins.Connect()
|
nodePins.Connect()
|
||||||
.Filter(n => n.Direction == PinDirection.Input)
|
.Filter(n => n.Direction == PinDirection.Input)
|
||||||
.Transform(nodePinVmFactory.InputPinViewModel)
|
.Transform(p => (PinViewModel) nodeVmFactory.InputPinViewModel(p))
|
||||||
.Bind(out ReadOnlyObservableCollection<PinViewModel> inputPins)
|
.Bind(out ReadOnlyObservableCollection<PinViewModel> inputPins)
|
||||||
.Subscribe();
|
.Subscribe();
|
||||||
nodePins.Connect()
|
nodePins.Connect()
|
||||||
.Filter(n => n.Direction == PinDirection.Output)
|
.Filter(n => n.Direction == PinDirection.Output)
|
||||||
.Transform(nodePinVmFactory.OutputPinViewModel)
|
.Transform(p => (PinViewModel) nodeVmFactory.OutputPinViewModel(p))
|
||||||
.Bind(out ReadOnlyObservableCollection<PinViewModel> outputPins)
|
.Bind(out ReadOnlyObservableCollection<PinViewModel> outputPins)
|
||||||
.Subscribe();
|
.Subscribe();
|
||||||
InputPinViewModels = inputPins;
|
InputPinViewModels = inputPins;
|
||||||
|
|||||||
@ -6,11 +6,20 @@ namespace Artemis.UI.Screens.VisualScripting.Pins;
|
|||||||
|
|
||||||
public class InputPinCollectionViewModel<T> : PinCollectionViewModel
|
public class InputPinCollectionViewModel<T> : PinCollectionViewModel
|
||||||
{
|
{
|
||||||
|
private readonly INodeVmFactory _nodeVmFactory;
|
||||||
public InputPinCollection<T> InputPinCollection { get; }
|
public InputPinCollection<T> InputPinCollection { get; }
|
||||||
|
|
||||||
public InputPinCollectionViewModel(InputPinCollection<T> inputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodePinVmFactory nodePinVmFactory, INodeEditorService nodeEditorService)
|
public InputPinCollectionViewModel(InputPinCollection<T> inputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
|
||||||
: base(inputPinCollection, nodeScriptViewModel, nodePinVmFactory, nodeEditorService)
|
: base(inputPinCollection, nodeScriptViewModel, nodeEditorService)
|
||||||
{
|
{
|
||||||
|
_nodeVmFactory = nodeVmFactory;
|
||||||
InputPinCollection = inputPinCollection;
|
InputPinCollection = inputPinCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override PinViewModel CreatePinViewModel(IPin pin)
|
||||||
|
{
|
||||||
|
PinViewModel vm = _nodeVmFactory.InputPinViewModel(pin);
|
||||||
|
vm.RemovePin = RemovePin;
|
||||||
|
return vm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -3,12 +3,9 @@ using Artemis.Core.Services;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||||
|
|
||||||
public class InputPinViewModel<T> : PinViewModel
|
public class InputPinViewModel : PinViewModel
|
||||||
{
|
{
|
||||||
public InputPin<T> InputPin { get; }
|
public InputPinViewModel(IPin inputPin, INodeService nodeService) : base(inputPin, nodeService)
|
||||||
|
|
||||||
public InputPinViewModel(InputPin<T> inputPin, INodeService nodeService) : base(inputPin, nodeService)
|
|
||||||
{
|
{
|
||||||
InputPin = inputPin;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6,11 +6,20 @@ namespace Artemis.UI.Screens.VisualScripting.Pins;
|
|||||||
|
|
||||||
public class OutputPinCollectionViewModel<T> : PinCollectionViewModel
|
public class OutputPinCollectionViewModel<T> : PinCollectionViewModel
|
||||||
{
|
{
|
||||||
|
private readonly INodeVmFactory _nodeVmFactory;
|
||||||
public OutputPinCollection<T> OutputPinCollection { get; }
|
public OutputPinCollection<T> OutputPinCollection { get; }
|
||||||
|
|
||||||
public OutputPinCollectionViewModel(OutputPinCollection<T> outputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodePinVmFactory nodePinVmFactory, INodeEditorService nodeEditorService)
|
public OutputPinCollectionViewModel(OutputPinCollection<T> outputPinCollection, NodeScriptViewModel nodeScriptViewModel, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService)
|
||||||
: base(outputPinCollection, nodeScriptViewModel, nodePinVmFactory, nodeEditorService)
|
: base(outputPinCollection, nodeScriptViewModel, nodeEditorService)
|
||||||
{
|
{
|
||||||
|
_nodeVmFactory = nodeVmFactory;
|
||||||
OutputPinCollection = outputPinCollection;
|
OutputPinCollection = outputPinCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override PinViewModel CreatePinViewModel(IPin pin)
|
||||||
|
{
|
||||||
|
PinViewModel vm = _nodeVmFactory.OutputPinViewModel(pin);
|
||||||
|
vm.RemovePin = RemovePin;
|
||||||
|
return vm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -3,12 +3,9 @@ using Artemis.Core.Services;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
namespace Artemis.UI.Screens.VisualScripting.Pins;
|
||||||
|
|
||||||
public class OutputPinViewModel<T> : PinViewModel
|
public class OutputPinViewModel : PinViewModel
|
||||||
{
|
{
|
||||||
public OutputPin<T> OutputPin { get; }
|
public OutputPinViewModel(IPin outputPin, INodeService nodeService) : base(outputPin, nodeService)
|
||||||
|
|
||||||
public OutputPinViewModel(OutputPin<T> outputPin, INodeService nodeService) : base(outputPin, nodeService)
|
|
||||||
{
|
{
|
||||||
OutputPin = outputPin;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -17,12 +17,8 @@ namespace Artemis.UI.Screens.VisualScripting.Pins;
|
|||||||
|
|
||||||
public abstract class PinCollectionViewModel : ActivatableViewModelBase
|
public abstract class PinCollectionViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private readonly INodePinVmFactory _nodePinVmFactory;
|
protected PinCollectionViewModel(IPinCollection pinCollection, NodeScriptViewModel nodeScriptViewModel, INodeEditorService nodeEditorService)
|
||||||
|
|
||||||
protected PinCollectionViewModel(IPinCollection pinCollection, NodeScriptViewModel nodeScriptViewModel, INodePinVmFactory nodePinVmFactory, INodeEditorService nodeEditorService)
|
|
||||||
{
|
{
|
||||||
_nodePinVmFactory = nodePinVmFactory;
|
|
||||||
|
|
||||||
PinCollection = pinCollection;
|
PinCollection = pinCollection;
|
||||||
PinViewModels = new ObservableCollection<PinViewModel>();
|
PinViewModels = new ObservableCollection<PinViewModel>();
|
||||||
|
|
||||||
@ -49,10 +45,5 @@ public abstract class PinCollectionViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
public ObservableCollection<PinViewModel> PinViewModels { get; }
|
public ObservableCollection<PinViewModel> PinViewModels { get; }
|
||||||
|
|
||||||
private PinViewModel CreatePinViewModel(IPin pin)
|
protected abstract PinViewModel CreatePinViewModel(IPin pin);
|
||||||
{
|
|
||||||
PinViewModel vm = PinCollection.Direction == PinDirection.Input ? _nodePinVmFactory.InputPinViewModel(pin) : _nodePinVmFactory.OutputPinViewModel(pin);
|
|
||||||
vm.RemovePin = RemovePin;
|
|
||||||
return vm;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -17,7 +17,8 @@
|
|||||||
<Border Classes="card">
|
<Border Classes="card">
|
||||||
<StackPanel Spacing="5">
|
<StackPanel Spacing="5">
|
||||||
<TextBlock Classes="h4">Nodes tests</TextBlock>
|
<TextBlock Classes="h4">Nodes tests</TextBlock>
|
||||||
<dataModelPicker:DataModelPickerButton Placement="BottomEdgeAlignedLeft"/>
|
<!-- <dataModelPicker:DataModelPickerButton Placement="BottomEdgeAlignedLeft"/> -->
|
||||||
|
<ContentControl Content="{CompiledBinding VisualEditorViewModel}" HorizontalAlignment="Stretch" Height="800"></ContentControl>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
<Border Classes="card">
|
<Border Classes="card">
|
||||||
|
|||||||
@ -75,6 +75,9 @@
|
|||||||
<Compile Update="Nodes\CustomViews\StaticStringValueNodeCustomView.axaml.cs">
|
<Compile Update="Nodes\CustomViews\StaticStringValueNodeCustomView.axaml.cs">
|
||||||
<DependentUpon>StaticStringValueNodeCustomView.axaml</DependentUpon>
|
<DependentUpon>StaticStringValueNodeCustomView.axaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="Nodes\DataModel\CustomViews\DataModelNodeCustomView.axaml.cs">
|
||||||
|
<DependentUpon>DataModelNodeCustomView.axaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -2,7 +2,13 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||||
|
xmlns:customViewModels="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.CustomViewModels"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelEventNodeCustomView">
|
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelEventNodeCustomView"
|
||||||
|
x:DataType="customViewModels:DataModelEventNodeCustomViewModel">
|
||||||
|
<dataModelPicker:DataModelPickerButton DataModelPath="{CompiledBinding DataModelPath}"
|
||||||
|
Modules="{CompiledBinding Modules}"
|
||||||
|
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}"
|
||||||
|
FilterTypes="{CompiledBinding FilterTypes}" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||||
|
xmlns:customViewModels="clr-namespace:Artemis.VisualScripting.Nodes.DataModel.CustomViewModels"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.VisualScripting.Nodes.DataModel.CustomViews.DataModelNodeCustomView"
|
||||||
|
x:DataType="customViewModels:DataModelNodeCustomViewModel">
|
||||||
|
<dataModelPicker:DataModelPickerButton DataModelPath="{CompiledBinding DataModelPath}"
|
||||||
|
Modules="{CompiledBinding Modules}"
|
||||||
|
ShowDataModelValues="{CompiledBinding ShowDataModelValues.Value}" />
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
|
namespace Artemis.VisualScripting.Nodes.DataModel.CustomViews
|
||||||
|
{
|
||||||
|
public partial class DataModelNodeCustomView : UserControl
|
||||||
|
{
|
||||||
|
public DataModelNodeCustomView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user