1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Added layer properties to core and hooked it up with the UI

Implemented timeline caret scrolling logic
Added special treeview style for the layer properties tree
This commit is contained in:
Robert 2020-01-06 22:50:51 +01:00
parent 8f438abe49
commit a2efeb887a
48 changed files with 618 additions and 381 deletions

View File

@ -1,7 +1,6 @@
using System;
using System.Linq;
using Artemis.Core.Models.Profile.LayerShapes;
using Artemis.Core.Models.Surface;
using Artemis.Storage.Entities.Profile;
using SkiaSharp;

View File

@ -14,6 +14,7 @@ namespace Artemis.Core.Models.Profile
{
public sealed class Layer : ProfileElement
{
private readonly List<LayerProperty> _properties;
private LayerShape _layerShape;
private List<ArtemisLed> _leds;
@ -27,6 +28,9 @@ namespace Artemis.Core.Models.Profile
Name = name;
_leds = new List<ArtemisLed>();
_properties = new List<LayerProperty>();
CreateDefaultProperties();
}
internal Layer(Profile profile, ProfileElement parent, LayerEntity layerEntity)
@ -40,6 +44,10 @@ namespace Artemis.Core.Models.Profile
Order = layerEntity.Order;
_leds = new List<ArtemisLed>();
_properties = new List<LayerProperty>();
// TODO: Load properties from entity instead of creating the defaults
CreateDefaultProperties();
switch (layerEntity.ShapeEntity?.Type)
{
@ -89,7 +97,7 @@ namespace Artemis.Core.Models.Profile
public SKPath Path { get; private set; }
/// <summary>
/// Defines the shape that is rendered by the <see cref="LayerBrush"/>.
/// Defines the shape that is rendered by the <see cref="LayerBrush" />.
/// </summary>
public LayerShape LayerShape
{
@ -103,7 +111,37 @@ namespace Artemis.Core.Models.Profile
}
/// <summary>
/// The brush that will fill the <see cref="LayerShape"/>.
/// A collection of all the properties on this layer
/// </summary>
public ReadOnlyCollection<LayerProperty> Properties => _properties.AsReadOnly();
/// <summary>
/// The anchor point property of this layer, also found in <see cref="Properties" />
/// </summary>
public LayerProperty AnchorPointProperty { get; private set; }
/// <summary>
/// The position of this layer, also found in <see cref="Properties" />
/// </summary>
public LayerProperty PositionProperty { get; private set; }
/// <summary>
/// The scale property of this layer, also found in <see cref="Properties" />
/// </summary>
public LayerProperty ScaleProperty { get; private set; }
/// <summary>
/// The rotation property of this layer, also found in <see cref="Properties" />
/// </summary>
public LayerProperty RotationProperty { get; private set; }
/// <summary>
/// The opacity property of this layer, also found in <see cref="Properties" />
/// </summary>
public LayerProperty OpacityProperty { get; private set; }
/// <summary>
/// The brush that will fill the <see cref="LayerShape" />.
/// </summary>
public LayerBrush LayerBrush { get; internal set; }
@ -121,7 +159,7 @@ namespace Artemis.Core.Models.Profile
canvas.ClipPath(Path);
// Placeholder
if (LayerShape?.RenderPath != null)
canvas.DrawPath(LayerShape.RenderPath, new SKPaint(){Color = new SKColor(255,0,0)});
canvas.DrawPath(LayerShape.RenderPath, new SKPaint {Color = new SKColor(255, 0, 0)});
LayerBrush?.Render(canvas);
canvas.Restore();
}
@ -134,6 +172,8 @@ namespace Artemis.Core.Models.Profile
LayerEntity.Order = Order;
LayerEntity.Name = Name;
LayerEntity.ProfileId = Profile.EntityId;
foreach (var layerProperty in Properties)
layerProperty.ApplyToEntity();
// LEDs
LayerEntity.Leds.Clear();
@ -251,6 +291,25 @@ namespace Artemis.Core.Models.Profile
OnRenderPropertiesUpdated();
}
private void CreateDefaultProperties()
{
var transformProperty = new LayerProperty(this, null, "Transform", "The default properties collection every layer has, allows you to transform the shape.", null);
AnchorPointProperty = new LayerProperty(this, transformProperty, "Anchor Point", "The point at which the shape is attached to its position.", typeof(SKPoint));
PositionProperty = new LayerProperty(this, transformProperty, "Position", "The position of the shape.", typeof(SKPoint));
ScaleProperty = new LayerProperty(this, transformProperty, "Scale", "The scale of the shape.", typeof(SKSize));
RotationProperty = new LayerProperty(this, transformProperty, "Rotation", "The rotation of the shape in degrees.", typeof(int));
OpacityProperty = new LayerProperty(this, transformProperty, "Opacity", "The opacity of the shape from 0 to 1.", typeof(float));
transformProperty.Children.Add(AnchorPointProperty);
transformProperty.Children.Add(PositionProperty);
transformProperty.Children.Add(ScaleProperty);
transformProperty.Children.Add(RotationProperty);
transformProperty.Children.Add(OpacityProperty);
_properties.Add(transformProperty);
_properties.AddRange(transformProperty.Children);
}
public override string ToString()
{
return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}";

