mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 11:26:27 +00:00
Profile tree - Fixed dragging while renaming
Profile tree - Fixed dragging folders onto themselves Profile tree - Suspend keybinds while renaming Brushes - Added brush presets UI Numberbox - Removed double validation error
This commit is contained in:
1 parent
a23af68a12
commit
29ef160975
16 files changed
+211
-103
No files matched your search
@@ -6,6 +6,8 @@ using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Threading;
|
||||
using ReactiveUI;
|
||||
|
||||
@@ -23,6 +25,8 @@ public class PlaybackViewModel : ActivatableViewModelBase
|
||||
private bool _repeating;
|
||||
private bool _repeatSegment;
|
||||
private bool _repeatTimeline;
|
||||
private ReactiveCommand<Unit, Unit>? _togglePlay;
|
||||
private ReactiveCommand<Unit, Unit>? _playFromStart;
|
||||
|
||||
public PlaybackViewModel(IProfileEditorService profileEditorService, ISettingsService settingsService)
|
||||
{
|
||||
@@ -36,15 +40,15 @@ public class PlaybackViewModel : ActivatableViewModelBase
|
||||
_currentTime = _profileEditorService.Time.ToProperty(this, vm => vm.CurrentTime).DisposeWith(d);
|
||||
_formattedCurrentTime = _profileEditorService.Time.Select(t => $"{Math.Floor(t.TotalSeconds):00}.{t.Milliseconds:000}").ToProperty(this, vm => vm.FormattedCurrentTime).DisposeWith(d);
|
||||
_playing = _profileEditorService.Playing.ToProperty(this, vm => vm.Playing).DisposeWith(d);
|
||||
|
||||
_lastUpdate = DateTime.MinValue;
|
||||
DispatcherTimer updateTimer = new(TimeSpan.FromMilliseconds(60.0 / 1000), DispatcherPriority.Render, Update);
|
||||
updateTimer.Start();
|
||||
Disposable.Create(() => updateTimer.Stop()).DisposeWith(d);
|
||||
|
||||
PlayFromStart = ReactiveCommand.Create(ExecutePlayFromStart, _profileEditorService.SuspendedKeybindings.Select(s => !s)).DisposeWith(d);
|
||||
TogglePlay = ReactiveCommand.Create(ExecuteTogglePlay, _profileEditorService.SuspendedKeybindings.Select(s => !s)).DisposeWith(d);
|
||||
});
|
||||
|
||||
PlayFromStart = ReactiveCommand.Create(ExecutePlayFromStart);
|
||||
TogglePlay = ReactiveCommand.Create(ExecuteTogglePlay);
|
||||
|
||||
GoToStart = ReactiveCommand.Create(ExecuteGoToStart);
|
||||
GoToEnd = ReactiveCommand.Create(ExecuteGoToEnd);
|
||||
GoToPreviousFrame = ReactiveCommand.Create(ExecuteGoToPreviousFrame);
|
||||
@@ -73,9 +77,19 @@ public class PlaybackViewModel : ActivatableViewModelBase
|
||||
get => _repeatSegment;
|
||||
set => RaiseAndSetIfChanged(ref _repeatSegment, value);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit,Unit> PlayFromStart { get; }
|
||||
public ReactiveCommand<Unit,Unit> TogglePlay { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit>? PlayFromStart
|
||||
{
|
||||
get => _playFromStart;
|
||||
set => RaiseAndSetIfChanged(ref _playFromStart, value);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit, Unit>? TogglePlay
|
||||
{
|
||||
get => _togglePlay;
|
||||
set => RaiseAndSetIfChanged(ref _togglePlay, value);
|
||||
}
|
||||
|
||||
public ReactiveCommand<Unit,Unit> GoToStart { get; }
|
||||
public ReactiveCommand<Unit,Unit> GoToEnd { get; }
|
||||
public ReactiveCommand<Unit,Unit> GoToPreviousFrame { get; }
|
||||
|
||||
+2
-1
@@ -49,7 +49,8 @@ public class ProfileTreeViewDropHandler : DropHandlerBase
|
||||
IVisual? targetVisual = treeView.GetVisualAt(position).FindAncestorOfType<TreeViewItem>();
|
||||
if (sourceContext is not T sourceNode || targetContext is not ProfileTreeViewModel vm || targetVisual is not IControl {DataContext: T targetNode})
|
||||
return false;
|
||||
|
||||
if (bExecute && targetNode == sourceNode)
|
||||
return false;
|
||||
TreeItemViewModel? sourceParent = sourceNode.Parent;
|
||||
TreeItemViewModel? targetParent = targetNode.Parent;
|
||||
ObservableCollection<TreeItemViewModel> sourceNodes = sourceParent is { } ? sourceParent.Children : vm.Children;
|
||||
|
||||
@@ -140,11 +140,13 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
|
||||
ProfileEditorService.ExecuteCommand(new RenameProfileElement(ProfileElement, RenameValue));
|
||||
Renaming = false;
|
||||
ProfileEditorService.ChangeSuspendedKeybindings(false);
|
||||
}
|
||||
|
||||
public void CancelRename()
|
||||
{
|
||||
Renaming = false;
|
||||
ProfileEditorService.ChangeSuspendedKeybindings(false);
|
||||
}
|
||||
|
||||
public void InsertElement(TreeItemViewModel elementViewModel, int targetIndex)
|
||||
@@ -237,6 +239,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
|
||||
{
|
||||
Renaming = true;
|
||||
RenameValue = ProfileElement?.Name;
|
||||
ProfileEditorService.ChangeSuspendedKeybindings(true);
|
||||
}
|
||||
|
||||
private void ExecuteAddFolder()
|
||||
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
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:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
xmlns:dialogs="clr-namespace:Artemis.UI.Screens.ProfileEditor.Properties.Tree.Dialogs"
|
||||
xmlns:layerBrushes="clr-namespace:Artemis.Core.LayerBrushes;assembly=Artemis.Core"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Tree.Dialogs.LayerBrushPresetView"
|
||||
x:DataType="dialogs:LayerBrushPresetViewModel"
|
||||
Width="500">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<TextBox Name="SearchBox" Text="{CompiledBinding SearchText}" Margin="0 0 0 15" Watermark="Search" />
|
||||
<ListBox Name="EffectDescriptorsList"
|
||||
Grid.Row="1"
|
||||
Items="{CompiledBinding Presets}"
|
||||
IsVisible="{CompiledBinding Presets.Count}"
|
||||
Height="300">
|
||||
|
||||
<ListBox.DataTemplates>
|
||||
<DataTemplate DataType="{x:Type layerBrushes:ILayerBrushPreset}">
|
||||
<Grid RowDefinitions="Auto,*"
|
||||
ColumnDefinitions="Auto,Auto"
|
||||
Background="Transparent"
|
||||
PointerReleased="InputElement_OnPointerReleased"
|
||||
Margin="0 4"
|
||||
VerticalAlignment="Center">
|
||||
<shared:ArtemisIcon Grid.Column="0"
|
||||
Grid.RowSpan="2"
|
||||
Icon="{CompiledBinding Icon}"
|
||||
Width="24"
|
||||
Height="24"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0 0 15 0" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Grid.Row="0"
|
||||
Classes="BodyStrongTextBlockStyle"
|
||||
Text="{CompiledBinding Name}"
|
||||
VerticalAlignment="Bottom"
|
||||
Width="450"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock Grid.Column="1"
|
||||
Grid.Row="1"
|
||||
Foreground="{DynamicResource TextFillColorSecondary}"
|
||||
Text="{CompiledBinding Description}"
|
||||
VerticalAlignment="Top"
|
||||
Width="450"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.DataTemplates>
|
||||
</ListBox>
|
||||
<Grid Grid.Row="1" Height="300">
|
||||
<StackPanel VerticalAlignment="Center"
|
||||
Spacing="20"
|
||||
IsVisible="{CompiledBinding !Presets.Count}">
|
||||
<avalonia:MaterialIcon Kind="CloseCircle" Width="32" Height="32" />
|
||||
<TextBlock Classes="h5" TextAlignment="Center">None of the presets match your search</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree.Dialogs;
|
||||
|
||||
public partial class LayerBrushPresetView : ReactiveUserControl<LayerBrushPresetViewModel>
|
||||
{
|
||||
public LayerBrushPresetView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (sender is not IDataContextProvider {DataContext: ILayerBrushPreset preset} || ViewModel == null)
|
||||
return;
|
||||
|
||||
ViewModel?.SelectPreset(preset);
|
||||
}
|
||||
}
|
||||
+50
-3
@@ -1,14 +1,61 @@
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reactive.Linq;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.LayerBrushes;
|
||||
using Artemis.Core.LayerEffects;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor;
|
||||
using Artemis.UI.Shared.Services.ProfileEditor.Commands;
|
||||
using DynamicData;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Properties.Tree.Dialogs;
|
||||
|
||||
public class LayerBrushPresetViewModel : ContentDialogViewModelBase
|
||||
{
|
||||
private readonly BaseLayerBrush _layerBrush;
|
||||
private string? _searchText;
|
||||
|
||||
public LayerBrushPresetViewModel(BaseLayerBrush layerBrush)
|
||||
{
|
||||
LayerBrush = layerBrush;
|
||||
_layerBrush = layerBrush;
|
||||
|
||||
SourceList<ILayerBrushPreset> presetsSourceList = new();
|
||||
if (layerBrush.Presets != null)
|
||||
presetsSourceList.AddRange(layerBrush.Presets);
|
||||
IObservable<Func<ILayerBrushPreset, bool>> presetsFilter = this.WhenAnyValue(vm => vm.SearchText).Select(CreatePredicate);
|
||||
|
||||
presetsSourceList.Connect()
|
||||
.Filter(presetsFilter)
|
||||
.Bind(out ReadOnlyObservableCollection<ILayerBrushPreset> presets)
|
||||
.Subscribe();
|
||||
Presets = presets;
|
||||
}
|
||||
|
||||
public BaseLayerBrush LayerBrush { get; }
|
||||
public ReadOnlyObservableCollection<ILayerBrushPreset> Presets { get; }
|
||||
|
||||
public string? SearchText
|
||||
{
|
||||
get => _searchText;
|
||||
set => RaiseAndSetIfChanged(ref _searchText, value);
|
||||
}
|
||||
|
||||
public void SelectPreset(ILayerBrushPreset preset)
|
||||
{
|
||||
_layerBrush.BaseProperties?.ResetAllLayerProperties();
|
||||
preset.Apply();
|
||||
ContentDialog?.Hide();
|
||||
}
|
||||
|
||||
private Func<ILayerBrushPreset, bool> CreatePredicate(string? search)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(search))
|
||||
return _ => true;
|
||||
|
||||
search = search.Trim();
|
||||
return data => data.Name.Contains(search, StringComparison.InvariantCultureIgnoreCase) ||
|
||||
data.Description.Contains(search, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -9,7 +9,8 @@
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Windows.BrushConfigurationWindowView"
|
||||
Title="Artemis | Brush configuration"
|
||||
Width="{Binding Configuration.DialogWidth}"
|
||||
Height="{Binding Configuration.DialogHeight}">
|
||||
Height="{Binding Configuration.DialogHeight}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Panel>
|
||||
<ContentControl Content="{Binding ConfigurationViewModel}" />
|
||||
</Panel>
|
||||
|
||||
+2
-1
@@ -9,7 +9,8 @@
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Properties.Windows.EffectConfigurationWindowView"
|
||||
Title="Artemis | Effect configuration"
|
||||
Width="{Binding Configuration.DialogWidth}"
|
||||
Height="{Binding Configuration.DialogHeight}">
|
||||
Height="{Binding Configuration.DialogHeight}"
|
||||
WindowStartupLocation="CenterOwner">
|
||||
<Panel>
|
||||
<ContentControl Content="{Binding ConfigurationViewModel}" />
|
||||
</Panel>
|
||||
|
||||
Reference in new issue
Block a user