2011-11-02 21:00:55 +00:00
|
|
|
/**
|
2012-06-20 01:20:28 +00:00
|
|
|
* DataModel surface.
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @class
|
|
|
|
* @constructor
|
2012-02-06 23:50:56 +00:00
|
|
|
* @extends {ve.EventEmitter}
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {ve.dm.Document} doc Document model to create surface for
|
2011-11-02 21:00:55 +00:00
|
|
|
*/
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.dm.Surface = function( doc ) {
|
2011-11-22 22:59:05 +00:00
|
|
|
// Inheritance
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.EventEmitter.call( this );
|
2011-11-22 22:59:05 +00:00
|
|
|
// Properties
|
2012-06-20 01:20:28 +00:00
|
|
|
this.documentModel = doc;
|
2011-12-06 01:52:38 +00:00
|
|
|
this.selection = null;
|
2011-12-09 23:52:41 +00:00
|
|
|
this.smallStack = [];
|
|
|
|
this.bigStack = [];
|
|
|
|
this.undoIndex = 0;
|
2012-06-20 01:20:28 +00:00
|
|
|
this.historyTrackingInterval = null;
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Methods */
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
ve.dm.Surface.prototype.startHistoryTracking = function() {
|
|
|
|
this.historyTrackingInterval = setInterval( ve.proxy( this.breakpoint, this ), 750 );
|
|
|
|
};
|
|
|
|
|
|
|
|
ve.dm.Surface.prototype.stopHistoryTracking = function() {
|
|
|
|
clearInterval( this.historyTrackingInterval );
|
|
|
|
};
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.dm.Surface.prototype.purgeHistory = function() {
|
2011-12-09 20:40:26 +00:00
|
|
|
this.selection = null;
|
2011-12-12 22:51:32 +00:00
|
|
|
this.smallStack = [];
|
|
|
|
this.bigStack = [];
|
2012-02-24 00:49:28 +00:00
|
|
|
this.undoIndex = 0;
|
2011-12-09 20:40:26 +00:00
|
|
|
};
|
2011-11-22 22:59:05 +00:00
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.dm.Surface.prototype.getHistory = function() {
|
2011-12-13 00:56:29 +00:00
|
|
|
if ( this.smallStack.length > 0 ) {
|
2012-02-24 00:49:28 +00:00
|
|
|
return this.bigStack.slice( 0 ).concat( [{ 'stack': this.smallStack.slice(0) }] );
|
2011-12-13 00:56:29 +00:00
|
|
|
} else {
|
2012-02-07 00:42:16 +00:00
|
|
|
return this.bigStack.slice( 0 );
|
2011-12-13 00:56:29 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-11-22 22:59:05 +00:00
|
|
|
/**
|
|
|
|
* Gets the document model of the surface.
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-22 22:59:05 +00:00
|
|
|
* @method
|
2012-02-06 23:50:56 +00:00
|
|
|
* @returns {ve.dm.DocumentNode} Document model of the surface
|
2011-11-22 22:59:05 +00:00
|
|
|
*/
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.dm.Surface.prototype.getDocument = function() {
|
2012-06-20 01:20:28 +00:00
|
|
|
return this.documentModel;
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
2011-11-22 22:59:05 +00:00
|
|
|
|
|
|
|
/**
|
2012-02-24 00:49:28 +00:00
|
|
|
* Gets the selection
|
|
|
|
*
|
2011-11-22 22:59:05 +00:00
|
|
|
* @method
|
2012-02-06 23:50:56 +00:00
|
|
|
* @returns {ve.Range} Current selection
|
2011-11-22 22:59:05 +00:00
|
|
|
*/
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.dm.Surface.prototype.getSelection = function() {
|
2011-11-22 22:59:05 +00:00
|
|
|
return this.selection;
|
|
|
|
};
|
|
|
|
|
2012-04-06 15:43:14 +00:00
|
|
|
/**
|
2012-06-20 01:20:28 +00:00
|
|
|
* Applies a series of transactions to the content data and sets the selection.
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-22 22:59:05 +00:00
|
|
|
* @method
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {ve.dm.Transaction} transaction Transaction to apply to the document
|
2012-02-06 23:50:56 +00:00
|
|
|
* @param {ve.Range} selection
|
2011-11-22 22:59:05 +00:00
|
|
|
*/
|
2012-06-20 01:20:28 +00:00
|
|
|
ve.dm.Surface.prototype.change = function( transaction, selection ) {
|
|
|
|
if ( transaction ) {
|
|
|
|
this.bigStack = this.bigStack.slice( 0, this.bigStack.length - this.undoIndex );
|
|
|
|
this.undoIndex = 0;
|
|
|
|
this.smallStack.push( transaction );
|
|
|
|
ve.dm.TransactionProcessor.commit( this.getDocument(), transaction );
|
|
|
|
}
|
|
|
|
if ( selection && ( !this.selection || !this.selection.equals ( selection ) ) ) {
|
|
|
|
selection.normalize();
|
2012-02-24 00:49:28 +00:00
|
|
|
this.selection = selection;
|
2012-06-20 01:20:28 +00:00
|
|
|
this.emit ('select', this.selection.clone() );
|
|
|
|
}
|
|
|
|
if ( transaction ) {
|
|
|
|
this.emit( 'transact', transaction );
|
|
|
|
}
|
|
|
|
this.emit( 'change', transaction, selection );
|
2011-12-06 01:52:38 +00:00
|
|
|
};
|
|
|
|
|
2011-11-22 22:59:05 +00:00
|
|
|
/**
|
2012-06-20 01:20:28 +00:00
|
|
|
* Applies an annotation to the current selection
|
2012-02-24 00:49:28 +00:00
|
|
|
*
|
2011-11-22 22:59:05 +00:00
|
|
|
* @method
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {String} annotation action: toggle, clear, set
|
|
|
|
* @param {Object} annotation object to apply.
|
2011-11-22 22:59:05 +00:00
|
|
|
*/
|
2012-06-20 01:20:28 +00:00
|
|
|
ve.dm.Surface.prototype.annotate = function( method, annotation ) {
|
|
|
|
var selection = this.getSelection();
|
|
|
|
if ( this.selection.getLength() ) {
|
|
|
|
var tx = ve.dm.Transaction.newFromAnnotation(
|
|
|
|
this.getDocument(), selection, method, annotation
|
|
|
|
);
|
|
|
|
this.change( tx );
|
|
|
|
}
|
2011-11-22 22:59:05 +00:00
|
|
|
};
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.dm.Surface.prototype.breakpoint = function( selection ) {
|
2011-12-09 23:52:41 +00:00
|
|
|
if( this.smallStack.length > 0 ) {
|
|
|
|
this.bigStack.push( {
|
|
|
|
stack: this.smallStack,
|
|
|
|
selection: selection || this.selection.clone()
|
|
|
|
} );
|
|
|
|
this.smallStack = [];
|
2012-06-20 01:20:28 +00:00
|
|
|
this.emit ( 'history' );
|
2012-04-02 22:28:26 +00:00
|
|
|
}
|
|
|
|
};
|
2011-12-09 23:52:41 +00:00
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.dm.Surface.prototype.undo = function() {
|
2011-12-09 23:52:41 +00:00
|
|
|
this.breakpoint();
|
2012-02-24 00:49:28 +00:00
|
|
|
this.undoIndex++;
|
2011-12-09 23:52:41 +00:00
|
|
|
if ( this.bigStack[this.bigStack.length - this.undoIndex] ) {
|
|
|
|
var diff = 0;
|
|
|
|
var item = this.bigStack[this.bigStack.length - this.undoIndex];
|
|
|
|
for( var i = item.stack.length - 1; i >= 0; i-- ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
this.documentModel.rollback( item.stack[i] );
|
2011-12-09 23:52:41 +00:00
|
|
|
diff += item.stack[i].lengthDifference;
|
2011-12-01 19:07:40 +00:00
|
|
|
}
|
2011-12-09 23:52:41 +00:00
|
|
|
var selection = item.selection;
|
2012-06-20 01:20:28 +00:00
|
|
|
selection.end -= diff;
|
|
|
|
this.emit ( 'history' );
|
|
|
|
return selection;
|
2011-12-01 19:07:40 +00:00
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
return null;
|
2011-11-22 22:59:05 +00:00
|
|
|
};
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.dm.Surface.prototype.redo = function() {
|
2011-12-09 23:52:41 +00:00
|
|
|
this.breakpoint();
|
|
|
|
if ( this.undoIndex > 0 ) {
|
|
|
|
if ( this.bigStack[this.bigStack.length - this.undoIndex] ) {
|
|
|
|
var diff = 0;
|
|
|
|
var item = this.bigStack[this.bigStack.length - this.undoIndex];
|
|
|
|
for( var i = 0; i < item.stack.length; i++ ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
this.documentModel.commit( item.stack[i] );
|
2011-12-09 23:52:41 +00:00
|
|
|
diff += item.stack[i].lengthDifference;
|
|
|
|
}
|
|
|
|
var selection = item.selection;
|
2012-06-20 01:20:28 +00:00
|
|
|
selection.end += diff;
|
2011-12-09 23:52:41 +00:00
|
|
|
}
|
|
|
|
this.undoIndex--;
|
2012-06-20 01:20:28 +00:00
|
|
|
this.emit ( 'history' );
|
|
|
|
return selection;
|
2011-12-09 23:52:41 +00:00
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
return null;
|
2011-11-22 22:59:05 +00:00
|
|
|
};
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
|
2011-11-22 22:59:05 +00:00
|
|
|
/* Inheritance */
|
|
|
|
|
2012-02-06 23:50:56 +00:00
|
|
|
ve.extendClass( ve.dm.Surface, ve.EventEmitter );
|