diff --git a/BallanceTasEditor/BallanceTasEditor/Frontend/Converters/RadioButtonConverter.cs b/BallanceTasEditor/BallanceTasEditor/Frontend/Converters/RadioButtonConverter.cs new file mode 100644 index 0000000..c1b623f --- /dev/null +++ b/BallanceTasEditor/BallanceTasEditor/Frontend/Converters/RadioButtonConverter.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; + +namespace BallanceTasEditor.Frontend.Converters { + + internal class GenericEnumRadioButtonConverter where T: struct { + public object Convert(object value, object parameter) { + var susValue = value as T?; + var susParam = parameter as T?; + + if (susValue is null || susParam is null) { + return Binding.DoNothing; + } else { + return susValue.Value.Equals(susParam.Value); + } + } + + public object ConvertBack(object value, object parameter) { + var susValue = value as bool?; + var susParam = parameter as T?; + + if (susValue is null || susParam is null) { + return Binding.DoNothing; + } else { + return susValue.Value ? susParam.Value : Binding.DoNothing; + } + } + } + + [ValueConversion(typeof(Shared.SequenceKind), typeof(bool))] + public class SequenceKindRadioButtonConverter : IValueConverter { + public static readonly SequenceKindRadioButtonConverter Instance = new(); + + private readonly GenericEnumRadioButtonConverter m_Inner = new(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { + return m_Inner.Convert(value, parameter); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { + return m_Inner.ConvertBack(value, parameter); + } + } + + [ValueConversion(typeof(Shared.EditorLayoutKind), typeof(bool))] + public class EditorLayoutKindRadioButtonConverter : IValueConverter { + public static readonly EditorLayoutKindRadioButtonConverter Instance = new(); + + private readonly GenericEnumRadioButtonConverter m_Inner = new(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { + return m_Inner.Convert(value, parameter); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { + return m_Inner.ConvertBack(value, parameter); + } + } + + [ValueConversion(typeof(Shared.EditorPasteBehavior), typeof(bool))] + public class EditorPasteBehaviorRadioButtonConverter : IValueConverter { + public static readonly EditorPasteBehaviorRadioButtonConverter Instance = new(); + + private readonly GenericEnumRadioButtonConverter m_Inner = new(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { + return m_Inner.Convert(value, parameter); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { + return m_Inner.ConvertBack(value, parameter); + } + } + +} diff --git a/BallanceTasEditor/BallanceTasEditor/Frontend/Models/EditorSetting.cs b/BallanceTasEditor/BallanceTasEditor/Frontend/Models/EditorSetting.cs index 1f7011d..734cac7 100644 --- a/BallanceTasEditor/BallanceTasEditor/Frontend/Models/EditorSetting.cs +++ b/BallanceTasEditor/BallanceTasEditor/Frontend/Models/EditorSetting.cs @@ -23,11 +23,11 @@ namespace BallanceTasEditor.Frontend.Models { } [ObservableProperty] - private Shared.TasSequenceKind sequenceKind; + private Shared.SequenceKind sequenceKind; [ObservableProperty] private Shared.EditorLayoutKind editorLayout; [ObservableProperty] - private Shared.EditorPasteMode pasteMode; + private Shared.EditorPasteBehavior pasteBehavior; [ObservableProperty] private int frameCount; [ObservableProperty] @@ -35,7 +35,7 @@ namespace BallanceTasEditor.Frontend.Models { [MemberNotNull(nameof(SequenceKind))] [MemberNotNull(nameof(EditorLayout))] - [MemberNotNull(nameof(PasteMode))] + [MemberNotNull(nameof(PasteBehavior))] [MemberNotNull(nameof(FrameCount))] [MemberNotNull(nameof(GamePath))] private void FromSingleton() { @@ -43,7 +43,7 @@ namespace BallanceTasEditor.Frontend.Models { SequenceKind = singleton.SequenceKind; EditorLayout = singleton.EditorLayout; - PasteMode = singleton.PasteMode; + PasteBehavior = singleton.PasteBehavior; FrameCount = singleton.FrameCount; GamePath = singleton.GamePath; } @@ -53,7 +53,7 @@ namespace BallanceTasEditor.Frontend.Models { singleton.SequenceKind = SequenceKind; singleton.EditorLayout = EditorLayout; - singleton.PasteMode = PasteMode; + singleton.PasteBehavior = PasteBehavior; singleton.FrameCount = FrameCount; singleton.GamePath = GamePath; } diff --git a/BallanceTasEditor/BallanceTasEditor/Frontend/Models/TasFile.cs b/BallanceTasEditor/BallanceTasEditor/Frontend/Models/TasFile.cs index 730e421..f1faf16 100644 --- a/BallanceTasEditor/BallanceTasEditor/Frontend/Models/TasFile.cs +++ b/BallanceTasEditor/BallanceTasEditor/Frontend/Models/TasFile.cs @@ -30,28 +30,28 @@ namespace BallanceTasEditor.Frontend.Models { get => FileBody is null; } - public void NewFile(Shared.TasSequenceKind kind, int count, uint fps) { + public void NewFile(Shared.SequenceKind kind, int count, uint fps) { // Check status if (IsFileLoaded) { throw new InvalidOperationException(); } // Initialize sequence - var seq = Shared.TasSequenceKindHelper.CreateSequenceByKind(kind); + var seq = Shared.SequenceKindHelper.CreateSequenceByKind(kind); // Initialize items Backend.TasStorage.Init(seq, count, fps); // Set members FileBody = seq; } - public void LoadFile(Shared.TasSequenceKind kind, string path) { + public void LoadFile(Shared.SequenceKind kind, string path) { // Check status if (IsFileLoaded) { throw new InvalidOperationException(); } // Initialize sequence - var seq = Shared.TasSequenceKindHelper.CreateSequenceByKind(kind); + var seq = Shared.SequenceKindHelper.CreateSequenceByKind(kind); // Load into sequence Backend.TasStorage.Load(path, seq); // Set members diff --git a/BallanceTasEditor/BallanceTasEditor/Frontend/Shared/EditorConfiguration.cs b/BallanceTasEditor/BallanceTasEditor/Frontend/Shared/EditorConfiguration.cs index c304eb0..b033411 100644 --- a/BallanceTasEditor/BallanceTasEditor/Frontend/Shared/EditorConfiguration.cs +++ b/BallanceTasEditor/BallanceTasEditor/Frontend/Shared/EditorConfiguration.cs @@ -18,21 +18,21 @@ namespace BallanceTasEditor.Frontend.Shared { Init(); } - public TasSequenceKind SequenceKind { get; set; } + public SequenceKind SequenceKind { get; set; } public EditorLayoutKind EditorLayout { get; set; } - public EditorPasteMode PasteMode { get; set; } + public EditorPasteBehavior PasteBehavior { get; set; } public int FrameCount { get; set; } public string GamePath { get; set; } [MemberNotNull(nameof(SequenceKind))] [MemberNotNull(nameof(EditorLayout))] - [MemberNotNull(nameof(PasteMode))] + [MemberNotNull(nameof(PasteBehavior))] [MemberNotNull(nameof(FrameCount))] [MemberNotNull(nameof(GamePath))] private void FromRaw(RawEditorConfiguration raw) { SequenceKind = raw.SequenceKind; EditorLayout = raw.EditorLayout; - PasteMode = raw.PasteMode; + PasteBehavior = raw.PasteBehavior; FrameCount = raw.FrameCount; GamePath = raw.GamePath; } @@ -41,7 +41,7 @@ namespace BallanceTasEditor.Frontend.Shared { return new RawEditorConfiguration { SequenceKind = SequenceKind, EditorLayout = EditorLayout, - PasteMode = PasteMode, + PasteBehavior = PasteBehavior, FrameCount = FrameCount, GamePath = GamePath }; @@ -69,7 +69,7 @@ namespace BallanceTasEditor.Frontend.Shared { [MemberNotNull(nameof(SequenceKind))] [MemberNotNull(nameof(EditorLayout))] - [MemberNotNull(nameof(PasteMode))] + [MemberNotNull(nameof(PasteBehavior))] [MemberNotNull(nameof(FrameCount))] [MemberNotNull(nameof(GamePath))] private void Init() { @@ -103,15 +103,15 @@ namespace BallanceTasEditor.Frontend.Shared { private class RawEditorConfiguration { [JsonProperty("sequence_kind", Required = Required.Always)] [JsonConverter(typeof(TasSequenceKindConverter))] - public TasSequenceKind SequenceKind { get; set; } = TasSequenceKind.Array; + public SequenceKind SequenceKind { get; set; } = SequenceKind.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("paste_behavior", Required = Required.Always)] + [JsonConverter(typeof(EditorPasteBehaviorConverter))] + public EditorPasteBehavior PasteBehavior { get; set; } = EditorPasteBehavior.Insert; [JsonProperty("frame_count", Required = Required.Always)] public int FrameCount { get; set; } = 20; @@ -122,11 +122,11 @@ namespace BallanceTasEditor.Frontend.Shared { #region Custom JSON Converter - private class TasSequenceKindConverter : JsonConverter { - public override TasSequenceKind ReadJson(JsonReader reader, Type objectType, TasSequenceKind existingValue, bool hasExistingValue, JsonSerializer serializer) { + private class TasSequenceKindConverter : JsonConverter { + public override SequenceKind ReadJson(JsonReader reader, Type objectType, SequenceKind existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { var value = (reader.Value as string).Unwrap(); - if (TasSequenceKindHelper.TryParse(value, out var kind)) { + if (SequenceKindHelper.TryParse(value, out var kind)) { return kind; } else { throw new JsonSerializationException($"given string can not be parsed as TasSequenceKind: {value}"); @@ -136,8 +136,8 @@ namespace BallanceTasEditor.Frontend.Shared { } } - public override void WriteJson(JsonWriter writer, TasSequenceKind value, JsonSerializer serializer) { - writer.WriteValue(TasSequenceKindHelper.ToString(value)); + public override void WriteJson(JsonWriter writer, SequenceKind value, JsonSerializer serializer) { + writer.WriteValue(SequenceKindHelper.ToString(value)); } } @@ -160,22 +160,22 @@ namespace BallanceTasEditor.Frontend.Shared { } } - private class EditorPasteModeConverter : JsonConverter { - public override EditorPasteMode ReadJson(JsonReader reader, Type objectType, EditorPasteMode existingValue, bool hasExistingValue, JsonSerializer serializer) { + private class EditorPasteBehaviorConverter : JsonConverter { + public override EditorPasteBehavior ReadJson(JsonReader reader, Type objectType, EditorPasteBehavior existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { var value = (reader.Value as string).Unwrap(); - if (EditorPasteModeHelper.TryParse(value, out var kind)) { + if (EditorPasteBehaviorHelper.TryParse(value, out var kind)) { return kind; } else { - throw new JsonSerializationException($"given string can not be parsed as EditorPasteMode: {value}"); + throw new JsonSerializationException($"given string can not be parsed as EditorPasteBehavior: {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)); + public override void WriteJson(JsonWriter writer, EditorPasteBehavior value, JsonSerializer serializer) { + writer.WriteValue(EditorPasteBehaviorHelper.ToString(value)); } } diff --git a/BallanceTasEditor/BallanceTasEditor/Frontend/Shared/Enums.cs b/BallanceTasEditor/BallanceTasEditor/Frontend/Shared/Enums.cs index cd23e03..9ea2778 100644 --- a/BallanceTasEditor/BallanceTasEditor/Frontend/Shared/Enums.cs +++ b/BallanceTasEditor/BallanceTasEditor/Frontend/Shared/Enums.cs @@ -8,27 +8,27 @@ using System.Threading.Tasks; namespace BallanceTasEditor.Frontend.Shared { - public enum TasSequenceKind { + public enum SequenceKind { Array, DoubleLinkedList } - public static class TasSequenceKindHelper { - public static Backend.ITasSequence CreateSequenceByKind(TasSequenceKind kind) { + public static class SequenceKindHelper { + public static Backend.ITasSequence CreateSequenceByKind(SequenceKind kind) { return kind switch { - TasSequenceKind.Array => new Backend.ListTasSequence(), - TasSequenceKind.DoubleLinkedList => new Backend.LegacyTasSequence(), + SequenceKind.Array => new Backend.ListTasSequence(), + SequenceKind.DoubleLinkedList => new Backend.LegacyTasSequence(), _ => throw new UnreachableException(), }; } - public static bool TryParse(string s, out TasSequenceKind value) { + public static bool TryParse(string s, out SequenceKind value) { switch (s) { case "array": - value = TasSequenceKind.Array; + value = SequenceKind.Array; return true; case "double_linked_list": - value = TasSequenceKind.DoubleLinkedList; + value = SequenceKind.DoubleLinkedList; return true; default: value = default; @@ -36,10 +36,10 @@ namespace BallanceTasEditor.Frontend.Shared { } } - public static string ToString(TasSequenceKind kind) { + public static string ToString(SequenceKind kind) { return kind switch { - TasSequenceKind.Array => "array", - TasSequenceKind.DoubleLinkedList => "double_linked_list", + SequenceKind.Array => "array", + SequenceKind.DoubleLinkedList => "double_linked_list", _ => throw new UnreachableException(), }; } @@ -73,19 +73,19 @@ namespace BallanceTasEditor.Frontend.Shared { } } - public enum EditorPasteMode { + public enum EditorPasteBehavior { Insert, Override } - public static class EditorPasteModeHelper { - public static bool TryParse(string s, out EditorPasteMode value) { + public static class EditorPasteBehaviorHelper { + public static bool TryParse(string s, out EditorPasteBehavior value) { switch (s) { case "insert": - value = EditorPasteMode.Insert; + value = EditorPasteBehavior.Insert; return true; case "override": - value = EditorPasteMode.Override; + value = EditorPasteBehavior.Override; return true; default: value = default; @@ -93,10 +93,10 @@ namespace BallanceTasEditor.Frontend.Shared { } } - public static string ToString(EditorPasteMode mode) { + public static string ToString(EditorPasteBehavior mode) { return mode switch { - EditorPasteMode.Insert => "insert", - EditorPasteMode.Override => "override", + EditorPasteBehavior.Insert => "insert", + EditorPasteBehavior.Override => "override", _ => throw new UnreachableException(), }; } diff --git a/BallanceTasEditor/BallanceTasEditor/Frontend/ViewModels/MainWindow.cs b/BallanceTasEditor/BallanceTasEditor/Frontend/ViewModels/MainWindow.cs index 280c7cd..96f1e9a 100644 --- a/BallanceTasEditor/BallanceTasEditor/Frontend/ViewModels/MainWindow.cs +++ b/BallanceTasEditor/BallanceTasEditor/Frontend/ViewModels/MainWindow.cs @@ -61,7 +61,7 @@ namespace BallanceTasEditor.Frontend.ViewModels { if (dialog is null) return; // Create new file - TasFile.NewFile(Shared.TasSequenceKind.Array, dialog.Count, dialog.Fps); + TasFile.NewFile(Shared.SequenceKind.Array, dialog.Count, dialog.Fps); // Set members TasFilePath = null; // Send notification @@ -80,7 +80,7 @@ namespace BallanceTasEditor.Frontend.ViewModels { // Load file try { - TasFile.LoadFile(Shared.TasSequenceKind.Array, dialog.Path); + TasFile.LoadFile(Shared.SequenceKind.Array, dialog.Path); } catch (Exception e) { m_DialogService.ShowOpenFileFailedDialog(e); return; diff --git a/BallanceTasEditor/BallanceTasEditor/Frontend/ViewModels/PreferenceDialog.cs b/BallanceTasEditor/BallanceTasEditor/Frontend/ViewModels/PreferenceDialog.cs index 9020cfd..5c984b3 100644 --- a/BallanceTasEditor/BallanceTasEditor/Frontend/ViewModels/PreferenceDialog.cs +++ b/BallanceTasEditor/BallanceTasEditor/Frontend/ViewModels/PreferenceDialog.cs @@ -2,17 +2,47 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; namespace BallanceTasEditor.Frontend.ViewModels { - public partial class PreferenceDialog : ObservableObject { + public partial class PreferenceDialog : ObservableValidator { public PreferenceDialog() { } + [ObservableProperty] + private Shared.SequenceKind sequenceKind; + [ObservableProperty] + private Shared.EditorLayoutKind layoutKind; + [ObservableProperty] + private Shared.EditorPasteBehavior pasteBehavior; + [ObservableProperty] + [NotifyDataErrorInfo] + [CustomValidation(typeof(PreferenceDialog), nameof(ValidateCount))] + [NotifyCanExecuteChangedFor(nameof(OkCommand))] + private string frameCount; + [ObservableProperty] + private string gamePath; + #region Validators + + private static readonly Validators.ValidatorAdapter g_CountValidator = + new Validators.ValidatorAdapter(new Validators.CountValidator()); + + public static ValidationResult? ValidateCount(string value, ValidationContext context) { + return g_CountValidator.Validate(value, context); + } + + //public Shared.NewFileDialogResult GetUserInput() { + // return + //} + + #endregion + + #region Commands [RelayCommand(CanExecute = nameof(CanOk))] private void Ok() { @@ -20,8 +50,7 @@ namespace BallanceTasEditor.Frontend.ViewModels { } private bool CanOk() { - // TODO - return true; + return !HasErrors; } [RelayCommand] @@ -29,12 +58,13 @@ namespace BallanceTasEditor.Frontend.ViewModels { OnRequestCloseDialog(false); } - public event Shared.RequestCloseDialogEventHandler? RequestCloseDialog; private void OnRequestCloseDialog(bool result) { RequestCloseDialog?.Invoke(new Shared.RequestCloseDialogEventArgs { Result = result }); } + #endregion + } } diff --git a/BallanceTasEditor/BallanceTasEditor/Frontend/Views/PreferenceDialog.xaml b/BallanceTasEditor/BallanceTasEditor/Frontend/Views/PreferenceDialog.xaml index 555f2ff..fc5a7a8 100644 --- a/BallanceTasEditor/BallanceTasEditor/Frontend/Views/PreferenceDialog.xaml +++ b/BallanceTasEditor/BallanceTasEditor/Frontend/Views/PreferenceDialog.xaml @@ -5,10 +5,12 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:BallanceTasEditor.Frontend.Views" xmlns:vm="clr-namespace:BallanceTasEditor.Frontend.ViewModels" + xmlns:conveter="clr-namespace:BallanceTasEditor.Frontend.Converters" + xmlns:shared="clr-namespace:BallanceTasEditor.Frontend.Shared" xmlns:widget="clr-namespace:BallanceTasEditor.Frontend.Widgets" d:DataContext="{d:DesignInstance vm:PreferenceDialog}" mc:Ignorable="d" WindowStartupLocation="CenterOwner" ResizeMode="NoResize" ShowInTaskbar="False" - Title="Editor Preference" Height="450" Width="400" Icon="/Frontend/Assets/Preference.ico"> + Title="Editor Preference" Height="500" Width="400" Icon="/Frontend/Assets/Preference.ico"> @@ -17,7 +19,7 @@ - @@ -25,26 +27,56 @@ - - + + - + - - + + + + + + + + + + + + - +