Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Undo Feature initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
scofalik committed Mar 18, 2016
1 parent 9ffa064 commit c055ebf
Show file tree
Hide file tree
Showing 4 changed files with 515 additions and 0 deletions.
89 changes: 89 additions & 0 deletions src/undocommand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

'use strict';

import Command from '../command/command.js';

/**
* Undo command stores batches in itself and is able to and apply reverted versions of them on the document.
*
* undo.UndoCommand
*/
export default class UndoCommand extends Command {
/**
* @see core.command.Command
* @param {core.Editor} editor
*/
constructor( editor ) {
super( editor );

/**
* Batches which are saved by the command. They can be reversed.
*
* @private
* @member {Array.<core.treeModel.Batch>} core.command.UndoCommand#_batchStack
*/
this._batchStack = [];
}

/**
* Stores a batch in the command. Stored batches can be then reverted.
*
* @param {core.teeModel.Batch} batch Batch to add.
*/
addBatch( batch ) {
this._batchStack.push( batch );
}

/**
* Removes all batches from the stack.
*/
clearStack() {
this._batchStack = [];
}

/**
* Checks whether this command should be enabled. Command is enabled when it has any batches in its stack.
*
* @private
* @returns {Boolean}
*/
_checkEnabled() {
return this._batchStack.length > 0;
}

/**
* Executes the command: reverts a {@link core.treeModel.Batch batch} added to the command's stack,
* applies it on the document and removes the batch from the stack.
*
* Fires `undo` event with reverted batch as a parameter.
*
* @private
* @param {Number} [batchIndex] If set, batch under the given index on the stack will be reverted and removed.
* If not set, or invalid, the last added batch will be reverted and removed.
*/
_doExecute( batchIndex ) {
batchIndex = this._batchStack[ batchIndex ] ? batchIndex : this._batchStack.length - 1;

const undoBatch = this._batchStack.splice( batchIndex, 1 )[ 0 ];
const undoDeltas = undoBatch.deltas.slice();

undoDeltas.reverse();

for ( let undoDelta of undoDeltas ) {
const undoDeltaReversed = undoDelta.getReversed();
const updatedDeltas = this.editor.document.history.updateDelta( undoDeltaReversed );

for ( let delta of updatedDeltas ) {
for ( let operation of delta.operations ) {
this.editor.document.applyOperation( operation );
}
}
}

this.fire( 'undo', undoBatch );
}
}
71 changes: 71 additions & 0 deletions src/undofeature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

'use strict';

import Feature from '../feature.js';
import UndoCommand from './undocommand.js';

/**
* Undo feature.
*
* Undo features brings in possibility to undo and re-do changes done in Tree Model by deltas through Batch API.
*/
export default class UndoFeature extends Feature {
constructor( editor ) {
super( editor );

/**
* Undo command which manages undo {@link core.treeModel.Batch batches} stack (history).
* Created and registered during {@link undo.UndoFeature#init feature initialization}.
*
* @private
* @member {undo.UndoCommand} undo.UndoFeature#_undoCommand
*/
this._undoCommand = null;

/**
* Undo command which manages redo {@link core.treeModel.Batch batches} stack (history).
* Created and registered during {@link undo.UndoFeature#init feature initialization}.
*
* @private
* @member {undo.UndoCommand} undo.UndoFeature#_redoCommand
*/
this._redoCommand = null;
}

/**
* Initializes undo feature.
*/
init() {
// Create commands.
this._redoCommand = new UndoCommand( this.editor );
this._undoCommand = new UndoCommand( this.editor );

// Register command to the editor.
this.editor.commands.set( 'redo', this._redoCommand );
this.editor.commands.set( 'undo', this._undoCommand );

// Whenever new batch is created add it to undo history and clear redo history.
this.listenTo( this.editor.document, 'batch', ( evt, batch ) => {
this._undoCommand.addBatch( batch );
this._redoCommand.clearStack();
} );

// Whenever batch is reverted by undo command, add it to redo history.
this._undoCommand.listenTo( this._redoCommand, 'undo', ( evt, batch ) => {
this._undoCommand.addBatch( batch );
} );

// Whenever batch is reverted by redo command, add it to undo history.
this._redoCommand.listenTo( this._undoCommand, 'undo', ( evt, batch ) => {
this._redoCommand.addBatch( batch );
} );
}

destroy() {
this.stopListening();
}
}
Loading

0 comments on commit c055ebf

Please sign in to comment.