Browse Source

Changed DataController to use model.change.

Oskar Wróbel 8 years ago
parent
commit
c8d6799cb6

+ 1 - 1
packages/ckeditor5-engine/src/controller/datacontroller.js

@@ -290,7 +290,7 @@ export default class DataController {
 	 * @returns {module:engine/model/documentfragment~DocumentFragment} Document fragment holding the clone of the selected content.
 	 */
 	getSelectedContent( selection ) {
-		return getSelectedContent( selection );
+		return getSelectedContent( this, selection );
 	}
 
 	/**

+ 79 - 76
packages/ckeditor5-engine/src/controller/getselectedcontent.js

@@ -21,90 +21,93 @@ import Position from '../model/position';
  *
  *		<quote><h>st</h></quote><p>se</p>
  *
+ * @param {module:engine/controller/datacontroller~DataController} dataController The data controller in context of which
+ * the selection modification should be performed.
  * @param {module:engine/model/selection~Selection} selection The selection of which content will be returned.
- * @param {module:engine/model/batch~Batch} batch Batch to which deltas will be added.
  * @returns {module:engine/model/documentfragment~DocumentFragment}
  */
-export default function getSelectedContent( selection, batch ) {
-	const frag = batch.createDocumentFragment();
-	const range = selection.getFirstRange();
+export default function getSelectedContent( dataController, selection ) {
+	return dataController.model.change( writer => {
+		const frag = writer.createDocumentFragment();
+		const range = selection.getFirstRange();
 
-	if ( !range || range.isCollapsed ) {
-		return frag;
-	}
-
-	const root = range.start.root;
-	const commonPath = range.start.getCommonPath( range.end );
-	const commonParent = root.getNodeByPath( commonPath );
-
-	// ## 1st step
-	//
-	// First, we'll clone a fragment represented by a minimal flat range
-	// containing the original range to be cloned.
-	// E.g. let's consider such a range:
-	//
-	// <p>x</p><quote><p>y</p><h>fir[st</h></quote><p>se]cond</p><p>z</p>
-	//
-	// A minimal flat range containing this one is:
-	//
-	// <p>x</p>[<quote><p>y</p><h>first</h></quote><p>second</p>]<p>z</p>
-	//
-	// We can easily clone this structure, preserving e.g. the <quote> element.
-	let flatSubtreeRange;
-
-	if ( range.start.parent == range.end.parent ) {
-		// The original range is flat, so take it.
-		flatSubtreeRange = range;
-	} else {
-		flatSubtreeRange = Range.createFromParentsAndOffsets(
-			commonParent, range.start.path[ commonPath.length ],
-			commonParent, range.end.path[ commonPath.length ] + 1
-		);
-	}
-
-	const howMany = flatSubtreeRange.end.offset - flatSubtreeRange.start.offset;
-
-	// Clone the whole contents.
-	for ( const item of flatSubtreeRange.getItems( { shallow: true } ) ) {
-		if ( item.is( 'textProxy' ) ) {
-			batch.appendText( item.data, item.getAttributes(), frag );
+		if ( !range || range.isCollapsed ) {
+			return frag;
+		}
+
+		const root = range.start.root;
+		const commonPath = range.start.getCommonPath( range.end );
+		const commonParent = root.getNodeByPath( commonPath );
+
+		// ## 1st step
+		//
+		// First, we'll clone a fragment represented by a minimal flat range
+		// containing the original range to be cloned.
+		// E.g. let's consider such a range:
+		//
+		// <p>x</p><quote><p>y</p><h>fir[st</h></quote><p>se]cond</p><p>z</p>
+		//
+		// A minimal flat range containing this one is:
+		//
+		// <p>x</p>[<quote><p>y</p><h>first</h></quote><p>second</p>]<p>z</p>
+		//
+		// We can easily clone this structure, preserving e.g. the <quote> element.
+		let flatSubtreeRange;
+
+		if ( range.start.parent == range.end.parent ) {
+			// The original range is flat, so take it.
+			flatSubtreeRange = range;
 		} else {
-			batch.append( item.clone( true ), frag );
+			flatSubtreeRange = Range.createFromParentsAndOffsets(
+				commonParent, range.start.path[ commonPath.length ],
+				commonParent, range.end.path[ commonPath.length ] + 1
+			);
 		}
-	}
-
-	// ## 2nd step
-	//
-	// If the original range wasn't flat, then we need to remove the excess nodes from the both ends of the cloned fragment.
-	//
-	// For example, for the range shown in the 1st step comment, we need to remove these pieces:
-	//
-	// <quote>[<p>y</p>]<h>[fir]st</h></quote><p>se[cond]</p>
-	//
-	// So this will be the final copied content:
-	//
-	// <quote><h>st</h></quote><p>se</p>
-	//
-	// In order to do that, we remove content from these two ranges:
-	//
-	// [<quote><p>y</p><h>fir]st</h></quote><p>se[cond</p>]
-	if ( flatSubtreeRange != range ) {
-		// Find the position of the original range in the cloned fragment.
-		const newRange = range._getTransformedByMove( flatSubtreeRange.start, Position.createAt( frag, 0 ), howMany )[ 0 ];
-
-		const leftExcessRange = new Range( Position.createAt( frag ), newRange.start );
-		const rightExcessRange = new Range( newRange.end, Position.createAt( frag, 'end' ) );
-
-		removeRangeContent( rightExcessRange, batch );
-		removeRangeContent( leftExcessRange, batch );
-	}
-
-	return frag;
+
+		const howMany = flatSubtreeRange.end.offset - flatSubtreeRange.start.offset;
+
+		// Clone the whole contents.
+		for ( const item of flatSubtreeRange.getItems( { shallow: true } ) ) {
+			if ( item.is( 'textProxy' ) ) {
+				writer.appendText( item.data, item.getAttributes(), frag );
+			} else {
+				writer.append( item.clone( true ), frag );
+			}
+		}
+
+		// ## 2nd step
+		//
+		// If the original range wasn't flat, then we need to remove the excess nodes from the both ends of the cloned fragment.
+		//
+		// For example, for the range shown in the 1st step comment, we need to remove these pieces:
+		//
+		// <quote>[<p>y</p>]<h>[fir]st</h></quote><p>se[cond]</p>
+		//
+		// So this will be the final copied content:
+		//
+		// <quote><h>st</h></quote><p>se</p>
+		//
+		// In order to do that, we remove content from these two ranges:
+		//
+		// [<quote><p>y</p><h>fir]st</h></quote><p>se[cond</p>]
+		if ( flatSubtreeRange != range ) {
+			// Find the position of the original range in the cloned fragment.
+			const newRange = range._getTransformedByMove( flatSubtreeRange.start, Position.createAt( frag, 0 ), howMany )[ 0 ];
+
+			const leftExcessRange = new Range( Position.createAt( frag ), newRange.start );
+			const rightExcessRange = new Range( newRange.end, Position.createAt( frag, 'end' ) );
+
+			removeRangeContent( rightExcessRange, writer );
+			removeRangeContent( leftExcessRange, writer );
+		}
+
+		return frag;
+	} );
 }
 
 // After https://github.com/ckeditor/ckeditor5-engine/issues/690 is fixed,
 // this function will, most likely, be able to rewritten using getMinimalFlatRanges().
-function removeRangeContent( range, batch ) {
+function removeRangeContent( range, writer ) {
 	const parentsToCheck = [];
 
 	Array.from( range.getItems( { direction: 'backward' } ) )
@@ -126,7 +129,7 @@ function removeRangeContent( range, batch ) {
 		.forEach( itemRange => {
 			parentsToCheck.push( itemRange.start.parent );
 
-			batch.remove( itemRange );
+			writer.remove( itemRange );
 		} );
 
 	// Remove ancestors of the removed items if they turned to be empty now
@@ -139,7 +142,7 @@ function removeRangeContent( range, batch ) {
 
 			parent = parent.parent;
 
-			batch.remove( removeRange );
+			writer.remove( removeRange );
 		}
 	} );
 }

+ 49 - 53
packages/ckeditor5-engine/src/controller/insertcontent.js

@@ -26,51 +26,47 @@ import log from '@ckeditor/ckeditor5-utils/src/log';
  * should be performed.
  * @param {module:engine/model/documentfragment~DocumentFragment|module:engine/model/item~Item} content The content to insert.
  * @param {module:engine/model/selection~Selection} selection Selection into which the content should be inserted.
- * @param {module:engine/model/batch~Batch} [batch] Batch to which deltas will be added. If not specified, then
- * changes will be added to a new batch.
  */
-export default function insertContent( dataController, content, selection, batch ) {
-	if ( !batch ) {
-		batch = dataController.model.batch();
-	}
-
-	if ( !selection.isCollapsed ) {
-		dataController.deleteContent( selection, batch );
-	}
+export default function insertContent( dataController, content, selection ) {
+	dataController.model.change( writer => {
+		if ( !selection.isCollapsed ) {
+			dataController.deleteContent( selection );
+		}
 
-	const insertion = new Insertion( dataController, batch, selection.anchor );
+		const insertion = new Insertion( dataController, writer, selection.anchor );
 
-	let nodesToInsert;
+		let nodesToInsert;
 
-	if ( content.is( 'documentFragment' ) ) {
-		nodesToInsert = content.getChildren();
-	} else {
-		nodesToInsert = [ content ];
-	}
-
-	insertion.handleNodes( nodesToInsert, {
-		// The set of children being inserted is the only set in this context
-		// so it's the first and last (it's a hack ;)).
-		isFirst: true,
-		isLast: true
-	} );
+		if ( content.is( 'documentFragment' ) ) {
+			nodesToInsert = content.getChildren();
+		} else {
+			nodesToInsert = [ content ];
+		}
 
-	const newRange = insertion.getSelectionRange();
+		insertion.handleNodes( nodesToInsert, {
+			// The set of children being inserted is the only set in this context
+			// so it's the first and last (it's a hack ;)).
+			isFirst: true,
+			isLast: true
+		} );
 
-	/* istanbul ignore else */
-	if ( newRange ) {
-		selection.setRanges( [ newRange ] );
-	} else {
-		// We are not testing else because it's a safe check for unpredictable edge cases:
-		// an insertion without proper range to select.
+		const newRange = insertion.getSelectionRange();
 
-		/**
-		 * Cannot determine a proper selection range after insertion.
-		 *
-		 * @warning insertcontent-no-range
-		 */
-		log.warn( 'insertcontent-no-range: Cannot determine a proper selection range after insertion.' );
-	}
+		/* istanbul ignore else */
+		if ( newRange ) {
+			selection.setRanges( [ newRange ] );
+		} else {
+			// We are not testing else because it's a safe check for unpredictable edge cases:
+			// an insertion without proper range to select.
+
+			/**
+			 * Cannot determine a proper selection range after insertion.
+			 *
+			 * @warning insertcontent-no-range
+			 */
+			log.warn( 'insertcontent-no-range: Cannot determine a proper selection range after insertion.' );
+		}
+	} );
 }
 
 /**
@@ -79,7 +75,7 @@ export default function insertContent( dataController, content, selection, batch
  * @private
  */
 class Insertion {
-	constructor( dataController, batch, position ) {
+	constructor( dataController, writer, position ) {
 		/**
 		 * The data controller in context of which the insertion should be performed.
 		 *
@@ -90,9 +86,9 @@ class Insertion {
 		/**
 		 * Batch to which deltas will be added.
 		 *
-		 * @member {module:engine/controller/batch~Batch} #batch
+		 * @member {module:engine/controller/writer~Batch} #writer
 		 */
-		this.batch = batch;
+		this.writer = writer;
 
 		/**
 		 * The position at which (or near which) the next node will be inserted.
@@ -153,7 +149,7 @@ class Insertion {
 			return Range.createOn( this.nodeToSelect );
 		}
 
-		return this.dataController.model.getNearestSelectionRange( this.position );
+		return this.dataController.model.document.getNearestSelectionRange( this.position );
 	}
 
 	/**
@@ -229,7 +225,7 @@ class Insertion {
 		// If the node is a text and bare text is allowed in current position it means that the node
 		// contains disallowed attributes and we have to remove them.
 		else if ( this.schema.check( { name: '$text', inside: this.position } ) ) {
-			this.schema.removeDisallowedAttributes( [ node ], this.position, this.batch );
+			this.schema.removeDisallowedAttributes( [ node ], this.position, this.writer );
 			this._handleNode( node, context );
 		}
 		// If text is not allowed, try autoparagraphing.
@@ -256,7 +252,7 @@ class Insertion {
 
 		const livePos = LivePosition.createFromPosition( this.position );
 
-		this.batch.insert( node, this.position );
+		this.writer.insert( node, this.position );
 
 		this.position = Position.createFromPosition( livePos );
 		livePos.detach();
@@ -286,12 +282,12 @@ class Insertion {
 		if ( mergeLeft ) {
 			const position = LivePosition.createFromPosition( this.position );
 
-			this.batch.merge( mergePosLeft );
+			this.writer.merge( mergePosLeft );
 
 			// We need to check and strip disallowed attributes in all nested nodes because after merge
 			// some attributes could end up in a path where are disallowed.
 			const parent = position.nodeBefore;
-			this.schema.removeDisallowedAttributes( parent.getChildren(), Position.createAt( parent ), this.batch );
+			this.schema.removeDisallowedAttributes( parent.getChildren(), Position.createAt( parent ), this.writer );
 
 			this.position = Position.createFromPosition( position );
 			position.detach();
@@ -314,11 +310,11 @@ class Insertion {
 			// NOK: <p>xx[]</p> + <p>yy</p> => <p>xxyy[]</p> (when sticks to next)
 			const position = new LivePosition( this.position.root, this.position.path, 'sticksToPrevious' );
 
-			this.batch.merge( mergePosRight );
+			this.writer.merge( mergePosRight );
 
 			// We need to check and strip disallowed attributes in all nested nodes because after merge
 			// some attributes could end up in a place where are disallowed.
-			this.schema.removeDisallowedAttributes( position.parent.getChildren(), position, this.batch );
+			this.schema.removeDisallowedAttributes( position.parent.getChildren(), position, this.writer );
 
 			this.position = Position.createFromPosition( position );
 			position.detach();
@@ -330,7 +326,7 @@ class Insertion {
 		// When there was no merge we need to check and strip disallowed attributes in all nested nodes of
 		// just inserted node because some attributes could end up in a place where are disallowed.
 		if ( !mergeLeft && !mergeRight ) {
-			this.schema.removeDisallowedAttributes( node.getChildren(), Position.createAt( node ), this.batch );
+			this.schema.removeDisallowedAttributes( node.getChildren(), Position.createAt( node ), this.writer );
 		}
 	}
 
@@ -341,7 +337,7 @@ class Insertion {
 	 * @param {Object} context
 	 */
 	_tryAutoparagraphing( node, context ) {
-		const paragraph = this.batch.createElement( 'paragraph' );
+		const paragraph = this.writer.createElement( 'paragraph' );
 
 		// Do not autoparagraph if the paragraph won't be allowed there,
 		// cause that would lead to an infinite loop. The paragraph would be rejected in
@@ -350,7 +346,7 @@ class Insertion {
 			// When node is a text and is disallowed by schema it means that contains disallowed attributes
 			// and we need to remove them.
 			if ( node.is( 'text' ) && !this._checkIsAllowed( node, [ paragraph ] ) ) {
-				this.schema.removeDisallowedAttributes( [ node ], [ paragraph ], this.batch );
+				this.schema.removeDisallowedAttributes( [ node ], [ paragraph ], this.writer );
 			}
 
 			if ( this._checkIsAllowed( node, [ paragraph ] ) ) {
@@ -385,14 +381,14 @@ class Insertion {
 				// Special case – parent is empty (<p>^</p>) so isAtStart == isAtEnd == true.
 				// We can remove the element after moving selection out of it.
 				if ( parent.isEmpty ) {
-					this.batch.remove( parent );
+					this.writer.remove( parent );
 				}
 			} else if ( this.position.isAtEnd ) {
 				this.position = Position.createAfter( this.position.parent );
 			} else {
 				const tempPos = Position.createAfter( this.position.parent );
 
-				this.batch.split( this.position );
+				this.writer.split( this.position );
 
 				this.position = tempPos;