Profile editor - Finished most of the refactor except databindings

This commit is contained in:
SpoinkyNL committed 2020-09-14 01:24:07 +02:00
1 parent 7fff1a593f
commit fea454ad12
56 files changed
+866 -459

No files matched your search

@@ -11,8 +11,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
{
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
private readonly IProfileEditorService _profileEditorService;
private bool _alwaysFinishTimeline;
private bool _displayContinuously;
private RenderProfileElement _renderProfileElement;
private int _transitionerIndex;
@@ -37,20 +35,22 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
public bool DisplayContinuously
{
get => _displayContinuously;
get => RenderProfileElement?.DisplayContinuously ?? false;
set
{
if (!SetAndNotify(ref _displayContinuously, value)) return;
if (RenderProfileElement == null || RenderProfileElement.DisplayContinuously == value) return;
RenderProfileElement.DisplayContinuously = value;
_profileEditorService.UpdateSelectedProfileElement();
}
}
public bool AlwaysFinishTimeline
{
get => _alwaysFinishTimeline;
get => RenderProfileElement?.AlwaysFinishTimeline ?? false;
set
{
if (!SetAndNotify(ref _alwaysFinishTimeline, value)) return;
if (RenderProfileElement == null || RenderProfileElement.AlwaysFinishTimeline == value) return;
RenderProfileElement.AlwaysFinishTimeline = value;
_profileEditorService.UpdateSelectedProfileElement();
}
}
@@ -70,12 +70,9 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
{
RenderProfileElement = e.RenderProfileElement;
NotifyOfPropertyChange(nameof(ConditionBehaviourEnabled));
_displayContinuously = RenderProfileElement?.DisplayContinuously ?? false;
NotifyOfPropertyChange(nameof(DisplayContinuously));
_alwaysFinishTimeline = RenderProfileElement?.AlwaysFinishTimeline ?? false;
NotifyOfPropertyChange(nameof(AlwaysFinishTimeline));
NotifyOfPropertyChange(nameof(ConditionBehaviourEnabled));
if (e.RenderProfileElement == null)
{
@@ -4,14 +4,10 @@
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"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
xmlns:dd="urn:gong-wpf-dragdrop"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:DataBindingViewModel}">
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
@@ -36,7 +36,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
_dataModelUIService = dataModelUIService;
_dataBindingsVmFactory = dataBindingsVmFactory;
DisplayName = Registration.Property.Name.ToUpper();
if (Registration.Member != null)
DisplayName = Registration.Member.Name.ToUpper();
else
DisplayName = Registration.LayerProperty.PropertyDescription.Name.ToUpper();
DataBindingModes = new BindableCollection<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(DataBindingMode)));
EasingViewModels = new BindableCollection<TimelineEasingViewModel>();
@@ -203,7 +206,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
TargetSelectionViewModel.IsEnabled = true;
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataBinding.SourceDataModel, DataBinding.SourcePropertyPath);
TargetSelectionViewModel.FilterTypes = new[] {DataBinding.TargetProperty.PropertyType};
TargetSelectionViewModel.FilterTypes = new[] {DataBinding.GetTargetType()};
UpdateModifierViewModels();
@@ -225,11 +228,18 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private void UpdateTestResult()
{
if (DataBinding == null)
{
TestInputValue = default;
TestResultValue = default;
return;
}
var currentValue = TargetSelectionViewModel.SelectedPropertyViewModel?.GetCurrentValue();
if (currentValue == null && Registration.Property.PropertyType.IsValueType)
currentValue = Activator.CreateInstance(Registration.Property.PropertyType);
TestInputValue = currentValue is TProperty testInputValue ? testInputValue : default;
if (currentValue == null)
currentValue = default(TProperty);
TestInputValue = (TProperty) Convert.ChangeType(currentValue, typeof(TProperty));
if (DataBinding != null)
TestResultValue = DataBinding.GetValue(TestInputValue);
else
@@ -6,7 +6,7 @@
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<TabControl ItemsSource="{Binding Items}" DisplayMemberPath="DisplayName" Style="{StaticResource MaterialDesignTabControl}">
<TabControl ItemsSource="{Binding Items}" SelectedIndex="{Binding SelectedItemIndex}" DisplayMemberPath="DisplayName" Style="{StaticResource MaterialDesignTabControl}">
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}" TextElement.Foreground="{DynamicResource MaterialDesignBody}" />
@@ -9,6 +9,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
{
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
private readonly IProfileEditorService _profileEditorService;
private int _selectedItemIndex;
public DataBindingsViewModel(IProfileEditorService profileEditorService, IDataBindingsVmFactory dataBindingsVmFactory)
{
@@ -19,6 +20,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
CreateDataBindingViewModels();
}
public int SelectedItemIndex
{
get => _selectedItemIndex;
set => SetAndNotify(ref _selectedItemIndex, value);
}
private void CreateDataBindingViewModels()
{
Items.Clear();
@@ -33,6 +40,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
// and creating the actual data bindings
foreach (var registration in registrations)
ActivateItem(_dataBindingsVmFactory.DataBindingViewModel(registration));
SelectedItemIndex = 0;
}
protected override void OnClose()
@@ -23,7 +23,7 @@
Think of things like blur, black &amp; white but also audio visualization etc.
</TextBlock>
</StackPanel>
<ListBox ItemsSource="{Binding LayerEffectDescriptors}" SelectedItem="{Binding SelectedLayerEffectDescriptor}" HorizontalContentAlignment="Stretch"
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedLayerEffectDescriptor}" HorizontalContentAlignment="Stretch"
Visibility="{Binding HasLayerEffectDescriptors, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
@@ -310,7 +310,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
foreach (var layerEffect in SelectedProfileElement.LayerEffects)
{
if (LayerPropertyGroups.Any(l => l.LayerPropertyGroup.LayerEffect == layerEffect))
if (LayerPropertyGroups.Any(l => l.LayerPropertyGroup.LayerEffect == layerEffect) || layerEffect.BaseProperties == null)
continue;
// TODO: wat?
@@ -11,6 +11,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
public class LayerPropertyGroupViewModel : PropertyChangedBase, IDisposable
{
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
private bool _isVisible;
public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, ILayerPropertyVmFactory layerPropertyVmFactory)
{
@@ -21,6 +22,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
TreeGroupViewModel = layerPropertyVmFactory.TreeGroupViewModel(this);
TimelineGroupViewModel = layerPropertyVmFactory.TimelineGroupViewModel(this);
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
IsVisible = !LayerPropertyGroup.IsHidden;
PopulateChildren();
}
@@ -29,7 +34,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
public TimelineGroupViewModel TimelineGroupViewModel { get; }
public BindableCollection<PropertyChangedBase> Children { get; }
public bool IsVisible => !LayerPropertyGroup.IsHidden;
public bool IsVisible
{
get => _isVisible;
set => SetAndNotify(ref _isVisible, value);
}
public bool IsExpanded
{
@@ -41,6 +50,83 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
}
}
public void Dispose()
{
LayerPropertyGroup.VisibilityChanged -= LayerPropertyGroupOnVisibilityChanged;
foreach (var child in Children)
{
if (child is IDisposable disposableChild)
disposableChild.Dispose();
}
}
public void UpdateOrder(int order)
{
LayerPropertyGroup.LayerEffect.Order = order;
NotifyOfPropertyChange(nameof(IsExpanded));
}
public List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels(bool expandedOnly)
{
var result = new List<ITimelineKeyframeViewModel>();
if (expandedOnly && !IsExpanded)
return result;
foreach (var child in Children)
{
if (child is LayerPropertyViewModel layerPropertyViewModel)
result.AddRange(layerPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframeViewModels());
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
result.AddRange(layerPropertyGroupViewModel.GetAllKeyframeViewModels(expandedOnly));
}
return result;
}
/// <summary>
/// Removes the keyframes between the <paramref name="start" /> and <paramref name="end" /> position from this property
/// group
/// </summary>
/// <param name="start">The position at which to start removing keyframes, if null this will start at the first keyframe</param>
/// <param name="end">The position at which to start removing keyframes, if null this will end at the last keyframe</param>
public virtual void WipeKeyframes(TimeSpan? start, TimeSpan? end)
{
foreach (var child in Children)
{
if (child is LayerPropertyViewModel layerPropertyViewModel)
layerPropertyViewModel.TimelinePropertyViewModel.WipeKeyframes(start, end);
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
layerPropertyGroupViewModel.WipeKeyframes(start, end);
}
TimelineGroupViewModel.UpdateKeyframePositions();
}
/// <summary>
/// Shifts the keyframes between the <paramref name="start" /> and <paramref name="end" /> position by the provided
/// <paramref name="amount" />
/// </summary>
/// <param name="start">The position at which to start shifting keyframes, if null this will start at the first keyframe</param>
/// <param name="end">The position at which to start shifting keyframes, if null this will end at the last keyframe</param>
/// <param name="amount">The amount to shift the keyframes for</param>
public void ShiftKeyframes(TimeSpan? start, TimeSpan? end, TimeSpan amount)
{
foreach (var child in Children)
{
if (child is LayerPropertyViewModel layerPropertyViewModel)
layerPropertyViewModel.TimelinePropertyViewModel.ShiftKeyframes(start, end, amount);
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
layerPropertyGroupViewModel.ShiftKeyframes(start, end, amount);
}
TimelineGroupViewModel.UpdateKeyframePositions();
}
private void LayerPropertyGroupOnVisibilityChanged(object sender, EventArgs e)
{
IsVisible = !LayerPropertyGroup.IsHidden;
}
private void PopulateChildren()
{
// Get all properties and property groups and create VMs for them
@@ -66,70 +152,5 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
Children.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerPropertyGroup));
}
}
public void Dispose()
{
foreach (var child in Children)
{
if (child is IDisposable disposableChild)
disposableChild.Dispose();
}
}
public void UpdateOrder(int order)
{
LayerPropertyGroup.LayerEffect.Order = order;
NotifyOfPropertyChange(nameof(IsExpanded));
}
public List<ITimelineKeyframeViewModel> GetAllKeyframeViewModels(bool expandedOnly)
{
var result = new List<ITimelineKeyframeViewModel>();
if (expandedOnly == IsExpanded)
return result;
foreach (var child in Children)
{
if (child is LayerPropertyViewModel layerPropertyViewModel)
result.AddRange(layerPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframeViewModels());
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
result.AddRange(layerPropertyGroupViewModel.GetAllKeyframeViewModels(expandedOnly));
}
return result;
}
/// <summary>
/// Removes the keyframes between the <paramref name="start"/> and <paramref name="end"/> position from this property group
/// </summary>
/// <param name="start">The position at which to start removing keyframes, if null this will start at the first keyframe</param>
/// <param name="end">The position at which to start removing keyframes, if null this will end at the last keyframe</param>
public virtual void WipeKeyframes(TimeSpan? start, TimeSpan? end)
{
foreach (var child in Children)
{
if (child is LayerPropertyViewModel layerPropertyViewModel)
layerPropertyViewModel.TimelinePropertyViewModel.WipeKeyframes(start, end);
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
layerPropertyGroupViewModel.WipeKeyframes(start, end);
}
}
/// <summary>
/// Shifts the keyframes between the <paramref name="start"/> and <paramref name="end"/> position by the provided <paramref name="amount"/>
/// </summary>
/// <param name="start">The position at which to start shifting keyframes, if null this will start at the first keyframe</param>
/// <param name="end">The position at which to start shifting keyframes, if null this will end at the last keyframe</param>
/// <param name="amount">The amount to shift the keyframes for</param>
public void ShiftKeyframes(TimeSpan? start, TimeSpan? end, TimeSpan amount)
{
foreach (var child in Children)
{
if (child is LayerPropertyViewModel layerPropertyViewModel)
layerPropertyViewModel.TimelinePropertyViewModel.ShiftKeyframes(start, end, amount);
else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
layerPropertyGroupViewModel.ShiftKeyframes(start, end, amount);
}
}
}
}
@@ -3,14 +3,14 @@ using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline;
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree;
using Ninject;
using Ninject.Parameters;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
{
public class LayerPropertyViewModel : PropertyChangedBase, IDisposable
{
private bool _isVisible;
public LayerPropertyViewModel(ILayerProperty layerProperty, IPropertyVmFactory propertyVmFactory)
{
LayerProperty = layerProperty;
@@ -23,8 +23,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
public ITreePropertyViewModel TreePropertyViewModel { get; }
public ITimelinePropertyViewModel TimelinePropertyViewModel { get; }
public bool IsVisible => !LayerProperty.IsHidden;
public bool IsVisible
{
get => _isVisible;
set => SetAndNotify(ref _isVisible, value);
}
public void Dispose()
{
TreePropertyViewModel?.Dispose();
@@ -1,4 +1,5 @@
using System;
using System.ComponentModel;
using System.Linq;
using Artemis.Core;
using Artemis.UI.Shared.Services;
@@ -19,24 +20,17 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
KeyframePositions = new BindableCollection<double>();
_profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged;
LayerPropertyGroupViewModel.PropertyChanged += LayerPropertyGroupViewModelOnPropertyChanged;
UpdateKeyframePositions();
}
public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; }
public LayerPropertyGroup LayerPropertyGroup { get; }
public BindableCollection<double> KeyframePositions { get; }
public void Dispose()
{
_profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
}
private void ProfileEditorServiceOnPixelsPerSecondChanged(object? sender, EventArgs e)
{
UpdateKeyframePositions();
}
public void UpdateKeyframePositions()
{
KeyframePositions.Clear();
@@ -44,5 +38,30 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
.GetAllKeyframeViewModels(false)
.Select(p => p.Position.TotalSeconds * _profileEditorService.PixelsPerSecond));
}
#region IDisposable
public void Dispose()
{
_profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
LayerPropertyGroupViewModel.PropertyChanged -= LayerPropertyGroupViewModelOnPropertyChanged;
}
#endregion
#region Event handlers
private void LayerPropertyGroupViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(LayerPropertyGroupViewModel.IsExpanded))
UpdateKeyframePositions();
}
private void ProfileEditorServiceOnPixelsPerSecondChanged(object sender, EventArgs e)
{
UpdateKeyframePositions();
}
#endregion
}
}
@@ -20,16 +20,15 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
{
_profileEditorService = profileEditorService;
LayerPropertyKeyframe = layerPropertyKeyframe;
EasingViewModels = new BindableCollection<TimelineEasingViewModel>();
_profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged;
LayerPropertyKeyframe.PropertyChanged += LayerPropertyKeyframeOnPropertyChanged;
}
public LayerPropertyKeyframe<T> LayerPropertyKeyframe { get; }
public BindableCollection<TimelineEasingViewModel> EasingViewModels
{
get => _easingViewModels;
set => SetAndNotify(ref _easingViewModels, value);
}
public LayerPropertyKeyframe<T> LayerPropertyKeyframe { get; }
public BindableCollection<TimelineEasingViewModel> EasingViewModels { get; }
public double X
{
@@ -53,6 +52,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
public void Dispose()
{
_profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
LayerPropertyKeyframe.PropertyChanged -= LayerPropertyKeyframeOnPropertyChanged;
foreach (var timelineEasingViewModel in EasingViewModels)
@@ -65,6 +65,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
Timestamp = $"{Math.Floor(LayerPropertyKeyframe.Position.TotalSeconds):00}.{LayerPropertyKeyframe.Position.Milliseconds:000}";
}
private void ProfileEditorServiceOnPixelsPerSecondChanged(object? sender, EventArgs e)
{
Update();
}
private void LayerPropertyKeyframeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(LayerPropertyKeyframe.Position))
@@ -73,7 +78,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
#region Easing
public void CreateEasingViewModels()
public void PopulateEasingViewModels()
{
if (EasingViewModels.Any())
return;
@@ -86,6 +91,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
timelineEasingViewModel.EasingModeSelected += TimelineEasingViewModelOnEasingModeSelected;
}
public void ClearEasingViewModels()
{
EasingViewModels.Clear();
}
private void TimelineEasingViewModelOnEasingModeSelected(object sender, EventArgs e)
{
SelectEasingMode((TimelineEasingViewModel) sender);
@@ -150,18 +160,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
#region Context menu actions
public void ContextMenuOpening()
{
CreateEasingViewModels();
}
public void ContextMenuClosing()
{
foreach (var timelineEasingViewModel in EasingViewModels)
timelineEasingViewModel.EasingModeSelected -= TimelineEasingViewModelOnEasingModeSelected;
EasingViewModels.Clear();
}
public void Copy()
{
var newKeyframe = new LayerPropertyKeyframe<T>(
@@ -211,6 +209,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
#region Context menu actions
void PopulateEasingViewModels();
void ClearEasingViewModels();
void Copy();
void Delete();
@@ -38,7 +38,7 @@
MouseDown="{s:Action KeyframeMouseDown}"
MouseUp="{s:Action KeyframeMouseUp}"
MouseMove="{s:Action KeyframeMouseMove}"
ContextMenuOpening="{s:Action ContextMenuOpening}"
ContextMenuOpening="{s:Action ContextMenuOpening}"
ContextMenuClosing="{s:Action ContextMenuClosing}">
<Ellipse.Style>
<Style TargetType="{x:Type Ellipse}">
@@ -19,6 +19,25 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
LayerProperty = layerProperty;
LayerPropertyViewModel = layerPropertyViewModel;
LayerProperty.KeyframesToggled += LayerPropertyOnKeyframesToggled;
LayerProperty.KeyframeAdded += LayerPropertyOnKeyframeAdded;
LayerProperty.KeyframeRemoved += LayerPropertyOnKeyframeRemoved;
UpdateKeyframes();
}
private void LayerPropertyOnKeyframesToggled(object sender, LayerPropertyEventArgs<T> e)
{
UpdateKeyframes();
}
private void LayerPropertyOnKeyframeRemoved(object sender, LayerPropertyEventArgs<T> e)
{
UpdateKeyframes();
}
private void LayerPropertyOnKeyframeAdded(object sender, LayerPropertyEventArgs<T> e)
{
UpdateKeyframes();
}
@@ -55,8 +74,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
start ??= TimeSpan.Zero;
end ??= TimeSpan.MaxValue;
var toShift = LayerProperty.Keyframes.Where(k => k.Position >= start && k.Position <= end).ToList();
foreach (var keyframe in toShift)
var toShift = LayerProperty.Keyframes.Where(k => k.Position >= start && k.Position < end).ToList();
foreach (var keyframe in toShift)
LayerProperty.RemoveKeyframe(keyframe);
UpdateKeyframes();
@@ -67,7 +86,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
start ??= TimeSpan.Zero;
end ??= TimeSpan.MaxValue;
var toShift = LayerProperty.Keyframes.Where(k => k.Position >= start && k.Position <= end).ToList();
var toShift = LayerProperty.Keyframes.Where(k => k.Position >= start && k.Position < end).ToList();
foreach (var keyframe in toShift)
keyframe.Position += amount;
@@ -76,6 +95,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
public void Dispose()
{
LayerProperty.KeyframesToggled -= LayerPropertyOnKeyframesToggled;
LayerProperty.KeyframeAdded -= LayerPropertyOnKeyframeAdded;
LayerProperty.KeyframeRemoved -= LayerPropertyOnKeyframeRemoved;
}
}
@@ -17,6 +17,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
private bool _showDisableButton;
private bool _showRepeatButton;
private bool _showSegmentName;
private TimeSpan _segmentLength;
private double _segmentWidth;
private bool _segmentEnabled;
private double _segmentStartPosition;
public TimelineSegmentViewModel(SegmentViewModelType segment, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups,
IProfileEditorService profileEditorService)
@@ -24,55 +28,54 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
ProfileEditorService = profileEditorService;
Segment = segment;
LayerPropertyGroups = layerPropertyGroups;
SelectedProfileElement = ProfileEditorService.SelectedProfileElement;
switch (Segment)
{
case SegmentViewModelType.Start:
ToolTip = "This segment is played when a layer starts displaying because it's conditions are met";
break;
case SegmentViewModelType.Main:
ToolTip = "This segment is played while a condition is met, either once or on a repeating loop";
break;
case SegmentViewModelType.End:
ToolTip = "This segment is played once a condition is no longer met";
break;
default:
throw new ArgumentOutOfRangeException(nameof(segment));
}
if (Segment == SegmentViewModelType.Start)
ToolTip = "This segment is played when a layer starts displaying because it's conditions are met";
else if (Segment == SegmentViewModelType.Main)
ToolTip = "This segment is played while a condition is met, either once or on a repeating loop";
else if (Segment == SegmentViewModelType.End)
ToolTip = "This segment is played once a condition is no longer met";
IsMainSegment = Segment == SegmentViewModelType.Main;
UpdateDisplay();
ProfileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged;
ProfileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected;
if (ProfileEditorService.SelectedProfileElement != null)
ProfileEditorService.SelectedProfileElement.PropertyChanged += SelectedProfileElementOnPropertyChanged;
Update();
}
public RenderProfileElement SelectedProfileElement { get; }
public RenderProfileElement SelectedProfileElement => ProfileEditorService.SelectedProfileElement;
public SegmentViewModelType Segment { get; }
public BindableCollection<LayerPropertyGroupViewModel> LayerPropertyGroups { get; }
public IProfileEditorService ProfileEditorService { get; }
public string ToolTip { get; }
public bool IsMainSegment { get; }
public TimeSpan SegmentLength
{
get
{
return Segment switch
{
SegmentViewModelType.Start => SelectedProfileElement?.StartSegmentLength ?? TimeSpan.Zero,
SegmentViewModelType.Main => SelectedProfileElement?.MainSegmentLength ?? TimeSpan.Zero,
SegmentViewModelType.End => SelectedProfileElement?.EndSegmentLength ?? TimeSpan.Zero,
_ => throw new ArgumentOutOfRangeException()
};
}
get => _segmentLength;
set => SetAndNotify(ref _segmentLength, value);
}
public double SegmentWidth => ProfileEditorService.PixelsPerSecond * SegmentLength.TotalSeconds;
public double SegmentWidth
{
get => _segmentWidth;
set => SetAndNotify(ref _segmentWidth, value);
}
public bool SegmentEnabled => SegmentLength != TimeSpan.Zero;
public bool IsMainSegment => Segment == SegmentViewModelType.Main;
public double SegmentStartPosition
{
get => _segmentStartPosition;
set => SetAndNotify(ref _segmentStartPosition, value);
}
public bool SegmentEnabled
{
get => _segmentEnabled;
set => SetAndNotify(ref _segmentEnabled, value);
}
// Only the main segment supports this, for any other segment the getter always returns false and the setter does nothing
public bool RepeatSegment
@@ -95,23 +98,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
}
}
public double SegmentStartPosition
{
get
{
if (SelectedProfileElement == null)
return 0;
return Segment switch
{
SegmentViewModelType.Start => 0,
SegmentViewModelType.Main => ProfileEditorService.PixelsPerSecond * SelectedProfileElement.StartSegmentLength.TotalSeconds,
SegmentViewModelType.End => ProfileEditorService.PixelsPerSecond * (SelectedProfileElement.StartSegmentLength.TotalSeconds + SelectedProfileElement.MainSegmentLength.TotalSeconds),
_ => throw new ArgumentOutOfRangeException()
};
}
}
public bool ShowSegmentName
{
get => _showSegmentName;
@@ -130,14 +116,57 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
set => SetAndNotify(ref _showDisableButton, value);
}
public void Dispose()
#region Updating
private void UpdateHeader()
{
ProfileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
ProfileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
if (SelectedProfileElement != null)
SelectedProfileElement.PropertyChanged -= SelectedProfileElementOnPropertyChanged;
if (!IsMainSegment)
ShowSegmentName = SegmentWidth > 60;
else
ShowSegmentName = SegmentWidth > 80;
ShowRepeatButton = SegmentWidth > 45 && IsMainSegment;
ShowDisableButton = SegmentWidth > 25;
}
private void Update()
{
if (SelectedProfileElement == null)
{
SegmentLength = TimeSpan.Zero;
SegmentStartPosition = 0;
SegmentWidth = 0;
SegmentEnabled = false;
return;
}
if (Segment == SegmentViewModelType.Start)
{
SegmentLength = SelectedProfileElement.StartSegmentLength;
SegmentStartPosition = 0;
}
else if (Segment == SegmentViewModelType.Main)
{
SegmentLength = SelectedProfileElement.MainSegmentLength;
SegmentStartPosition = ProfileEditorService.PixelsPerSecond * SelectedProfileElement.StartSegmentLength.TotalSeconds;
}
else if (Segment == SegmentViewModelType.End)
{
SegmentLength = SelectedProfileElement.EndSegmentLength;
SegmentStartPosition = ProfileEditorService.PixelsPerSecond * (SelectedProfileElement.StartSegmentLength.TotalSeconds +
SelectedProfileElement.MainSegmentLength.TotalSeconds);
}
SegmentWidth = ProfileEditorService.PixelsPerSecond * SegmentLength.TotalSeconds;
SegmentEnabled = SegmentLength != TimeSpan.Zero;
UpdateHeader();
}
#endregion
#region Controls
public void DisableSegment()
{
var startSegmentEnd = SelectedProfileElement.StartSegmentLength;
@@ -164,9 +193,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
SelectedProfileElement.EndSegmentLength = TimeSpan.Zero;
}
NotifyOfPropertyChange(nameof(SegmentEnabled));
ShiftNextSegment(SegmentLength - oldSegmentLength);
ProfileEditorService.UpdateSelectedProfileElement();
Update();
}
public void EnableSegment()
@@ -179,23 +208,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
else if (Segment == SegmentViewModelType.End)
SelectedProfileElement.EndSegmentLength = TimeSpan.FromSeconds(1);
NotifyOfPropertyChange(nameof(SegmentEnabled));
ProfileEditorService.UpdateSelectedProfileElement();
UpdateDisplay();
Update();
}
public void ShiftNextSegment(TimeSpan amount)
{
var segmentEnd = TimeSpan.Zero;
if (Segment == SegmentViewModelType.Start)
segmentEnd = SelectedProfileElement.StartSegmentLength;
else if (Segment == SegmentViewModelType.Main)
segmentEnd = SelectedProfileElement.StartSegmentLength + SelectedProfileElement.MainSegmentLength;
else if (Segment == SegmentViewModelType.End)
segmentEnd = SelectedProfileElement.TimelineLength;
#endregion
ShiftKeyframes(segmentEnd, null, amount);
}
#region Mouse events
public void SegmentMouseDown(object sender, MouseButtonEventArgs e)
{
@@ -260,18 +279,34 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
SelectedProfileElement.EndSegmentLength = newTime - SelectedProfileElement.StartSegmentLength - SelectedProfileElement.MainSegmentLength;
}
NotifyOfPropertyChange(nameof(SegmentLength));
NotifyOfPropertyChange(nameof(SegmentWidth));
ShiftNextSegment(SegmentLength - oldSegmentLength);
UpdateDisplay();
Update();
}
#endregion
#region IDIsposable
public void Dispose()
{
ProfileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
ProfileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
if (SelectedProfileElement != null)
SelectedProfileElement.PropertyChanged -= SelectedProfileElementOnPropertyChanged;
}
#endregion
#region Event handlers
private void ProfileEditorServiceOnProfileElementSelected(object? sender, RenderProfileElementEventArgs e)
{
if (e.PreviousRenderProfileElement != null)
e.PreviousRenderProfileElement.PropertyChanged -= SelectedProfileElementOnPropertyChanged;
e.RenderProfileElement.PropertyChanged += SelectedProfileElementOnPropertyChanged;
if (e.RenderProfileElement != null)
e.RenderProfileElement.PropertyChanged += SelectedProfileElementOnPropertyChanged;
Update();
}
private void SelectedProfileElementOnPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -279,31 +314,29 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
if (e.PropertyName == nameof(RenderProfileElement.StartSegmentLength) ||
e.PropertyName == nameof(RenderProfileElement.MainSegmentLength) ||
e.PropertyName == nameof(RenderProfileElement.EndSegmentLength))
{
NotifyOfPropertyChange(nameof(SegmentStartPosition));
NotifyOfPropertyChange(nameof(SegmentWidth));
}
Update();
else if (e.PropertyName == nameof(RenderProfileElement.DisplayContinuously))
NotifyOfPropertyChange(nameof(RepeatSegment));
}
private void ProfileEditorServiceOnPixelsPerSecondChanged(object? sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(SegmentWidth));
NotifyOfPropertyChange(nameof(SegmentStartPosition));
UpdateDisplay();
Update();
}
private void UpdateDisplay()
{
if (!IsMainSegment)
ShowSegmentName = SegmentWidth > 60;
else
ShowSegmentName = SegmentWidth > 80;
#endregion
ShowRepeatButton = SegmentWidth > 45 && IsMainSegment;
ShowDisableButton = SegmentWidth > 25;
public void ShiftNextSegment(TimeSpan amount)
{
var segmentEnd = TimeSpan.Zero;
if (Segment == SegmentViewModelType.Start)
segmentEnd = SelectedProfileElement.StartSegmentLength;
else if (Segment == SegmentViewModelType.Main)
segmentEnd = SelectedProfileElement.StartSegmentLength + SelectedProfileElement.MainSegmentLength;
else if (Segment == SegmentViewModelType.End)
segmentEnd = SelectedProfileElement.TimelineLength;
ShiftKeyframes(segmentEnd, null, amount);
}
private void WipeKeyframes(TimeSpan? start, TimeSpan? end)
@@ -50,7 +50,7 @@
Y1="0"
Y2="{Binding ActualHeight, ElementName=TimelineContainerGrid}"
HorizontalAlignment="Left"
Visibility="{Binding StartSegmentEnabled, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
Visibility="{Binding LayerPropertiesViewModel.StartTimelineSegmentViewModel.SegmentEnabled, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<Line Stroke="{StaticResource PrimaryHueDarkBrush}"
Opacity="0.5"
StrokeDashArray="4 2"
@@ -65,7 +65,7 @@
X2="{Binding EndSegmentEndPosition}"
Y1="0"
Y2="{Binding ActualHeight, ElementName=TimelineContainerGrid}"
Visibility="{Binding EndSegmentEnabled, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
Visibility="{Binding LayerPropertiesViewModel.EndTimelineSegmentViewModel.SegmentEnabled, Converter={x:Static s:BoolToVisibilityConverter.Instance}}" />
<!-- Multi-selection rectangle -->
<Path x:Name="MultiSelectionPath"
@@ -15,15 +15,14 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
{
public class TimelineViewModel : Screen, IDisposable
{
private readonly LayerPropertiesViewModel _layerPropertiesViewModel;
private readonly IProfileEditorService _profileEditorService;
private RectangleGeometry _selectionRectangle;
public TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups, IProfileEditorService profileEditorService)
{
_layerPropertiesViewModel = layerPropertiesViewModel;
_profileEditorService = profileEditorService;
LayerPropertiesViewModel = layerPropertiesViewModel;
LayerPropertyGroups = layerPropertyGroups;
SelectionRectangle = new RectangleGeometry();
@@ -31,10 +30,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
_profileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected;
if (_profileEditorService.SelectedProfileElement != null)
_profileEditorService.SelectedProfileElement.PropertyChanged += SelectedProfileElementOnPropertyChanged;
Update();
}
public RenderProfileElement SelectedProfileElement => _profileEditorService.SelectedProfileElement;
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
public BindableCollection<LayerPropertyGroupViewModel> LayerPropertyGroups { get; }
public RectangleGeometry SelectionRectangle
@@ -43,68 +42,57 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
set => SetAndNotify(ref _selectionRectangle, value);
}
public double StartSegmentWidth => _profileEditorService.PixelsPerSecond * (SelectedProfileElement?.StartSegmentLength.TotalSeconds ?? 0);
public double StartSegmentEndPosition => StartSegmentWidth;
public double MainSegmentWidth => _profileEditorService.PixelsPerSecond * (SelectedProfileElement?.MainSegmentLength.TotalSeconds ?? 0);
public double MainSegmentEndPosition => StartSegmentWidth + MainSegmentWidth;
public double EndSegmentWidth => _profileEditorService.PixelsPerSecond * (SelectedProfileElement?.EndSegmentLength.TotalSeconds ?? 0);
public double EndSegmentEndPosition => StartSegmentWidth + MainSegmentWidth + EndSegmentWidth;
public double TotalTimelineWidth => _profileEditorService.PixelsPerSecond * (SelectedProfileElement?.TimelineLength.TotalSeconds ?? 0);
public bool StartSegmentEnabled => SelectedProfileElement?.StartSegmentLength != TimeSpan.Zero;
public bool EndSegmentEnabled => SelectedProfileElement?.EndSegmentLength != TimeSpan.Zero;
public void Dispose()
public double StartSegmentEndPosition
{
_profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
_profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
if (_profileEditorService.SelectedProfileElement != null)
_profileEditorService.SelectedProfileElement.PropertyChanged -= SelectedProfileElementOnPropertyChanged;
get => _startSegmentEndPosition;
set => SetAndNotify(ref _startSegmentEndPosition, value);
}
public double MainSegmentEndPosition
{
get => _mainSegmentEndPosition;
set => SetAndNotify(ref _mainSegmentEndPosition, value);
}
public double EndSegmentEndPosition
{
get => _endSegmentEndPosition;
set => SetAndNotify(ref _endSegmentEndPosition, value);
}
public double TotalTimelineWidth
{
get => _totalTimelineWidth;
set => SetAndNotify(ref _totalTimelineWidth, value);
}
private void Update()
{
StartSegmentEndPosition = LayerPropertiesViewModel.StartTimelineSegmentViewModel.SegmentWidth;
MainSegmentEndPosition = StartSegmentEndPosition + LayerPropertiesViewModel.MainTimelineSegmentViewModel.SegmentWidth;
EndSegmentEndPosition = MainSegmentEndPosition + LayerPropertiesViewModel.EndTimelineSegmentViewModel.SegmentWidth;
TotalTimelineWidth = EndSegmentEndPosition;
}
private void SelectedProfileElementOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(_profileEditorService.SelectedProfileElement.StartSegmentLength))
{
NotifyOfPropertyChange(nameof(StartSegmentWidth));
NotifyOfPropertyChange(nameof(StartSegmentEndPosition));
NotifyOfPropertyChange(nameof(MainSegmentEndPosition));
NotifyOfPropertyChange(nameof(EndSegmentEndPosition));
NotifyOfPropertyChange(nameof(StartSegmentEnabled));
NotifyOfPropertyChange(nameof(TotalTimelineWidth));
}
else if (e.PropertyName == nameof(_profileEditorService.SelectedProfileElement.MainSegmentLength))
{
NotifyOfPropertyChange(nameof(MainSegmentWidth));
NotifyOfPropertyChange(nameof(MainSegmentEndPosition));
NotifyOfPropertyChange(nameof(EndSegmentEndPosition));
NotifyOfPropertyChange(nameof(TotalTimelineWidth));
}
else if (e.PropertyName == nameof(_profileEditorService.SelectedProfileElement.EndSegmentLength))
{
NotifyOfPropertyChange(nameof(EndSegmentWidth));
NotifyOfPropertyChange(nameof(EndSegmentEndPosition));
NotifyOfPropertyChange(nameof(EndSegmentEnabled));
NotifyOfPropertyChange(nameof(TotalTimelineWidth));
}
Update();
}
private void ProfileEditorServiceOnPixelsPerSecondChanged(object sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(StartSegmentWidth));
NotifyOfPropertyChange(nameof(StartSegmentEndPosition));
NotifyOfPropertyChange(nameof(MainSegmentWidth));
NotifyOfPropertyChange(nameof(MainSegmentEndPosition));
NotifyOfPropertyChange(nameof(EndSegmentWidth));
NotifyOfPropertyChange(nameof(EndSegmentEndPosition));
NotifyOfPropertyChange(nameof(TotalTimelineWidth));
Update();
}
private void ProfileEditorServiceOnProfileElementSelected(object? sender, RenderProfileElementEventArgs e)
{
if (e.PreviousRenderProfileElement != null)
e.PreviousRenderProfileElement.PropertyChanged -= SelectedProfileElementOnPropertyChanged;
e.RenderProfileElement.PropertyChanged += SelectedProfileElementOnPropertyChanged;
if (e.RenderProfileElement != null)
e.RenderProfileElement.PropertyChanged += SelectedProfileElementOnPropertyChanged;
Update();
}
#region Command handlers
@@ -139,26 +127,42 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
public void KeyframeMouseMove(object sender, MouseEventArgs e)
{
var viewModel = (sender as Ellipse)?.DataContext as ITimelineKeyframeViewModel;
if (viewModel == null)
return;
if (sender is Ellipse ellipse && ellipse.DataContext is ITimelineKeyframeViewModel viewModel)
{
if (e.LeftButton == MouseButtonState.Pressed)
MoveSelectedKeyframes(GetCursorTime(e.GetPosition(View)), viewModel);
if (e.LeftButton == MouseButtonState.Pressed)
MoveSelectedKeyframes(GetCursorTime(e.GetPosition(View)), viewModel);
e.Handled = true;
e.Handled = true;
}
}
#region Context menu actions
public void ContextMenuOpening(object sender, EventArgs e)
{
if (sender is Ellipse ellipse && ellipse.DataContext is ITimelineKeyframeViewModel viewModel)
viewModel.PopulateEasingViewModels();
}
public void ContextMenuClosing(object sender, EventArgs e)
{
if (sender is Ellipse ellipse && ellipse.DataContext is ITimelineKeyframeViewModel viewModel)
viewModel.ClearEasingViewModels();
}
public void Copy(ITimelineKeyframeViewModel viewModel)
{
viewModel.Copy();
// viewModel.Copy();
var keyframeViewModels = GetAllKeyframeViewModels();
foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected))
keyframeViewModel.Copy();
}
public void Delete(ITimelineKeyframeViewModel viewModel)
{
viewModel.Delete();
var keyframeViewModels = GetAllKeyframeViewModels();
foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected))
keyframeViewModel.Delete();
}
#endregion
@@ -220,7 +224,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected))
keyframeViewModel.ApplyOffsetToKeyframe(sourceKeyframeViewModel);
_layerPropertiesViewModel.ProfileEditorService.UpdateProfilePreview();
_profileEditorService.UpdateProfilePreview();
}
@@ -237,6 +241,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
private Point _mouseDragStartPoint;
private bool _mouseDragging;
private double _startSegmentEndPosition;
private double _mainSegmentEndPosition;
private double _endSegmentEndPosition;
private double _totalTimelineWidth;
// ReSharper disable once UnusedMember.Global - Called from view
public void TimelineCanvasMouseDown(object sender, MouseButtonEventArgs e)
@@ -335,5 +343,17 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline
}
#endregion
#region IDisposable
public void Dispose()
{
_profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
_profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
if (_profileEditorService.SelectedProfileElement != null)
_profileEditorService.SelectedProfileElement.PropertyChanged -= SelectedProfileElementOnPropertyChanged;
}
#endregion
}
}
@@ -20,6 +20,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
PropertyInputViewModel = _profileEditorService.CreatePropertyInputViewModel(LayerProperty);
_profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged;
LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged;
LayerPropertyViewModel.IsVisible = !LayerProperty.IsHidden;
}
public LayerProperty<T> LayerProperty { get; }
@@ -51,6 +54,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
{
_propertyInputViewModel?.Dispose();
_profileEditorService.SelectedDataBindingChanged -= ProfileEditorServiceOnSelectedDataBindingChanged;
LayerProperty.VisibilityChanged -= LayerPropertyOnVisibilityChanged;
}
#endregion
@@ -83,6 +87,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
NotifyOfPropertyChange(nameof(DataBindingsOpen));
}
private void LayerPropertyOnVisibilityChanged(object? sender, LayerPropertyEventArgs<T> e)
{
LayerPropertyViewModel.IsVisible = !LayerProperty.IsHidden;
}
#endregion
}
@@ -1,4 +1,5 @@
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services;
@@ -10,8 +11,10 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
public FolderViewModel(ProfileElement folder,
IProfileEditorService profileEditorService,
IDialogService dialogService,
IProfileTreeVmFactory profileTreeVmFactory) :
base(folder, profileEditorService, dialogService, profileTreeVmFactory)
IProfileTreeVmFactory profileTreeVmFactory,
ILayerBrushService layerBrushService,
ISurfaceService surfaceService) :
base(folder, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
{
}
@@ -1,4 +1,5 @@
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services;
@@ -9,8 +10,10 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
public LayerViewModel(ProfileElement layer,
IProfileEditorService profileEditorService,
IDialogService dialogService,
IProfileTreeVmFactory profileTreeVmFactory) :
base(layer, profileEditorService, dialogService, profileTreeVmFactory)
IProfileTreeVmFactory profileTreeVmFactory,
ILayerBrushService layerBrushService,
ISurfaceService surfaceService) :
base(layer, profileEditorService, dialogService, profileTreeVmFactory, layerBrushService, surfaceService)
{
}
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Exceptions;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.Dialogs;
@@ -16,16 +17,22 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
private readonly IDialogService _dialogService;
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
private readonly ILayerBrushService _layerBrushService;
private readonly ISurfaceService _surfaceService;
private ProfileElement _profileElement;
protected TreeItemViewModel(ProfileElement profileElement,
IProfileEditorService profileEditorService,
IDialogService dialogService,
IProfileTreeVmFactory profileTreeVmFactory)
IProfileTreeVmFactory profileTreeVmFactory,
ILayerBrushService layerBrushService,
ISurfaceService surfaceService)
{
_profileEditorService = profileEditorService;
_dialogService = dialogService;
_profileTreeVmFactory = profileTreeVmFactory;
_layerBrushService = layerBrushService;
_surfaceService = surfaceService;
ProfileElement = profileElement;
@@ -129,8 +136,11 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
if (!SupportsChildren)
throw new ArtemisUIException("Cannot add a layer to a profile element of type " + ProfileElement.GetType().Name);
var _ = new Layer(ProfileElement, "New layer");
var layer = new Layer(ProfileElement, "New layer");
layer.ChangeLayerBrush(_layerBrushService.GetDefaultLayerBrush());
layer.AddLeds(_surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds));
_profileEditorService.UpdateSelectedProfile();
_profileEditorService.ChangeSelectedProfileElement(layer);
}
// ReSharper disable once UnusedMember.Global - Called from view
@@ -167,6 +177,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
parent.RemoveExistingElement(this);
_profileEditorService.UpdateSelectedProfile();
_profileEditorService.ChangeSelectedProfileElement(null);
}
public void UpdateProfileElements()
@@ -1,8 +1,10 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Properties;
using Artemis.UI.Shared.Services;
@@ -10,10 +12,14 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools
{
public class SelectionToolViewModel : VisualizationToolViewModel
{
private readonly ILayerBrushService _layerBrushService;
private Rect _dragRectangle;
public SelectionToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService)
public SelectionToolViewModel(ProfileViewModel profileViewModel,
IProfileEditorService profileEditorService,
ILayerBrushService layerBrushService) : base(profileViewModel, profileEditorService)
{
_layerBrushService = layerBrushService;
using (var stream = new MemoryStream(Resources.aero_crosshair))
{
Cursor = new Cursor(stream);
@@ -52,20 +58,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools
}
// If no layer selected, apply it to a new layer in the selected folder
else if (ProfileEditorService.SelectedProfileElement is Folder folder)
{
var newLayer = new Layer(folder, "New layer");
newLayer.AddLeds(selectedLeds);
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
ProfileEditorService.UpdateSelectedProfileElement();
}
CreateLayer(folder, selectedLeds);
// If no folder selected, apply it to a new layer in the root folder
else
{
var rootFolder = ProfileEditorService.SelectedProfile.GetRootFolder();
var newLayer = new Layer(rootFolder, "New layer");
newLayer.AddLeds(selectedLeds);
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
ProfileEditorService.UpdateSelectedProfileElement();
CreateLayer(rootFolder, selectedLeds);
}
}
@@ -89,5 +87,14 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools
DragRectangle = selectedRect;
}
private void CreateLayer(Folder folder, List<ArtemisLed> selectedLeds)
{
var newLayer = new Layer(folder, "New layer");
newLayer.ChangeLayerBrush(_layerBrushService.GetDefaultLayerBrush());
newLayer.AddLeds(selectedLeds);
ProfileEditorService.ChangeSelectedProfileElement(newLayer);
ProfileEditorService.UpdateSelectedProfileElement();
}
}
}