Selaa lähdekoodia

Implemented CompponentRepository and basic UI components.

Piotrek Koszuliński 9 vuotta sitten
vanhempi
sitoutus
38f7a54b96

+ 7 - 0
packages/ckeditor5-engine/src/editorui.js

@@ -8,6 +8,7 @@
 import Controller from './ui/controller.js';
 import utils from './utils.js';
 import ObservableMixin from './observablemixin.js';
+import ComponentRepository from './ui/componentrepository.js';
 
 /**
  * Base class for the editor main view controllers.
@@ -26,6 +27,12 @@ export default class EditorUI extends Controller {
 		 * @member {core.Editor} core.EditorUI.editor
 		 */
 		this.editor = editor;
+
+		/**
+		 * @readonly
+		 * @type {core.ui.ComponentRepository}
+		 */
+		this.featureComponents = new ComponentRepository( editor );
 	}
 }
 

+ 28 - 0
packages/ckeditor5-engine/src/ui/button/button.js

@@ -0,0 +1,28 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import Controller from '../controller.js';
+
+/**
+ * The basic button controller class.
+ *
+ * @class core.ui.button.Button
+ * @extends core.ui.Controller
+ */
+
+export default class Button extends Controller {
+	/**
+	 * Creates a new button instance.
+	 *
+	 * @method constructor
+	 */
+	constructor( model, view ) {
+		super( model, view );
+
+		view.on( 'clicked', () => model.fire( 'executed' ) );
+	}
+}

+ 61 - 0
packages/ckeditor5-engine/src/ui/button/buttonview.js

@@ -0,0 +1,61 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import View from '../view.js';
+
+/**
+ * The basic button view class.
+ *
+ * @class core.ui.button.ButtonView
+ * @extends core.ui.View
+ */
+
+export default class ButtonView extends View {
+	/**
+	 * Creates a new button view instance.
+	 *
+	 * @method constructor
+	 * @param {Model} model
+	 */
+	constructor( model ) {
+		super( model );
+
+		const bind = this.attributeBinder;
+
+		this.template = {
+			tag: 'button',
+
+			attributes: {
+				class: [
+					'ck-button',
+					bind.to( 'isEnabled', value => value ? 'ck-enabled' : 'ck-disabled' ),
+					bind.to( 'isOn', value => value ? 'ck-on' : 'ck-off' )
+				]
+			},
+
+			children: [
+				{
+					text: bind.to( 'label' )
+				}
+			],
+
+			on: {
+				mousedown: ( evt ) => {
+					evt.preventDefault();
+				},
+
+				click: () => {
+					// We can't make the button disabled using the disabled attribute, because it won't be focusable.
+					// Though, shouldn't this condition be moved to the button controller?
+					if ( model.isEnabled ) {
+						this.fire( 'clicked' );
+					}
+				}
+			}
+		};
+	}
+}

+ 48 - 0
packages/ckeditor5-engine/src/ui/componentrepository.js

@@ -0,0 +1,48 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import CKEditorError from '../ckeditorerror.js';
+
+/**
+ * @class core.ui.ComponentRepository
+ */
+
+export default class ComponentRepository {
+	constructor( editor ) {
+		/**
+		 * @readonly
+		 * @type {core.Editor}
+		 */
+		this.editor = editor;
+
+		this._components = new Map();
+	}
+
+	add( name, ControllerClass, ViewClass, model ) {
+		if ( this._components.get( name ) ) {
+			throw new CKEditorError(
+				'componentrepository-item-exists: The item already exists in the component registry', { name }
+			);
+		}
+
+		this._components.set( name, {
+			ControllerClass,
+			ViewClass,
+			model
+		} );
+	}
+
+	create( name ) {
+		const component = this._components.get( name );
+
+		const model = component.model;
+		const view = new component.ViewClass( model );
+		const controller = new component.ControllerClass( this.editor, model, view );
+
+		return controller;
+	}
+}

+ 29 - 0
packages/ckeditor5-engine/src/ui/toolbar/toolbar.js

