1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 13:28:33 +00:00

Merge pull request #815 from Artemis-RGB/development

Adaption hints - Added more hints and sections
This commit is contained in:
RobertBeekman 2023-09-10 12:00:15 +02:00 committed by GitHub
commit 888ed3743e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 433 additions and 62 deletions

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Artemis.Storage.Entities.Profile.AdaptionHints;
using RGB.NET.Core;
@ -15,7 +16,12 @@ public class KeyboardSectionAdaptionHint : CorePropertyChanged, IAdaptionHint
{
{KeyboardSection.MacroKeys, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_Programmable1 && l <= LedId.Keyboard_Programmable32).ToList()},
{KeyboardSection.LedStrips, Enum.GetValues<LedId>().Where(l => l >= LedId.LedStripe1 && l <= LedId.LedStripe128).ToList()},
{KeyboardSection.Extra, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_Custom1 && l <= LedId.Keyboard_Custom64).ToList()}
{KeyboardSection.Extra, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_Custom1 && l <= LedId.Keyboard_Custom64).ToList()},
{KeyboardSection.FunctionKeys, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_F1 && l <= LedId.Keyboard_F12).ToList()},
{KeyboardSection.NumberKeys, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_1 && l <= LedId.Keyboard_0).ToList()},
{KeyboardSection.NumPad, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_NumLock && l <= LedId.Keyboard_NumPeriodAndDelete).ToList()},
{KeyboardSection.ArrowKeys, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_PageDown && l <= LedId.Keyboard_ArrowRight).ToList()},
{KeyboardSection.MediaKeys, Enum.GetValues<LedId>().Where(l => l >= LedId.Keyboard_MediaMute && l <= LedId.Keyboard_MediaNextTrack).ToList()},
};
private KeyboardSection _section;
@ -46,6 +52,12 @@ public class KeyboardSectionAdaptionHint : CorePropertyChanged, IAdaptionHint
/// <inheritdoc />
public void Apply(Layer layer, List<ArtemisDevice> devices)
{
if (Section == KeyboardSection.Movement)
{
ApplyMovement(layer, devices);
return;
}
// Only keyboards should have the LEDs we care about
foreach (ArtemisDevice keyboard in devices.Where(d => d.DeviceType == RGBDeviceType.Keyboard))
{
@ -54,6 +66,26 @@ public class KeyboardSectionAdaptionHint : CorePropertyChanged, IAdaptionHint
}
}
private void ApplyMovement(Layer layer, List<ArtemisDevice> devices)
{
// Only keyboards should have the LEDs we care about
foreach (ArtemisDevice keyboard in devices.Where(d => d.DeviceType == RGBDeviceType.Keyboard))
{
ArtemisLed? qLed = keyboard.Leds.FirstOrDefault(l => l.RgbLed.Id == LedId.Keyboard_Q);
ArtemisLed? aLed = keyboard.Leds.FirstOrDefault(l => l.RgbLed.Id == LedId.Keyboard_A);
if (qLed == null || aLed == null)
continue;
// AZERTY keyboards will have their A above their Q
bool isAzerty = aLed.Rectangle.MidX < qLed.Rectangle.MidX;
if (isAzerty)
layer.AddLeds(keyboard.Leds.Where(l => l.RgbLed.Id is LedId.Keyboard_Z or LedId.Keyboard_Q or LedId.Keyboard_S or LedId.Keyboard_D));
else
layer.AddLeds(keyboard.Leds.Where(l => l.RgbLed.Id is LedId.Keyboard_W or LedId.Keyboard_A or LedId.Keyboard_S or LedId.Keyboard_D));
}
}
/// <inheritdoc />
public IAdaptionHintEntity GetEntry()
{
@ -77,15 +109,45 @@ public enum KeyboardSection
/// <summary>
/// A region containing the macro keys of a keyboard
/// </summary>
MacroKeys,
[Description("Macro Keys")] MacroKeys,
/// <summary>
/// A region containing the LED strips of a keyboard
/// </summary>
LedStrips,
[Description("LED Strips")] LedStrips,
/// <summary>
/// A region containing extra non-standard LEDs of a keyboard
/// A region containing the extra non-standard LEDs of a keyboard
/// </summary>
Extra
[Description("Extra LEDs")] Extra,
/// <summary>
/// A region containing the movement keys of a keyboard (WASD for QWERTY and ZQSD for AZERTY)
/// </summary>
[Description("Movement (WASD/ZQSD)")] Movement,
/// <summary>
/// A region containing the F-keys of a keyboard
/// </summary>
[Description("F-keys")] FunctionKeys,
/// <summary>
/// A region containing the numeric keys of a keyboard
/// </summary>
[Description("Numeric keys")] NumberKeys,
/// <summary>
/// A region containing the Numpad of a keyboard
/// </summary>
[Description("Numpad")] NumPad,
/// <summary>
/// A region containing the arrow keys of a keyboard
/// </summary>
[Description("Arrow keys")] ArrowKeys,
/// <summary>
/// A region containing the media keys of a keyboard
/// </summary>
[Description("Media keys")] MediaKeys
}

