feat(设置): 新增高级设置和随机点名设置页面

refactor: 将高级和随机点名设置从主窗口迁移到独立页面
style: 优化墨迹识别页面的高精度直线拉直开关样式
fix: 修复URI处理中未刷新配置列表的问题
This commit is contained in:
PrefacedCorg
2026-04-25 20:26:56 +08:00
parent 77dff81217
commit f3ef2f7aec
15 changed files with 1339 additions and 1096 deletions
@@ -0,0 +1,226 @@
<ui:Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.AdvancedPage"
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:Ink_Canvas.Windows.SettingsViews.Pages"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:Ink_Canvas.Controls;assembly=InkCanvas.Controls"
mc:Ignorable="d"
Title="{i18n:I18n Key=Advanced_Title}">
<ScrollViewer PanningMode="VerticalFirst">
<Grid Margin="59,0,59,0">
<FrameworkElement.Resources>
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
TargetType="TextBlock">
<Style.Setters>
<Setter Property="Margin" Value="1,30,0,6" />
</Style.Setters>
</Style>
</FrameworkElement.Resources>
<Grid>
<ikw:SimpleStackPanel MaxWidth="1000"
HorizontalAlignment="Stretch"
Spacing="{StaticResource SettingsCardSpacing}">
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="{i18n:I18n Key=Advanced_Title}" />
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_SpecialScreenMode}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch x:Name="ToggleSwitchIsSpecialScreen"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="True"
Toggled="ToggleSwitchIsSpecialScreen_OnToggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Canvas_DisableHardwareAcceleration}"
Description="{i18n:I18n Key=Canvas_DisableHardwareAccelerationHint}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Process}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch x:Name="ToggleSwitchDisableHardwareAcceleration"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="False"
Toggled="ToggleSwitchDisableHardwareAcceleration_Toggled"/>
</ui:SettingsCard>
<ui:SettingsExpander x:Name="CardTouchMultiplier"
Header="{i18n:I18n Key=Advanced_TouchMultiplier}"
Description="{i18n:I18n Key=Advanced_TouchMultiplierHint}">
<ui:SettingsExpander.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Touch}" />
</ui:SettingsExpander.HeaderIcon>
<Slider x:Name="TouchMultiplierSlider"
Minimum="0" Maximum="2"
Width="200"
IsSnapToTickEnabled="True"
TickFrequency="0.01" TickPlacement="None"
ValueChanged="TouchMultiplierSlider_ValueChanged" />
<ui:SettingsExpander.Items>
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_TouchMultiplierCalibrateHint}"
ContentAlignment="Left">
<ikw:SimpleStackPanel Spacing="8" Margin="0,4,0,4">
<TextBlock Text="{i18n:I18n Key=Advanced_TouchMultiplierValueHint}"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
TextWrapping="Wrap" MaxWidth="420" />
<Border Margin="0,0,20,0" CornerRadius="4" Height="48" Background="Transparent"
BorderBrush="{DynamicResource ControlStrokeColorDefaultBrush}" BorderThickness="2"
TouchDown="BorderCalculateMultiplier_TouchDown" />
<TextBlock x:Name="TextBlockShowCalculatedMultiplier" FontSize="14" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
</ui:SettingsExpander.Items>
</ui:SettingsExpander>
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_EraserBindTouchMultiplier}"
Description="{i18n:I18n Key=Advanced_EraserBindTouchHint}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.EraseTool}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch x:Name="ToggleSwitchEraserBindTouchMultiplier"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="True"
Toggled="ToggleSwitchEraserBindTouchMultiplier_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_NibModeBoundsWidthHeader}">
<Slider x:Name="NibModeBoundsWidthSlider"
Minimum="1" Maximum="50" Width="200"
IsSnapToTickEnabled="True" TickFrequency="1" Value="5"
TickPlacement="None"
ValueChanged="NibModeBoundsWidthSlider_ValueChanged" />
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_FingerModeBoundsWidthHeader}">
<Slider x:Name="FingerModeBoundsWidthSlider"
Minimum="1" Maximum="50" Width="200"
IsSnapToTickEnabled="True" TickFrequency="1" Value="20"
TickPlacement="None"
ValueChanged="FingerModeBoundsWidthSlider_ValueChanged" />
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_QuadIRMode}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.FullScreen}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch x:Name="ToggleSwitchIsQuadIR"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="True"
Toggled="ToggleSwitchIsQuadIR_Toggled"/>
</ui:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="{i18n:I18n Key=Advanced_Logging}" />
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_Logging}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.OpenFile}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch x:Name="ToggleSwitchIsLogEnabled"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="True"
Toggled="ToggleSwitchIsLogEnabled_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_LogByDate}"
Description="{i18n:I18n Key=Advanced_LogRotateHint}">
<ui:ToggleSwitch x:Name="ToggleSwitchIsSaveLogByDate"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="True"
Toggled="ToggleSwitchIsSaveLogByDate_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Advanced_ConfirmExit}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.SignOut}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch x:Name="ToggleSwitchIsSecondConfimeWhenShutdownApp"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="True"
Toggled="ToggleSwitchIsSecondConfimeWhenShutdownApp_Toggled"/>
</ui:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="{i18n:I18n Key=Backup_Title}" />
<TextBlock Text="{i18n:I18n Key=Backup_Desc}"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
TextWrapping="Wrap" Margin="1,0,0,4" />
<ui:SettingsCard Header="{i18n:I18n Key=Backup_AutoBeforeUpdate}">
<ui:ToggleSwitch x:Name="ToggleSwitchIsAutoBackupBeforeUpdate"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="True"
Toggled="ToggleSwitchIsAutoBackupBeforeUpdate_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Backup_AutoPeriodic}">
<ui:ToggleSwitch x:Name="ToggleSwitchIsAutoBackupEnabled"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
IsOn="True"
Toggled="ToggleSwitchIsAutoBackupEnabled_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Backup_Interval}"
Description="{i18n:I18n Key=Backup_Interval_DefaultHint}">
<ComboBox x:Name="ComboBoxAutoBackupInterval"
SelectionChanged="ComboBoxAutoBackupInterval_SelectionChanged">
<ComboBoxItem Content="{i18n:I18n Key=Backup_Interval_1Day}" Tag="1" />
<ComboBoxItem Content="{i18n:I18n Key=Backup_Interval_3Days}" Tag="3" />
<ComboBoxItem Content="{i18n:I18n Key=Backup_Interval_7Days}" Tag="7" IsSelected="True" />
<ComboBoxItem Content="{i18n:I18n Key=Backup_Interval_14Days}" Tag="14" />
<ComboBoxItem Content="{i18n:I18n Key=Backup_Interval_30Days}" Tag="30" />
</ComboBox>
</ui:SettingsCard>
<ui:SettingsCard ContentAlignment="Left">
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="8">
<Button x:Name="BtnManualBackup" Content="{i18n:I18n Key=Backup_Manual}" Click="BtnManualBackup_Click" />
<Button x:Name="BtnRestoreBackup" Content="{i18n:I18n Key=Backup_Restore}" Click="BtnRestoreBackup_Click" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="{i18n:I18n Key=ConfigProfiles_Title}" />
<TextBlock Text="{i18n:I18n Key=ConfigProfiles_Desc}"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
TextWrapping="Wrap" Margin="1,0,0,4" />
<ui:SettingsCard Header="{i18n:I18n Key=ConfigProfiles_Label}">
<ComboBox x:Name="ComboBoxConfigProfile" MinWidth="180"
SelectionChanged="ComboBoxConfigProfile_SelectionChanged" />
</ui:SettingsCard>
<ui:SettingsCard ContentAlignment="Left">
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="8">
<Button x:Name="BtnDeleteConfigProfile" Content="{i18n:I18n Key=ConfigProfiles_Delete}" Click="BtnDeleteConfigProfile_Click" />
<Button x:Name="BtnSaveAsConfigProfile" Content="{i18n:I18n Key=ConfigProfiles_SaveAs}" Click="BtnSaveAsConfigProfile_Click" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<Rectangle Height="48" />
</ikw:SimpleStackPanel>
</Grid>
</Grid>
</ScrollViewer>
</ui:Page>
@@ -0,0 +1,467 @@
using Ink_Canvas.Helpers;
using Ink_Canvas.Windows.SettingsViews.Helpers;
using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using ContentDialog = iNKORE.UI.WPF.Modern.Controls.ContentDialog;
using MessageBox = System.Windows.MessageBox;
using Page = iNKORE.UI.WPF.Modern.Controls.Page;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class AdvancedPage : Page
{
private bool _isLoaded = false;
private bool _isRefreshingConfigProfileList = false;
private string _lastAppliedProfileName;
public AdvancedPage()
{
InitializeComponent();
Loaded += Page_Loaded;
Unloaded += Page_Unloaded;
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
LoadSettings();
_isLoaded = true;
RefreshConfigProfileList();
}
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
_isLoaded = false;
}
private MainWindow GetMainWindow() => Application.Current.MainWindow as MainWindow;
private void LoadSettings()
{
var settings = SettingsManager.Settings;
if (settings?.Advanced == null) return;
ToggleSwitchIsSpecialScreen.IsOn = settings.Advanced.IsSpecialScreen;
ToggleSwitchDisableHardwareAcceleration.IsOn = !settings.Canvas.UseHardwareAcceleration;
TouchMultiplierSlider.Value = settings.Advanced.TouchMultiplier;
ToggleSwitchEraserBindTouchMultiplier.IsOn = settings.Advanced.EraserBindTouchMultiplier;
NibModeBoundsWidthSlider.Value = settings.Advanced.NibModeBoundsWidth;
FingerModeBoundsWidthSlider.Value = settings.Advanced.FingerModeBoundsWidth;
ToggleSwitchIsQuadIR.IsOn = settings.Advanced.IsQuadIR;
ToggleSwitchIsLogEnabled.IsOn = settings.Advanced.IsLogEnabled;
ToggleSwitchIsSaveLogByDate.IsOn = settings.Advanced.IsSaveLogByDate;
ToggleSwitchIsSecondConfimeWhenShutdownApp.IsOn = settings.Advanced.IsSecondConfirmWhenShutdownApp;
ToggleSwitchIsAutoBackupBeforeUpdate.IsOn = settings.Advanced.IsAutoBackupBeforeUpdate;
ToggleSwitchIsAutoBackupEnabled.IsOn = settings.Advanced.IsAutoBackupEnabled;
foreach (ComboBoxItem item in ComboBoxAutoBackupInterval.Items)
{
if (item.Tag != null && int.TryParse(item.Tag.ToString(), out int interval) && interval == settings.Advanced.AutoBackupIntervalDays)
{
ComboBoxAutoBackupInterval.SelectedItem = item;
break;
}
}
CardTouchMultiplier.IsExpanded = settings.Advanced.IsSpecialScreen;
}
#region Special Screen & Touch Multiplier
private void ToggleSwitchIsSpecialScreen_OnToggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.IsSpecialScreen = ToggleSwitchIsSpecialScreen.IsOn;
CardTouchMultiplier.IsExpanded = ToggleSwitchIsSpecialScreen.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchDisableHardwareAcceleration_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Canvas.UseHardwareAcceleration = !ToggleSwitchDisableHardwareAcceleration.IsOn;
var mw = GetMainWindow();
if (mw != null) mw.UpdateInkSmoothingConfig();
SettingsManager.SaveSettingsToFile();
}
private void TouchMultiplierSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.TouchMultiplier = e.NewValue;
SettingsManager.SaveSettingsToFile();
}
private void BorderCalculateMultiplier_TouchDown(object sender, TouchEventArgs e)
{
var args = e.GetTouchPoint(null).Bounds;
double value;
if (!SettingsManager.Settings.Advanced.IsQuadIR) value = args.Width;
else value = Math.Sqrt(args.Width * args.Height);
TextBlockShowCalculatedMultiplier.Text = (5 / (value * 1.1)).ToString();
}
#endregion
#region Eraser & Bounds Width
private void ToggleSwitchEraserBindTouchMultiplier_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.EraserBindTouchMultiplier = ToggleSwitchEraserBindTouchMultiplier.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void NibModeBoundsWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.NibModeBoundsWidth = (int)e.NewValue;
var mw = GetMainWindow();
if (mw != null)
{
if (SettingsManager.Settings.Startup.IsEnableNibMode)
mw.BoundsWidth = SettingsManager.Settings.Advanced.NibModeBoundsWidth;
else
mw.BoundsWidth = SettingsManager.Settings.Advanced.FingerModeBoundsWidth;
}
SettingsManager.SaveSettingsToFile();
}
private void FingerModeBoundsWidthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.FingerModeBoundsWidth = (int)e.NewValue;
var mw = GetMainWindow();
if (mw != null)
{
if (SettingsManager.Settings.Startup.IsEnableNibMode)
mw.BoundsWidth = SettingsManager.Settings.Advanced.NibModeBoundsWidth;
else
mw.BoundsWidth = SettingsManager.Settings.Advanced.FingerModeBoundsWidth;
}
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchIsQuadIR_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.IsQuadIR = ToggleSwitchIsQuadIR.IsOn;
SettingsManager.SaveSettingsToFile();
}
#endregion
#region Logging & Exit
private void ToggleSwitchIsLogEnabled_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.IsLogEnabled = ToggleSwitchIsLogEnabled.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchIsSaveLogByDate_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.IsSaveLogByDate = ToggleSwitchIsSaveLogByDate.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchIsSecondConfimeWhenShutdownApp_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.IsSecondConfirmWhenShutdownApp = ToggleSwitchIsSecondConfimeWhenShutdownApp.IsOn;
SettingsManager.SaveSettingsToFile();
}
#endregion
#region Backup
private void ToggleSwitchIsAutoBackupBeforeUpdate_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.IsAutoBackupBeforeUpdate = ToggleSwitchIsAutoBackupBeforeUpdate.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchIsAutoBackupEnabled_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Advanced.IsAutoBackupEnabled = ToggleSwitchIsAutoBackupEnabled.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void ComboBoxAutoBackupInterval_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!_isLoaded) return;
if (ComboBoxAutoBackupInterval.SelectedItem is ComboBoxItem selectedItem && selectedItem.Tag != null)
{
if (int.TryParse(selectedItem.Tag.ToString(), out int interval))
{
SettingsManager.Settings.Advanced.AutoBackupIntervalDays = interval;
SettingsManager.SaveSettingsToFile();
}
}
}
private void BtnManualBackup_Click(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
string backupDir = Path.Combine(App.RootPath, "Backups");
if (!Directory.Exists(backupDir))
{
Directory.CreateDirectory(backupDir);
LogHelper.WriteLogToFile($"创建备份目录: {backupDir}");
}
string backupFileName = $"Settings_Backup_{DateTime.Now:yyyyMMdd_HHmmss}.json";
string backupPath = Path.Combine(backupDir, backupFileName);
string settingsJson = Newtonsoft.Json.JsonConvert.SerializeObject(SettingsManager.Settings, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(backupPath, settingsJson);
LogHelper.WriteLogToFile($"成功创建设置备份: {backupPath}");
MessageBox.Show($"设置已成功备份到:\n{backupPath}", "备份成功", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"创建设置备份时出错: {ex.Message}", LogHelper.LogType.Error);
MessageBox.Show($"创建备份失败: {ex.Message}", "备份失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void BtnRestoreBackup_Click(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
try
{
string backupDir = Path.Combine(App.RootPath, "Backups");
if (!Directory.Exists(backupDir))
{
Directory.CreateDirectory(backupDir);
LogHelper.WriteLogToFile($"创建备份目录: {backupDir}");
MessageBox.Show("没有找到备份文件,请先创建备份", "还原失败", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
var dlg = new Microsoft.Win32.OpenFileDialog();
dlg.InitialDirectory = backupDir;
dlg.Filter = "设置备份文件|Settings_Backup_*.json|所有JSON文件|*.json";
dlg.Title = "选择要还原的备份文件";
if (dlg.ShowDialog() == true)
{
string backupJson = File.ReadAllText(dlg.FileName);
Settings backupSettings = Newtonsoft.Json.JsonConvert.DeserializeObject<Settings>(backupJson);
if (backupSettings != null)
{
if (MessageBox.Show("确定要还原选择的备份文件吗?当前设置将被覆盖。", "确认还原",
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
string currentSettingsJson = Newtonsoft.Json.JsonConvert.SerializeObject(SettingsManager.Settings, Newtonsoft.Json.Formatting.Indented);
string tempBackupPath = Path.Combine(backupDir, $"Settings_Before_Restore_{DateTime.Now:yyyyMMdd_HHmmss}.json");
File.WriteAllText(tempBackupPath, currentSettingsJson);
SettingsManager.Settings = backupSettings;
SettingsManager.SaveSettingsToFile();
var mw = GetMainWindow();
if (mw != null) mw.ReloadSettingsFromFile();
LogHelper.WriteLogToFile($"成功从备份还原设置: {dlg.FileName}");
MessageBox.Show("设置已成功还原,部分设置可能需要重启软件后生效。", "还原成功", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
else
{
MessageBox.Show("无法解析备份文件,文件可能已损坏", "还原失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"还原设置备份时出错: {ex.Message}", LogHelper.LogType.Error);
MessageBox.Show($"还原备份失败: {ex.Message}", "还原失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
#endregion
#region Config Profiles
private void RefreshConfigProfileList()
{
try
{
if (ComboBoxConfigProfile == null) return;
_isRefreshingConfigProfileList = true;
try
{
var names = ConfigProfileManager.ListProfileNames();
ComboBoxConfigProfile.ItemsSource = names;
if (names.Count == 0)
{
ComboBoxConfigProfile.SelectedItem = null;
}
else if (_lastAppliedProfileName != null && names.Contains(_lastAppliedProfileName))
{
ComboBoxConfigProfile.SelectedItem = _lastAppliedProfileName;
}
else
{
var selected = ComboBoxConfigProfile.SelectedItem as string;
if (selected != null && names.Contains(selected))
ComboBoxConfigProfile.SelectedItem = selected;
else
ComboBoxConfigProfile.SelectedIndex = 0;
}
if (BtnDeleteConfigProfile != null)
BtnDeleteConfigProfile.IsEnabled = ComboBoxConfigProfile.SelectedItem != null;
}
finally
{
_isRefreshingConfigProfileList = false;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"刷新配置方案列表失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private void ComboBoxConfigProfile_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (BtnDeleteConfigProfile != null)
BtnDeleteConfigProfile.IsEnabled = ComboBoxConfigProfile?.SelectedItem != null;
if (!_isLoaded || _isRefreshingConfigProfileList) return;
var name = ComboBoxConfigProfile?.SelectedItem as string;
if (string.IsNullOrEmpty(name)) return;
try
{
if (ConfigProfileManager.ApplyProfile(name))
{
_lastAppliedProfileName = name;
var mw = GetMainWindow();
if (mw != null)
{
mw.ReloadSettingsFromFile();
mw.ShowNotification($"已切换至方案「{name}」");
}
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"切换配置方案失败: {ex.Message}", LogHelper.LogType.Error);
}
}
private async void BtnSaveAsConfigProfile_Click(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
var input = new System.Windows.Controls.TextBox
{
MinWidth = 260,
Padding = new Thickness(8, 6, 8, 6),
Margin = new Thickness(0, 0, 0, 12)
};
var label = new System.Windows.Controls.TextBlock
{
Text = "方案名称",
Margin = new Thickness(0, 0, 0, 8)
};
var content = new iNKORE.UI.WPF.Controls.SimpleStackPanel { Spacing = 6 };
content.Children.Add(label);
content.Children.Add(input);
var dialog = new ContentDialog
{
Title = "另存为方案",
Content = content,
PrimaryButtonText = "保存",
SecondaryButtonText = "取消",
Owner = GetMainWindow()
};
var result = await dialog.ShowAsync();
if (result != ContentDialogResult.Primary) return;
var name = input.Text?.Trim();
if (string.IsNullOrEmpty(name))
{
MessageBox.Show("请输入方案名称。", "另存为方案", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
try
{
var json = Newtonsoft.Json.JsonConvert.SerializeObject(SettingsManager.Settings, Newtonsoft.Json.Formatting.Indented);
if (ConfigProfileManager.SaveAsProfile(name, json))
{
_lastAppliedProfileName = name;
RefreshConfigProfileList();
var mw = GetMainWindow();
if (mw != null) mw.ShowNotification($"已另存为方案:{name}");
}
else
MessageBox.Show("保存失败,请查看日志。", "另存为方案", MessageBoxButton.OK, MessageBoxImage.Warning);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"另存为方案失败: {ex.Message}", LogHelper.LogType.Error);
MessageBox.Show($"保存失败: {ex.Message}", "另存为方案", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void BtnDeleteConfigProfile_Click(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
var name = ComboBoxConfigProfile?.SelectedItem as string;
if (string.IsNullOrEmpty(name))
{
MessageBox.Show("请先选择要删除的配置文件。", "配置文件", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
try
{
if (MessageBox.Show($"确定要删除配置文件「{name}」吗?", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
return;
if (ConfigProfileManager.DeleteProfile(name))
{
RefreshConfigProfileList();
var nextName = ComboBoxConfigProfile?.SelectedItem as string;
var mw = GetMainWindow();
if (!string.IsNullOrEmpty(nextName) && ConfigProfileManager.ApplyProfile(nextName))
{
_lastAppliedProfileName = nextName;
if (mw != null)
{
mw.ReloadSettingsFromFile();
mw.ShowNotification($"已删除方案「{name}」,已切换至「{nextName}」");
}
}
else
{
if (mw != null) mw.ShowNotification($"已删除方案:{name}");
}
}
else
MessageBox.Show("删除配置文件失败,请查看日志。", "配置文件", MessageBoxButton.OK, MessageBoxImage.Warning);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"删除配置文件失败: {ex.Message}", LogHelper.LogType.Error);
MessageBox.Show($"删除配置文件失败: {ex.Message}", "配置文件", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
#endregion
}
}
@@ -78,6 +78,13 @@
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard Header="高级" Description="高级设置"
IsClickEnabled="True" Click="QuickNavCard_Click" Tag="AdvancedPage">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard Header="画板" Description="画板设置"
IsClickEnabled="True" Click="QuickNavCard_Click" Tag="CanvasPage">
<ui:SettingsCard.HeaderIcon>
@@ -92,6 +99,13 @@
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard Header="随机点名" Description="随机点名与计时器"
IsClickEnabled="True" Click="QuickNavCard_Click" Tag="RandomDrawPage">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.People}" />
</ui:SettingsCard.HeaderIcon>
</ui:SettingsCard>
<ui:SettingsCard Header="关于" Description="关于 InkCanvasForClass"
IsClickEnabled="True" Click="QuickNavCard_Click" Tag="AboutPage">
<ui:SettingsCard.HeaderIcon>
@@ -79,18 +79,21 @@
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Settings}" />
</ui:SettingsExpander.HeaderIcon>
<ui:SettingsExpander.Items>
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_FixTriangle}">
<ui:SettingsCard ContentAlignment="Left">
<CheckBox x:Name="ToggleCheckboxEnableInkToShapeTriangle" IsChecked="True"
Content="{i18n:I18n Key=InkRecog_FixTriangle}"
Checked="ToggleCheckboxEnableInkToShapeTriangle_CheckedChanged"
Unchecked="ToggleCheckboxEnableInkToShapeTriangle_CheckedChanged" />
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_FixRectangle}">
<ui:SettingsCard ContentAlignment="Left">
<CheckBox x:Name="ToggleCheckboxEnableInkToShapeRectangle" IsChecked="True"
Content="{i18n:I18n Key=InkRecog_FixRectangle}"
Checked="ToggleCheckboxEnableInkToShapeRectangle_CheckedChanged"
Unchecked="ToggleCheckboxEnableInkToShapeRectangle_CheckedChanged" />
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_FixEllipse}">
<ui:SettingsCard ContentAlignment="Left">
<CheckBox x:Name="ToggleCheckboxEnableInkToShapeRounded" IsChecked="True"
Content="{i18n:I18n Key=InkRecog_FixEllipse}"
Checked="ToggleCheckboxEnableInkToShapeRounded_CheckedChanged"
Unchecked="ToggleCheckboxEnableInkToShapeRounded_CheckedChanged" />
</ui:SettingsCard>
@@ -128,9 +131,10 @@
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=InkRecog_HighPrecisionStraighten}"
Description="{i18n:I18n Key=InkRecog_HighPrecisionHint}">
<CheckBox x:Name="CheckboxHighPrecisionLineStraighten" IsChecked="False"
Checked="CheckboxHighPrecisionLineStraighten_CheckedChanged"
Unchecked="CheckboxHighPrecisionLineStraighten_CheckedChanged" />
<ui:ToggleSwitch x:Name="ToggleSwitchHighPrecisionLineStraighten"
OnContent="{DynamicResource Common_On}"
OffContent="{DynamicResource Common_Off}"
Toggled="ToggleSwitchHighPrecisionLineStraighten_Toggled" />
</ui:SettingsCard>
</ui:SettingsExpander.Items>
</ui:SettingsExpander>
@@ -50,7 +50,7 @@ namespace Ink_Canvas.Windows.SettingsViews.Pages
{
ToggleSwitchAutoStraightenLine.IsOn = settings.Canvas.AutoStraightenLine;
AutoStraightenLineThresholdSlider.Value = settings.Canvas.AutoStraightenLineThreshold;
CheckboxHighPrecisionLineStraighten.IsChecked = settings.Canvas.HighPrecisionLineStraighten;
ToggleSwitchHighPrecisionLineStraighten.IsOn = settings.Canvas.HighPrecisionLineStraighten;
ToggleSwitchLineEndpointSnapping.IsOn = settings.Canvas.LineEndpointSnapping;
}
}
@@ -146,10 +146,10 @@ namespace Ink_Canvas.Windows.SettingsViews.Pages
SettingsManager.SaveSettingsToFile();
}
private void CheckboxHighPrecisionLineStraighten_CheckedChanged(object sender, RoutedEventArgs e)
private void ToggleSwitchHighPrecisionLineStraighten_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.Canvas.HighPrecisionLineStraighten = (bool)CheckboxHighPrecisionLineStraighten.IsChecked;
SettingsManager.Settings.Canvas.HighPrecisionLineStraighten = ToggleSwitchHighPrecisionLineStraighten.IsOn;
SettingsManager.SaveSettingsToFile();
}
@@ -0,0 +1,207 @@
<ui:Page x:Class="Ink_Canvas.Windows.SettingsViews.Pages.RandomDrawPage"
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:Ink_Canvas.Windows.SettingsViews.Pages"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:i18n="clr-namespace:Ink_Canvas.MarkupExtensions"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="{i18n:I18n Key=Random_Title}">
<ScrollViewer PanningMode="VerticalFirst">
<Grid Margin="59,0,59,0">
<FrameworkElement.Resources>
<sys:Double x:Key="SettingsCardSpacing">4</sys:Double>
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
TargetType="TextBlock">
<Style.Setters>
<Setter Property="Margin" Value="1,30,0,6" />
</Style.Setters>
</Style>
</FrameworkElement.Resources>
<Grid>
<ikw:SimpleStackPanel MaxWidth="1000"
HorizontalAlignment="Stretch"
Spacing="{StaticResource SettingsCardSpacing}">
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="{i18n:I18n Key=Random_Title}" />
<ui:SettingsCard Header="{i18n:I18n Key=Random_ShowEditNamesButton}">
<ui:SettingsCard.HeaderIcon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Edit}" />
</ui:SettingsCard.HeaderIcon>
<ui:ToggleSwitch x:Name="ToggleSwitchDisplayRandWindowNamesInputBtn"
IsOn="True"
Toggled="ToggleSwitchDisplayRandWindowNamesInputBtn_OnToggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_EnableButtons}">
<ui:ToggleSwitch x:Name="ToggleSwitchShowRandomAndSingleDraw"
IsOn="True"
Toggled="ToggleSwitchShowRandomAndSingleDraw_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_EnableQuickButton}">
<ui:ToggleSwitch x:Name="ToggleSwitchEnableQuickDraw"
IsOn="True"
Toggled="ToggleSwitchEnableQuickDraw_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_UseExternal}">
<ui:ToggleSwitch x:Name="ToggleSwitchExternalCaller"
IsOn="False"
Toggled="ToggleSwitchExternalCaller_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_ExternalTypeLabel}">
<ComboBox x:Name="ComboBoxExternalCallerType"
SelectedIndex="0"
SelectionChanged="ComboBoxExternalCallerType_SelectionChanged">
<ComboBoxItem Content="{i18n:I18n Key=Random_ExternalType_ClassIsland}" />
<ComboBoxItem Content="{i18n:I18n Key=Random_ExternalType_SecRandom}" />
<ComboBoxItem Content="{i18n:I18n Key=Random_ExternalType_NamePicker}" />
</ComboBox>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_OnceCloseDelay}">
<Slider x:Name="RandWindowOnceCloseLatencySlider"
Minimum="0.5" Maximum="8" Width="200"
IsSnapToTickEnabled="True" Value="2.5"
TickFrequency="0.1" TickPlacement="None"
ValueChanged="RandWindowOnceCloseLatencySlider_ValueChanged" />
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_OnceMaxStudents}">
<Slider x:Name="RandWindowOnceMaxStudentsSlider"
Minimum="0" Maximum="20" Width="200"
IsSnapToTickEnabled="True" Value="10" TickFrequency="1"
TickPlacement="None"
ValueChanged="RandWindowOnceMaxStudentsSlider_ValueChanged" />
</ui:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="{i18n:I18n Key=Random_BackgroundSettingsTitle}" />
<ui:SettingsCard Header="{i18n:I18n Key=Random_BackgroundSelectLabel}">
<ComboBox x:Name="ComboBoxPickNameBackground"
SelectedIndex="0"
SelectionChanged="ComboBoxPickNameBackground_SelectionChanged" />
</ui:SettingsCard>
<ui:SettingsCard ContentAlignment="Left">
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="8">
<Button x:Name="ButtonAddCustomBackground" Content="{i18n:I18n Key=Random_CustomBackground_Upload}" Click="ButtonAddCustomBackground_Click" />
<Button x:Name="ButtonManageBackgrounds" Content="{i18n:I18n Key=Random_CustomBackground_Manage}" Click="ButtonManageBackgrounds_Click" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="{i18n:I18n Key=Random_NewUI_Title}" />
<ui:SettingsCard Header="{i18n:I18n Key=Random_NewUI_Enable}">
<ui:ToggleSwitch x:Name="ToggleSwitchUseNewRollCallUI"
IsOn="True"
Toggled="ToggleSwitchUseNewRollCallUI_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_ML_AvoidRepeat}">
<ui:ToggleSwitch x:Name="ToggleSwitchEnableMLAvoidance"
IsOn="True"
Toggled="ToggleSwitchEnableMLAvoidance_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_ML_HistoryCount}">
<Slider x:Name="MLAvoidanceHistorySlider"
Minimum="5" Maximum="50" Width="200"
IsSnapToTickEnabled="True" Value="50" TickFrequency="5"
TickPlacement="None"
ValueChanged="MLAvoidanceHistorySlider_ValueChanged" />
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Random_ML_Weight}">
<Slider x:Name="MLAvoidanceWeightSlider"
Minimum="0.1" Maximum="1.0" Width="200"
IsSnapToTickEnabled="True" Value="1.0" TickFrequency="0.1"
TickPlacement="None"
ValueChanged="MLAvoidanceWeightSlider_ValueChanged" />
</ui:SettingsCard>
<TextBlock Text="{i18n:I18n Key=Random_ML_Hint}"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
TextWrapping="Wrap" Margin="1,0,0,4" />
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="{i18n:I18n Key=Timer_Title}" />
<ui:SettingsCard Header="{i18n:I18n Key=Timer_UseLegacyButtons}">
<ui:ToggleSwitch x:Name="ToggleSwitchUseLegacyTimerUI"
IsOn="False"
Toggled="ToggleSwitchUseLegacyTimerUI_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Timer_NewUI}">
<ui:ToggleSwitch x:Name="ToggleSwitchUseNewStyleUI"
IsOn="False"
Toggled="ToggleSwitchUseNewStyleUI_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Timer_EnableCountUp}">
<ui:ToggleSwitch x:Name="ToggleSwitchEnableOvertimeCountUp"
IsOn="False"
Toggled="ToggleSwitchEnableOvertimeCountUp_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Timer_OvertimeHighlight}">
<ui:ToggleSwitch x:Name="ToggleSwitchEnableOvertimeRedText"
IsOn="True"
Toggled="ToggleSwitchEnableOvertimeRedText_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Timer_Volume}">
<Slider x:Name="TimerVolumeSlider"
Minimum="0" Maximum="1" Width="200"
IsSnapToTickEnabled="True" Value="1" TickFrequency="0.1"
TickPlacement="None"
ValueChanged="TimerVolumeSlider_ValueChanged" />
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Timer_CustomSoundLabel}">
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="8">
<Button x:Name="ButtonSelectCustomTimerSound" Content="{i18n:I18n Key=Timer_SelectFile}" Click="ButtonSelectCustomTimerSound_Click" />
<Button x:Name="ButtonResetTimerSound" Content="{i18n:I18n Key=Timer_Reset}" Click="ButtonResetTimerSound_Click" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Timer_Progressive}">
<ui:ToggleSwitch x:Name="ToggleSwitchEnableProgressiveReminder"
IsOn="False"
Toggled="ToggleSwitchEnableProgressiveReminder_Toggled"/>
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Timer_ProgressiveVolume}">
<Slider x:Name="ProgressiveReminderVolumeSlider"
Minimum="0" Maximum="1" Width="200"
IsSnapToTickEnabled="True" Value="1" TickFrequency="0.1"
TickPlacement="None"
ValueChanged="ProgressiveReminderVolumeSlider_ValueChanged" />
</ui:SettingsCard>
<ui:SettingsCard Header="{i18n:I18n Key=Timer_ProgressiveCustomLabel}">
<ikw:SimpleStackPanel Orientation="Horizontal" Spacing="8">
<Button x:Name="ButtonSelectCustomProgressiveReminderSound" Content="{i18n:I18n Key=Timer_ProgressiveSelectFile}" Click="ButtonSelectCustomProgressiveReminderSound_Click" />
<Button x:Name="ButtonResetProgressiveReminderSound" Content="{i18n:I18n Key=Timer_ProgressiveReset}" Click="ButtonResetProgressiveReminderSound_Click" />
</ikw:SimpleStackPanel>
</ui:SettingsCard>
<Rectangle Height="48" />
</ikw:SimpleStackPanel>
</Grid>
</Grid>
</ScrollViewer>
</ui:Page>
@@ -0,0 +1,346 @@
using Ink_Canvas.Helpers;
using Ink_Canvas.Windows.SettingsViews.Helpers;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Page = iNKORE.UI.WPF.Modern.Controls.Page;
namespace Ink_Canvas.Windows.SettingsViews.Pages
{
public partial class RandomDrawPage : Page
{
private bool _isLoaded = false;
public RandomDrawPage()
{
InitializeComponent();
Loaded += Page_Loaded;
Unloaded += Page_Unloaded;
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
LoadSettings();
_isLoaded = true;
}
private void Page_Unloaded(object sender, RoutedEventArgs e)
{
_isLoaded = false;
}
private MainWindow GetMainWindow() => Application.Current.MainWindow as MainWindow;
private void LoadSettings()
{
var settings = SettingsManager.Settings;
if (settings?.RandSettings == null) return;
ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn = settings.RandSettings.DisplayRandWindowNamesInputBtn;
RandWindowOnceCloseLatencySlider.Value = settings.RandSettings.RandWindowOnceCloseLatency;
RandWindowOnceMaxStudentsSlider.Value = settings.RandSettings.RandWindowOnceMaxStudents;
ToggleSwitchShowRandomAndSingleDraw.IsOn = settings.RandSettings.ShowRandomAndSingleDraw;
ToggleSwitchEnableQuickDraw.IsOn = settings.RandSettings.EnableQuickDraw;
ToggleSwitchExternalCaller.IsOn = settings.RandSettings.DirectCallCiRand;
ComboBoxExternalCallerType.SelectedIndex = settings.RandSettings.ExternalCallerType;
ToggleSwitchUseNewRollCallUI.IsOn = settings.RandSettings.UseNewRollCallUI;
ToggleSwitchEnableMLAvoidance.IsOn = settings.RandSettings.EnableMLAvoidance;
MLAvoidanceHistorySlider.Value = settings.RandSettings.MLAvoidanceHistoryCount;
MLAvoidanceWeightSlider.Value = settings.RandSettings.MLAvoidanceWeight;
ToggleSwitchUseLegacyTimerUI.IsOn = settings.RandSettings.UseLegacyTimerUI;
ToggleSwitchUseNewStyleUI.IsOn = settings.RandSettings.UseNewStyleUI;
ToggleSwitchEnableOvertimeCountUp.IsOn = settings.RandSettings.EnableOvertimeCountUp;
bool canEnableRedText = settings.RandSettings.EnableOvertimeCountUp && settings.RandSettings.EnableOvertimeRedText;
ToggleSwitchEnableOvertimeRedText.IsOn = canEnableRedText;
TimerVolumeSlider.Value = settings.RandSettings.TimerVolume;
ToggleSwitchEnableProgressiveReminder.IsOn = settings.RandSettings.EnableProgressiveReminder;
ProgressiveReminderVolumeSlider.Value = settings.RandSettings.ProgressiveReminderVolume;
UpdatePickNameBackgroundsInComboBox();
if (settings.RandSettings.SelectedBackgroundIndex >= ComboBoxPickNameBackground.Items.Count)
{
settings.RandSettings.SelectedBackgroundIndex = 0;
}
ComboBoxPickNameBackground.SelectedIndex = settings.RandSettings.SelectedBackgroundIndex;
}
#region Basic Settings
private void ToggleSwitchDisplayRandWindowNamesInputBtn_OnToggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.DisplayRandWindowNamesInputBtn = ToggleSwitchDisplayRandWindowNamesInputBtn.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void RandWindowOnceCloseLatencySlider_ValueChanged(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.RandWindowOnceCloseLatency = RandWindowOnceCloseLatencySlider.Value;
SettingsManager.SaveSettingsToFile();
}
private void RandWindowOnceMaxStudentsSlider_ValueChanged(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.RandWindowOnceMaxStudents = (int)RandWindowOnceMaxStudentsSlider.Value;
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchShowRandomAndSingleDraw_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
bool isToggled = ToggleSwitchShowRandomAndSingleDraw.IsOn;
SettingsManager.Settings.RandSettings.ShowRandomAndSingleDraw = isToggled;
var mw = GetMainWindow();
if (mw != null)
{
mw.BoardRandomDrawToolBtn.Visibility = isToggled ? Visibility.Visible : Visibility.Collapsed;
mw.BoardSingleDrawToolBtn.Visibility = isToggled ? Visibility.Visible : Visibility.Collapsed;
}
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchEnableQuickDraw_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.EnableQuickDraw = ToggleSwitchEnableQuickDraw.IsOn;
SettingsManager.SaveSettingsToFile();
var mw = GetMainWindow();
if (mw != null) mw.ShowQuickDrawFloatingButton();
}
private void ToggleSwitchExternalCaller_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.DirectCallCiRand = ToggleSwitchExternalCaller.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void ComboBoxExternalCallerType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.ExternalCallerType = ComboBoxExternalCallerType.SelectedIndex;
SettingsManager.SaveSettingsToFile();
}
#endregion
#region Background
private void UpdatePickNameBackgroundsInComboBox()
{
if (ComboBoxPickNameBackground == null) return;
while (ComboBoxPickNameBackground.Items.Count > 1)
{
ComboBoxPickNameBackground.Items.RemoveAt(ComboBoxPickNameBackground.Items.Count - 1);
}
foreach (var background in SettingsManager.Settings.RandSettings.CustomPickNameBackgrounds)
{
ComboBoxItem item = new ComboBoxItem();
item.Content = background.Name;
item.FontFamily = new FontFamily("Microsoft YaHei UI");
ComboBoxPickNameBackground.Items.Add(item);
}
}
private void ComboBoxPickNameBackground_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.SelectedBackgroundIndex = ComboBoxPickNameBackground.SelectedIndex;
SettingsManager.SaveSettingsToFile();
}
private void ButtonAddCustomBackground_Click(object sender, RoutedEventArgs e)
{
var mw = GetMainWindow();
if (mw == null) return;
AddPickNameBackgroundWindow dialog = new AddPickNameBackgroundWindow(mw);
dialog.Owner = mw;
dialog.ShowDialog();
if (dialog.IsSuccess)
{
ComboBoxPickNameBackground.SelectedIndex = ComboBoxPickNameBackground.Items.Count - 1;
}
}
private void ButtonManageBackgrounds_Click(object sender, RoutedEventArgs e)
{
var mw = GetMainWindow();
if (mw == null) return;
ManagePickNameBackgroundsWindow dialog = new ManagePickNameBackgroundsWindow(mw);
dialog.Owner = mw;
dialog.ShowDialog();
}
#endregion
#region New Roll Call UI
private void ToggleSwitchUseNewRollCallUI_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.UseNewRollCallUI = ToggleSwitchUseNewRollCallUI.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchEnableMLAvoidance_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.EnableMLAvoidance = ToggleSwitchEnableMLAvoidance.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void MLAvoidanceHistorySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.MLAvoidanceHistoryCount = (int)MLAvoidanceHistorySlider.Value;
SettingsManager.SaveSettingsToFile();
}
private void MLAvoidanceWeightSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.MLAvoidanceWeight = MLAvoidanceWeightSlider.Value;
SettingsManager.SaveSettingsToFile();
}
#endregion
#region Timer
private void ToggleSwitchUseLegacyTimerUI_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.UseLegacyTimerUI = ToggleSwitchUseLegacyTimerUI.IsOn;
if (ToggleSwitchUseLegacyTimerUI.IsOn)
{
ToggleSwitchUseNewStyleUI.IsOn = false;
SettingsManager.Settings.RandSettings.UseNewStyleUI = false;
}
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchUseNewStyleUI_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.UseNewStyleUI = ToggleSwitchUseNewStyleUI.IsOn;
if (ToggleSwitchUseNewStyleUI.IsOn)
{
ToggleSwitchUseLegacyTimerUI.IsOn = false;
SettingsManager.Settings.RandSettings.UseLegacyTimerUI = false;
}
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchEnableOvertimeCountUp_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.EnableOvertimeCountUp = ToggleSwitchEnableOvertimeCountUp.IsOn;
if (!ToggleSwitchEnableOvertimeCountUp.IsOn)
{
ToggleSwitchEnableOvertimeRedText.IsOn = false;
SettingsManager.Settings.RandSettings.EnableOvertimeRedText = false;
}
SettingsManager.SaveSettingsToFile();
}
private void ToggleSwitchEnableOvertimeRedText_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
if (ToggleSwitchEnableOvertimeRedText.IsOn && !ToggleSwitchEnableOvertimeCountUp.IsOn)
{
ToggleSwitchEnableOvertimeCountUp.IsOn = true;
SettingsManager.Settings.RandSettings.EnableOvertimeCountUp = true;
}
SettingsManager.Settings.RandSettings.EnableOvertimeRedText = ToggleSwitchEnableOvertimeRedText.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void TimerVolumeSlider_ValueChanged(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.TimerVolume = TimerVolumeSlider.Value;
SettingsManager.SaveSettingsToFile();
}
private void ButtonSelectCustomTimerSound_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog
{
Title = "选择计时器提醒铃声",
Filter = "音频文件 (*.wav)|*.wav|所有文件 (*.*)|*.*",
DefaultExt = "wav"
};
if (openFileDialog.ShowDialog() == true)
{
SettingsManager.Settings.RandSettings.CustomTimerSoundPath = openFileDialog.FileName;
SettingsManager.SaveSettingsToFile();
MessageBox.Show("自定义铃声设置成功!", "设置成功", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
private void ButtonResetTimerSound_Click(object sender, RoutedEventArgs e)
{
SettingsManager.Settings.RandSettings.CustomTimerSoundPath = "";
SettingsManager.SaveSettingsToFile();
MessageBox.Show("已重置为默认铃声!", "重置成功", MessageBoxButton.OK, MessageBoxImage.Information);
}
private void ToggleSwitchEnableProgressiveReminder_Toggled(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.EnableProgressiveReminder = ToggleSwitchEnableProgressiveReminder.IsOn;
SettingsManager.SaveSettingsToFile();
}
private void ProgressiveReminderVolumeSlider_ValueChanged(object sender, RoutedEventArgs e)
{
if (!_isLoaded) return;
SettingsManager.Settings.RandSettings.ProgressiveReminderVolume = ProgressiveReminderVolumeSlider.Value;
SettingsManager.SaveSettingsToFile();
}
private void ButtonSelectCustomProgressiveReminderSound_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog
{
Title = "选择渐进提醒音频文件",
Filter = "音频文件 (*.wav)|*.wav|所有文件 (*.*)|*.*",
DefaultExt = "wav"
};
if (openFileDialog.ShowDialog() == true)
{
SettingsManager.Settings.RandSettings.ProgressiveReminderSoundPath = openFileDialog.FileName;
SettingsManager.SaveSettingsToFile();
}
}
private void ButtonResetProgressiveReminderSound_Click(object sender, RoutedEventArgs e)
{
SettingsManager.Settings.RandSettings.ProgressiveReminderSoundPath = "";
SettingsManager.SaveSettingsToFile();
}
#endregion
}
}