View File

@ -1,16 +1,23 @@
using System;
using System.Collections.Generic;
using Artemis.Core.Exceptions;
namespace Artemis.Core.Models.Profile
{
public class LayerProperty
{
internal LayerProperty(Layer layer, LayerProperty parent)
private object _baseValue;
internal LayerProperty(Layer layer, LayerProperty parent, string name, string description, Type type)
{
Layer = layer;
Parent = parent;
Name = name;
Description = description;
Type = type;
Children = new List<LayerProperty>();
Keyframes = new List<Keyframe>();
}
public Layer Layer { get; }
@ -20,7 +27,23 @@ namespace Artemis.Core.Models.Profile
public string Name { get; set; }
public string Description { get; set; }
public Type Type { get; set; }
public object BaseValue { get; set; }
public object BaseValue
{
get => _baseValue;
set
{
if (value != null && value.GetType() != Type)
throw new ArtemisCoreException($"Cannot set value of type {value.GetType()} on property {Name}, expected type is {Type}.");
_baseValue = value;
}
}
public List<Keyframe> Keyframes { get; set; }
public void ApplyToEntity()
{
// Big o' TODO
}
}
}

View File

@ -7,6 +7,7 @@ namespace Artemis.Core.Models.Profile.LayerShapes
public Fill(Layer layer) : base(layer)
{
}
internal Fill(Layer layer, ShapeEntity shapeEntity) : base(layer, shapeEntity)
{
}

View File

@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Linq;
using Artemis.Storage.Entities.Profile;
using SkiaSharp;
@ -61,12 +60,12 @@ namespace Artemis.Core.Models.Profile.LayerShapes
}
/// <summary>
/// A render rectangle relative to the layer
/// A render rectangle relative to the layer
/// </summary>
public SKRect RenderRectangle { get; protected set; }
/// <summary>
/// A path relative to the layer
/// A path relative to the layer
/// </summary>
public SKPath RenderPath { get; protected set; }
@ -84,7 +83,7 @@ namespace Artemis.Core.Models.Profile.LayerShapes
}
/// <summary>
/// Updates Position and Size using the provided unscaled rectangle
/// Updates Position and Size using the provided unscaled rectangle
/// </summary>
/// <param name="rect">An unscaled rectangle where 1px = 1mm</param>
public void SetFromUnscaledRectangle(SKRect rect)

View File

@ -7,7 +7,6 @@ namespace Artemis.Core.Models.Profile.LayerShapes
{
public class Polygon : LayerShape
{
public Polygon(Layer layer) : base(layer)
{
}
@ -39,7 +38,7 @@ namespace Artemis.Core.Models.Profile.LayerShapes
{
base.ApplyToEntity();
Layer.LayerEntity.ShapeEntity.Type = ShapeEntityType.Polygon;
Layer.LayerEntity.ShapeEntity.Points = Points.Select(p => new ShapePointEntity { X = p.X, Y = p.Y }).ToList();
Layer.LayerEntity.ShapeEntity.Points = Points.Select(p => new ShapePointEntity {X = p.X, Y = p.Y}).ToList();
}
}
}

View File

@ -131,7 +131,5 @@ namespace Artemis.Core.Models.Profile
child.Parent = null;
}
}
}
}

View File

@ -149,11 +149,13 @@
<Compile Include="Converters\ColorToSolidColorBrushConverter.cs" />
<Compile Include="Converters\EnumToCollectionConverter.cs" />
<Compile Include="Converters\InverseBooleanConverter.cs" />
<Compile Include="Converters\LeftMarginMultiplierConverter.cs" />
<Compile Include="Converters\NullToImageConverter.cs" />
<Compile Include="Converters\NullToVisibilityConverter.cs" />
<Compile Include="Events\MainWindowFocusChangedEvent.cs" />
<Compile Include="Events\MainWindowKeyEvent.cs" />
<Compile Include="Events\WindowsThemeEventArgs.cs" />
<Compile Include="Extensions\TreeViewItemExtensions.cs" />
<Compile Include="Screens\GradientEditor\GradientEditorViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.xaml.cs">
<DependentUpon>LayerPropertiesView.xaml</DependentUpon>
@ -161,6 +163,7 @@
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\LayerPropertyViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeItemViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeParentViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeViewModel.cs" />
<Compile Include="Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackKeyframeViewModel.cs" />

View File