@@ -0,0 +1,29 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import Controller from '../controller.js';
+import ControllerCollection from '../controllercollection.js';
+
+/**
+ * The basic toolbar controller class.
+ *
+ * @class core.ui.toolbar.Toolbar
+ * @extends core.ui.Controller
+ */
+
+export default class Toolbar extends Controller {
+	/**
+	 * Creates a new toolbar instance.
+	 *
+	 * @method constructor
+	 */
+	constructor( model, view ) {
+		super( model, view );
+
+		this.collections.add( new ControllerCollection( 'buttons' ) );
+	}
+}

+ 36 - 0
packages/ckeditor5-engine/src/ui/toolbar/toolbarview.js

@@ -0,0 +1,36 @@
+/**
+ * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+'use strict';
+
+import View from '../view.js';
+
+/**
+ * The basic toolbar view class.
+ *
+ * @class core.ui.toolbar.ToolbarView
+ * @extends core.ui.View
+ */
+
+export default class ToolbarView extends View {
+	/**
+	 * Creates a new toolbar view instance.
+	 *
+	 * @method constructor
+	 * @param {Model} model
+	 */
+	constructor( model ) {
+		super( model );
+
+		this.template = {
+			tag: 'div',
+			attributes: {
+				class: 'ck-toolbar'
+			}
+		};
+
+		this.register( 'buttons', el => el );
+	}
+}

+ 1 - 0
packages/ckeditor5-engine/tests/_utils/ui/boxededitorui/boxededitorui.js

