diff --git a/src/Artemis.Core/Plugins/Settings/PluginSetting.cs b/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
index eb8ec0433..0756412f8 100644
--- a/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
+++ b/src/Artemis.Core/Plugins/Settings/PluginSetting.cs
@@ -11,18 +11,14 @@ namespace Artemis.Core
/// Represents a setting tied to a plugin of type
///
/// The value type of the setting
- public class PluginSetting : CorePropertyChanged
+ public class PluginSetting : CorePropertyChanged, IPluginSetting
{
- // TODO: Why? Should have included that...
- // ReSharper disable once NotAccessedField.Local
- private readonly Plugin _plugin;
private readonly IPluginRepository _pluginRepository;
private readonly PluginSettingEntity _pluginSettingEntity;
private T _value;
- internal PluginSetting(Plugin plugin, IPluginRepository pluginRepository, PluginSettingEntity pluginSettingEntity)
+ internal PluginSetting(IPluginRepository pluginRepository, PluginSettingEntity pluginSettingEntity)
{
- _plugin = plugin;
_pluginRepository = pluginRepository;
_pluginSettingEntity = pluginSettingEntity;
@@ -37,9 +33,7 @@ namespace Artemis.Core
}
}
- ///
- /// The name of the setting, unique to this plugin
- ///
+ ///
public string Name { get; }
///
@@ -63,28 +57,19 @@ namespace Artemis.Core
}
}
- ///
- /// Determines whether the setting has been changed
- ///
+ ///
public bool HasChanged => CoreJson.SerializeObject(Value) != _pluginSettingEntity.Value;
- ///
- /// Gets or sets whether changes must automatically be saved
- /// Note: When set to true is always false
- ///
+ ///
public bool AutoSave { get; set; }
- ///
- /// Resets the setting to the last saved value
- ///
+ ///
public void RejectChanges()
{
Value = CoreJson.DeserializeObject(_pluginSettingEntity.Value);
}
- ///
- /// Saves the setting
- ///
+ ///
public void Save()
{
if (!HasChanged)
@@ -95,14 +80,10 @@ namespace Artemis.Core
OnSettingSaved();
}
- ///
- /// Occurs when the value of the setting has been changed
- ///
+ ///
public event EventHandler? SettingChanged;
- ///
- /// Occurs when the value of the setting has been saved
- ///
+ ///
public event EventHandler? SettingSaved;
///
@@ -127,4 +108,46 @@ namespace Artemis.Core
SettingSaved?.Invoke(this, EventArgs.Empty);
}
}
+
+ ///
+ /// Represents a setting tied to a plugin
+ ///
+ public interface IPluginSetting
+ {
+ ///
+ /// The name of the setting, unique to this plugin
+ ///
+ string Name { get; }
+
+ ///
+ /// Determines whether the setting has been changed
+ ///
+ bool HasChanged { get; }
+
+ ///
+ /// Gets or sets whether changes must automatically be saved
+ /// Note: When set to true is always false
+ ///
+ bool AutoSave { get; set; }
+
+ ///
+ /// Resets the setting to the last saved value
+ ///
+ void RejectChanges();
+
+ ///
+ /// Saves the setting
+ ///
+ void Save();
+
+ ///
+ /// Occurs when the value of the setting has been changed
+ ///
+ event EventHandler? SettingChanged;
+
+ ///
+ /// Occurs when the value of the setting has been saved
+ ///
+ event EventHandler? SettingSaved;
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/Settings/PluginSettings.cs b/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
index 2c22ae42d..5b7a7409b 100644
--- a/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
+++ b/src/Artemis.Core/Plugins/Settings/PluginSettings.cs
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using Artemis.Storage.Entities.Plugins;
using Artemis.Storage.Repositories.Interfaces;
-using Newtonsoft.Json;
namespace Artemis.Core
{
@@ -12,15 +11,15 @@ namespace Artemis.Core
public class PluginSettings
{
private readonly IPluginRepository _pluginRepository;
- private readonly Dictionary _settingEntities;
+ private readonly Dictionary _settingEntities;
internal PluginSettings(Plugin plugin, IPluginRepository pluginRepository)
{
Plugin = plugin;
Plugin.Settings = this;
-
+
_pluginRepository = pluginRepository;
- _settingEntities = new Dictionary();
+ _settingEntities = new Dictionary();
}
///
@@ -49,14 +48,14 @@ namespace Artemis.Core
{
settingEntity = new PluginSettingEntity
{
- Name = name,
- PluginGuid = Plugin.Guid,
+ Name = name,
+ PluginGuid = Plugin.Guid,
Value = CoreJson.SerializeObject(defaultValue)
};
_pluginRepository.AddSetting(settingEntity);
}
- PluginSetting pluginSetting = new(Plugin, _pluginRepository, settingEntity);
+ PluginSetting pluginSetting = new(_pluginRepository, settingEntity);
// This overrides null with the default value, I'm not sure if that's desirable because you
// might expect something to go null and you might not
@@ -68,6 +67,15 @@ namespace Artemis.Core
}
}
+ ///
+ /// Saves all currently loaded settings
+ ///
+ public void SaveAllSettings()
+ {
+ foreach (var (_, pluginSetting) in _settingEntities)
+ pluginSetting.Save();
+ }
+
internal void ClearSettings()
{
_settingEntities.Clear();
diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs
index 40f2c42bd..9dbbea60f 100644
--- a/src/Artemis.Core/Services/RgbService.cs
+++ b/src/Artemis.Core/Services/RgbService.cs
@@ -35,7 +35,7 @@ namespace Artemis.Core.Services
_logger = logger;
_pluginManagementService = pluginManagementService;
_deviceRepository = deviceRepository;
- _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25);
+ _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 30);
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.25);
Surface = new RGBSurface();
diff --git a/src/Artemis.Core/Services/SettingsService.cs b/src/Artemis.Core/Services/SettingsService.cs
index 6dd54a47a..e2c9fb08e 100644
--- a/src/Artemis.Core/Services/SettingsService.cs
+++ b/src/Artemis.Core/Services/SettingsService.cs
@@ -16,6 +16,12 @@ namespace Artemis.Core.Services
{
return _pluginSettings.GetSetting(name, defaultValue);
}
+
+ ///
+ public void SaveAllSettings()
+ {
+ _pluginSettings.SaveAllSettings();
+ }
}
///
@@ -32,5 +38,10 @@ namespace Artemis.Core.Services
/// The default value to use if the setting does not exist yet
///
PluginSetting GetSetting(string name, T? defaultValue = default);
+
+ ///
+ /// Saves all settings, obviously
+ ///
+ void SaveAllSettings();
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Converters/NormalizedPercentageConverter.cs b/src/Artemis.UI/Converters/NormalizedPercentageConverter.cs
new file mode 100644
index 000000000..06cc0853c
--- /dev/null
+++ b/src/Artemis.UI/Converters/NormalizedPercentageConverter.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace Artemis.UI.Converters
+{
+ [ValueConversion(typeof(double), typeof(double))]
+ public class NormalizedPercentageConverter : IValueConverter
+ {
+ #region IValueConverter Members
+
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is double number)
+ return number * 100.0;
+
+ return value;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is double number)
+ return number / 100.0;
+
+ return value;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Events/WindowsThemeEventArgs.cs b/src/Artemis.UI/Events/WindowsThemeEventArgs.cs
index 54310f545..03fd30e14 100644
--- a/src/Artemis.UI/Events/WindowsThemeEventArgs.cs
+++ b/src/Artemis.UI/Events/WindowsThemeEventArgs.cs
@@ -1,15 +1,16 @@
using System;
+using Artemis.UI.Services;
using Artemis.UI.Utilities;
namespace Artemis.UI.Events
{
public class WindowsThemeEventArgs : EventArgs
{
- public WindowsThemeEventArgs(ThemeWatcher.WindowsTheme theme)
+ public WindowsThemeEventArgs(IThemeService.WindowsTheme theme)
{
Theme = theme;
}
- public ThemeWatcher.WindowsTheme Theme { get; set; }
+ public IThemeService.WindowsTheme Theme { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Providers/ToastNotificationProvider.cs b/src/Artemis.UI/Providers/ToastNotificationProvider.cs
index 53e8d5d25..a5b27ac85 100644
--- a/src/Artemis.UI/Providers/ToastNotificationProvider.cs
+++ b/src/Artemis.UI/Providers/ToastNotificationProvider.cs
@@ -4,8 +4,8 @@ using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Windows.UI.Notifications;
+using Artemis.UI.Services;
using Artemis.UI.Shared.Services;
-using Artemis.UI.Utilities;
using MaterialDesignThemes.Wpf;
using Microsoft.Toolkit.Uwp.Notifications;
using Stylet;
@@ -14,11 +14,11 @@ namespace Artemis.UI.Providers
{
public class ToastNotificationProvider : INotificationProvider
{
- private ThemeWatcher _themeWatcher;
+ private readonly IThemeService _themeService;
- public ToastNotificationProvider()
+ public ToastNotificationProvider(IThemeService themeService)
{
- _themeWatcher = new ThemeWatcher();
+ _themeService = themeService;
}
public static PngBitmapEncoder GetEncoderForIcon(PackIconKind icon, Color color)
@@ -71,7 +71,7 @@ namespace Artemis.UI.Providers
Execute.OnUIThreadSync(() =>
{
using FileStream stream = File.OpenWrite(imagePath);
- GetEncoderForIcon(icon, _themeWatcher.GetSystemTheme() == ThemeWatcher.WindowsTheme.Dark ? Colors.White : Colors.Black).Save(stream);
+ GetEncoderForIcon(icon, _themeService.GetSystemTheme() == IThemeService.WindowsTheme.Dark ? Colors.White : Colors.Black).Save(stream);
});
new ToastContentBuilder()
@@ -88,14 +88,10 @@ namespace Artemis.UI.Providers
#endregion
- #region IDisposable
-
///
public void Dispose()
{
ToastNotificationManagerCompat.Uninstall();
}
-
- #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
index 95af67ace..4c506471b 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
@@ -512,7 +512,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
if (SelectedProfileElement == null)
return;
- double frameTime = 1000.0 / SettingsService.GetSetting("Core.TargetFrameRate", 25).Value;
+ double frameTime = 1000.0 / SettingsService.GetSetting("Core.TargetFrameRate", 30).Value;
double newTime = Math.Max(0, Math.Round((ProfileEditorService.CurrentTime.TotalMilliseconds - frameTime) / frameTime) * frameTime);
ProfileEditorService.CurrentTime = TimeSpan.FromMilliseconds(newTime);
}
@@ -522,7 +522,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
if (SelectedProfileElement == null)
return;
- double frameTime = 1000.0 / SettingsService.GetSetting("Core.TargetFrameRate", 25).Value;
+ double frameTime = 1000.0 / SettingsService.GetSetting("Core.TargetFrameRate", 30).Value;
double newTime = Math.Round((ProfileEditorService.CurrentTime.TotalMilliseconds + frameTime) / frameTime) * frameTime;
newTime = Math.Min(newTime, SelectedProfileElement.Timeline.EndSegmentEndPosition.TotalMilliseconds);
ProfileEditorService.CurrentTime = TimeSpan.FromMilliseconds(newTime);
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml
index 95be11f8b..28afdf8ec 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml
@@ -1,27 +1,32 @@
-
+
+
+
- General
+
+
+
@@ -37,7 +42,7 @@
Start up with Windows
-
+
@@ -55,7 +60,9 @@
Start up with Windows minimized
-
+
@@ -72,14 +79,14 @@
Startup delay
- Set the amount of seconds to wait before running Artemis with Windows.
- If some devices don't work because Artemis starts before the manufacturer's software, try increasing this value.
+
+
@@ -105,7 +112,7 @@
- Log level
+
+ Log level
+
Sets the logging level, a higher logging level will result in more log files.
@@ -132,7 +141,7 @@
- Logs
+
+ Logs
+
Opens the directory where logs are stored.
-
+
- Web server
+
+ Web server
+
@@ -179,14 +190,18 @@
- Web server port
+
+ Web server port
+
- Artemis runs a local web server that can be used to externally interact with the application.
- This web server can only be accessed by applications running on your own computer, e.g. supported games.
+
+
-
@@ -194,7 +209,9 @@
- Updating
+
+
+
@@ -207,13 +224,15 @@
- Check for updates
+
+ Check for updates
+
If enabled, we'll check for updates on startup and periodically while running.
-
+
@@ -228,22 +247,24 @@
- Update
+
+ Update
+
Use the button on the right to check for updates now.
-
+
- Profile editor
+
+
+
@@ -256,16 +277,17 @@
- Show condition data model values
+
+ Show condition data model values
+
- While selecting a condition target, show the current values of the data model
+ While selecting a condition target, show the current values of the data model.
-
+
-
@@ -278,7 +300,9 @@
- Default brush
+
+ Default brush
+
Sets the default brush that is applied to new layers
@@ -290,18 +314,18 @@
materialDesign:ValidationAssist.UsePopup="True"
materialDesign:HintAssist.IsFloating="false"
HorizontalAlignment="Left"
- ItemsSource="{Binding Path=LayerBrushDescriptors}"
- SelectedValue="{Binding Path=SelectedLayerBrushDescriptor}"
- ItemTemplateSelector="{dataTemplateSelectors:ComboBoxTemplateSelector
- SelectedItemTemplate={StaticResource SimpleLayerBrushDescriptorTemplate},
- DropdownItemsTemplate={StaticResource ExtendedLayerBrushDescriptorTemplate}}" />
+ ItemsSource="{Binding LayerBrushDescriptors}"
+ SelectedValue="{Binding SelectedLayerBrushDescriptor}"
+ ItemTemplateSelector="{dataTemplateSelectors:ComboBoxTemplateSelector DropdownItemsTemplate={StaticResource ExtendedLayerBrushDescriptorTemplate}, SelectedItemTemplate={StaticResource SimpleLayerBrushDescriptorTemplate}}" />
- Rendering
+
+ Rendering
+
@@ -314,15 +338,17 @@
- Preferred render method
+
+ Preferred render method
+
- Software-based rendering is done purely on the CPU while Vulkan uses GPU-acceleration
+ Software-based rendering is done purely on the CPU while Vulkan uses GPU-acceleration.
Software
Vulkan
@@ -341,7 +367,9 @@
- Render scale
+
+ Render scale
+
Sets the resolution Artemis renders at, higher scale means more CPU-usage, especially on large surfaces.
@@ -367,9 +395,12 @@
- Target framerate
+
+ Target frame rate
+
- Sets the FPS Artemis tries to render at, higher FPS means more CPU-usage but smoother animations.
+ Sets the FPS Artemis tries to render at, higher FPS means more CPU-usage but smoother animations.
+ The options past 45 FPS are mostly useless unless you are using a custom device.
@@ -386,7 +417,9 @@
- Tools
+
+ Tools
+
@@ -399,15 +432,15 @@
- Setup wizard
+
+
+
- Opens the startup wizard usually shown when Artemis first starts.
+
-
+
@@ -422,15 +455,15 @@
- Debugger
+
+ Debugger
+
Use the debugger to see the raw image Artemis is rendering on the surface.
-
+
@@ -445,15 +478,15 @@
- Application files
+
+ Application files
+
Opens the directory where application files like plugins and settings are stored.
-
+
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
index 7eb659f62..3aaac1fae 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
@@ -30,8 +30,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
private readonly IUpdateService _updateService;
private readonly IWindowManager _windowManager;
private bool _canOfferUpdatesIfFound = true;
- private List> _renderScales;
- private List> _targetFrameRates;
public GeneralSettingsTabViewModel(
IKernel kernel,
@@ -41,9 +39,8 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
ISettingsService settingsService,
IUpdateService updateService,
IPluginManagementService pluginManagementService,
- IMessageService messageService,
IRegistrationService registrationService,
- ICoreService coreService
+ IMessageService messageService
)
{
DisplayName = "GENERAL";
@@ -54,38 +51,34 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
_debugService = debugService;
_settingsService = settingsService;
_updateService = updateService;
- _messageService = messageService;
_registrationService = registrationService;
+ _messageService = messageService;
LogLevels = new BindableCollection(EnumUtilities.GetAllValuesAndDescriptions(typeof(LogEventLevel)));
ColorSchemes = new BindableCollection(EnumUtilities.GetAllValuesAndDescriptions(typeof(ApplicationColorScheme)));
- RenderScales = new List>
+ RenderScales = new BindableCollection>
{
new("25%", 0.25),
new("50%", 0.5),
- new("100%", 1),
+ new("100%", 1)
+ };
+ TargetFrameRates = new BindableCollection>
+ {
+ new("10 FPS", 10),
+ new("20 FPS", 20),
+ new("30 FPS", 30),
+ new("45 FPS", 45),
+ new("60 FPS (lol)", 60),
+ new("144 FPS (omegalol)", 144)
};
- TargetFrameRates = new List>();
- for (int i = 10; i <= 30; i += 5)
- TargetFrameRates.Add(new Tuple(i + " FPS", i));
- if (coreService.StartupArguments.Contains("--pcmr"))
- {
- TargetFrameRates.Add(new Tuple("60 FPS (lol)", 60));
- TargetFrameRates.Add(new Tuple("144 FPS (omegalol)", 144));
- }
-
List layerBrushProviders = pluginManagementService.GetFeaturesOfType();
-
LayerBrushDescriptors = new BindableCollection(layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors));
_defaultLayerBrushDescriptor = _settingsService.GetSetting("ProfileEditor.DefaultLayerBrushDescriptor", new LayerBrushReference
{
LayerBrushProviderId = "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba",
BrushType = "SolidBrush"
});
-
- WebServerPortSetting = _settingsService.GetSetting("WebServer.Port", 9696);
- WebServerPortSetting.AutoSave = true;
}
public BindableCollection LayerBrushDescriptors { get; }
@@ -93,148 +86,87 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
public LayerBrushDescriptor SelectedLayerBrushDescriptor
{
get => LayerBrushDescriptors.FirstOrDefault(d => d.MatchesLayerBrushReference(_defaultLayerBrushDescriptor.Value));
- set
- {
- _defaultLayerBrushDescriptor.Value = new LayerBrushReference(value);
- _defaultLayerBrushDescriptor.Save();
- }
+ set => _defaultLayerBrushDescriptor.Value = new LayerBrushReference(value);
}
public BindableCollection LogLevels { get; }
public BindableCollection ColorSchemes { get; }
-
- public List> TargetFrameRates
- {
- get => _targetFrameRates;
- set => SetAndNotify(ref _targetFrameRates, value);
- }
-
- public List> RenderScales
- {
- get => _renderScales;
- set => SetAndNotify(ref _renderScales, value);
- }
-
- public bool StartWithWindows
- {
- get => _settingsService.GetSetting("UI.AutoRun", false).Value;
- set
- {
- _settingsService.GetSetting("UI.AutoRun", false).Value = value;
- _settingsService.GetSetting("UI.AutoRun", false).Save();
- NotifyOfPropertyChange(nameof(StartWithWindows));
- Task.Run(() => ApplyAutorun(false));
- }
- }
-
- public int AutoRunDelay
- {
- get => _settingsService.GetSetting("UI.AutoRunDelay", 15).Value;
- set
- {
- _settingsService.GetSetting("UI.AutoRunDelay", 15).Value = value;
- _settingsService.GetSetting("UI.AutoRunDelay", 15).Save();
- NotifyOfPropertyChange(nameof(AutoRunDelay));
- Task.Run(() => ApplyAutorun(true));
- }
- }
-
- public bool StartMinimized
- {
- get => !_settingsService.GetSetting("UI.ShowOnStartup", true).Value;
- set
- {
- _settingsService.GetSetting("UI.ShowOnStartup", true).Value = !value;
- _settingsService.GetSetting("UI.ShowOnStartup", true).Save();
- NotifyOfPropertyChange(nameof(StartMinimized));
- }
- }
-
- public bool CheckForUpdates
- {
- get => _settingsService.GetSetting("UI.CheckForUpdates", true).Value;
- set
- {
- _settingsService.GetSetting("UI.CheckForUpdates", true).Value = value;
- _settingsService.GetSetting("UI.CheckForUpdates", true).Save();
- NotifyOfPropertyChange(nameof(CheckForUpdates));
- }
- }
-
- public bool ShowDataModelValues
- {
- get => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false).Value;
- set
- {
- _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false).Value = value;
- _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false).Save();
- }
- }
+ public BindableCollection> RenderScales { get; }
+ public BindableCollection> TargetFrameRates { get; }
public Tuple SelectedRenderScale
{
- get => RenderScales.FirstOrDefault(s => Math.Abs(s.Item2 - RenderScale) < 0.01);
- set => RenderScale = value.Item2;
+ get => RenderScales.FirstOrDefault(s => Math.Abs(s.Item2 - CoreRenderScale.Value) < 0.01);
+ set => CoreRenderScale.Value = value.Item2;
}
public Tuple SelectedTargetFrameRate
{
- get => TargetFrameRates.FirstOrDefault(t => Math.Abs(t.Item2 - TargetFrameRate) < 0.01);
- set => TargetFrameRate = value.Item2;
+ get => TargetFrameRates.FirstOrDefault(s => s.Item2 == CoreTargetFrameRate.Value);
+ set => CoreTargetFrameRate.Value = value.Item2;
}
- public LogEventLevel SelectedLogLevel
+ public PluginSetting UIAutoRun => _settingsService.GetSetting("UI.AutoRun", false);
+ public PluginSetting UIAutoRunDelay => _settingsService.GetSetting("UI.AutoRunDelay", 15);
+ public PluginSetting UIShowOnStartup => _settingsService.GetSetting("UI.ShowOnStartup", true);
+ public PluginSetting UICheckForUpdates => _settingsService.GetSetting("UI.CheckForUpdates", true);
+ public PluginSetting UIColorScheme => _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
+ public PluginSetting ProfileEditorShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
+ public PluginSetting CoreLoggingLevel => _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information);
+ public PluginSetting CorePreferredGraphicsContext => _settingsService.GetSetting("Core.PreferredGraphicsContext", "Vulkan");
+ public PluginSetting CoreRenderScale => _settingsService.GetSetting("Core.RenderScale", 0.25);
+ public PluginSetting CoreTargetFrameRate => _settingsService.GetSetting("Core.TargetFrameRate", 30);
+ public PluginSetting WebServerPort => _settingsService.GetSetting("WebServer.Port", 9696);
+
+ private void UIAutoRunOnSettingChanged(object sender, EventArgs e)
{
- get => _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information).Value;
- set
+ Task.Run(() => ApplyAutorun(false));
+ }
+
+ private void UIAutoRunDelayOnSettingChanged(object sender, EventArgs e)
+ {
+ Task.Run(() => ApplyAutorun(true));
+ }
+
+ private void CorePreferredGraphicsContextOnSettingChanged(object sender, EventArgs e)
+ {
+ _registrationService.ApplyPreferredGraphicsContext();
+ }
+
+
+ private void ApplyAutorun(bool recreate)
+ {
+ if (!UIAutoRun.Value)
+ UIShowOnStartup.Value = true;
+
+ // Remove the old auto-run method of placing a shortcut in shell:startup
+ string autoRunFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), "Artemis.lnk");
+ if (File.Exists(autoRunFile))
+ File.Delete(autoRunFile);
+
+ if (Constants.BuildInfo.IsLocalBuild)
+ return;
+
+ // Create or remove the task if necessary
+ try
{
- _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information).Value = value;
- _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information).Save();
+ bool taskCreated = false;
+ if (!recreate)
+ taskCreated = SettingsUtilities.IsAutoRunTaskCreated();
+
+ if (UIAutoRun.Value && !taskCreated)
+ SettingsUtilities.CreateAutoRunTask(TimeSpan.FromSeconds(UIAutoRunDelay.Value));
+ else if (!UIAutoRun.Value && taskCreated)
+ SettingsUtilities.RemoveAutoRunTask();
+ }
+ catch (Exception e)
+ {
+ Execute.PostToUIThread(() => _dialogService.ShowExceptionDialog("An exception occured while trying to apply the auto run setting", e));
+ throw;
}
}
- public ApplicationColorScheme SelectedColorScheme
- {
- get => _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic).Value;
- set
- {
- _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic).Value = value;
- _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic).Save();
- }
- }
-
- public string PreferredGraphicsContext
- {
- get => _settingsService.GetSetting("Core.PreferredGraphicsContext", "Vulkan").Value;
- set
- {
- _settingsService.GetSetting("Core.PreferredGraphicsContext", "Vulkan").Value = value;
- _settingsService.GetSetting("Core.PreferredGraphicsContext", "Vulkan").Save();
- _registrationService.ApplyPreferredGraphicsContext();
- }
- }
-
- public double RenderScale
- {
- get => _settingsService.GetSetting("Core.RenderScale", 0.25).Value;
- set
- {
- _settingsService.GetSetting("Core.RenderScale", 0.25).Value = value;
- _settingsService.GetSetting("Core.RenderScale", 0.25).Save();
- }
- }
-
- public int TargetFrameRate
- {
- get => _settingsService.GetSetting("Core.TargetFrameRate", 25).Value;
- set
- {
- _settingsService.GetSetting("Core.TargetFrameRate", 25).Value = value;
- _settingsService.GetSetting("Core.TargetFrameRate", 25).Save();
- }
- }
-
- public PluginSetting WebServerPortSetting { get; }
+ #region View methods
public bool CanOfferUpdatesIfFound
{
@@ -298,44 +230,32 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
}
}
+ #endregion
+
+ #region Overrides of Screen
+
protected override void OnInitialActivate()
{
Task.Run(() => ApplyAutorun(false));
+
+ UIAutoRun.SettingChanged += UIAutoRunOnSettingChanged;
+ UIAutoRunDelay.SettingChanged += UIAutoRunDelayOnSettingChanged;
+ CorePreferredGraphicsContext.SettingChanged += CorePreferredGraphicsContextOnSettingChanged;
base.OnInitialActivate();
}
- private void ApplyAutorun(bool recreate)
+ protected override void OnClose()
{
- if (!StartWithWindows)
- StartMinimized = false;
+ UIAutoRun.SettingChanged -= UIAutoRunOnSettingChanged;
+ UIAutoRunDelay.SettingChanged -= UIAutoRunDelayOnSettingChanged;
+ CorePreferredGraphicsContext.SettingChanged -= CorePreferredGraphicsContextOnSettingChanged;
- // Remove the old auto-run method of placing a shortcut in shell:startup
- string autoRunFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), "Artemis.lnk");
- if (File.Exists(autoRunFile))
- File.Delete(autoRunFile);
-
- if (Constants.BuildInfo.IsLocalBuild)
- return;
-
- // Create or remove the task if necessary
- try
- {
- bool taskCreated = false;
- if (!recreate) taskCreated = SettingsUtilities.IsAutoRunTaskCreated();
-
- if (StartWithWindows && !taskCreated)
- SettingsUtilities.CreateAutoRunTask(TimeSpan.FromSeconds(AutoRunDelay));
- else if (!StartWithWindows && taskCreated)
- SettingsUtilities.RemoveAutoRunTask();
- }
- catch (Exception e)
- {
- Execute.PostToUIThread(() => _dialogService.ShowExceptionDialog("An exception occured while trying to apply the auto run setting", e));
- throw;
- }
+ _settingsService.SaveAllSettings();
+ base.OnClose();
}
- }
+ #endregion
+ }
public enum ApplicationColorScheme
{
diff --git a/src/Artemis.UI/Screens/TrayViewModel.cs b/src/Artemis.UI/Screens/TrayViewModel.cs
index 5bd8915d7..eb880f012 100644
--- a/src/Artemis.UI/Screens/TrayViewModel.cs
+++ b/src/Artemis.UI/Screens/TrayViewModel.cs
@@ -4,16 +4,12 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
-using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Events;
-using Artemis.UI.Screens.Settings.Tabs.General;
using Artemis.UI.Screens.Splash;
using Artemis.UI.Services;
using Artemis.UI.Shared.Services;
-using Artemis.UI.Utilities;
using Hardcodet.Wpf.TaskbarNotification;
-using MaterialDesignThemes.Wpf;
using Ninject;
using Stylet;
@@ -21,11 +17,10 @@ namespace Artemis.UI.Screens
{
public class TrayViewModel : Screen, IMainWindowProvider
{
- private readonly PluginSetting _colorScheme;
private readonly IDebugService _debugService;
private readonly IEventAggregator _eventAggregator;
private readonly IKernel _kernel;
- private readonly ThemeWatcher _themeWatcher;
+ private readonly IThemeService _themeService;
private readonly IWindowManager _windowManager;
private ImageSource _icon;
private bool _openingMainWindow;
@@ -40,24 +35,20 @@ namespace Artemis.UI.Screens
IEventAggregator eventAggregator,
ICoreService coreService,
IDebugService debugService,
- ISettingsService settingsService)
+ ISettingsService settingsService,
+ IThemeService themeService)
{
_kernel = kernel;
_windowManager = windowManager;
_eventAggregator = eventAggregator;
_debugService = debugService;
+ _themeService = themeService;
Core.Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
Core.Utilities.RestartRequested += UtilitiesOnShutdownRequested;
- _themeWatcher = new ThemeWatcher();
- _colorScheme = settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
- _colorScheme.SettingChanged += ColorSchemeOnSettingChanged;
- _themeWatcher.SystemThemeChanged += _themeWatcher_SystemThemeChanged;
- _themeWatcher.AppsThemeChanged += _themeWatcher_AppsThemeChanged;
-
- ApplyColorSchemeSetting();
- ApplyTrayIconTheme(_themeWatcher.GetSystemTheme());
+ _themeService.SystemThemeChanged += ThemeServiceOnSystemThemeChanged;
+ ApplyTrayIconTheme(_themeService.GetSystemTheme());
windowService.ConfigureMainWindowProvider(this);
bool autoRunning = Bootstrapper.StartupArguments.Contains("--autorun");
@@ -191,60 +182,21 @@ namespace Artemis.UI.Screens
#region Theme
- private void ApplyColorSchemeSetting()
- {
- if (_colorScheme.Value == ApplicationColorScheme.Automatic)
- ApplyUITheme(_themeWatcher.GetAppsTheme());
- else
- ChangeMaterialColors(_colorScheme.Value);
- }
-
- private void ApplyUITheme(ThemeWatcher.WindowsTheme theme)
- {
- if (_colorScheme.Value != ApplicationColorScheme.Automatic)
- return;
- if (theme == ThemeWatcher.WindowsTheme.Dark)
- ChangeMaterialColors(ApplicationColorScheme.Dark);
- else
- ChangeMaterialColors(ApplicationColorScheme.Light);
- }
-
- private void ApplyTrayIconTheme(ThemeWatcher.WindowsTheme theme)
+ private void ApplyTrayIconTheme(IThemeService.WindowsTheme theme)
{
Execute.PostToUIThread(() =>
{
- Icon = theme == ThemeWatcher.WindowsTheme.Dark
+ Icon = theme == IThemeService.WindowsTheme.Dark
? new BitmapImage(new Uri("pack://application:,,,/Artemis.UI;component/Resources/Images/Logo/bow-white.ico"))
: new BitmapImage(new Uri("pack://application:,,,/Artemis.UI;component/Resources/Images/Logo/bow-black.ico"));
});
}
- private void ChangeMaterialColors(ApplicationColorScheme colorScheme)
- {
- PaletteHelper paletteHelper = new();
- ITheme theme = paletteHelper.GetTheme();
- theme.SetBaseTheme(colorScheme == ApplicationColorScheme.Dark ? Theme.Dark : Theme.Light);
- paletteHelper.SetTheme(theme);
-
- MaterialDesignExtensions.Themes.PaletteHelper extensionsPaletteHelper = new();
- extensionsPaletteHelper.SetLightDark(colorScheme == ApplicationColorScheme.Dark);
- }
-
- private void _themeWatcher_AppsThemeChanged(object sender, WindowsThemeEventArgs e)
- {
- ApplyUITheme(e.Theme);
- }
-
- private void _themeWatcher_SystemThemeChanged(object sender, WindowsThemeEventArgs e)
+ private void ThemeServiceOnSystemThemeChanged(object sender, WindowsThemeEventArgs e)
{
ApplyTrayIconTheme(e.Theme);
}
- private void ColorSchemeOnSettingChanged(object sender, EventArgs e)
- {
- ApplyColorSchemeSetting();
- }
-
#endregion
#region Implementation of IMainWindowProvider
diff --git a/src/Artemis.UI/Services/RegistrationService.cs b/src/Artemis.UI/Services/RegistrationService.cs
index 563908898..e2e82628f 100644
--- a/src/Artemis.UI/Services/RegistrationService.cs
+++ b/src/Artemis.UI/Services/RegistrationService.cs
@@ -26,6 +26,7 @@ namespace Artemis.UI.Services
private readonly IWebServerService _webServerService;
private readonly IRgbService _rgbService;
private readonly ISettingsService _settingsService;
+ private readonly IThemeService _themeService;
private bool _registeredBuiltInDataModelDisplays;
private bool _registeredBuiltInDataModelInputs;
private bool _registeredBuiltInPropertyEditors;
@@ -40,7 +41,8 @@ namespace Artemis.UI.Services
IMessageService messageService,
IWebServerService webServerService,
IRgbService rgbService,
- ISettingsService settingsService)
+ ISettingsService settingsService,
+ IThemeService themeService)
{
_logger = logger;
_coreService = coreService;
@@ -52,6 +54,7 @@ namespace Artemis.UI.Services
_webServerService = webServerService;
_rgbService = rgbService;
_settingsService = settingsService;
+ _themeService = themeService;
LoadPluginModules();
pluginManagementService.PluginEnabling += PluginServiceOnPluginEnabling;
@@ -105,7 +108,7 @@ namespace Artemis.UI.Services
public void RegisterProviders()
{
_inputService.AddInputProvider(new NativeWindowInputProvider(_logger, _inputService));
- _messageService.SetNotificationProvider(new ToastNotificationProvider());
+ _messageService.SetNotificationProvider(new ToastNotificationProvider(_themeService));
}
public void RegisterControllers()
diff --git a/src/Artemis.UI/Services/ThemeService.cs b/src/Artemis.UI/Services/ThemeService.cs
new file mode 100644
index 000000000..e07c70eb7
--- /dev/null
+++ b/src/Artemis.UI/Services/ThemeService.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Globalization;
+using System.Management;
+using System.Security.Principal;
+using Artemis.Core;
+using Artemis.Core.Services;
+using Artemis.UI.Events;
+using Artemis.UI.Screens.Settings.Tabs.General;
+using MaterialDesignThemes.Wpf;
+using Microsoft.Win32;
+
+namespace Artemis.UI.Services
+{
+ public class ThemeService : IThemeService
+ {
+ private readonly PluginSetting _colorScheme;
+ private const string RegistryKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
+
+ private const string AppsThemeRegistryValueName = "AppsUseLightTheme";
+ private const string SystemThemeRegistryValueName = "SystemUsesLightTheme";
+
+ public ThemeService(ISettingsService settingsService)
+ {
+ WatchTheme();
+
+ _colorScheme = settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
+ _colorScheme.SettingChanged += ColorSchemeOnSettingChanged;
+
+ ApplyColorSchemeSetting();
+ AppsThemeChanged += OnAppsThemeChanged;
+ }
+
+ public IThemeService.WindowsTheme GetAppsTheme()
+ {
+ return GetTheme(AppsThemeRegistryValueName);
+ }
+
+ public IThemeService.WindowsTheme GetSystemTheme()
+ {
+ return GetTheme(SystemThemeRegistryValueName);
+ }
+
+ private void ApplyColorSchemeSetting()
+ {
+ if (_colorScheme.Value == ApplicationColorScheme.Automatic)
+ ApplyUITheme(GetAppsTheme());
+ else
+ ChangeMaterialColors(_colorScheme.Value);
+ }
+
+ private void ChangeMaterialColors(ApplicationColorScheme colorScheme)
+ {
+ PaletteHelper paletteHelper = new();
+ ITheme theme = paletteHelper.GetTheme();
+ theme.SetBaseTheme(colorScheme == ApplicationColorScheme.Dark ? Theme.Dark : Theme.Light);
+ paletteHelper.SetTheme(theme);
+
+ MaterialDesignExtensions.Themes.PaletteHelper extensionsPaletteHelper = new();
+ extensionsPaletteHelper.SetLightDark(colorScheme == ApplicationColorScheme.Dark);
+ }
+
+ private void ApplyUITheme(IThemeService.WindowsTheme theme)
+ {
+ if (_colorScheme.Value != ApplicationColorScheme.Automatic)
+ return;
+ if (theme == IThemeService.WindowsTheme.Dark)
+ ChangeMaterialColors(ApplicationColorScheme.Dark);
+ else
+ ChangeMaterialColors(ApplicationColorScheme.Light);
+ }
+
+ private void WatchTheme()
+ {
+ WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
+ string appsThemequery = string.Format(
+ CultureInfo.InvariantCulture,
+ @"SELECT * FROM RegistryValueChangeEvent WHERE Hive = 'HKEY_USERS' AND KeyPath = '{0}\\{1}' AND ValueName = '{2}'",
+ currentUser.User.Value,
+ RegistryKeyPath.Replace(@"\", @"\\"),
+ AppsThemeRegistryValueName);
+
+ string systemThemequery = string.Format(
+ CultureInfo.InvariantCulture,
+ @"SELECT * FROM RegistryValueChangeEvent WHERE Hive = 'HKEY_USERS' AND KeyPath = '{0}\\{1}' AND ValueName = '{2}'",
+ currentUser.User.Value,
+ RegistryKeyPath.Replace(@"\", @"\\"),
+ SystemThemeRegistryValueName);
+
+ try
+ {
+ // For Apps theme
+ ManagementEventWatcher appsThemWatcher = new(appsThemequery);
+ appsThemWatcher.EventArrived += (_, _) =>
+ {
+ IThemeService.WindowsTheme newWindowsTheme = GetAppsTheme();
+ OnAppsThemeChanged(new WindowsThemeEventArgs(newWindowsTheme));
+ };
+
+ // Start listening for apps theme events
+ appsThemWatcher.Start();
+
+
+ // For System theme
+ ManagementEventWatcher systemThemWatcher = new(systemThemequery);
+ systemThemWatcher.EventArrived += (_, _) =>
+ {
+ IThemeService.WindowsTheme newWindowsTheme = GetSystemTheme();
+ OnSystemThemeChanged(new WindowsThemeEventArgs(newWindowsTheme));
+ };
+
+ // Start listening for system theme events
+ systemThemWatcher.Start();
+ }
+ catch (Exception)
+ {
+ // This can fail on Windows 7
+ }
+ }
+
+ private IThemeService.WindowsTheme GetTheme(string themeKeyName)
+ {
+ using RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistryKeyPath);
+ object registryValueObject = key?.GetValue(themeKeyName);
+ if (registryValueObject == null) return IThemeService.WindowsTheme.Light;
+
+ int registryValue = (int) registryValueObject;
+
+ return registryValue > 0 ? IThemeService.WindowsTheme.Light : IThemeService.WindowsTheme.Dark;
+ }
+
+ #region Events
+
+ public event EventHandler AppsThemeChanged;
+ public event EventHandler SystemThemeChanged;
+
+ protected virtual void OnAppsThemeChanged(WindowsThemeEventArgs e)
+ {
+ AppsThemeChanged?.Invoke(this, e);
+ }
+
+ protected virtual void OnSystemThemeChanged(WindowsThemeEventArgs e)
+ {
+ SystemThemeChanged?.Invoke(this, e);
+ }
+
+ #endregion
+
+ #region Event handlers
+
+ private void ColorSchemeOnSettingChanged(object sender, EventArgs e)
+ {
+ ApplyColorSchemeSetting();
+ }
+
+ private void OnAppsThemeChanged(object sender, WindowsThemeEventArgs e)
+ {
+ ApplyUITheme(e.Theme);
+ }
+
+ #endregion
+ }
+
+ public interface IThemeService : IArtemisUIService
+ {
+ WindowsTheme GetAppsTheme();
+ WindowsTheme GetSystemTheme();
+ event EventHandler AppsThemeChanged;
+ event EventHandler SystemThemeChanged;
+
+ enum WindowsTheme
+ {
+ Light,
+ Dark
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Utilities/ThemeWatcher.cs b/src/Artemis.UI/Utilities/ThemeWatcher.cs
deleted file mode 100644
index cc0989ad5..000000000
--- a/src/Artemis.UI/Utilities/ThemeWatcher.cs
+++ /dev/null
@@ -1,112 +0,0 @@
-using System;
-using System.Globalization;
-using System.Management;
-using System.Security.Principal;
-using Artemis.UI.Events;
-using Microsoft.Win32;
-
-namespace Artemis.UI.Utilities
-{
- public class ThemeWatcher
- {
- private const string RegistryKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
-
- private const string appsThemeRegistryValueName = "AppsUseLightTheme";
- private const string systemThemeRegistryValueName = "SystemUsesLightTheme";
-
- public ThemeWatcher()
- {
- WatchTheme();
- }
-
- public void WatchTheme()
- {
- WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
- string appsThemequery = string.Format(
- CultureInfo.InvariantCulture,
- @"SELECT * FROM RegistryValueChangeEvent WHERE Hive = 'HKEY_USERS' AND KeyPath = '{0}\\{1}' AND ValueName = '{2}'",
- currentUser.User.Value,
- RegistryKeyPath.Replace(@"\", @"\\"),
- appsThemeRegistryValueName);
-
- string systemThemequery = string.Format(
- CultureInfo.InvariantCulture,
- @"SELECT * FROM RegistryValueChangeEvent WHERE Hive = 'HKEY_USERS' AND KeyPath = '{0}\\{1}' AND ValueName = '{2}'",
- currentUser.User.Value,
- RegistryKeyPath.Replace(@"\", @"\\"),
- systemThemeRegistryValueName);
-
- try
- {
- // For Apps theme
- ManagementEventWatcher appsThemWatcher = new(appsThemequery);
- appsThemWatcher.EventArrived += (_, _) =>
- {
- WindowsTheme newWindowsTheme = GetAppsTheme();
- OnAppsThemeChanged(new WindowsThemeEventArgs(newWindowsTheme));
- };
-
- // Start listening for apps theme events
- appsThemWatcher.Start();
-
-
- // For System theme
- ManagementEventWatcher systemThemWatcher = new(systemThemequery);
- systemThemWatcher.EventArrived += (_, _) =>
- {
- WindowsTheme newWindowsTheme = GetSystemTheme();
- OnSystemThemeChanged(new WindowsThemeEventArgs(newWindowsTheme));
- };
-
- // Start listening for system theme events
- systemThemWatcher.Start();
- }
- catch (Exception)
- {
- // This can fail on Windows 7
- }
- }
-
- private WindowsTheme GetTheme(string themeKeyName)
- {
- using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistryKeyPath))
- {
- object registryValueObject = key?.GetValue(themeKeyName);
- if (registryValueObject == null) return WindowsTheme.Light;
-
- int registryValue = (int)registryValueObject;
-
- return registryValue > 0 ? WindowsTheme.Light : WindowsTheme.Dark;
- }
- }
-
- public WindowsTheme GetAppsTheme()
- {
- return GetTheme(appsThemeRegistryValueName);
- }
-
- public WindowsTheme GetSystemTheme()
- {
- return GetTheme(systemThemeRegistryValueName);
- }
-
- public event EventHandler AppsThemeChanged;
- public event EventHandler SystemThemeChanged;
-
- protected virtual void OnAppsThemeChanged(WindowsThemeEventArgs e)
- {
- AppsThemeChanged?.Invoke(this, e);
- }
-
- protected virtual void OnSystemThemeChanged(WindowsThemeEventArgs e)
- {
- SystemThemeChanged?.Invoke(this, e);
- }
-
- public enum WindowsTheme
- {
- Light,
- Dark
- }
- }
-}
\ No newline at end of file