diff --git a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/BooleanActivationRequirement.cs b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/BooleanActivationRequirement.cs
index 2966fc4d0..7a9dddc12 100644
--- a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/BooleanActivationRequirement.cs
+++ b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/BooleanActivationRequirement.cs
@@ -15,5 +15,10 @@
{
return ActivationMet;
}
+
+ public string GetUserFriendlyDescription()
+ {
+ return "No description available";
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/IModuleActivationRequirement.cs b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/IModuleActivationRequirement.cs
index 20a791477..11528beb9 100644
--- a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/IModuleActivationRequirement.cs
+++ b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/IModuleActivationRequirement.cs
@@ -10,5 +10,11 @@
///
///
bool Evaluate();
+
+ ///
+ /// Returns a user-friendly description of the activation requirement, should include parameters if applicable
+ ///
+ /// A user-friendly description of the activation requirement
+ string GetUserFriendlyDescription();
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
index e18212b6d..1c226f1cc 100644
--- a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
+++ b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
@@ -43,5 +43,14 @@ namespace Artemis.Core.Plugins.Modules.ActivationRequirements
? processes.Any(p => string.Equals(Path.GetDirectoryName(p.GetProcessFilename()), Location, StringComparison.CurrentCultureIgnoreCase))
: processes.Any();
}
+
+ public string GetUserFriendlyDescription()
+ {
+ var description = $"Requirement met when \"{ProcessName}.exe\" is running";
+ if (Location != null)
+ description += $" from \"{Location}\"";
+
+ return description;
+ }
}
}
\ 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 8a6135300..2433fc64a 100644
--- a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
+++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
@@ -5,7 +5,9 @@ using Artemis.Core.Models.Profile.LayerProperties.Attributes;
using Artemis.Core.Models.Surface;
using Artemis.Core.Plugins;
using Artemis.Core.Plugins.Modules;
+using Artemis.Core.Plugins.Modules.ActivationRequirements;
using Artemis.UI.Screens.Module;
+using Artemis.UI.Screens.Module.Tabs;
using Artemis.UI.Screens.ProfileEditor;
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
@@ -30,7 +32,10 @@ namespace Artemis.UI.Ninject.Factories
public interface IModuleVmFactory : IVmFactory
{
- ModuleRootViewModel Create(Module module);
+ ModuleRootViewModel CreateModuleRootViewModel(Module module);
+ ProfileEditorViewModel CreateProfileEditorViewModel(ProfileModule module);
+ ActivationRequirementsViewModel CreateActivationRequirementsViewModel(Module module);
+ ActivationRequirementViewModel CreateActivationRequirementViewModel(IModuleActivationRequirement activationRequirement);
}
public interface ISettingsVmFactory : IVmFactory
@@ -43,12 +48,7 @@ namespace Artemis.UI.Ninject.Factories
{
DeviceDebugViewModel Create(ArtemisDevice device);
}
-
- public interface IProfileEditorVmFactory : IVmFactory
- {
- ProfileEditorViewModel Create(ProfileModule module);
- }
-
+
public interface IFolderVmFactory : IVmFactory
{
FolderViewModel Create(ProfileElement folder);
diff --git a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs
index 6125fdac1..286cf7059 100644
--- a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs
@@ -1,9 +1,6 @@
using System.Collections.Generic;
using System.Linq;
-using System.Threading.Tasks;
using Artemis.Core.Plugins.Modules;
-using Artemis.Core.Services;
-using Artemis.Core.Services.Interfaces;
using Artemis.UI.Ninject.Factories;
using Ninject;
using Ninject.Parameters;
@@ -13,17 +10,15 @@ namespace Artemis.UI.Screens.Module
{
public class ModuleRootViewModel : Conductor.Collection.OneActive
{
- private readonly IModuleService _moduleService;
- private readonly IProfileEditorVmFactory _profileEditorVmFactory;
private readonly IKernel _kernel;
+ private readonly IModuleVmFactory _moduleVmFactory;
- public ModuleRootViewModel(Core.Plugins.Modules.Module module, IModuleService moduleService, IProfileEditorVmFactory profileEditorVmFactory, IKernel kernel)
+ public ModuleRootViewModel(Core.Plugins.Modules.Module module, IModuleVmFactory moduleVmFactory, IKernel kernel)
{
DisplayName = module?.DisplayName;
Module = module;
- _moduleService = moduleService;
- _profileEditorVmFactory = profileEditorVmFactory;
+ _moduleVmFactory = moduleVmFactory;
_kernel = kernel;
}
@@ -31,31 +26,18 @@ namespace Artemis.UI.Screens.Module
protected override void OnActivate()
{
- Task.Run(async () =>
- {
- await _moduleService.SetActiveModuleOverride(Module);
- await AddTabsAsync();
- });
+ AddTabs();
base.OnActivate();
}
- protected override void OnDeactivate()
- {
- Task.Run(async () =>
- {
- await _moduleService.SetActiveModuleOverride(null);
- });
- base.OnDeactivate();
- }
-
- private async Task AddTabsAsync()
+ private void AddTabs()
{
// Create the profile editor and module VMs
if (Module is ProfileModule profileModule)
- {
- var profileEditor = _profileEditorVmFactory.Create(profileModule);
- Items.Add(profileEditor);
- }
+ Items.Add(_moduleVmFactory.CreateProfileEditorViewModel(profileModule));
+
+ if (Module.ActivationRequirements.Any())
+ Items.Add(_moduleVmFactory.CreateActivationRequirementsViewModel(Module));
if (Module.ModuleTabs != null)
{
diff --git a/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementView.xaml b/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementView.xaml
new file mode 100644
index 000000000..111376651
--- /dev/null
+++ b/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementView.xaml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementViewModel.cs b/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementViewModel.cs
new file mode 100644
index 000000000..1751c9888
--- /dev/null
+++ b/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementViewModel.cs
@@ -0,0 +1,64 @@
+using System.Timers;
+using Artemis.Core.Plugins.Modules.ActivationRequirements;
+using Humanizer;
+using Stylet;
+
+namespace Artemis.UI.Screens.Module.Tabs
+{
+ public class ActivationRequirementViewModel : Screen
+ {
+ private readonly IModuleActivationRequirement _activationRequirement;
+ private readonly Timer _updateTimer;
+ private string _requirementDescription;
+ private bool _requirementMet;
+
+ public ActivationRequirementViewModel(IModuleActivationRequirement activationRequirement)
+ {
+ _activationRequirement = activationRequirement;
+ _updateTimer = new Timer(500);
+
+ RequirementName = activationRequirement.GetType().Name.Humanize();
+ RequirementDescription = activationRequirement.GetUserFriendlyDescription();
+
+ _updateTimer.Elapsed += UpdateTimerOnElapsed;
+ }
+
+ public string RequirementName { get; }
+
+ public string RequirementDescription
+ {
+ get => _requirementDescription;
+ set => SetAndNotify(ref _requirementDescription, value);
+ }
+
+ public bool RequirementMet
+ {
+ get => _requirementMet;
+ set => SetAndNotify(ref _requirementMet, value);
+ }
+
+ protected override void OnActivate()
+ {
+ Update();
+ _updateTimer.Start();
+ base.OnActivate();
+ }
+
+ protected override void OnDeactivate()
+ {
+ _updateTimer.Stop();
+ base.OnDeactivate();
+ }
+
+ private void UpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
+ {
+ Update();
+ }
+
+ private void Update()
+ {
+ RequirementDescription = _activationRequirement.GetUserFriendlyDescription();
+ RequirementMet = _activationRequirement.Evaluate();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementsView.xaml b/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementsView.xaml
new file mode 100644
index 000000000..6957a31a9
--- /dev/null
+++ b/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementsView.xaml
@@ -0,0 +1,53 @@
+
+
+
+
+ Activation requirements
+
+ This module has built-in activation requirements and won't activate until .
+ These requirements allow the module creator to decide when the module is activated and you cannot override them.
+
+
+
+ Note: While you have the profile editor open the module is always activated and any other modules are deactivated.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementsViewModel.cs b/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementsViewModel.cs
new file mode 100644
index 000000000..d869f9794
--- /dev/null
+++ b/src/Artemis.UI/Screens/Module/Tabs/ActivationRequirementsViewModel.cs
@@ -0,0 +1,36 @@
+using System.Linq;
+using Artemis.Core.Plugins.Modules;
+using Artemis.UI.Ninject.Factories;
+using Stylet;
+
+namespace Artemis.UI.Screens.Module.Tabs
+{
+ public class ActivationRequirementsViewModel : Conductor.Collection.AllActive
+ {
+ private readonly IModuleVmFactory _moduleVmFactory;
+
+ public ActivationRequirementsViewModel(Core.Plugins.Modules.Module module, IModuleVmFactory moduleVmFactory)
+ {
+ _moduleVmFactory = moduleVmFactory;
+
+ DisplayName = "Activation requirements";
+ Module = module;
+
+ ActivationType = Module.ActivationRequirementMode == ActivationRequirementType.All
+ ? "all requirements are met"
+ : "any requirement is met";
+ }
+
+ public Core.Plugins.Modules.Module Module { get; }
+
+ public string ActivationType { get; set; }
+
+ protected override void OnActivate()
+ {
+ if (!Items.Any())
+ Items.AddRange(Module.ActivationRequirements.Select(_moduleVmFactory.CreateActivationRequirementViewModel));
+
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs
index 8ea8c0210..4bf212d0f 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs
@@ -7,6 +7,7 @@ using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Modules;
using Artemis.Core.Plugins.Settings;
using Artemis.Core.Services;
+using Artemis.Core.Services.Interfaces;
using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Screens.ProfileEditor.Dialogs;
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
@@ -24,6 +25,7 @@ namespace Artemis.UI.Screens.ProfileEditor
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileService _profileService;
private readonly ISettingsService _settingsService;
+ private readonly IModuleService _moduleService;
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
private BindableCollection _profiles;
private PluginSetting _sidePanelsWidth;
@@ -42,11 +44,13 @@ namespace Artemis.UI.Screens.ProfileEditor
IProfileService profileService,
IDialogService dialogService,
ISettingsService settingsService,
+ IModuleService moduleService,
ISnackbarMessageQueue snackbarMessageQueue)
{
_profileEditorService = profileEditorService;
_profileService = profileService;
_settingsService = settingsService;
+ _moduleService = moduleService;
_snackbarMessageQueue = snackbarMessageQueue;
DisplayName = "Profile editor";
@@ -233,19 +237,21 @@ namespace Artemis.UI.Screens.ProfileEditor
LoadWorkspaceSettings();
Module.IsProfileUpdatingDisabled = true;
Module.ActiveProfileChanged += ModuleOnActiveProfileChanged;
-
- Execute.PostToUIThread(LoadProfiles);
+ LoadProfiles();
+
+ Task.Run(async () => { await _moduleService.SetActiveModuleOverride(Module); });
base.OnActivate();
}
- protected override void OnClose()
+ protected override void OnDeactivate()
{
SaveWorkspaceSettings();
Module.IsProfileUpdatingDisabled = false;
Module.ActiveProfileChanged -= ModuleOnActiveProfileChanged;
_profileEditorService.ChangeSelectedProfile(null);
- base.OnClose();
+ Task.Run(async () => { await _moduleService.SetActiveModuleOverride(null); });
+ base.OnDeactivate();
}
private void RemoveProfile(ProfileDescriptor profileDescriptor)
@@ -309,19 +315,6 @@ namespace Artemis.UI.Screens.ProfileEditor
// Get all profiles from the database
Profiles.Clear();
Profiles.AddRange(_profileService.GetProfileDescriptors(Module).OrderBy(d => d.Name));
-
- // Populate the selected profile
- var lastActiveProfile = Profiles.FirstOrDefault(p => p.IsLastActiveProfile) ?? Profiles.FirstOrDefault();
- if (lastActiveProfile != null)
- {
- SelectedProfile = lastActiveProfile;
- return;
- }
-
- // Create a default profile if there is none
- var defaultProfile = _profileService.CreateProfileDescriptor(Module, "Default");
- Profiles.Add(defaultProfile);
- SelectedProfile = defaultProfile;
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
index 87d6e5779..7072d7bfe 100644
--- a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
@@ -211,7 +211,7 @@ namespace Artemis.UI.Screens.Sidebar
private void ActivateModule(INavigationItem sidebarItem)
{
- SelectedItem = SidebarModules.ContainsKey(sidebarItem) ? _moduleVmFactory.Create(SidebarModules[sidebarItem]) : null;
+ SelectedItem = SidebarModules.ContainsKey(sidebarItem) ? _moduleVmFactory.CreateModuleRootViewModel(SidebarModules[sidebarItem]) : null;
}
#region Event handlers
diff --git a/src/Plugins/Artemis.Plugins.Modules.Overlay/OverlayModule.cs b/src/Plugins/Artemis.Plugins.Modules.Overlay/OverlayModule.cs
index d079c1626..843f4a3b5 100644
--- a/src/Plugins/Artemis.Plugins.Modules.Overlay/OverlayModule.cs
+++ b/src/Plugins/Artemis.Plugins.Modules.Overlay/OverlayModule.cs
@@ -1,4 +1,6 @@
-using Artemis.Core.Plugins.Modules;
+using System;
+using System.IO;
+using Artemis.Core.Plugins.Modules;
using Artemis.Core.Plugins.Modules.ActivationRequirements;
namespace Artemis.Plugins.Modules.Overlay
@@ -14,6 +16,11 @@ namespace Artemis.Plugins.Modules.Overlay
DefaultPriorityCategory = ModulePriorityCategory.Overlay;
ActivationRequirements.Add(new ProcessActivationRequirement("taskmgr"));
+ ActivationRequirements.Add(new ProcessActivationRequirement("calc"));
+ ActivationRequirements.Add(new ProcessActivationRequirement("mspaint")
+ {
+ Location = Path.Combine(Directory.GetParent(Environment.GetFolderPath(Environment.SpecialFolder.System)).FullName, "System32")
+ });
}
// This is the end of your plugin life cycle.