浏览代码

WIP - WidgetToolbar.

Maciej Bukowski 7 年之前
父节点
当前提交
5a97db158d
共有 1 个文件被更改,包括 151 次插入0 次删除
  1. 151 0
      packages/ckeditor5-widget/src/widgettoolbar.js

+ 151 - 0
packages/ckeditor5-widget/src/widgettoolbar.js

@@ -0,0 +1,151 @@
+import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';
+import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';
+import BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';
+import { isWidget } from './utils';
+
+export default class WidgetToolbar extends Plugin {
+	/**
+	 * @inheritDoc
+	 */
+	static get requires() {
+		return [ ContextualBalloon ];
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	static get pluginName() {
+		return 'WidgetToolbar';
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	init() {
+		const editor = this.editor;
+		const balloonToolbar = editor.plugins.get( 'BalloonToolbar' );
+
+		// Disable the default balloon toolbar for all widgets.
+		this.listenTo( balloonToolbar, 'show', evt => {
+			if ( isWidgetSelected( editor.editing.view.document.selection ) ) {
+				evt.stop();
+			}
+		}, { priority: 'high' } );
+
+		this._balloon = this.editor.plugins.get( 'ContextualBalloon' );
+
+		this._toolbars = [];
+
+		this.listenTo( editor.ui, 'update', () => {
+			this._updateToolbars();
+		} );
+
+		// UI#update is not fired after focus is back in editor, we need to check if balloon panel should be visible.
+		this.listenTo( editor.ui.focusTracker, 'change:isFocused', () => {
+			this._updateToolbars();
+		}, { priority: 'low' } );
+	}
+
+	add( { toolbarItems, isSelected, balloonClassName = 'ck-toolbar-container' } ) {
+		const editor = this.editor;
+
+		if ( !toolbarItems ) {
+			return;
+		}
+
+		const toolbarView = new ToolbarView();
+
+		toolbarView.fillFromConfig( toolbarItems, editor.ui.componentFactory );
+
+		this._toolbars.push( {
+			view: toolbarView,
+			isSelected,
+			balloonClassName,
+		} );
+	}
+
+	_updateToolbars() {
+		for ( const toolbar of this._toolbars ) {
+			if ( !this.editor.ui.focusTracker.isFocused || !toolbar.isSelected( this.editor.editing.view.document.selection ) ) {
+				this._hideToolbar( toolbar );
+			} else {
+				this._showToolbar( toolbar );
+			}
+		}
+	}
+
+	_hideToolbar( toolbar ) {
+		if ( !this._isVisible( toolbar ) ) {
+			return;
+		}
+
+		this._balloon.remove( toolbar.view );
+	}
+
+	_showToolbar( toolbar ) {
+		if ( this._isVisible( toolbar ) ) {
+			repositionContextualBalloon( this.editor );
+		} else if ( !this._balloon.hasView( toolbar.view ) ) {
+			this._balloon.add( {
+				view: toolbar.view,
+				position: getBalloonPositionData( this.editor ),
+				balloonClassName: toolbar.balloonClassName,
+			} );
+		}
+	}
+
+	_isVisible( toolbar ) {
+		return this._balloon.visibleView == toolbar.view;
+	}
+}
+
+function repositionContextualBalloon( editor ) {
+	const balloon = editor.plugins.get( 'ContextualBalloon' );
+	const position = getBalloonPositionData( editor );
+
+	balloon.updatePosition( position );
+}
+
+function getBalloonPositionData( editor ) {
+	const editingView = editor.editing.view;
+	const defaultPositions = BalloonPanelView.defaultPositions;
+	let widget = getParentWidget( editingView.document.selection );
+
+	return {
+		target: editingView.domConverter.viewToDom( widget ),
+		positions: [
+			defaultPositions.northArrowSouth,
+			defaultPositions.northArrowSouthWest,
+			defaultPositions.northArrowSouthEast,
+			defaultPositions.southArrowNorth,
+			defaultPositions.southArrowNorthWest,
+			defaultPositions.southArrowNorthEast
+		]
+	};
+}
+
+function getParentWidget( selection ) {
+	const selectedElement = selection.getSelectedElement();
+
+	if ( selectedElement && isWidget( selectedElement ) ) {
+		return selectedElement;
+	}
+
+	const position = selection.getFirstPosition();
+	let parent = position.parent;
+
+	while ( parent ) {
+		if ( isWidget( parent ) ) {
+			return parent;
+		}
+
+		parent = parent.parent;
+	}
+}
+
+function isWidgetSelected( selection ) {
+	const viewElement = selection.getSelectedElement();
+
+	return !!( viewElement && isWidget( viewElement ) );
+}