feat: write shit
This commit is contained in:
20
BallanceTasEditor/BallanceTasEditor/Backend/AppSettings.cs
Normal file
20
BallanceTasEditor/BallanceTasEditor/Backend/AppSettings.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Backend {
|
||||
|
||||
public enum EditorLayoutKind {
|
||||
Horizontal, Vertical
|
||||
}
|
||||
|
||||
public class AppSettings {
|
||||
|
||||
|
||||
|
||||
public EditorLayoutKind EditorLayout { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -156,6 +156,14 @@ namespace BallanceTasEditor.Backend {
|
||||
raw.KeyFlags = m_KeyFlags;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回自身的克隆(深拷贝)。
|
||||
/// </summary>
|
||||
/// <returns>自身的克隆。</returns>
|
||||
public TasFrame Clone() {
|
||||
return new TasFrame(m_TimeDelta, m_KeyFlags);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 该帧的持续时间(以秒为单位)。
|
||||
/// </summary>
|
||||
|
||||
@@ -10,11 +10,31 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Backend {
|
||||
public static class TasStorage {
|
||||
|
||||
/// <summary>
|
||||
/// Initialize given TAS sequence with given count frame which has given FPS.
|
||||
/// </summary>
|
||||
/// <param name="seq">The TAS sequence to initialize.</param>
|
||||
/// <param name="count">The count of frame.</param>
|
||||
/// <param name="fps">The FPS of frame.</param>
|
||||
public static void Init(ITasSequence seq, int count, uint fps) {
|
||||
var frame = TasFrame.FromFps(fps);
|
||||
var iter = Enumerable.Range(0, count).Select((_) => frame.Clone());
|
||||
var exactSizeIter = new ExactSizeEnumerableAdapter<TasFrame>(iter, count);
|
||||
seq.Insert(seq.GetCount(), exactSizeIter);
|
||||
}
|
||||
|
||||
internal const int SIZEOF_I32 = sizeof(int);
|
||||
internal const int SIZEOF_F32 = sizeof(float);
|
||||
internal const int SIZEOF_U32 = sizeof(uint);
|
||||
internal const int SIZEOF_RAW_TAS_FRAME = SIZEOF_F32 + SIZEOF_U32;
|
||||
|
||||
/// <summary>
|
||||
/// Save given TAS sequence into given file path.
|
||||
/// </summary>
|
||||
/// <param name="filepath">The path to file for saving.</param>
|
||||
/// <param name="seq">The TAS sequence to save.</param>
|
||||
/// <exception cref="Exception">Any exception occurs when saving.</exception>
|
||||
public static void Save(string filepath, ITasSequence seq) {
|
||||
using (var fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)) {
|
||||
Save(fs, seq);
|
||||
@@ -22,6 +42,12 @@ namespace BallanceTasEditor.Backend {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save given TAS sequence into given file stream.
|
||||
/// </summary>
|
||||
/// <param name="fs">The file stream for saving.</param>
|
||||
/// <param name="seq">The TAS sequence to save.</param>
|
||||
/// <exception cref="Exception">Any exception occurs when saving.</exception>
|
||||
public static void Save(Stream fs, ITasSequence seq) {
|
||||
var totalByte = seq.GetCount() * SIZEOF_RAW_TAS_FRAME;
|
||||
fs.Write(BitConverter.GetBytes(totalByte), 0, SIZEOF_I32);
|
||||
@@ -46,6 +72,12 @@ namespace BallanceTasEditor.Backend {
|
||||
//zo.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load TAS sequence from given file path into given sequence.
|
||||
/// </summary>
|
||||
/// <param name="filepath">The path to file for loading.</param>
|
||||
/// <param name="seq">The TAS sequence to load.</param>
|
||||
/// <exception cref="Exception">Any exception occurs when loading.</exception>
|
||||
public static void Load(string filepath, ITasSequence seq) {
|
||||
using (var fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)) {
|
||||
Load(fs, seq);
|
||||
@@ -53,6 +85,12 @@ namespace BallanceTasEditor.Backend {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load TAS sequence from given file stream into given sequence.
|
||||
/// </summary>
|
||||
/// <param name="fs">The file stream for loading.</param>
|
||||
/// <param name="seq">The TAS sequence to load.</param>
|
||||
/// <exception cref="Exception">Any exception occurs when loading.</exception>
|
||||
public static void Load(Stream fs, ITasSequence seq) {
|
||||
// Read total bytes
|
||||
var lenCache = new byte[SIZEOF_I32];
|
||||
|
||||
@@ -17,9 +17,12 @@
|
||||
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.4.0" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="DotNetZip" Version="1.9.1.8" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.142" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="10.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Frontend\Models\" />
|
||||
<Folder Include="Frontend\Utils\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.Xaml.Behaviors;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Behaviors {
|
||||
public class ConfirmCloseBehavior : Behavior<Window> {
|
||||
|
||||
public ICommand ConfirmCommand {
|
||||
get { return (ICommand)GetValue(ConfirmCommandProperty); }
|
||||
set { SetValue(ConfirmCommandProperty, value); }
|
||||
}
|
||||
|
||||
// Using a DependencyProperty as the backing store for ConfirmCommand. This enables animation, styling, binding, etc...
|
||||
public static readonly DependencyProperty ConfirmCommandProperty =
|
||||
DependencyProperty.Register("ConfirmCommand", typeof(ICommand), typeof(ConfirmCloseBehavior));
|
||||
|
||||
|
||||
protected override void OnAttached() {
|
||||
base.OnAttached();
|
||||
AssociatedObject.Closing += OnClosing;
|
||||
}
|
||||
|
||||
protected override void OnDetaching() {
|
||||
AssociatedObject.Closing -= OnClosing;
|
||||
base.OnDetaching();
|
||||
}
|
||||
|
||||
private void OnClosing(object? sender, CancelEventArgs e) {
|
||||
if (ConfirmCommand?.CanExecute(null) == true) {
|
||||
// 假设Command返回 bool 或通过回调/事件通知结果
|
||||
bool allowClose = (Func<object?, bool>)ConfirmCommand.Execute(null);
|
||||
e.Cancel = !allowClose;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
|
||||
public interface IDialogService {
|
||||
NewFileDialogResult? ShowNewFileDialog();
|
||||
OpenFileDialogResult? ShowOpenFileDialog();
|
||||
void ShowOpenFileFailedDialog(Exception e);
|
||||
SaveFileDialogResult? ShowSaveFileDialog();
|
||||
void ShowSaveFileFailedDialog(Exception e);
|
||||
bool ShowConfirmCloseFileDialog(string message);
|
||||
bool ShowConfirmExitWhenOpeningFileDialog();
|
||||
bool ShowFileChangedDialog();
|
||||
GotoDialogResult? ShowGotoDialog();
|
||||
EditFpsDialogResult? ShowEditFpsDialog();
|
||||
AddFrameDialogResult? ShowAddFrameDialog();
|
||||
PreferenceDialogResult? ShowPreferenceDialog();
|
||||
void ShowAboutDialog();
|
||||
}
|
||||
|
||||
public record NewFileDialogResult {
|
||||
public required uint Fps { get; init; }
|
||||
public required int Count { get; init; }
|
||||
}
|
||||
|
||||
public record OpenFileDialogResult {
|
||||
public required string Path { get; init; }
|
||||
}
|
||||
|
||||
public record SaveFileDialogResult {
|
||||
public required string Path { get; init; }
|
||||
}
|
||||
|
||||
public record GotoDialogResult { }
|
||||
|
||||
public record EditFpsDialogResult { }
|
||||
|
||||
public record AddFrameDialogResult { }
|
||||
|
||||
public record PreferenceDialogResult { }
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
public partial class MainWindow : ObservableObject {
|
||||
public MainWindow(IDialogService dialogService) {
|
||||
m_DialogService = dialogService;
|
||||
|
||||
this.TasFile = null;
|
||||
this.TasFilePath = null;
|
||||
}
|
||||
|
||||
private IDialogService m_DialogService;
|
||||
|
||||
#region File Operation
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(WindowTitle))]
|
||||
[NotifyCanExecuteChangedFor(nameof(NewFileCommand))]
|
||||
[NotifyCanExecuteChangedFor(nameof(OpenFileCommand))]
|
||||
[NotifyCanExecuteChangedFor(nameof(SaveFileCommand))]
|
||||
[NotifyCanExecuteChangedFor(nameof(SaveFileAsCommand))]
|
||||
[NotifyCanExecuteChangedFor(nameof(CloseFileCommand))]
|
||||
private Backend.ITasSequence? tasFile;
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(WindowTitle))]
|
||||
private string? tasFilePath;
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanNewFile))]
|
||||
private void NewFile() {
|
||||
// Request new file properties
|
||||
var dialog = m_DialogService.ShowNewFileDialog();
|
||||
if (dialog is null) return;
|
||||
|
||||
// Initialize sequence
|
||||
var seq = new Backend.ListTasSequence();
|
||||
// Initialize items
|
||||
Backend.TasStorage.Init(seq, dialog.Count, dialog.Fps);
|
||||
// Set members
|
||||
this.TasFile = seq;
|
||||
this.TasFilePath = null;
|
||||
}
|
||||
|
||||
private bool CanNewFile() {
|
||||
return this.TasFile is null;
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanOpenFile))]
|
||||
private void OpenFile() {
|
||||
// Request file path
|
||||
var dialog = m_DialogService.ShowOpenFileDialog();
|
||||
if (dialog is null) return;
|
||||
|
||||
// Initialize sequence
|
||||
var seq = new Backend.ListTasSequence();
|
||||
// Load into sequence
|
||||
try {
|
||||
Backend.TasStorage.Load(dialog.Path, seq);
|
||||
} catch (Exception e) {
|
||||
m_DialogService.ShowOpenFileFailedDialog(e);
|
||||
return;
|
||||
}
|
||||
// Set members
|
||||
this.TasFile = seq;
|
||||
this.TasFilePath = dialog.Path;
|
||||
}
|
||||
|
||||
private bool CanOpenFile() {
|
||||
return this.TasFile is null;
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanSaveFile))]
|
||||
private void SaveFile() {
|
||||
// If there is no associated file path,
|
||||
// it means that this file is not stored on disk,
|
||||
// We must make a request to user for fetching it.
|
||||
string? filePath = this.TasFilePath;
|
||||
if (filePath is null) {
|
||||
var dialog = m_DialogService.ShowSaveFileDialog();
|
||||
if (dialog is null) return;
|
||||
filePath = dialog.Path;
|
||||
}
|
||||
|
||||
// Save file
|
||||
try {
|
||||
Backend.TasStorage.Save(filePath, this.TasFile.Unwrap());
|
||||
} catch (Exception e) {
|
||||
m_DialogService.ShowSaveFileFailedDialog(e);
|
||||
return;
|
||||
}
|
||||
// Update member
|
||||
this.TasFilePath = filePath;
|
||||
}
|
||||
|
||||
private bool CanSaveFile() {
|
||||
return this.TasFile is not null;
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanSaveFileAs))]
|
||||
private void SaveFileAs() {
|
||||
// We always request a new path when saving as
|
||||
var dialog = m_DialogService.ShowSaveFileDialog();
|
||||
if (dialog is null) return;
|
||||
|
||||
// Save file
|
||||
try {
|
||||
Backend.TasStorage.Save(dialog.Path, this.TasFile.Unwrap());
|
||||
} catch (Exception e) {
|
||||
m_DialogService.ShowSaveFileFailedDialog(e);
|
||||
return;
|
||||
}
|
||||
// Set file path
|
||||
TasFilePath = dialog.Path;
|
||||
}
|
||||
|
||||
private bool CanSaveFileAs() {
|
||||
return this.TasFile is not null;
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanCloseFile))]
|
||||
private void CloseFile() {
|
||||
this.TasFile = null;
|
||||
this.TasFilePath = null;
|
||||
}
|
||||
|
||||
private bool CanCloseFile() {
|
||||
return this.TasFile is not null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UI Only
|
||||
|
||||
public string WindowTitle {
|
||||
get {
|
||||
if (TasFile is null) {
|
||||
return "Ballance TAS Editor";
|
||||
} else {
|
||||
if (TasFilePath is null) {
|
||||
return "Ballance TAS Editor - [Untitled]";
|
||||
} else {
|
||||
return $"Ballance TAS Editor - [{TasFilePath}]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,6 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.ViewModels {
|
||||
|
||||
public struct NewFileDialogResult {
|
||||
public int Count { get; set; }
|
||||
public float DeltaTime { get; set; }
|
||||
}
|
||||
|
||||
public partial class NewFileDialog : ObservableValidator {
|
||||
public NewFileDialog() {
|
||||
Count = 10000.ToString();
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace BallanceTasEditor.Frontend.Views {
|
||||
|
||||
public class DialogService : ViewModels.IDialogService {
|
||||
public DialogService(Window parent) {
|
||||
m_Parent = parent;
|
||||
}
|
||||
|
||||
private readonly Window m_Parent;
|
||||
|
||||
public ViewModels.NewFileDialogResult? ShowNewFileDialog() {
|
||||
var dialog = new NewFileDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.NewFileDialogResult() { Count = 0, Fps = 60 };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModels.OpenFileDialogResult? ShowOpenFileDialog() {
|
||||
Microsoft.Win32.OpenFileDialog op = new Microsoft.Win32.OpenFileDialog();
|
||||
op.RestoreDirectory = true;
|
||||
op.Multiselect = false;
|
||||
op.Filter = "TAS file(*.tas)|*.tas|All file(*.*)|*.*";
|
||||
if (op.ShowDialog() is true) {
|
||||
return new ViewModels.OpenFileDialogResult() { Path = op.FileName };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowOpenFileFailedDialog(Exception e) {
|
||||
MessageBox.Show("Fail to open file. This file might not a legal TAS file." + e.Message,
|
||||
"Error",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
public ViewModels.SaveFileDialogResult? ShowSaveFileDialog() {
|
||||
Microsoft.Win32.SaveFileDialog op = new Microsoft.Win32.SaveFileDialog();
|
||||
op.RestoreDirectory = true;
|
||||
op.Filter = "TAS file(*.tas)|*.tas|All file(*.*)|*.*";
|
||||
if (op.ShowDialog() is true) {
|
||||
return new ViewModels.SaveFileDialogResult() { Path = op.FileName };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowSaveFileFailedDialog(Exception e) {
|
||||
MessageBox.Show(
|
||||
"Fail to save file." + e.Message,
|
||||
"Error",
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
|
||||
public bool ShowConfirmCloseFileDialog(string message) {
|
||||
var rv = MessageBox.Show(
|
||||
"Do you want to close this TAS file? All changes will not be saved.",
|
||||
"File Is Not Saved",
|
||||
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
return rv == MessageBoxResult.Yes;
|
||||
}
|
||||
|
||||
public bool ShowConfirmExitWhenOpeningFileDialog() {
|
||||
var rv = MessageBox.Show(
|
||||
"File is not closed. Do you want to just quit? All changes will not be saved.",
|
||||
"File Is Not Saved",
|
||||
MessageBoxButton.YesNo, MessageBoxImage.Warning);
|
||||
return rv == MessageBoxResult.Yes;
|
||||
}
|
||||
|
||||
public bool ShowFileChangedDialog() {
|
||||
var rv = MessageBox.Show(
|
||||
"File is changed. Do you want to reload it?",
|
||||
"File Is Changed",
|
||||
MessageBoxButton.YesNo, MessageBoxImage.Question);
|
||||
return rv == MessageBoxResult.Yes;
|
||||
}
|
||||
|
||||
public ViewModels.GotoDialogResult? ShowGotoDialog() {
|
||||
var dialog = new GotoDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.GotoDialogResult();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModels.EditFpsDialogResult? ShowEditFpsDialog() {
|
||||
var dialog = new EditFpsDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.EditFpsDialogResult();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModels.AddFrameDialogResult? ShowAddFrameDialog() {
|
||||
var dialog = new AddFrameDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.AddFrameDialogResult();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ViewModels.PreferenceDialogResult? ShowPreferenceDialog() {
|
||||
var dialog = new PreferenceDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
if (dialog.ShowDialog() is true) {
|
||||
// TODO: Finish result extraction
|
||||
return new ViewModels.PreferenceDialogResult();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowAboutDialog() {
|
||||
var dialog = new AboutDialog();
|
||||
dialog.Owner = m_Parent;
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,8 +5,11 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:BallanceTasEditor.Frontend.Views"
|
||||
xmlns:styles="clr-namespace:BallanceTasEditor.Frontend.Styles"
|
||||
mc:Ignorable="d" WindowStartupLocation="CenterScreen"
|
||||
Title="Ballance TAS Editor" Height="600" Width="800" Icon="/Frontend/Assets/App.ico">
|
||||
xmlns:vm="clr-namespace:BallanceTasEditor.Frontend.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance vm:MainWindow}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Title="{Binding WindowTitle, Mode=OneWay}" Height="600" Width="800" Icon="/Frontend/Assets/App.ico">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -44,14 +47,14 @@
|
||||
</Menu.Resources>
|
||||
|
||||
<MenuItem Header="_File" Padding="5">
|
||||
<MenuItem Header="_New File" Icon="{StaticResource IconNewFile}" InputGestureText="Ctrl+N" Click="MenuItem_Click_3"/>
|
||||
<MenuItem Header="_Open File" Icon="{StaticResource IconOpenFile}" InputGestureText="Ctrl+O"/>
|
||||
<MenuItem Header="_New File" Icon="{StaticResource IconNewFile}" InputGestureText="Ctrl+N" Command="{Binding NewFileCommand}"/>
|
||||
<MenuItem Header="_Open File" Icon="{StaticResource IconOpenFile}" InputGestureText="Ctrl+O" Command="{Binding OpenFileCommand}"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="_Save File" Icon="{StaticResource IconSaveFile}" InputGestureText="Ctrl+S"/>
|
||||
<MenuItem Header="Save File as ..." Icon="{StaticResource IconSaveFileAs}"/>
|
||||
<MenuItem Header="_Save File" Icon="{StaticResource IconSaveFile}" InputGestureText="Ctrl+S" Command="{Binding SaveFileCommand}"/>
|
||||
<MenuItem Header="Save File as ..." Icon="{StaticResource IconSaveFileAs}" Command="{Binding SaveFileAsCommand}"/>
|
||||
<MenuItem Header="Save File then _Run Game" Icon="{StaticResource IconSaveFileThenRunGame}" InputGestureText="B"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Close File" Icon="{StaticResource IconCloseFile}"/>
|
||||
<MenuItem Header="Close File" Icon="{StaticResource IconCloseFile}" Command="{Binding CloseFileCommand}"/>
|
||||
<MenuItem Header="Exit" Icon="{StaticResource IconExit}"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Edit" Padding="5">
|
||||
@@ -62,20 +65,20 @@
|
||||
<MenuItem Header="Previous Item" Icon="{StaticResource IconPreviousItem}" InputGestureText="S"/>
|
||||
<MenuItem Header="Next Page" Icon="{StaticResource IconNextPage}" InputGestureText="D"/>
|
||||
<MenuItem Header="Next Item" Icon="{StaticResource IconNextItem}" InputGestureText="F"/>
|
||||
<MenuItem Header="Goto Item" Icon="{StaticResource IconGoto}" InputGestureText="G" Click="MenuItem_Click_4"/>
|
||||
<MenuItem Header="Goto Item" Icon="{StaticResource IconGoto}" InputGestureText="G"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Select Mode" Icon="{StaticResource IconSelectMode}"/>
|
||||
<MenuItem Header="Fill Mode" Icon="{StaticResource IconFillMode}"/>
|
||||
<MenuItem Header="Draw Mode" Icon="{StaticResource IconDrawMode}"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Clear Keys" Icon="{StaticResource IconClearKeys}"/>
|
||||
<MenuItem Header="Uniform FPS" Icon="{StaticResource IconUniformFps}" Click="MenuItem_Click_5"/>
|
||||
<MenuItem Header="Uniform FPS" Icon="{StaticResource IconUniformFps}"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Preference" Icon="{StaticResource IconPreference}" InputGestureText="Ctrl+P" Click="MenuItem_Click"/>
|
||||
<MenuItem Header="Preference" Icon="{StaticResource IconPreference}" InputGestureText="Ctrl+P"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Help" Padding="5">
|
||||
<MenuItem Header="Report Bug" Icon="{StaticResource IconReportBug}"/>
|
||||
<MenuItem Header="About" Icon="{StaticResource IconAbout}" Click="MenuItem_Click_1"/>
|
||||
<MenuItem Header="About" Icon="{StaticResource IconAbout}"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
@@ -133,14 +136,14 @@
|
||||
<MenuItem Header="Paste after This" Icon="{StaticResource IconPaste}" InputGestureText="Ctrl+V"/>
|
||||
<MenuItem Header="Paste before This"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Delete This" Icon="{StaticResource IconDelete}"/>
|
||||
<MenuItem Header="Delete" Icon="{StaticResource IconDelete}"/>
|
||||
<MenuItem Header="Delete after This" InputGestureText="Del"/>
|
||||
<MenuItem Header="Delete before This" InputGestureText="Backspace"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Add after This" Icon="{StaticResource IconAdd}" Click="MenuItem_Click_2"/>
|
||||
<MenuItem Header="Add after This" Icon="{StaticResource IconAdd}"/>
|
||||
<MenuItem Header="Add before This"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="Set FPS" Icon="{StaticResource IconFps}" Click="MenuItem_Click_6"/>
|
||||
<MenuItem Header="Set FPS" Icon="{StaticResource IconFps}"/>
|
||||
</ContextMenu>
|
||||
</local:TasViewer.ContextMenu>
|
||||
</local:TasViewer>
|
||||
@@ -150,8 +153,6 @@
|
||||
<!-- 这玩意要逆序排列才能达到我想要的需求也是奇葩 -->
|
||||
<StatusBarItem Content="v2.0 stable" DockPanel.Dock="Right" Foreground="Gray" FontStyle="Italic"/>
|
||||
<Separator DockPanel.Dock="Right"/>
|
||||
<StatusBarItem Content="$PasteMode" DockPanel.Dock="Right"/>
|
||||
<Separator DockPanel.Dock="Right"/>
|
||||
<StatusBarItem Content="$Selection" DockPanel.Dock="Right"/>
|
||||
<Separator DockPanel.Dock="Right"/>
|
||||
<StatusBarItem Content="$ToolMode" DockPanel.Dock="Right"/>
|
||||
|
||||
@@ -20,48 +20,8 @@ namespace BallanceTasEditor.Frontend.Views {
|
||||
public partial class MainWindow : Window {
|
||||
public MainWindow() {
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MenuItem_Click_3(object sender, RoutedEventArgs e) {
|
||||
var dialog = new NewFileDialog();
|
||||
dialog.Owner = this;
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
|
||||
private void MenuItem_Click(object sender, RoutedEventArgs e) {
|
||||
var dialog = new PreferenceDialog();
|
||||
dialog.Owner = this;
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
|
||||
private void MenuItem_Click_1(object sender, RoutedEventArgs e) {
|
||||
var dialog = new AboutDialog();
|
||||
dialog.Owner = this;
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
|
||||
private void MenuItem_Click_4(object sender, RoutedEventArgs e) {
|
||||
var dialog =new GotoDialog();
|
||||
dialog.Owner = this;
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
|
||||
private void MenuItem_Click_5(object sender, RoutedEventArgs e) {
|
||||
var dialog = new EditFpsDialog();
|
||||
dialog.Owner = this;
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
|
||||
private void MenuItem_Click_6(object sender, RoutedEventArgs e) {
|
||||
var dialog = new EditFpsDialog();
|
||||
dialog.Owner = this;
|
||||
dialog.ShowDialog();
|
||||
}
|
||||
|
||||
private void MenuItem_Click_2(object sender, RoutedEventArgs e) {
|
||||
var dialog = new AddFrameDialog();
|
||||
dialog.Owner = this;
|
||||
dialog.ShowDialog();
|
||||
var dialogService = new DialogService(this);
|
||||
this.DataContext = new ViewModels.MainWindow(dialogService);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BallanceTasEditor.Backend {
|
||||
namespace BallanceTasEditor {
|
||||
public static class NullableExtensions {
|
||||
public static T Unwrap<T>(this T? value, [CallerArgumentExpression(nameof(value))] string? paramName = null) where T : class {
|
||||
ArgumentNullException.ThrowIfNull(value, paramName);
|
||||
@@ -40,7 +40,7 @@
|
||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
Reference in New Issue
Block a user