mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 13:28:33 +00:00
Profile editor - Fix race condition causing the editor to fail to activate on suspended profiles
Surface editor - Implemented left-handed preset
This commit is contained in:
parent
108cbaae3d
commit
06c5294e88
@ -157,10 +157,11 @@ internal class DeviceService : IDeviceService
|
||||
}
|
||||
}
|
||||
|
||||
/// <param name="leftHanded"></param>
|
||||
/// <inheritdoc />
|
||||
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();
|
||||
|
||||
@ -46,7 +46,8 @@ public interface IDeviceService : IArtemisService
|
||||
/// <summary>
|
||||
/// Applies auto-arranging logic to the surface
|
||||
/// </summary>
|
||||
void AutoArrangeDevices();
|
||||
/// <param name="leftHanded"></param>
|
||||
void AutoArrangeDevices(bool leftHanded);
|
||||
|
||||
/// <summary>
|
||||
/// Apples the best available to the provided <see cref="ArtemisDevice" />
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -32,7 +32,7 @@ internal class SurfaceArrangementConfiguration
|
||||
public int MarginBottom { get; }
|
||||
public SurfaceArrangement SurfaceArrangement { get; set; }
|
||||
|
||||
public bool Apply(List<ArtemisDevice> devices)
|
||||
public bool Apply(List<ArtemisDevice> devicesToArrange, List<ArtemisDevice> 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)
|
||||
{
|
||||
|
||||
@ -28,18 +28,18 @@ internal class SurfaceArrangementType
|
||||
|
||||
public void Arrange(List<ArtemisDevice> devices)
|
||||
{
|
||||
devices = devices.Where(d => d.DeviceType == DeviceType).ToList();
|
||||
if (!devices.Any())
|
||||
List<ArtemisDevice> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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}");
|
||||
}
|
||||
}
|
||||
@ -27,6 +27,7 @@ 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<StreamProgress> _progress = new();
|
||||
|
||||
@ -34,13 +35,19 @@ public partial class DefaultEntryItemViewModel : ActivatableViewModelBase
|
||||
[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;
|
||||
}
|
||||
@ -117,4 +123,21 @@ public partial class DefaultEntryItemViewModel : ActivatableViewModelBase
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -24,15 +24,14 @@
|
||||
HorizontalAlignment="Right"
|
||||
Margin="0 0 10 0"
|
||||
Width="280"
|
||||
Height="280"
|
||||
IsEnabled="False">
|
||||
Height="280">
|
||||
<StackPanel>
|
||||
<avalonia:MaterialIcon Kind="HandBackLeft" Width="150" Height="150" HorizontalAlignment="Center" />
|
||||
<TextBlock TextAlignment="Center" Classes="h4" Margin="0 10 0 0">
|
||||
Left-handed preset (NYI)
|
||||
Left-handed preset
|
||||
</TextBlock>
|
||||
<TextBlock TextAlignment="Center" Classes="subtitle" TextWrapping="Wrap">
|
||||
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%?)
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
@ -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<SettingsStepViewModel>();
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
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();
|
||||
|
||||
_deviceService.AutoArrangeDevices();
|
||||
if (contentDialogResult == ContentDialogResult.Primary)
|
||||
_deviceService.AutoArrangeDevices(true);
|
||||
else if (contentDialogResult == ContentDialogResult.Secondary)
|
||||
_deviceService.AutoArrangeDevices(false);
|
||||
}
|
||||
|
||||
private void RenderServiceOnFrameRendering(object? sender, FrameRenderingEventArgs e)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user