feat: add editor setting
This commit is contained in:
@@ -16,8 +16,8 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.4.0" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="OneOf" Version="3.0.271" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="10.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Models {
|
||||
|
||||
public partial class EditorSetting : ObservableObject {
|
||||
|
||||
public EditorSetting() {
|
||||
// YYC MARK:
|
||||
// Due to the shitty conflict between CommunityToolkit.Mvvm and Nullable aware,
|
||||
// I was forcely set this field to clear all warning.
|
||||
GamePath = "";
|
||||
|
||||
// Initialize from singleton.
|
||||
FromSingleton();
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private Shared.TasSequenceKind sequenceKind;
|
||||
[ObservableProperty]
|
||||
private Shared.EditorLayoutKind editorLayout;
|
||||
[ObservableProperty]
|
||||
private Shared.EditorPasteMode pasteMode;
|
||||
[ObservableProperty]
|
||||
private int frameCount;
|
||||
[ObservableProperty]
|
||||
private string gamePath;
|
||||
|
||||
[MemberNotNull(nameof(SequenceKind))]
|
||||
[MemberNotNull(nameof(EditorLayout))]
|
||||
[MemberNotNull(nameof(PasteMode))]
|
||||
[MemberNotNull(nameof(FrameCount))]
|
||||
[MemberNotNull(nameof(GamePath))]
|
||||
private void FromSingleton() {
|
||||
var singleton = Shared.EditorConfiguration.Instance;
|
||||
|
||||
SequenceKind = singleton.SequenceKind;
|
||||
EditorLayout = singleton.EditorLayout;
|
||||
PasteMode = singleton.PasteMode;
|
||||
FrameCount = singleton.FrameCount;
|
||||
GamePath = singleton.GamePath;
|
||||
}
|
||||
|
||||
private void ToSingleton() {
|
||||
var singleton = Shared.EditorConfiguration.Instance;
|
||||
|
||||
singleton.SequenceKind = SequenceKind;
|
||||
singleton.EditorLayout = EditorLayout;
|
||||
singleton.PasteMode = PasteMode;
|
||||
singleton.FrameCount = FrameCount;
|
||||
singleton.GamePath = GamePath;
|
||||
}
|
||||
|
||||
public void Save() {
|
||||
ToSingleton();
|
||||
Shared.EditorConfiguration.Instance.Save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,28 +30,28 @@ namespace BallanceTasEditor.Frontend.Models {
|
||||
get => FileBody is null;
|
||||
}
|
||||
|
||||
public void NewFile(TasSequenceKind kind, int count, uint fps) {
|
||||
public void NewFile(Shared.TasSequenceKind kind, int count, uint fps) {
|
||||
// Check status
|
||||
if (IsFileLoaded) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
// Initialize sequence
|
||||
var seq = TasSequenceKindHelper.CreateSequenceByKind(kind);
|
||||
var seq = Shared.TasSequenceKindHelper.CreateSequenceByKind(kind);
|
||||
// Initialize items
|
||||
Backend.TasStorage.Init(seq, count, fps);
|
||||
// Set members
|
||||
FileBody = seq;
|
||||
}
|
||||
|
||||
public void LoadFile(TasSequenceKind kind, string path) {
|
||||
public void LoadFile(Shared.TasSequenceKind kind, string path) {
|
||||
// Check status
|
||||
if (IsFileLoaded) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
// Initialize sequence
|
||||
var seq = TasSequenceKindHelper.CreateSequenceByKind(kind);
|
||||
var seq = Shared.TasSequenceKindHelper.CreateSequenceByKind(kind);
|
||||
// Load into sequence
|
||||
Backend.TasStorage.Load(path, seq);
|
||||
// Set members
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Models {
|
||||
public enum TasSequenceKind {
|
||||
Array,
|
||||
DoubleLinkedList
|
||||
}
|
||||
|
||||
public static class TasSequenceKindHelper {
|
||||
public static Backend.ITasSequence CreateSequenceByKind(TasSequenceKind kind) {
|
||||
return kind switch {
|
||||
TasSequenceKind.Array => new Backend.ListTasSequence(),
|
||||
TasSequenceKind.DoubleLinkedList => new Backend.LegacyTasSequence(),
|
||||
_ => throw new UnreachableException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
using BallanceTasEditor.Frontend.Models;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Shared {
|
||||
public class EditorConfiguration {
|
||||
|
||||
public static readonly EditorConfiguration Instance = new EditorConfiguration();
|
||||
|
||||
private EditorConfiguration() {
|
||||
Init();
|
||||
}
|
||||
|
||||
public TasSequenceKind SequenceKind { get; set; }
|
||||
public EditorLayoutKind EditorLayout { get; set; }
|
||||
public EditorPasteMode PasteMode { get; set; }
|
||||
public int FrameCount { get; set; }
|
||||
public string GamePath { get; set; }
|
||||
|
||||
[MemberNotNull(nameof(SequenceKind))]
|
||||
[MemberNotNull(nameof(EditorLayout))]
|
||||
[MemberNotNull(nameof(PasteMode))]
|
||||
[MemberNotNull(nameof(FrameCount))]
|
||||
[MemberNotNull(nameof(GamePath))]
|
||||
private void FromRaw(RawEditorConfiguration raw) {
|
||||
SequenceKind = raw.SequenceKind;
|
||||
EditorLayout = raw.EditorLayout;
|
||||
PasteMode = raw.PasteMode;
|
||||
FrameCount = raw.FrameCount;
|
||||
GamePath = raw.GamePath;
|
||||
}
|
||||
|
||||
private RawEditorConfiguration ToRaw() {
|
||||
return new RawEditorConfiguration {
|
||||
SequenceKind = SequenceKind,
|
||||
EditorLayout = EditorLayout,
|
||||
PasteMode = PasteMode,
|
||||
FrameCount = FrameCount,
|
||||
GamePath = GamePath
|
||||
};
|
||||
}
|
||||
|
||||
private string GetSettingFilePath() {
|
||||
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
string selfAppDataPath = Path.Combine(appDataPath, "BallanceTasEditor");
|
||||
return Path.Combine(selfAppDataPath, "BallanceTasEditor.cfg");
|
||||
}
|
||||
|
||||
private bool Load() {
|
||||
try {
|
||||
using (var fs = new StreamReader(GetSettingFilePath(), Encoding.UTF8)) {
|
||||
// Read semester object.
|
||||
var raw = JsonConvert.DeserializeObject<RawEditorConfiguration>(fs.ReadToEnd()).Unwrap();
|
||||
// Apply to self.
|
||||
FromRaw(raw);
|
||||
}
|
||||
return true;
|
||||
} catch (Exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[MemberNotNull(nameof(SequenceKind))]
|
||||
[MemberNotNull(nameof(EditorLayout))]
|
||||
[MemberNotNull(nameof(PasteMode))]
|
||||
[MemberNotNull(nameof(FrameCount))]
|
||||
[MemberNotNull(nameof(GamePath))]
|
||||
private void Init() {
|
||||
var defaultRaw = new RawEditorConfiguration();
|
||||
FromRaw(defaultRaw);
|
||||
}
|
||||
|
||||
public void LoadOrInit() {
|
||||
if (!Load()) {
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
public void Save() {
|
||||
try {
|
||||
// Check file path directory.
|
||||
var settingFilePath = GetSettingFilePath();
|
||||
var settingFileDirectory = Path.GetDirectoryName(settingFilePath).Unwrap();
|
||||
if (!Directory.Exists(settingFileDirectory)) {
|
||||
Directory.CreateDirectory(settingFileDirectory);
|
||||
}
|
||||
// Write it.
|
||||
using (var fs = new StreamWriter(GetSettingFilePath(), false, Encoding.UTF8)) {
|
||||
fs.Write(JsonConvert.SerializeObject(ToRaw()));
|
||||
}
|
||||
} catch (Exception) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
private class RawEditorConfiguration {
|
||||
[JsonProperty("sequence_kind", Required = Required.Always)]
|
||||
[JsonConverter(typeof(TasSequenceKindConverter))]
|
||||
public TasSequenceKind SequenceKind { get; set; } = TasSequenceKind.Array;
|
||||
|
||||
[JsonProperty("editor_layout", Required = Required.Always)]
|
||||
[JsonConverter(typeof(EditorLayoutKindConverter))]
|
||||
public EditorLayoutKind EditorLayout { get; set; } = EditorLayoutKind.Vertical;
|
||||
|
||||
[JsonProperty("paste_mode", Required = Required.Always)]
|
||||
[JsonConverter(typeof(EditorPasteModeConverter))]
|
||||
public EditorPasteMode PasteMode { get; set; } = EditorPasteMode.Insert;
|
||||
|
||||
[JsonProperty("frame_count", Required = Required.Always)]
|
||||
public int FrameCount { get; set; } = 20;
|
||||
|
||||
[JsonProperty("game_path", Required = Required.Always)]
|
||||
public string GamePath { get; set; } = "";
|
||||
}
|
||||
|
||||
#region Custom JSON Converter
|
||||
|
||||
private class TasSequenceKindConverter : JsonConverter<TasSequenceKind> {
|
||||
public override TasSequenceKind ReadJson(JsonReader reader, Type objectType, TasSequenceKind existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
||||
if (reader.TokenType == JsonToken.String) {
|
||||
var value = (reader.Value as string).Unwrap();
|
||||
if (TasSequenceKindHelper.TryParse(value, out var kind)) {
|
||||
return kind;
|
||||
} else {
|
||||
throw new JsonSerializationException($"given string can not be parsed as TasSequenceKind: {value}");
|
||||
}
|
||||
} else {
|
||||
throw new JsonSerializationException($"expect a integer but got {reader.TokenType}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, TasSequenceKind value, JsonSerializer serializer) {
|
||||
writer.WriteValue(TasSequenceKindHelper.ToString(value));
|
||||
}
|
||||
}
|
||||
|
||||
private class EditorLayoutKindConverter : JsonConverter<EditorLayoutKind> {
|
||||
public override EditorLayoutKind ReadJson(JsonReader reader, Type objectType, EditorLayoutKind existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
||||
if (reader.TokenType == JsonToken.String) {
|
||||
var value = (reader.Value as string).Unwrap();
|
||||
if (EditorLayoutKindHelper.TryParse(value, out var kind)) {
|
||||
return kind;
|
||||
} else {
|
||||
throw new JsonSerializationException($"given string can not be parsed as EditorLayoutKind: {value}");
|
||||
}
|
||||
} else {
|
||||
throw new JsonSerializationException($"expect a integer but got {reader.TokenType}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, EditorLayoutKind value, JsonSerializer serializer) {
|
||||
writer.WriteValue(EditorLayoutKindHelper.ToString(value));
|
||||
}
|
||||
}
|
||||
|
||||
private class EditorPasteModeConverter : JsonConverter<EditorPasteMode> {
|
||||
public override EditorPasteMode ReadJson(JsonReader reader, Type objectType, EditorPasteMode existingValue, bool hasExistingValue, JsonSerializer serializer) {
|
||||
if (reader.TokenType == JsonToken.String) {
|
||||
var value = (reader.Value as string).Unwrap();
|
||||
if (EditorPasteModeHelper.TryParse(value, out var kind)) {
|
||||
return kind;
|
||||
} else {
|
||||
throw new JsonSerializationException($"given string can not be parsed as EditorPasteMode: {value}");
|
||||
}
|
||||
} else {
|
||||
throw new JsonSerializationException($"expect a integer but got {reader.TokenType}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, EditorPasteMode value, JsonSerializer serializer) {
|
||||
writer.WriteValue(EditorPasteModeHelper.ToString(value));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
106
BallanceTasEditor/BallanceTasEditor/Frontend/Shared/Enums.cs
Normal file
106
BallanceTasEditor/BallanceTasEditor/Frontend/Shared/Enums.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Shared {
|
||||
|
||||
public enum TasSequenceKind {
|
||||
Array,
|
||||
DoubleLinkedList
|
||||
}
|
||||
|
||||
public static class TasSequenceKindHelper {
|
||||
public static Backend.ITasSequence CreateSequenceByKind(TasSequenceKind kind) {
|
||||
return kind switch {
|
||||
TasSequenceKind.Array => new Backend.ListTasSequence(),
|
||||
TasSequenceKind.DoubleLinkedList => new Backend.LegacyTasSequence(),
|
||||
_ => throw new UnreachableException(),
|
||||
};
|
||||
}
|
||||
|
||||
public static bool TryParse(string s, out TasSequenceKind value) {
|
||||
switch (s) {
|
||||
case "array":
|
||||
value = TasSequenceKind.Array;
|
||||
return true;
|
||||
case "double_linked_list":
|
||||
value = TasSequenceKind.DoubleLinkedList;
|
||||
return true;
|
||||
default:
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToString(TasSequenceKind kind) {
|
||||
return kind switch {
|
||||
TasSequenceKind.Array => "array",
|
||||
TasSequenceKind.DoubleLinkedList => "double_linked_list",
|
||||
_ => throw new UnreachableException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum EditorLayoutKind {
|
||||
Vertical,
|
||||
Horizontal
|
||||
}
|
||||
|
||||
public static class EditorLayoutKindHelper {
|
||||
public static bool TryParse(string s, out EditorLayoutKind value) {
|
||||
switch (s) {
|
||||
case "vertical":
|
||||
value = EditorLayoutKind.Vertical;
|
||||
return true;
|
||||
case "horizontal":
|
||||
value = EditorLayoutKind.Horizontal;
|
||||
return true;
|
||||
default:
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static string ToString(EditorLayoutKind kind) {
|
||||
return kind switch {
|
||||
EditorLayoutKind.Vertical => "vertical",
|
||||
EditorLayoutKind.Horizontal => "horizontal",
|
||||
_ => throw new UnreachableException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum EditorPasteMode {
|
||||
Insert,
|
||||
Override
|
||||
}
|
||||
|
||||
public static class EditorPasteModeHelper {
|
||||
public static bool TryParse(string s, out EditorPasteMode value) {
|
||||
switch (s) {
|
||||
case "insert":
|
||||
value = EditorPasteMode.Insert;
|
||||
return true;
|
||||
case "override":
|
||||
value = EditorPasteMode.Override;
|
||||
return true;
|
||||
default:
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToString(EditorPasteMode mode) {
|
||||
return mode switch {
|
||||
EditorPasteMode.Insert => "insert",
|
||||
EditorPasteMode.Override => "override",
|
||||
_ => throw new UnreachableException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -57,7 +57,7 @@ namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
if (dialog is null) return;
|
||||
|
||||
// Create new file
|
||||
TasFile.NewFile(Models.TasSequenceKind.Array, dialog.Count, dialog.Fps);
|
||||
TasFile.NewFile(Shared.TasSequenceKind.Array, dialog.Count, dialog.Fps);
|
||||
// Set members
|
||||
TasFilePath = null;
|
||||
// Send notification
|
||||
@@ -76,7 +76,7 @@ namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
|
||||
// Load file
|
||||
try {
|
||||
TasFile.LoadFile(Models.TasSequenceKind.Array, dialog.Path);
|
||||
TasFile.LoadFile(Shared.TasSequenceKind.Array, dialog.Path);
|
||||
} catch (Exception e) {
|
||||
m_DialogService.ShowOpenFileFailedDialog(e);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user