VPet.Solution 保存初始化

This commit is contained in:
Hakoyu 2024-01-09 23:22:25 +08:00
parent 204af1d109
commit 2993c5d5eb
13 changed files with 229 additions and 25 deletions

View File

@ -10,6 +10,6 @@
<c:BoolToVisibilityConverter x:Key="FalseToHiddenConverter" /> <c:BoolToVisibilityConverter x:Key="FalseToHiddenConverter" />
<c:EqualsConverter x:Key="EqualsConverter" /> <c:EqualsConverter x:Key="EqualsConverter" />
<c:EqualsConverter x:Key="NotEqualsConverter" Inverter="True" /> <c:EqualsConverter x:Key="NotEqualsConverter" Inverter="True" />
<c:ValueToBoolConverter x:Key="NullToFalse" /> <c:ValueToBoolConverter x:Key="NullToFalse" Invert="True" />
<c:BoolInverter x:Key="BoolInverter" /> <c:BoolInverter x:Key="BoolInverter" />
</ResourceDictionary> </ResourceDictionary>

View File

@ -14,7 +14,7 @@ public class BoolToVisibilityConverter : BoolToValueConverterBase<BoolToVisibili
DependencyProperty.Register( DependencyProperty.Register(
nameof(TrueVisibilityValue), nameof(TrueVisibilityValue),
typeof(Visibility), typeof(Visibility),
typeof(AllIsBoolToVisibilityConverter), typeof(BoolToVisibilityConverter),
new PropertyMetadata(Visibility.Visible) new PropertyMetadata(Visibility.Visible)
); );
@ -35,7 +35,7 @@ public class BoolToVisibilityConverter : BoolToValueConverterBase<BoolToVisibili
DependencyProperty.Register( DependencyProperty.Register(
nameof(FalseVisibilityValue), nameof(FalseVisibilityValue),
typeof(Visibility), typeof(Visibility),
typeof(AllIsBoolToVisibilityConverter), typeof(BoolToVisibilityConverter),
new PropertyMetadata(Visibility.Hidden) new PropertyMetadata(Visibility.Hidden)
); );

View File

@ -1,15 +1,77 @@
using HKW.WPF.Converters; using HKW.WPF.Converters;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
namespace HKW.WPF.Converters; namespace HKW.WPF.Converters;
public class ValueToBoolConverter : ValueConverterBase public class ValueToBoolConverter : ValueConverterBase
{ {
/// <summary>
///
/// </summary>
public static readonly DependencyProperty TargetValueProperty = DependencyProperty.Register(
nameof(TargetValue),
typeof(object),
typeof(ValueToBoolConverter),
new PropertyMetadata(null)
);
/// <summary>
/// 目标值
/// </summary>
[DefaultValue(true)]
public object TargetValue
{
get => (object)GetValue(TargetValueProperty);
set => SetValue(TargetValueProperty, value);
}
/// <summary>
///
/// </summary>
public static readonly DependencyProperty InvertProperty = DependencyProperty.Register(
nameof(Invert),
typeof(bool),
typeof(ValueToBoolConverter),
new PropertyMetadata(false)
);
/// <summary>
/// 颠倒
/// </summary>
[DefaultValue(false)]
public bool Invert
{
get => (bool)GetValue(InvertProperty);
set => SetValue(InvertProperty, value);
}
/// <summary>
///
/// </summary>
public static readonly DependencyProperty NullValueProperty = DependencyProperty.Register(
nameof(NullValue),
typeof(bool),
typeof(ValueToBoolConverter),
new PropertyMetadata(false)
);
/// <summary>
/// 为空值时布尔值
/// </summary>
[DefaultValue(false)]
public bool NullValue
{
get => (bool)GetValue(NullValueProperty);
set => SetValue(NullValueProperty, value);
}
public override object Convert( public override object Convert(
object value, object value,
Type targetType, Type targetType,
@ -17,6 +79,8 @@ public class ValueToBoolConverter : ValueConverterBase
CultureInfo culture CultureInfo culture
) )
{ {
throw new NotImplementedException(); if (value is null)
return NullValue;
return value.Equals(TargetValue) ^ Invert;
} }
} }

View File