@ -0,0 +1,28 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Artemis.UI.Extensions;
namespace Artemis.UI.Converters
{
public class LeftMarginMultiplierConverter : IValueConverter
{
public double Length { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var item = value as TreeViewItem;
if (item == null)
return new Thickness(0);
return new Thickness(Length * item.GetDepth(), 0, 0, 0);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,24 @@
using System.Windows.Controls;
using System.Windows.Media;
namespace Artemis.UI.Extensions
{
public static class TreeViewItemExtensions
{
public static int GetDepth(this TreeViewItem item)
{
TreeViewItem parent;
while ((parent = GetParent(item)) != null)
return GetDepth(parent) + 1;
return 0;
}
private static TreeViewItem GetParent(TreeViewItem item)
{
var parent = VisualTreeHelper.GetParent(item);
while (!(parent is TreeViewItem || parent is TreeView))
parent = VisualTreeHelper.GetParent(parent);
return parent as TreeViewItem;
}
}
}

View File

@ -7,8 +7,14 @@
xmlns:s="https://github.com/canton7/Stylet"
xmlns:timeline="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
d:DesignHeight="450"
d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:LayerPropertiesViewModel}">
<Grid x:Name="ContainerGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
@ -22,34 +28,44 @@
</Grid.RowDefinitions>
<!-- Misc controls & time display -->
<StackPanel Grid.Row="0">
<TextBlock>A play button, current time etc. etc.!</TextBlock>
<StackPanel Grid.Row="0" VerticalAlignment="Center">
<TextBlock Style="{StaticResource MaterialDesignTitleTextBlock}" Text="{Binding CurrentTime}" HorizontalAlignment="Right" Margin="0 0 20 0" />
</StackPanel>
<!-- Properties tree -->
<ScrollViewer Grid.Row="1" x:Name="PropertyTreeScrollViewer">
<ContentControl s:View.Model="{Binding PropertyTree}" />
<ScrollViewer Grid.Row="1" x:Name="PropertyTreeScrollViewer" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<Border BorderThickness="0,0,1,0" BorderBrush="{DynamicResource MaterialDesignDivider}">
<ContentControl s:View.Model="{Binding PropertyTree}" />
</Border>
</ScrollViewer>
</Grid>
<!-- Right side -->
<Grid Grid.Column="1">
<Grid Grid.Column="1"
MouseDown="{s:Action RightGridMouseDown}"
MouseMove="{s:Action RightGridMouseMove}">
<Grid.RowDefinitions>
<RowDefinition Height="56" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Caret -->
<Canvas ZIndex="1"
Margin="{Binding TimeCaretPosition}"
Cursor="SizeWE"
MouseEnter="{s:Action CaretMouseEnter}"
MouseLeave="{s:Action CaretMouseLeave}">
<Polygon Points="-10,0 0,20, 10,00" Fill="{StaticResource SecondaryAccentBrush}" />
<Line X1="0" X2="0" Y1="0" Y2="{Binding ActualHeight, ElementName=ContainerGrid}" StrokeThickness="2" Stroke="{StaticResource SecondaryAccentBrush}" />
</Canvas>
<!-- Timeline header -->
<ScrollViewer Grid.Row="0" x:Name="TimelineHeaderScrollViewer" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<ScrollViewer Grid.Row="0" x:Name="TimelineHeaderScrollViewer" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" >
<StackPanel>
<!-- Caret -->
<Canvas ZIndex="10" Height="25" Margin="{Binding TimeCaretPosition}" ClipToBounds="False">
<Polygon Points="-10,0 0,20, 10,00" Fill="{StaticResource SecondaryAccentBrush}" />
<Line X1="0" X2="0" Y1="0" Y2="10000" StrokeThickness="2" Stroke="{StaticResource SecondaryAccentBrush}" />
</Canvas>
<!-- Time -->
<timeline:PropertyTimelineHeader Fill="{DynamicResource MaterialDesignBody}"
<timeline:PropertyTimelineHeader Margin="0 25 0 0"
Fill="{DynamicResource MaterialDesignBody}"
PixelsPerSecond="{Binding PixelsPerSecond}"
HorizontalOffset="{Binding ContentHorizontalOffset, ElementName=TimelineHeaderScrollViewer}"
VisibleWidth="{Binding ActualWidth, ElementName=TimelineHeaderScrollViewer}" />
@ -57,12 +73,20 @@
</ScrollViewer>
<!-- Timeline rails -->
<ScrollViewer Grid.Row="1" x:Name="TimelineRailsScrollViewer">
<ScrollViewer Grid.Row="1" x:Name="TimelineRailsScrollViewer" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Hidden">
<ContentControl s:View.Model="{Binding PropertyTimeline}" />
</ScrollViewer>
</Grid>
<!-- Bottom row, a bit hacky but has a ZIndex of 2 to cut off the time caret that overlaps the entire timeline -->
<StackPanel Grid.Row="1"
Grid.ColumnSpan="2"
Grid.Column="0"
HorizontalAlignment="Stretch"
ZIndex="2"
Background="{DynamicResource MaterialDesignCardBackground}">
<!-- Zoom control -->
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<TextBlock Text="{Binding PixelsPerSecond}" VerticalAlignment="Center" />
<Slider Orientation="Horizontal"
HorizontalAlignment="Right"
@ -73,6 +97,6 @@
Value="{Binding PixelsPerSecond}"
Width="600" />
</StackPanel>
</Grid>
</StackPanel>
</Grid>
</UserControl>

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
/// <summary>
/// Interaction logic for LayerPropertiesView.xaml
/// Interaction logic for LayerPropertiesView.xaml
/// </summary>
public partial class LayerPropertiesView : UserControl
{
@ -27,4 +14,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
// Keeping the scroll viewers in sync is up to the view, not a viewmodel concern
}
}
}

