Created
March 7, 2018 13:54
-
-
Save nhaarman/e1e9bc34134a11b92c40c5f455e87d60 to your computer and use it in GitHub Desktop.
Simple Rx undo/redo stream
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fun <T, R> Observable<Command<T>>.undoRedo(initialValue: R, accumulator: (R, T) -> R): Observable<R> { | |
return this | |
.scan(UndoRedoStack.create<T>()) { stack, command -> | |
when (command) { | |
is Command.Do -> stack.push(command.action) | |
is Command.Undo -> stack.undo() | |
is Command.Redo -> stack.redo() | |
} | |
} | |
.map { stack -> | |
stack.actions.fold(initialValue, accumulator) | |
} | |
} | |
@Suppress("unused") | |
sealed class Command<out T> { | |
data class Do<T>(val action: T) : Command<T>() | |
object Undo : Command<Nothing>() | |
object Redo : Command<Nothing>() | |
} | |
private class UndoRedoStack<T> private constructor( | |
private val _actions: Stack<T>, | |
private val undoneEvents: Stack<T> | |
) { | |
val actions: List<T> get() = _actions | |
fun push(action: T): UndoRedoStack<T> { | |
_actions.push(action) | |
undoneEvents.clear() | |
return this | |
} | |
fun undo(): UndoRedoStack<T> { | |
if (_actions.isNotEmpty()) { | |
undoneEvents.push(_actions.pop()) | |
} | |
return this | |
} | |
fun redo(): UndoRedoStack<T> { | |
if (undoneEvents.isNotEmpty()) { | |
_actions.push(undoneEvents.pop()) | |
} | |
return this | |
} | |
companion object { | |
fun <T> create() = UndoRedoStack<T>(Stack(), Stack()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment