Conditions - Removed old systems

Data bindings - Removed old systems
Data bindings - Implemented node system
This commit is contained in:
Robert committed 2021-08-18 23:47:14 +02:00
1 parent 32d4ec2812
commit 5675d1895b
157 files changed
+784 -8802

No files matched your search

@@ -77,4 +77,7 @@
<ItemGroup>
<Resource Include="Resources\Fonts\RobotoMono-Regular.ttf" />
</ItemGroup>
<ItemGroup>
<Folder Include="Extensions\" />
</ItemGroup>
</Project>
+5 -4
View File
@@ -1,4 +1,5 @@
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Controls;
using Artemis.UI.Shared.Services;
using Ninject;
namespace Artemis.UI.Shared
@@ -23,9 +24,9 @@ namespace Artemis.UI.Shared
if (Initialized)
return;
IColorPickerService colorPickerService = kernel.Get<IColorPickerService>();
GradientPicker.ColorPickerService = colorPickerService;
ColorPicker.ColorPickerService = colorPickerService;
GradientPicker.ColorPickerService = kernel.Get<IColorPickerService>();
ColorPicker.ColorPickerService = kernel.Get<IColorPickerService>();
DataModelPicker.DataModelUIService = kernel.Get<IDataModelUIService>();
Initialized = true;
}
@@ -0,0 +1,75 @@
<UserControl x:Class="Artemis.UI.Shared.Controls.DataModelPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Shared.Controls"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:shared="clr-namespace:Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DataModelConditions.xaml" />
<ResourceDictionary>
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<shared:BindingProxy x:Key="DataContextProxy" Data="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<DataTemplate x:Key="DataModelDataTemplate">
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Button Background="{Binding ButtonBrush, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
BorderBrush="{Binding ButtonBrush, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
Style="{StaticResource DataModelConditionButton}"
IsEnabled="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
HorizontalAlignment="Left"
Click="PropertyButton_OnClick"
x:Name="DataModelButton">
<Button.ContextMenu>
<ContextMenu>
<ContextMenu.Resources>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Command" Value="{Binding Data.SelectPropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" />
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
</Style>
<shared:IntToVisibilityConverter x:Key="IntToVisibilityConverter" />
</ContextMenu.Resources>
<ContextMenu.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection="{Binding Data.ExtraDataModelViewModels, Source={StaticResource DataContextProxy}}" />
<Separator Visibility="{Binding Data.ExtraDataModelViewModels.Count, Source={StaticResource DataContextProxy}, Converter={StaticResource IntToVisibilityConverter}, Mode=OneWay}" />
<CollectionContainer Collection="{Binding Data.DataModelViewModel.Children, Source={StaticResource DataContextProxy}}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
</Button.ContextMenu>
<Grid>
<Grid x:Name="ValueDisplay">
<TextBlock x:Name="ValueDisplayTextBlock"
Visibility="{Binding DataModelPath, Converter={StaticResource NullToVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
<TextBlock FontStyle="Italic"
Visibility="{Binding DataModelPath, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">
<Run Text="« " /><Run Text="{Binding Placeholder, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /><Run Text=" »" />
</TextBlock>
</Grid>
<TextBlock x:Name="ValuePlaceholder" FontStyle="Italic">
« Invalid »
</TextBlock>
</Grid>
</Button>
</UserControl>
@@ -0,0 +1,303 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.UI.Shared.Services;
using Stylet;
namespace Artemis.UI.Shared.Controls
{
/// <summary>
/// Interaction logic for DataModelPicker.xaml
/// </summary>
public partial class DataModelPicker : INotifyPropertyChanged
{
private static IDataModelUIService _dataModelUIService;
/// <summary>
/// Gets or sets data model path
/// </summary>
public static readonly DependencyProperty DataModelPathProperty = DependencyProperty.Register(
nameof(DataModelPath), typeof(DataModelPath), typeof(DataModelPicker),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, DataModelPathPropertyChangedCallback)
);
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.Register(
nameof(Placeholder), typeof(string), typeof(DataModelPicker),
new FrameworkPropertyMetadata("Click to select")
);
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public static readonly DependencyProperty ShowDataModelValuesProperty = DependencyProperty.Register(nameof(ShowDataModelValues), typeof(bool), typeof(DataModelPicker));
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public static readonly DependencyProperty ShowFullPathProperty = DependencyProperty.Register(nameof(ShowFullPath), typeof(bool), typeof(DataModelPicker));
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public static readonly DependencyProperty ButtonBrushProperty = DependencyProperty.Register(nameof(ButtonBrush), typeof(Brush), typeof(DataModelPicker));
/// <summary>
/// A list of extra modules to show data models of
/// </summary>
public static readonly DependencyProperty ModulesProperty = DependencyProperty.Register(
nameof(Modules), typeof(BindableCollection<Module>), typeof(DataModelPicker),
new FrameworkPropertyMetadata(new BindableCollection<Module>(), FrameworkPropertyMetadataOptions.None, ModulesPropertyChangedCallback)
);
/// <summary>
/// The data model view model to show, if not provided one will be retrieved by the control
/// </summary>
public static readonly DependencyProperty DataModelViewModelProperty = DependencyProperty.Register(
nameof(DataModelViewModel), typeof(DataModelPropertiesViewModel), typeof(DataModelPicker),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, DataModelViewModelPropertyChangedCallback)
);
/// <summary>
/// A list of data model view models to show
/// </summary>
public static readonly DependencyProperty ExtraDataModelViewModelsProperty = DependencyProperty.Register(
nameof(ExtraDataModelViewModels), typeof(BindableCollection<DataModelPropertiesViewModel>), typeof(DataModelPicker),
new FrameworkPropertyMetadata(new BindableCollection<DataModelPropertiesViewModel>(), FrameworkPropertyMetadataOptions.None, ExtraDataModelViewModelsPropertyChangedCallback)
);
/// <summary>
/// A list of data model view models to show
/// </summary>
public static readonly DependencyProperty FilterTypesProperty = DependencyProperty.Register(
nameof(FilterTypes), typeof(BindableCollection<Type>), typeof(DataModelPicker),
new FrameworkPropertyMetadata(new BindableCollection<Type>())
);
public DataModelPicker()
{
SelectPropertyCommand = new DelegateCommand(ExecuteSelectPropertyCommand);
InitializeComponent();
GetDataModel();
UpdateValueDisplay();
}
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public DataModelPath? DataModelPath
{
get => (DataModelPath) GetValue(DataModelPathProperty);
set => SetValue(DataModelPathProperty, value);
}
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public string Placeholder
{
get => (string) GetValue(PlaceholderProperty);
set => SetValue(PlaceholderProperty, value);
}
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public bool ShowDataModelValues
{
get => (bool) GetValue(ShowDataModelValuesProperty);
set => SetValue(ShowDataModelValuesProperty, value);
}
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public bool ShowFullPath
{
get => (bool) GetValue(ShowFullPathProperty);
set => SetValue(ShowFullPathProperty, value);
}
/// <summary>
/// Gets or sets the brush to use when drawing the button
/// </summary>
public Brush ButtonBrush
{
get => (Brush) GetValue(ButtonBrushProperty);
set => SetValue(ButtonBrushProperty, value);
}
/// <summary>
/// Gets or sets a list of extra modules to show data models of
/// </summary>
public BindableCollection<Module>? Modules
{
get => (BindableCollection<Module>) GetValue(ModulesProperty);
set => SetValue(ModulesProperty, value);
}
/// <summary>
/// Gets or sets the data model view model to show
/// </summary>
public DataModelPropertiesViewModel? DataModelViewModel
{
get => (DataModelPropertiesViewModel) GetValue(DataModelViewModelProperty);
set => SetValue(DataModelViewModelProperty, value);
}
/// <summary>
/// Gets or sets a list of data model view models to show
/// </summary>
public BindableCollection<DataModelPropertiesViewModel>? ExtraDataModelViewModels
{
get => (BindableCollection<DataModelPropertiesViewModel>) GetValue(ExtraDataModelViewModelsProperty);
set => SetValue(ExtraDataModelViewModelsProperty, value);
}
/// <summary>
/// Gets or sets the types of properties this view model will allow to be selected
/// </summary>
public BindableCollection<Type>? FilterTypes
{
get => (BindableCollection<Type>) GetValue(FilterTypesProperty);
set => SetValue(FilterTypesProperty, value);
}
/// <summary>
/// Command used by view
/// </summary>
public DelegateCommand SelectPropertyCommand { get; }
internal static IDataModelUIService DataModelUIService
{
set
{
if (_dataModelUIService != null)
throw new AccessViolationException("This is not for you to touch");
_dataModelUIService = 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);
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void GetDataModel()
{
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 UpdateValueDisplay()
{
ValueDisplay.Visibility = DataModelPath == null || DataModelPath.IsValid ? Visibility.Visible : Visibility.Collapsed;
ValuePlaceholder.Visibility = DataModelPath == null || DataModelPath.IsValid ? Visibility.Collapsed : Visibility.Visible;
string? formattedPath = null;
if (DataModelPath != null && DataModelPath.IsValid)
formattedPath = string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription() != null).Select(s => s.GetPropertyDescription()!.Name));
DataModelButton.ToolTip = formattedPath;
ValueDisplayTextBlock.Text = ShowFullPath
? 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 ExecuteSelectPropertyCommand(object? context)
{
if (context is not DataModelVisualizationViewModel selected)
return;
DataModelPath = selected.DataModelPath;
OnDataModelPathSelected(new DataModelSelectedEventArgs(DataModelPath));
}
private void PropertyButton_OnClick(object sender, RoutedEventArgs e)
{
// DataContext is not set when using left button, I don't know why but there it is
if (sender is Button button && button.ContextMenu != null)
{
button.ContextMenu.DataContext = button.DataContext;
button.ContextMenu.IsOpen = true;
}
}
private static void DataModelPathPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not DataModelPicker dataModelPicker)
return;
if (e.OldValue is DataModelPath oldPath)
oldPath.Dispose();
dataModelPicker.UpdateValueDisplay();
}
private static void ModulesPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not DataModelPicker dataModelPicker)
return;
dataModelPicker.GetDataModel();
}
private static void DataModelViewModelPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not DataModelPicker dataModelPicker)
return;
}
private static void ExtraDataModelViewModelsPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not DataModelPicker dataModelPicker)
return;
}
public event PropertyChangedEventHandler? PropertyChanged;
}
}
@@ -0,0 +1,39 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace Artemis.UI.Shared
{
/// <summary>
/// Converts <see cref="int"/> to <see cref="Visibility"/>
/// </summary>
public class IntToVisibilityConverter : IValueConverter
{
/// <inheritdoc />
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
Parameters direction;
if (parameter == null)
direction = Parameters.Normal;
else
direction = (Parameters) Enum.Parse(typeof(Parameters), (string) parameter);
return direction == Parameters.Normal
? value is > 1 ? Visibility.Visible : Visibility.Collapsed
: value is > 1 ? Visibility.Collapsed : Visibility.Visible;
}
/// <inheritdoc />
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
private enum Parameters
{
Normal,
Inverted
}
}
}
@@ -1,109 +0,0 @@
<UserControl x:Class="Artemis.UI.Shared.Input.DataModelDynamicView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:shared="clr-namespace:Artemis.UI.Shared"
xmlns:input="clr-namespace:Artemis.UI.Shared.Input"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance input:DataModelDynamicViewModel}">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DataModelConditions.xaml" />
<ResourceDictionary>
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<shared:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
<DataTemplate x:Key="DataModelDataTemplate">
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<Style x:Key="DataModelConditionButtonCornerToggle" BasedOn="{StaticResource DataModelConditionButton}" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding DisplaySwitchButton}" Value="True">
<Setter Property="materialDesign:ButtonAssist.CornerRadius" Value="0 2 2 0" />
</DataTrigger>
<DataTrigger Binding="{Binding DisplaySwitchButton}" Value="False">
<Setter Property="materialDesign:ButtonAssist.CornerRadius" Value="2" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource MaterialDesignFlatDarkBgButton}"
Background="{Binding SwitchButtonBrush}"
BorderBrush="{Binding SwitchButtonBrush}"
Height="22"
Padding="0"
Width="22"
FontSize="12"
materialDesign:ButtonAssist.CornerRadius="2 0 0 2"
Margin="3 0 -3 0"
HorizontalAlignment="Left"
ToolTip="Switch to manual input"
Command="{s:Action SwitchToStatic}"
Visibility="{Binding DisplaySwitchButton, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<materialDesign:PackIcon Kind="SwapHorizontal" />
</Button>
<Button Background="{Binding ButtonBrush}"
BorderBrush="{Binding ButtonBrush}"
Style="{StaticResource DataModelConditionButtonCornerToggle}"
ToolTip="{Binding DisplayPath}"
IsEnabled="{Binding IsEnabled}"
HorizontalAlignment="Left"
Click="PropertyButton_OnClick">
<Button.ContextMenu>
<ContextMenu IsOpen="{Binding IsDataModelViewModelOpen, Mode=OneWayToSource}">
<ContextMenu.Resources>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Command" Value="{Binding Data.SelectPropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" />
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
</Style>
</ContextMenu.Resources>
<ContextMenu.ItemsSource>
<CompositeCollection>
<MenuItem Header="No modules available" IsEnabled="False" Visibility="{Binding Data.HasNoModules, Source={StaticResource DataContextProxy}, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<MenuItem.Icon>
<materialDesign:PackIcon Kind="EmojiSad" />
</MenuItem.Icon>
</MenuItem>
<CollectionContainer Collection="{Binding Data.ExtraDataModelViewModels, Source={StaticResource DataContextProxy}}" />
<Separator Visibility="{Binding Data.HasExtraDataModels, Source={StaticResource DataContextProxy}, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"/>
<CollectionContainer Collection="{Binding Data.DataModelViewModel.Children, Source={StaticResource DataContextProxy}}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
</Button.ContextMenu>
<Grid>
<Grid Visibility="{Binding IsValid,Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<TextBlock Text="{Binding DisplayValue}"
Visibility="{Binding DataModelPath, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock FontStyle="Italic"
Visibility="{Binding DataModelPath, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}">
<Run Text="« " /><Run Text="{Binding Placeholder}" /><Run Text=" »" />
</TextBlock>
</Grid>
<TextBlock FontStyle="Italic"
Visibility="{Binding IsValid, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
« Invalid »
</TextBlock>
</Grid>
</Button>
</StackPanel>
</UserControl>
@@ -1,29 +0,0 @@
using System.Windows;
using System.Windows.Controls;
namespace Artemis.UI.Shared.Input
{
/// <summary>
/// Interaction logic for DataModelDynamicView.xaml
/// </summary>
public partial class DataModelDynamicView : UserControl
{
/// <summary>
/// Creates a new instance of the <see cref="DataModelDynamicView" /> class
/// </summary>
public DataModelDynamicView()
{
InitializeComponent();
}
private void PropertyButton_OnClick(object sender, RoutedEventArgs e)
{
// DataContext is not set when using left button, I don't know why but there it is
if (sender is Button button && button.ContextMenu != null)
{
button.ContextMenu.DataContext = button.DataContext;
button.ContextMenu.IsOpen = true;
}
}
}
}
@@ -1,387 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Timers;
using System.Windows.Media;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Artemis.UI.Shared.Services;
using MaterialDesignColors.ColorManipulation;
using Stylet;
namespace Artemis.UI.Shared.Input
{
/// <summary>
/// Represents a view model that allows selecting a data model property used by boolean operations on a certain data
/// model property
/// </summary>
public class DataModelDynamicViewModel : PropertyChangedBase, IDisposable
{
private readonly List<Module> _modules;
private readonly IDataModelUIService _dataModelUIService;
private readonly Timer _updateTimer;
private SolidColorBrush _buttonBrush = new(Color.FromRgb(171, 71, 188));
private DataModelPath? _dataModelPath;
private DataModelPropertiesViewModel? _dataModelViewModel;
private bool _displaySwitchButton;
private Type[] _filterTypes = Array.Empty<Type>();
private bool _isDataModelViewModelOpen;
private bool _isEnabled = true;
private string _placeholder = "Select a property";
private readonly PluginSetting<bool> _showFullPath;
internal DataModelDynamicViewModel(List<Module> modules, ISettingsService settingsService, IDataModelUIService dataModelUIService)
{
_modules = modules;
_dataModelUIService = dataModelUIService;
_updateTimer = new Timer(500);
_showFullPath = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true);
ExtraDataModelViewModels = new BindableCollection<DataModelPropertiesViewModel>();
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
SelectPropertyCommand = new DelegateCommand(ExecuteSelectPropertyCommand);
Initialize();
}
/// <summary>
/// Gets or sets the brush to use for the input button
/// </summary>
public SolidColorBrush ButtonBrush
{
get => _buttonBrush;
set
{
if (!SetAndNotify(ref _buttonBrush, value)) return;
NotifyOfPropertyChange(nameof(SwitchButtonBrush));
}
}
/// <summary>
/// Gets the brush to use for the switch button
/// </summary>
public SolidColorBrush SwitchButtonBrush => new(ButtonBrush.Color.Darken());
/// <summary>
/// Gets or sets the placeholder text when no value is entered
/// </summary>
public string Placeholder
{
get => _placeholder;
set => SetAndNotify(ref _placeholder, value);
}
/// <summary>
/// Gets or sets the enabled state of the input
/// </summary>
public bool IsEnabled
{
get => _isEnabled;
set => SetAndNotify(ref _isEnabled, value);
}
/// <summary>
/// Gets or sets whether the switch button should be displayed
/// </summary>
public bool DisplaySwitchButton
{
get => _displaySwitchButton;
set => SetAndNotify(ref _displaySwitchButton, value);
}
/// <summary>
/// Gets or sets the types of properties this view model will allow to be selected
/// </summary>
public Type[] FilterTypes
{
get => _filterTypes;
set
{
if (!SetAndNotify(ref _filterTypes, value)) return;
DataModelViewModel?.ApplyTypeFilter(true, FilterTypes);
}
}
/// <summary>
/// Gets a bindable collection of extra data model view models to show
/// </summary>
public BindableCollection<DataModelPropertiesViewModel> ExtraDataModelViewModels { get; }
/// <summary>
/// Gets a boolean indicating whether there are any modules providing data models
/// </summary>
public bool HasNoModules => (DataModelViewModel == null || !DataModelViewModel.Children.Any()) && !HasExtraDataModels;
/// <summary>
/// Gets a boolean indicating whether there are any extra data models
/// </summary>
public bool HasExtraDataModels => ExtraDataModelViewModels.Any();
/// <summary>
/// Command used by view
/// </summary>
public DelegateCommand SelectPropertyCommand { get; }
/// <summary>
/// Setting used by view
/// </summary>
public PluginSetting<bool> ShowDataModelValues { get; }
public PluginSetting<bool> ShowFullPath { get; }
/// <summary>
/// Gets or sets root the data model view model
/// </summary>
public DataModelPropertiesViewModel? DataModelViewModel
{
get => _dataModelViewModel;
private set => SetAndNotify(ref _dataModelViewModel, value);
}
/// <summary>
/// Gets or sets a boolean indicating whether the data model is open
/// </summary>
public bool IsDataModelViewModelOpen
{
get => _isDataModelViewModelOpen;
set
{
if (!SetAndNotify(ref _isDataModelViewModelOpen, value)) return;
if (value)
{
UpdateDataModelVisualization();
if (DataModelViewModel != null)
OpenSelectedValue(DataModelViewModel);
}
}
}
/// <summary>
/// Gets or sets the data model path of the currently selected data model property
/// </summary>
public DataModelPath? DataModelPath
{
get => _dataModelPath;
private set
{
if (!SetAndNotify(ref _dataModelPath, value)) return;
NotifyOfPropertyChange(nameof(IsValid));
NotifyOfPropertyChange(nameof(DisplayValue));
NotifyOfPropertyChange(nameof(DisplayPath));
}
}
/// <summary>
/// Gets a boolean indicating whether the current selection is valid
/// </summary>
public bool IsValid => DataModelPath?.IsValid ?? true;
/// <summary>
/// Gets the display name of the currently selected property
/// </summary>
public string? DisplayValue
{
get
{
if (_showFullPath.Value)
return DisplayPath;
return DataModelPath?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier;
}
}
/// <summary>
/// Gets the human readable path of the currently selected property
/// </summary>
public string DisplayPath
{
get
{
if (DataModelPath == null)
return "Click to select a property";
if (!DataModelPath.IsValid)
return "Invalid path";
return string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription()!= null).Select(s => s.GetPropertyDescription()!.Name));
}
}
/// <summary>
/// Gets or sets a boolean indicating whether event child VMs should be loaded, defaults to <see langword="true" />
/// </summary>
public bool LoadEventChildren { get; set; } = true;
/// <summary>
/// Changes the root data model VM stored in <see cref="DataModelViewModel" /> to the provided
/// <paramref name="dataModel" />
/// </summary>
/// <param name="dataModel">The data model VM to set the new root data model to</param>
public void ChangeDataModel(DataModelPropertiesViewModel dataModel)
{
if (DataModelViewModel != null)
DataModelViewModel.UpdateRequested -= DataModelOnUpdateRequested;
DataModelViewModel = dataModel;
if (DataModelViewModel != null)
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
}
/// <summary>
/// Changes the currently selected property by its path
/// </summary>
/// <param name="dataModelPath">The path of the property to set the selection to</param>
public void ChangeDataModelPath(DataModelPath? dataModelPath)
{
DataModelPath?.Dispose();
DataModelPath = dataModelPath != null ? new DataModelPath(dataModelPath) : null;
}
/// <summary>
/// Requests switching the input type to static using a <see cref="DataModelStaticViewModel" />
/// </summary>
public void SwitchToStatic()
{
ChangeDataModelPath(null);
OnPropertySelected(new DataModelInputDynamicEventArgs(null));
OnSwitchToStaticRequested();
}
private void Initialize()
{
// Get the data models
DataModelViewModel = _dataModelUIService.GetPluginDataModelVisualization(_modules, true);
if (DataModelViewModel != null)
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
ExtraDataModelViewModels.CollectionChanged += ExtraDataModelViewModelsOnCollectionChanged;
_updateTimer.Start();
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
_showFullPath.SettingChanged += ShowFullPathOnSettingChanged;
}
private void ExecuteSelectPropertyCommand(object? context)
{
if (context is not DataModelVisualizationViewModel selected)
return;
ChangeDataModelPath(selected.DataModelPath);
OnPropertySelected(new DataModelInputDynamicEventArgs(DataModelPath));
}
#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)
{
_updateTimer.Stop();
_updateTimer.Dispose();
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
_showFullPath.SettingChanged -= ShowFullPathOnSettingChanged;
DataModelViewModel?.Dispose();
DataModelPath?.Dispose();
}
}
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region Event handlers
private void DataModelOnUpdateRequested(object? sender, EventArgs e)
{
DataModelViewModel?.ApplyTypeFilter(true, FilterTypes);
foreach (DataModelPropertiesViewModel extraDataModelViewModel in ExtraDataModelViewModels)
extraDataModelViewModel.ApplyTypeFilter(true, FilterTypes);
}
private void ExtraDataModelViewModelsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
NotifyOfPropertyChange(nameof(HasExtraDataModels));
}
private void OnUpdateTimerOnElapsed(object? sender, ElapsedEventArgs e)
{
if (!IsDataModelViewModelOpen)
return;
UpdateDataModelVisualization();
}
private void UpdateDataModelVisualization()
{
DataModelViewModel?.Update(_dataModelUIService, new DataModelUpdateConfiguration(LoadEventChildren));
foreach (DataModelPropertiesViewModel extraDataModelViewModel in ExtraDataModelViewModels)
extraDataModelViewModel.Update(_dataModelUIService, new DataModelUpdateConfiguration(LoadEventChildren));
}
private void OpenSelectedValue(DataModelVisualizationViewModel dataModelPropertiesViewModel)
{
if (DataModelPath == null)
return;
if (dataModelPropertiesViewModel.Children.Any(c => c.DataModelPath != null && DataModelPath.Path.StartsWith(c.DataModelPath.Path)))
{
dataModelPropertiesViewModel.IsVisualizationExpanded = true;
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in dataModelPropertiesViewModel.Children)
{
OpenSelectedValue(dataModelVisualizationViewModel);
}
}
}
private void ShowFullPathOnSettingChanged(object? sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(DisplayValue));
}
#endregion
#region Events
/// <summary>
/// Occurs when anew property has been selected
/// </summary>
public event EventHandler<DataModelInputDynamicEventArgs>? PropertySelected;
/// <summary>
/// Occurs when a switch to static input has been requested
/// </summary>
public event EventHandler? SwitchToStaticRequested;
/// <summary>
/// Invokes the <see cref="PropertySelected" /> event
/// </summary>
/// <param name="e"></param>
protected virtual void OnPropertySelected(DataModelInputDynamicEventArgs e)
{
PropertySelected?.Invoke(this, e);
}
/// <summary>
/// Invokes the <see cref="SwitchToStaticRequested" /> event
/// </summary>
protected virtual void OnSwitchToStaticRequested()
{
SwitchToStaticRequested?.Invoke(this, EventArgs.Empty);
}
#endregion
}
}
@@ -1,80 +0,0 @@
<UserControl x:Class="Artemis.UI.Shared.Input.DataModelStaticView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:input="clr-namespace:Artemis.UI.Shared.Input"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:shared="clr-namespace:Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance input:DataModelStaticViewModel}">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DataModelConditions.xaml" />
<ResourceDictionary>
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<Style x:Key="DataModelConditionButtonCornerToggle" BasedOn="{StaticResource DataModelConditionButton}" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding DisplaySwitchButton}" Value="True">
<Setter Property="materialDesign:ButtonAssist.CornerRadius" Value="0 2 2 0" />
</DataTrigger>
<DataTrigger Binding="{Binding DisplaySwitchButton}" Value="False">
<Setter Property="materialDesign:ButtonAssist.CornerRadius" Value="2" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<StackPanel Orientation="Horizontal" Visibility="{Binding InputViewModel, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}">
<Button Style="{StaticResource MaterialDesignFlatDarkBgButton}"
Background="{Binding SwitchButtonBrush}"
BorderBrush="{Binding SwitchButtonBrush}"
Height="22"
Padding="0"
Width="22"
FontSize="12"
materialDesign:ButtonAssist.CornerRadius="2 0 0 2"
Margin="3 0 -3 0"
HorizontalAlignment="Left"
ToolTip="Switch to data model value"
Command="{s:Action SwitchToDynamic}"
Visibility="{Binding DisplaySwitchButton, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
<materialDesign:PackIcon Kind="SwapHorizontal" />
</Button>
<Button Style="{StaticResource DataModelConditionButtonCornerToggle}"
Background="{Binding ButtonBrush}"
BorderBrush="{Binding ButtonBrush}"
Command="{s:Action ActivateInputViewModel}"
HorizontalAlignment="Left"
IsEnabled="{Binding IsEnabled}"
ToolTip="Click to edit value">
<Grid>
<StackPanel Visibility="{Binding Value, Converter={StaticResource NullToVisibilityConverter}}" Orientation="Horizontal">
<ContentControl s:View.Model="{Binding DisplayViewModel}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</StackPanel>
<TextBlock FontStyle="Italic" Visibility="{Binding Value, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}">
<Run Text="« " /><Run Text="{Binding Placeholder}" /><Run Text=" »" />
</TextBlock>
</Grid>
</Button>
</StackPanel>
<Border BorderBrush="{Binding ButtonBrush}"
Background="{DynamicResource MaterialDesignPaper}"
Visibility="{Binding InputViewModel, Converter={StaticResource NullToVisibilityConverter}}"
CornerRadius="3"
Padding="3"
Margin="0 -3"
HorizontalAlignment="Left"
MinWidth="140">
<ContentControl s:View.Model="{Binding InputViewModel}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</Border>
</Grid>
</UserControl>
@@ -1,285 +0,0 @@
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.UI.Shared.Services;
using MaterialDesignColors.ColorManipulation;
using Stylet;
namespace Artemis.UI.Shared.Input
{
/// <summary>
/// Represents a view model that allows inputting a static value used by boolean operations on a certain data model
/// property
/// </summary>
public class DataModelStaticViewModel : PropertyChangedBase, IDisposable
{
private readonly IDataModelUIService _dataModelUIService;
private readonly Window? _rootView;
private SolidColorBrush _buttonBrush = new(Color.FromRgb(171, 71, 188));
private bool _displaySwitchButton;
private DataModelDisplayViewModel? _displayViewModel;
private DataModelInputViewModel? _inputViewModel;
private bool _isEnabled;
private string _placeholder = "Enter a value";
private DataModelPropertyAttribute _targetDescription;
private Type _targetType;
private object? _value;
internal DataModelStaticViewModel(Type targetType, DataModelPropertyAttribute targetDescription, IDataModelUIService dataModelUIService)
{
_dataModelUIService = dataModelUIService;
_rootView = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
_targetType = targetType;
_targetDescription = targetDescription;
_isEnabled = TargetType != null;
_displayViewModel = _dataModelUIService.GetDataModelDisplayViewModel(TargetType ?? typeof(object), TargetDescription, true);
if (_rootView != null)
{
_rootView.MouseUp += RootViewOnMouseUp;
_rootView.KeyUp += RootViewOnKeyUp;
}
}
/// <summary>
/// Gets or sets the brush to use for the input button
/// </summary>
public SolidColorBrush ButtonBrush
{
get => _buttonBrush;
set
{
if (!SetAndNotify(ref _buttonBrush, value)) return;
NotifyOfPropertyChange(nameof(SwitchButtonBrush));
}
}
/// <summary>
/// Gets the brush to use for the switch button
/// </summary>
public SolidColorBrush SwitchButtonBrush => new(ButtonBrush.Color.Darken());
/// <summary>
/// Gets the view model used to display the value
/// </summary>
public DataModelDisplayViewModel? DisplayViewModel
{
get => _displayViewModel;
private set => SetAndNotify(ref _displayViewModel, value);
}
/// <summary>
/// Gets the view model used to edit the value
/// </summary>
public DataModelInputViewModel? InputViewModel
{
get => _inputViewModel;
private set => SetAndNotify(ref _inputViewModel, value);
}
/// <summary>
/// Gets the type of the target property
/// </summary>
public Type TargetType
{
get => _targetType;
private set => SetAndNotify(ref _targetType, value);
}
/// <summary>
/// Gets the description of the target property
/// </summary>
public DataModelPropertyAttribute TargetDescription
{
get => _targetDescription;
set => SetAndNotify(ref _targetDescription, value);
}
/// <summary>
/// Gets or sets the value of the target
/// </summary>
public object? Value
{
get => _value;
set
{
if (!SetAndNotify(ref _value, value)) return;
DisplayViewModel?.UpdateValue(_value);
}
}
/// <summary>
/// Gets or sets the placeholder text when no value is entered
/// </summary>
public string Placeholder
{
get => _placeholder;
set => SetAndNotify(ref _placeholder, value);
}
/// <summary>
/// Gets or sets the enabled state of the input
/// </summary>
public bool IsEnabled
{
get => _isEnabled;
private set => SetAndNotify(ref _isEnabled, value);
}
/// <summary>
/// Gets or sets whether the switch button should be displayed
/// </summary>
public bool DisplaySwitchButton
{
get => _displaySwitchButton;
set => SetAndNotify(ref _displaySwitchButton, value);
}
/// <summary>
/// Activates the input view model
/// </summary>
public void ActivateInputViewModel()
{
InputViewModel = _dataModelUIService.GetDataModelInputViewModel(
TargetType,
TargetDescription,
Value,
ApplyFreeInput
);
}
/// <summary>
/// Updates the target type
/// </summary>
/// <param name="target">The new target type</param>
public void UpdateTargetType(Type target)
{
TargetType = target;
DisplayViewModel = _dataModelUIService.GetDataModelDisplayViewModel(TargetType ?? typeof(object), TargetDescription, true);
IsEnabled = TargetType != null;
// If null, clear the input
if (TargetType == null)
{
ApplyFreeInput(null, true);
return;
}
// If the type changed, reset to the default type
if (Value == null || !TargetType.IsCastableFrom(Value.GetType()))
// Force the VM to close if it was open and apply the new value
ApplyFreeInput(TargetType.GetDefault(), true);
}
/// <summary>
/// Requests switching the input type to dynamic using a <see cref="DataModelDynamicViewModel"/>
/// </summary>
public void SwitchToDynamic()
{
InputViewModel?.Cancel();
ApplyFreeInput(TargetType.GetDefault(), true);
OnSwitchToDynamicRequested();
}
private void ApplyFreeInput(object? value, bool submitted)
{
if (submitted)
OnValueUpdated(new DataModelInputStaticEventArgs(value));
InputViewModel = null;
Value = value;
}
#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)
{
if (_rootView != null)
{
_rootView.MouseUp -= RootViewOnMouseUp;
_rootView.KeyUp -= RootViewOnKeyUp;
}
}
}
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region Event handlers
private void RootViewOnKeyUp(object sender, KeyEventArgs e)
{
if (InputViewModel == null)
return;
if (e.Key == Key.Escape)
InputViewModel.Cancel();
else if (e.Key == Key.Enter)
InputViewModel.Submit();
}
private void RootViewOnMouseUp(object sender, MouseButtonEventArgs e)
{
if (InputViewModel == null)
return;
if (sender is FrameworkElement frameworkElement && !frameworkElement.IsDescendantOf(InputViewModel.View))
InputViewModel.Submit();
}
#endregion
#region Events
/// <summary>
/// Occurs when the value of the property has been updated
/// </summary>
public event EventHandler<DataModelInputStaticEventArgs>? ValueUpdated;
/// <summary>
/// Occurs when a switch to dynamic input has been requested
/// </summary>
public event EventHandler? SwitchToDynamicRequested;
/// <summary>
/// Invokes the <see cref="ValueUpdated" /> event
/// </summary>
/// <param name="e"></param>
protected virtual void OnValueUpdated(DataModelInputStaticEventArgs e)
{
ValueUpdated?.Invoke(this, e);
}
/// <summary>
/// Invokes the <see cref="SwitchToDynamicRequested" /> event
/// </summary>
protected virtual void OnSwitchToDynamicRequested()
{
SwitchToDynamicRequested?.Invoke(this, EventArgs.Empty);
}
#endregion
}
}
@@ -11,15 +11,12 @@ namespace Artemis.UI.Shared
/// </summary>
public class DataModelListPropertiesViewModel : DataModelPropertiesViewModel
{
private readonly ListPredicateWrapperDataModel _listPredicateWrapper;
private object? _displayValue;
private int _index;
private Type? _listType;
internal DataModelListPropertiesViewModel(Type listType, string? name) : base(null, null, null)
{
_listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType, name);
DataModel = _listPredicateWrapper;
ListType = listType;
}
@@ -61,8 +58,6 @@ namespace Artemis.UI.Shared
/// <inheritdoc />
public override void Update(IDataModelUIService dataModelUIService, DataModelUpdateConfiguration? configuration)
{
_listPredicateWrapper.UntypedValue = DisplayValue;
PopulateProperties(dataModelUIService, configuration);
if (DisplayViewModel == null)
return;
@@ -10,22 +10,17 @@ namespace Artemis.UI.Shared
/// </summary>
public class DataModelListPropertyViewModel : DataModelPropertyViewModel
{
private readonly ListPredicateWrapperDataModel _listPredicateWrapper;
private int _index;
private Type? _listType;
internal DataModelListPropertyViewModel(Type listType, DataModelDisplayViewModel displayViewModel, string? name) : base(null, null, null)
{
_listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType, name);
DataModel = _listPredicateWrapper;
ListType = listType;
DisplayViewModel = displayViewModel;
}
internal DataModelListPropertyViewModel(Type listType, string? name) : base(null, null, null)
{
_listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType, name);
DataModel = _listPredicateWrapper;
ListType = listType;
}
@@ -60,8 +55,6 @@ namespace Artemis.UI.Shared
if (DisplayValue == null)
return;
_listPredicateWrapper.UntypedValue = DisplayValue;
if (DisplayViewModel == null)
DisplayViewModel = dataModelUIService.GetDataModelDisplayViewModel(DisplayValue.GetType(), PropertyDescription, true);
@@ -1,21 +0,0 @@
using System;
using Artemis.UI.Shared.Input;
namespace Artemis.UI.Shared
{
/// <summary>
/// Provides data about submit events raised by <see cref="DataModelStaticViewModel" />
/// </summary>
public class DataModelInputStaticEventArgs : EventArgs
{
internal DataModelInputStaticEventArgs(object? value)
{
Value = value;
}
/// <summary>
/// The value that was submitted
/// </summary>
public object? Value { get; }
}
}
@@ -1,22 +1,22 @@
using System;
using Artemis.Core;
using Artemis.UI.Shared.Input;
using Artemis.UI.Shared.Controls;
namespace Artemis.UI.Shared
{
/// <summary>
/// Provides data about selection events raised by <see cref="DataModelDynamicViewModel" />
/// Provides data about selection events raised by <see cref="DataModelPicker" />
/// </summary>
public class DataModelInputDynamicEventArgs : EventArgs
public class DataModelSelectedEventArgs : EventArgs
{
internal DataModelInputDynamicEventArgs(DataModelPath? dataModelPath)
{
DataModelPath = dataModelPath;
}
/// <summary>
/// Gets the data model path that was selected
/// </summary>
public DataModelPath? DataModelPath { get; }
public DataModelPath? Path { get; }
internal DataModelSelectedEventArgs(DataModelPath? path)
{
Path = path;
}
}
}
@@ -1,46 +0,0 @@
using System.Linq;
using Artemis.Core;
using Artemis.UI.Shared.Services;
namespace Artemis.UI.Shared
{
/// <summary>
/// Provides extensions for special data model wrappers used by events and list conditions
/// </summary>
public static class DataModelWrapperExtensions
{
/// <summary>
/// Creates a view model for a <see cref="EventPredicateWrapperDataModel" />
/// </summary>
/// <param name="wrapper">The wrapper to create the view model for</param>
/// <param name="dataModelUIService">The data model UI service to be used by the view model</param>
/// <param name="configuration">The update configuration to be used by the view model</param>
/// <returns>The created view model</returns>
public static DataModelPropertiesViewModel CreateViewModel(this EventPredicateWrapperDataModel wrapper, IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
DataModelPropertiesViewModel viewModel = new(wrapper, null, new DataModelPath(wrapper));
viewModel.Update(dataModelUIService, configuration);
viewModel.UpdateRequested += (sender, args) => viewModel.Update(dataModelUIService, configuration);
viewModel.Children.First().IsVisualizationExpanded = true;
return viewModel;
}
/// <summary>
/// Creates a view model for a <see cref="ListPredicateWrapperDataModel" />
/// </summary>
/// <param name="wrapper">The wrapper to create the view model for</param>
/// <param name="dataModelUIService">The data model UI service to be used by the view model</param>
/// <param name="configuration">The update configuration to be used by the view model</param>
/// <returns>The created view model</returns>
public static DataModelPropertiesViewModel CreateViewModel(this ListPredicateWrapperDataModel wrapper, IDataModelUIService dataModelUIService, DataModelUpdateConfiguration configuration)
{
DataModelPropertiesViewModel viewModel = new(wrapper, null, new DataModelPath(wrapper));
viewModel.Update(dataModelUIService, configuration);
viewModel.UpdateRequested += (sender, args) => viewModel.Update(dataModelUIService, configuration);
viewModel.Children.First().IsVisualizationExpanded = true;
return viewModel;
}
}
}
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using Artemis.Core.Modules;
using Artemis.UI.Shared.Input;
namespace Artemis.UI.Shared
namespace Artemis.UI.Shared
{
/// <summary>
/// Represents a factory for view models provided by the Artemis Shared UI library
@@ -11,25 +6,4 @@ namespace Artemis.UI.Shared
public interface ISharedVmFactory
{
}
/// <summary>
/// A factory that allows the creation of data model view models
/// </summary>
public interface IDataModelVmFactory : ISharedVmFactory
{
/// <summary>
/// Creates a new instance of the <see cref="DataModelDynamicViewModel" /> class
/// </summary>
/// <param name="modules">The modules to associate the dynamic view model with</param>
/// <returns>A new instance of the <see cref="DataModelDynamicViewModel" /> class</returns>
DataModelDynamicViewModel DataModelDynamicViewModel(List<Module> modules);
/// <summary>
/// Creates a new instance of the <see cref="DataModelStaticViewModel" /> class
/// </summary>
/// <param name="targetType">The type of property that is expected in this input</param>
/// <param name="targetDescription">The description of the property that this input is for</param>
/// <returns>A new instance of the <see cref="DataModelStaticViewModel" /> class</returns>
DataModelStaticViewModel DataModelStaticViewModel(Type targetType, DataModelPropertyAttribute targetDescription);
}
}
@@ -5,7 +5,6 @@ using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Artemis.UI.Shared.DefaultTypes.DataModel.Display;
using Artemis.UI.Shared.Input;
using Ninject;
using Ninject.Parameters;
@@ -14,15 +13,13 @@ namespace Artemis.UI.Shared.Services
internal class DataModelUIService : IDataModelUIService
{
private readonly IDataModelService _dataModelService;
private readonly IDataModelVmFactory _dataModelVmFactory;
private readonly IKernel _kernel;
private readonly List<DataModelVisualizationRegistration> _registeredDataModelDisplays;
private readonly List<DataModelVisualizationRegistration> _registeredDataModelEditors;
public DataModelUIService(IDataModelService dataModelService, IDataModelVmFactory dataModelVmFactory, IKernel kernel)
public DataModelUIService(IDataModelService dataModelService, IKernel kernel)
{
_dataModelService = dataModelService;
_dataModelVmFactory = dataModelVmFactory;
_kernel = kernel;
_registeredDataModelEditors = new List<DataModelVisualizationRegistration>();
_registeredDataModelDisplays = new List<DataModelVisualizationRegistration>();
@@ -223,22 +220,7 @@ namespace Artemis.UI.Shared.Services
return null;
}
}
public DataModelDynamicViewModel GetDynamicSelectionViewModel(Module? module)
{
return _dataModelVmFactory.DataModelDynamicViewModel(module == null ? new List<Module>() : new List<Module> {module});
}
public DataModelDynamicViewModel GetDynamicSelectionViewModel(List<Module> modules)
{
return _dataModelVmFactory.DataModelDynamicViewModel(modules);
}
public DataModelStaticViewModel GetStaticInputViewModel(Type targetType, DataModelPropertyAttribute targetDescription)
{
return _dataModelVmFactory.DataModelStaticViewModel(targetType, targetDescription);
}
private DataModelInputViewModel InstantiateDataModelInputViewModel(DataModelVisualizationRegistration registration, DataModelPropertyAttribute? description, object? initialValue)
{
// This assumes the type can be converted, that has been checked when the VM was created
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.UI.Shared.Input;
namespace Artemis.UI.Shared.Services
{
@@ -103,27 +102,5 @@ namespace Artemis.UI.Shared.Services
/// <param name="updateCallback">A function to call whenever the input was updated (submitted or not)</param>
/// <returns>The most appropriate input view model for the provided <paramref name="propertyType" /></returns>
DataModelInputViewModel? GetDataModelInputViewModel(Type propertyType, DataModelPropertyAttribute? description, object? initialValue, Action<object?, bool> updateCallback);
/// <summary>
/// Creates a view model that allows selecting a value from the data model
/// </summary>
/// <param name="module">An extra non-always active module to include</param>
/// <returns></returns>
DataModelDynamicViewModel GetDynamicSelectionViewModel(Module? module);
/// <summary>
/// Creates a view model that allows selecting a value from the data model
/// </summary>
/// <param name="modules">A list of extra extra non-always active modules to include</param>
/// <returns>A view model that allows selecting a value from the data model</returns>
DataModelDynamicViewModel GetDynamicSelectionViewModel(List<Module> modules);
/// <summary>
/// Creates a view model that allows entering a value matching the target data model type
/// </summary>
/// <param name="targetType">The type of data model property to allow input for</param>
/// <param name="targetDescription">The description of the target data model property</param>
/// <returns>A view model that allows entering a value matching the target data model type</returns>
DataModelStaticViewModel GetStaticInputViewModel(Type targetType, DataModelPropertyAttribute targetDescription);
}
}