浏览代码

Added: introduced markers conversion in conversion.EditingController.

Szymon Cofalik 9 年之前
父节点
当前提交
3e289652a7

+ 37 - 0
packages/ckeditor5-engine/src/controller/editingcontroller.js

@@ -8,6 +8,7 @@
  */
 
 import ViewDocument from '../view/document.js';
+import ModelRange from '../model/range.js';
 import Mapper from '../conversion/mapper.js';
 import ModelConversionDispatcher from '../conversion/modelconversiondispatcher.js';
 import { insertText, remove, move, rename } from '../conversion/model-to-view-converters.js';
@@ -97,6 +98,15 @@ export default class EditingController {
 			this.view.render();
 		}, { priority: 'low' } );
 
+		// Convert model markers changes.
+		this._listener.listenTo( this.model.markers, 'addMarker', ( evt, name, range ) => {
+			this.modelToView.convertMarker( 'addMarker', name, range );
+		} );
+
+		this._listener.listenTo( this.model.markers, 'removeMarker', ( evt, name, range ) => {
+			this.modelToView.convertMarker( 'removeMarker', name, range );
+		} );
+
 		// Convert view selection to model.
 		this._listener.listenTo( this.view, 'selectionChange', convertSelectionChange( model, this.mapper ) );
 
@@ -106,6 +116,33 @@ export default class EditingController {
 		this.modelToView.on( 'move', move(), { priority: 'low' } );
 		this.modelToView.on( 'rename', rename(), { priority: 'low' } );
 
+		// Attach markers converters.
+		this.modelToView.on( 'insert', ( evt, data ) => {
+			const pos = data.range.start;
+
+			for ( let [ range, name ] of this.model.markers._markerNames ) {
+				if ( range.containsPosition( pos ) || range.start.isEqual( pos ) ) {
+					this.modelToView.convertMarker( 'addMarker', name, data.range );
+				}
+			}
+		}, { priority: 'lowest' } );
+
+		this.modelToView.on( 'move', ( evt, data ) => {
+			const pos = data.sourcePosition._getTransformedByInsertion( data.targetPosition, data.item.offsetSize );
+
+			for ( let [ range, name ] of this.model.markers._markerNames ) {
+				if ( range.start.isEqual( pos ) || range.end.isEqual( pos ) ) {
+					const movedRange = ModelRange.createOn( data.item );
+
+					if ( range.containsPosition( data.targetPosition ) ) {
+						this.modelToView.convertMarker( 'addMarker', name, movedRange );
+					} else {
+						this.modelToView.convertMarker( 'removeMarker', name, movedRange );
+					}
+				}
+			}
+		}, { priority: 'lowest' } );
+
 		// Attach default selection converters.
 		this.modelToView.on( 'selection', clearAttributes(), { priority: 'low' } );
 		this.modelToView.on( 'selection', clearFakeSelection(), { priority: 'low' } );

+ 78 - 0
packages/ckeditor5-engine/tests/controller/editingcontroller.js

@@ -18,6 +18,7 @@ import buildModelConverter from 'ckeditor5/engine/conversion/buildmodelconverter
 import ModelDocument from 'ckeditor5/engine/model/document.js';
 import ModelPosition from 'ckeditor5/engine/model/position.js';
 import ModelRange from 'ckeditor5/engine/model/range.js';
+import ModelLiveRange from 'ckeditor5/engine/model/liverange.js';
 import ModelDocumentFragment from 'ckeditor5/engine/model/documentfragment.js';
 
 import createElement from 'ckeditor5/utils/dom/createelement.js';
@@ -252,6 +253,83 @@ describe( 'EditingController', () => {
 
 			expect( getViewData( editing.view ) ).to.equal( '<p>foo</p><p></p><p>ba{}r</p>' );
 		} );
+
+		it( 'should forward marker events to model conversion dispatcher', () => {
+			const range = ModelRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 1 );
+
+			sinon.spy( editing.modelToView, 'convertMarker' );
+
+			model.markers.fire( 'addMarker', range, 'name' );
+
+			expect( editing.modelToView.convertMarker.calledWithExactly( 'addMarker', range, 'name' ) ).to.be.true;
+
+			model.markers.fire( 'removeMarker', range, 'name' );
+
+			expect( editing.modelToView.convertMarker.calledWithExactly( 'removeMarker', range, 'name' ) ).to.be.true;
+
+			editing.modelToView.convertMarker.restore();
+		} );
+
+		it( 'should forward add marker event if content is inserted into a marker range', () => {
+			const markerRange = ModelLiveRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 3 );
+			const innerRange = ModelRange.createFromParentsAndOffsets( modelRoot, 1, modelRoot, 2 );
+
+			model.markers.addRange( markerRange, 'name' );
+
+			sinon.spy( editing.modelToView, 'convertMarker' );
+
+			editing.modelToView.fire( 'insert', {
+				range: innerRange
+			} );
+
+			expect( editing.modelToView.convertMarker.calledWithExactly( 'addMarker', 'name', innerRange ) ).to.be.true;
+
+			editing.modelToView.convertMarker.restore();
+		} );
+
+		it( 'should forward remove marker event if part of marker range is moved', () => {
+			const markerRange = ModelLiveRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 1 );
+			const consumableMock = {
+				consume: () => true,
+				test: () => true
+			};
+
+			model.markers.addRange( markerRange, 'name' );
+
+			sinon.spy( editing.modelToView, 'convertMarker' );
+
+			editing.modelToView.fire( 'move', {
+				sourcePosition: ModelPosition.createAt( modelRoot, 1 ),
+				targetPosition: ModelPosition.createAt( modelRoot, 2 ),
+				item: modelRoot.getChild( 2 )
+			}, consumableMock, { mapper: editing.mapper } );
+
+			expect( editing.modelToView.convertMarker.calledWith( 'removeMarker', 'name' ) ).to.be.true;
+
+			editing.modelToView.convertMarker.restore();
+		} );
+
+		it( 'should forward add marker event if content is moved into a marker range', () => {
+			const markerRange = ModelLiveRange.createFromParentsAndOffsets( modelRoot, 0, modelRoot, 3 );
+			const consumableMock = {
+				consume: () => true,
+				test: () => true
+			};
+
+			model.markers.addRange( markerRange, 'name' );
+
+			sinon.spy( editing.modelToView, 'convertMarker' );
+
+			editing.modelToView.fire( 'move', {
+				sourcePosition: ModelPosition.createAt( modelRoot, 2 ),
+				targetPosition: ModelPosition.createAt( modelRoot, 1 ),
+				item: modelRoot.getChild( 1 )
+			}, consumableMock, { mapper: editing.mapper } );
+
+			expect( editing.modelToView.convertMarker.calledWith( 'addMarker', 'name' ) ).to.be.true;
+
+			editing.modelToView.convertMarker.restore();
+		} );
 	} );
 
 	describe( 'destroy', () => {