correct Delete operation behavior

This commit is contained in:
2021-07-27 17:17:34 +08:00
parent e4c6da9990
commit 250dff7107
3 changed files with 38 additions and 18 deletions

View File

@ -89,7 +89,7 @@ namespace BallanceTASEditor.Core.FileOperation {
removedItems.Clear(); removedItems.Clear();
oldPointer = mPointer; oldPointer = mPointer;
oldPointerIndex = mPointerIndex; oldPointerIndex = mPointerIndex;
removeStartNode = absoluteRange.start == 1 ? null : mMem.FastGetNode(mPointer, mPointerIndex, absoluteRange.start - 1); removeStartNode = absoluteRange.start == 0 ? null : mMem.FastGetNode(mPointer, mPointerIndex, absoluteRange.start - 1);
// find proper pointer after remove first. but we do not apply it in there. // find proper pointer after remove first. but we do not apply it in there.
// if state is true, it mean the deleted content is placed before pointer previously. we should consider pointer data and we should correct them. // if state is true, it mean the deleted content is placed before pointer previously. we should consider pointer data and we should correct them.
@ -100,25 +100,25 @@ namespace BallanceTASEditor.Core.FileOperation {
// otherwise we only need to minus index with the length of removed content. // otherwise we only need to minus index with the length of removed content.
if (absoluteRange.Within(mPointerIndex)) { if (absoluteRange.Within(mPointerIndex)) {
// this contains 3 situation // this contains 3 situation
// if full delete, mPointer is null and mPointerIndex is invalid(with wrong data: 0) // if full delete, mPointer is null and mPointerIndex is invalid(with wrong data: -1)
// if delete from head, mPointer and mPointerIndex all are valid. but it is the tail of removed content // if delete from head, mPointer and mPointerIndex all are valid. but it is the tail of removed content
// otherwise, just find the head of removed content and shift to it. // otherwise, just find the head of removed content and shift to it.
if (absoluteRange.start == 1 && absoluteRange.end == mMem.Count) { if (absoluteRange.start == 0 && absoluteRange.end == mMem.Count - 1) {
// fully remove // fully remove
newPointer = null; newPointer = null;
newPointerIndex = 0; newPointerIndex = -1;
} else if (absoluteRange.start == 1) { } else if (absoluteRange.start == 0) {
// remove from head // remove from head
newPointerIndex = absoluteRange.end + 1; newPointerIndex = 0;
newPointer = mMem.FastGetNode(mPointer, mPointerIndex, newPointerIndex); newPointer = mMem.FastGetNode(mPointer, mPointerIndex, absoluteRange.end + 1);
} else { } else {
// simple remove // simple remove
newPointerIndex = absoluteRange.start - 1; newPointerIndex = absoluteRange.start - 1;
newPointer = mMem.FastGetNode(mPointer, mPointerIndex, newPointerIndex); newPointer = mMem.FastGetNode(mPointer, mPointerIndex, absoluteRange.start - 1);
} }
} else { } else {
newPointer = mPointer; newPointer = mPointer;
newPointerIndex = mPointerIndex - absoluteRange.GetCount() + 1; newPointerIndex = mPointerIndex - absoluteRange.GetCount();
} }
} else { } else {
// not affected situation // not affected situation
@ -128,8 +128,8 @@ namespace BallanceTASEditor.Core.FileOperation {
// the real remove operation // the real remove operation
foreach (var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) { foreach (var item in mMem.IterateWithSelectionRange(absoluteRange, mPointer, mPointerIndex)) {
removedItems.AddLast(item); // backups node first;
mMem.Remove(item); mMem.Remove(item);
removedItems.AddLast(item); // backups node;
} }
// apply gotten new pointer // apply gotten new pointer
@ -140,10 +140,12 @@ namespace BallanceTASEditor.Core.FileOperation {
public override void Undo(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) { public override void Undo(ref LinkedList<FrameData> mMem, ref LinkedListNode<FrameData> mPointer, ref long mPointerIndex) {
base.Undo(ref mMem, ref mPointer, ref mPointerIndex); base.Undo(ref mMem, ref mPointer, ref mPointerIndex);
if (mPointer == null) return; // may recovered from empty list
//if (mPointer == null) return;
// re-insert data // re-insert data
foreach (var item in removedItems.IterateFullReversed()) { foreach (var item in removedItems.IterateFullReversed()) {
removedItems.Remove(item);
if (removeStartNode == null) { if (removeStartNode == null) {
// insert at first // insert at first
mMem.AddFirst(item); mMem.AddFirst(item);
@ -395,11 +397,13 @@ namespace BallanceTASEditor.Core.FileOperation {
// if we use overwrite mode, we need re-add lost data // if we use overwrite mode, we need re-add lost data
if (isOverwritten) { if (isOverwritten) {
if (isInsertBefore) { if (isInsertBefore) {
foreach (var item in data.IterateFull()) { foreach (var item in oldItems.IterateFull()) {
oldItems.Remove(item);
mMem.AddBefore(addStartNode, item); mMem.AddBefore(addStartNode, item);
} }
} else { } else {
foreach (var item in data.IterateFullReversed()) { foreach (var item in oldItems.IterateFullReversed()) {
oldItems.Remove(item);
mMem.AddAfter(addStartNode, item); mMem.AddAfter(addStartNode, item);
} }
} }

View File

@ -33,21 +33,27 @@ namespace BallanceTASEditor.Core {
// for (int i = 0; i < count; i++) list.RemoveAt(index); // for (int i = 0; i < count; i++) list.RemoveAt(index);
//} //}
// remove safety. because it store the next node.
public static IEnumerable<LinkedListNode<FrameData>> IterateFullReversed(this LinkedList<FrameData> ls) { public static IEnumerable<LinkedListNode<FrameData>> IterateFullReversed(this LinkedList<FrameData> ls) {
var pos = ls.Last; var pos = ls.Last;
LinkedListNode<FrameData> cacheNextNode;
while (pos != null) { while (pos != null) {
cacheNextNode = pos.Previous;
yield return pos; yield return pos;
pos = pos.Previous; pos = cacheNextNode;
} }
} }
// remove safety. because it store the next node.
public static IEnumerable<LinkedListNode<FrameData>> IterateFull(this LinkedList<FrameData> ls) { public static IEnumerable<LinkedListNode<FrameData>> IterateFull(this LinkedList<FrameData> ls) {
var pos = ls.First; var pos = ls.First;
LinkedListNode<FrameData> cacheNextNode;
while(pos != null) { while(pos != null) {
cacheNextNode = pos.Next;
yield return pos; yield return pos;
pos = pos.Next; pos = cacheNextNode;
} }
} }

View File

@ -191,13 +191,23 @@ namespace BallanceTASEditor.UI {
case OperationEnum.DeleteAfter: case OperationEnum.DeleteAfter:
case OperationEnum.DeleteBefore: { case OperationEnum.DeleteBefore: {
var pos = mSelectionHelp.GetPoint(); var pos = mSelectionHelp.GetPoint();
pos += oper == OperationEnum.DeleteBefore ? -1 : 1; if (oper == OperationEnum.DeleteBefore) pos -= 1; // delete after mean delete current selected item
if (pos < 0 || pos > mFile.mFrameCount) return; if (pos < 0 || pos >= mFile.mFrameCount) return;
mFile.Remove(new SelectionRange(pos, pos));
// only delete before need shift selection // only delete before need shift selection
// delete before couldn't cause empty list, so we just need to directly shift
if (oper == OperationEnum.DeleteBefore) if (oper == OperationEnum.DeleteBefore)
mSelectionHelp.ShiftTo(false); mSelectionHelp.ShiftTo(false);
// also, if we use delete after and delete the tail of item list, we also need to shift pos(use `else if` to prevent double shift)
else if (oper == OperationEnum.DeleteAfter && pos == mFile.mFrameCount) {
// but delete after may cause empty list error(delete the item within only 1 item list)
// so we need prevent this situation
if (mFile.mFrameCount == 1) mSelectionHelp.Reset(); //yes, reset selection to prevent error
else mSelectionHelp.ShiftTo(false); //no, shift selection.
}
// do real operation
mFile.Remove(new SelectionRange(pos, pos));
updateSliderRange(); updateSliderRange();
RefreshDisplay(); RefreshDisplay();