mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Data model picker - Added flyout
This commit is contained in:
parent
4cd596602f
commit
75a0be0c98
@ -1,54 +0,0 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
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>
|
||||
|
||||
<Style Selector="controls|DataModelPicker">
|
||||
<!-- Set Defaults -->
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<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>
|
||||
</Styles>
|
||||
@ -0,0 +1,218 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.UI.Shared.DataModelVisualization.Shared;
|
||||
using Artemis.UI.Shared.Events;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Shared.Controls.DataModelPicker;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a data model picker picker that can be used to select a data model path.
|
||||
/// </summary>
|
||||
public class DataModelPicker : TemplatedControl
|
||||
{
|
||||
/// <summary>
|
||||
/// The data model UI service this picker should use.
|
||||
/// </summary>
|
||||
public static IDataModelUIService? DataModelUIService;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets data model path.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<DataModelPath?> DataModelPathProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, DataModelPath?>(nameof(DataModelPath), defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the data model picker should show current values when selecting a path.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<bool> ShowDataModelValuesProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowDataModelValues));
|
||||
|
||||
/// <summary>
|
||||
/// 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>());
|
||||
|
||||
/// <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>
|
||||
/// 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>());
|
||||
|
||||
/// <summary>
|
||||
/// A list of types to filter the selectable paths on.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<ObservableCollection<Type>?> FilterTypesProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, ObservableCollection<Type>?>(nameof(FilterTypes), new ObservableCollection<Type>());
|
||||
|
||||
static DataModelPicker()
|
||||
{
|
||||
ModulesProperty.Changed.Subscribe(ModulesChanged);
|
||||
DataModelViewModelProperty.Changed.Subscribe(DataModelViewModelPropertyChanged);
|
||||
ExtraDataModelViewModelsProperty.Changed.Subscribe(ExtraDataModelViewModelsChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelPicker" /> class.
|
||||
/// </summary>
|
||||
public DataModelPicker()
|
||||
{
|
||||
SelectPropertyCommand = ReactiveCommand.Create<DataModelVisualizationViewModel>(selected => ExecuteSelectPropertyCommand(selected));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a command that selects the path by it's view model.
|
||||
/// </summary>
|
||||
public ReactiveCommand<DataModelVisualizationViewModel, Unit> SelectPropertyCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets data model path.
|
||||
/// </summary>
|
||||
public DataModelPath? DataModelPath
|
||||
{
|
||||
get => GetValue(DataModelPathProperty);
|
||||
set => SetValue(DataModelPathProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the data model picker should show current values when selecting a path.
|
||||
/// </summary>
|
||||
public bool ShowDataModelValues
|
||||
{
|
||||
get => GetValue(ShowDataModelValuesProperty);
|
||||
set => SetValue(ShowDataModelValuesProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A list of extra modules to show data models of.
|
||||
/// </summary>
|
||||
public ObservableCollection<Module>? Modules
|
||||
{
|
||||
get => GetValue(ModulesProperty);
|
||||
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>
|
||||
/// A list of data model view models to show.
|
||||
/// </summary>
|
||||
public ObservableCollection<DataModelPropertiesViewModel>? ExtraDataModelViewModels
|
||||
{
|
||||
get => GetValue(ExtraDataModelViewModelsProperty);
|
||||
set => SetValue(ExtraDataModelViewModelsProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A list of types to filter the selectable paths on.
|
||||
/// </summary>
|
||||
public ObservableCollection<Type>? FilterTypes
|
||||
{
|
||||
get => GetValue(FilterTypesProperty);
|
||||
set => SetValue(FilterTypesProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a new path has been selected
|
||||
/// </summary>
|
||||
public event EventHandler<DataModelSelectedEventArgs>? DataModelPathSelected;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the <see cref="DataModelPathSelected" /> event
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnDataModelPathSelected(DataModelSelectedEventArgs e)
|
||||
{
|
||||
DataModelPathSelected?.Invoke(this, e);
|
||||
}
|
||||
|
||||
#region Overrides of TemplatedControl
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
GetDataModel();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
private void ExecuteSelectPropertyCommand(DataModelVisualizationViewModel selected)
|
||||
{
|
||||
if (selected.DataModelPath == null)
|
||||
return;
|
||||
if (selected.DataModelPath.Equals(DataModelPath))
|
||||
return;
|
||||
|
||||
DataModelPath = new DataModelPath(selected.DataModelPath);
|
||||
OnDataModelPathSelected(new DataModelSelectedEventArgs(DataModelPath));
|
||||
}
|
||||
|
||||
private void GetDataModel()
|
||||
{
|
||||
if (DataModelUIService == null)
|
||||
return;
|
||||
|
||||
ChangeDataModel(DataModelUIService.GetPluginDataModelVisualization(Modules?.ToList() ?? new List<Module>(), true));
|
||||
}
|
||||
|
||||
private void ChangeDataModel(DataModelPropertiesViewModel? dataModel)
|
||||
{
|
||||
if (DataModelViewModel != null)
|
||||
{
|
||||
DataModelViewModel.Dispose();
|
||||
DataModelViewModel.UpdateRequested -= DataModelOnUpdateRequested;
|
||||
}
|
||||
|
||||
DataModelViewModel = dataModel;
|
||||
if (DataModelViewModel != null)
|
||||
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
|
||||
}
|
||||
|
||||
private void DataModelOnUpdateRequested(object? sender, EventArgs e)
|
||||
{
|
||||
DataModelViewModel?.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
||||
if (ExtraDataModelViewModels == null) return;
|
||||
foreach (DataModelPropertiesViewModel extraDataModelViewModel in ExtraDataModelViewModels)
|
||||
extraDataModelViewModel.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
||||
}
|
||||
}
|
||||
@ -1,45 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.UI.Shared.Controls.Flyouts;
|
||||
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.Interactivity;
|
||||
using Avalonia.Threading;
|
||||
using ReactiveUI;
|
||||
using FluentAvalonia.Core;
|
||||
|
||||
namespace Artemis.UI.Shared.Controls;
|
||||
namespace Artemis.UI.Shared.Controls.DataModelPicker;
|
||||
|
||||
public class DataModelPicker : TemplatedControl
|
||||
/// <summary>
|
||||
/// Represents a button that can be used to pick a data model path in a flyout.
|
||||
/// </summary>
|
||||
public class DataModelPickerButton : TemplatedControl
|
||||
{
|
||||
private static IDataModelUIService? _dataModelUIService;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets data model path.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<DataModelPath?> DataModelPathProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, DataModelPath?>(nameof(DataModelPath), defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the placeholder to show when nothing is selected.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<string> PlaceholderProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, string>(nameof(Placeholder), "Click to select");
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the data model picker should show current values when selecting a path.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<bool> ShowDataModelValuesProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowDataModelValues));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the data model picker should show the full path of the selected value.
|
||||
/// </summary>
|
||||
@ -47,10 +33,28 @@ public class DataModelPicker : TemplatedControl
|
||||
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowFullPath));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the brush to use when drawing the button.
|
||||
/// Gets a boolean indicating whether the data model picker has a value.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<Brush> ButtonBrushProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, Brush>(nameof(ButtonBrush));
|
||||
public static readonly StyledProperty<bool> HasValueProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(HasValue));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the desired flyout placement.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<FlyoutPlacementMode> PlacementProperty =
|
||||
AvaloniaProperty.Register<FlyoutBase, FlyoutPlacementMode>(nameof(Placement));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets data model path.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<DataModelPath?> DataModelPathProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, DataModelPath?>(nameof(DataModelPath), defaultBindingMode: BindingMode.TwoWay);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the data model picker should show current values when selecting a path.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<bool> ShowDataModelValuesProperty =
|
||||
AvaloniaProperty.Register<DataModelPicker, bool>(nameof(ShowDataModelValues));
|
||||
|
||||
/// <summary>
|
||||
/// A list of extra modules to show data models of.
|
||||
@ -76,103 +80,16 @@ 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;
|
||||
private bool _flyoutActive;
|
||||
private Button? _button;
|
||||
private DataModelPickerFlyout? _flyout;
|
||||
private IDisposable? _dataModelPathChanged;
|
||||
|
||||
static DataModelPicker()
|
||||
static DataModelPickerButton()
|
||||
{
|
||||
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>
|
||||
public DataModelPicker()
|
||||
{
|
||||
SelectPropertyCommand = ReactiveCommand.Create<DataModelVisualizationViewModel>(selected => ExecuteSelectPropertyCommand(selected));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a command that selects the path by it's view model.
|
||||
/// </summary>
|
||||
public ReactiveCommand<DataModelVisualizationViewModel, Unit> SelectPropertyCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Internal, don't use.
|
||||
/// </summary>
|
||||
public static IDataModelUIService DataModelUIService
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_dataModelUIService != null)
|
||||
throw new AccessViolationException("This is not for you to touch");
|
||||
_dataModelUIService = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets data model path.
|
||||
/// </summary>
|
||||
public DataModelPath? DataModelPath
|
||||
{
|
||||
get => GetValue(DataModelPathProperty);
|
||||
set => SetValue(DataModelPathProperty, value);
|
||||
DataModelPathProperty.Changed.Subscribe(DataModelPathChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -193,6 +110,33 @@ public class DataModelPicker : TemplatedControl
|
||||
set => SetValue(ShowFullPathProperty, 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>
|
||||
/// Gets or sets the desired flyout placement.
|
||||
/// </summary>
|
||||
public FlyoutPlacementMode Placement
|
||||
{
|
||||
get => GetValue(PlacementProperty);
|
||||
set => SetValue(PlacementProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets data model path.
|
||||
/// </summary>
|
||||
public DataModelPath? DataModelPath
|
||||
{
|
||||
get => GetValue(DataModelPathProperty);
|
||||
set => SetValue(DataModelPathProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the data model picker should show current values when selecting a path.
|
||||
/// </summary>
|
||||
@ -202,15 +146,6 @@ public class DataModelPicker : TemplatedControl
|
||||
set => SetValue(ShowDataModelValuesProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the brush to use when drawing the button.
|
||||
/// </summary>
|
||||
public Brush ButtonBrush
|
||||
{
|
||||
get => GetValue(ButtonBrushProperty);
|
||||
set => SetValue(ButtonBrushProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A list of extra modules to show data models of.
|
||||
/// </summary>
|
||||
@ -248,58 +183,111 @@ public class DataModelPicker : TemplatedControl
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether the data model picker has a value.
|
||||
/// Raised when the flyout opens.
|
||||
/// </summary>
|
||||
public bool HasValue
|
||||
{
|
||||
get => GetValue(HasValueProperty);
|
||||
private set => SetValue(HasValueProperty, value);
|
||||
}
|
||||
public event TypedEventHandler<DataModelPickerButton, EventArgs>? FlyoutOpened;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a new path has been selected
|
||||
/// Raised when the flyout closes.
|
||||
/// </summary>
|
||||
public event EventHandler<DataModelSelectedEventArgs>? DataModelPathSelected;
|
||||
public event TypedEventHandler<DataModelPickerButton, EventArgs>? FlyoutClosed;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the <see cref="DataModelPathSelected" /> event
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnDataModelPathSelected(DataModelSelectedEventArgs e)
|
||||
private static void DataModelPathChanged(AvaloniaPropertyChangedEventArgs<DataModelPath?> e)
|
||||
{
|
||||
DataModelPathSelected?.Invoke(this, e);
|
||||
}
|
||||
|
||||
private void ExecuteSelectPropertyCommand(DataModelVisualizationViewModel selected)
|
||||
{
|
||||
if (selected.DataModelPath == null)
|
||||
return;
|
||||
if (selected.DataModelPath.Equals(DataModelPath))
|
||||
if (e.Sender is not DataModelPickerButton self || !self._attached)
|
||||
return;
|
||||
|
||||
DataModelPath = new DataModelPath(selected.DataModelPath);
|
||||
OnDataModelPathSelected(new DataModelSelectedEventArgs(DataModelPath));
|
||||
}
|
||||
|
||||
private void GetDataModel()
|
||||
{
|
||||
if (_dataModelUIService == null)
|
||||
return;
|
||||
|
||||
ChangeDataModel(_dataModelUIService.GetPluginDataModelVisualization(Modules?.ToList() ?? new List<Module>(), true));
|
||||
}
|
||||
|
||||
private void ChangeDataModel(DataModelPropertiesViewModel? dataModel)
|
||||
{
|
||||
if (DataModelViewModel != null)
|
||||
if (e.OldValue.Value != null)
|
||||
{
|
||||
DataModelViewModel.Dispose();
|
||||
DataModelViewModel.UpdateRequested -= DataModelOnUpdateRequested;
|
||||
e.OldValue.Value.PathInvalidated -= self.PathValidationChanged;
|
||||
e.OldValue.Value.PathValidated -= self.PathValidationChanged;
|
||||
e.OldValue.Value.Dispose();
|
||||
}
|
||||
|
||||
DataModelViewModel = dataModel;
|
||||
if (DataModelViewModel != null)
|
||||
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
|
||||
if (e.NewValue.Value != null)
|
||||
{
|
||||
e.NewValue.Value.PathInvalidated += self.PathValidationChanged;
|
||||
e.NewValue.Value.PathValidated += self.PathValidationChanged;
|
||||
}
|
||||
|
||||
self.UpdateValueDisplay();
|
||||
}
|
||||
|
||||
private static void ShowFullPathChanged(AvaloniaPropertyChangedEventArgs<bool> e)
|
||||
{
|
||||
if (e.Sender is DataModelPickerButton self)
|
||||
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)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(UpdateValueDisplay, DispatcherPriority.DataBind);
|
||||
}
|
||||
|
||||
private void UpdateValueDisplay()
|
||||
{
|
||||
HasValue = DataModelPath != null && DataModelPath.IsValid;
|
||||
|
||||
if (_button == null)
|
||||
return;
|
||||
|
||||
if (!HasValue)
|
||||
{
|
||||
ToolTip.SetTip(_button, null);
|
||||
_button.Content = Placeholder;
|
||||
}
|
||||
else
|
||||
{
|
||||
string? formattedPath = null;
|
||||
if (DataModelPath != null && DataModelPath.IsValid)
|
||||
formattedPath = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
|
||||
|
||||
ToolTip.SetTip(_button, formattedPath);
|
||||
_button.Content = ShowFullPath
|
||||
? formattedPath
|
||||
: DataModelPath?.Segments.LastOrDefault()?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnButtonClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_flyout == null)
|
||||
return;
|
||||
|
||||
// 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.DataModelViewModel = DataModelViewModel;
|
||||
_flyout.DataModelPicker.ExtraDataModelViewModels = ExtraDataModelViewModels;
|
||||
_flyout.DataModelPicker.FilterTypes = FilterTypes;
|
||||
_flyout.DataModelPicker.Modules = Modules;
|
||||
_flyout.DataModelPicker.ShowDataModelValues = ShowDataModelValues;
|
||||
|
||||
_flyout.Placement = Placement;
|
||||
_flyout.ShowAt(_button != null ? _button : this);
|
||||
_flyoutActive = true;
|
||||
|
||||
_dataModelPathChanged = DataModelPicker.DataModelPathProperty.Changed.Subscribe(FlyoutDataModelPathChanged);
|
||||
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
|
||||
@ -307,17 +295,15 @@ public class DataModelPicker : TemplatedControl
|
||||
/// <inheritdoc />
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
if (_button != null)
|
||||
_button.Click -= OnButtonClick;
|
||||
base.OnApplyTemplate(e);
|
||||
_dataModelButton = e.NameScope.Find<Button>("DataModelButton");
|
||||
|
||||
GetDataModel();
|
||||
_button = e.NameScope.Find<Button>("MainButton");
|
||||
if (_button != null)
|
||||
_button.Click += OnButtonClick;
|
||||
UpdateValueDisplay();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides of Visual
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
@ -328,7 +314,13 @@ public class DataModelPicker : TemplatedControl
|
||||
DataModelPath.PathValidated += PathValidationChanged;
|
||||
}
|
||||
|
||||
base.OnAttachedToVisualTree(e);
|
||||
if (_flyout == null)
|
||||
{
|
||||
_flyout = new DataModelPickerFlyout();
|
||||
_flyout.FlyoutPresenterClasses.Add("data-model-picker-presenter");
|
||||
}
|
||||
|
||||
_flyout.Closed += OnFlyoutClosed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -341,46 +333,10 @@ public class DataModelPicker : TemplatedControl
|
||||
}
|
||||
|
||||
DataModelViewModel?.Dispose();
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
|
||||
if (_flyout != null)
|
||||
_flyout.Closed -= OnFlyoutClosed;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void UpdateValueDisplay()
|
||||
{
|
||||
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));
|
||||
|
||||
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)
|
||||
{
|
||||
DataModelViewModel?.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
||||
if (ExtraDataModelViewModels == null) return;
|
||||
foreach (DataModelPropertiesViewModel extraDataModelViewModel in ExtraDataModelViewModels)
|
||||
extraDataModelViewModel.ApplyTypeFilter(true, FilterTypes?.ToArray() ?? Type.EmptyTypes);
|
||||
}
|
||||
|
||||
private void PathValidationChanged(object? sender, EventArgs e)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(UpdateValueDisplay, DispatcherPriority.DataBind);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Artemis.UI.Shared.Controls.Flyouts;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a flyout that hosts a data model picker.
|
||||
/// </summary>
|
||||
public sealed class DataModelPickerFlyout : Flyout
|
||||
{
|
||||
private DataModelPicker.DataModelPicker? _picker;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data model picker that the flyout hosts.
|
||||
/// </summary>
|
||||
public DataModelPicker.DataModelPicker DataModelPicker => _picker ??= new DataModelPicker.DataModelPicker();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Control CreatePresenter()
|
||||
{
|
||||
_picker ??= new DataModelPicker.DataModelPicker();
|
||||
FlyoutPresenter presenter = new() {Content = DataModelPicker};
|
||||
return presenter;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
||||
namespace Artemis.UI.Shared.Controls.Flyouts;
|
||||
|
||||
@ -11,7 +10,7 @@ public sealed class GradientPickerFlyout : Flyout
|
||||
private GradientPicker.GradientPicker? _picker;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the gradient picker that this flyout hosts
|
||||
/// Gets the gradient picker that this flyout hosts.
|
||||
/// </summary>
|
||||
public GradientPicker.GradientPicker GradientPicker => _picker ??= new GradientPicker.GradientPicker();
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Modules;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
using ReactiveUI;
|
||||
|
||||
@ -21,7 +20,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared
|
||||
private ObservableCollection<DataModelVisualizationViewModel> _children;
|
||||
private DataModel? _dataModel;
|
||||
private bool _isMatchingFilteredTypes;
|
||||
private bool _isVisualizationExpanded = true;
|
||||
private bool _isVisualizationExpanded;
|
||||
private DataModelVisualizationViewModel? _parent;
|
||||
private DataModelPropertyAttribute? _propertyDescription;
|
||||
private bool _populatedStaticChildren;
|
||||
|
||||
@ -26,7 +26,8 @@
|
||||
<!-- Custom controls -->
|
||||
<StyleInclude Source="/Styles/Controls/GradientPicker.axaml" />
|
||||
<StyleInclude Source="/Styles/Controls/GradientPickerButton.axaml" />
|
||||
<StyleInclude Source="/Controls/DataModelPicker.axaml" />
|
||||
<StyleInclude Source="/Styles/Controls/DataModelPicker.axaml" />
|
||||
<StyleInclude Source="/Styles/Controls/DataModelPickerButton.axaml" />
|
||||
|
||||
<!-- Custom styles -->
|
||||
<StyleInclude Source="/Styles/Border.axaml" />
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:dataModel="clr-namespace:Artemis.UI.Shared.DataModelVisualization.Shared"
|
||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia">
|
||||
<Design.PreviewWith>
|
||||
<dataModelPicker:DataModelPicker />
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="dataModelPicker|DataModelPicker">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Grid RowDefinitions="Auto,Auto,*" Width="600" Height="400">
|
||||
<TextBox Grid.Row="0" Watermark="Search" Name="SearchBox"></TextBox>
|
||||
|
||||
<Border Grid.Row="1" Classes="card card-condensed" Margin="0 15">
|
||||
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,*,*">
|
||||
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" Classes="SubtitleTextBlockStyle">Current selection</TextBlock>
|
||||
<avalonia:MaterialIcon Kind="CalculatorVariantOutline" Grid.Column="0" Grid.Row="1" Grid.RowSpan="2" Height="22" Width="22" Margin="5 0 15 0"></avalonia:MaterialIcon>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Classes="BodyStrongTextBlockStyle">Cursor Y-position</TextBlock>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Classes="BodyTextBlockStyle" Foreground="{DynamicResource TextFillColorSecondary}">The current Y-position of the cursor in pixels</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<TreeView Grid.Row="2" Items="{Binding DataModelViewModel.Children, RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<TreeView.Styles>
|
||||
<Style Selector="TreeViewItem">
|
||||
<Setter Property="IsExpanded" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
||||
</Style>
|
||||
</TreeView.Styles>
|
||||
<TreeView.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"
|
||||
Margin="0 0 10 0" />
|
||||
</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" Margin="0 0 10 0" />
|
||||
</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"
|
||||
Margin="0 0 10 0" />
|
||||
</Grid>
|
||||
</TreeDataTemplate>
|
||||
|
||||
<TreeDataTemplate DataType="{x:Type dataModel:DataModelEventViewModel}" ItemsSource="{Binding Children}">
|
||||
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip.Tip="{Binding PropertyDescription.Description}" />
|
||||
</TreeDataTemplate>
|
||||
</TreeView.DataTemplates>
|
||||
</TreeView>
|
||||
<StackPanel Grid.Row="2" VerticalAlignment="Center" Spacing="20" IsVisible="False">
|
||||
<avalonia:MaterialIcon Kind="CloseCircle" Width="64" Height="64"></avalonia:MaterialIcon>
|
||||
<TextBlock Classes="h4" TextAlignment="Center">No parts of the data model match your search</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
@ -0,0 +1,36 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20" Width="200">
|
||||
<StackPanel Spacing="5">
|
||||
<dataModelPicker:DataModelPickerButton />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="FlyoutPresenter.data-model-picker-presenter">
|
||||
<!-- <Setter Property="Padding" Value="0" /> -->
|
||||
<Setter Property="MaxWidth" Value="1200" />
|
||||
<Setter Property="MaxHeight" Value="1200" />
|
||||
<Setter Property="Background" Value="{DynamicResource SolidBackgroundFillColorBaseBrush}" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="dataModelPicker|DataModelPickerButton">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrush}" />
|
||||
<Setter Property="MinHeight" Value="{DynamicResource TextControlThemeMinHeight}" />
|
||||
<Setter Property="MinWidth" Value="{DynamicResource TextControlThemeMinWidth}" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<controls:Button Name="MainButton"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}">
|
||||
</controls:Button>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Reactive;
|
||||
using Artemis.Core.Ninject;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Ninject;
|
||||
using Artemis.UI.Exceptions;
|
||||
using Artemis.UI.Ninject;
|
||||
using Artemis.UI.Screens.Root;
|
||||
using Artemis.UI.Shared.Controls;
|
||||
using Artemis.UI.Shared.Controls.DataModelPicker;
|
||||
using Artemis.UI.Shared.Ninject;
|
||||
using Artemis.UI.Shared.Services.Interfaces;
|
||||
using Artemis.VisualScripting.Ninject;
|
||||
@ -17,57 +17,55 @@ using Ninject.Modules;
|
||||
using ReactiveUI;
|
||||
using Splat.Ninject;
|
||||
|
||||
namespace Artemis.UI
|
||||
namespace Artemis.UI;
|
||||
|
||||
public static class ArtemisBootstrapper
|
||||
{
|
||||
public static class ArtemisBootstrapper
|
||||
private static StandardKernel? _kernel;
|
||||
private static Application? _application;
|
||||
|
||||
public static StandardKernel Bootstrap(Application application, params INinjectModule[] modules)
|
||||
{
|
||||
private static StandardKernel? _kernel;
|
||||
private static Application? _application;
|
||||
if (_application != null || _kernel != null)
|
||||
throw new ArtemisUIException("UI already bootstrapped");
|
||||
|
||||
public static StandardKernel Bootstrap(Application application, params INinjectModule[] modules)
|
||||
{
|
||||
if (_application != null || _kernel != null)
|
||||
throw new ArtemisUIException("UI already bootstrapped");
|
||||
Utilities.PrepareFirstLaunch();
|
||||
|
||||
Utilities.PrepareFirstLaunch();
|
||||
_application = application;
|
||||
_kernel = new StandardKernel();
|
||||
_kernel.Settings.InjectNonPublic = true;
|
||||
|
||||
_application = application;
|
||||
_kernel = new StandardKernel();
|
||||
_kernel.Settings.InjectNonPublic = true;
|
||||
_kernel.Load<CoreModule>();
|
||||
_kernel.Load<UIModule>();
|
||||
_kernel.Load<SharedUIModule>();
|
||||
_kernel.Load<NoStringNinjectModule>();
|
||||
_kernel.Load(modules);
|
||||
_kernel.UseNinjectDependencyResolver();
|
||||
|
||||
_kernel.Load<CoreModule>();
|
||||
_kernel.Load<UIModule>();
|
||||
_kernel.Load<SharedUIModule>();
|
||||
_kernel.Load<NoStringNinjectModule>();
|
||||
_kernel.Load(modules);
|
||||
DataModelPicker.DataModelUIService = _kernel.Get<IDataModelUIService>();
|
||||
|
||||
_kernel.UseNinjectDependencyResolver();
|
||||
return _kernel;
|
||||
}
|
||||
|
||||
DataModelPicker.DataModelUIService = _kernel.Get<IDataModelUIService>();
|
||||
public static void Initialize()
|
||||
{
|
||||
if (_application == null || _kernel == null)
|
||||
throw new ArtemisUIException("UI not yet bootstrapped");
|
||||
if (_application.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
|
||||
return;
|
||||
|
||||
return _kernel;
|
||||
}
|
||||
// Don't shut down when the last window closes, we might still be active in the tray
|
||||
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
|
||||
// Create the root view model that drives the UI
|
||||
RootViewModel rootViewModel = _kernel.Get<RootViewModel>();
|
||||
// Apply the root view model to the data context of the application so that tray icon commands work
|
||||
_application.DataContext = rootViewModel;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (_application == null || _kernel == null)
|
||||
throw new ArtemisUIException("UI not yet bootstrapped");
|
||||
if (_application.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
|
||||
return;
|
||||
RxApp.DefaultExceptionHandler = Observer.Create<Exception>(DisplayUnhandledException);
|
||||
}
|
||||
|
||||
// Don't shut down when the last window closes, we might still be active in the tray
|
||||
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
|
||||
// Create the root view model that drives the UI
|
||||
RootViewModel rootViewModel = _kernel.Get<RootViewModel>();
|
||||
// Apply the root view model to the data context of the application so that tray icon commands work
|
||||
_application.DataContext = rootViewModel;
|
||||
|
||||
RxApp.DefaultExceptionHandler = Observer.Create<Exception>(DisplayUnhandledException);
|
||||
}
|
||||
|
||||
private static void DisplayUnhandledException(Exception exception)
|
||||
{
|
||||
_kernel?.Get<IWindowService>().ShowExceptionDialog("Exception", exception);
|
||||
}
|
||||
private static void DisplayUnhandledException(Exception exception)
|
||||
{
|
||||
_kernel?.Get<IWindowService>().ShowExceptionDialog("Exception", exception);
|
||||
}
|
||||
}
|
||||
@ -8,6 +8,7 @@
|
||||
xmlns:attachedProperties="clr-namespace:Artemis.UI.Shared.AttachedProperties;assembly=Artemis.UI.Shared"
|
||||
xmlns:workshop="clr-namespace:Artemis.UI.Screens.Workshop"
|
||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker;assembly=Artemis.UI.Shared"
|
||||
xmlns:dataModelPicker="clr-namespace:Artemis.UI.Shared.Controls.DataModelPicker;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="800"
|
||||
x:Class="Artemis.UI.Screens.Workshop.WorkshopView"
|
||||
x:DataType="workshop:WorkshopViewModel">
|
||||
@ -16,8 +17,7 @@
|
||||
<Border Classes="card">
|
||||
<StackPanel Spacing="5">
|
||||
<TextBlock Classes="h4">Nodes tests</TextBlock>
|
||||
<controls:DataModelPicker ></controls:DataModelPicker>
|
||||
<!-- <ContentControl Content="{CompiledBinding VisualEditorViewModel}" HorizontalAlignment="Stretch" Height="800"></ContentControl> -->
|
||||
<dataModelPicker:DataModelPickerButton Placement="BottomEdgeAlignedLeft"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Classes="card">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user