View File

@ -1,20 +1,52 @@
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Artemis.Core.Models.Profile;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline;
using Artemis.UI.Services.Interfaces;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
public class LayerPropertiesViewModel : ProfileEditorPanelViewModel
{
public LayerPropertiesViewModel()
private readonly IProfileEditorService _profileEditorService;
public LayerPropertiesViewModel(IProfileEditorService profileEditorService)
{
_profileEditorService = profileEditorService;
CurrentTime = TimeSpan.Zero;
PixelsPerSecond = 1;
PropertyTree = new PropertyTreeViewModel(this);
PropertyTimeline = new PropertyTimelineViewModel(this);
PopulateProperties();
_profileEditorService.SelectedProfileElementChanged += (sender, args) => PopulateProperties();
}
public TimeSpan CurrentTime
{
get => _currentTime;
set
{
_currentTime = value;
OnCurrentTimeChanged();
}
}
public int PixelsPerSecond
{
get => _pixelsPerSecond;
set
{
_pixelsPerSecond = value;
OnPixelsPerSecondChanged();
}
}
public TimeSpan CurrentTime { get; set; }
public int PixelsPerSecond { get; set; }
public Thickness TimeCaretPosition
{
get => new Thickness(CurrentTime.TotalSeconds * PixelsPerSecond, 0, 0, 0);
@ -24,29 +56,72 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
public PropertyTreeViewModel PropertyTree { get; set; }
public PropertyTimelineViewModel PropertyTimeline { get; set; }
private void CreateTestValues()
private void PopulateProperties()
{
// var propertyRailViewModels = new List<TimelinePropertyRailViewModel>();
// for (var i = 0; i < 20; i++)
// propertyRailViewModels.Add(new TimelinePropertyRailViewModel());
//
// TimelinePropertyRailViewModels.AddRange(propertyRailViewModels);
//
// // Transform will be the only built-in properties so test with that
// var testVm = new TimelinePropertiesViewModel { PropertiesName = "Transform" };
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Anchor Point" });
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Position" });
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Scale" });
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Rotation" });
// testVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Opacity" });
// // Purely for testing, add a nested property
// var subTestVm = new TimelinePropertiesViewModel() { PropertiesName = "Sub Properties" };
// subTestVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Sub Property 1" });
// subTestVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Sub Property 2" });
// subTestVm.Properties.Add(new TimelinePropertyViewModel { PropertyName = "Sub Property 3" });
// testVm.Properties.Add(subTestVm);
//
// TimelinePropertiesViewModels.Add(testVm);
if (_profileEditorService.SelectedProfileElement is Layer selectedLayer)
{
// Only create VMs for top-level parents, let parents populate their own children recursively
var propertyViewModels = selectedLayer.Properties
.Where(p => p.Children.Any())
.Select(p => new LayerPropertyViewModel(p, null))
.ToList();
PropertyTree.PopulateProperties(propertyViewModels);
PropertyTimeline.PopulateProperties(propertyViewModels);
}
else
{
PropertyTree.ClearProperties();
PropertyTimeline.ClearProperties();
}
}
#region Caret movement
private double _caretStartMouseStartOffset;
private bool _mouseOverCaret;
private int _pixelsPerSecond;
private TimeSpan _currentTime;
public void RightGridMouseDown(object sender, MouseButtonEventArgs e)
{
_caretStartMouseStartOffset = e.GetPosition((IInputElement) sender).X - TimeCaretPosition.Left;
}
public void CaretMouseEnter(object sender, MouseEventArgs e)
{
_mouseOverCaret = true;
}
public void CaretMouseLeave(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed)
_mouseOverCaret = false;
}
public void RightGridMouseMove(object sender, MouseEventArgs e)
{
if (_mouseOverCaret && e.LeftButton == MouseButtonState.Pressed)
TimeCaretPosition = new Thickness(Math.Max(0, e.GetPosition((IInputElement) sender).X), 0, 0, 0);
}
#endregion
#region Events
public event EventHandler CurrentTimeChanged;
public event EventHandler PixelsPerSecondChanged;
protected virtual void OnCurrentTimeChanged()
{
CurrentTimeChanged?.Invoke(this, EventArgs.Empty);
}
protected virtual void OnPixelsPerSecondChanged()
{
PixelsPerSecondChanged?.Invoke(this, EventArgs.Empty);
}
#endregion
}
}

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using Artemis.Core.Models.Profile;
using Stylet;
@ -10,13 +6,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
{
public class LayerPropertyViewModel : PropertyChangedBase
{
public LayerProperty LayerProperty { get; }
public LayerPropertyViewModel(LayerProperty layerProperty)
public LayerPropertyViewModel(LayerProperty layerProperty, LayerPropertyViewModel parent)
{
LayerProperty = layerProperty;
Parent = parent;
Children = new List<LayerPropertyViewModel>();
foreach (var child in layerProperty.Children)
Children.Add(new LayerPropertyViewModel(child, this));
}
public bool IsCollapsed { get; set; }
public LayerProperty LayerProperty { get; }
public LayerPropertyViewModel Parent { get; }
public List<LayerPropertyViewModel> Children { get; set; }
public bool IsExpanded { get; set; }
}
}

