mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
UI - Moved color scheme code away from tray VM
UI - Cleaned up settings page code Core - Changed default framerate to 30
This commit is contained in:
parent
da123e2fe2
commit
ef4e5b4c3b
@ -11,18 +11,14 @@ namespace Artemis.Core
|
||||
/// Represents a setting tied to a plugin of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The value type of the setting</typeparam>
|
||||
public class PluginSetting<T> : CorePropertyChanged
|
||||
public class PluginSetting<T> : 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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name of the setting, unique to this plugin
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
@ -63,28 +57,19 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the setting has been changed
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public bool HasChanged => CoreJson.SerializeObject(Value) != _pluginSettingEntity.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether changes must automatically be saved
|
||||
/// <para>Note: When set to <c>true</c> <see cref="HasChanged" /> is always <c>false</c></para>
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public bool AutoSave { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resets the setting to the last saved value
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void RejectChanges()
|
||||
{
|
||||
Value = CoreJson.DeserializeObject<T>(_pluginSettingEntity.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the setting
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void Save()
|
||||
{
|
||||
if (!HasChanged)
|
||||
@ -95,14 +80,10 @@ namespace Artemis.Core
|
||||
OnSettingSaved();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the value of the setting has been changed
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? SettingChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the value of the setting has been saved
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? SettingSaved;
|
||||
|
||||
/// <inheritdoc />
|
||||
@ -127,4 +108,46 @@ namespace Artemis.Core
|
||||
SettingSaved?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a setting tied to a plugin
|
||||
/// </summary>
|
||||
public interface IPluginSetting
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the setting, unique to this plugin
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the setting has been changed
|
||||
/// </summary>
|
||||
bool HasChanged { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether changes must automatically be saved
|
||||
/// <para>Note: When set to <c>true</c> <see cref="HasChanged" /> is always <c>false</c></para>
|
||||
/// </summary>
|
||||
bool AutoSave { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resets the setting to the last saved value
|
||||
/// </summary>
|
||||
void RejectChanges();
|
||||
|
||||
/// <summary>
|
||||
/// Saves the setting
|
||||
/// </summary>
|
||||
void Save();
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the value of the setting has been changed
|
||||
/// </summary>
|
||||
event EventHandler? SettingChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the value of the setting has been saved
|
||||
/// </summary>
|
||||
event EventHandler? SettingSaved;
|
||||
}
|
||||
}
|
||||
@ -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,7 +11,7 @@ namespace Artemis.Core
|
||||
public class PluginSettings
|
||||
{
|
||||
private readonly IPluginRepository _pluginRepository;
|
||||
private readonly Dictionary<string, object> _settingEntities;
|
||||
private readonly Dictionary<string, IPluginSetting> _settingEntities;
|
||||
|
||||
internal PluginSettings(Plugin plugin, IPluginRepository pluginRepository)
|
||||
{
|
||||
@ -20,7 +19,7 @@ namespace Artemis.Core
|
||||
Plugin.Settings = this;
|
||||
|
||||
_pluginRepository = pluginRepository;
|
||||
_settingEntities = new Dictionary<string, object>();
|
||||
_settingEntities = new Dictionary<string, IPluginSetting>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -56,7 +55,7 @@ namespace Artemis.Core
|
||||
_pluginRepository.AddSetting(settingEntity);
|
||||
}
|
||||
|
||||
PluginSetting<T> pluginSetting = new(Plugin, _pluginRepository, settingEntity);
|
||||
PluginSetting<T> 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
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves all currently loaded settings
|
||||
/// </summary>
|
||||
public void SaveAllSettings()
|
||||
{
|
||||
foreach (var (_, pluginSetting) in _settingEntities)
|
||||
pluginSetting.Save();
|
||||
}
|
||||
|
||||
internal void ClearSettings()
|
||||
{
|
||||
_settingEntities.Clear();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -16,6 +16,12 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
return _pluginSettings.GetSetting(name, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SaveAllSettings()
|
||||
{
|
||||
_pluginSettings.SaveAllSettings();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -32,5 +38,10 @@ namespace Artemis.Core.Services
|
||||
/// <param name="defaultValue">The default value to use if the setting does not exist yet</param>
|
||||
/// <returns></returns>
|
||||
PluginSetting<T> GetSetting<T>(string name, T? defaultValue = default);
|
||||
|
||||
/// <summary>
|
||||
/// Saves all settings, obviously
|
||||
/// </summary>
|
||||
void SaveAllSettings();
|
||||
}
|
||||
}
|
||||
30
src/Artemis.UI/Converters/NormalizedPercentageConverter.cs
Normal file
30
src/Artemis.UI/Converters/NormalizedPercentageConverter.cs
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
@ -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; }
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
ToastNotificationManagerCompat.Uninstall();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -1,27 +1,32 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.Settings.Tabs.General.GeneralSettingsTabView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings.Tabs.General"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:dataTemplateSelectors="clr-namespace:Artemis.UI.DataTemplateSelectors"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance local:GeneralSettingsTabViewModel}">
|
||||
<UserControl
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings.Tabs.General"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:dataTemplateSelectors="clr-namespace:Artemis.UI.DataTemplateSelectors"
|
||||
xmlns:system="clr-namespace:System;assembly=System.Runtime"
|
||||
xmlns:Converters="clr-namespace:Artemis.UI.Converters" x:Class="Artemis.UI.Screens.Settings.Tabs.General.GeneralSettingsTabView"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance {x:Type local:GeneralSettingsTabViewModel}}">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/LayerBrushDescriptors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<Converters:InverseBooleanConverter x:Key="InverseBooleanConverter" />
|
||||
<Converters:NormalizedPercentageConverter x:Key="NormalizedPercentageConverter" />
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
||||
<StackPanel Margin="15" MaxWidth="800">
|
||||
<!-- General settings -->
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">General</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">
|
||||
<Run Text="General" />
|
||||
</TextBlock>
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch" Margin="0,0,5,0">
|
||||
<StackPanel Margin="15">
|
||||
<Grid>
|
||||
@ -37,7 +42,7 @@
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Start up with Windows</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding StartWithWindows}" />
|
||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding UIAutoRun.Value}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
@ -55,7 +60,9 @@
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Start up with Windows minimized</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding StartMinimized}" IsEnabled="{Binding StartWithWindows}" />
|
||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}"
|
||||
IsChecked="{Binding UIShowOnStartup.Value, Converter={StaticResource InverseBooleanConverter}}"
|
||||
IsEnabled="{Binding UIAutoRun.Value}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
@ -72,14 +79,14 @@
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Startup delay</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
Set the amount of seconds to wait before running Artemis with Windows. <LineBreak />
|
||||
If some devices don't work because Artemis starts before the manufacturer's software, try increasing this value.
|
||||
<Run Text="Set the amount of seconds to wait before running Artemis with Windows." /><LineBreak />
|
||||
<Run Text="If some devices don't work because Artemis starts before the manufacturer's software, try increasing this value." />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<TextBox Style="{StaticResource MaterialDesignFilledTextBox}"
|
||||
Text="{Binding AutoRunDelay}"
|
||||
IsEnabled="{Binding StartWithWindows}"
|
||||
Text="{Binding UIAutoRunDelay.Value}"
|
||||
IsEnabled="{Binding UIAutoRun.Value}"
|
||||
Width="100"
|
||||
materialDesign:TextFieldAssist.SuffixText="sec"
|
||||
materialDesign:HintAssist.IsFloating="false" />
|
||||
@ -105,7 +112,7 @@
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ComboBox Style="{StaticResource MaterialDesignFilledComboBox}"
|
||||
Width="100"
|
||||
SelectedValue="{Binding SelectedColorScheme}"
|
||||
SelectedValue="{Binding UIColorScheme.Value}"
|
||||
ItemsSource="{Binding ColorSchemes}"
|
||||
SelectedValuePath="Value"
|
||||
DisplayMemberPath="Description"
|
||||
@ -124,7 +131,9 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Log level</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Log level
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
Sets the logging level, a higher logging level will result in more log files.
|
||||
</TextBlock>
|
||||
@ -132,7 +141,7 @@
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ComboBox Style="{StaticResource MaterialDesignFilledComboBox}"
|
||||
Width="100"
|
||||
SelectedValue="{Binding SelectedLogLevel}"
|
||||
SelectedValue="{Binding CoreLoggingLevel.Value}"
|
||||
ItemsSource="{Binding LogLevels}"
|
||||
SelectedValuePath="Value"
|
||||
DisplayMemberPath="Description"
|
||||
@ -151,22 +160,24 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Logs</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Logs
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}">
|
||||
Opens the directory where logs are stored.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowLogsFolder}" Width="150">
|
||||
SHOW LOGS
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowLogsFolder}" Width="150" Content="SHOW LOGS" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
|
||||
<!-- Web server settings -->
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">Web server</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">
|
||||
Web server
|
||||
</TextBlock>
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch" Margin="0,0,5,0">
|
||||
<StackPanel Margin="15">
|
||||
<Grid>
|
||||
@ -179,14 +190,18 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Web server port</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Web server port
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
Artemis runs a local web server that can be used to externally interact with the application. <LineBreak />
|
||||
This web server can only be accessed by applications running on your own computer, e.g. supported games.
|
||||
<Run Text="Artemis runs a local web server that can be used to externally interact with the application." /><LineBreak />
|
||||
<Run Text="This web server can only be accessed by applications running on your own computer, e.g. supported games." />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<TextBox Style="{StaticResource MaterialDesignFilledTextBox}" Text="{Binding WebServerPortSetting.Value}" Width="100"
|
||||
<TextBox Style="{StaticResource MaterialDesignFilledTextBox}"
|
||||
Text="{Binding WebServerPort.Value}"
|
||||
Width="100"
|
||||
materialDesign:HintAssist.IsFloating="false" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
@ -194,7 +209,9 @@
|
||||
</materialDesign:Card>
|
||||
|
||||
<!-- Update settings -->
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">Updating</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">
|
||||
<Run Text="Updating" />
|
||||
</TextBlock>
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch" Margin="0,0,5,0">
|
||||
<StackPanel Margin="15">
|
||||
<Grid>
|
||||
@ -207,13 +224,15 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Check for updates</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Check for updates
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
If enabled, we'll check for updates on startup and periodically while running.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding CheckForUpdates}" />
|
||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding UICheckForUpdates.Value}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
@ -228,22 +247,24 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Update</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Update
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}">
|
||||
Use the button on the right to check for updates now.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action OfferUpdatesIfFound}" Width="150">
|
||||
CHECK NOW
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action OfferUpdatesIfFound}" Width="150" Content="CHECK NOW" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
|
||||
<!-- Profile editor settings -->
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">Profile editor</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">
|
||||
<Run Text="Profile editor" />
|
||||
</TextBlock>
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch" Margin="0,0,5,0">
|
||||
<StackPanel Margin="15">
|
||||
<Grid>
|
||||
@ -256,16 +277,17 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Show condition data model values</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Show condition data model values
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
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.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding ShowDataModelValues}" />
|
||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding ProfileEditorShowDataModelValues.Value}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
|
||||
<Grid>
|
||||
@ -278,7 +300,9 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Default brush</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Default brush
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
Sets the default brush that is applied to new layers
|
||||
</TextBlock>
|
||||
@ -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}}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</materialDesign:Card>
|
||||
|
||||
<!-- Rendering settings -->
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">Rendering</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">
|
||||
Rendering
|
||||
</TextBlock>
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch" Margin="0,0,5,0">
|
||||
<StackPanel Margin="15">
|
||||
<Grid>
|
||||
@ -314,15 +338,17 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Preferred render method</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Preferred render method
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
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.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<ComboBox Style="{StaticResource MaterialDesignFilledComboBox}"
|
||||
Width="100"
|
||||
SelectedItem="{Binding PreferredGraphicsContext}"
|
||||
SelectedItem="{Binding CorePreferredGraphicsContext.Value}"
|
||||
materialDesign:HintAssist.IsFloating="false">
|
||||
<system:String>Software</system:String>
|
||||
<system:String>Vulkan</system:String>
|
||||
@ -341,7 +367,9 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Render scale</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Render scale
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
Sets the resolution Artemis renders at, higher scale means more CPU-usage, especially on large surfaces.
|
||||
</TextBlock>
|
||||
@ -367,9 +395,12 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Target framerate</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Target frame rate
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
||||
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. <LineBreak/>
|
||||
The options past 45 FPS are mostly useless unless you are using a custom device.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
@ -386,7 +417,9 @@
|
||||
|
||||
|
||||
<!-- Tools -->
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">Tools</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="0 15">
|
||||
Tools
|
||||
</TextBlock>
|
||||
<materialDesign:Card materialDesign:ShadowAssist.ShadowDepth="Depth1" VerticalAlignment="Stretch" Margin="0,0,5,0">
|
||||
<StackPanel Margin="15">
|
||||
<Grid>
|
||||
@ -399,15 +432,15 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Setup wizard</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
<Run Text="Setup wizard" />
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}">
|
||||
Opens the startup wizard usually shown when Artemis first starts.
|
||||
<Run Text="Opens the startup wizard usually shown when Artemis first starts." />
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowSetupWizard}" Width="150">
|
||||
SHOW WIZARD
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowSetupWizard}" Width="150" Content="SHOW WIZARD" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
@ -422,15 +455,15 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Debugger</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Debugger
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}">
|
||||
Use the debugger to see the raw image Artemis is rendering on the surface.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowDebugger}" Width="150">
|
||||
SHOW DEBUGGER
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowDebugger}" Width="150" Content="SHOW DEBUGGER" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||
@ -445,15 +478,15 @@
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0" VerticalAlignment="Center">
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Application files</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">
|
||||
Application files
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}">
|
||||
Opens the directory where application files like plugins and settings are stored.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowDataFolder}" Width="150">
|
||||
SHOW APP FILES
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignOutlinedButton}" Command="{s:Action ShowDataFolder}" Width="150" Content="SHOW APP FILES" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
@ -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<Tuple<string, double>> _renderScales;
|
||||
private List<Tuple<string, int>> _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<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(LogEventLevel)));
|
||||
ColorSchemes = new BindableCollection<ValueDescription>(EnumUtilities.GetAllValuesAndDescriptions(typeof(ApplicationColorScheme)));
|
||||
RenderScales = new List<Tuple<string, double>>
|
||||
RenderScales = new BindableCollection<Tuple<string, double>>
|
||||
{
|
||||
new("25%", 0.25),
|
||||
new("50%", 0.5),
|
||||
new("100%", 1),
|
||||
new("100%", 1)
|
||||
};
|
||||
TargetFrameRates = new BindableCollection<Tuple<string, int>>
|
||||
{
|
||||
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<Tuple<string, int>>();
|
||||
for (int i = 10; i <= 30; i += 5)
|
||||
TargetFrameRates.Add(new Tuple<string, int>(i + " FPS", i));
|
||||
if (coreService.StartupArguments.Contains("--pcmr"))
|
||||
{
|
||||
TargetFrameRates.Add(new Tuple<string, int>("60 FPS (lol)", 60));
|
||||
TargetFrameRates.Add(new Tuple<string, int>("144 FPS (omegalol)", 144));
|
||||
}
|
||||
|
||||
List<LayerBrushProvider> layerBrushProviders = pluginManagementService.GetFeaturesOfType<LayerBrushProvider>();
|
||||
|
||||
LayerBrushDescriptors = new BindableCollection<LayerBrushDescriptor>(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<LayerBrushDescriptor> 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<ValueDescription> LogLevels { get; }
|
||||
public BindableCollection<ValueDescription> ColorSchemes { get; }
|
||||
|
||||
public List<Tuple<string, int>> TargetFrameRates
|
||||
{
|
||||
get => _targetFrameRates;
|
||||
set => SetAndNotify(ref _targetFrameRates, value);
|
||||
}
|
||||
|
||||
public List<Tuple<string, double>> 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<Tuple<string, double>> RenderScales { get; }
|
||||
public BindableCollection<Tuple<string, int>> TargetFrameRates { get; }
|
||||
|
||||
public Tuple<string, double> 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<string, int> 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<bool> UIAutoRun => _settingsService.GetSetting("UI.AutoRun", false);
|
||||
public PluginSetting<int> UIAutoRunDelay => _settingsService.GetSetting("UI.AutoRunDelay", 15);
|
||||
public PluginSetting<bool> UIShowOnStartup => _settingsService.GetSetting("UI.ShowOnStartup", true);
|
||||
public PluginSetting<bool> UICheckForUpdates => _settingsService.GetSetting("UI.CheckForUpdates", true);
|
||||
public PluginSetting<ApplicationColorScheme> UIColorScheme => _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
|
||||
public PluginSetting<bool> ProfileEditorShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false);
|
||||
public PluginSetting<LogEventLevel> CoreLoggingLevel => _settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Information);
|
||||
public PluginSetting<string> CorePreferredGraphicsContext => _settingsService.GetSetting("Core.PreferredGraphicsContext", "Vulkan");
|
||||
public PluginSetting<double> CoreRenderScale => _settingsService.GetSetting("Core.RenderScale", 0.25);
|
||||
public PluginSetting<int> CoreTargetFrameRate => _settingsService.GetSetting("Core.TargetFrameRate", 30);
|
||||
public PluginSetting<int> 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<int> 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
|
||||
{
|
||||
|
||||
@ -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<ApplicationColorScheme> _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
|
||||
|
||||
@ -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()
|
||||
|
||||
176
src/Artemis.UI/Services/ThemeService.cs
Normal file
176
src/Artemis.UI/Services/ThemeService.cs
Normal file
@ -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<ApplicationColorScheme> _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<WindowsThemeEventArgs> AppsThemeChanged;
|
||||
public event EventHandler<WindowsThemeEventArgs> 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<WindowsThemeEventArgs> AppsThemeChanged;
|
||||
event EventHandler<WindowsThemeEventArgs> SystemThemeChanged;
|
||||
|
||||
enum WindowsTheme
|
||||
{
|
||||
Light,
|
||||
Dark
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<WindowsThemeEventArgs> AppsThemeChanged;
|
||||
public event EventHandler<WindowsThemeEventArgs> 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
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user