@ -1,5 +1,6 @@
using FastMember; using FastMember;
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using LinePutScript;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows; using System.Windows;
@ -24,7 +25,7 @@ public class SettingModel : ObservableClass<SettingModel>
private string _filePath; private string _filePath;
/// <summary> /// <summary>
/// 路径 /// 文件路径
/// </summary> /// </summary>
public string FilePath public string FilePath
{ {
@ -54,15 +55,21 @@ public class SettingModel : ObservableClass<SettingModel>
set => SetProperty(ref _interactiveSetting, value); set => SetProperty(ref _interactiveSetting, value);
} }
private static HashSet<string> _settingProperties =
new(typeof(Setting).GetProperties().Select(p => p.Name));
private Setting _setting;
public SettingModel(Setting setting) public SettingModel(Setting setting)
{ {
GraphicsSetting = LoadGraphicsSettings(setting); _setting = setting;
GraphicsSetting = LoadGraphicsSettings();
} }
private GraphicsSettingModel LoadGraphicsSettings(Setting setting) private GraphicsSettingModel LoadGraphicsSettings()
{ {
var graphicsSettings = new GraphicsSettingModel(); var graphicsSettings = new GraphicsSettingModel();
var sourceAccessor = ObjectAccessor.Create(setting); var sourceAccessor = ObjectAccessor.Create(_setting);
var targetAccessor = ObjectAccessor.Create(graphicsSettings); var targetAccessor = ObjectAccessor.Create(graphicsSettings);
foreach (var property in typeof(GraphicsSettingModel).GetProperties()) foreach (var property in typeof(GraphicsSettingModel).GetProperties())
{ {
@ -77,4 +84,33 @@ public class SettingModel : ObservableClass<SettingModel>
} }
return graphicsSettings; return graphicsSettings;
} }
public void Save()
{
SaveGraphicsSettings();
File.WriteAllText(FilePath, _setting.ToString());
}
private void SaveGraphicsSettings()
{
var sourceAccessor = ObjectAccessor.Create(GraphicsSetting);
var targetAccessor = ObjectAccessor.Create(_setting);
foreach (var property in typeof(GraphicsSettingModel).GetProperties())
{
//if (_settingProperties.Contains(property.Name) is false)
// continue;
var sourceValue = sourceAccessor[property.Name];
var targetValue = targetAccessor[property.Name];
if (sourceValue.Equals(targetValue))
continue;
if (sourceValue is ObservablePoint point)
{
targetAccessor[property.Name] = point.ToPoint();
}
else
{
targetAccessor[property.Name] = sourceValue;
}
}
}
} }

View File

