Skip to content

Commit d5ef35f

Browse files
Force Break Undo Groups When Forcing Grouping (#81)
### Description Forces the undo manager to start a new undo group after calling `startUndoGrouping` or `endUndoGrouping`. This fixes a case where two groups could accidentally be combined. For instance when dragging text and then dragging it back into the same spot. Previously that operation would result in the following undo grouping: After first drag: ``` Group 1: - {0,8} "" // Removed text Group 2: - {0, 0} "DragText" // Inserted text ``` After dragging back to the original location: ``` Group 1: - {0,8} "" // Removed text Group 2: - {0, 0} "DragText" // Inserted text - {0,8} "" // Removed text Group 3: - {0, 0} "DragText" // Inserted text ``` When it *should* have looked like the following after the second drag back to the original position. ``` Group 1: - {0,8} "" // Removed text Group 2: - {0, 0} "DragText" // Inserted text Group 3: - {0,8} "" // Removed text Group 4: - {0, 0} "DragText" // Inserted text ``` ### Related Issues * N/A ### Checklist <!--- Add things that are not yet implemented above --> - [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md) - [x] The issues this PR addresses are related to each other - [x] My changes generate no new warnings - [x] My code builds and runs on my machine - [x] My changes are all related to the related issue above - [x] I documented my code ### Screenshots N/A
1 parent 82bc832 commit d5ef35f

File tree

1 file changed

+20
-10
lines changed

1 file changed

+20
-10
lines changed

Sources/CodeEditTextView/Utils/CEUndoManager.swift

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public class CEUndoManager {
8383

8484
private weak var textView: TextView?
8585
private(set) public var isGrouping: Bool = false
86+
87+
/// After ``endUndoGrouping`` is called, we'd expect the next mutation to be exclusive no matter what. This
88+
/// flag facilitates that, and is set by ``endUndoGrouping``
89+
private var shouldBreakNextGroup: Bool = false
90+
8691
/// True when the manager is ignoring mutations.
8792
private var isDisabled: Bool = false
8893

@@ -154,18 +159,19 @@ public class CEUndoManager {
154159
return
155160
}
156161
let newMutation = Mutation(mutation: mutation, inverse: textStorage.inverseMutation(for: mutation))
157-
if !undoStack.isEmpty, let lastMutation = undoStack.last?.mutations.last {
158-
if isGrouping || shouldContinueGroup(newMutation, lastMutation: lastMutation) {
159-
undoStack[undoStack.count - 1].mutations.append(newMutation)
160-
} else {
161-
undoStack.append(UndoGroup(mutations: [newMutation]))
162-
}
162+
// We can continue a group if:
163+
// - A group exists
164+
// - We're not direct to break the current group
165+
// - We're forced grouping OR we automagically detect we can group.
166+
if !undoStack.isEmpty,
167+
let lastMutation = undoStack.last?.mutations.last,
168+
!shouldBreakNextGroup,
169+
isGrouping || shouldContinueGroup(newMutation, lastMutation: lastMutation) {
170+
undoStack[undoStack.count - 1].mutations.append(newMutation)
163171
} else {
164-
undoStack.append(
165-
UndoGroup(mutations: [newMutation])
166-
)
172+
undoStack.append(UndoGroup(mutations: [newMutation]))
173+
shouldBreakNextGroup = false
167174
}
168-
169175
redoStack.removeAll()
170176
}
171177

@@ -178,6 +184,8 @@ public class CEUndoManager {
178184
return
179185
}
180186
isGrouping = true
187+
// This is a new undo group, break for it.
188+
shouldBreakNextGroup = true
181189
}
182190

183191
/// Stops grouping all incoming mutations.
@@ -187,6 +195,8 @@ public class CEUndoManager {
187195
return
188196
}
189197
isGrouping = false
198+
// We just ended a group, do not allow the next mutation to be added to the group we just made.
199+
shouldBreakNextGroup = true
190200
}
191201

192202
/// Determines whether or not two mutations should be grouped.

0 commit comments

Comments
 (0)