mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 11:26:27 +00:00
Core - Streamlined public parts of profile creation
UI - Started adjusting the VMs for the layer refactor
This commit is contained in:
1 parent
1de6fefc2a
commit
c07ea09c9d
58 files changed
+694
-1196
No files matched your search
+4
-25
@@ -1,44 +1,23 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract
|
||||
{
|
||||
public abstract class DisplayConditionViewModel : PropertyChangedBase, IDisposable
|
||||
public abstract class DisplayConditionViewModel : Conductor<DisplayConditionViewModel>.Collection.AllActive
|
||||
{
|
||||
protected DisplayConditionViewModel(DisplayConditionPart model, DisplayConditionViewModel parent)
|
||||
protected DisplayConditionViewModel(DisplayConditionPart model)
|
||||
{
|
||||
Model = model;
|
||||
Parent = parent;
|
||||
Children = new BindableCollection<DisplayConditionViewModel>();
|
||||
}
|
||||
|
||||
public DisplayConditionPart Model { get; }
|
||||
public DisplayConditionViewModel Parent { get; set; }
|
||||
public BindableCollection<DisplayConditionViewModel> Children { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var child in Children)
|
||||
child.Dispose();
|
||||
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public abstract void Update();
|
||||
|
||||
public virtual void Delete()
|
||||
{
|
||||
Model.Parent.RemoveChild(Model);
|
||||
Parent.Update();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
((DisplayConditionViewModel) Parent).Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -124,7 +124,7 @@
|
||||
<materialDesign:PackIcon Kind="Add" Width="18" Height="18" />
|
||||
</Button>
|
||||
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Children}">
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<materialDesign:TransitioningContent>
|
||||
|
||||
+16
-24
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
||||
@@ -11,21 +10,24 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionGroupViewModel : DisplayConditionViewModel, IViewAware
|
||||
public class DisplayConditionGroupViewModel : DisplayConditionViewModel
|
||||
{
|
||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private bool _isInitialized;
|
||||
private bool _isRootGroup;
|
||||
|
||||
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup, DisplayConditionViewModel parent, bool isListGroup,
|
||||
IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory) : base(displayConditionGroup, parent)
|
||||
public DisplayConditionGroupViewModel(DisplayConditionGroup displayConditionGroup,
|
||||
bool isListGroup,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDisplayConditionsVmFactory displayConditionsVmFactory)
|
||||
: base(displayConditionGroup)
|
||||
{
|
||||
IsListGroup = isListGroup;
|
||||
_profileEditorService = profileEditorService;
|
||||
_displayConditionsVmFactory = displayConditionsVmFactory;
|
||||
|
||||
Children.CollectionChanged += (sender, args) => NotifyOfPropertyChange(nameof(DisplayBooleanOperator));
|
||||
Items.CollectionChanged += (sender, args) => NotifyOfPropertyChange(nameof(DisplayBooleanOperator));
|
||||
|
||||
Execute.PostToUIThread(async () =>
|
||||
{
|
||||
@@ -50,16 +52,9 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
set => SetAndNotify(ref _isInitialized, value);
|
||||
}
|
||||
|
||||
public bool DisplayBooleanOperator => Children.Count > 1;
|
||||
public bool DisplayBooleanOperator => Items.Count > 1;
|
||||
public string SelectedBooleanOperator => DisplayConditionGroup.BooleanOperator.Humanize();
|
||||
|
||||
public void AttachView(UIElement view)
|
||||
{
|
||||
View = view;
|
||||
}
|
||||
|
||||
public UIElement View { get; set; }
|
||||
|
||||
public void SelectBooleanOperator(string type)
|
||||
{
|
||||
var enumValue = Enum.Parse<BooleanOperator>(type);
|
||||
@@ -105,39 +100,36 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
NotifyOfPropertyChange(nameof(SelectedBooleanOperator));
|
||||
|
||||
// Remove VMs of effects no longer applied on the layer
|
||||
var toRemove = Children.Where(c => !DisplayConditionGroup.Children.Contains(c.Model)).ToList();
|
||||
var toRemove = Items.Where(c => !DisplayConditionGroup.Children.Contains(c.Model)).ToList();
|
||||
// Using RemoveRange breaks our lovely animations
|
||||
foreach (var displayConditionViewModel in toRemove)
|
||||
{
|
||||
Children.Remove(displayConditionViewModel);
|
||||
displayConditionViewModel.Dispose();
|
||||
}
|
||||
CloseItem(displayConditionViewModel);
|
||||
|
||||
foreach (var childModel in Model.Children)
|
||||
{
|
||||
if (Children.Any(c => c.Model == childModel))
|
||||
if (Items.Any(c => c.Model == childModel))
|
||||
continue;
|
||||
|
||||
switch (childModel)
|
||||
{
|
||||
case DisplayConditionGroup displayConditionGroup:
|
||||
Children.Add(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this, IsListGroup));
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, IsListGroup));
|
||||
break;
|
||||
case DisplayConditionList displayConditionListPredicate:
|
||||
Children.Add(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate, this));
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate));
|
||||
break;
|
||||
case DisplayConditionPredicate displayConditionPredicate:
|
||||
if (!IsListGroup)
|
||||
Children.Add(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate, this));
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate));
|
||||
break;
|
||||
case DisplayConditionListPredicate displayConditionListPredicate:
|
||||
if (IsListGroup)
|
||||
Children.Add(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate, this));
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var childViewModel in Children)
|
||||
foreach (var childViewModel in Items)
|
||||
childViewModel.Update();
|
||||
}
|
||||
}
|
||||
|
||||
+12
-13
@@ -17,9 +17,9 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionListPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>
|
||||
public class DisplayConditionListPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>, IDisposable
|
||||
{
|
||||
private readonly IDataModelService _dataModelService;
|
||||
private readonly IConditionOperatorService _conditionOperatorService;
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
@@ -39,16 +39,15 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
public DisplayConditionListPredicateViewModel(
|
||||
DisplayConditionListPredicate displayConditionListPredicate,
|
||||
DisplayConditionViewModel parent,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelUIService dataModelUIService,
|
||||
IDataModelService dataModelService,
|
||||
IConditionOperatorService conditionOperatorService,
|
||||
ISettingsService settingsService,
|
||||
IEventAggregator eventAggregator) : base(displayConditionListPredicate, parent)
|
||||
IEventAggregator eventAggregator) : base(displayConditionListPredicate)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_dataModelService = dataModelService;
|
||||
_conditionOperatorService = conditionOperatorService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_updateTimer = new Timer(500);
|
||||
_supportedInputTypes = new List<Type>();
|
||||
@@ -206,7 +205,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
// Get the supported operators
|
||||
Operators.Clear();
|
||||
Operators.AddRange(_dataModelService.GetConditionOperatorsForType(leftSideType));
|
||||
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
||||
if (DisplayConditionListPredicate.Operator == null)
|
||||
DisplayConditionListPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
||||
SelectedOperator = DisplayConditionListPredicate.Operator;
|
||||
@@ -277,12 +276,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
_eventAggregator.Subscribe(this);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_updateTimer.Stop();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
|
||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (LeftSideDataModelOpen)
|
||||
@@ -353,5 +346,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
SelectedOperator = displayConditionOperator;
|
||||
ApplyOperator();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_updateTimer.Dispose();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -105,7 +105,7 @@
|
||||
</Button.ContextMenu>
|
||||
</Button>
|
||||
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Children}" Margin="0 4 0 0">
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" Margin="0 4 0 0">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<materialDesign:TransitioningContent>
|
||||
|
||||
+14
-17
@@ -14,7 +14,7 @@ using Humanizer;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionListViewModel : DisplayConditionViewModel
|
||||
public class DisplayConditionListViewModel : DisplayConditionViewModel, IDisposable
|
||||
{
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||
@@ -30,7 +30,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelUIService dataModelUIService,
|
||||
IDisplayConditionsVmFactory displayConditionsVmFactory,
|
||||
ISettingsService settingsService) : base(displayConditionList, parent)
|
||||
ISettingsService settingsService) : base(displayConditionList)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelUIService = dataModelUIService;
|
||||
@@ -152,36 +152,27 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
TargetDataModel.ApplyTypeFilter(true, typeof(IList));
|
||||
|
||||
// Remove VMs of effects no longer applied on the layer
|
||||
var toRemove = Children.Where(c => !DisplayConditionList.Children.Contains(c.Model)).ToList();
|
||||
var toRemove = Items.Where(c => !DisplayConditionList.Children.Contains(c.Model)).ToList();
|
||||
// Using RemoveRange breaks our lovely animations
|
||||
foreach (var displayConditionViewModel in toRemove)
|
||||
{
|
||||
Children.Remove(displayConditionViewModel);
|
||||
displayConditionViewModel.Dispose();
|
||||
}
|
||||
CloseItem(displayConditionViewModel);
|
||||
|
||||
foreach (var childModel in Model.Children)
|
||||
{
|
||||
if (Children.Any(c => c.Model == childModel))
|
||||
if (Items.Any(c => c.Model == childModel))
|
||||
continue;
|
||||
if (!(childModel is DisplayConditionGroup displayConditionGroup))
|
||||
continue;
|
||||
|
||||
var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this, true);
|
||||
var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, true);
|
||||
viewModel.IsRootGroup = true;
|
||||
Children.Add(viewModel);
|
||||
ActivateItem(viewModel);
|
||||
}
|
||||
|
||||
foreach (var childViewModel in Children)
|
||||
foreach (var childViewModel in Items)
|
||||
childViewModel.Update();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_updateTimer.Stop();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
|
||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (TargetDataModelOpen)
|
||||
@@ -205,5 +196,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
SelectedListProperty = dataModelListViewModel;
|
||||
ApplyList();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_updateTimer.Dispose();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-14
@@ -16,9 +16,9 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>
|
||||
public class DisplayConditionPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>, IDisposable
|
||||
{
|
||||
private readonly IDataModelService _dataModelService;
|
||||
private readonly IConditionOperatorService _conditionOperatorService;
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IEventAggregator _eventAggregator;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
@@ -38,16 +38,15 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
public DisplayConditionPredicateViewModel(
|
||||
DisplayConditionPredicate displayConditionPredicate,
|
||||
DisplayConditionViewModel parent,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelUIService dataModelUIService,
|
||||
IDataModelService dataModelService,
|
||||
IConditionOperatorService conditionOperatorService,
|
||||
ISettingsService settingsService,
|
||||
IEventAggregator eventAggregator) : base(displayConditionPredicate, parent)
|
||||
IEventAggregator eventAggregator) : base(displayConditionPredicate)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_dataModelService = dataModelService;
|
||||
_conditionOperatorService = conditionOperatorService;
|
||||
_eventAggregator = eventAggregator;
|
||||
_updateTimer = new Timer(500);
|
||||
_supportedInputTypes = new List<Type>();
|
||||
@@ -208,7 +207,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
// Get the supported operators
|
||||
Operators.Clear();
|
||||
Operators.AddRange(_dataModelService.GetConditionOperatorsForType(leftSideType));
|
||||
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
||||
if (DisplayConditionPredicate.Operator == null)
|
||||
DisplayConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
||||
SelectedOperator = DisplayConditionPredicate.Operator;
|
||||
@@ -278,13 +277,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
);
|
||||
_eventAggregator.Subscribe(this);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_updateTimer.Stop();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
|
||||
|
||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (LeftSideDataModelOpen)
|
||||
@@ -335,5 +328,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
SelectedOperator = displayConditionOperator;
|
||||
ApplyOperator();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_updateTimer.Dispose();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
<Grid Grid.Row="2" Grid.Column="0">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="{StaticResource MaterialDesignCardBackground}">
|
||||
<ContentControl s:View.Model="{Binding RootGroup}" />
|
||||
<ContentControl s:View.Model="{Binding ActiveItem}" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
|
||||
+7
-17
@@ -3,17 +3,17 @@ using Artemis.Core;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
{
|
||||
public class DisplayConditionsViewModel : ProfileEditorPanelViewModel
|
||||
public class DisplayConditionsViewModel : Conductor<DisplayConditionGroupViewModel>, IProfileEditorPanelViewModel
|
||||
{
|
||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private bool _alwaysFinishTimeline;
|
||||
private bool _displayContinuously;
|
||||
private RenderProfileElement _renderProfileElement;
|
||||
private DisplayConditionGroupViewModel _rootGroup;
|
||||
private int _transitionerIndex;
|
||||
|
||||
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory)
|
||||
@@ -28,11 +28,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
set => SetAndNotify(ref _transitionerIndex, value);
|
||||
}
|
||||
|
||||
public DisplayConditionGroupViewModel RootGroup
|
||||
{
|
||||
get => _rootGroup;
|
||||
set => SetAndNotify(ref _rootGroup, value);
|
||||
}
|
||||
|
||||
public RenderProfileElement RenderProfileElement
|
||||
{
|
||||
@@ -70,9 +65,6 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
protected override void OnDeactivate()
|
||||
{
|
||||
_profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
|
||||
|
||||
RootGroup?.Dispose();
|
||||
RootGroup = null;
|
||||
}
|
||||
|
||||
private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
|
||||
@@ -87,8 +79,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
if (e.RenderProfileElement == null)
|
||||
{
|
||||
RootGroup?.Dispose();
|
||||
RootGroup = null;
|
||||
ActiveItem = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,14 +87,13 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
if (e.RenderProfileElement.DisplayConditionGroup == null)
|
||||
e.RenderProfileElement.DisplayConditionGroup = new DisplayConditionGroup(null);
|
||||
|
||||
RootGroup?.Dispose();
|
||||
RootGroup = _displayConditionsVmFactory.DisplayConditionGroupViewModel(e.RenderProfileElement.DisplayConditionGroup, null, false);
|
||||
RootGroup.IsRootGroup = true;
|
||||
RootGroup.Update();
|
||||
ActiveItem = _displayConditionsVmFactory.DisplayConditionGroupViewModel(e.RenderProfileElement.DisplayConditionGroup, false);
|
||||
ActiveItem.IsRootGroup = true;
|
||||
ActiveItem.Update();
|
||||
|
||||
// Only show the intro to conditions once, and only if the layer has no conditions
|
||||
if (TransitionerIndex != 1)
|
||||
TransitionerIndex = RootGroup.Children.Any() ? 1 : 0;
|
||||
TransitionerIndex = ActiveItem.Items.Any() ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor
|
||||
{
|
||||
public class ProfileEditorPanelViewModel : Screen
|
||||
public interface IProfileEditorPanelViewModel : IScreen
|
||||
{
|
||||
}
|
||||
}
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract
|
||||
{
|
||||
public abstract class LayerPropertyBaseViewModel : PropertyChangedBase, IDisposable
|
||||
{
|
||||
private BindableCollection<LayerPropertyBaseViewModel> _children;
|
||||
private bool _isExpanded;
|
||||
|
||||
protected LayerPropertyBaseViewModel()
|
||||
{
|
||||
Children = new BindableCollection<LayerPropertyBaseViewModel>();
|
||||
}
|
||||
|
||||
public abstract bool IsVisible { get; }
|
||||
|
||||
public virtual bool IsExpanded
|
||||
{
|
||||
get => _isExpanded;
|
||||
set => SetAndNotify(ref _isExpanded, value);
|
||||
}
|
||||
|
||||
public BindableCollection<LayerPropertyBaseViewModel> Children
|
||||
{
|
||||
get => _children;
|
||||
set => SetAndNotify(ref _children, value);
|
||||
}
|
||||
|
||||
public abstract void Dispose();
|
||||
|
||||
public abstract List<BaseLayerPropertyKeyframe> GetKeyframes(bool expandedOnly);
|
||||
}
|
||||
}
|
||||
+9
-19
@@ -9,32 +9,22 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
||||
{
|
||||
public class EffectsViewModel : PropertyChangedBase
|
||||
public class EffectsViewModel : Conductor<LayerEffectDescriptor>.Collection.AllActive
|
||||
{
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IRenderElementService _renderElementService;
|
||||
private BindableCollection<LayerEffectDescriptor> _layerEffectDescriptors;
|
||||
private LayerEffectDescriptor _selectedLayerEffectDescriptor;
|
||||
|
||||
public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginService pluginService, IRenderElementService renderElementService, IProfileEditorService profileEditorService)
|
||||
public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginService pluginService, IProfileEditorService profileEditorService)
|
||||
{
|
||||
_pluginService = pluginService;
|
||||
_renderElementService = renderElementService;
|
||||
_profileEditorService = profileEditorService;
|
||||
LayerPropertiesViewModel = layerPropertiesViewModel;
|
||||
LayerEffectDescriptors = new BindableCollection<LayerEffectDescriptor>();
|
||||
PropertyChanged += HandleSelectedLayerEffectChanged;
|
||||
}
|
||||
|
||||
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
|
||||
public bool HasLayerEffectDescriptors => LayerEffectDescriptors.Any();
|
||||
|
||||
public BindableCollection<LayerEffectDescriptor> LayerEffectDescriptors
|
||||
{
|
||||
get => _layerEffectDescriptors;
|
||||
set => SetAndNotify(ref _layerEffectDescriptors, value);
|
||||
}
|
||||
public bool HasLayerEffectDescriptors => Items.Any();
|
||||
|
||||
public LayerEffectDescriptor SelectedLayerEffectDescriptor
|
||||
{
|
||||
@@ -46,15 +36,15 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
||||
{
|
||||
var layerBrushProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
|
||||
var descriptors = layerBrushProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
|
||||
LayerEffectDescriptors.AddRange(descriptors.Except(LayerEffectDescriptors));
|
||||
LayerEffectDescriptors.RemoveRange(LayerEffectDescriptors.Except(descriptors));
|
||||
Items.AddRange(descriptors.Except(Items));
|
||||
Items.RemoveRange(Items.Except(descriptors));
|
||||
|
||||
// Sort by display name
|
||||
var index = 0;
|
||||
foreach (var layerEffectDescriptor in LayerEffectDescriptors.OrderBy(d => d.DisplayName).ToList())
|
||||
foreach (var layerEffectDescriptor in Items.OrderBy(d => d.DisplayName).ToList())
|
||||
{
|
||||
if (LayerEffectDescriptors.IndexOf(layerEffectDescriptor) != index)
|
||||
LayerEffectDescriptors.Move(LayerEffectDescriptors.IndexOf(layerEffectDescriptor), index);
|
||||
if (Items.IndexOf(layerEffectDescriptor) != index)
|
||||
((BindableCollection<LayerEffectDescriptor>) Items).Move(Items.IndexOf(layerEffectDescriptor), index);
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -78,7 +68,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
||||
Execute.PostToUIThread(async () =>
|
||||
{
|
||||
await Task.Delay(500);
|
||||
_renderElementService.AddLayerEffect(renderElement, SelectedLayerEffectDescriptor);
|
||||
renderElement.AddLayerEffect(SelectedLayerEffectDescriptor);
|
||||
_profileEditorService.UpdateSelectedProfileElement();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,11 +16,10 @@ using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using GongSolutions.Wpf.DragDrop;
|
||||
using Stylet;
|
||||
using static Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerPropertyGroupViewModel.ViewModelType;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||
{
|
||||
public class LayerPropertiesViewModel : ProfileEditorPanelViewModel, IDropTarget
|
||||
public class LayerPropertiesViewModel : Conductor<IScreen>.Collection.AllActive, IProfileEditorPanelViewModel, IDropTarget
|
||||
{
|
||||
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
||||
private readonly IDataBindingsVmFactory _dataBindingsVmFactory;
|
||||
|
||||
+23
-143
@@ -1,58 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline;
|
||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Humanizer;
|
||||
using Ninject;
|
||||
using Ninject.Parameters;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||
{
|
||||
public class LayerPropertyGroupViewModel : LayerPropertyBaseViewModel
|
||||
public class LayerPropertyGroupViewModel : PropertyChangedBase, IDisposable
|
||||
{
|
||||
private readonly ILayerPropertyVmFactory _layerPropertyVmFactory;
|
||||
private ViewModelType _groupType;
|
||||
private TimelinePropertyGroupViewModel _timelinePropertyGroupViewModel;
|
||||
private TreePropertyGroupViewModel _treePropertyGroupViewModel;
|
||||
|
||||
public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, PropertyGroupDescriptionAttribute propertyGroupDescription,
|
||||
IProfileEditorService profileEditorService, ILayerPropertyVmFactory layerPropertyVmFactory)
|
||||
public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, ILayerPropertyVmFactory layerPropertyVmFactory)
|
||||
{
|
||||
_layerPropertyVmFactory = layerPropertyVmFactory;
|
||||
ProfileEditorService = profileEditorService;
|
||||
|
||||
LayerPropertyGroup = layerPropertyGroup;
|
||||
PropertyGroupDescription = propertyGroupDescription;
|
||||
|
||||
TreePropertyGroupViewModel = _layerPropertyVmFactory.TreePropertyGroupViewModel(this);
|
||||
TimelinePropertyGroupViewModel = _layerPropertyVmFactory.TimelinePropertyGroupViewModel(this);
|
||||
|
||||
// Generate a fallback name if the description does not contain one
|
||||
if (PropertyGroupDescription.Name == null)
|
||||
{
|
||||
var propertyInfo = LayerPropertyGroup.Parent?.GetType().GetProperties().FirstOrDefault(p => ReferenceEquals(p.GetValue(LayerPropertyGroup.Parent), LayerPropertyGroup));
|
||||
if (propertyInfo != null)
|
||||
PropertyGroupDescription.Name = propertyInfo.Name.Humanize();
|
||||
else
|
||||
PropertyGroupDescription.Name = "Unknown group";
|
||||
}
|
||||
|
||||
LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged;
|
||||
LayerPropertyGroupTreeViewModel = layerPropertyVmFactory.LayerPropertyGroupTreeViewModel(this);
|
||||
PopulateChildren();
|
||||
DetermineType();
|
||||
}
|
||||
|
||||
public override bool IsVisible => !LayerPropertyGroup.IsHidden;
|
||||
public IProfileEditorService ProfileEditorService { get; }
|
||||
public LayerPropertyGroup LayerPropertyGroup { get; }
|
||||
public PropertyGroupDescriptionAttribute PropertyGroupDescription { get; }
|
||||
public LayerPropertyGroupTreeViewModel LayerPropertyGroupTreeViewModel { get; }
|
||||
public BindableCollection<PropertyChangedBase> Children { get; set; }
|
||||
|
||||
public override bool IsExpanded
|
||||
public bool IsVisible => !LayerPropertyGroup.IsHidden;
|
||||
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => LayerPropertyGroup.ProfileElement.IsPropertyGroupExpanded(LayerPropertyGroup);
|
||||
set
|
||||
@@ -62,81 +35,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModelType GroupType
|
||||
{
|
||||
get => _groupType;
|
||||
set => SetAndNotify(ref _groupType, value);
|
||||
}
|
||||
|
||||
public TreePropertyGroupViewModel TreePropertyGroupViewModel
|
||||
{
|
||||
get => _treePropertyGroupViewModel;
|
||||
set => SetAndNotify(ref _treePropertyGroupViewModel, value);
|
||||
}
|
||||
|
||||
public TimelinePropertyGroupViewModel TimelinePropertyGroupViewModel
|
||||
{
|
||||
get => _timelinePropertyGroupViewModel;
|
||||
set => SetAndNotify(ref _timelinePropertyGroupViewModel, value);
|
||||
}
|
||||
|
||||
public override List<BaseLayerPropertyKeyframe> GetKeyframes(bool expandedOnly)
|
||||
{
|
||||
var result = new List<BaseLayerPropertyKeyframe>();
|
||||
if (expandedOnly && !IsExpanded || LayerPropertyGroup.IsHidden)
|
||||
return result;
|
||||
|
||||
foreach (var layerPropertyBaseViewModel in Children)
|
||||
result.AddRange(layerPropertyBaseViewModel.GetKeyframes(expandedOnly));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
foreach (var layerPropertyBaseViewModel in Children)
|
||||
layerPropertyBaseViewModel.Dispose();
|
||||
|
||||
LayerPropertyGroup.VisibilityChanged -= LayerPropertyGroupOnVisibilityChanged;
|
||||
TimelinePropertyGroupViewModel.Dispose();
|
||||
}
|
||||
|
||||
public List<LayerPropertyBaseViewModel> GetAllChildren()
|
||||
{
|
||||
var result = new List<LayerPropertyBaseViewModel>();
|
||||
foreach (var layerPropertyBaseViewModel in Children)
|
||||
{
|
||||
result.Add(layerPropertyBaseViewModel);
|
||||
if (layerPropertyBaseViewModel is LayerPropertyGroupViewModel layerPropertyGroupViewModel)
|
||||
result.AddRange(layerPropertyGroupViewModel.GetAllChildren());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void UpdateOrder(int order)
|
||||
{
|
||||
LayerPropertyGroup.LayerEffect.Order = order;
|
||||
NotifyOfPropertyChange(nameof(IsExpanded));
|
||||
}
|
||||
|
||||
private void DetermineType()
|
||||
{
|
||||
if (LayerPropertyGroup is LayerGeneralProperties)
|
||||
GroupType = ViewModelType.General;
|
||||
else if (LayerPropertyGroup is LayerTransformProperties)
|
||||
GroupType = ViewModelType.Transform;
|
||||
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerBrush != null)
|
||||
GroupType = ViewModelType.LayerBrushRoot;
|
||||
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerEffect != null)
|
||||
GroupType = ViewModelType.LayerEffectRoot;
|
||||
else
|
||||
GroupType = ViewModelType.None;
|
||||
}
|
||||
|
||||
private void PopulateChildren()
|
||||
{
|
||||
// Get all properties and property groups and create VMs for them
|
||||
// The group has methods for getting this without reflection but then we lose the order of the properties as they are defined on the group
|
||||
foreach (var propertyInfo in LayerPropertyGroup.GetType().GetProperties())
|
||||
{
|
||||
var propertyAttribute = (PropertyDescriptionAttribute) Attribute.GetCustomAttribute(propertyInfo, typeof(PropertyDescriptionAttribute));
|
||||
@@ -144,50 +46,28 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||
var value = propertyInfo.GetValue(LayerPropertyGroup);
|
||||
|
||||
// Create VMs for properties on the group
|
||||
if (propertyAttribute != null && value is BaseLayerProperty baseLayerProperty)
|
||||
if (propertyAttribute != null && value is ILayerProperty layerProperty)
|
||||
{
|
||||
var viewModel = CreateLayerPropertyViewModel(baseLayerProperty, propertyAttribute);
|
||||
if (viewModel != null)
|
||||
Children.Add(viewModel);
|
||||
var layerPropertyViewModel = _layerPropertyVmFactory.LayerPropertyViewModel(layerProperty);
|
||||
// After creation ensure a supported input VM was found, if not, discard the VM
|
||||
if (!layerPropertyViewModel.LayerPropertyTreeViewModel.HasPropertyInputViewModel)
|
||||
layerPropertyViewModel.Dispose();
|
||||
else
|
||||
Children.Add(layerPropertyViewModel);
|
||||
}
|
||||
// Create VMs for child groups on this group, resulting in a nested structure
|
||||
else if (groupAttribute != null && value is LayerPropertyGroup layerPropertyGroup)
|
||||
Children.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerPropertyGroup, groupAttribute));
|
||||
Children.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerPropertyGroup));
|
||||
}
|
||||
}
|
||||
|
||||
private LayerPropertyBaseViewModel CreateLayerPropertyViewModel(BaseLayerProperty baseLayerProperty, PropertyDescriptionAttribute propertyDescription)
|
||||
public void Dispose()
|
||||
{
|
||||
// Go through the pain of instantiating a generic type VM now via reflection to make things a lot simpler down the line
|
||||
var genericType = baseLayerProperty.GetType().Name == typeof(LayerProperty<>).Name
|
||||
? baseLayerProperty.GetType().GetGenericArguments()[0]
|
||||
: baseLayerProperty.GetType().BaseType.GetGenericArguments()[0];
|
||||
|
||||
// Only create entries for types supported by a tree input VM
|
||||
if (!genericType.IsEnum && ProfileEditorService.RegisteredPropertyEditors.All(r => r.SupportedType != genericType))
|
||||
return null;
|
||||
var genericViewModel = typeof(LayerPropertyViewModel<>).MakeGenericType(genericType);
|
||||
var parameters = new IParameter[]
|
||||
foreach (var child in Children)
|
||||
{
|
||||
new ConstructorArgument("layerProperty", baseLayerProperty),
|
||||
new ConstructorArgument("propertyDescription", propertyDescription)
|
||||
};
|
||||
|
||||
return (LayerPropertyBaseViewModel) ProfileEditorService.Kernel.Get(genericViewModel, parameters);
|
||||
}
|
||||
|
||||
private void LayerPropertyGroupOnVisibilityChanged(object sender, EventArgs e)
|
||||
{
|
||||
NotifyOfPropertyChange(nameof(IsVisible));
|
||||
}
|
||||
|
||||
public enum ViewModelType
|
||||
{
|
||||
General,
|
||||
Transform,
|
||||
LayerBrushRoot,
|
||||
LayerEffectRoot,
|
||||
None
|
||||
if (child is IDisposable disposableChild)
|
||||
disposableChild.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,141 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Exceptions;
|
||||
using Artemis.UI.PropertyInput;
|
||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline;
|
||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Humanizer;
|
||||
using Ninject;
|
||||
using Ninject.Parameters;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||
{
|
||||
public class LayerPropertyViewModel<T> : LayerPropertyViewModel
|
||||
public class LayerPropertyViewModel : PropertyChangedBase, IDisposable
|
||||
{
|
||||
private TimelinePropertyViewModel<T> _timelinePropertyViewModel;
|
||||
private TreePropertyViewModel<T> _treePropertyViewModel;
|
||||
|
||||
public LayerPropertyViewModel(IProfileEditorService profileEditorService, LayerProperty<T> layerProperty) : base(profileEditorService, layerProperty)
|
||||
public LayerPropertyViewModel(ILayerProperty layerProperty, IKernel kernel)
|
||||
{
|
||||
LayerProperty = layerProperty;
|
||||
|
||||
TreePropertyViewModel = CreateTreePropertyViewModel();
|
||||
TimelinePropertyViewModel = new TimelinePropertyViewModel<T>(this, profileEditorService);
|
||||
var parameter = new ConstructorArgument("layerProperty", LayerProperty);
|
||||
var treeViewModelType = typeof(LayerPropertyTreeViewModel<>).MakeGenericType(layerProperty.GetType().GetGenericArguments());
|
||||
var timelineViewModelType = typeof(LayerPropertyTimelineViewModel<>).MakeGenericType(layerProperty.GetType().GetGenericArguments());
|
||||
|
||||
TreePropertyBaseViewModel = TreePropertyViewModel;
|
||||
TimelinePropertyBaseViewModel = TimelinePropertyViewModel;
|
||||
|
||||
// Generate a fallback name if the description does not contain one
|
||||
if (LayerProperty.PropertyDescription.Name == null)
|
||||
{
|
||||
var propertyInfo = LayerProperty.Parent?.GetType().GetProperties().FirstOrDefault(p => ReferenceEquals(p.GetValue(LayerProperty.Parent), LayerProperty));
|
||||
if (propertyInfo != null)
|
||||
LayerProperty.PropertyDescription.Name = propertyInfo.Name.Humanize();
|
||||
else
|
||||
LayerProperty.PropertyDescription.Name = $"Unknown {typeof(T).Name} property";
|
||||
}
|
||||
|
||||
LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged;
|
||||
LayerPropertyTreeViewModel = (ILayerPropertyTreeViewModel) kernel.Get(treeViewModelType, parameter);
|
||||
LayerPropertyTimelineViewModel = (ILayerPropertyTimelineViewModel) kernel.Get(timelineViewModelType, parameter);
|
||||
}
|
||||
|
||||
public override bool IsVisible => !LayerProperty.IsHidden;
|
||||
public ILayerProperty LayerProperty { get; }
|
||||
public ILayerPropertyTreeViewModel LayerPropertyTreeViewModel { get; }
|
||||
public ILayerPropertyTimelineViewModel LayerPropertyTimelineViewModel { get; }
|
||||
|
||||
public LayerProperty<T> LayerProperty { get; }
|
||||
public bool IsVisible { get; set; }
|
||||
public bool IsExpanded { get; set; }
|
||||
|
||||
public TreePropertyViewModel<T> TreePropertyViewModel
|
||||
public void Dispose()
|
||||
{
|
||||
get => _treePropertyViewModel;
|
||||
set => SetAndNotify(ref _treePropertyViewModel, value);
|
||||
}
|
||||
|
||||
public TimelinePropertyViewModel<T> TimelinePropertyViewModel
|
||||
{
|
||||
get => _timelinePropertyViewModel;
|
||||
set => SetAndNotify(ref _timelinePropertyViewModel, value);
|
||||
}
|
||||
|
||||
public override List<BaseLayerPropertyKeyframe> GetKeyframes(bool expandedOnly)
|
||||
{
|
||||
if (LayerProperty.KeyframesEnabled && !LayerProperty.IsHidden)
|
||||
return LayerProperty.BaseKeyframes.ToList();
|
||||
return new List<BaseLayerPropertyKeyframe>();
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
TreePropertyViewModel.Dispose();
|
||||
TimelinePropertyViewModel.Dispose();
|
||||
|
||||
LayerProperty.VisibilityChanged -= LayerPropertyOnVisibilityChanged;
|
||||
}
|
||||
|
||||
public void SetCurrentValue(T value, bool saveChanges)
|
||||
{
|
||||
LayerProperty.SetCurrentValue(value, ProfileEditorService.CurrentTime);
|
||||
if (saveChanges)
|
||||
ProfileEditorService.UpdateSelectedProfileElement();
|
||||
else
|
||||
ProfileEditorService.UpdateProfilePreview();
|
||||
}
|
||||
|
||||
private TreePropertyViewModel<T> CreateTreePropertyViewModel()
|
||||
{
|
||||
// Make sure there is a supported property editor VM, unless the type is an enum, then we'll use the EnumPropertyInputViewModel
|
||||
Type vmType = null;
|
||||
if (typeof(T).IsEnum)
|
||||
vmType = typeof(EnumPropertyInputViewModel<>).MakeGenericType(typeof(T));
|
||||
else
|
||||
{
|
||||
var registration = ProfileEditorService.RegisteredPropertyEditors.FirstOrDefault(r => r.SupportedType == typeof(T));
|
||||
if (registration != null)
|
||||
vmType = registration.ViewModelType;
|
||||
}
|
||||
|
||||
if (vmType == null)
|
||||
throw new ArtemisUIException($"Cannot create a tree property view model for type {typeof(T)}, found no matching property editor");
|
||||
|
||||
var parameters = new IParameter[]
|
||||
{
|
||||
new ConstructorArgument("layerProperty", LayerProperty)
|
||||
};
|
||||
return new TreePropertyViewModel<T>(this, (PropertyInputViewModel<T>) ProfileEditorService.Kernel.Get(vmType, parameters), ProfileEditorService);
|
||||
}
|
||||
|
||||
private void LayerPropertyOnVisibilityChanged(object sender, EventArgs e)
|
||||
{
|
||||
NotifyOfPropertyChange(nameof(IsVisible));
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class LayerPropertyViewModel : LayerPropertyBaseViewModel
|
||||
{
|
||||
private TimelinePropertyViewModel _timelinePropertyBaseViewModel;
|
||||
private TreePropertyViewModel _treePropertyBaseViewModel;
|
||||
|
||||
protected LayerPropertyViewModel(IProfileEditorService profileEditorService, BaseLayerProperty baseLayerProperty)
|
||||
{
|
||||
ProfileEditorService = profileEditorService;
|
||||
BaseLayerProperty = baseLayerProperty;
|
||||
}
|
||||
|
||||
public IProfileEditorService ProfileEditorService { get; }
|
||||
public BaseLayerProperty BaseLayerProperty { get; }
|
||||
|
||||
public TreePropertyViewModel TreePropertyBaseViewModel
|
||||
{
|
||||
get => _treePropertyBaseViewModel;
|
||||
set => SetAndNotify(ref _treePropertyBaseViewModel, value);
|
||||
}
|
||||
|
||||
public TimelinePropertyViewModel TimelinePropertyBaseViewModel
|
||||
{
|
||||
get => _timelinePropertyBaseViewModel;
|
||||
set => SetAndNotify(ref _timelinePropertyBaseViewModel, value);
|
||||
LayerPropertyTreeViewModel?.Dispose();
|
||||
LayerPropertyTimelineViewModel?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using Artemis.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
||||
{
|
||||
public class LayerPropertyTimelineViewModel<T> : Screen, ILayerPropertyTimelineViewModel
|
||||
{
|
||||
public LayerProperty<T> LayerProperty { get; }
|
||||
public LayerPropertyViewModel LayerPropertyViewModel { get; }
|
||||
|
||||
public LayerPropertyTimelineViewModel(LayerProperty<T> layerProperty, LayerPropertyViewModel layerPropertyViewModel)
|
||||
{
|
||||
LayerProperty = layerProperty;
|
||||
LayerPropertyViewModel = layerPropertyViewModel;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public interface ILayerPropertyTimelineViewModel : IScreen, IDisposable
|
||||
{
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline.Rails
|
||||
{
|
||||
public class TimelineGroupViewModel
|
||||
{
|
||||
public LayerPropertyGroup LayerPropertyGroup { get; }
|
||||
|
||||
public TimelineGroupViewModel(LayerPropertyGroup layerPropertyGroup)
|
||||
{
|
||||
LayerPropertyGroup = layerPropertyGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-26
@@ -9,7 +9,7 @@
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:dd="urn:gong-wpf-dragdrop"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance local:TreePropertyGroupViewModel}"
|
||||
d:DataContext="{d:DesignInstance local:LayerPropertyGroupTreeViewModel}"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||
@@ -18,8 +18,8 @@
|
||||
<!-- Type: None -->
|
||||
<TextBlock
|
||||
dd:DragDrop.DragSourceIgnore="True"
|
||||
Text="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Name}"
|
||||
ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}"
|
||||
Text="{Binding LayerPropertyGroup.GroupDescription.Name}"
|
||||
ToolTip="{Binding LayerPropertyGroup.GroupDescription.Description}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="3 5 0 5">
|
||||
@@ -27,7 +27,7 @@
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="None">
|
||||
<DataTrigger Binding="{Binding GroupType}" Value="None">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
@@ -41,14 +41,14 @@
|
||||
<Style TargetType="{x:Type StackPanel}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="General">
|
||||
<DataTrigger Binding="{Binding GroupType}" Value="General">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<materialDesign:PackIcon Kind="HammerWrench" Margin="0 -1 5 0" />
|
||||
<TextBlock ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}">General</TextBlock>
|
||||
<TextBlock ToolTip="{Binding LayerPropertyGroup.GroupDescription.Description}">General</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Type: Transform -->
|
||||
@@ -57,14 +57,14 @@
|
||||
<Style TargetType="{x:Type StackPanel}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="Transform">
|
||||
<DataTrigger Binding="{Binding GroupType}" Value="Transform">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</StackPanel.Style>
|
||||
<materialDesign:PackIcon Kind="TransitConnectionVariant" Margin="0 -1 5 0" />
|
||||
<TextBlock ToolTip="{Binding LayerPropertyGroupViewModel.PropertyGroupDescription.Description}">Transform</TextBlock>
|
||||
<TextBlock ToolTip="{Binding LayerPropertyGroup.GroupDescription.Description}">Transform</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Type: LayerBrushRoot -->
|
||||
@@ -79,23 +79,23 @@
|
||||
<Style TargetType="{x:Type Grid}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="LayerBrushRoot">
|
||||
<DataTrigger Binding="{Binding GroupType}" Value="LayerBrushRoot">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Grid.Style>
|
||||
<materialDesign:PackIcon Grid.Column="0"
|
||||
Kind="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Icon}"
|
||||
Kind="{Binding LayerPropertyGroup.LayerBrush.Descriptor.Icon}"
|
||||
Margin="0 5 5 0" />
|
||||
<TextBlock Grid.Column="1"
|
||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Description}"
|
||||
ToolTip="{Binding LayerPropertyGroup.LayerBrush.Descriptor.Description}"
|
||||
Margin="0 5 0 0">
|
||||
Brush - 
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="2"
|
||||
Text="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.DisplayName}"
|
||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.Descriptor.Description}"
|
||||
Text="{Binding LayerPropertyGroup.LayerBrush.Descriptor.DisplayName}"
|
||||
ToolTip="{Binding LayerPropertyGroup.LayerBrush.Descriptor.Description}"
|
||||
Margin="0 5 0 0" />
|
||||
|
||||
<Button Grid.Column="3"
|
||||
@@ -106,7 +106,7 @@
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{s:Action OpenBrushSettings}"
|
||||
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.ConfigurationDialog, Converter={StaticResource NullToVisibilityConverter}}">
|
||||
Visibility="{Binding LayerPropertyGroup.LayerBrush.ConfigurationDialog, Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<materialDesign:PackIcon Kind="Settings" Height="16" Width="16" />
|
||||
</Button>
|
||||
</Grid>
|
||||
@@ -125,7 +125,7 @@
|
||||
<Style TargetType="{x:Type Grid}">
|
||||
<Setter Property="Visibility" Value="Collapsed" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding LayerPropertyGroupViewModel.GroupType}" Value="LayerEffectRoot">
|
||||
<DataTrigger Binding="{Binding GroupType}" Value="LayerEffectRoot">
|
||||
<Setter Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
@@ -134,29 +134,29 @@
|
||||
<materialDesign:PackIcon
|
||||
Grid.Column="0"
|
||||
Cursor="SizeNS"
|
||||
Kind="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Icon}"
|
||||
Kind="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Icon}"
|
||||
Margin="0 5 5 0"
|
||||
Background="Transparent" />
|
||||
<TextBlock Grid.Column="1" ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}" Margin="0 5 0 0">
|
||||
<TextBlock Grid.Column="1" ToolTip="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Description}" Margin="0 5 0 0">
|
||||
Effect
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="2"
|
||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||
ToolTip="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||
Margin="3 5">
|
||||
-
|
||||
</TextBlock>
|
||||
|
||||
<!-- Show either the descriptors display name or, if set, the effect name -->
|
||||
<TextBlock Grid.Column="3"
|
||||
Text="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.DisplayName}"
|
||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||
Text="{Binding LayerPropertyGroup.LayerEffect.Descriptor.DisplayName}"
|
||||
ToolTip="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||
Margin="0 5"
|
||||
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
||||
Visibility="{Binding LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
||||
<TextBlock Grid.Column="4"
|
||||
Text="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name}"
|
||||
ToolTip="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||
Text="{Binding LayerPropertyGroup.LayerEffect.Name}"
|
||||
ToolTip="{Binding LayerPropertyGroup.LayerEffect.Descriptor.Description}"
|
||||
Margin="0 5"
|
||||
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}}" />
|
||||
Visibility="{Binding LayerPropertyGroup.LayerEffect.Name, Converter={StaticResource NullToVisibilityConverter}}" />
|
||||
|
||||
<StackPanel Grid.Column="5" Orientation="Horizontal">
|
||||
<ToggleButton
|
||||
@@ -164,7 +164,7 @@
|
||||
ToolTip="Toggle enabled state"
|
||||
Width="18"
|
||||
Height="18"
|
||||
IsChecked="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Enabled}"
|
||||
IsChecked="{Binding LayerPropertyGroup.LayerEffect.Enabled}"
|
||||
VerticalAlignment="Center" Padding="-25"
|
||||
Margin="5 0"
|
||||
Command="{s:Action EnableToggled}">
|
||||
@@ -184,7 +184,7 @@
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Command="{s:Action OpenEffectSettings}"
|
||||
Visibility="{Binding LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.ConfigurationDialog, Converter={StaticResource NullToVisibilityConverter}}">
|
||||
Visibility="{Binding LayerPropertyGroup.LayerEffect.ConfigurationDialog, Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<materialDesign:PackIcon Kind="Settings" Height="16" Width="16" />
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignIconButton}"
|
||||
+42
-15
@@ -1,13 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Artemis.Core.LayerEffects;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Exceptions;
|
||||
using Artemis.UI.Screens.ProfileEditor.Dialogs;
|
||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
||||
using Artemis.UI.Screens.ProfileEditor.Windows;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Ninject;
|
||||
using Ninject.Parameters;
|
||||
@@ -15,34 +14,36 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||
{
|
||||
public class TreePropertyGroupViewModel : PropertyChangedBase
|
||||
public class LayerPropertyGroupTreeViewModel : PropertyChangedBase
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IKernel _kernel;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IRenderElementService _renderElementService;
|
||||
private readonly IWindowManager _windowManager;
|
||||
|
||||
public TreePropertyGroupViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel,
|
||||
public LayerPropertyGroupTreeViewModel(
|
||||
LayerPropertyGroupViewModel layerPropertyGroupViewModel,
|
||||
IProfileEditorService profileEditorService,
|
||||
IRenderElementService renderElementService,
|
||||
IDialogService dialogService,
|
||||
IWindowManager windowManager,
|
||||
IKernel kernel)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_renderElementService = renderElementService;
|
||||
_dialogService = dialogService;
|
||||
_windowManager = windowManager;
|
||||
_kernel = kernel;
|
||||
LayerPropertyGroupViewModel = (LayerPropertyGroupViewModel) layerPropertyBaseViewModel;
|
||||
|
||||
LayerPropertyGroupViewModel = layerPropertyGroupViewModel;
|
||||
LayerPropertyGroup = LayerPropertyGroupViewModel.LayerPropertyGroup;
|
||||
}
|
||||
|
||||
public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; }
|
||||
public LayerPropertyGroup LayerPropertyGroup { get; }
|
||||
public LayerPropertyGroupType GroupType { get; set; }
|
||||
|
||||
public void OpenBrushSettings()
|
||||
{
|
||||
var layerBrush = LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush;
|
||||
var layerBrush = LayerPropertyGroup.LayerBrush;
|
||||
var configurationViewModel = layerBrush.ConfigurationDialog;
|
||||
if (configurationViewModel == null)
|
||||
return;
|
||||
@@ -69,7 +70,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||
|
||||
public void OpenEffectSettings()
|
||||
{
|
||||
var layerEffect = LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect;
|
||||
var layerEffect = LayerPropertyGroup.LayerEffect;
|
||||
var configurationViewModel = layerEffect.ConfigurationDialog;
|
||||
if (configurationViewModel == null)
|
||||
return;
|
||||
@@ -100,20 +101,23 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{"subject", "effect"},
|
||||
{"currentName", LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name}
|
||||
{"currentName", LayerPropertyGroup.LayerEffect.Name}
|
||||
}
|
||||
);
|
||||
if (result is string newName)
|
||||
{
|
||||
LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.Name = newName;
|
||||
LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.HasBeenRenamed = true;
|
||||
LayerPropertyGroup.LayerEffect.Name = newName;
|
||||
LayerPropertyGroup.LayerEffect.HasBeenRenamed = true;
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteEffect()
|
||||
{
|
||||
_renderElementService.RemoveLayerEffect(LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect);
|
||||
if (LayerPropertyGroup.LayerEffect == null)
|
||||
return;
|
||||
|
||||
LayerPropertyGroup.ProfileElement.RemoveLayerEffect(LayerPropertyGroup.LayerEffect);
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
|
||||
@@ -121,5 +125,28 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||
{
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
|
||||
private void DetermineGroupType()
|
||||
{
|
||||
if (LayerPropertyGroup is LayerGeneralProperties)
|
||||
GroupType = LayerPropertyGroupType.General;
|
||||
else if (LayerPropertyGroup is LayerTransformProperties)
|
||||
GroupType = LayerPropertyGroupType.Transform;
|
||||
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerBrush != null)
|
||||
GroupType = LayerPropertyGroupType.LayerBrushRoot;
|
||||
else if (LayerPropertyGroup.Parent == null && LayerPropertyGroup.LayerEffect != null)
|
||||
GroupType = LayerPropertyGroupType.LayerEffectRoot;
|
||||
else
|
||||
GroupType = LayerPropertyGroupType.None;
|
||||
}
|
||||
|
||||
public enum LayerPropertyGroupType
|
||||
{
|
||||
General,
|
||||
Transform,
|
||||
LayerBrushRoot,
|
||||
LayerEffectRoot,
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-8
@@ -1,14 +1,12 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree.TreePropertyView"
|
||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree.LayerPropertyTreeView"
|
||||
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"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:tree="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type tree:TreePropertyViewModel}}">
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid Height="22" Margin="-20 0 0 0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -22,7 +20,7 @@
|
||||
Width="18"
|
||||
Height="18"
|
||||
IsChecked="{Binding KeyframesEnabled}"
|
||||
IsEnabled="{Binding LayerPropertyViewModel.LayerProperty.KeyframesSupported}"
|
||||
IsEnabled="{Binding LayerProperty.KeyframesSupported}"
|
||||
VerticalAlignment="Center" Padding="-25">
|
||||
<materialDesign:PackIcon Kind="Stopwatch" Height="13" Width="13" />
|
||||
</ToggleButton>
|
||||
@@ -32,8 +30,8 @@
|
||||
Padding="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Text="{Binding LayerPropertyViewModel.LayerProperty.PropertyDescription.Name}"
|
||||
ToolTip="{Binding LayerPropertyViewModel.LayerProperty.PropertyDescription.Description}"
|
||||
Text="{Binding LayerProperty.PropertyDescription.Name}"
|
||||
ToolTip="{Binding LayerProperty.PropertyDescription.Description}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<ContentControl Grid.Column="2" Margin="20 0" s:View.Model="{Binding PropertyInputViewModel}">
|
||||
@@ -51,7 +49,7 @@
|
||||
Width="20"
|
||||
Height="20"
|
||||
VerticalAlignment="Center"
|
||||
IsEnabled="{Binding LayerPropertyViewModel.LayerProperty.DataBindingsSupported}"
|
||||
IsEnabled="{Binding LayerProperty.DataBindingsSupported}"
|
||||
IsChecked="{Binding DataBindingsOpen}">
|
||||
<materialDesign:PackIcon Kind="VectorLink" Height="13" Width="13" />
|
||||
</ToggleButton>
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||
{
|
||||
public class LayerPropertyTreeViewModel<T> : Screen, ILayerPropertyTreeViewModel
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private PropertyInputViewModel<T> _propertyInputViewModel;
|
||||
|
||||
public LayerPropertyTreeViewModel(LayerProperty<T> layerProperty, LayerPropertyViewModel layerPropertyViewModel, IProfileEditorService profileEditorService)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
LayerProperty = layerProperty;
|
||||
LayerPropertyViewModel = layerPropertyViewModel;
|
||||
|
||||
PropertyInputViewModel = _profileEditorService.CreatePropertyInputViewModel(LayerProperty);
|
||||
_profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged;
|
||||
}
|
||||
|
||||
public LayerProperty<T> LayerProperty { get; }
|
||||
public LayerPropertyViewModel LayerPropertyViewModel { get; }
|
||||
|
||||
public PropertyInputViewModel<T> PropertyInputViewModel
|
||||
{
|
||||
get => _propertyInputViewModel;
|
||||
set => SetAndNotify(ref _propertyInputViewModel, value);
|
||||
}
|
||||
|
||||
public bool HasPropertyInputViewModel => PropertyInputViewModel != null;
|
||||
|
||||
public bool KeyframesEnabled
|
||||
{
|
||||
get => LayerProperty.KeyframesEnabled;
|
||||
set => ApplyKeyframesEnabled(value);
|
||||
}
|
||||
|
||||
public bool DataBindingsOpen
|
||||
{
|
||||
get => _profileEditorService.SelectedDataBinding == LayerProperty;
|
||||
set => _profileEditorService.ChangeSelectedDataBinding(value ? LayerProperty : null);
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_propertyInputViewModel?.Dispose();
|
||||
_profileEditorService.SelectedDataBindingChanged -= ProfileEditorServiceOnSelectedDataBindingChanged;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void ApplyKeyframesEnabled(bool enable)
|
||||
{
|
||||
// If enabling keyframes for the first time, add a keyframe with the current value at the current position
|
||||
if (enable && !LayerProperty.Keyframes.Any())
|
||||
{
|
||||
LayerProperty.AddKeyframe(new LayerPropertyKeyframe<T>(
|
||||
LayerProperty.CurrentValue,
|
||||
_profileEditorService.CurrentTime,
|
||||
Easings.Functions.Linear,
|
||||
LayerProperty
|
||||
));
|
||||
}
|
||||
// If disabling keyframes, set the base value to the current value
|
||||
else if (!enable && LayerProperty.Keyframes.Any())
|
||||
LayerProperty.BaseValue = LayerProperty.CurrentValue;
|
||||
|
||||
LayerProperty.KeyframesEnabled = enable;
|
||||
|
||||
_profileEditorService.UpdateSelectedProfileElement();
|
||||
}
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void ProfileEditorServiceOnSelectedDataBindingChanged(object sender, EventArgs e)
|
||||
{
|
||||
NotifyOfPropertyChange(nameof(DataBindingsOpen));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public interface ILayerPropertyTreeViewModel : IScreen, IDisposable
|
||||
{
|
||||
bool HasPropertyInputViewModel { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||
{
|
||||
public class TreePropertyViewModel<T> : TreePropertyViewModel
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private PropertyInputViewModel<T> _propertyInputViewModel;
|
||||
|
||||
public TreePropertyViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel, PropertyInputViewModel<T> propertyInputViewModel,
|
||||
IProfileEditorService profileEditorService) : base(layerPropertyBaseViewModel)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
LayerPropertyViewModel = (LayerPropertyViewModel<T>) layerPropertyBaseViewModel;
|
||||
PropertyInputViewModel = propertyInputViewModel;
|
||||
|
||||
_profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged;
|
||||
}
|
||||
|
||||
public LayerPropertyViewModel<T> LayerPropertyViewModel { get; }
|
||||
|
||||
public PropertyInputViewModel<T> PropertyInputViewModel
|
||||
{
|
||||
get => _propertyInputViewModel;
|
||||
set => SetAndNotify(ref _propertyInputViewModel, value);
|
||||
}
|
||||
|
||||
public bool KeyframesEnabled
|
||||
{
|
||||
get => LayerPropertyViewModel.LayerProperty.KeyframesEnabled;
|
||||
set => ApplyKeyframesEnabled(value);
|
||||
}
|
||||
|
||||
public bool DataBindingsOpen
|
||||
{
|
||||
get => _profileEditorService.SelectedDataBinding == LayerPropertyViewModel.BaseLayerProperty;
|
||||
set => _profileEditorService.ChangeSelectedDataBinding(value ? LayerPropertyViewModel.BaseLayerProperty : null);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
PropertyInputViewModel.Dispose();
|
||||
}
|
||||
|
||||
private void ProfileEditorServiceOnSelectedDataBindingChanged(object sender, EventArgs e)
|
||||
{
|
||||
NotifyOfPropertyChange(nameof(DataBindingsOpen));
|
||||
}
|
||||
|
||||
private void ApplyKeyframesEnabled(bool enable)
|
||||
{
|
||||
// If enabling keyframes for the first time, add a keyframe with the current value at the current position
|
||||
if (enable && !LayerPropertyViewModel.LayerProperty.Keyframes.Any())
|
||||
{
|
||||
LayerPropertyViewModel.LayerProperty.AddKeyframe(new LayerPropertyKeyframe<T>(
|
||||
LayerPropertyViewModel.LayerProperty.CurrentValue,
|
||||
_profileEditorService.CurrentTime,
|
||||
Easings.Functions.Linear,
|
||||
LayerPropertyViewModel.LayerProperty
|
||||
));
|
||||
}
|
||||
// If disabling keyframes, set the base value to the current value
|
||||
else if (!enable && LayerPropertyViewModel.LayerProperty.Keyframes.Any())
|
||||
LayerPropertyViewModel.LayerProperty.BaseValue = LayerPropertyViewModel.LayerProperty.CurrentValue;
|
||||
|
||||
LayerPropertyViewModel.LayerProperty.KeyframesEnabled = enable;
|
||||
|
||||
_profileEditorService.UpdateSelectedProfileElement();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class TreePropertyViewModel : PropertyChangedBase, IDisposable
|
||||
{
|
||||
protected TreePropertyViewModel(LayerPropertyBaseViewModel layerPropertyBaseViewModel)
|
||||
{
|
||||
LayerPropertyBaseViewModel = layerPropertyBaseViewModel;
|
||||
}
|
||||
|
||||
public LayerPropertyBaseViewModel LayerPropertyBaseViewModel { get; }
|
||||
|
||||
public abstract void Dispose();
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:dd="urn:gong-wpf-dragdrop"
|
||||
xmlns:tree="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree"
|
||||
xmlns:layerProperties1="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type tree:TreeViewModel}}">
|
||||
@@ -98,11 +98,11 @@
|
||||
</Style>
|
||||
</TreeView.ItemContainerStyle>
|
||||
<TreeView.Resources>
|
||||
<HierarchicalDataTemplate DataType="{x:Type layerProperties1:LayerPropertyGroupViewModel}" ItemsSource="{Binding Children}">
|
||||
<ContentControl s:View.Model="{Binding TreePropertyGroupViewModel}" />
|
||||
<HierarchicalDataTemplate DataType="{x:Type local:LayerPropertyGroupViewModel}" ItemsSource="{Binding Items}">
|
||||
<ContentControl s:View.Model="{Binding LayerPropertyGroupTreeViewModel}" />
|
||||
</HierarchicalDataTemplate>
|
||||
<DataTemplate DataType="{x:Type layerProperties1:LayerPropertyViewModel}">
|
||||
<ContentControl s:View.Model="{Binding TreePropertyBaseViewModel}" dd:DragDrop.DragSourceIgnore="True" />
|
||||
<DataTemplate DataType="{x:Type local:LayerPropertyViewModel}">
|
||||
<ContentControl s:View.Model="{Binding LayerPropertyTreeViewModel}" dd:DragDrop.DragSourceIgnore="True" />
|
||||
</DataTemplate>
|
||||
</TreeView.Resources>
|
||||
</TreeView>
|
||||
|
||||
@@ -5,11 +5,13 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree
|
||||
{
|
||||
public class TreeViewModel : PropertyChangedBase
|
||||
public class TreeViewModel : Screen
|
||||
{
|
||||
public TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection<LayerPropertyGroupViewModel> layerPropertyGroups)
|
||||
{
|
||||
LayerPropertiesViewModel = layerPropertiesViewModel;
|
||||
|
||||
// Not using the Items collection because the list should persist even after this VM gets closed
|
||||
LayerPropertyGroups = layerPropertyGroups;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor
|
||||
{
|
||||
public class ProfileEditorViewModel : Conductor<ProfileEditorPanelViewModel>.Collection.AllActive
|
||||
public class ProfileEditorViewModel : Conductor<IProfileEditorPanelViewModel>.Collection.AllActive
|
||||
{
|
||||
private readonly IModuleService _moduleService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
@@ -36,7 +36,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
||||
private PluginSetting<GridLength> _sidePanelsWidth;
|
||||
|
||||
public ProfileEditorViewModel(ProfileModule module,
|
||||
ICollection<ProfileEditorPanelViewModel> viewModels,
|
||||
ICollection<IProfileEditorPanelViewModel> viewModels,
|
||||
IProfileEditorService profileEditorService,
|
||||
IProfileService profileService,
|
||||
IDialogService dialogService,
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</StackPanel>
|
||||
|
||||
<TreeView Grid.Row="1"
|
||||
ItemsSource="{Binding RootFolder.Children}"
|
||||
ItemsSource="{Binding ActiveItem.Items}"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
dd:DragDrop.IsDragSource="True"
|
||||
dd:DragDrop.IsDropTarget="True"
|
||||
@@ -36,11 +36,11 @@
|
||||
<behaviors:TreeViewSelectionBehavior ExpandSelected="True" SelectedItem="{Binding SelectedTreeItem}" />
|
||||
</b:Interaction.Behaviors>
|
||||
<TreeView.Resources>
|
||||
<HierarchicalDataTemplate DataType="{x:Type treeItem1:FolderViewModel}" ItemsSource="{Binding Children}">
|
||||
<HierarchicalDataTemplate DataType="{x:Type treeItem1:FolderViewModel}" ItemsSource="{Binding Items}">
|
||||
<ContentControl s:View.Model="{Binding}" />
|
||||
</HierarchicalDataTemplate>
|
||||
<!-- TODO: Ensure this item source is required -->
|
||||
<HierarchicalDataTemplate DataType="{x:Type treeItem1:LayerViewModel}" ItemsSource="{Binding Children}">
|
||||
<HierarchicalDataTemplate DataType="{x:Type treeItem1:LayerViewModel}" ItemsSource="{Binding Items}">
|
||||
<ContentControl s:View.Model="{Binding}" />
|
||||
</HierarchicalDataTemplate>
|
||||
</TreeView.Resources>
|
||||
|
||||
@@ -11,24 +11,17 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
{
|
||||
public class ProfileTreeViewModel : ProfileEditorPanelViewModel, IDropTarget
|
||||
public class ProfileTreeViewModel : Conductor<FolderViewModel>, IProfileEditorPanelViewModel, IDropTarget
|
||||
{
|
||||
private readonly IFolderVmFactory _folderVmFactory;
|
||||
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private FolderViewModel _rootFolder;
|
||||
private TreeItemViewModel _selectedTreeItem;
|
||||
private bool _updatingTree;
|
||||
|
||||
public ProfileTreeViewModel(IProfileEditorService profileEditorService, IFolderVmFactory folderVmFactory)
|
||||
public ProfileTreeViewModel(IProfileEditorService profileEditorService, IProfileTreeVmFactory profileTreeVmFactory)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_folderVmFactory = folderVmFactory;
|
||||
}
|
||||
|
||||
public FolderViewModel RootFolder
|
||||
{
|
||||
get => _rootFolder;
|
||||
set => SetAndNotify(ref _rootFolder, value);
|
||||
_profileTreeVmFactory = profileTreeVmFactory;
|
||||
}
|
||||
|
||||
public TreeItemViewModel SelectedTreeItem
|
||||
@@ -73,7 +66,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
switch (dragDropType)
|
||||
{
|
||||
case DragDropType.Add:
|
||||
source.Parent.RemoveExistingElement(source);
|
||||
((TreeItemViewModel) source.Parent).RemoveExistingElement(source);
|
||||
target.AddExistingElement(source);
|
||||
break;
|
||||
case DragDropType.InsertBefore:
|
||||
@@ -92,27 +85,25 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
// ReSharper disable once UnusedMember.Global - Called from view
|
||||
public void AddFolder()
|
||||
{
|
||||
RootFolder?.AddFolder();
|
||||
ActiveItem?.AddFolder();
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedMember.Global - Called from view
|
||||
public void AddLayer()
|
||||
{
|
||||
RootFolder?.AddLayer();
|
||||
ActiveItem?.AddLayer();
|
||||
}
|
||||
|
||||
protected override void OnInitialActivate()
|
||||
{
|
||||
Subscribe();
|
||||
CreateRootFolderViewModel();
|
||||
base.OnInitialActivate();
|
||||
}
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
Unsubscribe();
|
||||
|
||||
RootFolder?.Dispose();
|
||||
RootFolder = null;
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
@@ -122,12 +113,11 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
var firstChild = _profileEditorService.SelectedProfile?.Children?.FirstOrDefault();
|
||||
if (!(firstChild is Folder folder))
|
||||
{
|
||||
RootFolder = null;
|
||||
ActivateItem(null);
|
||||
return;
|
||||
}
|
||||
|
||||
RootFolder?.Dispose();
|
||||
RootFolder = _folderVmFactory.Create(folder);
|
||||
ActivateItem(_profileTreeVmFactory.FolderViewModel(folder));
|
||||
_updatingTree = false;
|
||||
|
||||
// Auto-select the first layer
|
||||
@@ -150,7 +140,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
{
|
||||
if (parent == source)
|
||||
return DragDropType.None;
|
||||
parent = parent.Parent;
|
||||
parent = (TreeItemViewModel) parent.Parent;
|
||||
}
|
||||
|
||||
switch (dropInfo.InsertPosition)
|
||||
@@ -186,20 +176,20 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
||||
if (e.RenderProfileElement == SelectedTreeItem?.ProfileElement)
|
||||
return;
|
||||
|
||||
if (RootFolder == null)
|
||||
if (ActiveItem == null)
|
||||
{
|
||||
CreateRootFolderViewModel();
|
||||
return;
|
||||
}
|
||||
|
||||
_updatingTree = true;
|
||||
RootFolder.UpdateProfileElements();
|
||||
ActiveItem.UpdateProfileElements();
|
||||
_updatingTree = false;
|
||||
if (e.RenderProfileElement == null)
|
||||
SelectedTreeItem = null;
|
||||
else
|
||||
{
|
||||
var match = RootFolder.GetAllChildren().FirstOrDefault(vm => vm.ProfileElement == e.RenderProfileElement);
|
||||
var match = ActiveItem.GetAllChildren().FirstOrDefault(vm => vm.ProfileElement == e.RenderProfileElement);
|
||||
if (match != null)
|
||||
SelectedTreeItem = match;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared.Services;
|
||||
|
||||
@@ -11,36 +10,11 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
public FolderViewModel(ProfileElement folder,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IRenderElementService renderElementService,
|
||||
IFolderVmFactory folderVmFactory,
|
||||
ILayerVmFactory layerVmFactory) :
|
||||
base(null, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public FolderViewModel(TreeItemViewModel parent,
|
||||
ProfileElement folder,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IRenderElementService renderElementService,
|
||||
IFolderVmFactory folderVmFactory,
|
||||
ILayerVmFactory layerVmFactory) :
|
||||
base(parent, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
|
||||
IProfileTreeVmFactory profileTreeVmFactory) :
|
||||
base(folder, profileEditorService, dialogService, profileTreeVmFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool SupportsChildren => true;
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
foreach (var treeItemViewModel in Children)
|
||||
treeItemViewModel.Dispose();
|
||||
Children.Clear();
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Shared.Services;
|
||||
|
||||
@@ -7,14 +6,11 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
public class LayerViewModel : TreeItemViewModel
|
||||
{
|
||||
public LayerViewModel(TreeItemViewModel parent,
|
||||
ProfileElement folder,
|
||||
public LayerViewModel(ProfileElement layer,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IRenderElementService renderElementService,
|
||||
IFolderVmFactory folderVmFactory,
|
||||
ILayerVmFactory layerVmFactory) :
|
||||
base(parent, folder, profileEditorService, dialogService, renderElementService, folderVmFactory, layerVmFactory)
|
||||
IProfileTreeVmFactory profileTreeVmFactory) :
|
||||
base(layer, profileEditorService, dialogService, profileTreeVmFactory)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ 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;
|
||||
@@ -12,66 +11,45 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
public abstract class TreeItemViewModel : PropertyChangedBase, IDisposable
|
||||
public abstract class TreeItemViewModel : Conductor<TreeItemViewModel>.Collection.AllActive, IDisposable
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IFolderVmFactory _folderVmFactory;
|
||||
private readonly ILayerVmFactory _layerVmFactory;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IRenderElementService _renderElementService;
|
||||
private TreeItemViewModel _parent;
|
||||
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||
private ProfileElement _profileElement;
|
||||
|
||||
protected TreeItemViewModel(TreeItemViewModel parent,
|
||||
ProfileElement profileElement,
|
||||
protected TreeItemViewModel(ProfileElement profileElement,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDialogService dialogService,
|
||||
IRenderElementService renderElementService,
|
||||
IFolderVmFactory folderVmFactory,
|
||||
ILayerVmFactory layerVmFactory)
|
||||
IProfileTreeVmFactory profileTreeVmFactory)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dialogService = dialogService;
|
||||
_renderElementService = renderElementService;
|
||||
_folderVmFactory = folderVmFactory;
|
||||
_layerVmFactory = layerVmFactory;
|
||||
_profileTreeVmFactory = profileTreeVmFactory;
|
||||
|
||||
Parent = parent;
|
||||
ProfileElement = profileElement;
|
||||
|
||||
Children = new BindableCollection<TreeItemViewModel>();
|
||||
|
||||
Subscribe();
|
||||
UpdateProfileElements();
|
||||
}
|
||||
|
||||
public TreeItemViewModel Parent
|
||||
{
|
||||
get => _parent;
|
||||
set => SetAndNotify(ref _parent, value);
|
||||
}
|
||||
|
||||
public ProfileElement ProfileElement
|
||||
{
|
||||
get => _profileElement;
|
||||
set => SetAndNotify(ref _profileElement, value);
|
||||
}
|
||||
|
||||
public BindableCollection<TreeItemViewModel> Children { get; }
|
||||
|
||||
public abstract bool SupportsChildren { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Unsubscribe();
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public List<TreeItemViewModel> GetAllChildren()
|
||||
{
|
||||
var children = new List<TreeItemViewModel>();
|
||||
foreach (var childFolder in Children)
|
||||
foreach (var childFolder in Items)
|
||||
{
|
||||
// Add all children in this element
|
||||
children.Add(childFolder);
|
||||
@@ -84,34 +62,38 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
|
||||
public void SetElementInFront(TreeItemViewModel source)
|
||||
{
|
||||
var sourceParent = (TreeItemViewModel) source.Parent;
|
||||
var parent = (TreeItemViewModel) Parent;
|
||||
if (source.Parent != Parent)
|
||||
{
|
||||
source.Parent.RemoveExistingElement(source);
|
||||
Parent.AddExistingElement(source);
|
||||
sourceParent.RemoveExistingElement(source);
|
||||
parent.AddExistingElement(source);
|
||||
}
|
||||
|
||||
Parent.Unsubscribe();
|
||||
Parent.ProfileElement.RemoveChild(source.ProfileElement);
|
||||
Parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order);
|
||||
Parent.Subscribe();
|
||||
parent.Unsubscribe();
|
||||
parent.ProfileElement.RemoveChild(source.ProfileElement);
|
||||
parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order);
|
||||
parent.Subscribe();
|
||||
|
||||
Parent.UpdateProfileElements();
|
||||
parent.UpdateProfileElements();
|
||||
}
|
||||
|
||||
public void SetElementBehind(TreeItemViewModel source)
|
||||
{
|
||||
var sourceParent = (TreeItemViewModel) source.Parent;
|
||||
var parent = (TreeItemViewModel) Parent;
|
||||
if (source.Parent != Parent)
|
||||
{
|
||||
source.Parent.RemoveExistingElement(source);
|
||||
Parent.AddExistingElement(source);
|
||||
sourceParent.RemoveExistingElement(source);
|
||||
parent.AddExistingElement(source);
|
||||
}
|
||||
|
||||
Parent.Unsubscribe();
|
||||
Parent.ProfileElement.RemoveChild(source.ProfileElement);
|
||||
Parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order + 1);
|
||||
Parent.Subscribe();
|
||||
parent.Unsubscribe();
|
||||
parent.ProfileElement.RemoveChild(source.ProfileElement);
|
||||
parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order + 1);
|
||||
parent.Subscribe();
|
||||
|
||||
Parent.UpdateProfileElements();
|
||||
parent.UpdateProfileElements();
|
||||
}
|
||||
|
||||
public void RemoveExistingElement(TreeItemViewModel treeItem)
|
||||
@@ -138,7 +120,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
if (!SupportsChildren)
|
||||
throw new ArtemisUIException("Cannot add a folder to a profile element of type " + ProfileElement.GetType().Name);
|
||||
|
||||
ProfileElement.AddChild(new Folder(ProfileElement.Profile, ProfileElement, "New folder"));
|
||||
var _ = new Folder(ProfileElement, "New folder");
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
|
||||
@@ -147,7 +129,7 @@ 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);
|
||||
|
||||
_renderElementService.CreateLayer(ProfileElement.Profile, ProfileElement, "New layer");
|
||||
var _ = new Layer(ProfileElement, "New layer");
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
|
||||
@@ -180,7 +162,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
return;
|
||||
|
||||
// Farewell, cruel world
|
||||
var parent = Parent;
|
||||
var parent = (TreeItemViewModel) Parent;
|
||||
ProfileElement.Parent?.RemoveChild(ProfileElement);
|
||||
parent.RemoveExistingElement(this);
|
||||
|
||||
@@ -190,17 +172,17 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
public void UpdateProfileElements()
|
||||
{
|
||||
// Remove VMs that are no longer a child
|
||||
var toRemove = Children.Where(c => c.ProfileElement.Parent != ProfileElement).ToList();
|
||||
var toRemove = Items.Where(c => c.ProfileElement.Parent != ProfileElement).ToList();
|
||||
foreach (var treeItemViewModel in toRemove)
|
||||
Children.Remove(treeItemViewModel);
|
||||
DeactivateItem(treeItemViewModel);
|
||||
|
||||
// Order the children
|
||||
var vmsList = Children.OrderBy(v => v.ProfileElement.Order).ToList();
|
||||
var vmsList = Items.OrderBy(v => v.ProfileElement.Order).ToList();
|
||||
for (var index = 0; index < vmsList.Count; index++)
|
||||
{
|
||||
var profileElementViewModel = vmsList[index];
|
||||
if (Children.IndexOf(profileElementViewModel) != index)
|
||||
Children.Move(Children.IndexOf(profileElementViewModel), index);
|
||||
if (Items.IndexOf(profileElementViewModel) != index)
|
||||
((BindableCollection<TreeItemViewModel>) Items).Move(Items.IndexOf(profileElementViewModel), index);
|
||||
}
|
||||
|
||||
// Ensure every child element has an up-to-date VM
|
||||
@@ -212,13 +194,13 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
if (profileElement is Folder folder)
|
||||
{
|
||||
if (Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder) == null)
|
||||
newChildren.Add(_folderVmFactory.Create((FolderViewModel) this, folder));
|
||||
if (Items.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder) == null)
|
||||
newChildren.Add(_profileTreeVmFactory.FolderViewModel(folder));
|
||||
}
|
||||
else if (profileElement is Layer layer)
|
||||
{
|
||||
if (Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer) == null)
|
||||
newChildren.Add(_layerVmFactory.Create((FolderViewModel) this, layer));
|
||||
if (Items.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer) == null)
|
||||
newChildren.Add(_profileTreeVmFactory.LayerViewModel(layer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +211,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
foreach (var treeItemViewModel in newChildren)
|
||||
{
|
||||
treeItemViewModel.UpdateProfileElements();
|
||||
Children.Add(treeItemViewModel);
|
||||
ActivateItem(treeItemViewModel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,13 +220,6 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
_profileEditorService.UpdateSelectedProfile();
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void Subscribe()
|
||||
{
|
||||
ProfileElement.ChildAdded += ProfileElementOnChildAdded;
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.Visualization.ProfileDeviceView"
|
||||
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:converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:visualization1="clr-namespace:Artemis.UI.Screens.ProfileEditor.Visualization"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type visualization1:ProfileDeviceViewModel}}">
|
||||
<UserControl.Resources>
|
||||
<converters:NullToImageConverter x:Key="NullToImageConverter" />
|
||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Width="{Binding Device.RgbDevice.ActualSize.Width}" Height="{Binding Device.RgbDevice.ActualSize.Height}">
|
||||
<Grid.RenderTransform>
|
||||
<RotateTransform Angle="{Binding Device.Rotation}" />
|
||||
</Grid.RenderTransform>
|
||||
|
||||
<!-- Device image with fallback -->
|
||||
<Image VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
Source="{Binding Device.RgbDevice.DeviceInfo.Image, Converter={StaticResource NullToImageConverter}}" />
|
||||
|
||||
<Rectangle Fill="{DynamicResource MaterialDesignCardBackground}"
|
||||
Stroke="{DynamicResource MaterialDesignTextBoxBorder}"
|
||||
Margin="-5"
|
||||
StrokeThickness="1"
|
||||
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}" />
|
||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}"
|
||||
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
TextAlignment="Center" />
|
||||
|
||||
<!-- LEDs -->
|
||||
<ItemsControl ItemsSource="{Binding Leds}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemContainerStyle>
|
||||
<Style TargetType="{x:Type ContentPresenter}">
|
||||
<Setter Property="Canvas.Left" Value="{Binding X}" />
|
||||
<Setter Property="Canvas.Top" Value="{Binding Y}" />
|
||||
</Style>
|
||||
</ItemsControl.ItemContainerStyle>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentControl Width="{Binding Width}" Height="{Binding Height}" s:View.Model="{Binding}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -1,96 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Artemis.Core;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
public class ProfileDeviceViewModel : CanvasViewModel
|
||||
{
|
||||
private bool _addedLeds;
|
||||
private ArtemisDevice _device;
|
||||
private ObservableCollection<ProfileLedViewModel> _leds;
|
||||
|
||||
public ProfileDeviceViewModel(ArtemisDevice device)
|
||||
{
|
||||
Device = device;
|
||||
Leds = new ObservableCollection<ProfileLedViewModel>();
|
||||
|
||||
Task.Run(AddLedsAsync);
|
||||
}
|
||||
|
||||
public ObservableCollection<ProfileLedViewModel> Leds
|
||||
{
|
||||
get => _leds;
|
||||
set => SetAndNotify(ref _leds, value);
|
||||
}
|
||||
|
||||
public ArtemisDevice Device
|
||||
{
|
||||
get => _device;
|
||||
set => SetAndNotify(ref _device, value);
|
||||
}
|
||||
|
||||
public bool AddedLeds
|
||||
{
|
||||
get => _addedLeds;
|
||||
private set => SetAndNotify(ref _addedLeds, value);
|
||||
}
|
||||
|
||||
public new double X
|
||||
{
|
||||
get => Device.X;
|
||||
set => Device.X = value;
|
||||
}
|
||||
|
||||
public new double Y
|
||||
{
|
||||
get => Device.Y;
|
||||
set => Device.Y = value;
|
||||
}
|
||||
|
||||
public int ZIndex
|
||||
{
|
||||
get => Device.ZIndex;
|
||||
set => Device.ZIndex = value;
|
||||
}
|
||||
|
||||
|
||||
public Rect DeviceRectangle => Device.RgbDevice == null
|
||||
? new Rect()
|
||||
: new Rect(X, Y, Device.RgbDevice.Size.Width, Device.RgbDevice.Size.Height);
|
||||
|
||||
/// <summary>
|
||||
/// Update the color of all LEDs if finished adding
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
if (!AddedLeds)
|
||||
return;
|
||||
|
||||
foreach (var ledViewModel in Leds)
|
||||
ledViewModel.Update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds LEDs in batches of 5 to avoid UI freezes
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task AddLedsAsync()
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var led in Device.Leds.ToList())
|
||||
{
|
||||
Execute.OnUIThreadSync(() => Leds.Add(new ProfileLedViewModel(led)));
|
||||
if (index % 5 == 0)
|
||||
await Task.Delay(1);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
AddedLeds = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.Visualization.ProfileLedView"
|
||||
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:converters="clr-namespace:Artemis.UI.Converters"
|
||||
xmlns:visualization1="clr-namespace:Artemis.UI.Screens.ProfileEditor.Visualization"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance {x:Type visualization1:ProfileLedViewModel}}"
|
||||
d:DesignHeight="25" d:DesignWidth="25">
|
||||
<UserControl.Resources>
|
||||
<converters:NullToImageConverter x:Key="NullToImageConverter" />
|
||||
<Style TargetType="{x:Type Path}" x:Key="DimStyle">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsDimmed}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="(Shape.Opacity)" To="0.2" Duration="0:0:0.25" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation Storyboard.TargetProperty="(Shape.Opacity)" To="1" Duration="0:0:0.25" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<Canvas Width="{Binding Led.RgbLed.ActualSize.Width, Mode=OneWay}" Height="{Binding Led.RgbLed.ActualSize.Height, Mode=OneWay}">
|
||||
<Canvas.Background>
|
||||
<ImageBrush AlignmentX="Center" AlignmentY="Center" Stretch="Fill"
|
||||
ImageSource="{Binding Led.RgbLed.Image, Converter={StaticResource NullToImageConverter}, Mode=OneWay}" />
|
||||
</Canvas.Background>
|
||||
|
||||
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" Style="{StaticResource DimStyle}">
|
||||
<Path.Fill>
|
||||
<SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" Opacity="0.333" />
|
||||
</Path.Fill>
|
||||
</Path>
|
||||
<Path Data="{Binding StrokeGeometry, Mode=OneWay}" ClipToBounds="False" Style="{StaticResource DimStyle}">
|
||||
<Path.Fill>
|
||||
<SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" />
|
||||
</Path.Fill>
|
||||
</Path>
|
||||
|
||||
<!-- Selection -->
|
||||
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1" StrokeLineJoin="Round">
|
||||
<Path.Style>
|
||||
<Style TargetType="{x:Type Path}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsSelected}" Value="True">
|
||||
<DataTrigger.EnterActions>
|
||||
<BeginStoryboard x:Name="ToSelected">
|
||||
<Storyboard>
|
||||
<ColorAnimation
|
||||
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
|
||||
To="{StaticResource Accent700}" Duration="0:0:0.25" />
|
||||
<ColorAnimation
|
||||
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
|
||||
To="{StaticResource Accent400}" Duration="0:0:0.25" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.EnterActions>
|
||||
<DataTrigger.ExitActions>
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<ColorAnimation
|
||||
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
|
||||
To="Transparent" Duration="0:0:0.25" />
|
||||
<ColorAnimation
|
||||
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
|
||||
To="Transparent" Duration="0:0:0.25" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</DataTrigger.ExitActions>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Path.Style>
|
||||
<Path.Fill>
|
||||
<SolidColorBrush Opacity="0.25" />
|
||||
</Path.Fill>
|
||||
<Path.Stroke>
|
||||
<SolidColorBrush Opacity="0.5" />
|
||||
</Path.Stroke>
|
||||
</Path>
|
||||
</Canvas>
|
||||
</UserControl>
|
||||
@@ -1,148 +0,0 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using Artemis.Core;
|
||||
using Artemis.UI.Extensions;
|
||||
using RGB.NET.Core;
|
||||
using Stylet;
|
||||
using Color = System.Windows.Media.Color;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
public class ProfileLedViewModel : PropertyChangedBase
|
||||
{
|
||||
private Color _displayColor;
|
||||
private Geometry _displayGeometry;
|
||||
private bool _isDimmed;
|
||||
private bool _isSelected;
|
||||
private Geometry _strokeGeometry;
|
||||
|
||||
public ProfileLedViewModel(ArtemisLed led)
|
||||
{
|
||||
Led = led;
|
||||
|
||||
// Don't want ActualLocation here since rotation is done in XAML
|
||||
X = led.RgbLed.Location.X * led.RgbLed.Device.Scale.Horizontal;
|
||||
Y = led.RgbLed.Location.Y * led.RgbLed.Device.Scale.Vertical;
|
||||
Width = led.RgbLed.ActualSize.Width;
|
||||
Height = led.RgbLed.ActualSize.Height;
|
||||
|
||||
Execute.PostToUIThread(CreateLedGeometry);
|
||||
}
|
||||
|
||||
public ArtemisLed Led { get; }
|
||||
|
||||
public double X { get; }
|
||||
public double Y { get; }
|
||||
public double Width { get; }
|
||||
public double Height { get; }
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => _isSelected;
|
||||
set => SetAndNotify(ref _isSelected, value);
|
||||
}
|
||||
|
||||
public bool IsDimmed
|
||||
{
|
||||
get => _isDimmed;
|
||||
set => SetAndNotify(ref _isDimmed, value);
|
||||
}
|
||||
|
||||
public Geometry DisplayGeometry
|
||||
{
|
||||
get => _displayGeometry;
|
||||
private set => SetAndNotify(ref _displayGeometry, value);
|
||||
}
|
||||
|
||||
public Geometry StrokeGeometry
|
||||
{
|
||||
get => _strokeGeometry;
|
||||
private set => SetAndNotify(ref _strokeGeometry, value);
|
||||
}
|
||||
|
||||
public Color DisplayColor
|
||||
{
|
||||
get => _displayColor;
|
||||
private set => SetAndNotify(ref _displayColor, value);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var newColor = Led.RgbLed.Color.ToMediaColor();
|
||||
Execute.PostToUIThread(() =>
|
||||
{
|
||||
if (!DisplayColor.Equals(newColor))
|
||||
DisplayColor = newColor;
|
||||
});
|
||||
}
|
||||
|
||||
private void CreateLedGeometry()
|
||||
{
|
||||
switch (Led.RgbLed.Shape)
|
||||
{
|
||||
case Shape.Custom:
|
||||
if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
|
||||
CreateCustomGeometry(2.0);
|
||||
else
|
||||
CreateCustomGeometry(1.0);
|
||||
break;
|
||||
case Shape.Rectangle:
|
||||
if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
|
||||
CreateKeyCapGeometry();
|
||||
else
|
||||
CreateRectangleGeometry();
|
||||
break;
|
||||
case Shape.Circle:
|
||||
CreateCircleGeometry();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
// Stroke geometry is the display geometry excluding the inner geometry
|
||||
StrokeGeometry = DisplayGeometry.GetWidenedPathGeometry(new Pen(null, 1.0), 0.1, ToleranceType.Absolute);
|
||||
DisplayGeometry.Freeze();
|
||||
StrokeGeometry.Freeze();
|
||||
}
|
||||
|
||||
private void CreateRectangleGeometry()
|
||||
{
|
||||
DisplayGeometry = new RectangleGeometry(new Rect(0.5, 0.5, Width - 1, Height - 1));
|
||||
}
|
||||
|
||||
private void CreateCircleGeometry()
|
||||
{
|
||||
DisplayGeometry = new EllipseGeometry(new Rect(0.5, 0.5, Width - 1, Height - 1));
|
||||
}
|
||||
|
||||
private void CreateKeyCapGeometry()
|
||||
{
|
||||
DisplayGeometry = new RectangleGeometry(new Rect(1, 1, Width - 2, Height - 2), 1.6, 1.6);
|
||||
}
|
||||
|
||||
private void CreateCustomGeometry(double deflateAmount)
|
||||
{
|
||||
try
|
||||
{
|
||||
DisplayGeometry = Geometry.Combine(
|
||||
Geometry.Empty,
|
||||
Geometry.Parse(Led.RgbLed.ShapeData),
|
||||
GeometryCombineMode.Union,
|
||||
new TransformGroup
|
||||
{
|
||||
Children = new TransformCollection
|
||||
{
|
||||
new ScaleTransform(Width - deflateAmount, Height - deflateAmount),
|
||||
new TranslateTransform(deflateAmount / 2, deflateAmount / 2)
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
CreateRectangleGeometry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
|
||||
public class ProfileViewModel : Screen, IProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
|
||||
{
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IProfileLayerVmFactory _profileLayerVmFactory;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<controls:MaterialWindow x:Class="Artemis.UI.Screens.ProfileEditor.LayerBrushSettingsWindowView"
|
||||
<controls:MaterialWindow x:Class="Artemis.UI.Screens.ProfileEditor.Windows.LayerBrushSettingsWindowView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Windows
|
||||
{
|
||||
public class LayerBrushSettingsWindowViewModel : Conductor<BrushConfigurationViewModel>
|
||||
{
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<controls:MaterialWindow x:Class="Artemis.UI.Screens.ProfileEditor.LayerEffectSettingsWindowView"
|
||||
<controls:MaterialWindow x:Class="Artemis.UI.Screens.ProfileEditor.Windows.LayerEffectSettingsWindowView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
using Artemis.Core.LayerEffects;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Windows
|
||||
{
|
||||
public class LayerEffectSettingsWindowViewModel : Conductor<EffectConfigurationViewModel>
|
||||
{
|
||||
Reference in new issue
Block a user