@ -8,7 +8,7 @@ namespace HKW.HKWUtils.Observable;
/// 具有参数的可观察命令 /// 具有参数的可观察命令
/// </summary> /// </summary>
[DebuggerDisplay("\\{ObservableCommand, CanExecute = {IsCanExecute.Value}\\}")] [DebuggerDisplay("\\{ObservableCommand, CanExecute = {IsCanExecute.Value}\\}")]
public class ObservableCommand<T> : ObservableClass<ObservableCommand>, ICommand public class ObservableCommand<T> : ObservableClass<ObservableCommand<T>>, ICommand
{ {
bool _isCanExecute = true; bool _isCanExecute = true;

View File

@ -325,6 +325,11 @@ public static class Extensions
private static Dictionary<Window, WindowCloseState> _windowCloseStates = new(); private static Dictionary<Window, WindowCloseState> _windowCloseStates = new();
/// <summary>
/// 设置关闭状态
/// </summary>
/// <param name="window"></param>
/// <param name="state">关闭状态</param>
public static void SetCloseState(this Window window, WindowCloseState state) public static void SetCloseState(this Window window, WindowCloseState state)
{ {
window.Closing -= WindowCloseState_Closing; window.Closing -= WindowCloseState_Closing;
@ -332,13 +337,32 @@ public static class Extensions
_windowCloseStates[window] = state; _windowCloseStates[window] = state;
} }
public static void CloseX(this Window window) /// <summary>
/// 强制关闭
/// </summary>
/// <param name="window"></param>
public static void CloseX(this Window? window)
{ {
if (window is null)
return;
_windowCloseStates.Remove(window); _windowCloseStates.Remove(window);
window.Closing -= WindowCloseState_Closing; window.Closing -= WindowCloseState_Closing;
window.Close(); window.Close();
} }
/// <summary>
/// 显示或者聚焦
/// </summary>
/// <param name="window"></param>
public static void ShowOrActivate(this Window? window)
{
if (window is null)
return;
if (window.IsVisible is false)
window.Show();
window.Activate();
}
private static void WindowCloseState_Closing(object sender, CancelEventArgs e) private static void WindowCloseState_Closing(object sender, CancelEventArgs e)
{ {
if (sender is not Window window) if (sender is not Window window)

View File

@ -46,6 +46,11 @@ public class ObservablePoint : ObservableClass<ObservablePoint>, IEquatable<Obse
return new(X, Y); return new(X, Y);
} }
public Point ToPoint()
{
return new Point(X, Y);
}
#region Other #region Other
/// <inheritdoc/> /// <inheritdoc/>

View File

@ -25,7 +25,10 @@ public class GraphicsSettingPageVM : ObservableClass<GraphicsSettingPageVM>
private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e) private void Current_PropertyChangedX(SettingWindowVM sender, PropertyChangedXEventArgs e)
{ {
if (e.PropertyName == nameof(SettingWindowVM.CurrentSetting)) if (
e.PropertyName == nameof(SettingWindowVM.CurrentSetting)
&& sender.CurrentSetting is not null
)
{ {
GraphicsSetting = sender.CurrentSetting.GraphicsSetting; GraphicsSetting = sender.CurrentSetting.GraphicsSetting;
} }

View File

@ -1,5 +1,6 @@
using HKW.HKWUtils.Observable; using HKW.HKWUtils.Observable;
using LinePutScript; using LinePutScript;
using Panuon.WPF.UI;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -7,8 +8,10 @@ using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
using VPet.Solution.Models; using VPet.Solution.Models;
using VPet.Solution.Models.SettingEditor; using VPet.Solution.Models.SettingEditor;
using VPet.Solution.Views.SettingEditor;
using VPet_Simulator.Windows.Interface; using VPet_Simulator.Windows.Interface;
namespace VPet.Solution.ViewModels.SettingEditor; namespace VPet.Solution.ViewModels.SettingEditor;
@ -17,6 +20,7 @@ public class SettingWindowVM : ObservableClass<SettingWindowVM>
{ {
public static SettingWindowVM Current { get; private set; } public static SettingWindowVM Current { get; private set; }
#region Properties
private SettingModel _currentSettings; private SettingModel _currentSettings;
public SettingModel CurrentSetting public SettingModel CurrentSetting
{ {
@ -40,6 +44,13 @@ public class SettingWindowVM : ObservableClass<SettingWindowVM>
set => SetProperty(ref _searchSetting, value); set => SetProperty(ref _searchSetting, value);
} }
#endregion
#region Command
public ObservableCommand ResetSettingCommand { get; } = new();
public ObservableCommand<SettingModel> SaveSettingCommand { get; } = new();
public ObservableCommand SaveAllSettingCommand { get; } = new();
#endregion
public SettingWindowVM() public SettingWindowVM()
{ {
Current = this; Current = this;
@ -49,18 +60,49 @@ public class SettingWindowVM : ObservableClass<SettingWindowVM>
_settings.Add(s); _settings.Add(s);
PropertyChanged += MainWindowVM_PropertyChanged; PropertyChanged += MainWindowVM_PropertyChanged;
ResetSettingCommand.ExecuteCommand += ResetSettingCommand_ExecuteCommand;
SaveSettingCommand.ExecuteCommand += SaveSettingCommand_ExecuteCommand;
}
private void SaveSettingCommand_ExecuteCommand(SettingModel parameter)
{
parameter.Save();
}
private void ResetSettingCommand_ExecuteCommand()
{
if (
MessageBoxX.Show(
SettingWindow.Instance,
"确定重置吗",
"",
MessageBoxButton.YesNo,
MessageBoxIcon.Warning
)
is not MessageBoxResult.Yes
)
return;
CurrentSetting = _settings[_settings.IndexOf(CurrentSetting)] = new SettingModel(
new Setting("")
);
RefreshShowSettings(SearchSetting);
}
public void RefreshShowSettings(string name)
{
if (string.IsNullOrWhiteSpace(name))
ShowSettings = _settings;
else
ShowSettings = _settings.Where(
s => s.Name.Contains(SearchSetting, StringComparison.OrdinalIgnoreCase)
);
} }
private void MainWindowVM_PropertyChanged(object sender, PropertyChangedEventArgs e) private void MainWindowVM_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(SearchSetting)) if (e.PropertyName == nameof(SearchSetting))
{ {
if (string.IsNullOrWhiteSpace(SearchSetting)) RefreshShowSettings(SearchSetting);
ShowSettings = _settings;
else
ShowSettings = _settings.Where(
s => s.Name.Contains(SearchSetting, StringComparison.OrdinalIgnoreCase)
);
} }
} }

View File

@ -37,8 +37,6 @@ public partial class MainWindow : WindowX
private void Button_OpenSettingEditor_Click(object sender, RoutedEventArgs e) private void Button_OpenSettingEditor_Click(object sender, RoutedEventArgs e)
{ {
if (SettingWindow.IsVisible is false) SettingWindow.ShowOrActivate();
SettingWindow.Show();
SettingWindow.Activate();
} }
} }

View File

