Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into t/629b
Browse files Browse the repository at this point in the history
  • Loading branch information
Reinmar committed Nov 16, 2016
2 parents bf87840 + 25383a0 commit 6a9306e
Show file tree
Hide file tree
Showing 13 changed files with 212 additions and 290 deletions.
79 changes: 68 additions & 11 deletions src/controller/datacontroller.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import ViewDocumentFragment from '../view/documentfragment.js';
import ModelRange from '../model/range.js';
import ModelPosition from '../model/position.js';

import insert from './insert.js';
import insertContent from './insertcontent.js';
import deleteContent from './deletecontent.js';
import modifySelection from './modifyselection.js';

/**
* Controller for the data pipeline. The data pipeline controls how data is retrieved from the document
Expand Down Expand Up @@ -111,7 +113,9 @@ export default class DataController {
this.viewToModel.on( 'element', convertToModelFragment(), { priority: 'lowest' } );
this.viewToModel.on( 'documentFragment', convertToModelFragment(), { priority: 'lowest' } );

this.on( 'insert', ( evt, data ) => insert( this, data.content, data.selection, data.batch ) );
this.on( 'insertContent', ( evt, data ) => insertContent( this, data.content, data.selection, data.batch ) );
this.on( 'deleteContent', ( evt, data ) => deleteContent( data.selection, data.batch, data.options ) );
this.on( 'modifySelection', ( evt, data ) => modifySelection( data.selection, data.options ) );
}

/**
Expand Down Expand Up @@ -214,30 +218,83 @@ export default class DataController {
destroy() {}

/**
* See {@link engine.controller.insert}.
* See {@link engine.controller.insertContent}.
*
* @fires engine.controller.DataController#insert
* @param {engine.view.DocumentFragment} content The content to insert.
* @fires engine.controller.DataController#insertContent
* @param {engine.model.DocumentFragment} content The content to insert.
* @param {engine.model.Selection} selection Selection into which the content should be inserted.
* @param {engine.model.Batch} [batch] Batch to which deltas will be added. If not specified, then
* changes will be added to a new batch.
*/
insert( content, selection, batch ) {
this.fire( 'insert', { content, selection, batch } );
insertContent( content, selection, batch ) {
this.fire( 'insertContent', { content, selection, batch } );
}

/**
* See {@link engine.controller.deleteContent}.
*
* Note: For the sake of predictability, the resulting selection should always be collapsed.
* In cases where a feature wants to modify deleting behavior so selection isn't collapsed
* (e.g. a table feature may want to keep row selection after pressing <kbd>Backspace</kbd>),
* then that behavior should be implemented in the view's listener. At the same time, the table feature
* will need to modify this method's behavior too, e.g. to "delete contents and then collapse
* the selection inside the last selected cell" or "delete the row and collapse selection somewhere near".
* That needs to be done in order to ensure that other features which use `deleteContent()` will work well with tables.
*
* @fires engine.controller.DataController#deleteContent
* @param {engine.model.Selection} selection Selection of which the content should be deleted.
* @param {engine.model.Batch} batch Batch to which deltas will be added.
* @param {Object} options See {@link engine.controller.deleteContent}'s options.
*/
deleteContent( selection, batch, options ) {
this.fire( 'deleteContent', { batch, selection, options } );
}

/**
* See {@link engine.controller.modifySelection}.
*
* @fires engine.controller.DataController#modifySelection
* @param {engine.model.Selection} The selection to modify.
* @param {Object} options See {@link engine.controller.modifySelection}'s options.
*/
modifySelection( selection, options ) {
this.fire( 'modifySelection', { selection, options } );
}
}

mix( DataController, EmitterMixin );

/**
* Event fired when {@link engine.controller.DataController#insert} method is called.
* The {@link engine.controller.dataController.insert default action of the composer} is implemented as a
* listener to that event so it can be fully customized by the features.
* Event fired when {@link engine.controller.DataController#insertContent} method is called.
* The {@link engine.controller.dataController.insertContent default action of that method} is implemented as a
* listener to this event so it can be fully customized by the features.
*
* @event engine.controller.DataController#insert
* @event engine.controller.DataController#insertContent
* @param {Object} data
* @param {engine.view.DocumentFragment} data.content The content to insert.
* @param {engine.model.Selection} data.selection Selection into which the content should be inserted.
* @param {engine.model.Batch} [data.batch] Batch to which deltas will be added.
*/