View File

@ -1,17 +1,20 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyTreeChildView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
d:DesignHeight="20" d:DesignWidth="800">
<Grid>
mc:Ignorable="d"
d:DesignHeight="19"
d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:PropertyTreeChildViewModel}">
<Grid Height="22">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ToggleButton Grid.Column="0"
Style="{StaticResource MaterialDesignFlatToggleButton}"
@ -28,18 +31,29 @@
Padding="0,0,5,0"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"
Text="{Binding PropertyName}"
Text="{Binding LayerPropertyViewModel.LayerProperty.Name}"
ToolTip="{Binding LayerPropertyViewModel.LayerProperty.Description}"
HorizontalAlignment="Left" />
<Button Grid.Column="2"
<StackPanel Grid.Column="2" Margin="20 0" VerticalAlignment="Center">
<!-- Height is very limited so squeeze things together -->
<TextBox Width="100"
Margin="0 -1"
Padding="0 -1"
materialDesign:ValidationAssist.UsePopup="True"
HorizontalAlignment="Left"
ToolTip="Use a popup which can escape the bounds of the control where space is limited" />
</StackPanel>
<Button Grid.Column="3"
Style="{StaticResource MaterialDesignOutlinedButton}"
Margin="0,1,0,1.2"
Padding="0"
Width="110"
Height="17"
ToolTip="Change the property's data binding"
Width="80"
Height="Auto"
ToolTip="Change the property's data binding"
VerticalAlignment="Center">
<TextBlock FontSize="10">DATA BINDING</TextBlock>
</Button>
</Grid>
</UserControl>
</UserControl>

View File

@ -1,19 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeChildViewModel : PropertyChangedBase
public class PropertyTreeChildViewModel : PropertyTreeItemViewModel
{
public LayerPropertyViewModel LayerPropertyViewModel { get; }
private bool _keyframesEnabled;
public PropertyTreeChildViewModel(LayerPropertyViewModel layerPropertyViewModel)
{
LayerPropertyViewModel = layerPropertyViewModel;
}
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public bool KeyframesEnabled
{
get => _keyframesEnabled;
set
{
_keyframesEnabled = value;
UpdateKeyframes();
}
}
private void UpdateKeyframes()
{
}
}
}
}

View File

@ -0,0 +1,8 @@
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeItemViewModel : PropertyChangedBase
{
}
}

View File

@ -1,19 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeParentViewModel : PropertyTreeItemViewModel
{
public string Name { get; set; }
public PropertyTreeItemViewModel Children { get; set; }
}
public PropertyTreeParentViewModel(LayerPropertyViewModel layerPropertyViewModel)
{
LayerPropertyViewModel = layerPropertyViewModel;
Children = new BindableCollection<PropertyTreeItemViewModel>();
public class PropertyTreeItemViewModel : PropertyChangedBase
{
foreach (var childProperty in layerPropertyViewModel.Children)
{
if (childProperty.Children.Any())
Children.Add(new PropertyTreeParentViewModel(childProperty));
else
Children.Add(new PropertyTreeChildViewModel(childProperty));
}
}
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public BindableCollection<PropertyTreeItemViewModel> Children { get; set; }
}
}
}

View File

