@@ -15,45 +15,7 @@ import TextStory
1515/// - Grouping pasted text
1616///
1717/// If needed, the automatic undo grouping can be overridden using the `beginGrouping()` and `endGrouping()` methods.
18- public class CEUndoManager {
19- /// An `UndoManager` subclass that forwards relevant actions to a `CEUndoManager`.
20- /// Allows for objects like `TextView` to use the `UndoManager` API
21- /// while CETV manages the undo/redo actions.
22- public class DelegatedUndoManager : UndoManager {
23- weak var parent : CEUndoManager ?
24-
25- public override var isUndoing : Bool { parent? . isUndoing ?? false }
26- public override var isRedoing : Bool { parent? . isRedoing ?? false }
27- public override var canUndo : Bool { parent? . canUndo ?? false }
28- public override var canRedo : Bool { parent? . canRedo ?? false }
29-
30- public func registerMutation( _ mutation: TextMutation ) {
31- parent? . registerMutation ( mutation)
32- removeAllActions ( )
33- }
34-
35- public override func undo( ) {
36- parent? . undo ( )
37- }
38-
39- public override func redo( ) {
40- parent? . redo ( )
41- }
42-
43- public override func beginUndoGrouping( ) {
44- parent? . beginUndoGrouping ( )
45- }
46-
47- public override func endUndoGrouping( ) {
48- parent? . endUndoGrouping ( )
49- }
50-
51- public override func registerUndo( withTarget target: Any , selector: Selector , object anObject: Any ? ) {
52- // no-op, but just in case to save resources:
53- removeAllActions ( )
54- }
55- }
56-
18+ public class CEUndoManager : UndoManager {
5719 /// Represents a group of mutations that should be treated as one mutation when undoing/redoing.
5820 private struct UndoGroup {
5921 var mutations : [ Mutation ]
@@ -65,16 +27,17 @@ public class CEUndoManager {
6527 var inverse : TextMutation
6628 }
6729
68- public let manager : DelegatedUndoManager
69- private( set) public var isUndoing : Bool = false
70- private( set) public var isRedoing : Bool = false
30+ private var _isUndoing : Bool = false
31+ private var _isRedoing : Bool = false
7132
72- public var canUndo : Bool {
73- !undoStack. isEmpty
74- }
75- public var canRedo : Bool {
76- !redoStack. isEmpty
77- }
33+ override public var isUndoing : Bool { _isUndoing }
34+ override public var isRedoing : Bool { _isRedoing }
35+
36+ override public var undoCount : Int { undoStack. count }
37+ override public var redoCount : Int { redoStack. count }
38+
39+ override public var canUndo : Bool { !undoStack. isEmpty }
40+ override public var canRedo : Bool { !redoStack. isEmpty }
7841
7942 /// A stack of operations that can be undone.
8043 private var undoStack : [ UndoGroup ] = [ ]
@@ -93,10 +56,7 @@ public class CEUndoManager {
9356
9457 // MARK: - Init
9558
96- public init ( ) {
97- self . manager = DelegatedUndoManager ( )
98- manager. parent = self
99- }
59+ override public init ( ) { }
10060
10161 convenience init ( textView: TextView ) {
10262 self . init ( )
@@ -106,37 +66,49 @@ public class CEUndoManager {
10666 // MARK: - Undo/Redo
10767
10868 /// Performs an undo operation if there is one available.
109- public func undo( ) {
110- guard !isDisabled, let item = undoStack. popLast ( ) , let textView else {
69+ override public func undo( ) {
70+ guard !isDisabled, let textView else {
71+ return
72+ }
73+
74+ guard let item = undoStack. popLast ( ) else {
75+ NSSound . beep ( )
11176 return
11277 }
113- isUndoing = true
114- NotificationCenter . default. post ( name: . NSUndoManagerWillUndoChange, object: self . manager)
78+
79+ _isUndoing = true
80+ NotificationCenter . default. post ( name: . NSUndoManagerWillUndoChange, object: self )
11581 textView. textStorage. beginEditing ( )
11682 for mutation in item. mutations. reversed ( ) {
11783 textView. replaceCharacters ( in: mutation. inverse. range, with: mutation. inverse. string)
11884 }
11985 textView. textStorage. endEditing ( )
120- NotificationCenter . default. post ( name: . NSUndoManagerDidUndoChange, object: self . manager )
86+ NotificationCenter . default. post ( name: . NSUndoManagerDidUndoChange, object: self )
12187 redoStack. append ( item)
122- isUndoing = false
88+ _isUndoing = false
12389 }
12490
12591 /// Performs a redo operation if there is one available.
126- public func redo( ) {
127- guard !isDisabled, let item = redoStack. popLast ( ) , let textView else {
92+ override public func redo( ) {
93+ guard !isDisabled, let textView else {
94+ return
95+ }
96+
97+ guard let item = redoStack. popLast ( ) else {
98+ NSSound . beep ( )
12899 return
129100 }
130- isRedoing = true
131- NotificationCenter . default. post ( name: . NSUndoManagerWillRedoChange, object: self . manager)
101+
102+ _isRedoing = true
103+ NotificationCenter . default. post ( name: . NSUndoManagerWillRedoChange, object: self )
132104 textView. textStorage. beginEditing ( )
133105 for mutation in item. mutations {
134106 textView. replaceCharacters ( in: mutation. mutation. range, with: mutation. mutation. string)
135107 }
136108 textView. textStorage. endEditing ( )
137- NotificationCenter . default. post ( name: . NSUndoManagerDidRedoChange, object: self . manager )
109+ NotificationCenter . default. post ( name: . NSUndoManagerDidRedoChange, object: self )
138110 undoStack. append ( item)
139- isRedoing = false
111+ _isRedoing = false
140112 }
141113
142114 /// Clears the undo/redo stacks.
@@ -147,11 +119,17 @@ public class CEUndoManager {
147119
148120 // MARK: - Mutations
149121
122+ public override func registerUndo( withTarget target: Any , selector: Selector , object anObject: Any ? ) {
123+ // no-op, but just in case to save resources:
124+ removeAllActions ( )
125+ }
126+
150127 /// Registers a mutation into the undo stack.
151128 ///
152129 /// Calling this method while the manager is in an undo/redo operation will result in a no-op.
153130 /// - Parameter mutation: The mutation to register for undo/redo
154131 public func registerMutation( _ mutation: TextMutation ) {
132+ removeAllActions ( )
155133 guard let textView,
156134 let textStorage = textView. textStorage,
157135 !isUndoing,
@@ -178,15 +156,15 @@ public class CEUndoManager {
178156 // MARK: - Grouping
179157
180158 /// Groups all incoming mutations.
181- public func beginUndoGrouping( ) {
159+ override public func beginUndoGrouping( ) {
182160 guard !isGrouping else { return }
183161 isGrouping = true
184162 // This is a new undo group, break for it.
185163 shouldBreakNextGroup = true
186164 }
187165
188166 /// Stops grouping all incoming mutations.
189- public func endUndoGrouping( ) {
167+ override public func endUndoGrouping( ) {
190168 guard isGrouping else { return }
191169 isGrouping = false
192170 // We just ended a group, do not allow the next mutation to be added to the group we just made.
0 commit comments