View File

@ -0,0 +1,102 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Storage.Entities.Profile.AdaptionHints;
using RGB.NET.Core;
namespace Artemis.Core;
/// <summary>
/// Represents a hint that adapts layers to a single LED of one or more devices
/// </summary>
public class SingleLedAdaptionHint : CorePropertyChanged, IAdaptionHint
{
private LedId _ledId;
private int _skip;
private bool _limitAmount;
private int _amount;
/// <summary>
/// Creates a new instance of the <see cref="SingleLedAdaptionHint" /> class
/// </summary>
public SingleLedAdaptionHint()
{
}
internal SingleLedAdaptionHint(SingleLedAdaptionHintEntity entity)
{
LedId = (LedId) entity.LedId;
Skip = entity.Skip;
LimitAmount = entity.LimitAmount;
Amount = entity.Amount;
}
/// <summary>
/// Gets or sets the LED ID to apply to.
/// </summary>
public LedId LedId
{
get => _ledId;
set => SetAndNotify(ref _ledId, value);
}
/// <summary>
/// Gets or sets the amount of devices to skip
/// </summary>
public int Skip
{
get => _skip;
set => SetAndNotify(ref _skip, value);
}
/// <summary>
/// Gets or sets a boolean indicating whether a limited amount of devices should be used
/// </summary>
public bool LimitAmount
{
get => _limitAmount;
set => SetAndNotify(ref _limitAmount, value);
}
/// <summary>
/// Gets or sets the amount of devices to limit to if <see cref="LimitAmount" /> is <see langword="true" />
/// </summary>
public int Amount
{
get => _amount;
set => SetAndNotify(ref _amount, value);
}
#region Implementation of IAdaptionHint
/// <inheritdoc />
public void Apply(Layer layer, List<ArtemisDevice> devices)
{
IEnumerable<ArtemisDevice> matches = devices
.Where(d => d.Leds.Any(l => l.RgbLed.Id == LedId))
.OrderBy(d => d.Rectangle.Top)
.ThenBy(d => d.Rectangle.Left)
.Skip(Skip);
if (LimitAmount)
matches = matches.Take(Amount);
foreach (ArtemisDevice artemisDevice in matches)
{
ArtemisLed led = artemisDevice.Leds.First(l => l.RgbLed.Id == LedId);
layer.AddLed(led);
}
}
/// <inheritdoc />
public IAdaptionHintEntity GetEntry()
{
return new SingleLedAdaptionHintEntity {Amount = Amount, LimitAmount = LimitAmount, Skip = Skip, LedId = (int) LedId};
}
/// <inheritdoc />
public override string ToString()
{
return $"Single LED adaption - {nameof(LedId)}: {LedId}, {nameof(Skip)}: {Skip}, {nameof(LimitAmount)}: {LimitAmount}, {nameof(Amount)}: {Amount}";
}
#endregion
}

View File

@ -111,6 +111,15 @@ public class LayerAdapter : IStorageModel
newHints.Add(hint);
}
}
// A single LED assignment is turned into a hint for one matching LED ID on the same device type
if (Layer.Leds.Count == 1)
{
ArtemisLed led = Layer.Leds.Single();
SingleLedAdaptionHint hint = new() {LedId = led.RgbLed.Id, Amount = 1, LimitAmount = true};
Add(hint);
newHints.Add(hint);
}
}
return newHints;
@ -184,6 +193,9 @@ public class LayerAdapter : IStorageModel
case KeyboardSectionAdaptionHintEntity entity:
Add(new KeyboardSectionAdaptionHint(entity));
break;
case SingleLedAdaptionHintEntity entity:
Add(new SingleLedAdaptionHint(entity));
break;
}
}
}