@ -1,31 +1,103 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyTreeView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:timeline="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:profile="clr-namespace:Artemis.Core.Models.Profile;assembly=Artemis.Core"
mc:Ignorable="d"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style x:Key="PropertyTreeStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Foreground" Value="{DynamicResource MaterialDesignBody}" />
<Setter Property="Padding" Value="1" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="ScrollViewer.PanningMode" Value="Both" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<ControlTemplate.Resources>
<converters:LeftMarginMultiplierConverter Length="19" x:Key="lengthConverter" />
</ControlTemplate.Resources>
<StackPanel>
<Border Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource MaterialDesignDivider}"
BorderThickness="0,0,0,1"
Padding="{TemplateBinding Padding}">
<Grid Margin="{Binding Converter={StaticResource lengthConverter}, RelativeSource={RelativeSource TemplatedParent}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="19" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton x:Name="Expander"
Foreground="{DynamicResource MaterialDesignBody}"
Style="{StaticResource MaterialDesignExpandCollapseToggleStyle}"
IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press" />
<ContentPresenter x:Name="PART_Header"
Grid.Column="1"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Grid>
</Border>
<ItemsPresenter x:Name="ItemsHost" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="false">
<Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="Expander" Property="Visibility" Value="Hidden" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader" Value="false" />
<Condition Property="Width" Value="Auto" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header" Property="MinWidth" Value="75" />
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader" Value="false" />
<Condition Property="Height" Value="Auto" />
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header" Property="MinHeight" Value="19" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<TreeView ItemsSource="{Binding PropertyTreeItemViewModels}"
HorizontalContentAlignment="Stretch"
materialDesign:RippleAssist.IsDisabled="True"
Background="{DynamicResource MaterialDesignToolBarBackground}">
Background="{DynamicResource MaterialDesignToolBarBackground}"
Margin="0 -1">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem" BasedOn="{StaticResource MaterialDesignTreeViewItem}">
<!-- TODO: Disable hover -->
<Setter Property="Focusable" Value="False" />
<Setter Property="Padding" Value="2" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Style TargetType="TreeViewItem" BasedOn="{StaticResource PropertyTreeStyle}">
<Setter Property="IsExpanded" Value="{Binding LayerPropertyViewModel.IsExpanded, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.Resources>
<!-- Parents only show their name and children -->
<HierarchicalDataTemplate DataType="{x:Type local:PropertyTreeParentViewModel}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" Margin="3 2" />
<StackPanel Height="22" Orientation="Horizontal">
<TextBlock Text="{Binding LayerPropertyViewModel.LayerProperty.Name}"
ToolTip="{Binding LayerPropertyViewModel.LayerProperty.Description}"
Margin="5 0"
VerticalAlignment="Center" />
</StackPanel>
</HierarchicalDataTemplate>
<!-- Children show their full view -->
<DataTemplate DataType="{x:Type local:PropertyTreeChildViewModel}">
@ -33,4 +105,4 @@
</DataTemplate>
</TreeView.Resources>
</TreeView>
</UserControl>
</UserControl>

View File

@ -1,19 +1,35 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree
{
public class PropertyTreeViewModel : PropertyChangedBase
{
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
public BindableCollection<PropertyTreeChildViewModel> PropertyTreeItemViewModels { get; set; }
public PropertyTreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel)
{
LayerPropertiesViewModel = layerPropertiesViewModel;
PropertyTreeItemViewModels = new BindableCollection<PropertyTreeItemViewModel>();
}
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
public BindableCollection<PropertyTreeItemViewModel> PropertyTreeItemViewModels { get; set; }
public void PopulateProperties(List<LayerPropertyViewModel> properties)
{
PropertyTreeItemViewModels.Clear();
// Only put parents on the top-level, let parents populate their own children recursively
foreach (var property in properties)
{
if (property.Children.Any())
PropertyTreeItemViewModels.Add(new PropertyTreeParentViewModel(property));
}
}
public void ClearProperties()
{
PropertyTreeItemViewModels.Clear();
}
}
}
}

View File

@ -1,33 +1,23 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline.PropertyTimelineView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
d:DesignHeight="25"
mc:Ignorable="d"
d:DesignHeight="25"
d:DesignWidth="800"
d:DataContext="{d:DesignInstance local:PropertyTimelineViewModel}">
<ItemsControl ItemsSource="{Binding TimelineKeyframeViewModels}"
Width="{Binding Width}"
<ItemsControl ItemsSource="{Binding PropertyTrackViewModels}"
Width="{Binding Width}"
MinWidth="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollViewer}}"
Background="{DynamicResource MaterialDesignToolBarBackground}"
Background="{DynamicResource MaterialDesignToolBarBackground}"
HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding}"/>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
</UserControl>

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Stylet;
@ -9,21 +10,46 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public PropertyTimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel)
{
LayerPropertiesViewModel = layerPropertiesViewModel;
RailItemViewModels = new BindableCollection<PropertyTrackViewModel>();
PropertyTrackViewModels = new BindableCollection<PropertyTrackViewModel>();
}
public LayerPropertiesViewModel LayerPropertiesViewModel { get; }
public double Width { get; set; }
public BindableCollection<PropertyTrackViewModel> RailItemViewModels { get; set; }
public BindableCollection<PropertyTrackViewModel> PropertyTrackViewModels { get; set; }
public void UpdateEndTime()
{
// End time is the last keyframe + 10 sec
var lastKeyFrame = RailItemViewModels.SelectMany(r => r.KeyframeViewModels).OrderByDescending(t => t.Keyframe.Position).FirstOrDefault();
var lastKeyFrame = PropertyTrackViewModels.SelectMany(r => r.KeyframeViewModels).OrderByDescending(t => t.Keyframe.Position).FirstOrDefault();
var endTime = lastKeyFrame?.Keyframe.Position.Add(new TimeSpan(0, 0, 0, 10)) ?? TimeSpan.FromSeconds(10);
Width = endTime.TotalSeconds * LayerPropertiesViewModel.PixelsPerSecond;
// Ensure the caret isn't outside the end time
if (LayerPropertiesViewModel.CurrentTime > endTime)
LayerPropertiesViewModel.CurrentTime = endTime;
}
public void PopulateProperties(List<LayerPropertyViewModel> properties)
{
PropertyTrackViewModels.Clear();
foreach (var property in properties)
CreateViewModels(property);
UpdateEndTime();
}
private void CreateViewModels(LayerPropertyViewModel property)
{
PropertyTrackViewModels.Add(new PropertyTrackViewModel(this, property));
foreach (var child in property.Children)
CreateViewModels(child);
}
public void ClearProperties()
{
PropertyTrackViewModels.Clear();
}
}
}

