import * as InkModel from '../model/InkModel'
import * as UndoRedoContext from '../model/UndoRedoContext'
import { modelLogger as logger } from '../configuration/LoggerConfig'
import Constants from '../configuration/Constants'
/**
* Undo/redo manager
* @typedef {Object} UndoRedoManager
* @property {function} updateModel Push the current model into the undo/redo context.
* @property {function} undo Undo.
* @property {function} redo Redo.
* @property {function} clear Clear.
*/
/**
* Get current model in stack
* @param {UndoRedoContext} undoRedoContext Current undo/redo context
* @param {Boolean} [clone=true] Whether or not to clone the model
* @param {...String} types
*/
export function getModel (undoRedoContext, clone = true, ...types) {
const model = undoRedoContext.stack[undoRedoContext.currentPosition]
const val = {
res: clone ? InkModel.cloneModel(model) : model,
types
}
return Promise.resolve(val)
}
/**
* Mutate the undoRedo stack by adding a new model to it.
* @param {UndoRedoContext} undoRedoContext Current undo/redo context.
* @param {Model} model Current model.
*/
export function updateModel (undoRedoContext, model) {
// Used to update the model with the recognition result if relevant
const modelIndex = undoRedoContext.stack.findIndex(item => (item.modificationTime === model.modificationTime) && (item.rawStrokes.length === model.rawStrokes.length))
const modelReference = model
modelReference.modificationTime = new Date().getTime()
const types = []
if (modelIndex > -1) {
undoRedoContext.stack.splice(modelIndex, 1, InkModel.cloneModel(modelReference))
logger.debug('model updated', modelReference)
} else {
const undoRedoContextReference = undoRedoContext
undoRedoContextReference.currentPosition += 1
undoRedoContextReference.stack = undoRedoContextReference.stack.slice(0, undoRedoContextReference.currentPosition)
undoRedoContextReference.stack.push(InkModel.cloneModel(modelReference))
if (undoRedoContextReference.stack.length > undoRedoContextReference.maxSize) {
undoRedoContextReference.stack.shift()
undoRedoContextReference.currentPosition--
}
logger.debug('model pushed', modelReference)
types.push(Constants.EventType.CHANGED)
}
UndoRedoContext.updateUndoRedoState(undoRedoContext)
logger.debug('undo/redo stack updated', undoRedoContext)
return getModel(undoRedoContext, false, ...types)
}
/**
* Undo
* @param {UndoRedoContext} undoRedoContext Current undo/redo context.
* @param {Model} model Current model.
*/
export function undo (undoRedoContext, model) {
const undoRedoContextReference = undoRedoContext
if (undoRedoContextReference.currentPosition > 0) {
undoRedoContextReference.currentPosition -= 1
UndoRedoContext.updateUndoRedoState(undoRedoContext)
logger.debug('undo index', undoRedoContextReference.currentPosition)
}
return getModel(undoRedoContext, true, Constants.EventType.CHANGED, Constants.EventType.EXPORTED)
}
/**
* Redo
* @param {UndoRedoContext} undoRedoContext Current undo/redo context.
* @param {Model} model Current model.
*/
export function redo (undoRedoContext, model) {
const undoRedoContextReference = undoRedoContext
if (undoRedoContextReference.currentPosition < undoRedoContextReference.stack.length - 1) {
undoRedoContextReference.currentPosition += 1
UndoRedoContext.updateUndoRedoState(undoRedoContext)
logger.debug('redo index', undoRedoContextReference.currentPosition)
}
return getModel(undoRedoContext, true, Constants.EventType.CHANGED, Constants.EventType.EXPORTED)
}