mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Profile tree - Fixed moving layers into folders leaving a copy behind
Profile tree - Added rename/delete hotkeys to elements Profile tree - Moved dialogs to the tree panel Layer properties - Auto-select transform tool when modifying transform properties
This commit is contained in:
parent
375c04090b
commit
a3290c40f8
@ -8,7 +8,7 @@
|
||||
KeyframesSupported = false;
|
||||
DataBindingsSupported = false;
|
||||
|
||||
BaseValueChanged += OnBaseValueChanged;
|
||||
CurrentValueSet += OnCurrentValueSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -25,7 +25,7 @@
|
||||
throw new ArtemisCoreException("Color Gradients do not support keyframes.");
|
||||
}
|
||||
|
||||
private void OnBaseValueChanged(object sender, LayerPropertyEventArgs<ColorGradient> e)
|
||||
private void OnCurrentValueSet(object sender, LayerPropertyEventArgs<ColorGradient> e)
|
||||
{
|
||||
// Don't allow color gradients to be null
|
||||
if (BaseValue == null)
|
||||
|
||||
@ -157,7 +157,7 @@ namespace Artemis.Core
|
||||
Transform.GroupDescription = (PropertyGroupDescriptionAttribute) transformAttribute;
|
||||
Transform.Initialize(this, "Transform.", Constants.CorePluginInfo);
|
||||
|
||||
General.ShapeType.BaseValueChanged += ShapeTypeOnBaseValueChanged;
|
||||
General.ShapeType.CurrentValueSet += ShapeTypeOnCurrentValueSet;
|
||||
ApplyShapeType();
|
||||
ActivateLayerBrush();
|
||||
}
|
||||
@ -213,7 +213,7 @@ namespace Artemis.Core
|
||||
|
||||
#region Shape management
|
||||
|
||||
private void ShapeTypeOnBaseValueChanged(object sender, EventArgs e)
|
||||
private void ShapeTypeOnCurrentValueSet(object sender, EventArgs e)
|
||||
{
|
||||
ApplyShapeType();
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Artemis.Core
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of property encapsulated in this layer property</typeparam>
|
||||
public abstract class LayerProperty<T> : ILayerProperty
|
||||
public class LayerProperty<T> : ILayerProperty
|
||||
{
|
||||
private bool _disposed;
|
||||
|
||||
@ -120,8 +120,7 @@ namespace Artemis.Core
|
||||
|
||||
_baseValue = value;
|
||||
Update(0);
|
||||
OnBaseValueChanged();
|
||||
LayerPropertyGroup.OnLayerPropertyBaseValueChanged(new LayerPropertyEventArgs(this));
|
||||
OnCurrentValueSet();
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,6 +164,7 @@ namespace Artemis.Core
|
||||
// Force an update so that the base value is applied to the current value and
|
||||
// keyframes/data bindings are applied using the new base value
|
||||
Update(0);
|
||||
OnCurrentValueSet();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -534,9 +534,9 @@ namespace Artemis.Core
|
||||
public event EventHandler<LayerPropertyEventArgs<T>> Updated;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the base value of the layer property was updated
|
||||
/// Occurs when the current value of the layer property was updated by some form of input
|
||||
/// </summary>
|
||||
public event EventHandler<LayerPropertyEventArgs<T>> BaseValueChanged;
|
||||
public event EventHandler<LayerPropertyEventArgs<T>> CurrentValueSet;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the <see cref="IsHidden" /> value of the layer property was updated
|
||||
@ -573,9 +573,10 @@ namespace Artemis.Core
|
||||
Updated?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||
}
|
||||
|
||||
protected virtual void OnBaseValueChanged()
|
||||
protected virtual void OnCurrentValueSet()
|
||||
{
|
||||
BaseValueChanged?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||
CurrentValueSet?.Invoke(this, new LayerPropertyEventArgs<T>(this));
|
||||
LayerPropertyGroup.OnLayerPropertyOnCurrentValueSet(new LayerPropertyEventArgs(this));
|
||||
}
|
||||
|
||||
protected virtual void OnVisibilityChanged()
|
||||
|
||||
@ -274,10 +274,10 @@ namespace Artemis.Core
|
||||
public event EventHandler PropertyGroupInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when one of the base value of one of the layer properties in this group changes
|
||||
/// Occurs when one of the current value of one of the layer properties in this group changes by some form of input
|
||||
/// <para>Note: Will not trigger on properties in child groups</para>
|
||||
/// </summary>
|
||||
public event EventHandler<LayerPropertyEventArgs> LayerPropertyBaseValueChanged;
|
||||
public event EventHandler<LayerPropertyEventArgs> LayerPropertyOnCurrentValueSet;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the <see cref="IsHidden" /> value of the layer property was updated
|
||||
@ -294,9 +294,9 @@ namespace Artemis.Core
|
||||
VisibilityChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
internal virtual void OnLayerPropertyBaseValueChanged(LayerPropertyEventArgs e)
|
||||
internal virtual void OnLayerPropertyOnCurrentValueSet(LayerPropertyEventArgs e)
|
||||
{
|
||||
LayerPropertyBaseValueChanged?.Invoke(this, e);
|
||||
LayerPropertyOnCurrentValueSet?.Invoke(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@ -65,6 +65,7 @@
|
||||
KeyDown="InputKeyDown"
|
||||
Visibility="Collapsed"
|
||||
RequestBringIntoView="Input_OnRequestBringIntoView"
|
||||
PreviewTextInput="Input_PreviewTextInput" />
|
||||
PreviewTextInput="Input_PreviewTextInput"
|
||||
DataObject.Pasting="Input_OnPasting"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
@ -18,6 +16,8 @@ namespace Artemis.UI.Shared
|
||||
new FrameworkPropertyMetadata(default(float), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, FloatPropertyChangedCallback));
|
||||
|
||||
public static readonly DependencyProperty StepSizeProperty = DependencyProperty.Register(nameof(StepSize), typeof(float), typeof(DraggableFloat));
|
||||
public static readonly DependencyProperty MinProperty = DependencyProperty.Register(nameof(Min), typeof(float?), typeof(DraggableFloat));
|
||||
public static readonly DependencyProperty MaxProperty = DependencyProperty.Register(nameof(Max), typeof(float?), typeof(DraggableFloat));
|
||||
|
||||
public static readonly RoutedEvent ValueChangedEvent =
|
||||
EventManager.RegisterRoutedEvent(
|
||||
@ -49,6 +49,18 @@ namespace Artemis.UI.Shared
|
||||
set => SetValue(StepSizeProperty, value);
|
||||
}
|
||||
|
||||
public float? Min
|
||||
{
|
||||
get => (float?) GetValue(MinProperty);
|
||||
set => SetValue(MinProperty, value);
|
||||
}
|
||||
|
||||
public float? Max
|
||||
{
|
||||
get => (float?) GetValue(MaxProperty);
|
||||
set => SetValue(MaxProperty, value);
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public event EventHandler DragStarted;
|
||||
@ -126,7 +138,16 @@ namespace Artemis.UI.Shared
|
||||
if (stepSize == 0)
|
||||
stepSize = 0.1m;
|
||||
|
||||
Value = (float) UltimateRoundingFunction(startValue + stepSize * (x - startX), stepSize, 0.5m);
|
||||
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
|
||||
stepSize = stepSize * 10;
|
||||
|
||||
var value = (float) UltimateRoundingFunction(startValue + stepSize * (x - startX), stepSize, 0.5m);
|
||||
if (Min != null)
|
||||
value = Math.Max(value, Min.Value);
|
||||
if (Max != null)
|
||||
value = Math.Min(value, Max.Value);
|
||||
|
||||
Value = value;
|
||||
}
|
||||
|
||||
private void InputLostFocus(object sender, RoutedEventArgs e)
|
||||
@ -166,9 +187,34 @@ namespace Artemis.UI.Shared
|
||||
|
||||
private void Input_PreviewTextInput(object sender, TextCompositionEventArgs e)
|
||||
{
|
||||
var seperator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
|
||||
var regex = new Regex("^[" + seperator + "][-|0-9]+$|^-?[0-9]*[" + seperator + "]{0,1}[0-9]*$");
|
||||
e.Handled = !regex.IsMatch(e.Text);
|
||||
e.Handled = !ValidateInput(sender, e);
|
||||
}
|
||||
|
||||
private void Input_OnPasting(object sender, DataObjectPastingEventArgs e)
|
||||
{
|
||||
if (e.DataObject.GetDataPresent(typeof(string)))
|
||||
{
|
||||
var text = (string) e.DataObject.GetData(typeof(string));
|
||||
if (!float.TryParse(text, out _))
|
||||
e.CancelCommand();
|
||||
}
|
||||
else
|
||||
e.CancelCommand();
|
||||
}
|
||||
|
||||
// Borrowed from https://stackoverflow.com/a/48082972/5015269 because a regex approach has bad compatibility with
|
||||
// different locales
|
||||
private bool ValidateInput(object sender, TextCompositionEventArgs e)
|
||||
{
|
||||
if (!(sender is TextBox textBox))
|
||||
return false;
|
||||
|
||||
// Use SelectionStart property to find the caret position.
|
||||
// Insert the previewed text into the existing text in the textbox.
|
||||
var fullText = textBox.Text.Insert(textBox.SelectionStart, e.Text);
|
||||
|
||||
// If parsing is successful, set Handled to false
|
||||
return float.TryParse(fullText, out _);
|
||||
}
|
||||
|
||||
private static decimal UltimateRoundingFunction(decimal amountToRound, decimal nearstOf, decimal fairness)
|
||||
|
||||
@ -15,7 +15,7 @@ namespace Artemis.UI.Shared
|
||||
LayerProperty = layerProperty;
|
||||
ProfileEditorService = profileEditorService;
|
||||
LayerProperty.Updated += LayerPropertyOnUpdated;
|
||||
LayerProperty.BaseValueChanged += LayerPropertyOnUpdated;
|
||||
LayerProperty.CurrentValueSet += LayerPropertyOnUpdated;
|
||||
LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange;
|
||||
LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange;
|
||||
UpdateInputValue();
|
||||
@ -26,7 +26,7 @@ namespace Artemis.UI.Shared
|
||||
LayerProperty = layerProperty;
|
||||
ProfileEditorService = profileEditorService;
|
||||
LayerProperty.Updated += LayerPropertyOnUpdated;
|
||||
LayerProperty.BaseValueChanged += LayerPropertyOnUpdated;
|
||||
LayerProperty.CurrentValueSet += LayerPropertyOnUpdated;
|
||||
LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange;
|
||||
LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange;
|
||||
UpdateInputValue();
|
||||
@ -56,7 +56,7 @@ namespace Artemis.UI.Shared
|
||||
public override void Dispose()
|
||||
{
|
||||
LayerProperty.Updated -= LayerPropertyOnUpdated;
|
||||
LayerProperty.BaseValueChanged -= LayerPropertyOnUpdated;
|
||||
LayerProperty.CurrentValueSet -= LayerPropertyOnUpdated;
|
||||
LayerProperty.DataBindingEnabled -= LayerPropertyOnDataBindingChange;
|
||||
LayerProperty.DataBindingDisabled -= LayerPropertyOnDataBindingChange;
|
||||
Dispose(true);
|
||||
|
||||
@ -13,11 +13,19 @@
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" Text="{Binding Header}" TextWrapping="Wrap" />
|
||||
<TextBlock Style="{StaticResource MaterialDesignBody1TextBlock}" Margin="0 20 0 20" Text="{Binding Text}" TextWrapping="Wrap" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}" IsCancel="True" Margin="0 8 8 0"
|
||||
Command="{s:Action Cancel}" Content="{Binding CancelText}" />
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}" IsDefault="True" Margin="0 8 0 0"
|
||||
Command="{s:Action Confirm}" Content="{Binding ConfirmText}" />
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 8 0 0">
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
||||
Focusable="False"
|
||||
IsCancel="True"
|
||||
Command="{s:Action Cancel}"
|
||||
Content="{Binding CancelText}" />
|
||||
<Button x:Name="ConfirmButton"
|
||||
Style="{StaticResource MaterialDesignFlatButton}"
|
||||
IsDefault="True"
|
||||
Focusable="True"
|
||||
Command="{s:Action Confirm}"
|
||||
Content="{Binding ConfirmText}" />
|
||||
</StackPanel>
|
||||
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@ -12,7 +12,7 @@ namespace Artemis.UI.Shared.Services
|
||||
public interface IDialogService : IArtemisSharedUIService
|
||||
{
|
||||
/// <summary>
|
||||
/// Shows a confirm dialog on the dialog host provided
|
||||
/// Shows a confirm dialog on the main dialog host
|
||||
/// </summary>
|
||||
/// <param name="header">The title of the dialog</param>
|
||||
/// <param name="text">The body text of the dialog</param>
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
<shared:DraggableFloat Value="{Binding InputValue}"
|
||||
materialDesign:ValidationAssist.UsePopup="True"
|
||||
StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}"
|
||||
Max="{Binding LayerProperty.PropertyDescription.MaxInputValue}"
|
||||
Min="{Binding LayerProperty.PropertyDescription.MinInputValue}"
|
||||
DragStarted="{s:Action InputDragStarted}"
|
||||
DragEnded="{s:Action InputDragEnded}"
|
||||
IsEnabled="{Binding IsEnabled}"/>
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
<shared:DraggableFloat Value="{Binding InputValue}"
|
||||
materialDesign:ValidationAssist.UsePopup="True"
|
||||
StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}"
|
||||
Max="{Binding LayerProperty.PropertyDescription.MaxInputValue}"
|
||||
Min="{Binding LayerProperty.PropertyDescription.MinInputValue}"
|
||||
DragStarted="{s:Action InputDragStarted}"
|
||||
DragEnded="{s:Action InputDragEnded}"
|
||||
IsEnabled="{Binding IsEnabled}"/>
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
<shared:DraggableFloat ToolTip="X-coordinate (horizontal)"
|
||||
Value="{Binding X}"
|
||||
StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}"
|
||||
Max="{Binding LayerProperty.PropertyDescription.MaxInputValue}"
|
||||
Min="{Binding LayerProperty.PropertyDescription.MinInputValue}"
|
||||
DragStarted="{s:Action InputDragStarted}"
|
||||
DragEnded="{s:Action InputDragEnded}"
|
||||
IsEnabled="{Binding IsXEnabled}"/>
|
||||
@ -21,6 +23,8 @@
|
||||
<shared:DraggableFloat ToolTip="Y-coordinate (vertical)"
|
||||
Value="{Binding Y}"
|
||||
StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}"
|
||||
Max="{Binding LayerProperty.PropertyDescription.MaxInputValue}"
|
||||
Min="{Binding LayerProperty.PropertyDescription.MinInputValue}"
|
||||
DragStarted="{s:Action InputDragStarted}"
|
||||
DragEnded="{s:Action InputDragEnded}"
|
||||
IsEnabled="{Binding IsYEnabled}"/>
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
<shared:DraggableFloat ToolTip="Height"
|
||||
Value="{Binding Height}"
|
||||
StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}"
|
||||
Max="{Binding LayerProperty.PropertyDescription.MaxInputValue}"
|
||||
Min="{Binding LayerProperty.PropertyDescription.MinInputValue}"
|
||||
DragStarted="{s:Action InputDragStarted}"
|
||||
DragEnded="{s:Action InputDragEnded}"
|
||||
IsEnabled="{Binding IsHeightEnabled}"/>
|
||||
@ -21,6 +23,8 @@
|
||||
<shared:DraggableFloat ToolTip="Width"
|
||||
Value="{Binding Width}"
|
||||
StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}"
|
||||
Max="{Binding LayerProperty.PropertyDescription.MaxInputValue}"
|
||||
Min="{Binding LayerProperty.PropertyDescription.MinInputValue}"
|
||||
DragStarted="{s:Action InputDragStarted}"
|
||||
DragEnded="{s:Action InputDragEnded}"
|
||||
IsEnabled="{Binding IsWidthEnabled}"/>
|
||||
|
||||
@ -103,7 +103,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
var toRemove = Items.Where(c => !DisplayConditionGroup.Children.Contains(c.Model)).ToList();
|
||||
// Using RemoveRange breaks our lovely animations
|
||||
foreach (var displayConditionViewModel in toRemove)
|
||||
CloseItem(displayConditionViewModel);
|
||||
Items.Remove(displayConditionViewModel);
|
||||
|
||||
foreach (var childModel in Model.Children)
|
||||
{
|
||||
@ -113,18 +113,18 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
switch (childModel)
|
||||
{
|
||||
case DisplayConditionGroup displayConditionGroup:
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, IsListGroup));
|
||||
Items.Add(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, IsListGroup));
|
||||
break;
|
||||
case DisplayConditionList displayConditionListPredicate:
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate));
|
||||
Items.Add(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate));
|
||||
break;
|
||||
case DisplayConditionPredicate displayConditionPredicate:
|
||||
if (!IsListGroup)
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate));
|
||||
Items.Add(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate));
|
||||
break;
|
||||
case DisplayConditionListPredicate displayConditionListPredicate:
|
||||
if (IsListGroup)
|
||||
ActivateItem(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate));
|
||||
Items.Add(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
var toRemove = Items.Where(c => !DisplayConditionList.Children.Contains(c.Model)).ToList();
|
||||
// Using RemoveRange breaks our lovely animations
|
||||
foreach (var displayConditionViewModel in toRemove)
|
||||
CloseItem(displayConditionViewModel);
|
||||
Items.Remove(displayConditionViewModel);
|
||||
|
||||
foreach (var childModel in Model.Children)
|
||||
{
|
||||
@ -163,7 +163,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
|
||||
var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, true);
|
||||
viewModel.IsRootGroup = true;
|
||||
ActivateItem(viewModel);
|
||||
Items.Add(viewModel);
|
||||
}
|
||||
|
||||
foreach (var childViewModel in Items)
|
||||
|
||||
@ -39,7 +39,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
||||
// Create a data binding VM for each data bindable property. These VMs will be responsible for retrieving
|
||||
// and creating the actual data bindings
|
||||
foreach (var registration in registrations)
|
||||
ActivateItem(_dataBindingsVmFactory.DataBindingViewModel(registration));
|
||||
Items.Add(_dataBindingsVmFactory.DataBindingViewModel(registration));
|
||||
|
||||
SelectedItemIndex = 0;
|
||||
}
|
||||
|
||||
@ -9,62 +9,67 @@
|
||||
xmlns:behaviors="clr-namespace:Artemis.UI.Behaviors"
|
||||
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:profileTree1="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree"
|
||||
xmlns:treeItem1="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem"
|
||||
xmlns:treeItem="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type profileTree1:ProfileTreeViewModel}}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}" Margin="10 5 0 -4">
|
||||
Profile elements
|
||||
</TextBlock>
|
||||
<Separator Style="{StaticResource MaterialDesignDarkSeparator}" Margin="8 0" />
|
||||
</StackPanel>
|
||||
<materialDesign:DialogHost IsTabStop="False" Focusable="False" Identifier="ProfileTreeDialog" DialogTheme="Inherit">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}" Margin="10 5 0 -4">
|
||||
Profile elements
|
||||
</TextBlock>
|
||||
<Separator Style="{StaticResource MaterialDesignDarkSeparator}" Margin="8 0" />
|
||||
</StackPanel>
|
||||
|
||||
<TreeView Grid.Row="1"
|
||||
ItemsSource="{Binding ActiveItem.Items}"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
dd:DragDrop.IsDragSource="True"
|
||||
dd:DragDrop.IsDropTarget="True"
|
||||
dd:DragDrop.DropHandler="{Binding}">
|
||||
<b:Interaction.Behaviors>
|
||||
<behaviors:TreeViewSelectionBehavior ExpandSelected="True" SelectedItem="{Binding SelectedTreeItem}" />
|
||||
</b:Interaction.Behaviors>
|
||||
<TreeView.Resources>
|
||||
<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 Items}">
|
||||
<ContentControl s:View.Model="{Binding}" />
|
||||
</HierarchicalDataTemplate>
|
||||
</TreeView.Resources>
|
||||
</TreeView>
|
||||
<TreeView Grid.Row="1"
|
||||
ItemsSource="{Binding ActiveItem.Items}"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
dd:DragDrop.IsDragSource="True"
|
||||
dd:DragDrop.IsDropTarget="True"
|
||||
dd:DragDrop.DropHandler="{Binding}">
|
||||
<TreeView.InputBindings>
|
||||
<KeyBinding Key="F2" Command="{s:Action RenameElement}" s:View.ActionTarget="{Binding SelectedTreeItem}"/>
|
||||
<KeyBinding Key="Delete" Command="{s:Action DeleteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}"/>
|
||||
</TreeView.InputBindings>
|
||||
<b:Interaction.Behaviors>
|
||||
<behaviors:TreeViewSelectionBehavior ExpandSelected="True" SelectedItem="{Binding SelectedTreeItem}" />
|
||||
</b:Interaction.Behaviors>
|
||||
<TreeView.Resources>
|
||||
<HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Items}">
|
||||
<ContentControl s:View.Model="{Binding}" />
|
||||
</HierarchicalDataTemplate>
|
||||
<HierarchicalDataTemplate DataType="{x:Type treeItem:LayerViewModel}">
|
||||
<ContentControl s:View.Model="{Binding}" />
|
||||
</HierarchicalDataTemplate>
|
||||
</TreeView.Resources>
|
||||
</TreeView>
|
||||
|
||||
<StackPanel HorizontalAlignment="Right" Grid.Row="2" Orientation="Horizontal" Margin="8">
|
||||
<Button Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
Padding="2 0 2 0"
|
||||
Width="30"
|
||||
Height="30"
|
||||
materialDesign:RippleAssist.IsCentered="True"
|
||||
ToolTip="Add new folder to root"
|
||||
Command="{s:Action AddFolder}">
|
||||
<materialDesign:PackIcon Kind="CreateNewFolder" Width="15" />
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Padding="2 0 2 0"
|
||||
materialDesign:RippleAssist.IsCentered="True"
|
||||
ToolTip="Add new layer to root"
|
||||
Command="{s:Action AddLayer}">
|
||||
<materialDesign:PackIcon Kind="LayersPlus" Width="15" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<StackPanel HorizontalAlignment="Right" Grid.Row="2" Orientation="Horizontal" Margin="8">
|
||||
<Button Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
Padding="2 0 2 0"
|
||||
Width="30"
|
||||
Height="30"
|
||||
materialDesign:RippleAssist.IsCentered="True"
|
||||
ToolTip="Add new folder to root"
|
||||
Command="{s:Action AddFolder}">
|
||||
<materialDesign:PackIcon Kind="CreateNewFolder" Width="15" />
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Padding="2 0 2 0"
|
||||
materialDesign:RippleAssist.IsCentered="True"
|
||||
ToolTip="Add new layer to root"
|
||||
Command="{s:Action AddLayer}">
|
||||
<materialDesign:PackIcon Kind="LayersPlus" Width="15" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</materialDesign:DialogHost>
|
||||
</UserControl>
|
||||
@ -71,6 +71,8 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
{
|
||||
var sourceParent = (TreeItemViewModel) source.Parent;
|
||||
var parent = (TreeItemViewModel) Parent;
|
||||
|
||||
// If the parents are different, remove the element from the old parent and add it to the new parent
|
||||
if (source.Parent != Parent)
|
||||
{
|
||||
sourceParent.RemoveExistingElement(source);
|
||||
@ -146,7 +148,8 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
// ReSharper disable once UnusedMember.Global - Called from view
|
||||
public async Task RenameElement()
|
||||
{
|
||||
var result = await _dialogService.ShowDialog<RenameViewModel>(
|
||||
var result = await _dialogService.ShowDialogAt<RenameViewModel>(
|
||||
"ProfileTreeDialog",
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{"subject", ProfileElement is Folder ? "folder" : "layer"},
|
||||
@ -163,9 +166,10 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
// ReSharper disable once UnusedMember.Global - Called from view
|
||||
public async Task DeleteElement()
|
||||
{
|
||||
var result = await _dialogService.ShowConfirmDialog(
|
||||
var result = await _dialogService.ShowConfirmDialogAt(
|
||||
"ProfileTreeDialog",
|
||||
"Delete profile element",
|
||||
"Are you sure you want to delete this element? This cannot be undone."
|
||||
"Are you sure?"
|
||||
);
|
||||
|
||||
if (!result)
|
||||
@ -185,7 +189,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
// Remove VMs that are no longer a child
|
||||
var toRemove = Items.Where(c => c.ProfileElement.Parent != ProfileElement).ToList();
|
||||
foreach (var treeItemViewModel in toRemove)
|
||||
DeactivateItem(treeItemViewModel);
|
||||
Items.Remove(treeItemViewModel);
|
||||
|
||||
// Order the children
|
||||
var vmsList = Items.OrderBy(v => v.ProfileElement.Order).ToList();
|
||||
@ -222,7 +226,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
||||
foreach (var treeItemViewModel in newChildren)
|
||||
{
|
||||
treeItemViewModel.UpdateProfileElements();
|
||||
ActivateItem(treeItemViewModel);
|
||||
Items.Add(treeItemViewModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
private BindableCollection<ArtemisDevice> _devices;
|
||||
private BindableCollection<ArtemisLed> _highlightedLeds;
|
||||
private PluginSetting<bool> _highlightSelectedLayer;
|
||||
private bool _isInitializing;
|
||||
private PluginSetting<bool> _onlyShowSelectedShape;
|
||||
private PanZoomViewModel _panZoomViewModel;
|
||||
private Layer _previousSelectedLayer;
|
||||
@ -67,12 +66,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
eventAggregator.Subscribe(this);
|
||||
}
|
||||
|
||||
public bool IsInitializing
|
||||
{
|
||||
get => _isInitializing;
|
||||
private set => SetAndNotify(ref _isInitializing, value);
|
||||
}
|
||||
|
||||
public bool CanSelectEditTool
|
||||
{
|
||||
get => _canSelectEditTool;
|
||||
@ -375,11 +368,16 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
private void OnProfileElementSelected(object sender, EventArgs e)
|
||||
{
|
||||
if (_previousSelectedLayer != null)
|
||||
{
|
||||
_previousSelectedLayer.LayerBrushUpdated -= SelectedLayerOnLayerBrushUpdated;
|
||||
_previousSelectedLayer.Transform.LayerPropertyOnCurrentValueSet -= TransformValueChanged;
|
||||
}
|
||||
|
||||
if (_profileEditorService.SelectedProfileElement is Layer layer)
|
||||
{
|
||||
_previousSelectedLayer = layer;
|
||||
_previousSelectedLayer.LayerBrushUpdated += SelectedLayerOnLayerBrushUpdated;
|
||||
_previousSelectedLayer.Transform.LayerPropertyOnCurrentValueSet += TransformValueChanged;
|
||||
}
|
||||
else
|
||||
_previousSelectedLayer = null;
|
||||
@ -392,7 +390,13 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization
|
||||
{
|
||||
UpdateCanSelectEditTool();
|
||||
}
|
||||
|
||||
|
||||
private void TransformValueChanged(object? sender, LayerPropertyEventArgs e)
|
||||
{
|
||||
if (ActiveToolIndex != 1)
|
||||
ActivateToolByIndex(1);
|
||||
}
|
||||
|
||||
private void OnSelectedProfileElementUpdated(object sender, EventArgs e)
|
||||
{
|
||||
ApplyActiveProfile();
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
Data="{Binding ShapeGeometry, Mode=OneWay}"
|
||||
Fill="Transparent"
|
||||
Stroke="{DynamicResource PrimaryHueMidBrush}"
|
||||
StrokeThickness="{Binding OutlineThickness}"
|
||||
StrokeDashArray="2 2"
|
||||
Cursor="/Resources/Cursors/aero_drag.cur"
|
||||
MouseDown="MoveOnMouseDown"
|
||||
|
||||
@ -49,31 +49,41 @@
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</mde:MaterialWindow.Resources>
|
||||
<materialDesign:DialogHost Identifier="RootDialog" DialogTheme="Inherit" SnackbarMessageQueue="{Binding MainMessageQueue}">
|
||||
<Grid>
|
||||
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding SidebarViewModel.IsSidebarOpen}">
|
||||
<materialDesign:DrawerHost.LeftDrawerContent>
|
||||
<ContentControl s:View.Model="{Binding SidebarViewModel}" Width="220" ClipToBounds="False" />
|
||||
</materialDesign:DrawerHost.LeftDrawerContent>
|
||||
<DockPanel>
|
||||
<mde:AppBar Type="Dense"
|
||||
IsNavigationDrawerOpen="{Binding SidebarViewModel.IsSidebarOpen, Mode=TwoWay}"
|
||||
Title="{Binding ActiveItem.DisplayName}"
|
||||
ShowNavigationDrawerButton="True"
|
||||
DockPanel.Dock="Top">
|
||||
<StackPanel>
|
||||
<!-- Bug: materialDesign:RippleAssist.RippleOnTop doesn't look as nice but otherwise it doesn't work at all, not sure why -->
|
||||
<Button Style="{StaticResource MaterialDesignIconForegroundButton}" ToolTip="Open debugger" Command="{s:Action ShowDebugger}"
|
||||
materialDesign:RippleAssist.RippleOnTop="True">
|
||||
<materialDesign:PackIcon Kind="Matrix" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</mde:AppBar>
|
||||
<materialDesign:DialogHost IsTabStop="False"
|
||||
Focusable="False"
|
||||
Identifier="RootDialog"
|
||||
DialogTheme="Inherit"
|
||||
SnackbarMessageQueue="{Binding MainMessageQueue}">
|
||||
|
||||
<materialDesign:DrawerHost IsLeftDrawerOpen="{Binding SidebarViewModel.IsSidebarOpen}">
|
||||
<materialDesign:DrawerHost.LeftDrawerContent>
|
||||
<ContentControl s:View.Model="{Binding SidebarViewModel}" Width="220" ClipToBounds="False" />
|
||||
</materialDesign:DrawerHost.LeftDrawerContent>
|
||||
<DockPanel>
|
||||
<mde:AppBar Type="Dense"
|
||||
IsNavigationDrawerOpen="{Binding SidebarViewModel.IsSidebarOpen, Mode=TwoWay}"
|
||||
Title="{Binding ActiveItem.DisplayName}"
|
||||
ShowNavigationDrawerButton="True"
|
||||
DockPanel.Dock="Top">
|
||||
<StackPanel>
|
||||
<!-- Bug: materialDesign:RippleAssist.RippleOnTop doesn't look as nice but otherwise it doesn't work at all, not sure why -->
|
||||
<Button Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||
ToolTip="Open debugger"
|
||||
Command="{s:Action ShowDebugger}"
|
||||
materialDesign:RippleAssist.RippleOnTop="True">
|
||||
<materialDesign:PackIcon Kind="Matrix" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</mde:AppBar>
|
||||
|
||||
<Grid>
|
||||
<ContentControl s:View.Model="{Binding ActiveItem}" Style="{StaticResource InitializingFade}" />
|
||||
</DockPanel>
|
||||
</materialDesign:DrawerHost>
|
||||
<materialDesign:Snackbar x:Name="MainSnackbar" MessageQueue="{Binding MainMessageQueue}" materialDesign:SnackbarMessage.InlineActionButtonMaxHeight="80"
|
||||
materialDesign:SnackbarMessage.ContentMaxHeight="200" />
|
||||
</Grid>
|
||||
<materialDesign:Snackbar x:Name="MainSnackbar"
|
||||
MessageQueue="{Binding MainMessageQueue}"
|
||||
materialDesign:SnackbarMessage.InlineActionButtonMaxHeight="80"
|
||||
materialDesign:SnackbarMessage.ContentMaxHeight="200" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</materialDesign:DrawerHost>
|
||||
</materialDesign:DialogHost>
|
||||
</mde:MaterialWindow>
|
||||
@ -19,17 +19,14 @@ namespace Artemis.Plugins.LayerBrushes.Color
|
||||
public override void EnableLayerBrush()
|
||||
{
|
||||
Layer.RenderPropertiesUpdated += HandleShaderChange;
|
||||
Properties.LayerPropertyBaseValueChanged += HandleShaderChange;
|
||||
Properties.LayerPropertyOnCurrentValueSet += HandleShaderChange;
|
||||
Properties.Colors.BaseValue.PropertyChanged += BaseValueOnPropertyChanged;
|
||||
}
|
||||
|
||||
public override void DisableLayerBrush()
|
||||
{
|
||||
Layer.RenderPropertiesUpdated -= HandleShaderChange;
|
||||
Properties.GradientType.BaseValueChanged -= HandleShaderChange;
|
||||
Properties.Color.BaseValueChanged -= HandleShaderChange;
|
||||
Properties.TileMode.BaseValueChanged -= HandleShaderChange;
|
||||
Properties.ColorsMultiplier.BaseValueChanged -= HandleShaderChange;
|
||||
Properties.LayerPropertyOnCurrentValueSet -= HandleShaderChange;
|
||||
Properties.Colors.BaseValue.PropertyChanged -= BaseValueOnPropertyChanged;
|
||||
|
||||
_paint?.Dispose();
|
||||
|
||||
@ -38,26 +38,26 @@ namespace Artemis.Plugins.LayerBrushes.Color.PropertyGroups
|
||||
|
||||
protected override void EnableProperties()
|
||||
{
|
||||
GradientType.BaseValueChanged += GradientTypeOnBaseValueChanged;
|
||||
GradientType.CurrentValueSet += GradientTypeOnCurrentValueSet;
|
||||
if (ProfileElement is Layer layer)
|
||||
layer.General.ResizeMode.BaseValueChanged += ResizeModeOnBaseValueChanged;
|
||||
layer.General.ResizeMode.CurrentValueSet += ResizeModeOnCurrentValueSet;
|
||||
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
protected override void DisableProperties()
|
||||
{
|
||||
GradientType.BaseValueChanged -= GradientTypeOnBaseValueChanged;
|
||||
GradientType.CurrentValueSet -= GradientTypeOnCurrentValueSet;
|
||||
if (ProfileElement is Layer layer)
|
||||
layer.General.ResizeMode.BaseValueChanged -= ResizeModeOnBaseValueChanged;
|
||||
layer.General.ResizeMode.CurrentValueSet -= ResizeModeOnCurrentValueSet;
|
||||
}
|
||||
|
||||
private void GradientTypeOnBaseValueChanged(object sender, LayerPropertyEventArgs<ColorType> e)
|
||||
private void GradientTypeOnCurrentValueSet(object sender, LayerPropertyEventArgs<ColorType> e)
|
||||
{
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
private void ResizeModeOnBaseValueChanged(object sender, LayerPropertyEventArgs<LayerResizeMode> e)
|
||||
private void ResizeModeOnCurrentValueSet(object sender, LayerPropertyEventArgs<LayerResizeMode> e)
|
||||
{
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ namespace Artemis.Plugins.LayerBrushes.Color.PropertyGroups
|
||||
protected override void EnableProperties()
|
||||
{
|
||||
if (ProfileElement is Layer layer)
|
||||
layer.General.ResizeMode.BaseValueChanged += ResizeModeOnBaseValueChanged;
|
||||
layer.General.ResizeMode.CurrentValueSet += ResizeModeOnCurrentValueSet;
|
||||
|
||||
UpdateVisibility();
|
||||
}
|
||||
@ -27,10 +27,10 @@ namespace Artemis.Plugins.LayerBrushes.Color.PropertyGroups
|
||||
protected override void DisableProperties()
|
||||
{
|
||||
if (ProfileElement is Layer layer)
|
||||
layer.General.ResizeMode.BaseValueChanged -= ResizeModeOnBaseValueChanged;
|
||||
layer.General.ResizeMode.CurrentValueSet -= ResizeModeOnCurrentValueSet;
|
||||
}
|
||||
|
||||
private void ResizeModeOnBaseValueChanged(object sender, LayerPropertyEventArgs<LayerResizeMode> e)
|
||||
private void ResizeModeOnCurrentValueSet(object sender, LayerPropertyEventArgs<LayerResizeMode> e)
|
||||
{
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
@ -44,12 +44,18 @@ namespace Artemis.Plugins.LayerBrushes.Noise
|
||||
|
||||
protected override void EnableProperties()
|
||||
{
|
||||
ColorType.BaseValueChanged += (sender, args) => UpdateVisibility();
|
||||
ColorType.CurrentValueSet += ColorTypeOnCurrentValueSet;
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
protected override void DisableProperties()
|
||||
{
|
||||
ColorType.CurrentValueSet -= ColorTypeOnCurrentValueSet;
|
||||
}
|
||||
|
||||
private void ColorTypeOnCurrentValueSet(object sender, LayerPropertyEventArgs<ColorMappingType> e)
|
||||
{
|
||||
UpdateVisibility();
|
||||
}
|
||||
|
||||
private void UpdateVisibility()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user