@ -274,7 +274,8 @@
Style="{DynamicResource Switch_BaseStyle}" Style="{DynamicResource Switch_BaseStyle}"
ToolTip="{ll:Str '从Steam启动该游戏, 统计时长不能停'}" /> ToolTip="{ll:Str '从Steam启动该游戏, 统计时长不能停'}" />
</Grid> </Grid>
<Grid MinHeight="40"> <!-- 无需设置 -->
<!--<Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition /> <ColumnDefinition />
@ -302,7 +303,7 @@
Text="{ll:Str '动画描述...'}" Text="{ll:Str '动画描述...'}"
TextWrapping="WrapWithOverflow" /> TextWrapping="WrapWithOverflow" />
</Grid> </Grid>
</Grid> </Grid>-->
<Grid MinHeight="40"> <Grid MinHeight="40">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />

View File

@ -26,6 +26,8 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition /> <RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBox Style="{DynamicResource StandardTextBoxStyle}" Text="{Binding SearchSetting, UpdateSourceTrigger=PropertyChanged}" /> <TextBox Style="{DynamicResource StandardTextBoxStyle}" Text="{Binding SearchSetting, UpdateSourceTrigger=PropertyChanged}" />
<ListBox <ListBox
@ -37,18 +39,44 @@
Style="{DynamicResource SideMenuListBoxStyle}"> Style="{DynamicResource SideMenuListBoxStyle}">
<ListBox.ItemContainerStyle> <ListBox.ItemContainerStyle>
<Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem"> <Style BasedOn="{StaticResource {x:Type ListBoxItem}}" TargetType="ListBoxItem">
<Setter Property="Tag" Value="{Binding DataContext, RelativeSource={RelativeSource AncestorType=Window}}" />
<Setter Property="Content" Value="{Binding Name}" /> <Setter Property="Content" Value="{Binding Name}" />
<Setter Property="ToolTip" Value="{Binding Path}" /> <Setter Property="ToolTip" Value="{Binding FilePath}" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem
Command="{Binding PlacementTarget.Tag.SaveSettingCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
Header="{ll:Str 保存}" />
</ContextMenu>
</Setter.Value>
</Setter>
</Style> </Style>
</ListBox.ItemContainerStyle> </ListBox.ItemContainerStyle>
</ListBox> </ListBox>
<Button
Grid.Row="2"
Margin="0"
HorizontalAlignment="Stretch"
Command="{Binding ResetSettingCommand}"
Content="{ll:Str 重置选中的设置}"
IsEnabled="{Binding SelectedItem, ElementName=ListBox_Saves, Converter={StaticResource NullToFalse}}"
Style="{DynamicResource Button_BaseStyle}" />
<Button
Grid.Row="3"
Margin="0"
HorizontalAlignment="Stretch"
Command="{Binding SaveAllSettingCommand}"
Content="{ll:Str 全部保存}"
Style="{DynamicResource Button_BaseStyle}" />
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<ListBox x:Name="ListBox_Main" Style="{DynamicResource SideMenuListBoxStyle}"> <ListBox x:Name="ListBox_Pages" Style="{DynamicResource SideMenuListBoxStyle}">
<ListBox.ItemsPanel> <ListBox.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" /> <StackPanel Orientation="Horizontal" />
@ -64,7 +92,7 @@
<Frame <Frame
x:Name="Frame_Main" x:Name="Frame_Main"
Grid.Row="1" Grid.Row="1"
Content="{Binding SelectedItem.Tag, ElementName=ListBox_Main}" Content="{Binding SelectedItem.Tag, ElementName=ListBox_Pages}"
ContentRendered="Frame_Main_ContentRendered" ContentRendered="Frame_Main_ContentRendered"
NavigationUIVisibility="Hidden" /> NavigationUIVisibility="Hidden" />
<!--<TabControl <!--<TabControl

View File

@ -12,6 +12,7 @@ namespace VPet.Solution.Views.SettingEditor;
/// </summary> /// </summary>
public partial class SettingWindow : WindowX public partial class SettingWindow : WindowX
{ {
public static SettingWindow Instance { get; private set; }
public SettingWindowVM ViewModel => (SettingWindowVM)DataContext; public SettingWindowVM ViewModel => (SettingWindowVM)DataContext;
public SettingWindow() public SettingWindow()
@ -26,6 +27,8 @@ public partial class SettingWindow : WindowX
ListBoxItem_CustomizedSettings.Tag = new CustomizedSettingPage(); ListBoxItem_CustomizedSettings.Tag = new CustomizedSettingPage();
ListBoxItem_DiagnosticSettings.Tag = new DiagnosticSettingPage(); ListBoxItem_DiagnosticSettings.Tag = new DiagnosticSettingPage();
ListBoxItem_ModSettings.Tag = new ModSettingPage(); ListBoxItem_ModSettings.Tag = new ModSettingPage();
ListBox_Pages.SelectedIndex = 0;
Instance = this;
} }
private void Frame_Main_ContentRendered(object sender, EventArgs e) private void Frame_Main_ContentRendered(object sender, EventArgs e)