Data bindings - Added the option for different data binding modes

This commit is contained in:
Robert committed 2020-09-15 19:40:57 +02:00
1 parent 906efdac98
commit f270d786f0
32 files changed
+940 -497

No files matched your search

@@ -31,6 +31,29 @@
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="{StaticResource MaterialDesignCardBackground}">
<ContentControl s:View.Model="{Binding ActiveItem}" />
</ScrollViewer>
<materialDesign:Card
Visibility="{Binding DisplayStartHint, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"
VerticalAlignment="Top"
Background="{DynamicResource PrimaryHueDarkBrush}"
Foreground="{DynamicResource PrimaryHueDarkForegroundBrush}"
Margin="5 30 5 0"
Padding="8"
Width="315"
HorizontalAlignment="Left">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<materialDesign:PackIcon Kind="Redo" Margin="0 0 5 0">
<materialDesign:PackIcon.RenderTransform>
<RotateTransform Angle="225" CenterX="8" CenterY="8" />
</materialDesign:PackIcon.RenderTransform>
</materialDesign:PackIcon>
<TextBlock Grid.Column="1" VerticalAlignment="Center">Click the plus icon to start using display conditions!</TextBlock>
</Grid>
</materialDesign:Card>
</Grid>
<Grid Grid.Row="3">
@@ -0,0 +1,20 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.ConditionalDataBinding.ConditionalDataBindingModeView"
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:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Top" Margin="16">
<materialDesign:PackIcon Kind="Crane" Width="60" Height="60" HorizontalAlignment="Center" />
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" TextWrapping="Wrap" HorizontalAlignment="Center" Margin="0 25">
Conditional data bindings not yet implemented
</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" TextWrapping="Wrap" HorizontalAlignment="Center">
This is where you'd provide values and their conditions.. :>
</TextBlock>
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,28 @@
using Artemis.Core;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.ConditionalDataBinding
{
public class ConditionalDataBindingModeViewModel<TLayerProperty, TProperty> : Screen, IDataBindingModeViewModel
{
public ConditionalDataBindingModeViewModel(ConditionalDataBinding<TLayerProperty, TProperty> conditionalDataBinding)
{
ConditionalDataBinding = conditionalDataBinding;
}
public ConditionalDataBinding<TLayerProperty, TProperty> ConditionalDataBinding { get; }
public void Dispose()
{
}
public void Update()
{
}
public object GetTestValue()
{
return null;
}
}
}
@@ -17,152 +17,112 @@
</UserControl.Resources>
<ScrollViewer VerticalScrollBarVisibility="Auto">
<Grid Margin="10 0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.75*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Margin="0 5 5 0">
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="48" />
<RowDefinition Height="48" />
<RowDefinition Height="48" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="-3 0 0 0">
<Label FontSize="10" Foreground="{StaticResource MaterialDesignNavigationItemSubheader}" Margin="0 0 0 2">Source</Label>
<ContentControl s:View.Model="{Binding TargetSelectionViewModel}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
</StackPanel>
<materialDesign:Card Grid.Column="0"
UniformCornerRadius="0"
materialDesign:ShadowAssist.ShadowDepth="Depth3"
materialDesign:ShadowAssist.ShadowEdges="Right"
Background="{DynamicResource MaterialDesignPaper}"
Panel.ZIndex="2">
<Grid Margin="10 5" >
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="48" />
<RowDefinition Height="48" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ComboBox Grid.Row="1"
<ComboBox Grid.Row="0"
Style="{StaticResource MaterialDesignFloatingHintComboBox}"
materialDesign:HintAssist.Hint="Data binding mode"
MinWidth="128"
SelectedValue="{Binding SelectedDataBindingMode}" ItemsSource="{Binding DataBindingModes}" SelectedValuePath="Value" DisplayMemberPath="Description" >
</ComboBox>
SelectedValue="{Binding SelectedDataBindingMode}"
ItemsSource="{Binding DataBindingModes}"
SelectedValuePath="Value"
DisplayMemberPath="Description" >
</ComboBox>
<StackPanel Grid.Row="2">
<TextBox Style="{StaticResource MaterialDesignFloatingHintTextBox}"
<StackPanel Grid.Row="1">
<TextBox Style="{StaticResource MaterialDesignFloatingHintTextBox}"
Text="{Binding EasingTime}"
materialDesign:TextFieldAssist.HasClearButton="True"
materialDesign:TextFieldAssist.SuffixText="ms"
materialDesign:HintAssist.Hint="Easing time"
IsEnabled="{Binding IsDataBindingEnabled}" />
</StackPanel>
</StackPanel>
<ComboBox Grid.Row="3"
<ComboBox Grid.Row="2"
Style="{StaticResource MaterialDesignFloatingHintComboBox}"
materialDesign:HintAssist.Hint="Easing type"
MinWidth="128"
IsEnabled="{Binding IsEasingTimeEnabled}"
SelectedItem="{Binding SelectedEasingViewModel}"
ItemsSource="{Binding EasingViewModels}">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Polyline Stroke="{DynamicResource MaterialDesignBody}"
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Polyline Stroke="{DynamicResource MaterialDesignBody}"
StrokeThickness="1"
Points="{Binding EasingPoints}"
Stretch="Uniform"
Width="14"
Height="14"
Margin="0 0 10 0" />
<TextBlock Text="{Binding Description}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<materialDesign:Card Grid.Row="4" Grid.ColumnSpan="2" Margin="0 5 0 0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Margin="10 10 4 0">
Test result
</TextBlock>
<Separator Grid.Row="1" Style="{StaticResource MaterialDesignLightSeparator}" Margin="0" />
<Grid Grid.Row="2" Margin="10 4 10 10">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Margin="0 2">Input</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" Margin="0 2" FontFamily="Consolas" Text="{Binding TestInputValue}" />
<TextBlock Grid.Row="1" Grid.Column="0" Margin="0 2">Output</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" Margin="0 2" FontFamily="Consolas" Text="{Binding TestResultValue}" />
</Grid>
</Grid>
</materialDesign:Card>
</Grid>
<Grid Grid.Column="1">
<Grid Margin="5 26 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Style="{StaticResource MaterialDesignFlatMidBgButton}"
HorizontalAlignment="Left"
FontSize="12"
Padding="6 4"
Height="22"
IsEnabled="{Binding CanAddModifier}"
Command="{s:Action AddModifier}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Margin="0 -1 4 0" Kind="Plus" />
<TextBlock>
Add modifier
</TextBlock>
</StackPanel>
</Button>
<CheckBox Grid.Row="0"
Grid.Column="1"
Style="{StaticResource MaterialDesignCheckBox}"
HorizontalAlignment="Right"
VerticalAlignment="Top"
IsChecked="{Binding IsDataBindingEnabled}">
Enable data binding
</CheckBox>
<ListBox Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
ItemsSource="{Binding ModifierViewModels}"
materialDesign:RippleAssist.IsDisabled="True"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.UseDefaultDragAdorner="True"
dd:DragDrop.DropHandler="{Binding}"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
<TextBlock Text="{Binding Description}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ComboBox.ItemTemplate>
</ComboBox>
<materialDesign:Card Grid.Row="3" Grid.ColumnSpan="2" Margin="0 5 0 0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Margin="10 10 4 0">
Test result
</TextBlock>
<Separator Grid.Row="1" Style="{StaticResource MaterialDesignLightSeparator}" Margin="0" />
<Grid Grid.Row="2" Margin="10 4 10 10">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Margin="0 2">Input</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="1" Margin="0 2" FontFamily="Consolas" Text="{Binding TestInputValue}" />
<TextBlock Grid.Row="1" Grid.Column="0" Margin="0 2">Output</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="1" Margin="0 2" FontFamily="Consolas" Text="{Binding TestResultValue}" />
</Grid>
</Grid>
</materialDesign:Card>
</Grid>
</Grid>
</materialDesign:Card>
<materialDesign:Card Grid.Column="1" UniformCornerRadius="0" Background="{DynamicResource MaterialDesignToolBarBackground}" Panel.ZIndex="1">
<Grid Margin="10 5">
<ContentControl s:View.Model="{Binding ActiveItem, IsAsync=True}"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
IsTabStop="False"/>
</Grid>
</materialDesign:Card>
</Grid>
</ScrollViewer>
</UserControl>
@@ -4,38 +4,32 @@ using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Input;
using Artemis.UI.Shared.Services;
using Ninject.Planning.Targets;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
{
public class DataBindingViewModel<TLayerProperty, TProperty> : Screen, IDataBindingViewModel
public class DataBindingViewModel<TLayerProperty, TProperty> : Conductor<IDataBindingModeViewModel>, IDataBindingViewModel
{
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
private readonly IDataModelUIService _dataModelUIService;
private readonly IProfileEditorService _profileEditorService;
private DataBinding<TLayerProperty, TProperty> _dataBinding;
private int _easingTime;
private bool _isDataBindingEnabled;
private bool _isEasingTimeEnabled;
private DataBindingMode _selectedDataBindingMode;
private DataBindingModeType _selectedDataBindingMode;
private TimelineEasingViewModel _selectedEasingViewModel;
private DataModelDynamicViewModel _targetSelectionViewModel;
private TProperty _testInputValue;
private TProperty _testResultValue;
private bool _updating;
private bool _canAddModifier;
private bool _isDataBindingEnabled;
public DataBindingViewModel(DataBindingRegistration<TLayerProperty, TProperty> registration,
IProfileEditorService profileEditorService,
IDataModelUIService dataModelUIService,
IDataBindingsVmFactory dataBindingsVmFactory)
{
Registration = registration;
_profileEditorService = profileEditorService;
_dataModelUIService = dataModelUIService;
_dataBindingsVmFactory = dataBindingsVmFactory;
if (Registration.Member != null)
@@ -43,15 +37,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
else
DisplayName = Registration.LayerProperty.PropertyDescription.Name.ToUpper();
DataBindingModes = new BindableCollection<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(DataBindingMode)));
DataBindingModes = new BindableCollection<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(DataBindingModeType)));
EasingViewModels = new BindableCollection<TimelineEasingViewModel>();
ModifierViewModels = new BindableCollection<DataBindingModifierViewModel<TLayerProperty, TProperty>>();
DataBinding = Registration.DataBinding;
if (DataBinding != null)
DataBinding.ModifiersUpdated += DataBindingOnModifiersUpdated;
_isDataBindingEnabled = DataBinding != null;
Initialize();
}
@@ -60,12 +49,21 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
public BindableCollection<ValueDescription> DataBindingModes { get; }
public BindableCollection<TimelineEasingViewModel> EasingViewModels { get; }
public BindableCollection<DataBindingModifierViewModel<TLayerProperty, TProperty>> ModifierViewModels { get; }
public DataBindingMode SelectedDataBindingMode
public DataBindingModeType SelectedDataBindingMode
{
get => _selectedDataBindingMode;
set => SetAndNotify(ref _selectedDataBindingMode, value);
set
{
if (!SetAndNotify(ref _selectedDataBindingMode, value)) return;
ApplyDataBindingMode();
}
}
public bool IsDataBindingEnabled
{
get => _isDataBindingEnabled;
set => SetAndNotify(ref _isDataBindingEnabled, value);
}
public TimelineEasingViewModel SelectedEasingViewModel
@@ -98,39 +96,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
}
}
public DataModelDynamicViewModel TargetSelectionViewModel
{
get => _targetSelectionViewModel;
private set => SetAndNotify(ref _targetSelectionViewModel, value);
}
public bool IsDataBindingEnabled
{
get => _isDataBindingEnabled;
set
{
if (!SetAndNotify(ref _isDataBindingEnabled, value)) return;
if (value)
EnableDataBinding();
else
RemoveDataBinding();
}
}
public bool CanAddModifier
{
get => _canAddModifier;
private set => SetAndNotify(ref _canAddModifier, value);
}
public DataBinding<TLayerProperty, TProperty> DataBinding
{
get => _dataBinding;
set
{
if (!SetAndNotify(ref _dataBinding, value)) return;
UpdateModifierViewModels();
}
set => SetAndNotify(ref _dataBinding, value);
}
public TProperty TestInputValue
@@ -145,79 +114,70 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
set => SetAndNotify(ref _testResultValue, value);
}
public void EnableDataBinding()
public void Dispose()
{
if (DataBinding != null)
return;
DataBinding = Registration.LayerProperty.EnableDataBinding(Registration);
DataBinding.ModifiersUpdated += DataBindingOnModifiersUpdated;
Update();
_profileEditorService.UpdateSelectedProfileElement();
}
public void RemoveDataBinding()
{
if (DataBinding == null)
return;
var toDisable = DataBinding;
DataBinding = null;
Registration.LayerProperty.DisableDataBinding(toDisable);
toDisable.ModifiersUpdated -= DataBindingOnModifiersUpdated;
Update();
_profileEditorService.UpdateSelectedProfileElement();
}
public void AddModifier()
{
if (DataBinding == null)
return;
var modifier = new DataBindingModifier<TLayerProperty, TProperty>(DataBinding, ProfileRightSideType.Dynamic);
DataBinding.AddModifier(modifier);
_profileEditorService.UpdateSelectedProfileElement();
_profileEditorService.ProfilePreviewUpdated -= ProfileEditorServiceOnProfilePreviewUpdated;
}
private void Initialize()
{
EasingViewModels.AddRange(Enum.GetValues(typeof(Easings.Functions)).Cast<Easings.Functions>().Select(v => new TimelineEasingViewModel(v, false)));
TargetSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected;
_profileEditorService.ProfilePreviewUpdated += ProfileEditorServiceOnProfilePreviewUpdated;
CreateDataBindingModeModeViewModel();
Update();
}
private void CreateDataBindingModeModeViewModel()
{
if (DataBinding?.DataBindingMode == null)
{
ActiveItem = null;
return;
}
switch (DataBinding.DataBindingMode)
{
case DirectDataBinding<TLayerProperty, TProperty> directDataBinding:
ActiveItem = _dataBindingsVmFactory.DirectDataBindingModeViewModel(directDataBinding);
break;
case ConditionalDataBinding<TLayerProperty, TProperty> conditionalDataBinding:
ActiveItem = _dataBindingsVmFactory.ConditionalDataBindingModeViewModel(conditionalDataBinding);
break;
}
}
private void Update()
{
if (_updating)
return;
CanAddModifier = IsDataBindingEnabled && DataBinding.SourceDataModel != null;
if (DataBinding == null)
{
TargetSelectionViewModel.IsEnabled = false;
IsEasingTimeEnabled = false;
return;
}
_updating = true;
SelectedDataBindingMode = DataBinding.Mode;
IsDataBindingEnabled = ActiveItem != null;
EasingTime = (int) DataBinding.EasingTime.TotalMilliseconds;
SelectedEasingViewModel = EasingViewModels.First(vm => vm.EasingFunction == DataBinding.EasingFunction);
IsEasingTimeEnabled = EasingTime > 0;
switch (DataBinding.DataBindingMode)
{
case DirectDataBinding<TLayerProperty, TProperty> _:
SelectedDataBindingMode = DataBindingModeType.Direct;
break;
case ConditionalDataBinding<TLayerProperty, TProperty> _:
SelectedDataBindingMode = DataBindingModeType.Conditional;
break;
default:
SelectedDataBindingMode = DataBindingModeType.None;
break;
}
TargetSelectionViewModel.IsEnabled = true;
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataBinding.SourceDataModel, DataBinding.SourcePropertyPath);
TargetSelectionViewModel.FilterTypes = new[] {DataBinding.GetTargetType()};
UpdateModifierViewModels();
ActiveItem?.Update();
_updating = false;
}
@@ -229,7 +189,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
if (DataBinding != null)
{
DataBinding.Mode = SelectedDataBindingMode;
DataBinding.EasingTime = TimeSpan.FromMilliseconds(EasingTime);
DataBinding.EasingFunction = SelectedEasingViewModel?.EasingFunction ?? Easings.Functions.Linear;
}
@@ -238,6 +197,27 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
Update();
}
private void ApplyDataBindingMode()
{
if (_updating)
return;
if (DataBinding != null && SelectedDataBindingMode == DataBindingModeType.None)
{
RemoveDataBinding();
CreateDataBindingModeModeViewModel();
return;
}
if (DataBinding == null && SelectedDataBindingMode != DataBindingModeType.None)
EnableDataBinding();
DataBinding.ChangeDataBindingMode(SelectedDataBindingMode);
CreateDataBindingModeModeViewModel();
_profileEditorService.UpdateSelectedProfileElement();
}
private void UpdateTestResult()
{
if (DataBinding == null)
@@ -247,10 +227,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
return;
}
var currentValue = TargetSelectionViewModel.SelectedPropertyViewModel?.GetCurrentValue();
if (currentValue == null)
currentValue = default(TProperty);
var currentValue = ActiveItem?.GetTestValue() ?? default(TProperty);
TestInputValue = Registration.Converter.ConvertFromObject(currentValue);
if (DataBinding != null)
TestResultValue = DataBinding.GetValue(TestInputValue);
@@ -258,49 +236,31 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
TestInputValue = default;
}
private void UpdateModifierViewModels()
private void EnableDataBinding()
{
foreach (var dataBindingModifierViewModel in ModifierViewModels)
dataBindingModifierViewModel.Dispose();
ModifierViewModels.Clear();
if (DataBinding != null)
return;
DataBinding = Registration.LayerProperty.EnableDataBinding(Registration);
_profileEditorService.UpdateSelectedProfileElement();
}
private void RemoveDataBinding()
{
if (DataBinding == null)
return;
foreach (var dataBindingModifier in DataBinding.Modifiers)
ModifierViewModels.Add(_dataBindingsVmFactory.DataBindingModifierViewModel(dataBindingModifier));
}
private void ProfileEditorServiceOnProfilePreviewUpdated(object sender, EventArgs e)
{
UpdateTestResult();
}
private void DataBindingOnModifiersUpdated(object sender, EventArgs e)
{
UpdateModifierViewModels();
}
private void TargetSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
{
DataBinding.UpdateSource(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.PropertyPath);
var toDisable = DataBinding;
DataBinding = null;
Registration.LayerProperty.DisableDataBinding(toDisable);
Update();
_profileEditorService.UpdateSelectedProfileElement();
}
public void Dispose()
private void ProfileEditorServiceOnProfilePreviewUpdated(object sender, EventArgs e)
{
_profileEditorService.ProfilePreviewUpdated -= ProfileEditorServiceOnProfilePreviewUpdated;
TargetSelectionViewModel.PropertySelected -= TargetSelectionViewModelOnPropertySelected;
TargetSelectionViewModel.Dispose();
if (DataBinding != null)
DataBinding.ModifiersUpdated -= DataBindingOnModifiersUpdated;
foreach (var dataBindingModifierViewModel in ModifierViewModels)
dataBindingModifierViewModel.Dispose();
ModifierViewModels.Clear();
UpdateTestResult();
}
}
@@ -1,4 +1,4 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DataBindingModifierView"
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDataBinding.DataBindingModifierView"
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"
@@ -1,17 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDataBinding
{
/// <summary>
/// Interaction logic for DataBindingModifierView.xaml
@@ -7,7 +7,7 @@ using Artemis.UI.Shared.Input;
using Artemis.UI.Shared.Services;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDataBinding
{
public class DataBindingModifierViewModel<TLayerProperty, TProperty> : PropertyChangedBase, IDisposable
{
@@ -63,13 +63,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
public void Delete()
{
Modifier.DataBinding.RemoveModifier(Modifier);
Modifier.DirectDataBinding.RemoveModifier(Modifier);
}
public void SwapType()
{
if (Modifier.ParameterType == ProfileRightSideType.Dynamic)
Modifier.UpdateParameter(Modifier.DataBinding.GetSourceType().GetDefault());
Modifier.UpdateParameter(Modifier.DirectDataBinding.GetSourceType().GetDefault());
else
Modifier.UpdateParameter(null, null);
@@ -88,7 +88,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private void Update()
{
var sourceType = Modifier.DataBinding.GetSourceType();
var sourceType = Modifier.DirectDataBinding.GetSourceType();
if (sourceType == null)
throw new ArtemisUIException("Cannot use a data binding modifier VM for a data binding without a source");
@@ -0,0 +1,61 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDataBinding.DirectDataBindingModeView"
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:s="https://github.com/canton7/Stylet"
xmlns:dd="urn:gong-wpf-dragdrop"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Margin="5 10 0 0">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl Grid.Row="0"
s:View.Model="{Binding TargetSelectionViewModel}"
VerticalContentAlignment="Stretch"
HorizontalContentAlignment="Stretch"
IsTabStop="False" />
<Button Grid.Row="0"
Grid.Column="1"
Style="{StaticResource MaterialDesignFlatMidBgButton}"
HorizontalAlignment="Right"
FontSize="12"
Padding="6 4"
Height="22"
Command="{s:Action AddModifier}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Margin="0 -1 4 0" Kind="Plus" />
<TextBlock>
Add modifier
</TextBlock>
</StackPanel>
</Button>
<ListBox Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
ItemsSource="{Binding ModifierViewModels}"
materialDesign:RippleAssist.IsDisabled="True"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.UseDefaultDragAdorner="True"
dd:DragDrop.DropHandler="{Binding}"
HorizontalContentAlignment="Stretch"
Margin="0 5 0 0">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>
@@ -0,0 +1,118 @@
using System;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Input;
using Artemis.UI.Shared.Services;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.DirectDataBinding
{
public class DirectDataBindingModeViewModel<TLayerProperty, TProperty> : Screen, IDataBindingModeViewModel
{
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
private readonly IDataModelUIService _dataModelUIService;
private readonly IProfileEditorService _profileEditorService;
private DataModelDynamicViewModel _targetSelectionViewModel;
public DirectDataBindingModeViewModel(DirectDataBinding<TLayerProperty, TProperty> directDataBinding,
IProfileEditorService profileEditorService,
IDataModelUIService dataModelUIService,
IDataBindingsVmFactory dataBindingsVmFactory)
{
_profileEditorService = profileEditorService;
_dataModelUIService = dataModelUIService;
_dataBindingsVmFactory = dataBindingsVmFactory;
DirectDataBinding = directDataBinding;
ModifierViewModels = new BindableCollection<DataBindingModifierViewModel<TLayerProperty, TProperty>>();
Initialize();
}
public DirectDataBinding<TLayerProperty, TProperty> DirectDataBinding { get; }
public BindableCollection<DataBindingModifierViewModel<TLayerProperty, TProperty>> ModifierViewModels { get; }
public DataModelDynamicViewModel TargetSelectionViewModel
{
get => _targetSelectionViewModel;
private set => SetAndNotify(ref _targetSelectionViewModel, value);
}
public void Update()
{
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DirectDataBinding.SourceDataModel, DirectDataBinding.SourcePropertyPath);
TargetSelectionViewModel.FilterTypes = new[] {DirectDataBinding.DataBinding.GetTargetType()};
UpdateModifierViewModels();
}
public object GetTestValue()
{
return TargetSelectionViewModel.SelectedPropertyViewModel?.GetCurrentValue();
}
private void Initialize()
{
DirectDataBinding.ModifiersUpdated += DirectDataBindingOnModifiersUpdated;
TargetSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected;
Update();
}
#region Target
private void TargetSelectionViewModelOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
{
DirectDataBinding.UpdateSource(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.PropertyPath);
Update();
_profileEditorService.UpdateSelectedProfileElement();
}
#endregion
#region Modifiers
public void AddModifier()
{
DirectDataBinding.AddModifier(ProfileRightSideType.Dynamic);
_profileEditorService.UpdateSelectedProfileElement();
}
private void UpdateModifierViewModels()
{
foreach (var dataBindingModifierViewModel in ModifierViewModels)
dataBindingModifierViewModel.Dispose();
ModifierViewModels.Clear();
foreach (var dataBindingModifier in DirectDataBinding.Modifiers)
ModifierViewModels.Add(_dataBindingsVmFactory.DataBindingModifierViewModel(dataBindingModifier));
}
private void DirectDataBindingOnModifiersUpdated(object sender, EventArgs e)
{
UpdateModifierViewModels();
}
#endregion
#region IDisposable
public void Dispose()
{
TargetSelectionViewModel.PropertySelected -= TargetSelectionViewModelOnPropertySelected;
TargetSelectionViewModel.Dispose();
DirectDataBinding.ModifiersUpdated -= DirectDataBindingOnModifiersUpdated;
foreach (var dataBindingModifierViewModel in ModifierViewModels)
dataBindingModifierViewModel.Dispose();
ModifierViewModels.Clear();
}
#endregion
}
}
@@ -0,0 +1,11 @@
using System;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
{
public interface IDataBindingModeViewModel : IScreen, IDisposable
{
void Update();
object GetTestValue();
}
}
@@ -78,7 +78,7 @@
<!-- Left side -->
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="56" />
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
@@ -173,7 +173,7 @@
</materialDesign:TransitionerSlide.BackwardWipe>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="56" />
<RowDefinition Height="48" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
@@ -208,7 +208,7 @@
<!-- Timeline header body -->
<controls:PropertyTimelineHeader Margin="0 25 0 0"
<controls:PropertyTimelineHeader Margin="0 18 0 0"
Fill="{DynamicResource MaterialDesignBody}"
PixelsPerSecond="{Binding ProfileEditorService.PixelsPerSecond}"
HorizontalOffset="{Binding ContentHorizontalOffset, ElementName=TimelineHeaderScrollViewer}"
@@ -250,7 +250,7 @@
<materialDesign:TransitionerSlide.BackwardWipe>
<materialDesign:CircleWipe />
</materialDesign:TransitionerSlide.BackwardWipe>
<Grid Background="{StaticResource MaterialDesignPaper}">
<Grid Background="{StaticResource MaterialDesignCardBackground}">
<ContentControl s:View.Model="{Binding DataBindingsViewModel}" />
</Grid>
</materialDesign:TransitionerSlide>
@@ -29,6 +29,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
set => SetAndNotify(ref _isVisible, value);
}
public bool IsExpanded => false;
public void Dispose()
{
TreePropertyViewModel?.Dispose();
@@ -129,9 +129,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline.Controls
var typeFace = new Typeface(FontFamily, new FontStyle(), new FontWeight(), new FontStretch());
var formattedText = new FormattedText(text, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeFace, 9, Fill, null, VisualTreeHelper.GetDpi(this).PixelsPerDip);
if (x == 0 && OffsetFirstValue)
drawingContext.DrawText(formattedText, new Point(2, 2));
drawingContext.DrawText(formattedText, new Point(2, 5));
else
drawingContext.DrawText(formattedText, new Point(x - formattedText.Width / 2, 2));
drawingContext.DrawText(formattedText, new Point(x - formattedText.Width / 2, 5));
}
private void UpdateTimeScale()
@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Linq;
using Artemis.Core;
using Artemis.UI.Shared;
@@ -58,7 +59,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
}
#endregion
private void ApplyKeyframesEnabled(bool enable)
{
// If enabling keyframes for the first time, add a keyframe with the current value at the current position
@@ -95,8 +96,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
#endregion
}
public interface ITreePropertyViewModel : IScreen, IDisposable
public interface ITreePropertyViewModel : IScreen, INotifyPropertyChanged, IDisposable
{
bool HasPropertyInputViewModel { get; }
bool DataBindingsOpen { get; set; }
}
}
@@ -95,6 +95,11 @@
<Style TargetType="TreeViewItem" BasedOn="{StaticResource PropertyTreeStyle}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="Visibility" Value="{Binding IsVisible, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
<Style.Triggers>
<DataTrigger Binding="{Binding TreePropertyViewModel.DataBindingsOpen}" Value="True">
<Setter Property="Background" Value="{DynamicResource MaterialDesignPaper}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>