diff --git a/src/Avalonia/Artemis.UI.Shared/Controls/EnumComboBox.axaml.cs b/src/Avalonia/Artemis.UI.Shared/Controls/EnumComboBox.axaml.cs
index f0663ce77..f04f5572d 100644
--- a/src/Avalonia/Artemis.UI.Shared/Controls/EnumComboBox.axaml.cs
+++ b/src/Avalonia/Artemis.UI.Shared/Controls/EnumComboBox.axaml.cs
@@ -58,7 +58,7 @@ namespace Artemis.UI.Shared.Controls
private void OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
- if (_enumComboBox == null)
+ if (_enumComboBox == null || _enumComboBox.SelectedIndex == -1)
return;
(Enum enumValue, _) = _currentValues[_enumComboBox.SelectedIndex];
diff --git a/src/Avalonia/Artemis.UI.Shared/Services/PropertyInput/PropertyInputViewModel.cs b/src/Avalonia/Artemis.UI.Shared/Services/PropertyInput/PropertyInputViewModel.cs
index 04be6fc19..2956c61bb 100644
--- a/src/Avalonia/Artemis.UI.Shared/Services/PropertyInput/PropertyInputViewModel.cs
+++ b/src/Avalonia/Artemis.UI.Shared/Services/PropertyInput/PropertyInputViewModel.cs
@@ -17,10 +17,8 @@ namespace Artemis.UI.Shared.Services.PropertyInput;
/// The type of property this input view model supports
public abstract class PropertyInputViewModel : PropertyInputViewModel
{
- private T _dragStartValue;
- private bool _inputDragging;
-
[AllowNull] private T _inputValue;
+ private LayerPropertyPreview? _preview;
private TimeSpan _time;
private bool _updating;
@@ -35,7 +33,6 @@ public abstract class PropertyInputViewModel : PropertyInputViewModel
PropertyInputService = propertyInputService;
_inputValue = default!;
- _dragStartValue = default!;
this.WhenActivated(d =>
{
@@ -55,8 +52,6 @@ public abstract class PropertyInputViewModel : PropertyInputViewModel
.Subscribe(_ => UpdateDataBinding())
.DisposeWith(d);
});
-
- ValidationContext.ValidationStatusChange.Subscribe(s => Console.WriteLine(s));
}
///
@@ -80,17 +75,13 @@ public abstract class PropertyInputViewModel : PropertyInputViewModel
public IPropertyInputService PropertyInputService { get; }
///
- /// Gets or sets a boolean indicating whether the input is currently being dragged
+ /// Gets or boolean indicating whether the current input is being previewed, the value won't be applied until
///
/// Only applicable when using something like a , see
- /// and
+ /// and
///
///
- public bool InputDragging
- {
- get => _inputDragging;
- private set => this.RaiseAndSetIfChanged(ref _inputDragging, value);
- }
+ public bool IsPreviewing => _preview != null;
///
/// Gets or sets the input value
@@ -119,27 +110,37 @@ public abstract class PropertyInputViewModel : PropertyInputViewModel
internal override object InternalGuard { get; } = new();
///
- /// Called by the view input drag has started
- ///
- /// To use, add the following to DraggableFloat in your xaml: DragStarted="{s:Action InputDragStarted}"
- ///
+ /// Starts the preview of the current property, allowing updates without causing real changes to the property.
///
- public void InputDragStarted(object sender, EventArgs e)
+ public void StartPreview()
{
- InputDragging = true;
- _dragStartValue = GetDragStartValue();
+ _preview?.DiscardPreview();
+ _preview = new LayerPropertyPreview(LayerProperty, _time);
}
///
- /// Called by the view when input drag has ended
- ///
- /// To use, add the following to DraggableFloat in your xaml: DragEnded="{s:Action InputDragEnded}"
- ///
+ /// Applies the current preview to the property.
///
- public void InputDragEnded(object sender, EventArgs e)
+ public void ApplyPreview()
{
- InputDragging = false;
- ProfileEditorService.ExecuteCommand(new UpdateLayerProperty(LayerProperty, _inputValue, _dragStartValue, _time));
+ if (_preview == null)
+ return;
+
+ if (_preview.DiscardPreview() && _preview.PreviewValue != null)
+ ProfileEditorService.ExecuteCommand(new UpdateLayerProperty(LayerProperty, _inputValue, _preview.PreviewValue, _time));
+ _preview = null;
+ }
+
+ ///
+ /// Discard the preview of the property.
+ ///
+ public void DiscardPreview()
+ {
+ if (_preview == null)
+ return;
+
+ _preview.DiscardPreview();
+ _preview = null;
}
///
@@ -157,37 +158,31 @@ public abstract class PropertyInputViewModel : PropertyInputViewModel
}
///
- /// Called when dragging starts to get the initial value before dragging begun
- ///
- /// The initial value before dragging begun
- protected virtual T? GetDragStartValue()
- {
- return InputValue;
- }
-
- ///
- /// Applies the input value to the layer property using an .
+ /// Applies the input value to the layer property or the currently active preview.
///
protected virtual void ApplyInputValue()
{
- if (_updating)
+ // Avoid reapplying the latest value by checking if we're currently updating
+ if (_updating || !ValidationContext.IsValid)
return;
- if (InputDragging)
- ProfileEditorService.ChangeTime(_time);
- else if (ValidationContext.IsValid)
+ if (_preview != null)
+ _preview.Preview(_inputValue);
+ else
ProfileEditorService.ExecuteCommand(new UpdateLayerProperty(LayerProperty, _inputValue, _time));
}
private void UpdateInputValue()
{
+ // Always run this on the UI thread to avoid race conditions with ApplyInputValue
Dispatcher.UIThread.Post(() =>
{
try
{
_updating = true;
+
// Avoid unnecessary UI updates and validator cycles
- if (_inputValue != null && _inputValue.Equals(LayerProperty.CurrentValue) || _inputValue == null && LayerProperty.CurrentValue == null)
+ if (Equals(_inputValue, LayerProperty.CurrentValue))
return;
// Override the input value
@@ -202,7 +197,6 @@ public abstract class PropertyInputViewModel : PropertyInputViewModel
_updating = false;
}
});
-
}
private void UpdateDataBinding()
diff --git a/src/Avalonia/Artemis.UI/DefaultTypes/PropertyInput/SKColorPropertyInputView.axaml b/src/Avalonia/Artemis.UI/DefaultTypes/PropertyInput/SKColorPropertyInputView.axaml
index 1d458cb89..0f271bc78 100644
--- a/src/Avalonia/Artemis.UI/DefaultTypes/PropertyInput/SKColorPropertyInputView.axaml
+++ b/src/Avalonia/Artemis.UI/DefaultTypes/PropertyInput/SKColorPropertyInputView.axaml
@@ -5,25 +5,56 @@
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:propertyInput="clr-namespace:Artemis.UI.DefaultTypes.PropertyInput"
- mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+ mc:Ignorable="d" d:DesignWidth="200" d:DesignHeight="450"
x:Class="Artemis.UI.DefaultTypes.PropertyInput.SKColorPropertyInputView"
x:DataType="propertyInput:SKColorPropertyInputViewModel">
+
+
+
+
+
-
+
-
+
+
+ ShowAcceptDismissButtons="False" />
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/DefaultTypes/PropertyInput/SKColorPropertyInputView.axaml.cs b/src/Avalonia/Artemis.UI/DefaultTypes/PropertyInput/SKColorPropertyInputView.axaml.cs
index 95c3e2618..13922a4fc 100644
--- a/src/Avalonia/Artemis.UI/DefaultTypes/PropertyInput/SKColorPropertyInputView.axaml.cs
+++ b/src/Avalonia/Artemis.UI/DefaultTypes/PropertyInput/SKColorPropertyInputView.axaml.cs
@@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls;
+using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
@@ -17,4 +18,4 @@ namespace Artemis.UI.DefaultTypes.PropertyInput
AvaloniaXamlLoader.Load(this);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarView.axaml b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarView.axaml
index be30ad2bd..f1ef33ff0 100644
--- a/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarView.axaml
+++ b/src/Avalonia/Artemis.UI/Screens/ProfileEditor/Panels/MenuBar/MenuBarView.axaml
@@ -3,8 +3,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
+ xmlns:menuBar="clr-namespace:Artemis.UI.Screens.ProfileEditor.MenuBar"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
- x:Class="Artemis.UI.Screens.ProfileEditor.MenuBar.MenuBarView">
+ x:Class="Artemis.UI.Screens.ProfileEditor.MenuBar.MenuBarView"
+ x:DataType="menuBar:MenuBarViewModel">