diff --git a/src/Artemis.Core/Models/Profile/ProfileCategory.cs b/src/Artemis.Core/Models/Profile/ProfileCategory.cs
index a15a63e91..f2e9cac5a 100644
--- a/src/Artemis.Core/Models/Profile/ProfileCategory.cs
+++ b/src/Artemis.Core/Models/Profile/ProfileCategory.cs
@@ -203,45 +203,4 @@ namespace Artemis.Core
///
General
}
-
- ///
- /// Represents a type of behaviour when this profile is activated
- ///
- public enum ActivationBehaviour
- {
- ///
- /// Do nothing to other profiles
- ///
- None,
-
- ///
- /// Disable all other profiles
- ///
- DisableOthers,
-
- ///
- /// Disable all other profiles below this one
- ///
- DisableOthersBelow,
-
- ///
- /// Disable all other profiles above this one
- ///
- DisableOthersAbove,
-
- ///
- /// Disable all other profiles in the same category
- ///
- DisableOthersInCategory,
-
- ///
- /// Disable all other profiles below this one in the same category
- ///
- DisableOthersBelowInCategory,
-
- ///
- /// Disable all other profiles above this one in the same category
- ///
- DisableOthersAboveInCategory
- }
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs
index f70ef6e9c..22b15e662 100644
--- a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs
+++ b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs
@@ -92,6 +92,21 @@ namespace Artemis.Core
///
public ProfileConfigurationIcon Icon { get; }
+ ///
+ /// Gets or sets the used to determine hotkey behaviour
+ ///
+ public ProfileConfigurationHotkeyMode HotkeyMode { get; set; }
+
+ ///
+ /// Gets or sets the hotkey used to enable or toggle the profile
+ ///
+ public ProfileConfigurationHotkey? EnableHotkey { get; set; }
+
+ ///
+ /// Gets or sets the hotkey used to disable the profile
+ ///
+ public ProfileConfigurationHotkey? DisableHotkey { get; set; }
+
///
/// Gets the profile of this profile configuration
///
@@ -151,6 +166,10 @@ namespace Artemis.Core
ActivationConditionMet = ActivationCondition == null || ActivationCondition.Evaluate();
}
+ ///
+ /// Determines whether the profile of this configuration should be active
+ ///
+ /// Whether or not to take activation conditions into consideration
public bool ShouldBeActive(bool includeActivationCondition)
{
if (_disposed)
@@ -201,13 +220,15 @@ namespace Artemis.Core
Name = Entity.Name;
IsSuspended = Entity.IsSuspended;
ActivationBehaviour = (ActivationBehaviour) Entity.ActivationBehaviour;
+ HotkeyMode = (ProfileConfigurationHotkeyMode) Entity.HotkeyMode;
Order = Entity.Order;
Icon.Load();
- ActivationCondition = Entity.ActivationCondition != null
- ? new DataModelConditionGroup(null, Entity.ActivationCondition)
- : null;
+ ActivationCondition = Entity.ActivationCondition != null ? new DataModelConditionGroup(null, Entity.ActivationCondition) : null;
+
+ EnableHotkey = Entity.EnableHotkey != null ? new ProfileConfigurationHotkey(Entity.EnableHotkey) : null;
+ DisableHotkey = Entity.DisableHotkey != null ? new ProfileConfigurationHotkey(Entity.DisableHotkey) : null;
}
///
@@ -219,18 +240,19 @@ namespace Artemis.Core
Entity.Name = Name;
Entity.IsSuspended = IsSuspended;
Entity.ActivationBehaviour = (int) ActivationBehaviour;
+ Entity.HotkeyMode = (int) HotkeyMode;
Entity.ProfileCategoryId = Category.Entity.Id;
Entity.Order = Order;
Icon.Save();
- if (ActivationCondition != null)
- {
- ActivationCondition.Save();
- Entity.ActivationCondition = ActivationCondition.Entity;
- }
- else
- Entity.ActivationCondition = null;
+ ActivationCondition?.Save();
+ Entity.ActivationCondition = ActivationCondition?.Entity;
+
+ EnableHotkey?.Save();
+ Entity.EnableHotkey = EnableHotkey?.Entity;
+ DisableHotkey?.Save();
+ Entity.DisableHotkey = DisableHotkey?.Entity;
if (!IsMissingModule)
Entity.ModuleId = Module?.Id;
@@ -238,4 +260,66 @@ namespace Artemis.Core
#endregion
}
+
+ ///
+ /// Represents a type of behaviour when this profile is activated
+ ///
+ public enum ActivationBehaviour
+ {
+ ///
+ /// Do nothing to other profiles
+ ///
+ None,
+
+ ///
+ /// Disable all other profiles
+ ///
+ DisableOthers,
+
+ ///
+ /// Disable all other profiles below this one
+ ///
+ DisableOthersBelow,
+
+ ///
+ /// Disable all other profiles above this one
+ ///
+ DisableOthersAbove,
+
+ ///
+ /// Disable all other profiles in the same category
+ ///
+ DisableOthersInCategory,
+
+ ///
+ /// Disable all other profiles below this one in the same category
+ ///
+ DisableOthersBelowInCategory,
+
+ ///
+ /// Disable all other profiles above this one in the same category
+ ///
+ DisableOthersAboveInCategory
+ }
+
+ ///
+ /// Represents a hotkey mode for a profile configuration
+ ///
+ public enum ProfileConfigurationHotkeyMode
+ {
+ ///
+ /// Use no hotkeys
+ ///
+ None,
+
+ ///
+ /// Toggle the profile with one hotkey
+ ///
+ Toggle,
+
+ ///
+ /// Enable and disable the profile with two separate hotkeys
+ ///
+ EnableDisable
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfigurationHotkey.cs b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfigurationHotkey.cs
new file mode 100644
index 000000000..0a735f875
--- /dev/null
+++ b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfigurationHotkey.cs
@@ -0,0 +1,65 @@
+using Artemis.Core.Services;
+using Artemis.Storage.Entities.Profile;
+
+namespace Artemis.Core
+{
+ ///
+ /// Represents a key or combination of keys that changes the suspension status of a
+ ///
+ public class ProfileConfigurationHotkey : CorePropertyChanged, IStorageModel
+ {
+
+ ///
+ /// Creates a new instance of
+ ///
+ public ProfileConfigurationHotkey()
+ {
+ Entity = new ProfileConfigurationHotkeyEntity();
+ }
+
+ internal ProfileConfigurationHotkey(ProfileConfigurationHotkeyEntity entity)
+ {
+ Entity = entity;
+ Load();
+ }
+
+ internal ProfileConfigurationHotkeyEntity Entity { get; }
+
+ ///
+ /// Gets or sets the of the hotkey
+ ///
+ public KeyboardKey? Key { get; set; }
+
+ ///
+ /// Gets or sets the s of the hotkey
+ ///
+ public KeyboardModifierKey? Modifiers { get; set; }
+
+ ///
+ /// Determines whether the provided match the hotkey
+ ///
+ /// if the event args match the hotkey; otherwise
+ public bool MatchesEventArgs(ArtemisKeyboardKeyEventArgs eventArgs)
+ {
+ return eventArgs.Key == Key && eventArgs.Modifiers == Modifiers;
+ }
+
+ #region Implementation of IStorageModel
+
+ ///
+ public void Load()
+ {
+ Key = (KeyboardKey?) Entity.Key;
+ Modifiers = (KeyboardModifierKey?) Entity.Modifiers;
+ }
+
+ ///
+ public void Save()
+ {
+ Entity.Key = (int?) Key;
+ Entity.Modifiers = (int?) Modifiers;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs
index 027ac09af..00a74d2a5 100644
--- a/src/Artemis.Core/Services/PluginManagementService.cs
+++ b/src/Artemis.Core/Services/PluginManagementService.cs
@@ -537,15 +537,13 @@ namespace Artemis.Core.Services
string metaDataDirectory = metaDataFileEntry.FullName.Replace(metaDataFileEntry.Name, "");
foreach (ZipArchiveEntry zipArchiveEntry in archive.Entries)
{
- if (zipArchiveEntry.FullName.StartsWith(metaDataDirectory))
+ if (zipArchiveEntry.FullName.StartsWith(metaDataDirectory) && !zipArchiveEntry.FullName.EndsWith("/"))
{
string target = Path.Combine(directoryInfo.FullName, zipArchiveEntry.FullName.Remove(0, metaDataDirectory.Length));
// Create folders
- if (zipArchiveEntry.FullName.EndsWith("/"))
- Utilities.CreateAccessibleDirectory(Path.GetDirectoryName(target)!);
+ Utilities.CreateAccessibleDirectory(Path.GetDirectoryName(target)!);
// Extract files
- else
- zipArchiveEntry.ExtractToFile(target);
+ zipArchiveEntry.ExtractToFile(target);
}
}
diff --git a/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs b/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
index 84fa8ebae..cdf7a8d52 100644
--- a/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/Interfaces/IProfileService.cs
@@ -10,14 +10,14 @@ namespace Artemis.Core.Services
public interface IProfileService : IArtemisService
{
///
- /// Gets the JSON serializer settings used to create profile mementos
+ /// Gets the JSON serializer settings used to create profile mementos
///
public static JsonSerializerSettings MementoSettings { get; } = new() {TypeNameHandling = TypeNameHandling.All};
///
- /// Gets the JSON serializer settings used to import/export profiles
+ /// Gets the JSON serializer settings used to import/export profiles
///
- public static JsonSerializerSettings ExportSettings { get; } = new() {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented};
+ public static JsonSerializerSettings ExportSettings { get; } = new() {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented};
///
/// Gets a read only collection containing all the profile categories
@@ -29,6 +29,11 @@ namespace Artemis.Core.Services
///
ReadOnlyCollection ProfileConfigurations { get; }
+ ///
+ /// Gets or sets a boolean indicating whether hotkeys are enabled
+ ///
+ bool HotkeysEnabled { get; set; }
+
///
/// Gets or sets a boolean indicating whether rendering should only be done for profiles being edited
///
@@ -128,10 +133,14 @@ namespace Artemis.Core.Services
/// The in which to import the profile
/// The model containing the profile to import
/// Whether or not to give the profile a new GUID, making it unique
- /// Whether or not to mark the profile as a fresh import, causing it to be adapted until any changes are made to it
+ ///
+ /// Whether or not to mark the profile as a fresh import, causing it to be adapted until
+ /// any changes are made to it
+ ///
/// Text to add after the name of the profile (separated by a dash)
/// The resulting profile configuration
- ProfileConfiguration ImportProfile(ProfileCategory category, ProfileConfigurationExportModel exportModel, bool makeUnique = true, bool markAsFreshImport = true, string? nameAffix = "imported");
+ ProfileConfiguration ImportProfile(ProfileCategory category, ProfileConfigurationExportModel exportModel, bool makeUnique = true, bool markAsFreshImport = true,
+ string? nameAffix = "imported");
///
/// Adapts a given profile to the currently active devices
diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs
index b3fb0c267..453e2c6e5 100644
--- a/src/Artemis.Core/Services/Storage/ProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/ProfileService.cs
@@ -15,16 +15,17 @@ namespace Artemis.Core.Services
internal class ProfileService : IProfileService
{
private readonly ILogger _logger;
+
+ private readonly List _pendingKeyboardEvents = new();
private readonly IPluginManagementService _pluginManagementService;
private readonly List _profileCategories;
private readonly IProfileCategoryRepository _profileCategoryRepository;
private readonly IProfileRepository _profileRepository;
- private readonly IRgbService _rgbService;
-
- private readonly List _updateExceptions = new();
- private DateTime _lastUpdateExceptionLog;
private readonly List _renderExceptions = new();
+ private readonly IRgbService _rgbService;
+ private readonly List _updateExceptions = new();
private DateTime _lastRenderExceptionLog;
+ private DateTime _lastUpdateExceptionLog;
public ProfileService(ILogger logger,
IRgbService rgbService,
@@ -33,6 +34,7 @@ namespace Artemis.Core.Services
IDataBindingService dataBindingService,
IProfileCategoryRepository profileCategoryRepository,
IPluginManagementService pluginManagementService,
+ IInputService inputService,
IProfileRepository profileRepository)
{
_logger = logger;
@@ -46,10 +48,23 @@ namespace Artemis.Core.Services
_pluginManagementService.PluginFeatureEnabled += PluginManagementServiceOnPluginFeatureToggled;
_pluginManagementService.PluginFeatureDisabled += PluginManagementServiceOnPluginFeatureToggled;
+ inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp;
+
if (!_profileCategories.Any())
CreateDefaultProfileCategories();
}
+ private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
+ {
+ if (!HotkeysEnabled)
+ return;
+
+ lock (_profileCategories)
+ {
+ _pendingKeyboardEvents.Add(e);
+ }
+ }
+
///
/// Populates all missing LEDs on all currently active profiles
///
@@ -88,84 +103,25 @@ namespace Artemis.Core.Services
UpdateModules();
}
- public bool RenderForEditor { get; set; }
-
- public void UpdateProfiles(double deltaTime)
+ private void ProcessPendingKeyEvents(ProfileConfiguration profileConfiguration)
{
- lock (_profileCategories)
+ if (profileConfiguration.HotkeyMode == ProfileConfigurationHotkeyMode.None)
+ return;
+
+ foreach (ArtemisKeyboardKeyEventArgs e in _pendingKeyboardEvents)
{
- // Iterate the children in reverse because the first category must be rendered last to end up on top
- for (int i = _profileCategories.Count - 1; i > -1; i--)
+ if (profileConfiguration.HotkeyMode == ProfileConfigurationHotkeyMode.Toggle)
{
- ProfileCategory profileCategory = _profileCategories[i];
- for (int j = profileCategory.ProfileConfigurations.Count - 1; j > -1; j--)
- {
- ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
- // Profiles being edited are updated at their own leisure
- if (profileConfiguration.IsBeingEdited)
- continue;
-
- bool shouldBeActive = profileConfiguration.ShouldBeActive(false);
- if (shouldBeActive)
- {
- profileConfiguration.Update();
- shouldBeActive = profileConfiguration.ActivationConditionMet;
- }
-
- try
- {
- // Make sure the profile is active or inactive according to the parameters above
- if (shouldBeActive && profileConfiguration.Profile == null)
- ActivateProfile(profileConfiguration);
- else if (!shouldBeActive && profileConfiguration.Profile != null)
- DeactivateProfile(profileConfiguration);
-
- profileConfiguration.Profile?.Update(deltaTime);
- }
- catch (Exception e)
- {
- _updateExceptions.Add(e);
- }
- }
+ if (profileConfiguration.EnableHotkey != null && profileConfiguration.EnableHotkey.MatchesEventArgs(e))
+ profileConfiguration.IsSuspended = !profileConfiguration.IsSuspended;
}
-
- LogProfileUpdateExceptions();
- }
- }
-
- public void RenderProfiles(SKCanvas canvas)
- {
- lock (_profileCategories)
- {
- // Iterate the children in reverse because the first category must be rendered last to end up on top
- for (int i = _profileCategories.Count - 1; i > -1; i--)
+ else
{
- ProfileCategory profileCategory = _profileCategories[i];
- for (int j = profileCategory.ProfileConfigurations.Count - 1; j > -1; j--)
- {
- try
- {
- ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
- if (RenderForEditor)
- {
- if (profileConfiguration.IsBeingEdited)
- profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
- }
- else
- {
- // Ensure all criteria are met before rendering
- if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && profileConfiguration.ActivationConditionMet)
- profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
- }
- }
- catch (Exception e)
- {
- _renderExceptions.Add(e);
- }
- }
+ if (profileConfiguration.IsSuspended && profileConfiguration.EnableHotkey != null && profileConfiguration.EnableHotkey.MatchesEventArgs(e))
+ profileConfiguration.IsSuspended = false;
+ if (!profileConfiguration.IsSuspended && profileConfiguration.DisableHotkey != null && profileConfiguration.DisableHotkey.MatchesEventArgs(e))
+ profileConfiguration.IsSuspended = true;
}
-
- LogProfileRenderExceptions();
}
}
@@ -211,6 +167,93 @@ namespace Artemis.Core.Services
_renderExceptions.Clear();
}
+ public bool HotkeysEnabled { get; set; }
+ public bool RenderForEditor { get; set; }
+
+ public void UpdateProfiles(double deltaTime)
+ {
+ lock (_profileCategories)
+ {
+ // Iterate the children in reverse because the first category must be rendered last to end up on top
+ for (int i = _profileCategories.Count - 1; i > -1; i--)
+ {
+ ProfileCategory profileCategory = _profileCategories[i];
+ for (int j = profileCategory.ProfileConfigurations.Count - 1; j > -1; j--)
+ {
+ ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
+
+ // Process hotkeys that where pressed since this profile last updated
+ ProcessPendingKeyEvents(profileConfiguration);
+
+ // Profiles being edited are updated at their own leisure
+ if (profileConfiguration.IsBeingEdited)
+ continue;
+
+ bool shouldBeActive = profileConfiguration.ShouldBeActive(false);
+ if (shouldBeActive)
+ {
+ profileConfiguration.Update();
+ shouldBeActive = profileConfiguration.ActivationConditionMet;
+ }
+
+ try
+ {
+ // Make sure the profile is active or inactive according to the parameters above
+ if (shouldBeActive && profileConfiguration.Profile == null)
+ ActivateProfile(profileConfiguration);
+ else if (!shouldBeActive && profileConfiguration.Profile != null)
+ DeactivateProfile(profileConfiguration);
+
+ profileConfiguration.Profile?.Update(deltaTime);
+ }
+ catch (Exception e)
+ {
+ _updateExceptions.Add(e);
+ }
+ }
+ }
+
+ LogProfileUpdateExceptions();
+ _pendingKeyboardEvents.Clear();
+ }
+ }
+
+ public void RenderProfiles(SKCanvas canvas)
+ {
+ lock (_profileCategories)
+ {
+ // Iterate the children in reverse because the first category must be rendered last to end up on top
+ for (int i = _profileCategories.Count - 1; i > -1; i--)
+ {
+ ProfileCategory profileCategory = _profileCategories[i];
+ for (int j = profileCategory.ProfileConfigurations.Count - 1; j > -1; j--)
+ {
+ try
+ {
+ ProfileConfiguration profileConfiguration = profileCategory.ProfileConfigurations[j];
+ if (RenderForEditor)
+ {
+ if (profileConfiguration.IsBeingEdited)
+ profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
+ }
+ else
+ {
+ // Ensure all criteria are met before rendering
+ if (!profileConfiguration.IsSuspended && !profileConfiguration.IsMissingModule && profileConfiguration.ActivationConditionMet)
+ profileConfiguration.Profile?.Render(canvas, SKPointI.Empty);
+ }
+ }
+ catch (Exception e)
+ {
+ _renderExceptions.Add(e);
+ }
+ }
+ }
+
+ LogProfileRenderExceptions();
+ }
+ }
+
public ReadOnlyCollection ProfileCategories
{
get
@@ -485,7 +528,8 @@ namespace Artemis.Core.Services
if (markAsFreshImport)
profileEntity.IsFreshImport = true;
- _profileRepository.Add(profileEntity);
+ if (!makeUnique && _profileRepository.Get(profileEntity.Id) == null)
+ _profileRepository.Add(profileEntity);
ProfileConfiguration profileConfiguration;
if (exportModel.ProfileConfigurationEntity != null)
@@ -500,9 +544,7 @@ namespace Artemis.Core.Services
profileConfiguration.Name = $"{profileConfiguration.Name} - {nameAffix}";
}
else
- {
profileConfiguration = new ProfileConfiguration(category, profileEntity.Name, "Import");
- }
if (exportModel.ProfileImage != null)
{
diff --git a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs
index 32c92e15f..8b9f08dd8 100644
--- a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs
+++ b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs
@@ -15,6 +15,10 @@ namespace Artemis.Storage.Entities.Profile
public int ActivationBehaviour { get; set; }
public DataModelConditionGroupEntity ActivationCondition { get; set; }
+ public int HotkeyMode { get; set; }
+ public ProfileConfigurationHotkeyEntity EnableHotkey { get; set; }
+ public ProfileConfigurationHotkeyEntity DisableHotkey { get; set; }
+
public string ModuleId { get; set; }
public Guid ProfileCategoryId { get; set; }
diff --git a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationHotkeyEntity.cs b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationHotkeyEntity.cs
new file mode 100644
index 000000000..f99cecfb2
--- /dev/null
+++ b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationHotkeyEntity.cs
@@ -0,0 +1,8 @@
+namespace Artemis.Storage.Entities.Profile
+{
+ public class ProfileConfigurationHotkeyEntity
+ {
+ public int? Key { get; set; }
+ public int? Modifiers { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
index 1bf08637d..e63671e50 100644
--- a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
+++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
@@ -106,6 +106,7 @@ namespace Artemis.UI.Ninject.Factories
{
SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory);
SidebarProfileConfigurationViewModel SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration);
+ ProfileConfigurationHotkeyViewModel ProfileConfigurationHotkeyViewModel(ProfileConfiguration profileConfiguration, bool isDisableHotkey);
ModuleActivationRequirementViewModel ModuleActivationRequirementViewModel(IModuleActivationRequirement activationRequirement);
}
diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/Predicate/DataModelConditionEventPredicateViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Conditions/Predicate/DataModelConditionEventPredicateViewModel.cs
index 90fb5702c..baadf2a02 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/Conditions/Predicate/DataModelConditionEventPredicateViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/Predicate/DataModelConditionEventPredicateViewModel.cs
@@ -9,6 +9,7 @@ using Artemis.UI.Extensions;
using Artemis.UI.Screens.ProfileEditor.Conditions.Abstract;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
+using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.Conditions
{
@@ -62,7 +63,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
protected override List GetExtraRightSideDataModelViewModels()
{
// Extra data models are expected to not have an empty root, so lets return the child
- return GetEventDataModel().Children.Cast().ToList();
+ BindableCollection children = GetEventDataModel().Children;
+ return children.Cast().ToList();
}
private DataModelPropertiesViewModel GetEventDataModel()
diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileConfigurationHotkeyView.xaml b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileConfigurationHotkeyView.xaml
new file mode 100644
index 000000000..badf3bd73
--- /dev/null
+++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileConfigurationHotkeyView.xaml
@@ -0,0 +1,20 @@
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileConfigurationHotkeyViewModel.cs b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileConfigurationHotkeyViewModel.cs
new file mode 100644
index 000000000..000b32945
--- /dev/null
+++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileConfigurationHotkeyViewModel.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Linq;
+using System.Windows.Input;
+using Artemis.Core;
+using Artemis.Core.Services;
+using Stylet;
+
+namespace Artemis.UI.Screens.Sidebar.Dialogs.ProfileEdit
+{
+ public class ProfileConfigurationHotkeyViewModel : Screen
+ {
+ private readonly bool _isDisableHotkey;
+ private readonly ProfileConfiguration _profileConfiguration;
+ private string _hint;
+ private string _hotkeyDisplay;
+
+ public ProfileConfigurationHotkeyViewModel(ProfileConfiguration profileConfiguration, bool isDisableHotkey)
+ {
+ _profileConfiguration = profileConfiguration;
+ _isDisableHotkey = isDisableHotkey;
+
+ UpdateHotkeyDisplay();
+ }
+
+ public ProfileConfigurationHotkey Hotkey => _isDisableHotkey ? _profileConfiguration.DisableHotkey : _profileConfiguration.EnableHotkey;
+
+ public string Hint
+ {
+ get => _hint;
+ set => SetAndNotify(ref _hint, value);
+ }
+
+ public string HotkeyDisplay
+ {
+ get => _hotkeyDisplay;
+ set
+ {
+ if (!SetAndNotify(ref _hotkeyDisplay, value)) return;
+ if (value == null && Hotkey != null)
+ {
+ Hotkey.Key = null;
+ Hotkey.Modifiers = null;
+ }
+ }
+ }
+
+ public void UpdateHotkeyDisplay()
+ {
+ string display = null;
+ if (Hotkey?.Modifiers != null)
+ display = string.Join("+", Enum.GetValues().Skip(1).Where(m => Hotkey.Modifiers.Value.HasFlag(m)));
+ if (Hotkey?.Key != null)
+ display = string.IsNullOrEmpty(display) ? Hotkey.Key.ToString() : $"{display}+{Hotkey.Key}";
+
+ HotkeyDisplay = display;
+ if (_profileConfiguration.HotkeyMode == ProfileConfigurationHotkeyMode.EnableDisable)
+ Hint = _isDisableHotkey ? "Disable hotkey" : "Enable hotkey";
+ else
+ Hint = "Toggle hotkey";
+ }
+
+ public void TextBoxKeyUp(object sender, KeyEventArgs e)
+ {
+ if (e.Key >= Key.LeftShift && e.Key <= Key.RightAlt)
+ return;
+
+ if (_isDisableHotkey)
+ {
+ _profileConfiguration.DisableHotkey ??= new ProfileConfigurationHotkey();
+ _profileConfiguration.DisableHotkey.Key = (KeyboardKey?) e.Key;
+ _profileConfiguration.DisableHotkey.Modifiers = (KeyboardModifierKey?) Keyboard.Modifiers;
+ }
+ else
+ {
+ _profileConfiguration.EnableHotkey ??= new ProfileConfigurationHotkey();
+ _profileConfiguration.EnableHotkey.Key = (KeyboardKey?) e.Key;
+ _profileConfiguration.EnableHotkey.Modifiers = (KeyboardModifierKey?) Keyboard.Modifiers;
+ }
+
+ e.Handled = true;
+ UpdateHotkeyDisplay();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditView.xaml b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditView.xaml
index 9e279ca51..6e3c4939e 100644
--- a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditView.xaml
+++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditView.xaml
@@ -221,16 +221,29 @@
- Keybinds
+ Hotkeys
- You may set up keybinds to activate/deactivate the profile
+ You may set up hotkeys to activate/deactivate the profile
-
-
-
- Keybinds are not yet implemented
-
-
+
+
+
+
diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditViewModel.cs b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditViewModel.cs
index a54e44440..bbfb771cd 100644
--- a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditViewModel.cs
+++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditViewModel.cs
@@ -48,17 +48,23 @@ namespace Artemis.UI.Screens.Sidebar.Dialogs.ProfileEdit
_modules = ProfileConfiguration.Module != null ? new List {ProfileConfiguration.Module} : new List();
IconTypes = new BindableCollection(EnumUtilities.GetAllValuesAndDescriptions(typeof(ProfileConfigurationIconType)));
+ HotkeyModes = new BindableCollection(EnumUtilities.GetAllValuesAndDescriptions(typeof(ProfileConfigurationHotkeyMode)));
Icons = new BindableCollection();
Modules = new BindableCollection(
pluginManagementService.GetFeaturesOfType().Where(m => !m.IsAlwaysAvailable).Select(m => new ProfileModuleViewModel(m))
);
Initializing = true;
+
ActivationConditionViewModel = dataModelConditionsVmFactory.DataModelConditionGroupViewModel(_dataModelConditionGroup, ConditionGroupType.General, _modules);
ActivationConditionViewModel.ConductWith(this);
ActivationConditionViewModel.IsRootGroup = true;
ModuleActivationRequirementsViewModel = new ModuleActivationRequirementsViewModel(sidebarVmFactory);
ModuleActivationRequirementsViewModel.ConductWith(this);
ModuleActivationRequirementsViewModel.SetModule(ProfileConfiguration.Module);
+ EnableHotkeyViewModel = sidebarVmFactory.ProfileConfigurationHotkeyViewModel(ProfileConfiguration, false);
+ EnableHotkeyViewModel.ConductWith(this);
+ DisableHotkeyViewModel = sidebarVmFactory.ProfileConfigurationHotkeyViewModel(ProfileConfiguration, true);
+ DisableHotkeyViewModel.ConductWith(this);
_profileName = ProfileConfiguration.Name;
_selectedModule = Modules.FirstOrDefault(m => m.Module == ProfileConfiguration.Module);
@@ -79,9 +85,15 @@ namespace Artemis.UI.Screens.Sidebar.Dialogs.ProfileEdit
});
}
- public ProfileConfiguration ProfileConfiguration { get; }
+ public DataModelConditionGroupViewModel ActivationConditionViewModel { get; }
+ public ModuleActivationRequirementsViewModel ModuleActivationRequirementsViewModel { get; }
+ public ProfileConfigurationHotkeyViewModel EnableHotkeyViewModel { get; }
+ public ProfileConfigurationHotkeyViewModel DisableHotkeyViewModel { get; }
+
public bool IsNew { get; }
+ public ProfileConfiguration ProfileConfiguration { get; }
public BindableCollection IconTypes { get; }
+ public BindableCollection HotkeyModes { get; }
public BindableCollection Icons { get; }
public BindableCollection Modules { get; }
public bool HasUsableModules => Modules.Any();
@@ -108,6 +120,24 @@ namespace Artemis.UI.Screens.Sidebar.Dialogs.ProfileEdit
}
}
+ public ProfileConfigurationHotkeyMode SelectedHotkeyMode
+ {
+ get => ProfileConfiguration.HotkeyMode;
+ set
+ {
+ ProfileConfiguration.HotkeyMode = value;
+ NotifyOfPropertyChange(nameof(SelectedHotkeyMode));
+ NotifyOfPropertyChange(nameof(ShowEnableHotkey));
+ NotifyOfPropertyChange(nameof(ShowDisableHotkey));
+
+ EnableHotkeyViewModel.UpdateHotkeyDisplay();
+ DisableHotkeyViewModel.UpdateHotkeyDisplay();
+ }
+ }
+
+ public bool ShowEnableHotkey => ProfileConfiguration.HotkeyMode != ProfileConfigurationHotkeyMode.None;
+ public bool ShowDisableHotkey => ProfileConfiguration.HotkeyMode == ProfileConfigurationHotkeyMode.EnableDisable;
+
public Stream SelectedImage
{
get => _selectedImage;
@@ -135,9 +165,6 @@ namespace Artemis.UI.Screens.Sidebar.Dialogs.ProfileEdit
}
}
- public DataModelConditionGroupViewModel ActivationConditionViewModel { get; }
- public ModuleActivationRequirementsViewModel ModuleActivationRequirementsViewModel { get; }
-
public void Delete()
{
Session.Close(nameof(Delete));
@@ -202,6 +229,22 @@ namespace Artemis.UI.Screens.Sidebar.Dialogs.ProfileEdit
_changedImage = true;
SelectedImage = File.OpenRead(dialog.FileName);
}
+
+ #region Overrides of Screen
+
+ protected override void OnInitialActivate()
+ {
+ _profileService.HotkeysEnabled = false;
+ base.OnInitialActivate();
+ }
+
+ protected override void OnClose()
+ {
+ _profileService.HotkeysEnabled = true;
+ base.OnClose();
+ }
+
+ #endregion
}
public class ProfileEditViewModelValidator : AbstractValidator
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs
index a4f85cf19..0a8384003 100644
--- a/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarCategoryViewModel.cs
@@ -200,13 +200,16 @@ namespace Artemis.UI.Screens.Sidebar
private void ProfileCategoryOnProfileConfigurationAdded(object sender, ProfileConfigurationEventArgs e)
{
- if (!_addingProfile && ShowItems)
+ Execute.PostToUIThread(() =>
{
- Items.Add(_vmFactory.SidebarProfileConfigurationViewModel(e.ProfileConfiguration));
- ((BindableCollection) Items).Sort(p => p.ProfileConfiguration.Order);
- }
+ if (!_addingProfile && ShowItems)
+ {
+ Items.Add(_vmFactory.SidebarProfileConfigurationViewModel(e.ProfileConfiguration));
+ ((BindableCollection)Items).Sort(p => p.ProfileConfiguration.Order);
+ }
- SelectedProfileConfiguration = Items.FirstOrDefault(i => i.ProfileConfiguration.IsBeingEdited);
+ SelectedProfileConfiguration = Items.FirstOrDefault(i => i.ProfileConfiguration.IsBeingEdited);
+ });
}
#region Overrides of Screen
diff --git a/src/Artemis.sln.DotSettings b/src/Artemis.sln.DotSettings
index bffc7dc38..c899abc86 100644
--- a/src/Artemis.sln.DotSettings
+++ b/src/Artemis.sln.DotSettings
@@ -241,6 +241,7 @@
True
True
True
+ True
True
True
True