Adaption hints - Added single LED adaption hint

Adaption hints - Added more sections to keyboard section adaption hint
This commit is contained in:
Robert committed 2023-09-10 11:58:37 +02:00
1 parent ca9ce948c5
commit d96581f11c
21 files changed
+433 -62

No files matched your search

@@ -26,7 +26,7 @@
</Button>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" Spacing="5">
<shared:EnumComboBox Value="{CompiledBinding CategoryAdaptionHint.Category}" Width="130" Margin="0 0 10 0" />
<shared:EnumComboBox Value="{CompiledBinding CategoryAdaptionHint.Category}" Width="200" Margin="0 0 10 0" />
<TextBlock VerticalAlignment="Center">Skip</TextBlock>
<controls:NumberBox HorizontalAlignment="Stretch"
@@ -26,7 +26,7 @@
</Button>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" Spacing="5">
<shared:EnumComboBox Value="{CompiledBinding DeviceAdaptionHint.DeviceType}" Width="130" Margin="0 0 10 0" />
<shared:EnumComboBox Value="{CompiledBinding DeviceAdaptionHint.DeviceType}" Width="200" Margin="0 0 10 0" />
<TextBlock VerticalAlignment="Center">Skip</TextBlock>
<controls:NumberBox HorizontalAlignment="Stretch"
@@ -25,7 +25,7 @@
</Button>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" Spacing="5">
<shared:EnumComboBox Value="{CompiledBinding KeyboardSectionAdaptionHint.Section}" Width="130" Margin="0 0 10 0" />
<shared:EnumComboBox Value="{CompiledBinding KeyboardSectionAdaptionHint.Section}" Width="200" Margin="0 0 10 0" />
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,57 @@
<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:adaptionHints="clr-namespace:Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints.SingleLedAdaptionHintView"
x:DataType="adaptionHints:SingleLedAdaptionHintViewModel">
<Grid ColumnDefinitions="*,Auto" RowDefinitions="Auto,Auto">
<StackPanel Grid.ColumnSpan="2" Margin="0 0 0 5">
<TextBlock Classes="h5">Single LED hint</TextBlock>
<TextBlock Classes="subtitle">Applies the layer to a single LED of one or more devices</TextBlock>
</StackPanel>
<Button Grid.Row="0"
Grid.Column="1"
Classes="icon-button"
VerticalAlignment="Top"
HorizontalAlignment="Right"
ToolTip.Tip="Remove hint"
Command="{CompiledBinding Remove}">
<avalonia:MaterialIcon Kind="Delete" />
</Button>
<StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" Spacing="5">
<controls:FAComboBox Width="200"
Margin="0 0 10 0"
ItemsSource="{CompiledBinding AdaptionLeds}"
SelectedItem="{CompiledBinding SelectedLed}"
DisplayMemberBinding="{CompiledBinding Description}"
IsEditable="True"
IsTextSearchEnabled="True"></controls:FAComboBox>
<TextBlock VerticalAlignment="Center">Skip</TextBlock>
<controls:NumberBox HorizontalAlignment="Stretch"
Value="{CompiledBinding SingleLedAdaptionHint.Skip}"
Minimum="0" />
<TextBlock VerticalAlignment="Center">device(s)</TextBlock>
<TextBlock VerticalAlignment="Center">Take</TextBlock>
<controls:NumberBox IsEnabled="{CompiledBinding SingleLedAdaptionHint.LimitAmount}"
HorizontalAlignment="Stretch"
Value="{CompiledBinding SingleLedAdaptionHint.Amount}"
Minimum="1" />
<TextBlock VerticalAlignment="Center">device(s)</TextBlock>
</StackPanel>
<CheckBox Grid.Row="1"
Grid.Column="1"
Content="Take all devices"
VerticalAlignment="Center"
HorizontalAlignment="Right"
IsChecked="{CompiledBinding !SingleLedAdaptionHint.LimitAmount}" />
</Grid>
</UserControl>
@@ -0,0 +1,13 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
public partial class SingleLedAdaptionHintView : UserControl
{
public SingleLedAdaptionHintView()
{
InitializeComponent();
}
}
@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core;
using ReactiveUI;
using RGB.NET.Core;
namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
public class SingleLedAdaptionHintViewModel : AdaptionHintViewModelBase
{
private List<AdaptionLed> _adaptionLeds;
private AdaptionLed? _selectedLed;
public SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint) : base(layer, adaptionHint)
{
SingleLedAdaptionHint = adaptionHint;
this.WhenAnyValue(vm => vm.SelectedLed).WhereNotNull().Subscribe(l => SingleLedAdaptionHint.LedId = l.Value);
Task.Run(() =>
{
AdaptionLeds = Enum.GetValues<LedId>().Select(l => new AdaptionLed(l)).ToList();
SelectedLed = AdaptionLeds.FirstOrDefault(l => l.Value == adaptionHint.LedId);
});
}
public List<AdaptionLed> AdaptionLeds
{
get => _adaptionLeds;
set => RaiseAndSetIfChanged(ref _adaptionLeds, value);
}
public AdaptionLed? SelectedLed
{
get => _selectedLed;
set => RaiseAndSetIfChanged(ref _selectedLed, value);
}
public SingleLedAdaptionHint SingleLedAdaptionHint { get; }
}
public class AdaptionLed
{
public AdaptionLed(LedId led)
{
Value = led;
Description = led.ToString();
}
public LedId Value { get; }
public string Description { get; }
}
@@ -34,37 +34,34 @@
</TextBlock>
</Grid>
<Border Grid.Row="1" Classes="card" Margin="0 15">
<Panel>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden" IsVisible="{CompiledBinding AdaptionHints.Count}">
<ItemsControl ItemsSource="{CompiledBinding AdaptionHints}" Classes="adaption-hints">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Spacing="10" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Classes="card-condensed">
<ContentControl Content="{CompiledBinding}"></ContentControl>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<Panel Grid.Row="1" Classes="card" Margin="0 15">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden" IsVisible="{CompiledBinding AdaptionHints.Count}">
<ItemsControl ItemsSource="{CompiledBinding AdaptionHints}" Classes="adaption-hints">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Spacing="5" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Classes="card-condensed">
<ContentControl Content="{CompiledBinding}"></ContentControl>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<StackPanel IsVisible="{CompiledBinding !AdaptionHints.Count}" VerticalAlignment="Center" HorizontalAlignment="Center">
<avalonia:MaterialIcon Kind="AlertCircleOutline" HorizontalAlignment="Center" Width="48" Height="48" />
<TextBlock Classes="h4" TextAlignment="Center" TextWrapping="Wrap">
You haven't set up any adaption hints
</TextBlock>
<TextBlock Classes="subtitle" TextAlignment="Center" TextWrapping="Wrap">
Artemis will attempt to directly map the LEDs of this layer to different surfaces but results may vary.
</TextBlock>
</StackPanel>
</Panel>
</Border>
<StackPanel IsVisible="{CompiledBinding !AdaptionHints.Count}" VerticalAlignment="Center" HorizontalAlignment="Center">
<avalonia:MaterialIcon Kind="AlertCircleOutline" HorizontalAlignment="Center" Width="48" Height="48" />
<TextBlock Classes="h4" TextAlignment="Center" TextWrapping="Wrap">
You haven't set up any adaption hints
</TextBlock>
<TextBlock Classes="subtitle" TextAlignment="Center" TextWrapping="Wrap">
Artemis will attempt to directly map the LEDs of this layer to different surfaces but results may vary.
</TextBlock>
</StackPanel>
</Panel>
<Grid Grid.Row="2" ColumnDefinitions="*,Auto">
<Button Grid.Row="0" Grid.Column="0" Command="{CompiledBinding AutoDetermineHints}">Auto-determine hints</Button>
@@ -87,6 +84,11 @@
<avalonia:MaterialIcon Kind="Keyboard" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Single LED hint" Command="{CompiledBinding AddSingleLedHint}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="LedVariantOn" />
</MenuItem.Icon>
</MenuItem>
</MenuFlyout>
</DropDownButton.Flyout>
Add hint
@@ -66,6 +66,12 @@ public class LayerHintsDialogViewModel : DialogViewModelBase<bool>
{
Layer.Adapter.Add(new KeyboardSectionAdaptionHint());
}
public void AddSingleLedHint()
{
Layer.Adapter.Add(new SingleLedAdaptionHint());
}
public void RemoveAdaptionHint(IAdaptionHint hint)
{
@@ -79,6 +85,7 @@ public class LayerHintsDialogViewModel : DialogViewModelBase<bool>
CategoryAdaptionHint categoryAdaptionHint => _vmFactory.CategoryAdaptionHintViewModel(Layer, categoryAdaptionHint),
DeviceAdaptionHint deviceAdaptionHint => _vmFactory.DeviceAdaptionHintViewModel(Layer, deviceAdaptionHint),
KeyboardSectionAdaptionHint keyboardSectionAdaptionHint => _vmFactory.KeyboardSectionAdaptionHintViewModel(Layer, keyboardSectionAdaptionHint),
SingleLedAdaptionHint singleLedAdaptionHint => _vmFactory.SingleLedAdaptionHintViewModel(Layer, singleLedAdaptionHint),
_ => throw new ArgumentOutOfRangeException(nameof(hint))
};
}
@@ -22,7 +22,7 @@ public class FolderTreeItemViewModel : TreeItemViewModel
IProfileEditorService profileEditorService,
IRgbService rgbService,
IProfileEditorVmFactory profileEditorVmFactory)
: base(parent, folder, windowService, profileEditorService, profileEditorVmFactory)
: base(parent, folder, windowService, rgbService, profileEditorService, profileEditorVmFactory)
{
_rgbService = rgbService;
Folder = folder;
@@ -22,7 +22,7 @@ public class LayerTreeItemViewModel : TreeItemViewModel
IProfileEditorService profileEditorService,
IRgbService rgbService,
IProfileEditorVmFactory profileEditorVmFactory)
: base(parent, layer, windowService, profileEditorService, profileEditorVmFactory)
: base(parent, layer, windowService, rgbService, profileEditorService, profileEditorVmFactory)
{
_rgbService = rgbService;
Layer = layer;
@@ -119,6 +119,11 @@
<avalonia:MaterialIcon Kind="Magic" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Apply adaption hints" Command="{CompiledBinding ApplyAdaptionHints}">
<MenuItem.Icon>
<avalonia:MaterialIcon Kind="CogPlay" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="-" />
<MenuItem Header="Duplicate" Command="{CompiledBinding Duplicate}" InputGesture="Ctrl+D">
<MenuItem.Icon>
@@ -7,6 +7,7 @@ using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.DryIoc.Factories;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.ProfileEditor;
@@ -22,8 +23,8 @@ public class ProfileTreeViewModel : TreeItemViewModel
private ObservableAsPropertyHelper<bool>? _keyBindingsEnabled;
private TreeItemViewModel? _selectedChild;
public ProfileTreeViewModel(IWindowService windowService, IProfileEditorService profileEditorService, IProfileEditorVmFactory profileEditorVmFactory)
: base(null, null, windowService, profileEditorService, profileEditorVmFactory)
public ProfileTreeViewModel(IWindowService windowService, IRgbService rgbService, IProfileEditorService profileEditorService, IProfileEditorVmFactory profileEditorVmFactory)
: base(null, null, windowService, rgbService, profileEditorService, profileEditorVmFactory)
{
this.WhenActivated(d =>
{
@@ -5,8 +5,10 @@ using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.DryIoc.Factories;
using Artemis.UI.Extensions;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.ContentDialogs;
@@ -26,6 +28,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
{
private readonly IProfileEditorVmFactory _profileEditorVmFactory;
private readonly IWindowService _windowService;
private readonly IRgbService _rgbService;
protected readonly IProfileEditorService ProfileEditorService;
private bool _canPaste;
private RenderProfileElement? _currentProfileElement;
@@ -38,11 +41,13 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
protected TreeItemViewModel(TreeItemViewModel? parent,
ProfileElement? profileElement,
IWindowService windowService,
IRgbService rgbService,
IProfileEditorService profileEditorService,
IProfileEditorVmFactory profileEditorVmFactory)
{
ProfileEditorService = profileEditorService;
_windowService = windowService;
_rgbService = rgbService;
_profileEditorVmFactory = profileEditorVmFactory;
Parent = parent;
@@ -51,6 +56,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
AddLayer = ReactiveCommand.Create(ExecuteAddLayer);
AddFolder = ReactiveCommand.Create(ExecuteAddFolder);
OpenAdaptionHints = ReactiveCommand.CreateFromTask(ExecuteOpenAdaptionHints, this.WhenAnyValue(vm => vm.ProfileElement).Select(p => p is Layer));
ApplyAdaptionHints = ReactiveCommand.Create(ExecuteApplyAdaptionHints, this.WhenAnyValue(vm => vm.ProfileElement).Select(p => p is Layer));
Rename = ReactiveCommand.CreateFromTask(ExecuteRename);
Delete = ReactiveCommand.Create(ExecuteDelete);
Duplicate = ReactiveCommand.CreateFromTask(ExecuteDuplicate);
@@ -109,6 +115,7 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
public ReactiveCommand<Unit, Unit> AddLayer { get; }
public ReactiveCommand<Unit, Unit> AddFolder { get; }
public ReactiveCommand<Unit, Unit> OpenAdaptionHints { get; }
public ReactiveCommand<Unit, Unit> ApplyAdaptionHints { get; }
public ReactiveCommand<Unit, Unit> Rename { get; }
public ReactiveCommand<Unit, Unit> Duplicate { get; }
public ReactiveCommand<Unit, Unit> Copy { get; }
@@ -254,6 +261,14 @@ public abstract class TreeItemViewModel : ActivatableViewModelBase
await _windowService.ShowDialogAsync<LayerHintsDialogViewModel, bool>(layer);
await ProfileEditorService.SaveProfileAsync();
}
private void ExecuteApplyAdaptionHints()
{
if (ProfileElement is not Layer layer)
return;
ProfileEditorService.ExecuteCommand(new ApplyAdaptionHints(layer, _rgbService.EnabledDevices.ToList()));
}
private async void UpdateCanPaste(bool isFlyoutOpen)
{