@@ -12,6 +12,7 @@ export default class BoxedEditorUI extends EditorUI {
 	constructor( editor ) {
 		super( editor );
 
+		this.collections.add( new ControllerCollection( 'top' ) );
 		this.collections.add( new ControllerCollection( 'main' ) );
 
 		const config = editor.config;

+ 20 - 4
packages/ckeditor5-engine/tests/_utils/ui/boxededitorui/boxededitoruiview.js

@@ -13,11 +13,27 @@ export default class BoxedEditorUIView extends View {
 
 		this.template = {
 			tag: 'div',
-			attrs: {
-				'class': [ 'ck-chrome' ]
-			}
+			attributes: {
+				class: 'ck-box'
+			},
+			children: [
+				{
+					tag: 'div',
+					attributes: {
+						class: 'ck-box-region ck-top'
+					}
+				},
+
+				{
+					tag: 'div',
+					attributes: {
+						class: 'ck-box-region ck-main'
+					}
+				}
+			]
 		};
 
-		this.register( 'main', el => el );
+		this.register( 'top', '.ck-top' );
+		this.register( 'main', '.ck-main' );
 	}
 }

+ 52 - 0
packages/ckeditor5-engine/tests/creator/manual/_assets/styles.css

@@ -0,0 +1,52 @@
+.ck-box {
+	background: rgb( 200, 200, 200 );
+	padding: 1px 0;
+}
+
+.ck-box-region {
+	background: rgb( 240, 240, 240 );
+	padding: 5px;
+	margin: 1px;
+}
+.ck-box-region:first-child {
+	margin-top: 0;
+}
+.ck-box-region:last-child {
+	margin-bottom: 0;
+}
+
+.ck-main {
+	background: #FFF;
+}
+
+.ck-top {
+}
+
+.ck-button {
+	border: solid 1px transparent;
+	background: transparent;
+	display: inline-block;
+	padding: 5px 10px;
+	border-radius: 1px;
+	margin-right: 5px;
+
+	font-size: 16px;
+	color: rgb( 69, 69, 69 );
+
+	cursor: pointer;
+}
+
+.ck-button:hover:not(.ck-disabled) {
+	border: solid 1px rgb( 180, 180, 180 );
+	box-shadow: 0 0 2px rgba( 0, 0, 0, 0.1 );
+}
+
+.ck-button.ck-on {
+	border: solid 1px rgb( 200, 200, 200 );
+	box-shadow: inset 0 0 3px rgba( 0, 0, 0, 0.1 );
+	background: rgba( 0, 0, 0, 0.05 );
+}
+
+.ck-button.ck-disabled {
+	color: rgb( 180, 180, 180 );
+}

+ 56 - 0
packages/ckeditor5-engine/tests/creator/manual/_utils/creator/classiccreator.js

@@ -10,6 +10,11 @@ import BoxedEditorUI from '/tests/core/_utils/ui/boxededitorui/boxededitorui.js'
 import BoxedEditorUIView from '/tests/core/_utils/ui/boxededitorui/boxededitoruiview.js';
 import FramedEditable from '/tests/core/_utils/ui/editable/framed/framededitable.js';
 import FramedEditableView from '/tests/core/_utils/ui/editable/framed/framededitableview.js';
+import Model from '/ckeditor5/core/ui/model.js';
+import Toolbar from '/ckeditor5/ui/toolbar/toolbar.js';
+import ToolbarView from '/ckeditor5/ui/toolbar/toolbarview.js';
+import Button from '/ckeditor5/ui/button/button.js';
+import ButtonView from '/ckeditor5/ui/button/buttonview.js';
 
 export default class ClassicCreator extends Creator {
 	constructor( editor ) {
@@ -19,8 +24,11 @@ export default class ClassicCreator extends Creator {
 	}
 
 	create() {
+		this._imitateFeatures();
+
 		this._replaceElement();
 		this._setupEditable();
+		this._setupToolbar();
 
 		return super.create()
 			.then( () => this.loadDataFromEditorElement() );
@@ -39,6 +47,14 @@ export default class ClassicCreator extends Creator {
 		this.editor.ui.add( 'main', editable );
 	}
 
+	_setupToolbar() {
+		const toolbar = new Toolbar( this.editor, new Model(), new ToolbarView() );
+
+		toolbar.addButtons( this.editor.config.toolbar );
+
+		this.editor.ui.collections.get( 'top' ).add( toolbar );
+	}
+
 	_createEditable() {
 		const editable = new FramedEditable( this.editor );
 		const editableView = new FramedEditableView( editable.viewModel );
@@ -56,4 +72,44 @@ export default class ClassicCreator extends Creator {
 
 		return editorUI;
 	}
+
+	/**
+	 * Immitates that some features were loaded and did their job.
+	 */
+	_imitateFeatures() {
+		const editor = this.editor;
+
+		const boldModel = new Model( {
+			isEnabled: true,
+			isOn: false,
+			label: 'bold'
+		} );
+
+		boldModel.on( 'executed', () => {
+			/* global console */
+			console.log( 'bold executed' );
+
+			boldModel.isOn = !boldModel.isOn;
+		} );
+
+		editor.ui.featureComponents.add( 'bold', Button, ButtonView, boldModel );
+
+		const italicModel = new Model( {
+			isEnabled: true,
+			isOn: false,
+			label: 'italic'
+		} );
+
+		italicModel.on( 'executed', () => {
+			/* global console */
+			console.log( 'italic executed' );
+
+			italicModel.isOn = !italicModel.isOn;
+		} );
+
+		editor.ui.featureComponents.add( 'italic', Button, ButtonView, italicModel );
+
+		window.boldModel = boldModel;
+		window.italicModel = italicModel;
+	}
 }

+ 4 - 0
packages/ckeditor5-engine/tests/creator/manual/creator-classic.html

@@ -1,3 +1,7 @@
+<head>
+	<link rel="stylesheet" href="%TEST_DIR%_assets/styles.css">
+</head>
+
 <div id="editor">
 	<h1>Hello world!</h1>
 	<p>This is an editor instance.</p>

+ 2 - 1
packages/ckeditor5-engine/tests/creator/manual/creator-classic.js

@@ -19,7 +19,8 @@ function initEditor() {
 		ui: {
 			width: 400,
 			height: 400
-		}
+		},
+		toolbar: [ 'bold', 'italic' ]
 	} )
 	.then( ( newEditor ) => {
 		console.log( 'Editor was initialized', newEditor );