This repository has been archived by the owner on Jun 26, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 40
Merged
T/undo 2 #499
Changes from 12 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
0e63536
Added: engine.model.Batch#type. Initial batch has now 'ignore' type.
scofalik 1c91980
Added: engine.model.Batch#baseVersion.
scofalik 1147c71
Cleared and rewritten engine.model.History.
scofalik 51bbbc5
Docs: engine.model.Batch fix.
scofalik 69ce444
Changed: RemoveOperation now inserts "holder" elements in graveyard f…
scofalik ecaf85d
Added: engine.model.CompressedHistory.
scofalik 9b2d6b3
Added: setter for RemoveOperation#_holderElementOffset and changed it…
scofalik 999d74c
Fixed: In OT, RemoveOperations created by splitting RemoveOperation h…
scofalik 3a7cabd
Merge branch 'master' into t/undo-2
Reinmar a48602c
Docs: fixed docs for CompressedHistory#removeDelta.
scofalik 03232e6
API docs fixes.
Reinmar 18be3a0
Docs: minor fix in Batch.
scofalik f566d0b
Changed: merge CompressedHistory and History into one class History.
scofalik 90f9103
Change: rename RemoveOperation#_insertHolderElement to #_needsHolderE…
scofalik 5030ee8
Changed: Batch.type available values reduced to 'transparent' and 'de…
scofalik File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/** | ||
* @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
'use strict'; | ||
|
||
import History from './history.js'; | ||
|
||
/** | ||
* `CompressedHistory` keeps deltas applied to the {@link engine.model.Document document} in their transformed state. Deltas | ||
* stored in `CompressedHistory` might get updated, split into more deltas or removed as other deltas are applied to the document. | ||
* Modifying the original deltas history results in a compressed version of history and makes some scripts faster and easier to implement. | ||
* | ||
* **Note:** deltas kept in `CompressedHistory` should be used only to transform deltas. Do not use `CompressedHistory` to get original | ||
* delta (especially basing on its {@link engine.model.delta.Delta#baseVersion baseVersion}). Do not trust base versions of deltas | ||
* returned by `CompressedHistory`. After transforming your delta by deltas from `CompressedHistory`, fix its base version accordingly. | ||
* | ||
* @see engine.model.History | ||
* @memberOf engine.model | ||
*/ | ||
export default class CompressedHistory extends History { | ||
constructor() { | ||
super(); | ||
|
||
/** | ||
* Stores base versions of deltas which has been marked as inactive. | ||
* | ||
* @private | ||
* @member {Array.<Number>} engine.model.CompressedHistory#_inactiveBaseVersions | ||
*/ | ||
this._inactiveBaseVersions = []; | ||
} | ||
|
||
/** | ||
* Returns one or more deltas from compressed history that bases on given `baseVersion`. Most often it will be just | ||
* one delta, but if that delta got updated by multiple deltas, all of those updated deltas will be returned. | ||
* | ||
* @see engine.model.CompressedHistory#updateDelta | ||
* @param {Number} baseVersion Base version of the delta to retrieve. | ||
* @returns {Array.<engine.model.delta.Delta>|null} Delta with given base version or null if no such delta is in history. | ||
*/ | ||
getDelta( baseVersion ) { | ||
let index = this._historyPoints.get( baseVersion ); | ||
|
||
if ( index === undefined ) { | ||
return null; | ||
} | ||
|
||
const deltas = []; | ||
|
||
for ( index; index < this._deltas.length; index++ ) { | ||
const delta = this._deltas[ index ]; | ||
|
||
if ( delta.baseVersion != baseVersion ) { | ||
break; | ||
} | ||
|
||
deltas.push( delta ); | ||
} | ||
|
||
return deltas.length === 0 ? null : deltas; | ||
} | ||
|
||
/** | ||
* Removes delta from the history. This happens i.e., when a delta is undone by another delta. Both undone delta and | ||
* undoing delta should be removed so they won't have an impact on transforming other deltas. | ||
* | ||
* **Note:** using this method does not change the state of {@link engine.model.Document model}. It just affects | ||
* the state of `CompressedHistory`. | ||
* | ||
* **Note:** when some deltas are removed, deltas between them should probably get updated. See | ||
* {@link engine.model.CompressedHistory#updateDelta}. | ||
* | ||
* **Note:** if delta with `baseVersion` got {@link engine.model.CompressedHistory#updateDelta updated} by multiple | ||
* deltas, all updated deltas will be removed. | ||
* | ||
* @param {Number} baseVersion Base version of a delta to be removed. | ||
*/ | ||
removeDelta( baseVersion ) { | ||
this.updateDelta( baseVersion, [] ); | ||
this._inactiveBaseVersions.push( baseVersion ); | ||
} | ||
|
||
/** | ||
* Substitutes delta from compressed history by one or more given deltas. | ||
* | ||
* **Note:** if delta with `baseVersion` was already updated by multiple deltas, all updated deltas will be removed | ||
* and new deltas will be inserted at their position. | ||
* | ||
* **Note:** delta marked as reversed won't get updated. | ||
* | ||
* @param {Number} baseVersion Base version of a delta to update. | ||
* @param {Iterable.<engine.model.delta.Delta>} updatedDeltas Deltas to be inserted in place of updated delta. | ||
*/ | ||
updateDelta( baseVersion, updatedDeltas ) { | ||
if ( this._inactiveBaseVersions.indexOf( baseVersion ) != -1 ) { | ||
return; | ||
} | ||
|
||
const deltas = this.getDelta( baseVersion ); | ||
|
||
// If there are no deltas, stop executing function as there is nothing to mark. | ||
if ( deltas === null ) { | ||
return; | ||
} | ||
|
||
// Make sure that every updated delta has correct `baseVersion`. | ||
// This is crucial for algorithms in `CompressedHistory` and algorithms using `CompressedHistory`. | ||
for ( let delta of updatedDeltas ) { | ||
delta.baseVersion = baseVersion; | ||
} | ||
|
||
// Put updated deltas in place of old deltas. | ||
this._deltas.splice( this._getIndex( baseVersion ), deltas.length, ...updatedDeltas ); | ||
|
||
// Update history points. | ||
this._updateHistoryPointsAfter( baseVersion, updatedDeltas.length - deltas.length ); | ||
} | ||
|
||
/** | ||
* Returns base versions of deltas which has been marked as reversed, in given base versions range. | ||
* | ||
* @param {Number} [from=0] Start of base versions range to check. | ||
* @param {Number} [to=Number.POSITIVE_INFINITY] End of base versions range to check. | ||
* @returns {Iterator.<Number>} Base versions of deltas marked as reversed. | ||
*/ | ||
*getInactiveBaseVersions( from = 0, to = Number.POSITIVE_INFINITY ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something not bangla here. |
||
for ( let baseVersion of this._inactiveBaseVersions ) { | ||
if ( baseVersion >= from && baseVersion < to ) { | ||
yield baseVersion; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Updates {@link engine.model.History#_historyPoints} structure. | ||
* | ||
* @private | ||
* @param {Number} baseVersion Base version of delta after which history points should be updated. | ||
* @param {Number} changeBy By how much change history points. Can be a negative value. | ||
*/ | ||
_updateHistoryPointsAfter( baseVersion, changeBy ) { | ||
for ( let key of this._historyPoints.keys() ) { | ||
if ( key > baseVersion ) { | ||
this._historyPoints.set( key, this._historyPoints.get( key ) + changeBy ); | ||
} | ||
} | ||
} | ||
} |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ import transformations from './delta/basic-transformations.js'; // jshint ignore | |
|
||
import RootElement from './rootelement.js'; | ||
import Batch from './batch.js'; | ||
import History from './history.js'; | ||
import CompressedHistory from './compressedhistory.js'; | ||
import Selection from './selection.js'; | ||
import EmitterMixin from '../../utils/emittermixin.js'; | ||
import CKEditorError from '../../utils/ckeditorerror.js'; | ||
|
@@ -108,10 +108,13 @@ export default class Document { | |
/** | ||
* Document's history. | ||
* | ||
* This is a compressed document history. It means that stored deltas might be removed or different | ||
* than originally applied deltas. | ||
* | ||
* @readonly | ||
* @member {engine.model.History} engine.model.Document#history | ||
* @member {engine.model.CompressedHistory} engine.model.Document#history | ||
*/ | ||
this.history = new History(); | ||
this.history = new CompressedHistory( this ); | ||
} | ||
|
||
/** | ||
|
@@ -159,7 +162,10 @@ export default class Document { | |
|
||
this.version++; | ||
|
||
this.history.addOperation( operation ); | ||
if ( operation.delta ) { | ||
// Right now I can't imagine operations without deltas, but let's be safe. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can hide an error this way. Silent exit is never a good solution. If you want to be save throw error. |
||
this.history.addDelta( operation.delta ); | ||
} | ||
|
||
const batch = operation.delta && operation.delta.batch; | ||
|
||
|
@@ -172,10 +178,11 @@ export default class Document { | |
/** | ||
* Creates a {@link engine.model.Batch} instance which allows to change the document. | ||
* | ||
* @param {String} [type] Batch type. See {@link engine.model.Batch#type}. | ||
* @returns {engine.model.Batch} Batch instance. | ||
*/ | ||
batch() { | ||
return new Batch( this ); | ||
batch( type ) { | ||
return new Batch( this, type ); | ||
} | ||
|
||
/** | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CompressedHistory
has nothing to do with compression. Also I do not see any reason to keepCompressedHistory
andHistory
separated.