View File

@ -9,23 +9,28 @@
mc:Ignorable="d"
d:DesignHeight="20" d:DesignWidth="600"
d:DataContext="{d:DesignInstance local:PropertyTrackViewModel}">
<ItemsControl ItemsSource="{Binding KeyframeViewModels}"
Background="{DynamicResource MaterialDesignToolBarBackground}"
HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Fill="{StaticResource PrimaryHueMidBrush}" Width="10" Height="10" Margin="-5,6,0,0" ToolTip="{Binding Timestamp}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Border Height="25"
BorderThickness="0,0,0,1"
BorderBrush="{DynamicResource MaterialDesignDivider}"
Visibility="{Binding LayerPropertyViewModel.Parent.IsExpanded, Converter={StaticResource BoolToVisibilityConverter}}">
<ItemsControl ItemsSource="{Binding KeyframeViewModels}"
Background="{DynamicResource MaterialDesignToolBarBackground}"
HorizontalAlignment="Left">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Fill="{StaticResource PrimaryHueMidBrush}" Width="10" Height="10" Margin="-5,6,0,0" ToolTip="{Binding Timestamp}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</UserControl>

View File

@ -1,18 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
{
public class PropertyTrackViewModel : PropertyChangedBase
{
public PropertyTimelineViewModel PropertyTimelineViewModel { get; }
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public BindableCollection<PropertyTrackKeyframeViewModel> KeyframeViewModels { get; set; }
public PropertyTrackViewModel(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel)
{
PropertyTimelineViewModel = propertyTimelineViewModel;
@ -23,6 +15,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
UpdateKeyframes(propertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond);
}
public PropertyTimelineViewModel PropertyTimelineViewModel { get; }
public LayerPropertyViewModel LayerPropertyViewModel { get; }
public BindableCollection<PropertyTrackKeyframeViewModel> KeyframeViewModels { get; set; }
public void PopulateKeyframes()
{
foreach (var keyframe in LayerPropertyViewModel.LayerProperty.Keyframes)
@ -36,9 +32,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public void UpdateKeyframes(int pixelsPerSecond)
{
foreach (var keyframeViewModel in KeyframeViewModels)
{
keyframeViewModel.Update(pixelsPerSecond);
}
}
}
}

View File

@ -12,10 +12,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{
public abstract class TreeItemViewModel : PropertyChangedBase
{
private readonly IProfileEditorService _profileEditorService;
private readonly IDialogService _dialogService;
private readonly IFolderViewModelFactory _folderViewModelFactory;
private readonly ILayerViewModelFactory _layerViewModelFactory;
private readonly IProfileEditorService _profileEditorService;
protected TreeItemViewModel(TreeItemViewModel parent,
ProfileElement profileElement,
@ -175,13 +175,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{
existing = Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder);
if (existing == null)
Children.Add(_folderViewModelFactory.Create((FolderViewModel)this, folder));
Children.Add(_folderViewModelFactory.Create((FolderViewModel) this, folder));
}
else if (profileElement is Layer layer)
{
existing = Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer);
if (existing == null)
Children.Add(_layerViewModelFactory.Create((FolderViewModel)this, layer));
Children.Add(_layerViewModelFactory.Create((FolderViewModel) this, layer));
}
existing?.UpdateProfileElements();

View File

@ -7,7 +7,7 @@ using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{
public class ProfileDeviceViewModel : CanvasViewModel
public class ProfileDeviceViewModel : CanvasViewModel
{
public ProfileDeviceViewModel(ArtemisDevice device)
{

View File

@ -30,7 +30,7 @@
</UserControl.Resources>
<Canvas Style="{StaticResource SelectedStyle}">
<!-- The part of the layer's shape that falls outside the layer -->
<Path Data="{Binding ShapeGeometry, Mode=OneWay}" >
<Path Data="{Binding ShapeGeometry, Mode=OneWay}">
<Path.Fill>
<SolidColorBrush Color="{StaticResource Accent700}" Opacity="0.05" />
</Path.Fill>
@ -40,7 +40,7 @@
</Path>
<!-- The part of the layer's shape that is inside the layer -->
<Path Data="{Binding ShapeGeometry, Mode=OneWay}" >
<Path Data="{Binding ShapeGeometry, Mode=OneWay}">
<Path.Fill>
<SolidColorBrush Color="{StaticResource Accent700}" Opacity="0.35" />
</Path.Fill>

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{
/// <summary>
/// Interaction logic for ProfileLayerView.xaml
/// Interaction logic for ProfileLayerView.xaml
/// </summary>
public partial class ProfileLayerView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
InitializeComponent();
}
}
}
}

View File

@ -86,7 +86,7 @@
<SolidColorBrush Opacity="0.25" />
</Path.Fill>
<Path.Stroke>
<SolidColorBrush Opacity="0.5"/>
<SolidColorBrush Opacity="0.5" />
</Path.Stroke>
</Path>
</Canvas>

View File

@ -23,8 +23,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
{
private readonly IProfileEditorService _profileEditorService;
private readonly ISettingsService _settingsService;
private readonly IProfileLayerViewModelFactory _profileLayerViewModelFactory;
private readonly ISettingsService _settingsService;
private readonly ISurfaceService _surfaceService;
private int _activeToolIndex;
private VisualizationToolViewModel _activeToolViewModel;
@ -181,6 +181,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization
{
viewModel = Devices.FirstOrDefault(vm => vm.Device.RgbDevice == surfaceDeviceConfiguration.RgbDevice);
}
if (viewModel == null)
{
// Create outside the UI thread to avoid slowdowns as much as possible

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
/// <summary>
/// Interaction logic for EllipseToolView.xaml
/// Interaction logic for EllipseToolView.xaml
/// </summary>
public partial class EllipseToolView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
InitializeComponent();
}
}
}
}

