diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/CountableEnumerable.cs b/BallanceTasEditor/BallanceTasEditor/Backend/CountableEnumerable.cs
deleted file mode 100644
index 96d283c..0000000
--- a/BallanceTasEditor/BallanceTasEditor/Backend/CountableEnumerable.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BallanceTasEditor.Backend {
- ///
- /// 一种提前给定元素个数的的IEnumerable。
- ///
- public sealed class CountableEnumerable {
- ///
- /// 以直接方式构建。
- ///
- /// 一个迭代器,其最多只能迭代给定次数。
- /// 迭代器会迭代的次数。
- public CountableEnumerable(IEnumerable enumerable, int count) {
- m_Inner = enumerable;
- m_Count = count;
- }
-
- ///
- /// 从数组便捷构建。
- ///
- /// 要使用的数组。
- public CountableEnumerable(T[] array) {
- m_Inner = array;
- m_Count = array.Length;
- }
-
- private readonly IEnumerable m_Inner;
- private readonly int m_Count;
-
- ///
- /// 获取迭代器对象。
- ///
- /// 用于迭代的迭代器。
- /// 当迭代器迭代次数与给定次数不匹配时。
- public IEnumerable GetInner() {
- int counter = 0;
- foreach (var item in m_Inner) {
- if (counter >= m_Count) {
- throw new ArgumentException("Given IEnumerable is not stopped at given count.");
- } else {
- yield return item;
- ++counter;
- }
- }
-
- if (counter != m_Count) {
- throw new ArgumentException("Given IEnumerable is not stopped at given count.");
- }
- }
-
- ///
- /// 获取该迭代器会迭代的次数。
- ///
- /// 迭代器会迭代的次数,用于给使用该结构的方法提前分配必要的空间。
- public int GetCount() {
- return m_Count;
- }
-
- }
-}
diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/ExactSizeEnumerable.cs b/BallanceTasEditor/BallanceTasEditor/Backend/ExactSizeEnumerable.cs
new file mode 100644
index 0000000..c2dd6b7
--- /dev/null
+++ b/BallanceTasEditor/BallanceTasEditor/Backend/ExactSizeEnumerable.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BallanceTasEditor.Backend {
+
+ ///
+ /// 一种提前给定元素个数的的IEnumerable。
+ ///
+ ///
+ public interface IExactSizeEnumerable : IEnumerable {
+ ///
+ /// 该迭代器会返回的元素的个数。
+ ///
+ ///
+ /// 如果迭代器返回的元素个数与该方法给定的个数不同,
+ /// 则是未定义行为。
+ ///
+ /// 迭代器会返回的元素的准确个数。大于等于0。
+ public int GetCount();
+ }
+
+ ///
+ /// 将普通IEnumerable转变为IExactSizeEnumerable的适配器。
+ ///
+ ///
+ public sealed class ExactSizeEnumerableAdapter : IExactSizeEnumerable {
+ ///
+ /// 以迭代器和指定长度构建适配器。
+ ///
+ ///
+ /// 如果迭代器返回的元素个数与该方法给定的个数不同,
+ /// 则是未定义行为。
+ ///
+ /// 一个迭代器,其最多只能迭代给定次数。
+ /// 迭代器会迭代的次数。
+ public ExactSizeEnumerableAdapter(IEnumerable enumerable, int count) {
+ m_Inner = enumerable;
+ m_Count = count;
+ }
+
+ private readonly IEnumerable m_Inner;
+ private readonly int m_Count;
+
+ public IEnumerator GetEnumerator() {
+ return m_Inner.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return m_Inner.GetEnumerator();
+ }
+
+ public int GetCount() {
+ return m_Count;
+ }
+
+ }
+
+}
diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasClipboard.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasClipboard.cs
new file mode 100644
index 0000000..a0495fd
--- /dev/null
+++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasClipboard.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace BallanceTasEditor.Backend {
+ public class TasClipboard {
+ // Reference: https://stackoverflow.com/questions/22272822/copy-binary-data-to-clipboard
+
+ private static readonly string CLIPBOARD_DATA_FORMAT = "BallanceTasEditor.TasFrames";
+
+ public static void SetClipboard(IExactSizeEnumerable frames) {
+ DataObject data = new DataObject();
+ var rawFrames = frames.Select((f) => f.ToRaw()).ToArray();
+ data.SetData(CLIPBOARD_DATA_FORMAT, rawFrames, false);
+ Clipboard.SetDataObject(data, true);
+ }
+
+ private static RawTasFrame[]? GetClipboardObject() {
+ DataObject? retrievedData = Clipboard.GetDataObject() as DataObject;
+ if (retrievedData is null) return null;
+ if (!retrievedData.GetDataPresent(CLIPBOARD_DATA_FORMAT)) return null;
+
+ RawTasFrame[]? rawFrames = retrievedData.GetData(CLIPBOARD_DATA_FORMAT) as RawTasFrame[];
+ if (rawFrames is null) return null;
+
+ return rawFrames;
+ }
+
+ public static bool HasClipboard() {
+ return GetClipboardObject() is not null;
+ }
+
+ public static EnumerableArray? GetClipboard() {
+ var rawFrames = GetClipboardObject();
+ if (rawFrames is null) return null;
+
+ return new EnumerableArray(rawFrames);
+ }
+
+ public sealed class EnumerableArray : IExactSizeEnumerable {
+ public EnumerableArray(RawTasFrame[] rawFrames) {
+ m_RawFrames = rawFrames;
+ }
+
+ private RawTasFrame[] m_RawFrames;
+
+ public IEnumerator GetEnumerator() {
+ return m_RawFrames.Select((f) => new TasFrame(f)).GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
+ public int GetCount() {
+ return m_RawFrames.Length;
+ }
+
+ }
+ }
+}
diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasFrame.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasFrame.cs
index f8a6853..ed8675d 100644
--- a/BallanceTasEditor/BallanceTasEditor/Backend/TasFrame.cs
+++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasFrame.cs
@@ -11,6 +11,7 @@ namespace BallanceTasEditor.Backend {
/// 原始的TAS帧结构,与二进制结构保持一致。
///
[StructLayout(LayoutKind.Sequential)]
+ [Serializable]
public struct RawTasFrame {
///
/// 该帧的持续时间(以秒为单位)。
diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasOperationStack.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasOperationStack.cs
deleted file mode 100644
index 5bec10a..0000000
--- a/BallanceTasEditor/BallanceTasEditor/Backend/TasOperationStack.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace BallanceTasEditor.Backend {
- internal class TasOperationStack {
- }
-}
diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs
index 5f65ace..2875f67 100644
--- a/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs
+++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasSequence.cs
@@ -44,7 +44,7 @@ namespace BallanceTasEditor.Backend {
/// 要在前方插入数据的元素的索引。
/// 要插入的元素的迭代器。
/// 给定的索引无效。
- void Insert(int index, CountableEnumerable items);
+ void Insert(int index, IExactSizeEnumerable items);
///
/// 从序列中移出给定帧区间的元素。
///
@@ -89,7 +89,7 @@ namespace BallanceTasEditor.Backend {
throw new NotImplementedException();
}
- public void Insert(int index, CountableEnumerable items) {
+ public void Insert(int index, IExactSizeEnumerable items) {
throw new NotImplementedException();
}
@@ -139,14 +139,14 @@ namespace BallanceTasEditor.Backend {
}
}
- public void Insert(int index, CountableEnumerable items) {
+ public void Insert(int index, IExactSizeEnumerable items) {
if (index == m_Container.Count) {
- m_Container.AddRange(items.GetInner());
+ m_Container.AddRange(items);
} else {
if (index > m_Container.Count || index < 0) {
throw new IndexOutOfRangeException("Invalid index for frame.");
} else {
- m_Container.InsertRange(index, items.GetInner());
+ m_Container.InsertRange(index, items);
}
}
}
@@ -272,12 +272,12 @@ namespace BallanceTasEditor.Backend {
}
}
- public void Insert(int index, CountableEnumerable items) {
+ public void Insert(int index, IExactSizeEnumerable items) {
if (index >= m_Container.Count || index < 0) {
throw new IndexOutOfRangeException("Invalid index for frame.");
} else {
if (index == m_Container.Count) {
- foreach (TasFrame item in items.GetInner()) {
+ foreach (TasFrame item in items) {
m_Container.AddLast(item);
}
@@ -290,7 +290,7 @@ namespace BallanceTasEditor.Backend {
} else {
MoveToIndex(index);
- foreach (TasFrame item in items.GetInner()) {
+ foreach (TasFrame item in items) {
m_Container.AddBefore(m_Cursor.Node, item);
}
m_Cursor.Index += items.GetCount();
diff --git a/BallanceTasEditor/BallanceTasEditor/Backend/TasStorage.cs b/BallanceTasEditor/BallanceTasEditor/Backend/TasStorage.cs
index f940190..3f820dd 100644
--- a/BallanceTasEditor/BallanceTasEditor/Backend/TasStorage.cs
+++ b/BallanceTasEditor/BallanceTasEditor/Backend/TasStorage.cs
@@ -10,8 +10,8 @@ using System.Threading.Tasks;
namespace BallanceTasEditor.Backend {
public static class TasStorage {
- internal const int SIZEOF_F32 = sizeof(float);
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;
@@ -70,7 +70,7 @@ namespace BallanceTasEditor.Backend {
var memWrapper = new EnumerableMemoryStream(mem, expectedCount);
seq.Clear();
- seq.Insert(0, new CountableEnumerable(memWrapper, expectedCount));
+ seq.Insert(0, memWrapper);
mem.Close();
}
@@ -105,7 +105,7 @@ namespace BallanceTasEditor.Backend {
//target.Flush();
}
- private class EnumerableMemoryStream : IEnumerable {
+ private sealed class EnumerableMemoryStream : IExactSizeEnumerable {
public EnumerableMemoryStream(MemoryStream mem, int frameCnt) {
m_MemoryStream = mem;
m_FrameCount = frameCnt;
@@ -130,6 +130,9 @@ namespace BallanceTasEditor.Backend {
return GetEnumerator();
}
+ public int GetCount() {
+ return m_FrameCount;
+ }
}
}