|
|
@@ -1,289 +0,0 @@
|
|
|
-/**
|
|
|
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
|
|
|
- * For licensing, see LICENSE.md.
|
|
|
- */
|
|
|
-
|
|
|
-import Collection from '../utils/collection.js';
|
|
|
-import ControllerCollection from './controllercollection.js';
|
|
|
-import CKEditorError from '../utils/ckeditorerror.js';
|
|
|
-import EmitterMixin from '../utils/emittermixin.js';
|
|
|
-import mix from '../utils/mix.js';
|
|
|
-
|
|
|
-const anon = '$anonymous';
|
|
|
-
|
|
|
-/**
|
|
|
- * Basic Controller class.
|
|
|
- *
|
|
|
- * @memberOf ui
|
|
|
- * @mixes utils.EmitterMixin
|
|
|
- */
|
|
|
-export default class Controller {
|
|
|
- /**
|
|
|
- * Creates an instance of the {@link ui.Controller} class.
|
|
|
- *
|
|
|
- * @param {ui.Model} [model] Model of this Controller.
|
|
|
- * @param {ui.View} [view] View instance of this Controller.
|
|
|
- */
|
|
|
- constructor( model, view ) {
|
|
|
- /**
|
|
|
- * Model of this controller.
|
|
|
- *
|
|
|
- * @member {ui.Model} ui.Controller#model
|
|
|
- */
|
|
|
- this.model = model || null;
|
|
|
-
|
|
|
- /**
|
|
|
- * Set `true` after {@link #init}.
|
|
|
- *
|
|
|
- * @member {Boolean} ui.Controller#ready
|
|
|
- */
|
|
|
- this.ready = false;
|
|
|
-
|
|
|
- /**
|
|
|
- * View of this controller.
|
|
|
- *
|
|
|
- * @member {ui.View} ui.Controller#view
|
|
|
- */
|
|
|
- this.view = view || null;
|
|
|
-
|
|
|
- /**
|
|
|
- * A collection of {@link ControllerCollection} instances containing
|
|
|
- * child controllers.
|
|
|
- *
|
|
|
- * @member {utils.Collection} ui.Controller#collections
|
|
|
- */
|
|
|
- this.collections = new Collection( {
|
|
|
- idProperty: 'name'
|
|
|
- } );
|
|
|
-
|
|
|
- /**
|
|
|
- * Anonymous collection of this controller instance. It groups child controllers
|
|
|
- * which are not to be handled by `Controller#collections`–to–`View#region`
|
|
|
- * automation. It also means their views must be handled individually
|
|
|
- * by the view, i.e. passed as members of {@link ui.TemplateDefinition#children}.
|
|
|
- *
|
|
|
- * @protected
|
|
|
- * @member {ui.ControllerCollection} ui.Controller#_anonymousCollection
|
|
|
- */
|
|
|
- this.collections.add( this._anonymousCollection = new ControllerCollection( anon ) );
|
|
|
-
|
|
|
- // Listen to {@link ControllerCollection#add} and {@link ControllerCollection#remove}
|
|
|
- // of newly added Collection to synchronize this controller's view and children
|
|
|
- // controllers' views in the future.
|
|
|
- this.collections.on( 'add', ( evt, collection ) => {
|
|
|
- // Set the {@link ControllerCollection#parent} to this controller.
|
|
|
- // It allows the collection to determine the {@link #ready} state of this controller
|
|
|
- // and accordingly initialize a child controller when added.
|
|
|
- collection.parent = this;
|
|
|
-
|
|
|
- this.listenTo( collection, 'add', ( evt, childController, index ) => {
|
|
|
- // Child view is added to corresponding region in this controller's view
|
|
|
- // when a new Controller joins the collection.
|
|
|
- if ( this.ready && childController.view ) {
|
|
|
- this.view.regions.get( collection.name ).views.add( childController.view, index );
|
|
|
- }
|
|
|
- } );
|
|
|
-
|
|
|
- this.listenTo( collection, 'remove', ( evt, childController ) => {
|
|
|
- // Child view is removed from corresponding region in this controller's view
|
|
|
- // when a new Controller is removed from the the collection.
|
|
|
- if ( this.ready && childController.view ) {
|
|
|
- this.view.regions.get( collection.name ).views.remove( childController.view );
|
|
|
- }
|
|
|
- } );
|
|
|
- } );
|
|
|
-
|
|
|
- this.collections.on( 'remove', ( evt, collection ) => {
|
|
|
- // Release the collection. Once removed from {@link #collections}, it can be
|
|
|
- // moved to another controller.
|
|
|
- collection.parent = null;
|
|
|
-
|
|
|
- this.stopListening( collection );
|
|
|
- } );
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Initializes the controller instance. The process includes:
|
|
|
- *
|
|
|
- * 1. Initialization of the child {@link #view}.
|
|
|
- * 2. Initialization of child controllers in {@link #collections}.
|
|
|
- * 3. Setting {@link #ready} flag `true`.
|
|
|
- *
|
|
|
- * @returns {Promise} A Promise resolved when the initialization process is finished.
|
|
|
- */
|
|
|
- init() {
|
|
|
- if ( this.ready ) {
|
|
|
- /**
|
|
|
- * This Controller already been initialized.
|
|
|
- *
|
|
|
- * @error ui-controller-init-reinit
|
|
|
- */
|
|
|
- throw new CKEditorError( 'ui-controller-init-reinit: This Controller already been initialized.' );
|
|
|
- }
|
|
|
-
|
|
|
- return Promise.resolve()
|
|
|
- .then( this._initView.bind( this ) )
|
|
|
- .then( this._initCollections.bind( this ) )
|
|
|
- .then( () => {
|
|
|
- this.ready = true;
|
|
|
- this.fire( 'ready' );
|
|
|
- } );
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Destroys the controller instance. The process includes:
|
|
|
- *
|
|
|
- * 1. Destruction of the child {@link #view}.
|
|
|
- * 2. Destruction of child controllers in {@link #collections}.
|
|
|
- *
|
|
|
- * @returns {Promise} A Promise resolved when the destruction process is finished.
|
|
|
- */
|
|
|
- destroy() {
|
|
|
- let promises = [];
|
|
|
- let collection, childController;
|
|
|
-
|
|
|
- for ( collection of this.collections ) {
|
|
|
- for ( childController of collection ) {
|
|
|
- promises.push( childController.destroy() );
|
|
|
- }
|
|
|
-
|
|
|
- collection.clear();
|
|
|
- }
|
|
|
-
|
|
|
- this.collections.clear();
|
|
|
-
|
|
|
- if ( this.view ) {
|
|
|
- promises.push( Promise.resolve().then( () => {
|
|
|
- return this.view.destroy();
|
|
|
- } ) );
|
|
|
- }
|
|
|
-
|
|
|
- promises.push( Promise.resolve().then( () => {
|
|
|
- this.model = this.ready = this.view = this.collections = null;
|
|
|
- } ) );
|
|
|
-
|
|
|
- return Promise.all( promises );
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Adds a new collection to {@link ui.Controller#collections}.
|
|
|
- *
|
|
|
- * @param {String} collectionName Name of the controller collection.
|
|
|
- * @returns {ui.ControllerCollection} The new collection instance.
|
|
|
- */
|
|
|
- addCollection( collectionName ) {
|
|
|
- const collection = new ControllerCollection( collectionName, this.view && this.view.locale );
|
|
|
-
|
|
|
- this.collections.add( collection );
|
|
|
-
|
|
|
- return collection;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Adds a child {@link Controller} instance to {@link #collections} at given index.
|
|
|
- *
|
|
|
- * // Adds child to the specified collection. The collection name
|
|
|
- * // must correspond with the region name in parent.view#regions.
|
|
|
- * parent.add( 'collection-name', child );
|
|
|
- *
|
|
|
- * // Adds child to the specified collection at specific index.
|
|
|
- * // The collection name must correspond with the region name in parent.view#regions.
|
|
|
- * parent.add( 'collection-name', child, 3 );
|
|
|
- *
|
|
|
- * // Adds child to the {@link ui.Controller#_anonymousCollection} in the parent. In such case,
|
|
|
- * // parent#view must put the child#view in the correct place in parent.view#template
|
|
|
- * // because there's no association between the {@link ui.Controller#_anonymousCollection}
|
|
|
- * // and any of the regions.
|
|
|
- * parent.add( child );
|
|
|
- *
|
|
|
- * @param {String|ui.Controller} collectionNameOrController Name of the collection or the controller instance.
|
|
|
- * @param {ui.Controller} [controller] A controller instance to be added.
|
|
|
- * @param {Number} [index] An index in the collection.
|
|
|
- * @returns {Promise} A Promise resolved when the child {@link ui.Controller#init} is done.
|
|
|
- */
|
|
|
- add( ...args ) {
|
|
|
- if ( args[ 0 ] instanceof Controller ) {
|
|
|
- return this._anonymousCollection.add( ...args );
|
|
|
- } else {
|
|
|
- return this.collections.get( args[ 0 ] ).add( args[ 1 ], args[ 2 ] );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Removes a child {@link ui.Controller} instance from one of {@link ui.Controller#collections}.
|
|
|
- *
|
|
|
- * **Note**: To remove children from {@link ui.Controller#_anonymousCollection}, use the following syntax
|
|
|
- *
|
|
|
- * parent.remove( child );
|
|
|
- *
|
|
|
- * @param {String|ui.Controller} collectionNameOrController Name of the collection or the controller instance.
|
|
|
- * @param {ui.Controller|Number} [toRemove] A Controller instance or index to be removed.
|
|
|
- * @returns {Object} The removed item.
|
|
|
- */
|
|
|
- remove( collectionNameOrController, toRemove ) {
|
|
|
- if ( collectionNameOrController instanceof Controller ) {
|
|
|
- return this._anonymousCollection.remove( collectionNameOrController );
|
|
|
- } else {
|
|
|
- return this.collections.get( collectionNameOrController ).remove( toRemove );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Initializes the {@link #view} of this controller instance.
|
|
|
- *
|
|
|
- * @protected
|
|
|
- * @returns {Promise} A Promise resolved when initialization process is finished.
|
|
|
- */
|
|
|
- _initView() {
|
|
|
- let promise = Promise.resolve();
|
|
|
-
|
|
|
- if ( this.view ) {
|
|
|
- promise = promise.then( this.view.init.bind( this.view ) );
|
|
|
- }
|
|
|
-
|
|
|
- return promise;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Initializes the {@link #collections} of this controller instance.
|
|
|
- *
|
|
|
- * @protected
|
|
|
- * @returns {Promise} A Promise resolved when initialization process is finished.
|
|
|
- */
|
|
|
- _initCollections() {
|
|
|
- const promises = [];
|
|
|
- let collection, childController;
|
|
|
-
|
|
|
- for ( collection of this.collections ) {
|
|
|
- for ( childController of collection ) {
|
|
|
- // Anonymous collection {@link ui.Controller#_anonymousCollection} does not allow
|
|
|
- // automated controller-to-view binding, because there's no such thing as
|
|
|
- // anonymous Region in the View instance.
|
|
|
- if ( !isAnonymous( collection ) && this.view && childController.view ) {
|
|
|
- this.view.regions.get( collection.name ).views.add( childController.view );
|
|
|
- }
|
|
|
-
|
|
|
- promises.push( childController.init() );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return Promise.all( promises );
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-mix( Controller, EmitterMixin );
|
|
|
-
|
|
|
-// Checks whether the collection is anonymous.
|
|
|
-//
|
|
|
-// @private
|
|
|
-// @param {ui.ControllerCollection} collection
|
|
|
-// @returns {Boolean}
|
|
|
-function isAnonymous( collection ) {
|
|
|
- return collection.name == anon;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Fired when the controller is fully initialized.
|
|
|
- *
|
|
|
- * @event ui.Controller#ready
|
|
|
- */
|