From 0534b225017c2d140702acda47f16b8820d73ef8 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Tue, 21 Sep 2021 20:17:03 +0800 Subject: [PATCH] finish zh document and vertical layout design --- BallanceTASEditor/MainWindow.xaml | 204 ++++++++++++++------------- BallanceTASEditor/MainWindow.xaml.cs | 46 +++++- BallanceTASEditor/UI/TASFlow.cs | 133 ++++++++++++++--- BallanceTASEditor/UI/TASSlider.cs | 81 +++++++++-- BallanceTASEditor/UI/Util.cs | 29 ++++ README_ZH.md | 85 +++++++---- 6 files changed, 422 insertions(+), 156 deletions(-) diff --git a/BallanceTASEditor/MainWindow.xaml b/BallanceTASEditor/MainWindow.xaml index bc05d01..ca76b54 100644 --- a/BallanceTASEditor/MainWindow.xaml +++ b/BallanceTASEditor/MainWindow.xaml @@ -74,7 +74,7 @@ - + @@ -84,14 +84,13 @@ - + - + - @@ -127,107 +126,116 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - + + diff --git a/BallanceTASEditor/MainWindow.xaml.cs b/BallanceTASEditor/MainWindow.xaml.cs index 79b703b..d92377c 100644 --- a/BallanceTASEditor/MainWindow.xaml.cs +++ b/BallanceTASEditor/MainWindow.xaml.cs @@ -23,9 +23,31 @@ namespace BallanceTASEditor { public MainWindow() { InitializeComponent(); - mFlow = new TASFlow(uiTASData); - mSlider = new TASSlider(uiTASSlider); + // init layout controller + var headers = new List(); + headers.Add(uiFlowHeader_Frame); + headers.Add(uiFlowHeader_DeltaTime); + headers.Add(uiFlowHeader_Up); + headers.Add(uiFlowHeader_Down); + headers.Add(uiFlowHeader_Left); + headers.Add(uiFlowHeader_Right); + headers.Add(uiFlowHeader_Shift); + headers.Add(uiFlowHeader_Space); + headers.Add(uiFlowHeader_Q); + headers.Add(uiFlowHeader_Esc); + headers.Add(uiFlowHeader_Enter); + mFlow = new TASFlow(uiTASData, headers.ToArray()); + var components = new TASSliderComponents(); + components.container = uiTASSliderContainer; + components.btnFastPrev = uiBtn_FastMovePrev; + components.btnPrev = uiBtn_MovePrev; + components.btnNext = uiBtn_MoveNext; + components.btnFastNext = uiBtn_FastMoveNext; + components.mSlider = uiTASSlider; + mSlider = new TASSlider(components); ; + + // refresh ui and load cfg RefreshUI(false); ApplyConfigureManager(); } @@ -428,8 +450,26 @@ namespace BallanceTASEditor { } private void ChangeLayout(bool isHorizontal) { + // swap window size + var swap = this.Width; + this.Width = this.Height; + this.Height = swap; + // change self layout first + uiLayoutContainer.RowDefinitions.Clear(); + uiLayoutContainer.ColumnDefinitions.Clear(); + if (isHorizontal) { + UI.Util.GridRowAdder(uiLayoutContainer, new GridLength(1, GridUnitType.Star)); + UI.Util.GridRowAdder(uiLayoutContainer, GridLength.Auto); + } else { + UI.Util.GridColumnAdder(uiLayoutContainer, new GridLength(1, GridUnitType.Star)); + UI.Util.GridColumnAdder(uiLayoutContainer, GridLength.Auto); + } + UI.Util.SwapGridItemRC(uiTASFlowContainer); + UI.Util.SwapGridItemRC(uiTASSliderContainer); + + // change sub layout mFlow.ChangeLayout(isHorizontal); - // todo: add more change + mSlider.ChangeLayout(isHorizontal); } } diff --git a/BallanceTASEditor/UI/TASFlow.cs b/BallanceTASEditor/UI/TASFlow.cs index ba4231f..eee641e 100644 --- a/BallanceTASEditor/UI/TASFlow.cs +++ b/BallanceTASEditor/UI/TASFlow.cs @@ -16,8 +16,9 @@ using System.Windows.Shapes; namespace BallanceTASEditor.UI { public partial class TASFlow { - public TASFlow(Grid coreWindow) { + public TASFlow(Grid coreWindow, TextBlock[] headers) { uiCoreWindow = coreWindow; + mHeaders = headers; mItemList = new List(); mRectMap = new Dictionary(); mItemCount = 0; @@ -27,6 +28,9 @@ namespace BallanceTASEditor.UI { public event Action Click; + private const double SELECTION_HEADER_HEIGHT = 10.0f; // header selection height, originally copied from TASFlowItem class + + private readonly TextBlock[] mHeaders; private bool mIsHorizontalLayout; private Grid uiCoreWindow; private int mItemCount; @@ -36,10 +40,73 @@ namespace BallanceTASEditor.UI { public List DataSources { get; set; } public void ChangeLayout(bool isHorizontal) { + if (isHorizontal == mIsHorizontalLayout) return; + // the layout changed, re-construct elements - if (isHorizontal != mIsHorizontalLayout) { - // todo: change layout + mIsHorizontalLayout = isHorizontal; + + // delete original grid layout + var lenHeader = mHeaders.Length; + uiCoreWindow.ColumnDefinitions.Clear(); + uiCoreWindow.RowDefinitions.Clear(); + + // add header layout + if (mIsHorizontalLayout) { + // horizontal layout + // row is header count + // column is tas unit + + // header + layout_row_adder(new GridLength(SELECTION_HEADER_HEIGHT, GridUnitType.Pixel)); + for (int r = 0; r < lenHeader; r++) { + layout_row_adder(GridLength.Auto); + } + layout_row_adder(new GridLength(1, GridUnitType.Star)); + + // tas unit + layout_column_adder(GridLength.Auto); + for (int c = 0; c < mItemCount; c++) { + layout_column_adder(new GridLength(1, GridUnitType.Star)); + } + } else { + // vertical layout + // row is tas unit + // column is header count (use start to split, not auto) + + // header + layout_column_adder(new GridLength(SELECTION_HEADER_HEIGHT, GridUnitType.Pixel)); + for (int r = 0; r < lenHeader; r++) { + if (r == 0 || r == 1) + layout_column_adder(GridLength.Auto); + else + layout_column_adder(new GridLength(1, GridUnitType.Star)); + } + //layout_column_adder(new GridLength(1, GridUnitType.Star)); + + // tas unit + layout_row_adder(GridLength.Auto); + for (int c = 0; c < mItemCount; c++) { + layout_row_adder(new GridLength(1, GridUnitType.Star)); + } } + + // now, change items attach prop + // just swap Grid.Row and Grid.Column's number + foreach (var item in mHeaders) { + var swap = Grid.GetColumn(item); + Grid.SetColumn(item, Grid.GetRow(item)); + Grid.SetRow(item, swap); + } + foreach (var item in mItemList) { + item.FlipUnit(); + } + + } + private void layout_row_adder(GridLength size) { + UI.Util.GridRowAdder(uiCoreWindow, size); + } + private void layout_column_adder(GridLength size) { + UI.Util.GridColumnAdder(uiCoreWindow, size); } public void RefreshDataSources() { @@ -58,18 +125,24 @@ namespace BallanceTASEditor.UI { // change column defination first if (offset > 0) { for (int i = 0; i < abs; i++) { - var item = new ColumnDefinition(); - item.Width = new GridLength(1, GridUnitType.Star); - uiCoreWindow.ColumnDefinitions.Add(item); + if (mIsHorizontalLayout) { + layout_column_adder(new GridLength(1, GridUnitType.Star)); + } else { + layout_row_adder(new GridLength(1, GridUnitType.Star)); + } } } else { - uiCoreWindow.ColumnDefinitions.RemoveRange(newCount + 1, abs); // the first col is sheet header, so add 1 additionally + if (mIsHorizontalLayout) { + uiCoreWindow.ColumnDefinitions.RemoveRange(newCount + 1, abs); // the first col is sheet header, so add 1 additionally + } else { + uiCoreWindow.RowDefinitions.RemoveRange(newCount + 1, abs); // the first col is sheet header, so add 1 additionally + } } // add / remove item if (offset > 0) { for (int i = 0; i < abs; i++) { - var newItem = new TASFlowUIItem(mItemCount + 1 + i); // the first col is sheet header, so add 1 additionally + var newItem = new TASFlowUIItem(mItemCount + 1 + i, mIsHorizontalLayout); // the first col is sheet header, so add 1 additionally newItem.Add(uiCoreWindow, mRectMap, Rectangle_MouseDown); mItemList.Add(newItem); } @@ -177,20 +250,28 @@ namespace BallanceTASEditor.UI { private static readonly Color COLOR_SELECTED = Colors.OrangeRed; private static readonly Color COLOR_UNSELECTED = Colors.LightGray; private const int KEY_COUNT = 9; - private const double SELECTION_HEADER_HEIGHT = 10.0f; - public TASFlowUIItem(int column) { + public TASFlowUIItem(int column, bool useHorizontalLayout) { // basic item sel_rect = new Rectangle(); frame = new TextBlock(); deltaTime = new TextBlock(); - Grid.SetRow(sel_rect, 0); - Grid.SetRow(frame, 1); - Grid.SetRow(deltaTime, 2); - Grid.SetColumn(sel_rect, column); - Grid.SetColumn(frame, column); - Grid.SetColumn(deltaTime, column); + if (useHorizontalLayout) { + Grid.SetRow(sel_rect, 0); + Grid.SetRow(frame, 1); + Grid.SetRow(deltaTime, 2); + Grid.SetColumn(sel_rect, column); + Grid.SetColumn(frame, column); + Grid.SetColumn(deltaTime, column); + } else { + Grid.SetColumn(sel_rect, 0); + Grid.SetColumn(frame, 1); + Grid.SetColumn(deltaTime, 2); + Grid.SetRow(sel_rect, column); + Grid.SetRow(frame, column); + Grid.SetRow(deltaTime, column); + } sel_rect.Margin = RECT_MARGIN; frame.Margin = DEFAULT_MARGIN; @@ -198,7 +279,7 @@ namespace BallanceTASEditor.UI { sel_rect.StrokeThickness = 2; sel_rect.Stroke = SEL_RECT_STROKE; - sel_rect.Height = SELECTION_HEADER_HEIGHT; + //sel_rect.Height = SELECTION_HEADER_HEIGHT; // now sel_rect's size decided by layout // keystates item keystates = new Rectangle[KEY_COUNT]; @@ -208,8 +289,13 @@ namespace BallanceTASEditor.UI { keystates[i] = new Rectangle(); keystatesFill[i] = new SolidColorBrush(COLOR_UNSET); keystatesStroke[i] = new SolidColorBrush(COLOR_UNSELECTED); - Grid.SetRow(keystates[i], 3 + i); - Grid.SetColumn(keystates[i], column); + if (useHorizontalLayout) { + Grid.SetRow(keystates[i], 3 + i); + Grid.SetColumn(keystates[i], column); + } else { + Grid.SetColumn(keystates[i], 3 + i); + Grid.SetRow(keystates[i], column); + } keystates[i].Margin = RECT_MARGIN; keystates[i].StrokeThickness = 3; keystates[i].Stroke = keystatesStroke[i]; @@ -221,6 +307,15 @@ namespace BallanceTASEditor.UI { rawIsEnable = false; } + public void FlipUnit() { + UI.Util.SwapGridItemRC(sel_rect); + UI.Util.SwapGridItemRC(frame); + UI.Util.SwapGridItemRC(deltaTime); + for (int i = 0; i < KEY_COUNT; i++) { + UI.Util.SwapGridItemRC(keystates[i]); + } + } + public void Add(Grid target, Dictionary map, MouseButtonEventHandler func) { target.Children.Add(sel_rect); target.Children.Add(frame); diff --git a/BallanceTASEditor/UI/TASSlider.cs b/BallanceTASEditor/UI/TASSlider.cs index 209fc76..3872be9 100644 --- a/BallanceTASEditor/UI/TASSlider.cs +++ b/BallanceTASEditor/UI/TASSlider.cs @@ -16,29 +16,94 @@ using System.Windows.Shapes; namespace BallanceTASEditor.UI { public class TASSlider { - public TASSlider(Slider slider) { - mSlider = slider; - mSlider.Minimum = 0; + public TASSlider(TASSliderComponents _components) { + components = _components; + components.mSlider.Minimum = 0; + mIsHorizontalLayout = true; - mSlider.ValueChanged += func_SliderValueChanged; + components.mSlider.ValueChanged += func_SliderValueChanged; } public event Action ValueChanged; - Slider mSlider; + TASSliderComponents components; + bool mIsHorizontalLayout; public void MoveSliderManually(bool isPrev, bool isFast, int fastCount) { var step = isFast ? fastCount : 1; - mSlider.Value = Util.Clamp(mSlider.Value.ToInt32() + (isPrev ? -1 : 1) * step, mSlider.Minimum.ToInt32(), mSlider.Maximum.ToInt32()); + components.mSlider.Value = Core.Util.Clamp(components.mSlider.Value.ToInt32() + (isPrev ? -1 : 1) * step, components.mSlider.Minimum.ToInt32(), components.mSlider.Maximum.ToInt32()); } public void UpdateRange(TASFile mFile) { - mSlider.Maximum = mFile.mFrameCount - 1; - mSlider.Value = mFile.GetPointerIndex(); + components.mSlider.Maximum = mFile.mFrameCount - 1; + components.mSlider.Value = mFile.GetPointerIndex(); } private void func_SliderValueChanged(object sender, RoutedPropertyChangedEventArgs e) { ValueChanged?.Invoke(e.NewValue.ToInt64()); } + public void ChangeLayout(bool isHorizontal) { + if (isHorizontal == mIsHorizontalLayout) return; + + // the layout changed, re-construct elements + mIsHorizontalLayout = isHorizontal; + + // change container + components.container.RowDefinitions.Clear(); + components.container.ColumnDefinitions.Clear(); + if (mIsHorizontalLayout) { + for(int i = 0; i < 4; i++) { + UI.Util.GridColumnAdder(components.container, GridLength.Auto); + } + UI.Util.GridColumnAdder(components.container, new GridLength(1, GridUnitType.Star)); + } else { + for (int i = 0; i < 4; i++) { + UI.Util.GridRowAdder(components.container, GridLength.Auto); + } + UI.Util.GridRowAdder(components.container, new GridLength(1, GridUnitType.Star)); + } + + // flip elements + UI.Util.SwapGridItemRC(components.btnFastPrev); + UI.Util.SwapGridItemRC(components.btnPrev); + UI.Util.SwapGridItemRC(components.btnNext); + UI.Util.SwapGridItemRC(components.btnFastNext); + UI.Util.SwapGridItemRC(components.mSlider); + + // change transform + if (mIsHorizontalLayout) { + // clear all btn's transform and set slider as horizontal style + components.btnFastPrev.RenderTransform = Transform.Identity; + components.btnPrev.RenderTransform = Transform.Identity; + components.btnNext.RenderTransform = Transform.Identity; + components.btnFastNext.RenderTransform = Transform.Identity; + + components.mSlider.RenderTransform = Transform.Identity; + components.mSlider.Orientation = Orientation.Horizontal; + components.mSlider.VerticalAlignment = VerticalAlignment.Center; + components.mSlider.HorizontalAlignment = HorizontalAlignment.Stretch; + } else { + components.btnFastPrev.RenderTransform = new RotateTransform(90); + components.btnPrev.RenderTransform = new RotateTransform(90); + components.btnNext.RenderTransform = new RotateTransform(90); + components.btnFastNext.RenderTransform = new RotateTransform(90); + + components.mSlider.RenderTransform = new RotateTransform(180); + components.mSlider.Orientation = Orientation.Vertical; + components.mSlider.VerticalAlignment = VerticalAlignment.Stretch; + components.mSlider.HorizontalAlignment = HorizontalAlignment.Center; + } + + } + + } + + public class TASSliderComponents { + public Grid container; + public Button btnFastPrev; + public Button btnPrev; + public Button btnNext; + public Button btnFastNext; + public Slider mSlider; } } diff --git a/BallanceTASEditor/UI/Util.cs b/BallanceTASEditor/UI/Util.cs index fe713c7..a69036b 100644 --- a/BallanceTASEditor/UI/Util.cs +++ b/BallanceTASEditor/UI/Util.cs @@ -3,9 +3,38 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +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.UI { + public static class Util { + public static void GridRowAdder(Grid container, GridLength size) { + var item = new RowDefinition(); + item.Height = size; + container.RowDefinitions.Add(item); + } + + public static void GridColumnAdder(Grid container, GridLength size) { + var item = new ColumnDefinition(); + item.Width = size; + container.ColumnDefinitions.Add(item); + } + + public static void SwapGridItemRC(UIElement item) { + var swap = Grid.GetColumn(item); + Grid.SetColumn(item, Grid.GetRow(item)); + Grid.SetRow(item, swap); + } + } + public enum ToolMode { Cursor, Fill, diff --git a/README_ZH.md b/README_ZH.md index 8a6e9ea..94a1559 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -2,20 +2,42 @@ 一款专门用于编辑Ballance TAS文件的编辑器 -## 基本操作 +## 基本界面 -### 菜单 +### 程序菜单 -* File - * Open:打开一个TAS文件 - * Save:保存当前改动到TAS文件 - * Save As...:将当前改动保存到另一个新地方,保存完毕后文件自动切换成新目标,之后的保存操作将针对新文件来保存 - * Close:关闭当前文件 -* Display - * Item Count:设置一行显示多少个TAS操作单元:最少5个,最多30个 -* Help - * Report bugs:打开一个网页来汇报这个程序的Bug - * About:关于此程序 +* 文件 + * 打开:打开一个TAS文件 + * 保存:保存当前改动到TAS文件 + * 另存为...:将当前改动保存到另一个新地方,保存完毕后文件自动切换成新目标,之后的保存操作将针对新文件来保存 + * 关闭:关闭当前文件 +* 编辑 + * 撤销:撤销上一步操作 + * 重做:重做上个撤销的操作 + * 项个数:设置一个页面显示多少个TAS操作单元。 + * 覆盖式粘贴:决定粘贴时的操作是插入式还是覆盖式,详情请查看“覆盖式粘贴”章节 + * 横向布局:决定TAS单元的显示方向,选中为横向布局,不选中则为纵向布局 +* 帮助 + * 汇报漏洞:打开一个网页来汇报这个程序的Bug + * 关于:关于此程序 + +### TAS单元菜单 + +在TAS单元页面右键将打开一个操作菜单,其会根据您当前选择的工具,和选中的项目决定可以做的操作: + +|操作|需要的模式|需要的选中|作用| +|:---|:---|:---|:---| +|设置|填充模式|多选|设置选中单元为设置状态| +|不设置|填充模式|多选|设置选中单元为不设置状态| +|剪切|选择模式|多选|剪切选中单元| +|复制|选择模式|多选|复制选中单元| +|粘贴于后方|选择模式|单选|在其后方粘贴剪贴板中已复制的单元| +|粘贴于前方|选择模式|单选|在其前方粘贴剪贴板中已复制的单元| +|删除|选择模式|单选|删除选中单元| +|向后删除|选择模式|单选|删除当前选中单元,将光标移至后一项| +|向前删除|选择模式|单选|删除当前选中单元之前的一项| +|在后方添加新项|选择模式|单选|在其后方添加空白单元| +|在前方添加新项|选择模式|单选|在其前方添加空白单元| ### 状态栏 @@ -24,8 +46,7 @@ ## 移动视图 打开文件后,靠近底部有一个滑条,可以快速滑动到希望浏览的位置。 -滑条左侧有4个按钮,分别是:快退,退一个单元,进一个单元,快进。快进和快退将一次性前进或后退一个页面的单元数量。 -键盘上的ASDF四个键从左至右也分别对应滑条左侧的四个按钮的功能。 +滑条左侧有4个按钮,分别是:快退,退一个单元,进一个单元,快进。快进和快退将一次性前进或后退一个页面的单元数量。 ## 模式介绍 @@ -33,16 +54,17 @@ 打开文件后,上部3个带有图标的按钮,是TAS编辑器的三种模式,它们分别是: -* Select mode:选择模式:允许成列的选择TAS操作单元。在此模式下可以进行复制,粘贴,插入和删除操作。 -* Fill mode:填充模式:像编辑表格那样,允许多列选择和跨行选择(但必须连续),并且支持在选择区域内批量设置或不设置项目 -* Draw mode:绘画模式:将鼠标视为画笔,反转点击的单元格的设置状态。 +* 选择模式:允许成列的选择TAS操作单元。在此模式下可以进行复制,粘贴,插入和删除操作。 +* 填充模式:像编辑表格那样,允许多列选择和跨行选择(但必须连续),并且支持在选择区域内批量设置或不设置项目 +* 画笔模式:将鼠标视为画笔,反转点击的单元格的设置状态。 ### 如何单选与多选 选择模式允许单选,直接单击某一个TAS操作单元,即可选中。 选择模式和填充模式允许多选,具体操作是点击某个单元格作为起始位置,然后按住Shift点击第二个单元格作为终止位置。完成多选。 -再次左键单击重新开始一次选择。再次按住Shift左键单击重新选定终止位置。 +再次左键单击重新开始一次选择。再次按住Shift左键单击重新选定终止位置。 +如果您仅仅只需要选中一个单元格,但是要求的操作需要多选,可以再按Shift点击当前单元完成多选。 ### 选择的标识 @@ -50,18 +72,25 @@ 填充模式下,选中的单元格的外边框将从灰色变为橘色。 -### 模式中的菜单 +## 特殊操作 -在表格页面右键将打开一个操作菜单,如下: +### 覆盖式粘贴与插入式粘贴 -* Set:位于填充模式且已多选时,设置选中单元为设置状态 -* Unset:位于填充模式且已多选时,设置选中单元为不设置状态 -* Copy:位于选择模式且已多选时,复制选中单元 -* Delete:位于选择模式且已多选时,删除选中单元 -* Paste after this:位于选择模式且已单选时,在其前方粘贴剪贴板中已复制的单元 -* Paste before this:位于选择模式且已单选时,在其后方粘贴剪贴板中已复制的单元 -* Add blank item after this:位于选择模式且已单选时,在其前方添加空白单元 -* Add blank item before this:位于选择模式且已单选时,在其后方添加空白单元 +覆盖式粘贴与插入式粘贴为粘贴的两种模式。 +插入式粘贴为在选中项前或后方插入剪贴板内的内容。 +覆盖式粘贴则将会以当前选中单元为粘贴的头或尾,向前或向后覆盖式写入剪贴板内的内容,如果后方或前方数据长度不够,则会添加额外的项目补充。 + +### 快捷键 + +* 键盘上的ASDF四个键从左至右也分别对应滑条左侧的四个按钮的功能。 +* `Ctrl + O`:打开文件 +* `Ctrl + S`:保存文件 +* `Ctrl + Z`:撤销 +* `Ctrl + Y`:重做 +* `Ctrl + X`:剪切 +* `Ctrl + C`:复制 +* `Delete`:向后删除 +* `Backspace`:向前删除 ## 出错啦