/**
* Event fired when {@link engine.controller.DataController#deleteContent} method is called.
* The {@link engine.controller.deleteContent default action of that method} is implemented as a
* listener to this event so it can be fully customized by the features.
*
* @event engine.controller.DataController#deleteContent
* @param {Object} data
* @param {engine.model.Batch} data.batch
* @param {engine.model.Selection} data.selection
* @param {Object} data.options See {@link engine.controller.deleteContent}'s options.
*/

/**
* Event fired when {@link engine.controller.DataController#modifySelection} method is called.
* The {@link engine.controller.modifySelection default action of that method} is implemented as a
* listener to this event so it can be fully customized by the features.
*
* @event engine.controller.DataController#modifySelection
* @param {Object} data
* @param {engine.model.Selection} data.selection
* @param {Object} data.options See {@link engine.controller.modifySelection}'s options.
*/
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
* For licensing, see LICENSE.md.
*/

import LivePosition from '../liveposition.js';
import Position from '../position.js';
import Element from '../element.js';
import compareArrays from '../../../utils/comparearrays.js';
import LivePosition from '../model/liveposition.js';
import Position from '../model/position.js';
import Element from '../model/element.js';
import compareArrays from '../../utils/comparearrays.js';

/**
* Delete contents of the selection and merge siblings. The resulting selection is always collapsed.
* Deletes content of the selection and merge siblings. The resulting selection is always collapsed.
*
* @method engine.model.composer.deleteContents
* @param {engine.model.Batch} batch Batch to which the deltas will be added.
* @method engine.controller.deleteContent
* @param {engine.model.Selection} selection Selection of which the content should be deleted.
* @param {engine.model.Batch} batch Batch to which the deltas will be added.
* @param {Object} [options]
* @param {Boolean} [options.merge=false] Merge elements after removing the contents of the selection.
* For example, `<h>x[x</h><p>y]y</p>` will become: `<h>x^y</h>` with the option enabled
* and: `<h>x^</h><p>y</p>` without it.
*/
export default function deleteContents( batch, selection, options = {} ) {
export default function deleteContent( selection, batch, options = {} ) {
if ( selection.isCollapsed ) {
return;
}
Expand Down
39 changes: 19 additions & 20 deletions src/controller/insert.js → src/controller/insertcontent.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,36 @@ import Element from '../model/element.js';
import Range from '../model/range.js';
import log from '../../utils/log.js';

// import { stringify as stringifyModel } from '../dev-utils/model.js';

/**
* Inserts content into the editor (specified selection) as one would expect the paste
* functionality to work.
*
* **Note:** Use {@link engine.controller.DataController#insert} instead of this function.
* This function is only exposed to be reusable in algorithms which change the {@link engine.controller.DataController#insert}
* **Note:** Use {@link engine.controller.DataController#insertContent} instead of this function.
* This function is only exposed to be reusable in algorithms which change the {@link engine.controller.DataController#insertContent}
* method's behavior.
*
* @method engine.controller.insert
* @method engine.controller.insertContent
* @param {engine.controller.DataController} dataController The data controller in context of which the insertion
* should be performed.
* @param {engine.view.DocumentFragment} content The content to insert.
* @param {engine.model.DocumentFragment} content The content to insert.
* @param {engine.model.Selection} selection Selection into which the content should be inserted.
* @param {engine.model.Batch} [batch] Batch to which deltas will be added. If not specified, then
* changes will be added to a new batch.
*/
export default function insert( dataController, content, selection, batch ) {
export default function insertContent( dataController, content, selection, batch ) {
if ( !batch ) {
batch = dataController.model.batch();
}

if ( !selection.isCollapsed ) {
dataController.model.composer.deleteContents( batch, selection, {
dataController.deleteContent( selection, batch, {
merge: true
} );
}

// Convert the pasted content to a model document fragment.
// Convertion is contextual, but in this case we need an "all allowed" context and for that
// we use the $clipboardHolder item.
const modelFragment = dataController.viewToModel.convert( content, {
context: [ '$clipboardHolder' ]
} );

// We'll be debugging this dozens of times still.
// console.log( stringifyModel( modelFragment ) );

const insertion = new Insertion( dataController, batch, selection.anchor );

insertion.handleNodes( modelFragment.getChildren(), {
insertion.handleNodes( content.getChildren(), {
// 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,
Expand All @@ -71,16 +59,22 @@ class Insertion {
constructor( dataController, batch, position ) {
/**
* The data controller in context of which the insertion should be performed.
*
* @member {engine.controller.DataController} #dataController
*/
this.dataController = dataController;

/**
* Batch to which deltas will be added.
*
* @member {engine.model.Batch} #batch
*/
this.batch = batch;

/**
* The position at which (or near which) the next node will be inserted.
*
* @member {engine.model.Position} #position
*/
this.position = position;

Expand All @@ -91,11 +85,16 @@ class Insertion {
* <p>x</p><p>^y</p> + <p>z</p> (can merge to <p>y</p>)
* <p>x^y</p> + <p>z</p> (can merge to <p>xy</p> which will be split during the action,
* so both its pieces will be added to this set)
*
*
* @member {Set} #canMergeWith
*/
this.canMergeWith = new Set( [ this.position.parent ] );

/**
* Schema of the model.
*
* @member {engine.model.Schema} #schema
*/
this.schema = dataController.model.schema;
}
Expand Down Expand Up @@ -152,7 +151,7 @@ class Insertion {
* @param {Boolean} context.isFirst Whether the given node is the first one in the content to be inserted.
* @param {Boolean} context.isLast Whether the given node is the last one in the content to be inserted.
*/
_handleNode( node, context = {} ) {
_handleNode( node, context ) {
// Let's handle object in a special way.
// * They should never be merged with other elements.
// * If they are not allowed in any of the selection ancestors, they could be either autoparagraphed or totally removed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
* For licensing, see LICENSE.md.
*/

import Position from '../position.js';
import TreeWalker from '../treewalker.js';
import Range from '../range.js';
import { isInsideSurrogatePair, isInsideCombinedSymbol } from '../../../utils/unicode.js';
import Position from '../model/position.js';
import TreeWalker from '../model/treewalker.js';
import Range from '../model/range.js';
import { isInsideSurrogatePair, isInsideCombinedSymbol } from '../../utils/unicode.js';

/**
* Modifies the selection. Currently the supported modifications are:
* Modifies the selection. Currently, the supported modifications are:
*
* * Extending. The selection focus is moved in the specified `options.direction` with a step specified in `options.unit`.
* Possible values for `unit` are:
Expand All @@ -29,7 +29,7 @@ import { isInsideSurrogatePair, isInsideCombinedSymbol } from '../../../utils/un
*
* **Note:** if you extend a forward selection in a backward direction you will in fact shrink it.
*
* @method engine.model.composer.modifySelection
* @method engine.controller.modifySelection
* @param {engine.model.Selection} selection The selection to modify.
* @param {Object} [options]
* @param {'forward'|'backward'} [options.direction='forward'] The direction in which the selection should be modified.
Expand Down
87 changes: 0 additions & 87 deletions src/model/composer/composer.js

This file was deleted.

10 changes: 0 additions & 10 deletions src/model/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import Batch from './batch.js';
import History from './history.js';
import LiveSelection from './liveselection.js';
import Schema from './schema.js';
import Composer from './composer/composer.js';
import clone from '../../utils/lib/lodash/clone.js';
import EmitterMixin from '../../utils/emittermixin.js';
import CKEditorError from '../../utils/ckeditorerror.js';
Expand Down Expand Up @@ -78,15 +77,6 @@ export default class Document {
*/
this.history = new History( this );

/**
* Composer for this document. Set of tools to work with the document.
*
* The features can tune up these tools to better work on their specific cases.
*
* @member {engine.model.composer.Composer} engine.model.Document#composer
*/
this.composer = new Composer();

/**
* Array of pending changes. See: {@link engine.model.Document#enqueueChanges}.
*
Expand Down
Loading

0 comments on commit 6a9306e

Please sign in to comment.