Răsfoiți Sursa

Changed: LiveRange uses Range#getTransformedByMove instead of LivePositions now.

Szymon Cofalik 9 ani în urmă
părinte
comite
4e8a970996

+ 38 - 26
packages/ckeditor5-engine/src/treemodel/liverange.js

@@ -6,17 +6,14 @@
 'use strict';
 
 import Range from './range.js';
-import LivePosition from './liveposition.js';
 import EmitterMixin from '../../utils/emittermixin.js';
 import utils from '../../utils/utils.js';
 
 /**
  * LiveRange is a Range in the Tree Model that updates itself as the tree changes. It may be used as a bookmark.
  *
- * **Note:** Constructor creates it's own {@link engine.treeModel.LivePosition} instances basing on passed values.
- *
- * **Note:** Be very careful when dealing with LiveRange. Each LiveRange instance bind events that might
- * have to be unbound. Use {@link engine.treeModel.LiveRange#detach detach} whenever you don't need LiveRange anymore.
+ * **Note:** Be very careful when dealing with `LiveRange`. Each `LiveRange` instance bind events that might
+ * have to be unbound. Use {@link engine.treeModel.LiveRange#detach detach} whenever you don't need `LiveRange` anymore.
  *
  * @memberOf engine.treeModel
  */
@@ -29,9 +26,6 @@ export default class LiveRange extends Range {
 	constructor( start, end ) {
 		super( start, end );
 
-		this.start = new LivePosition( this.start.root, this.start.path.slice(), 'STICKS_TO_NEXT' );
-		this.end = new LivePosition( this.end.root, this.end.path.slice(), 'STICKS_TO_PREVIOUS' );
-
 		bindWithDocument.call( this );
 	}
 
@@ -41,8 +35,6 @@ export default class LiveRange extends Range {
 	 * referring to it).
 	 */
 	detach() {
-		this.start.detach();
-		this.end.detach();
 		this.stopListening();
 	}
 
@@ -117,23 +109,43 @@ function bindWithDocument() {
  */
 function fixBoundaries( type, range, position ) {
 	/* jshint validthis: true */
+	let updated;
+	const howMany = range.end.offset - range.start.offset;
+
+	switch ( type ) {
+		case 'insert':
+			updated = this.getTransformedByInsertion( range.start, howMany )[ 0 ];
+			break;
+
+		case 'move':
+		case 'remove':
+		case 'reinsert':
+			const result = this.getTransformedByMove( position, range.start, howMany );
+
+			// First item in the array is the "difference" part, so a part of the range
+			// that did not get moved. We use it as reference range and expand if possible.
+			updated = result[ 0 ];
+
+			// We will check if there is other range and if it is touching the reference range.
+			// If it does, we will expand the reference range (at the beginning or at the end).
+			// Keep in mind that without settings `spread` flag, `getTransformedByMove` may
+			// return maximum two ranges.
+			if ( result.length > 1 ) {
+				let otherRange = result[ 1 ];
+
+				if ( updated.start.isTouching( otherRange.end ) ) {
+					updated.start = otherRange.start;
+				} else if ( updated.end.isTouching( otherRange.start ) ) {
+					updated.end = otherRange.end;
+				}
+			}
+
+			break;
+	}
 
-	if ( type == 'move' || type == 'remove' || type == 'reinsert' ) {
-		let containsStart = range.containsPosition( this.start ) || range.start.isEqual( this.start );
-		let containsEnd = range.containsPosition( this.end ) || range.end.isEqual( this.end );
-		position = position.getTransformedByInsertion( range.start, range.end.offset - range.start.offset, true );
-
-		// If the range contains both start and end, don't do anything - LivePositions that are boundaries of
-		// this LiveRange are in correct places, they got correctly transformed.
-		if ( containsStart && !containsEnd && !range.end.isTouching( position ) ) {
-			this.start.path = position.path.slice();
-			this.start.root = position.root;
-		}
-
-		if ( containsEnd && !containsStart && !range.start.isTouching( position ) ) {
-			this.end.path = position.path.slice();
-			this.end.root = position.root;
-		}
+	if ( updated ) {
+		this.start = updated.start;
+		this.end = updated.end;
 	}
 }
 

+ 34 - 11
packages/ckeditor5-engine/tests/treemodel/liverange.js

@@ -159,7 +159,7 @@ describe( 'LiveRange', () => {
 			} );
 
 			it( 'is to the same parent as range end and before it', () => {
-				let moveSource = new Position( root, [ 2 ] );
+				let moveSource = new Position( root, [ 3 ] );
 				let moveRange = new Range( new Position( root, [ 0, 2, 0 ] ), new Position( root, [ 0, 2, 4 ] ) );
 
 				let changes = {
@@ -331,6 +331,38 @@ describe( 'LiveRange', () => {
 				expect( live.start.path ).to.deep.equal( [ 0, 3, 1 ] );
 				expect( live.end.path ).to.deep.equal( [ 0, 3, 4 ] );
 			} );
+
+			it( 'is inside live range and points to live range', () => {
+				live.end.path = [ 0, 1, 12 ];
+
+				let moveSource = new Position( root, [ 0, 1, 6 ] );
+				let moveRange = new Range( new Position( root, [ 0, 1, 8 ] ), new Position( root, [ 0, 1, 10 ] ) );
+
+				let changes = {
+					range: moveRange,
+					sourcePosition: moveSource
+				};
+				doc.fire( 'change', 'move', changes, null );
+
+				expect( live.start.path ).to.deep.equal( [ 0, 1, 4 ] );
+				expect( live.end.path ).to.deep.equal( [ 0, 1, 12 ] );
+			} );
+
+			it( 'is intersecting with live range and points to live range', () => {
+				live.end.path = [ 0, 1, 12 ];
+
+				let moveSource = new Position( root, [ 0, 1, 2 ] );
+				let moveRange = new Range( new Position( root, [ 0, 1, 5 ] ), new Position( root, [ 0, 1, 9 ] ) );
+
+				let changes = {
+					range: moveRange,
+					sourcePosition: moveSource
+				};
+				doc.fire( 'change', 'move', changes, null );
+
+				expect( live.start.path ).to.deep.equal( [ 0, 1, 2 ] );
+				expect( live.end.path ).to.deep.equal( [ 0, 1, 12 ] );
+			} );
 		} );
 	} );
 
@@ -353,9 +385,6 @@ describe( 'LiveRange', () => {
 		} );
 
 		describe( 'insertion', () => {
-			// Technically range will be expanded but the boundaries properties will stay the same.
-			// Start won't change because insertion is after it.
-			// End won't change because it is in different node.
 			it( 'is in the same parent as range start and after it', () => {
 				let insertRange = new Range( new Position( root, [ 0, 1, 7 ] ), new Position( root, [ 0, 1, 9 ] ) );
 
@@ -390,9 +419,6 @@ describe( 'LiveRange', () => {
 		} );
 
 		describe( 'range move', () => {
-			// Technically range will be expanded but the boundaries properties will stay the same.
-			// Start won't change because insertion is after it.
-			// End won't change because it is in different node.
 			it( 'is to the same parent as range start and after it', () => {
 				let moveSource = new Position( root, [ 4 ] );
 				let moveRange = new Range( new Position( root, [ 0, 1, 7 ] ), new Position( root, [ 0, 1, 9 ] ) );
@@ -406,7 +432,7 @@ describe( 'LiveRange', () => {
 				expect( live.isEqual( clone ) ).to.be.true;
 			} );
 
-			it( 'is to the same parent as range end and before it', () => {
+			it( 'is to the same parent as range end and after it', () => {
 				let moveSource = new Position( root, [ 4 ] );
 				let moveRange = new Range( new Position( root, [ 0, 2, 3 ] ), new Position( root, [ 0, 2, 5 ] ) );
 
@@ -432,9 +458,6 @@ describe( 'LiveRange', () => {
 				expect( live.isEqual( clone ) ).to.be.true;
 			} );
 
-			// Technically range will be shrunk but the boundaries properties will stay the same.
-			// Start won't change because deletion is after it.
-			// End won't change because it is in different node.
 			it( 'is from the same parent as range start and after it', () => {
 				let moveSource = new Position( root, [ 0, 1, 6 ] );
 				let moveRange = new Range( new Position( root, [ 4, 0 ] ), new Position( root, [ 4, 3 ] ) );