@@ -57,15 +57,22 @@ pub struct Undoer<State> {
57
57
/// The latest undo point may (often) be the current state.
58
58
undos : VecDeque < State > ,
59
59
60
+ /// Stores redos immediately after a sequence of undos.
61
+ /// Gets cleared every time the state changes.
62
+ /// Does not need to be a deque, because there can only be up to undos.len() redos,
63
+ /// which is already limited to settings.max_undos.
64
+ redos : Vec < State > ,
65
+
60
66
#[ cfg_attr( feature = "serde" , serde( skip) ) ]
61
67
flux : Option < Flux < State > > ,
62
68
}
63
69
64
70
impl < State > std:: fmt:: Debug for Undoer < State > {
65
71
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
66
- let Self { undos, .. } = self ;
72
+ let Self { undos, redos , .. } = self ;
67
73
f. debug_struct ( "Undoer" )
68
74
. field ( "undo count" , & undos. len ( ) )
75
+ . field ( "redo count" , & redos. len ( ) )
69
76
. finish ( )
70
77
}
71
78
}
91
98
}
92
99
}
93
100
101
+ pub fn has_redo ( & self , current_state : & State ) -> bool {
102
+ !self . redos . is_empty ( ) && self . undos . back ( ) == Some ( current_state)
103
+ }
104
+
94
105
/// Return true if the state is currently changing
95
106
pub fn is_in_flux ( & self ) -> bool {
96
107
self . flux . is_some ( )
@@ -101,7 +112,9 @@ where
101
112
self . flux = None ;
102
113
103
114
if self . undos . back ( ) == Some ( current_state) {
104
- self . undos . pop_back ( ) ;
115
+ self . redos . push ( self . undos . pop_back ( ) . unwrap ( ) ) ;
116
+ } else {
117
+ self . redos . push ( current_state. clone ( ) ) ;
105
118
}
106
119
107
120
// Note: we keep the undo point intact.
@@ -111,9 +124,20 @@ where
111
124
}
112
125
}
113
126
127
+ pub fn redo ( & mut self , current_state : & State ) -> Option < & State > {
128
+ if !self . undos . is_empty ( ) && self . undos . back ( ) != Some ( current_state) {
129
+ // state changed since the last undo, redos should be cleared.
130
+ self . redos . clear ( ) ;
131
+ None
132
+ } else if let Some ( state) = self . redos . pop ( ) {
133
+ self . undos . push_back ( state) ;
134
+ self . undos . back ( )
135
+ } else {
136
+ None
137
+ }
138
+ }
139
+
114
140
/// Add an undo point if, and only if, there has been a change since the latest undo point.
115
- ///
116
- /// * `time`: current time in seconds.
117
141
pub fn add_undo ( & mut self , current_state : & State ) {
118
142
if self . undos . back ( ) != Some ( current_state) {
119
143
self . undos . push_back ( current_state. clone ( ) ) ;
@@ -139,6 +163,8 @@ where
139
163
if latest_undo == current_state {
140
164
self . flux = None ;
141
165
} else {
166
+ self . redos . clear ( ) ;
167
+
142
168
match self . flux . as_mut ( ) {
143
169
None => {
144
170
self . flux = Some ( Flux {
0 commit comments