浏览代码

Introduced ControllerCollection class.

Aleksander Nowodzinski 10 年之前
父节点
当前提交
4fa9ee868d

+ 19 - 54
packages/ckeditor5-ui/src/ui/controller.js

@@ -43,12 +43,12 @@ CKEDITOR.define( [
 			this.view = view || null;
 
 			/**
-			 * Collections of child controllers.
+			 * A collection of {@link ControllerCollection} instances containing
+			 * child controllers.
 			 *
-			 * @private
 			 * @property {Collection}
 			 */
-			this._collections = new Collection( {
+			this.collections = new Collection( {
 				idProperty: 'name'
 			} );
 		}
@@ -56,7 +56,7 @@ CKEDITOR.define( [
 		/**
 		 * Initializes the controller instance. The process includes:
 		 *  1. Initialization of the child {@link #view}.
-		 *  2. Initialization of child controllers in {@link #_collections}.
+		 *  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.
@@ -96,7 +96,7 @@ CKEDITOR.define( [
 		}
 
 		/**
-		 * Initializes the {@link #_collections} of this controller instance.
+		 * Initializes the {@link #collections} of this controller instance.
 		 *
 		 * @protected
 		 * @returns {Promise} A Promise resolved when initialization process is finished.
@@ -105,7 +105,7 @@ CKEDITOR.define( [
 			const promises = [];
 			let collection, childController;
 
-			for ( collection of this._collections ) {
+			for ( collection of this.collections ) {
 				for ( childController of collection ) {
 					if ( this.view, childController.view ) {
 						this.view.addChild( collection.name, childController.view );
@@ -119,12 +119,12 @@ CKEDITOR.define( [
 		}
 
 		/**
-		 * Adds a child controller to one of the {@link #_collections} (see {@link #register}).
+		 * Adds a child controller to one of the {@link #collections} (see {@link #register}).
 		 * If this controller instance is ready, the child view will be initialized when added.
 		 * If this controller and child controller have views, the child view will be added
 		 * to corresponding region in this controller's view.
 		 *
-		 * @param {String} collectionName One of {@link #_collections} the child should be added to.
+		 * @param {String} collectionName One of {@link #collections} the child should be added to.
 		 * @param {Controller} childController A child controller.
 		 * @param {Number} [index] Index at which the child will be added to the collection.
 		 * @returns {Promise} A Promise resolved when the child is added.
@@ -139,7 +139,7 @@ CKEDITOR.define( [
 				throw new CKEditorError( 'ui-controller-addchild-badcname' );
 			}
 
-			const collection = this._collections.get( collectionName );
+			const collection = this.collections.get( collectionName );
 
 			if ( !collection ) {
 				/**
@@ -180,11 +180,11 @@ CKEDITOR.define( [
 		}
 
 		/**
-		 * Removes a child controller from one of the {@link #_collections} (see {@link #register}).
+		 * Removes a child controller from one of the {@link #collections} (see {@link #register}).
 		 * If this controller and child controller have views, the child view will be removed
 		 * from corresponding region in this controller's view.
 		 *
-		 * @param {String} collectionName One of {@link #_collections} the child should be removed from.
+		 * @param {String} collectionName One of {@link #collections} the child should be removed from.
 		 * @param {Controller} childController A child controller.
 		 * @returns {Controller} A child controller instance after removal.
 		 */
@@ -198,7 +198,7 @@ CKEDITOR.define( [
 				throw new CKEditorError( 'ui-controller-removechild-badcname' );
 			}
 
-			const collection = this._collections.get( collectionName );
+			const collection = this.collections.get( collectionName );
 
 			if ( !collection ) {
 				/**
@@ -228,15 +228,15 @@ CKEDITOR.define( [
 		}
 
 		/**
-		 * Returns a child controller from one of the {@link #_collections}
+		 * Returns a child controller from one of the {@link #collections}
 		 * (see {@link #register}) at given `index`.
 		 *
-		 * @param {String} collectionName One of {@link #_collections} the child should be retrieved from.
+		 * @param {String} collectionName One of {@link #collections} the child should be retrieved from.
 		 * @param {Number} [index] An index of desired controller.
 		 * @returns {Controller} A child controller instance.
 		 */
 		getChild( collectionName, index ) {
-			const collection = this._collections.get( collectionName );
+			const collection = this.collections.get( collectionName );
 
 			if ( !collection ) {
 				/**
@@ -251,44 +251,9 @@ CKEDITOR.define( [
 		}
 
 		/**
-		 * Registers a collection in {@link #_collections}.
-		 *
-		 * @param {String} collectionName The name of the collection to be registered.
-		 * @param {Collection} collection Collection to be registered.
-		 * @param {Boolean} [override] When set `true` it will allow overriding of registered collections.
-		 */
-		register( collectionName, collection, override ) {
-			const registered = this._collections.get( collectionName );
-			const that = this;
-
-			if ( !registered ) {
-				add( collection );
-			} else {
-				if ( registered !== collection ) {
-					if ( !override ) {
-						/**
-						 * Overriding is possible only when `override` flag is set.
-						 *
-						 * @error ui-controller-register-noverride
-						 */
-						throw new CKEditorError( 'ui-controller-register-noverride' );
-					}
-
-					that._collections.remove( registered );
-					add( collection );
-				}
-			}
-
-			function add() {
-				collection.name = collectionName;
-				that._collections.add( collection );
-			}
-		}
-
-		/**
 		 * Destroys the controller instance. The process includes:
 		 *  1. Destruction of the child {@link #view}.
-		 *  2. Destruction of child controllers in {@link #_collections}.
+		 *  2. Destruction of child controllers in {@link #collections}.
 		 *
 		 * @returns {Promise} A Promise resolved when the destruction process is finished.
 		 */
@@ -296,7 +261,7 @@ CKEDITOR.define( [
 			let promises = [];
 			let collection, childController;
 
-			for ( collection of this._collections ) {
+			for ( collection of this.collections ) {
 				for ( childController of collection ) {
 					if ( this.view && childController.view ) {
 						this.view.removeChild( collection.name, childController.view );
@@ -307,7 +272,7 @@ CKEDITOR.define( [
 					collection.remove( childController );
 				}
 
-				this._collections.remove( collection );
+				this.collections.remove( collection );
 			}
 
 			if ( this.view ) {
@@ -317,7 +282,7 @@ CKEDITOR.define( [
 			}
 
 			promises.push( Promise.resolve().then( () => {
-				this.model = this.ready = this.view = this._collections = null;
+				this.model = this.ready = this.view = this.collections = null;
 			} ) );
 
 			return Promise.all( promises );

+ 42 - 0
packages/ckeditor5-ui/src/ui/controllercollection.js

@@ -0,0 +1,42 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+/**
+ * Manages UI Controllers.
+ *
+ * @class ControllerCollection
+ * @extends Collection
+ */
+CKEDITOR.define( [
+	'collection',
+	'ckeditorerror'
+], ( Collection, CKEditorError ) => {
+	class ControllerCollection extends Collection {
+		/**
+		 * Creates an instance of the ControllerCollection class, initializing it with a name.
+		 *
+		 * @constructor
+		 */
+		constructor( name ) {
+			super();
+
+			if ( !name ) {
+				/**
+				 * ControllerCollection must be initialized with a name.
+				 *
+				 * @error ui-controllercollection-no-name
+				 */
+				throw new CKEditorError( 'ui-controllercollection-no-name: ControllerCollection must be initialized with a name.' );
+			}
+
+			this.name = name;
+		}
+
+	}
+
+	return ControllerCollection;
+} );

+ 31 - 81
packages/ckeditor5-ui/tests/ui/controller.js

@@ -10,6 +10,7 @@
 const modules = bender.amd.require( 'ckeditor',
 	'ui/view',
 	'ui/controller',
+	'ui/controllercollection',
 	'ui/region',
 	'ckeditorerror',
 	'model',
@@ -17,7 +18,7 @@ const modules = bender.amd.require( 'ckeditor',
 	'eventinfo'
 );
 
-let View, Controller, Model, CKEditorError, Collection;
+let View, Controller, Model, CKEditorError, Collection, ControllerCollection;
 let ParentView;
 
 bender.tools.createSinonSandbox();
@@ -32,7 +33,7 @@ describe( 'Controller', () => {
 			expect( controller.model ).to.be.null;
 			expect( controller.ready ).to.be.false;
 			expect( controller.view ).to.be.null;
-			expect( controller._collections.length ).to.be.equal( 0 );
+			expect( controller.collections.length ).to.be.equal( 0 );
 		} );
 
 		it( 'should accept model and view', () => {
@@ -81,7 +82,7 @@ describe( 'Controller', () => {
 
 		it( 'should initialize child controllers in own collections', () => {
 			const parentController = new Controller();
-			parentController.register( 'buttons', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'buttons' ) );
 
 			const childController1 = new Controller();
 			const childController2 = new Controller();
@@ -101,64 +102,13 @@ describe( 'Controller', () => {
 		} );
 	} );
 
-	describe( 'register', () => {
-		it( 'should throw when bad type of argument', () => {
-			const controller = new Controller();
-
-			controller.register( 'x', new Collection() );
-
-			expect( () => {
-				controller.register();
-			} ).to.throw;
-		} );
-
-		it( 'should throw when already registered but no override flag', () => {
-			const controller = new Controller();
-
-			controller.register( 'x', new Collection() );
-
-			expect( () => {
-				controller.register( 'x', new Collection() );
-			} ).to.throw( CKEditorError, /ui-controller-register-noverride/ );
-		} );
-
-		it( 'should register a collection', () => {
-			const controller = new Controller();
-			const collection = new Collection();
-
-			controller.register( 'x', collection );
-
-			expect( controller._collections.get( 'x' ) ).to.be.equal( collection );
-		} );
-
-		it( 'should override existing collection with override flag', () => {
-			const controller = new Controller();
-			const newCollection = new Collection();
-
-			controller.register( 'x', new Collection() );
-			controller.register( 'x', newCollection, true );
-
-			expect( controller._collections.get( 'x' ) ).to.be.equal( newCollection );
-		} );
-
-		it( 'should override existing collection with the same collection', () => {
-			const controller = new Controller();
-			const newCollection = new Collection();
-
-			controller.register( 'x', newCollection );
-			controller.register( 'x', newCollection );
-
-			expect( controller._collections.get( 'x' ) ).to.be.equal( newCollection );
-		} );
-	} );
-
 	describe( 'addChild', () => {
 		beforeEach( defineParentViewClass );
 
 		it( 'should throw when no collection name', () => {
 			const controller = new Controller();
 
-			controller.register( 'x', new Collection() );
+			controller.collections.add( new ControllerCollection( 'x' ) );
 
 			expect( () => {
 				controller.addChild();
@@ -168,7 +118,7 @@ describe( 'Controller', () => {
 		it( 'should throw when collection of given name does not exist', () => {
 			const controller = new Controller();
 
-			controller.register( 'x', new Collection() );
+			controller.collections.add( new ControllerCollection( 'x' ) );
 
 			expect( () => {
 				controller.addChild( 'y', new Controller() );
@@ -178,7 +128,7 @@ describe( 'Controller', () => {
 		it( 'should throw when no controller is passed', () => {
 			const controller = new Controller();
 
-			controller.register( 'x', new Collection() );
+			controller.collections.add( new ControllerCollection( 'x' ) );
 
 			expect( () => {
 				controller.addChild( 'x' );
@@ -188,9 +138,9 @@ describe( 'Controller', () => {
 		it( 'should add a child controller to given collection and return promise', () => {
 			const parentController = new Controller();
 			const childController = new Controller();
-			const collection = new Collection();
+			const collection = new ControllerCollection( 'x' );
 
-			parentController.register( 'x', collection );
+			parentController.collections.add( collection );
 
 			const returned = parentController.addChild( 'x', childController );
 
@@ -202,9 +152,9 @@ describe( 'Controller', () => {
 			const parentController = new Controller();
 			const childController1 = new Controller();
 			const childController2 = new Controller();
-			const collection = new Collection();
+			const collection = new ControllerCollection( 'x' );
 
-			parentController.register( 'x', collection );
+			parentController.collections.add( collection );
 
 			parentController.addChild( 'x', childController1 );
 			parentController.addChild( 'x', childController2, 0 );
@@ -217,7 +167,7 @@ describe( 'Controller', () => {
 			const parentController = new Controller( null, new ParentView() );
 			const childController = new Controller();
 
-			parentController.register( 'x', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 
 			return parentController.init()
 				.then( () => {
@@ -235,7 +185,7 @@ describe( 'Controller', () => {
 
 			const spy1 = bender.sinon.spy( parentView, 'addChild' );
 
-			parentController.register( 'x', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 			parentController.addChild( 'x', childController );
 
 			sinon.assert.notCalled( spy1 );
@@ -260,7 +210,7 @@ describe( 'Controller', () => {
 			const childView2 = new View();
 			const childController2 = new Controller( null, childView2 );
 
-			parentController.register( 'x', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 
 			return parentController.init()
 				.then( () => {
@@ -279,7 +229,7 @@ describe( 'Controller', () => {
 			const childController = new Controller( null, new View() );
 			const spy = bender.sinon.spy( childController, 'init' );
 
-			parentController.register( 'x', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 			parentController.addChild( 'x', childController );
 			parentController.removeChild( 'x', childController );
 
@@ -299,7 +249,7 @@ describe( 'Controller', () => {
 			const childController = new Controller( null, new View() );
 			const spy = bender.sinon.spy( childController, 'init' );
 
-			parentController.register( 'x', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 
 			return parentController.init()
 				.then( () => {
@@ -320,7 +270,7 @@ describe( 'Controller', () => {
 		it( 'should throw when no collection name', () => {
 			const controller = new Controller();
 
-			controller.register( 'x', new Collection() );
+			controller.collections.add( new ControllerCollection( 'x' ) );
 
 			expect( () => {
 				controller.removeChild();
@@ -330,7 +280,7 @@ describe( 'Controller', () => {
 		it( 'should throw when collection of given name does not exist', () => {
 			const controller = new Controller();
 
-			controller.register( 'x', new Collection() );
+			controller.collections.add( new ControllerCollection( 'x' ) );
 
 			expect( () => {
 				controller.removeChild( 'y' );
@@ -340,7 +290,7 @@ describe( 'Controller', () => {
 		it( 'should throw when controller or wrong controller is passed', () => {
 			const controller = new Controller();
 
-			controller.register( 'x', new Collection() );
+			controller.collections.add( new ControllerCollection( 'x' ) );
 
 			expect( () => {
 				controller.removeChild( 'x' );
@@ -350,9 +300,9 @@ describe( 'Controller', () => {
 		it( 'should remove child controller and return it', () => {
 			const parentController = new Controller();
 			const childController = new Controller();
-			const collection = new Collection();
+			const collection = new ControllerCollection( 'x' );
 
-			parentController.register( 'x', collection );
+			parentController.collections.add( collection );
 
 			parentController.addChild( 'x', childController );
 			const returned = parentController.removeChild( 'x', childController );
@@ -368,7 +318,7 @@ describe( 'Controller', () => {
 
 			const spy = bender.sinon.spy( parentView, 'removeChild' );
 
-			parentController.register( 'x', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 			parentController.addChild( 'x', childController );
 
 			sinon.assert.notCalled( spy );
@@ -388,7 +338,7 @@ describe( 'Controller', () => {
 		it( 'should throw when collection of given name does not exist', () => {
 			const controller = new Controller();
 
-			controller.register( 'x', new Collection() );
+			controller.collections.add( new ControllerCollection( 'x' ) );
 
 			expect( () => {
 				controller.getChild( 'y', 0 );
@@ -398,9 +348,8 @@ describe( 'Controller', () => {
 		it( 'should get child controller by index', () => {
 			const parentController = new Controller();
 			const childController = new Controller();
-			const collection = new Collection();
 
-			parentController.register( 'x', collection );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 			parentController.addChild( 'x', childController );
 
 			expect( parentController.getChild( 'x', 0 ) ).to.be.equal( childController );
@@ -425,7 +374,7 @@ describe( 'Controller', () => {
 					expect( controller.model ).to.be.null;
 					expect( controller.ready ).to.be.null;
 					expect( controller.view ).to.be.null;
-					expect( controller._collections ).to.be.null;
+					expect( controller.collections ).to.be.null;
 				} );
 		} );
 
@@ -439,7 +388,7 @@ describe( 'Controller', () => {
 				.then( () => {
 					expect( controller.model ).to.be.null;
 					expect( controller.view ).to.be.null;
-					expect( controller._collections ).to.be.null;
+					expect( controller.collections ).to.be.null;
 				} );
 		} );
 
@@ -449,7 +398,7 @@ describe( 'Controller', () => {
 			const childController = new Controller( null, childView );
 			const spy = bender.sinon.spy( childView, 'destroy' );
 
-			parentController.register( 'x', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 			parentController.addChild( 'x', childController );
 
 			return parentController.init()
@@ -460,7 +409,7 @@ describe( 'Controller', () => {
 					sinon.assert.calledOnce( spy );
 					expect( childController.model ).to.be.null;
 					expect( childController.view ).to.be.null;
-					expect( childController._collections ).to.be.null;
+					expect( childController.collections ).to.be.null;
 				} );
 		} );
 
@@ -468,7 +417,7 @@ describe( 'Controller', () => {
 			const parentController = new Controller( null, new ParentView() );
 			const childController = new Controller( null, null );
 
-			parentController.register( 'x', new Collection() );
+			parentController.collections.add( new ControllerCollection( 'x' ) );
 			parentController.addChild( 'x', childController );
 
 			return parentController.init()
@@ -478,7 +427,7 @@ describe( 'Controller', () => {
 				.then( () => {
 					expect( childController.model ).to.be.null;
 					expect( childController.view ).to.be.null;
-					expect( childController._collections ).to.be.null;
+					expect( childController.collections ).to.be.null;
 				} );
 		} );
 	} );
@@ -489,6 +438,7 @@ function updateModuleReference() {
 	Controller = modules[ 'ui/controller' ];
 	Model = modules.model;
 	Collection = modules.collection;
+	ControllerCollection = modules[ 'ui/controllercollection' ];
 	CKEditorError = modules.ckeditorerror;
 }
 

+ 24 - 0
packages/ckeditor5-ui/tests/ui/controllercollection.js

@@ -0,0 +1,24 @@
+/**
+ * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* bender-tags: core, ui */
+
+'use strict';
+
+const modules = bender.amd.require( 'ckeditor', 'ui/controllercollection' );
+
+bender.tools.createSinonSandbox();
+
+describe( 'ControllerCollection', () => {
+	describe( 'constructor', () => {
+		it( 'should throw when no name is passed', () => {
+			const ControllerCollection = modules[ 'ui/controllercollection' ];
+
+			expect( () => {
+				new ControllerCollection();
+			} ).to.throw( /^ui-controllercollection-no-name/ );
+		} );
+	} );
+} );