View File

@ -1,12 +1,10 @@
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.LayerShapes;
using Artemis.UI.Properties;
using Artemis.UI.Services.Interfaces;
using SkiaSharp;
using SkiaSharp.Views.WPF;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools

View File

@ -1,9 +1,9 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools.FillToolView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
</UserControl>
</UserControl>

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
/// <summary>
/// Interaction logic for FillToolView.xaml
/// Interaction logic for FillToolView.xaml
/// </summary>
public partial class FillToolView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
InitializeComponent();
}
}
}
}

View File

@ -31,7 +31,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
led => panZoomVm.TransformContainingRect(led.RgbLed.AbsoluteLedRectangle).Contains(position))
);
if (layer == null)
if (layer == null)
return;
layer.LayerShape = new Fill(layer);
ProfileEditorService.UpdateSelectedProfileElement();

View File

@ -1,12 +1,10 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools.PolygonToolView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>
<Grid />
</UserControl>

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
/// <summary>
/// Interaction logic for PolygonToolView.xaml
/// Interaction logic for PolygonToolView.xaml
/// </summary>
public partial class PolygonToolView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
InitializeComponent();
}
}
}
}

View File

@ -31,7 +31,7 @@
</Style>
</UserControl.Resources>
<Canvas Background="Transparent" Width="50" Height="50">
<Canvas.ContextMenu>
<ContextMenu>
<MenuItem Header="Ellipse action 1" Command="{s:Action CreateLayer}" CommandParameter="{Binding}">

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
/// <summary>
/// Interaction logic for RectangleToolView.xaml
/// Interaction logic for RectangleToolView.xaml
/// </summary>
public partial class RectangleToolView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
InitializeComponent();
}
}
}
}

View File

@ -1,12 +1,10 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools.SelectionAddToolView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>
<Grid />
</UserControl>

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
/// <summary>
/// Interaction logic for SelectionAddToolView.xaml
/// Interaction logic for SelectionAddToolView.xaml
/// </summary>
public partial class SelectionAddToolView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
InitializeComponent();
}
}
}
}

View File

@ -1,12 +1,10 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools.SelectionRemoveToolView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>
<Grid />
</UserControl>

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
/// <summary>
/// Interaction logic for SelectionRemoveToolView.xaml
/// Interaction logic for SelectionRemoveToolView.xaml
/// </summary>
public partial class SelectionRemoveToolView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
InitializeComponent();
}
}
}
}

View File

@ -20,7 +20,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
base.MouseUp(sender, e);
var position = e.GetPosition((IInputElement)sender);
var position = e.GetPosition((IInputElement) sender);
var selectedRect = new Rect(MouseDownStartPosition, position);
foreach (var device in ProfileViewModel.Devices)

View File

@ -1,12 +1,12 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools.SelectionToolView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<Style TargetType="Shape" x:Key="ShowIfMouseDown">
@ -60,4 +60,4 @@
</Rectangle.Fill>
</Rectangle>
</Canvas>
</UserControl>
</UserControl>

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
/// <summary>
/// Interaction logic for SelectionToolView.xaml
/// Interaction logic for SelectionToolView.xaml
/// </summary>
public partial class SelectionToolView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
InitializeComponent();
}
}
}
}

View File

@ -1,12 +1,10 @@
<UserControl x:Class="Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools.ViewpointMoveToolView"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools"
mc:Ignorable="d"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</UserControl>
<Grid />
</UserControl>

View File

@ -1,22 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls;
namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{
/// <summary>
/// Interaction logic for ViewpointMoveToolView.xaml
/// Interaction logic for ViewpointMoveToolView.xaml
/// </summary>
public partial class ViewpointMoveToolView : UserControl
{
@ -25,4 +12,4 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
InitializeComponent();
}
}
}
}