View File

@ -0,0 +1,10 @@
namespace Artemis.Storage.Entities.Profile.AdaptionHints;
public class SingleLedAdaptionHintEntity : IAdaptionHintEntity
{
public int LedId { get; set; }
public bool LimitAmount { get; set; }
public int Skip { get; set; }
public int Amount { get; set; }
}

View File

@ -8,7 +8,7 @@
<ComboBox x:Name="ChildEnumComboBox" HorizontalAlignment="Stretch">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:EnumComboBoxItem">
<TextBlock Text="{CompiledBinding Value}" />
<TextBlock Text="{CompiledBinding Description}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

View File

@ -0,0 +1,45 @@
using System.Collections.Generic;
using Artemis.Core;
namespace Artemis.UI.Shared.Services.ProfileEditor.Commands;
/// <summary>
/// Represents a profile editor command that can be used to apply adaption hints to a layer.
/// </summary>
public class ApplyAdaptionHints : IProfileEditorCommand
{
private readonly Layer _layer;
private readonly List<ArtemisDevice> _devices;
private readonly List<ArtemisLed> _originalLeds;
/// <summary>
/// Creates a new instance of the <see cref="ApplyAdaptionHints" /> class.
/// </summary>
public ApplyAdaptionHints(Layer layer, List<ArtemisDevice> devices)
{
_layer = layer;
_devices = devices;
_originalLeds = new List<ArtemisLed>(_layer.Leds);
}
#region Implementation of IProfileEditorCommand
/// <inheritdoc />
public string DisplayName => "Apply adaption hints";
/// <inheritdoc />
public void Execute()
{
_layer.ClearLeds();
_layer.Adapter.Adapt(_devices);
}
/// <inheritdoc />
public void Undo()
{
_layer.ClearLeds();
_layer.AddLeds(_originalLeds);
}
#endregion
}

View File

@ -51,23 +51,4 @@
<ItemGroup>
<AvaloniaResource Include="Assets\**" />
</ItemGroup>
<ItemGroup>
<Compile Update="Screens\Workshop\Entries\Tabs\ProfileListView.axaml.cs">
<DependentUpon>ProfileListView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Screens\Workshop\Entries\Tabs\LayoutListView.axaml.cs">
<DependentUpon>LayoutListView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Screens\Workshop\Library\SubmissionDetailView.axaml.cs">
<DependentUpon>SubmissionsDetailView.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<UpToDateCheckInput Remove="Screens\Workshop\Entries\Windows\MarkdownPreviewView.axaml" />
</ItemGroup>
</Project>

View File

@ -430,6 +430,7 @@ public interface ILayerHintVmFactory : IVmFactory
CategoryAdaptionHintViewModel CategoryAdaptionHintViewModel(Layer layer, CategoryAdaptionHint adaptionHint);
DeviceAdaptionHintViewModel DeviceAdaptionHintViewModel(Layer layer, DeviceAdaptionHint adaptionHint);
KeyboardSectionAdaptionHintViewModel KeyboardSectionAdaptionHintViewModel(Layer layer, KeyboardSectionAdaptionHint adaptionHint);
SingleLedAdaptionHintViewModel SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint);
}
public class LayerHintVmFactory : ILayerHintVmFactory
{
@ -454,6 +455,11 @@ public class LayerHintVmFactory : ILayerHintVmFactory
{
return _container.Resolve<KeyboardSectionAdaptionHintViewModel>(new object[] { layer, adaptionHint });
}
public SingleLedAdaptionHintViewModel SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint)
{
return _container.Resolve<SingleLedAdaptionHintViewModel>(new object[] { layer, adaptionHint });
}
}
public interface IScriptVmFactory : IVmFactory

View File

@ -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"

View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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();
}
}

View File

@ -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; }
}

View File

@ -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

View File

@ -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))
};
}

View File

@ -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;

View File

@ -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;

View File

@ -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>

View File

@ -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 =>
{

View File

@ -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)
{