diff --git a/src/.idea/.idea.Artemis/.idea/avalonia.xml b/src/.idea/.idea.Artemis/.idea/avalonia.xml
index 07f14ce84..8021c13f5 100644
--- a/src/.idea/.idea.Artemis/.idea/avalonia.xml
+++ b/src/.idea/.idea.Artemis/.idea/avalonia.xml
@@ -14,6 +14,7 @@
+
@@ -27,7 +28,12 @@
+
+
+
+
+
@@ -40,6 +46,7 @@
+
@@ -47,6 +54,7 @@
+
diff --git a/src/Artemis.Core/Events/Profiles/LayerAdapterHintEventArgs.cs b/src/Artemis.Core/Events/Profiles/LayerAdapterHintEventArgs.cs
new file mode 100644
index 000000000..5d3600ba4
--- /dev/null
+++ b/src/Artemis.Core/Events/Profiles/LayerAdapterHintEventArgs.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Artemis.Core;
+
+///
+/// Provides data for layer adapter hint events.
+///
+public class LayerAdapterHintEventArgs : EventArgs
+{
+ internal LayerAdapterHintEventArgs(IAdaptionHint adaptionHint)
+ {
+ AdaptionHint = adaptionHint;
+ }
+
+ ///
+ /// Gets the layer adaption hint this event is related to
+ ///
+ public IAdaptionHint AdaptionHint { get; }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/Profile/AdaptionHints/CategoryAdaptionHint.cs b/src/Artemis.Core/Models/Profile/AdaptionHints/CategoryAdaptionHint.cs
index 824b27963..18e87f574 100644
--- a/src/Artemis.Core/Models/Profile/AdaptionHints/CategoryAdaptionHint.cs
+++ b/src/Artemis.Core/Models/Profile/AdaptionHints/CategoryAdaptionHint.cs
@@ -7,8 +7,13 @@ namespace Artemis.Core
///
/// Represents a hint that adapts layers to a certain category of devices
///
- public class CategoryAdaptionHint : IAdaptionHint
+ public class CategoryAdaptionHint : CorePropertyChanged, IAdaptionHint
{
+ private DeviceCategory _category;
+ private int _skip;
+ private bool _limitAmount;
+ private int _amount;
+
///
/// Creates a new instance of the class
///
@@ -27,22 +32,38 @@ namespace Artemis.Core
///
/// Gets or sets the category of devices LEDs will be applied to
///
- public DeviceCategory Category { get; set; }
+ public DeviceCategory Category
+ {
+ get => _category;
+ set => SetAndNotify(ref _category, value);
+ }
///
/// Gets or sets the amount of devices to skip
///
- public int Skip { get; set; }
+ public int Skip
+ {
+ get => _skip;
+ set => SetAndNotify(ref _skip, value);
+ }
///
/// Gets or sets a boolean indicating whether a limited amount of devices should be used
///
- public bool LimitAmount { get; set; }
+ public bool LimitAmount
+ {
+ get => _limitAmount;
+ set => SetAndNotify(ref _limitAmount, value);
+ }
///
/// Gets or sets the amount of devices to limit to if is
///
- public int Amount { get; set; }
+ public int Amount
+ {
+ get => _amount;
+ set => SetAndNotify(ref _amount, value);
+ }
///
public override string ToString()
diff --git a/src/Artemis.Core/Models/Profile/AdaptionHints/DeviceAdaptionHint.cs b/src/Artemis.Core/Models/Profile/AdaptionHints/DeviceAdaptionHint.cs
index 28058f641..62ed05b85 100644
--- a/src/Artemis.Core/Models/Profile/AdaptionHints/DeviceAdaptionHint.cs
+++ b/src/Artemis.Core/Models/Profile/AdaptionHints/DeviceAdaptionHint.cs
@@ -8,8 +8,13 @@ namespace Artemis.Core
///
/// Represents a hint that adapts layers to a certain type of devices
///
- public class DeviceAdaptionHint : IAdaptionHint
+ public class DeviceAdaptionHint : CorePropertyChanged, IAdaptionHint
{
+ private RGBDeviceType _deviceType;
+ private int _skip;
+ private bool _limitAmount;
+ private int _amount;
+
///
/// Creates a new instance of the class
///
@@ -28,22 +33,38 @@ namespace Artemis.Core
///
/// Gets or sets the type of devices LEDs will be applied to
///
- public RGBDeviceType DeviceType { get; set; }
+ public RGBDeviceType DeviceType
+ {
+ get => _deviceType;
+ set => SetAndNotify(ref _deviceType, value);
+ }
///
/// Gets or sets the amount of devices to skip
///
- public int Skip { get; set; }
+ public int Skip
+ {
+ get => _skip;
+ set => SetAndNotify(ref _skip, value);
+ }
///
/// Gets or sets a boolean indicating whether a limited amount of devices should be used
///
- public bool LimitAmount { get; set; }
+ public bool LimitAmount
+ {
+ get => _limitAmount;
+ set => SetAndNotify(ref _limitAmount, value);
+ }
///
/// Gets or sets the amount of devices to limit to if is
///
- public int Amount { get; set; }
+ public int Amount
+ {
+ get => _amount;
+ set => SetAndNotify(ref _amount, value);
+ }
#region Implementation of IAdaptionHint
diff --git a/src/Artemis.Core/Models/Profile/AdaptionHints/KeyboardSectionAdaptionHint.cs b/src/Artemis.Core/Models/Profile/AdaptionHints/KeyboardSectionAdaptionHint.cs
index 0177a8938..cf61108c4 100644
--- a/src/Artemis.Core/Models/Profile/AdaptionHints/KeyboardSectionAdaptionHint.cs
+++ b/src/Artemis.Core/Models/Profile/AdaptionHints/KeyboardSectionAdaptionHint.cs
@@ -9,7 +9,7 @@ namespace Artemis.Core
///
/// Represents a hint that adapts layers to a certain region of keyboards
///
- public class KeyboardSectionAdaptionHint : IAdaptionHint
+ public class KeyboardSectionAdaptionHint : CorePropertyChanged, IAdaptionHint
{
private static readonly Dictionary> RegionLedIds = new()
{
@@ -18,6 +18,8 @@ namespace Artemis.Core
{KeyboardSection.Extra, Enum.GetValues().Where(l => l >= LedId.Keyboard_Custom1 && l <= LedId.Keyboard_Custom64).ToList()}
};
+ private KeyboardSection _section;
+
///
/// Creates a new instance of the class
///
@@ -33,7 +35,11 @@ namespace Artemis.Core
///
/// Gets or sets the section this hint will apply LEDs to
///
- public KeyboardSection Section { get; set; }
+ public KeyboardSection Section
+ {
+ get => _section;
+ set => SetAndNotify(ref _section, value);
+ }
#region Implementation of IAdaptionHint
diff --git a/src/Artemis.Core/Models/Profile/LayerAdapter.cs b/src/Artemis.Core/Models/Profile/LayerAdapter.cs
index b60d901f9..aa8ceeb5c 100644
--- a/src/Artemis.Core/Models/Profile/LayerAdapter.cs
+++ b/src/Artemis.Core/Models/Profile/LayerAdapter.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Linq;
using Artemis.Storage.Entities.Profile;
using Artemis.Storage.Entities.Profile.AdaptionHints;
@@ -12,10 +13,13 @@ namespace Artemis.Core
///
public class LayerAdapter : IStorageModel
{
+ private readonly List _adaptionHints;
+
internal LayerAdapter(Layer layer)
{
+ _adaptionHints = new List();
Layer = layer;
- AdaptionHints = new List();
+ AdaptionHints = new ReadOnlyCollection(_adaptionHints);
}
///
@@ -26,7 +30,7 @@ namespace Artemis.Core
///
/// Gets or sets a list containing the adaption hints used by this adapter
///
- public List AdaptionHints { get; set; }
+ public ReadOnlyCollection AdaptionHints { get; set; }
///
/// Modifies the layer, adapting it to the provided
@@ -73,7 +77,7 @@ namespace Artemis.Core
if (devices.All(DoesLayerCoverDevice))
{
DeviceAdaptionHint hint = new() {DeviceType = RGBDeviceType.All};
- AdaptionHints.Add(hint);
+ Add(hint);
newHints.Add(hint);
}
else
@@ -88,7 +92,7 @@ namespace Artemis.Core
if (DoesLayerCoverDevice(device))
{
DeviceAdaptionHint hint = new() {DeviceType = device.DeviceType};
- AdaptionHints.Add(hint);
+ Add(hint);
newHints.Add(hint);
}
}
@@ -103,7 +107,7 @@ namespace Artemis.Core
if (categoryDevices.Any() && categoryDevices.All(DoesLayerCoverDevice))
{
CategoryAdaptionHint hint = new() {Category = deviceCategory};
- AdaptionHints.Add(hint);
+ Add(hint);
newHints.Add(hint);
}
}
@@ -117,25 +121,57 @@ namespace Artemis.Core
return device.Leds.All(l => Layer.Leds.Contains(l));
}
+ ///
+ /// Adds an adaption hint to the adapter.
+ ///
+ /// The adaption hint to add.
+ public void Add(IAdaptionHint adaptionHint)
+ {
+ if (_adaptionHints.Contains(adaptionHint))
+ return;
+
+ _adaptionHints.Add(adaptionHint);
+ AdapterHintAdded?.Invoke(this, new LayerAdapterHintEventArgs(adaptionHint));
+ }
+
+ ///
+ /// Removes the first occurrence of a specific adaption hint from the adapter.
+ ///
+ /// The adaption hint to remove.
+ public void Remove(IAdaptionHint adaptionHint)
+ {
+ if (_adaptionHints.Remove(adaptionHint))
+ AdapterHintRemoved?.Invoke(this, new LayerAdapterHintEventArgs(adaptionHint));
+ }
+
+ ///
+ /// Removes all adaption hints from the adapter.
+ ///
+ public void Clear()
+ {
+ while (_adaptionHints.Any())
+ Remove(_adaptionHints.First());
+ }
+
#region Implementation of IStorageModel
///
public void Load()
{
- AdaptionHints.Clear();
+ _adaptionHints.Clear();
// Kind of meh.
// This leaves the adapter responsible for finding the right hint for the right entity, but it's gotta be done somewhere..
foreach (IAdaptionHintEntity hintEntity in Layer.LayerEntity.AdaptionHints)
switch (hintEntity)
{
case DeviceAdaptionHintEntity entity:
- AdaptionHints.Add(new DeviceAdaptionHint(entity));
+ Add(new DeviceAdaptionHint(entity));
break;
case CategoryAdaptionHintEntity entity:
- AdaptionHints.Add(new CategoryAdaptionHint(entity));
+ Add(new CategoryAdaptionHint(entity));
break;
case KeyboardSectionAdaptionHintEntity entity:
- AdaptionHints.Add(new KeyboardSectionAdaptionHint(entity));
+ Add(new KeyboardSectionAdaptionHint(entity));
break;
}
}
@@ -149,5 +185,15 @@ namespace Artemis.Core
}
#endregion
+
+ ///
+ /// Occurs whenever a new adapter hint is added to the adapter.
+ ///
+ public event EventHandler? AdapterHintAdded;
+
+ ///
+ /// Occurs whenever an adapter hint is removed from the adapter.
+ ///
+ public event EventHandler? AdapterHintRemoved;
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Controls/EnumComboBox.axaml b/src/Artemis.UI.Shared/Controls/EnumComboBox.axaml
index 36ada5068..59195d73a 100644
--- a/src/Artemis.UI.Shared/Controls/EnumComboBox.axaml
+++ b/src/Artemis.UI.Shared/Controls/EnumComboBox.axaml
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
index d96befb87..05e6d08e2 100644
--- a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
+++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
@@ -7,6 +7,7 @@ using Artemis.UI.Screens.Plugins;
using Artemis.UI.Screens.ProfileEditor;
using Artemis.UI.Screens.ProfileEditor.DisplayCondition.ConditionTypes;
using Artemis.UI.Screens.ProfileEditor.ProfileTree;
+using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
using Artemis.UI.Screens.ProfileEditor.Properties;
using Artemis.UI.Screens.ProfileEditor.Properties.DataBinding;
using Artemis.UI.Screens.ProfileEditor.Properties.Timeline;
@@ -114,4 +115,11 @@ public interface IConditionVmFactory : IVmFactory
PlayOnceConditionViewModel PlayOnceConditionViewModel(PlayOnceCondition playOnceCondition);
StaticConditionViewModel StaticConditionViewModel(StaticCondition staticCondition);
EventConditionViewModel EventConditionViewModel(EventCondition eventCondition);
+}
+
+public interface ILayerHintVmFactory : IVmFactory
+{
+ CategoryAdaptionHintViewModel CategoryAdaptionHintViewModel(CategoryAdaptionHint adaptionHint);
+ DeviceAdaptionHintViewModel DeviceAdaptionHintViewModel(DeviceAdaptionHint adaptionHint);
+ KeyboardSectionAdaptionHintViewModel KeyboardSectionAdaptionHintViewModel(KeyboardSectionAdaptionHint adaptionHint);
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/AdaptionHintViewModelBase.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/AdaptionHintViewModelBase.cs
new file mode 100644
index 000000000..96495d5c8
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/AdaptionHintViewModelBase.cs
@@ -0,0 +1,22 @@
+using System.Reactive;
+using Artemis.Core;
+using Artemis.UI.Shared;
+using ReactiveUI;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
+
+public abstract class AdaptionHintViewModelBase : ViewModelBase
+{
+ protected AdaptionHintViewModelBase(IAdaptionHint adaptionHint)
+ {
+ AdaptionHint = adaptionHint;
+ Remove = ReactiveCommand.Create(ExecuteRemove);
+ }
+
+ public ReactiveCommand Remove { get; }
+ public IAdaptionHint AdaptionHint { get; }
+
+ private void ExecuteRemove()
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintView.axaml
new file mode 100644
index 000000000..6fc3e55ba
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintView.axaml
@@ -0,0 +1,52 @@
+
+
+
+ Category hint
+ Applies the layer to devices of a certain category
+
+
+
+
+
+
+
+ Skip
+
+ device(s)
+
+ Take
+
+ device(s)
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintView.axaml.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintView.axaml.cs
new file mode 100644
index 000000000..41b29c88a
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintView.axaml.cs
@@ -0,0 +1,18 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
+
+public partial class CategoryAdaptionHintView : UserControl
+{
+ public CategoryAdaptionHintView()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintViewModel.cs
new file mode 100644
index 000000000..7d6c3cc11
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/CategoryAdaptionHintViewModel.cs
@@ -0,0 +1,13 @@
+using Artemis.Core;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
+
+public class CategoryAdaptionHintViewModel : AdaptionHintViewModelBase
+{
+ public CategoryAdaptionHintViewModel(CategoryAdaptionHint adaptionHint) : base(adaptionHint)
+ {
+ CategoryAdaptionHint = adaptionHint;
+ }
+
+ public CategoryAdaptionHint CategoryAdaptionHint { get; }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintView.axaml
new file mode 100644
index 000000000..0a21cc216
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintView.axaml
@@ -0,0 +1,52 @@
+
+
+
+ Device type hint
+ Applies the layer to devices of a certain type
+
+
+
+
+
+
+
+ Skip
+
+ device(s)
+
+ Take
+
+ device(s)
+
+
+
+
+
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintView.axaml.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintView.axaml.cs
new file mode 100644
index 000000000..af6f2ef81
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintView.axaml.cs
@@ -0,0 +1,18 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
+
+public partial class DeviceAdaptionHintView : UserControl
+{
+ public DeviceAdaptionHintView()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintViewModel.cs
new file mode 100644
index 000000000..723554871
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/DeviceAdaptionHintViewModel.cs
@@ -0,0 +1,13 @@
+using Artemis.Core;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
+
+public class DeviceAdaptionHintViewModel : AdaptionHintViewModelBase
+{
+ public DeviceAdaptionHintViewModel(DeviceAdaptionHint adaptionHint) : base(adaptionHint)
+ {
+ DeviceAdaptionHint = adaptionHint;
+ }
+
+ public DeviceAdaptionHint DeviceAdaptionHint { get; }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintView.axaml
new file mode 100644
index 000000000..aeb3353dc
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintView.axaml
@@ -0,0 +1,32 @@
+
+
+
+ Keyboard section hint
+ Applies the layer to a section of all keyboards
+
+
+
+
+
+
+
+
+
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintView.axaml.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintView.axaml.cs
new file mode 100644
index 000000000..7acec3936
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintView.axaml.cs
@@ -0,0 +1,18 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
+
+public partial class KeyboardSectionAdaptionHintView : UserControl
+{
+ public KeyboardSectionAdaptionHintView()
+ {
+ InitializeComponent();
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintViewModel.cs
new file mode 100644
index 000000000..3d4449deb
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/AdaptionHints/KeyboardSectionAdaptionHintViewModel.cs
@@ -0,0 +1,13 @@
+using Artemis.Core;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
+
+public class KeyboardSectionAdaptionHintViewModel : AdaptionHintViewModelBase
+{
+ public KeyboardSectionAdaptionHintViewModel(KeyboardSectionAdaptionHint adaptionHint) : base(adaptionHint)
+ {
+ KeyboardSectionAdaptionHint = adaptionHint;
+ }
+
+ public KeyboardSectionAdaptionHint KeyboardSectionAdaptionHint { get; }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogView.axaml
new file mode 100644
index 000000000..75b799e45
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogView.axaml
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+ Learn more about adaption hints
+
+
+
+ Add hints below to help decide where to place this layer when the profile is imported.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Add hint
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogView.axaml.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogView.axaml.cs
new file mode 100644
index 000000000..2a4585ba1
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogView.axaml.cs
@@ -0,0 +1,22 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using FluentAvalonia.UI.Controls;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
+
+public partial class LayerHintsDialogView : ReactiveCoreWindow
+{
+ public LayerHintsDialogView()
+ {
+ InitializeComponent();
+#if DEBUG
+ this.AttachDevTools();
+#endif
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogViewModel.cs
new file mode 100644
index 000000000..ae4786351
--- /dev/null
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/Dialogs/LayerHintsDialogViewModel.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive.Linq;
+using Artemis.Core;
+using Artemis.Core.Services;
+using Artemis.UI.Ninject.Factories;
+using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
+using Artemis.UI.Shared;
+using Avalonia.Controls.Mixins;
+using DynamicData;
+using ReactiveUI;
+
+namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
+
+public class LayerHintsDialogViewModel : DialogViewModelBase
+{
+ private readonly IRgbService _rgbService;
+ private readonly ILayerHintVmFactory _vmFactory;
+
+ public LayerHintsDialogViewModel(Layer layer, IRgbService rgbService, ILayerHintVmFactory vmFactory)
+ {
+ _rgbService = rgbService;
+ _vmFactory = vmFactory;
+
+ Layer = layer;
+ AdaptionHints = new ObservableCollection();
+
+ this.WhenActivated(d =>
+ {
+ Observable.FromEventPattern(x => layer.Adapter.AdapterHintAdded += x, x => layer.Adapter.AdapterHintAdded -= x)
+ .Subscribe(c => AdaptionHints.Add(CreateHintViewModel(c.EventArgs.AdaptionHint)))
+ .DisposeWith(d);
+ Observable.FromEventPattern(x => layer.Adapter.AdapterHintRemoved += x, x => layer.Adapter.AdapterHintRemoved -= x)
+ .Subscribe(c => AdaptionHints.Remove(AdaptionHints.FirstOrDefault(h => h.AdaptionHint == c.EventArgs.AdaptionHint)!))
+ .DisposeWith(d);
+
+ AdaptionHints.AddRange(Layer.Adapter.AdaptionHints.Select(CreateHintViewModel));
+ });
+ }
+
+ public Layer Layer { get; }
+ public ObservableCollection AdaptionHints { get; }
+
+ public void Finish()
+ {
+ Close(true);
+ }
+
+ public void AutoDetermineHints()
+ {
+ Layer.Adapter.DetermineHints(_rgbService.EnabledDevices);
+ }
+
+ public void AddCategoryHint()
+ {
+ Layer.Adapter.Add(new CategoryAdaptionHint());
+ }
+
+ public void AddDeviceHint()
+ {
+ Layer.Adapter.Add(new DeviceAdaptionHint());
+ }
+
+ public void AddKeyboardSectionHint()
+ {
+ Layer.Adapter.Add(new KeyboardSectionAdaptionHint());
+ }
+
+ public void RemoveAdaptionHint(IAdaptionHint hint)
+ {
+ Layer.Adapter.Remove(hint);
+ }
+
+ private AdaptionHintViewModelBase CreateHintViewModel(IAdaptionHint hint)
+ {
+ return hint switch
+ {
+ CategoryAdaptionHint categoryAdaptionHint => _vmFactory.CategoryAdaptionHintViewModel(categoryAdaptionHint),
+ DeviceAdaptionHint deviceAdaptionHint => _vmFactory.DeviceAdaptionHintViewModel(deviceAdaptionHint),
+ KeyboardSectionAdaptionHint keyboardSectionAdaptionHint => _vmFactory.KeyboardSectionAdaptionHintViewModel(keyboardSectionAdaptionHint),
+ _ => throw new ArgumentOutOfRangeException(nameof(hint))
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml
index 22cff3a34..45e2d9141 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeView.axaml
@@ -112,6 +112,11 @@
+