diff --git a/src/Artemis.Core/Services/DeviceService.cs b/src/Artemis.Core/Services/DeviceService.cs
index 54dfd34a2..aaa27c59b 100644
--- a/src/Artemis.Core/Services/DeviceService.cs
+++ b/src/Artemis.Core/Services/DeviceService.cs
@@ -157,10 +157,11 @@ internal class DeviceService : IDeviceService
}
}
+ ///
///
- public void AutoArrangeDevices()
+ public void AutoArrangeDevices(bool leftHanded)
{
- SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement();
+ SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement(leftHanded);
surfaceArrangement.Arrange(_devices);
foreach (ArtemisDevice artemisDevice in _devices)
artemisDevice.ApplyDefaultCategories();
diff --git a/src/Artemis.Core/Services/Interfaces/IDeviceService.cs b/src/Artemis.Core/Services/Interfaces/IDeviceService.cs
index 6594535fd..eb611d613 100644
--- a/src/Artemis.Core/Services/Interfaces/IDeviceService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IDeviceService.cs
@@ -46,7 +46,8 @@ public interface IDeviceService : IArtemisService
///
/// Applies auto-arranging logic to the surface
///
- void AutoArrangeDevices();
+ ///
+ void AutoArrangeDevices(bool leftHanded);
///
/// Apples the best available to the provided
diff --git a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs
index 9f4e78fe1..24cf3ba1d 100644
--- a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs
+++ b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangement.cs
@@ -48,22 +48,42 @@ internal class SurfaceArrangement
}
}
- internal static SurfaceArrangement GetDefaultArrangement()
+ internal static SurfaceArrangement GetDefaultArrangement(bool leftHanded)
{
SurfaceArrangement arrangement = new();
- SurfaceArrangementType keypad = arrangement.AddType(RGBDeviceType.Keypad, 1);
- keypad.AddConfiguration(new SurfaceArrangementConfiguration(null, HorizontalArrangementPosition.Equal, VerticalArrangementPosition.Equal, 20));
+ SurfaceArrangementType keyboard, keypad, mousepad, mouse;
+ if (leftHanded)
+ {
+ mousepad = arrangement.AddType(RGBDeviceType.Mousepad, 1);
+ mousepad.AddConfiguration(new SurfaceArrangementConfiguration(null, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Equal, 10));
- SurfaceArrangementType keyboard = arrangement.AddType(RGBDeviceType.Keyboard, 1);
- keyboard.AddConfiguration(new SurfaceArrangementConfiguration(keypad, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Equal, 20));
+ mouse = arrangement.AddType(RGBDeviceType.Mouse, 2);
+ mouse.AddConfiguration(new SurfaceArrangementConfiguration(mousepad, HorizontalArrangementPosition.Center, VerticalArrangementPosition.Center, 0));
+ mouse.AddConfiguration(new SurfaceArrangementConfiguration(null, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Center, 10));
- SurfaceArrangementType mousepad = arrangement.AddType(RGBDeviceType.Mousepad, 1);
- mousepad.AddConfiguration(new SurfaceArrangementConfiguration(keyboard, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Equal, 10));
+ keyboard = arrangement.AddType(RGBDeviceType.Keyboard, 1);
+ keyboard.AddConfiguration(new SurfaceArrangementConfiguration(mousepad, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Equal, 10));
+ keyboard.AddConfiguration(new SurfaceArrangementConfiguration(mouse, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Equal, 100));
- SurfaceArrangementType mouse = arrangement.AddType(RGBDeviceType.Mouse, 2);
- mouse.AddConfiguration(new SurfaceArrangementConfiguration(mousepad, HorizontalArrangementPosition.Center, VerticalArrangementPosition.Center, 0));
- mouse.AddConfiguration(new SurfaceArrangementConfiguration(keyboard, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Center, 100));
+ keypad = arrangement.AddType(RGBDeviceType.Keypad, 1);
+ keypad.AddConfiguration(new SurfaceArrangementConfiguration(keyboard, HorizontalArrangementPosition.Equal, VerticalArrangementPosition.Equal, 20));
+ }
+ else
+ {
+ keypad = arrangement.AddType(RGBDeviceType.Keypad, 1);
+ keypad.AddConfiguration(new SurfaceArrangementConfiguration(null, HorizontalArrangementPosition.Equal, VerticalArrangementPosition.Equal, 20));
+
+ keyboard = arrangement.AddType(RGBDeviceType.Keyboard, 1);
+ keyboard.AddConfiguration(new SurfaceArrangementConfiguration(keypad, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Equal, 20));
+
+ mousepad = arrangement.AddType(RGBDeviceType.Mousepad, 1);
+ mousepad.AddConfiguration(new SurfaceArrangementConfiguration(keyboard, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Equal, 10));
+
+ mouse = arrangement.AddType(RGBDeviceType.Mouse, 2);
+ mouse.AddConfiguration(new SurfaceArrangementConfiguration(mousepad, HorizontalArrangementPosition.Center, VerticalArrangementPosition.Center, 0));
+ mouse.AddConfiguration(new SurfaceArrangementConfiguration(keyboard, HorizontalArrangementPosition.Right, VerticalArrangementPosition.Center, 100));
+ }
SurfaceArrangementType headset = arrangement.AddType(RGBDeviceType.Headset, 1);
headset.AddConfiguration(new SurfaceArrangementConfiguration(keyboard, HorizontalArrangementPosition.Center, VerticalArrangementPosition.Bottom, 100));
diff --git a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs
index 7f59731f9..284c797a5 100644
--- a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs
+++ b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementConfiguration.cs
@@ -32,7 +32,7 @@ internal class SurfaceArrangementConfiguration
public int MarginBottom { get; }
public SurfaceArrangement SurfaceArrangement { get; set; }
- public bool Apply(List devices)
+ public bool Apply(List devicesToArrange, List devices)
{
if (Anchor != null && !Anchor.HasDevices(devices))
return false;
@@ -42,10 +42,10 @@ internal class SurfaceArrangementConfiguration
new SurfaceArrangementType(SurfaceArrangement, RGBDeviceType.All, 1).GetEdge(HorizontalPosition, VerticalPosition);
// Stack multiple devices of the same type vertically if they are wider than they are tall
- bool stackVertically = devices.Average(d => d.RgbDevice.Size.Width) >= devices.Average(d => d.RgbDevice.Size.Height);
+ bool stackVertically = devicesToArrange.Average(d => d.RgbDevice.Size.Width) >= devicesToArrange.Average(d => d.RgbDevice.Size.Height);
ArtemisDevice? previous = null;
- foreach (ArtemisDevice artemisDevice in devices)
+ foreach (ArtemisDevice artemisDevice in devicesToArrange)
{
if (previous != null)
{
diff --git a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementType.cs b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementType.cs
index 48d0d015f..d855b720b 100644
--- a/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementType.cs
+++ b/src/Artemis.Core/Services/Storage/Models/SurfaceArrangementType.cs
@@ -28,18 +28,18 @@ internal class SurfaceArrangementType
public void Arrange(List devices)
{
- devices = devices.Where(d => d.DeviceType == DeviceType).ToList();
- if (!devices.Any())
+ List devicesToArrange = devices.Where(d => d.DeviceType == DeviceType).ToList();
+ if (!devicesToArrange.Any())
return;
AppliedConfiguration = null;
foreach (SurfaceArrangementConfiguration configuration in Configurations)
{
- bool applied = configuration.Apply(devices);
+ bool applied = configuration.Apply(devicesToArrange, devices);
if (applied)
{
AppliedConfiguration = configuration;
- foreach (ArtemisDevice artemisDevice in devices)
+ foreach (ArtemisDevice artemisDevice in devicesToArrange)
artemisDevice.ZIndex = ZIndex;
return;
}
@@ -52,7 +52,7 @@ internal class SurfaceArrangementType
VerticalArrangementPosition.Equal,
10
) {SurfaceArrangement = SurfaceArrangement};
- fallback.Apply(devices);
+ fallback.Apply(devicesToArrange, devices);
AppliedConfiguration = fallback;
}
diff --git a/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs
index a9f17c2ee..ae9518f83 100644
--- a/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/ProfileEditor/ProfileEditorService.cs
@@ -185,12 +185,15 @@ internal class ProfileEditorService : IProfileEditorService
{
// Activate the profile if one was provided
if (profileConfiguration != null)
+ {
+ _profileService.FocusProfile = profileConfiguration;
_profileService.ActivateProfile(profileConfiguration);
+ }
+
// If there is no profile configuration or module, deliberately set the override to null
_moduleService.SetActivationOverride(profileConfiguration?.Module);
});
-
- _profileService.FocusProfile = profileConfiguration;
+
_profileConfigurationSubject.OnNext(profileConfiguration);
ChangeTime(TimeSpan.Zero);
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs
index 38f8c6856..16bf19759 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Panels/ProfileTree/ProfileTreeViewModel.cs
@@ -79,11 +79,6 @@ public partial class ProfileTreeViewModel : TreeItemViewModel
public override bool SupportsChildren => true;
- public void UpdateCanPaste()
- {
- throw new NotImplementedException();
- }
-
protected override Task ExecuteDuplicate()
{
throw new NotSupportedException();
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationViewModel.cs
index ee5e5c111..5596c3e9f 100644
--- a/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationViewModel.cs
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarProfileConfigurationViewModel.cs
@@ -132,6 +132,6 @@ public class SidebarProfileConfigurationViewModel : ActivatableViewModelBase
public bool Matches(string s)
{
- return s == $"profile/{ProfileConfiguration.ProfileId}/editor";
+ return s.StartsWith($"profile/{ProfileConfiguration.ProfileId}");
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/StartupWizard/Steps/DefaultEntryItemViewModel.cs b/src/Artemis.UI/Screens/StartupWizard/Steps/DefaultEntryItemViewModel.cs
index 0aa1d901e..2d288b321 100644
--- a/src/Artemis.UI/Screens/StartupWizard/Steps/DefaultEntryItemViewModel.cs
+++ b/src/Artemis.UI/Screens/StartupWizard/Steps/DefaultEntryItemViewModel.cs
@@ -27,20 +27,27 @@ public partial class DefaultEntryItemViewModel : ActivatableViewModelBase
private readonly IWorkshopService _workshopService;
private readonly IWindowService _windowService;
private readonly IPluginManagementService _pluginManagementService;
+ private readonly IProfileService _profileService;
private readonly ISettingsVmFactory _settingsVmFactory;
private readonly Progress _progress = new();
[Notify] private bool _isInstalled;
[Notify] private bool _shouldInstall;
[Notify] private float _installProgress;
-
- public DefaultEntryItemViewModel(ILogger logger, IEntrySummary entry, IWorkshopService workshopService, IWindowService windowService, IPluginManagementService pluginManagementService,
+
+ public DefaultEntryItemViewModel(ILogger logger,
+ IEntrySummary entry,
+ IWorkshopService workshopService,
+ IWindowService windowService,
+ IPluginManagementService pluginManagementService,
+ IProfileService profileService,
ISettingsVmFactory settingsVmFactory)
{
_logger = logger;
_workshopService = workshopService;
_windowService = windowService;
_pluginManagementService = pluginManagementService;
+ _profileService = profileService;
_settingsVmFactory = settingsVmFactory;
Entry = entry;
@@ -62,19 +69,18 @@ public partial class DefaultEntryItemViewModel : ActivatableViewModelBase
if (!result.IsSuccess)
{
- await _windowService.CreateContentDialog().WithTitle("Failed to install entry")
+ await _windowService.CreateContentDialog()
+ .WithTitle("Failed to install entry")
.WithContent($"Failed to install entry '{Entry.Name}' ({Entry.Id}): {result.Message}")
.WithCloseButtonText("Skip and continue")
.ShowAsync();
}
// If the entry is a plugin, enable the plugin and all features
else if (result.Entry?.EntryType == EntryType.Plugin)
- {
await EnablePluginAndFeatures(result.Entry);
- } else if (result.Entry?.EntryType == EntryType.Profile)
- {
-
- }
+ // If the entry is a profile, move it to the General profile category
+ else if (result.Entry?.EntryType == EntryType.Profile)
+ MoveProfileToGeneral(result.Entry);
return result.IsSuccess;
}
@@ -107,14 +113,31 @@ public partial class DefaultEntryItemViewModel : ActivatableViewModelBase
_logger.Warning(e, "Failed to enable plugin feature '{FeatureName}', skipping", pluginFeatureInfo.Name);
}
}
-
+
// If the plugin has a mandatory settings window, open it and wait
if (plugin.ConfigurationDialog != null && plugin.ConfigurationDialog.IsMandatory)
{
if (plugin.Resolve(plugin.ConfigurationDialog.Type) is not PluginConfigurationViewModel viewModel)
throw new ArtemisUIException($"The type of a plugin configuration dialog must inherit {nameof(PluginConfigurationViewModel)}");
-
+
await _windowService.ShowDialogAsync(new PluginSettingsWindowViewModel(viewModel));
}
}
+
+ private void MoveProfileToGeneral(InstalledEntry entry)
+ {
+ if (!entry.TryGetMetadata("ProfileId", out Guid profileId))
+ return;
+
+ ProfileConfiguration? profile = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(c => c.ProfileId == profileId);
+ if (profile == null)
+ return;
+
+ ProfileCategory category = _profileService.ProfileCategories.FirstOrDefault(c => c.Name == "General") ?? _profileService.CreateProfileCategory("General", true);
+ if (category.ProfileConfigurations.Contains(profile))
+ return;
+
+ category.AddProfileConfiguration(profile, null);
+ _profileService.SaveProfileCategory(category);
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/StartupWizard/Steps/SurfaceStepView.axaml b/src/Artemis.UI/Screens/StartupWizard/Steps/SurfaceStepView.axaml
index a66959529..c7aabb5c2 100644
--- a/src/Artemis.UI/Screens/StartupWizard/Steps/SurfaceStepView.axaml
+++ b/src/Artemis.UI/Screens/StartupWizard/Steps/SurfaceStepView.axaml
@@ -24,15 +24,14 @@
HorizontalAlignment="Right"
Margin="0 0 10 0"
Width="280"
- Height="280"
- IsEnabled="False">
+ Height="280">
- Left-handed preset (NYI)
+ Left-handed preset
- A preset with the mouse on the left side of the keyboard
+ A preset with the mouse on the left side of the keyboard (are you the 10%?)
diff --git a/src/Artemis.UI/Screens/StartupWizard/Steps/SurfaceStepViewModel.cs b/src/Artemis.UI/Screens/StartupWizard/Steps/SurfaceStepViewModel.cs
index 04989be43..ccdcdac00 100644
--- a/src/Artemis.UI/Screens/StartupWizard/Steps/SurfaceStepViewModel.cs
+++ b/src/Artemis.UI/Screens/StartupWizard/Steps/SurfaceStepViewModel.cs
@@ -27,9 +27,7 @@ public class SurfaceStepViewModel : WizardStepViewModel
private void ExecuteSelectLayout(string layout)
{
- // TODO: Implement the layout
- _deviceService.AutoArrangeDevices();
-
+ _deviceService.AutoArrangeDevices(layout == "left");
Wizard.ChangeScreen();
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs
index 248ca19de..f596e0f23 100644
--- a/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs
+++ b/src/Artemis.UI/Screens/SurfaceEditor/SurfaceEditorViewModel.cs
@@ -13,6 +13,7 @@ using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Services;
using Avalonia;
+using FluentAvalonia.UI.Controls;
using PropertyChanged.SourceGenerator;
using ReactiveUI;
using SkiaSharp;
@@ -180,11 +181,18 @@ public partial class SurfaceEditorViewModel : RoutableScreen, IMainScreenViewMod
private async Task ExecuteAutoArrange()
{
- bool confirmed = await _windowService.ShowConfirmContentDialog("Auto-arrange layout", "Are you sure you want to auto-arrange your layout? Your current settings will be overwritten.");
- if (!confirmed)
- return;
-
- _deviceService.AutoArrangeDevices();
+ ContentDialogResult contentDialogResult = await _windowService.CreateContentDialog()
+ .WithTitle("Auto-arrange layout")
+ .WithContent("Which preset would you like to apply? Your current settings will be overwritten.")
+ .HavingPrimaryButton(b => b.WithText("Left-handed preset"))
+ .HavingSecondaryButton(b => b.WithText("Right-handed preset"))
+ .WithCloseButtonText("Cancel")
+ .ShowAsync();
+
+ if (contentDialogResult == ContentDialogResult.Primary)
+ _deviceService.AutoArrangeDevices(true);
+ else if (contentDialogResult == ContentDialogResult.Secondary)
+ _deviceService.AutoArrangeDevices(false);
}
private void RenderServiceOnFrameRendering(object? sender, FrameRenderingEventArgs e)