2019-08-31 20:48:37 +03:00
|
|
|
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
|
|
|
|
|
import ClickObserver from '@ckeditor/ckeditor5-engine/src/view/observer/clickobserver';
|
|
|
|
|
import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';
|
|
|
|
|
import clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsidehandler';
|
|
|
|
|
|
|
|
|
|
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
|
|
|
|
|
import MainFormView from './ui/mainformview';
|
|
|
|
|
|
|
|
|
|
// Need math commands from there
|
|
|
|
|
import MathEditing from './mathediting';
|
2019-09-17 16:31:39 +03:00
|
|
|
import { defaultConfig } from './utils';
|
2019-08-31 20:48:37 +03:00
|
|
|
|
|
|
|
|
import pluginIcon from '../theme/icons/icon.svg';
|
|
|
|
|
|
|
|
|
|
const mathKeystroke = 'Ctrl+M';
|
|
|
|
|
|
|
|
|
|
export default class MathUI extends Plugin {
|
|
|
|
|
static get requires() {
|
|
|
|
|
return [ ContextualBalloon, MathEditing ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static get pluginName() {
|
|
|
|
|
return 'MathUI';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
init() {
|
|
|
|
|
const editor = this.editor;
|
|
|
|
|
editor.editing.view.addObserver( ClickObserver );
|
|
|
|
|
|
|
|
|
|
this._form = this._createFormView();
|
|
|
|
|
|
|
|
|
|
this._balloon = editor.plugins.get( ContextualBalloon );
|
|
|
|
|
|
|
|
|
|
this._createToolbarMathButton();
|
|
|
|
|
|
|
|
|
|
this._enableUserBalloonInteractions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
destroy() {
|
|
|
|
|
super.destroy();
|
|
|
|
|
|
|
|
|
|
this._form.destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_showUI() {
|
|
|
|
|
const editor = this.editor;
|
|
|
|
|
const mathCommand = editor.commands.get( 'math' );
|
|
|
|
|
|
|
|
|
|
if ( !mathCommand.isEnabled ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._addFormView();
|
|
|
|
|
|
|
|
|
|
this._balloon.showStack( 'main' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_createFormView() {
|
|
|
|
|
const editor = this.editor;
|
|
|
|
|
const mathCommand = editor.commands.get( 'math' );
|
2019-09-17 16:19:35 +03:00
|
|
|
|
2019-09-17 16:31:39 +03:00
|
|
|
const mathConfig = {
|
|
|
|
|
...defaultConfig,
|
|
|
|
|
...this.editor.config.get( 'math' )
|
|
|
|
|
}
|
2019-08-31 20:48:37 +03:00
|
|
|
|
2019-09-17 16:31:39 +03:00
|
|
|
const formView = new MainFormView( editor.locale, mathConfig.engine );
|
2019-08-31 20:48:37 +03:00
|
|
|
|
|
|
|
|
formView.mathInputView.bind( 'value' ).to( mathCommand, 'value' );
|
2019-09-17 15:47:58 +03:00
|
|
|
formView.displayButtonView.bind( 'displayIsOn' ).to( mathCommand, 'display');
|
2019-08-31 20:48:37 +03:00
|
|
|
|
2019-09-17 15:47:58 +03:00
|
|
|
// Listen to submit button click
|
2019-08-31 20:48:37 +03:00
|
|
|
this.listenTo( formView, 'submit', () => {
|
2019-09-17 15:47:58 +03:00
|
|
|
editor.execute( 'math', formView.equation, formView.displayButtonView.isOn );
|
2019-08-31 20:48:37 +03:00
|
|
|
this._closeFormView();
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
// Listen to cancel button click
|
|
|
|
|
this.listenTo( formView, 'cancel', () => {
|
|
|
|
|
this._closeFormView();
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
// Close plugin ui, if esc is pressed (while ui is focused)
|
|
|
|
|
formView.keystrokes.set( 'esc', ( data, cancel ) => {
|
|
|
|
|
this._closeFormView();
|
|
|
|
|
cancel();
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
return formView;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_addFormView() {
|
|
|
|
|
if ( this._isFormInPanel ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const editor = this.editor;
|
|
|
|
|
const mathCommand = editor.commands.get( 'math' );
|
|
|
|
|
|
|
|
|
|
this._balloon.add( {
|
|
|
|
|
view: this._form,
|
|
|
|
|
position: this._getBalloonPositionData(),
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
if ( this._balloon.visibleView === this._form ) {
|
|
|
|
|
this._form.mathInputView.select();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._form.equation = mathCommand.value || '';
|
2019-09-17 15:47:58 +03:00
|
|
|
this._form.displayButtonView.isOn = mathCommand.display || false;
|
2019-08-31 20:48:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_hideUI() {
|
|
|
|
|
if ( !this._isFormInPanel ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const editor = this.editor;
|
|
|
|
|
|
|
|
|
|
this.stopListening( editor.ui, 'update' );
|
|
|
|
|
this.stopListening( this._balloon, 'change:visibleView' );
|
|
|
|
|
|
|
|
|
|
editor.editing.view.focus();
|
|
|
|
|
|
|
|
|
|
// Remove form first because it's on top of the stack.
|
|
|
|
|
this._removeFormView();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_closeFormView() {
|
|
|
|
|
const mathCommand = this.editor.commands.get( 'math' );
|
|
|
|
|
if ( mathCommand.value !== undefined ) {
|
|
|
|
|
this._removeFormView();
|
|
|
|
|
} else {
|
|
|
|
|
this._hideUI();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_removeFormView() {
|
|
|
|
|
if ( this._isFormInPanel ) {
|
|
|
|
|
this._form.saveButtonView.focus();
|
|
|
|
|
|
|
|
|
|
this._balloon.remove( this._form );
|
|
|
|
|
|
|
|
|
|
this.editor.editing.view.focus();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_getBalloonPositionData() {
|
|
|
|
|
const view = this.editor.editing.view;
|
|
|
|
|
const viewDocument = view.document;
|
|
|
|
|
const target = view.domConverter.viewRangeToDom( viewDocument.selection.getFirstRange() );
|
|
|
|
|
return { target };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_createToolbarMathButton() {
|
|
|
|
|
const editor = this.editor;
|
|
|
|
|
const mathCommand = editor.commands.get( 'math' );
|
|
|
|
|
const t = editor.t;
|
|
|
|
|
|
|
|
|
|
// Handle the `Ctrl+M` keystroke and show the panel.
|
|
|
|
|
editor.keystrokes.set( mathKeystroke, ( keyEvtData, cancel ) => {
|
|
|
|
|
// Prevent focusing the search bar in FF and opening new tab in Edge. #153, #154.
|
|
|
|
|
cancel();
|
|
|
|
|
|
|
|
|
|
if ( mathCommand.isEnabled ) {
|
|
|
|
|
this._showUI();
|
|
|
|
|
}
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
this.editor.ui.componentFactory.add( 'math', locale => {
|
|
|
|
|
const button = new ButtonView( locale );
|
|
|
|
|
|
|
|
|
|
button.isEnabled = true;
|
|
|
|
|
button.label = t( 'Insert math' );
|
|
|
|
|
button.icon = pluginIcon;
|
|
|
|
|
button.keystroke = mathKeystroke;
|
|
|
|
|
button.tooltip = true;
|
|
|
|
|
button.isToggleable = true;
|
|
|
|
|
|
|
|
|
|
button.bind( 'isEnabled' ).to( mathCommand, 'isEnabled' );
|
|
|
|
|
|
|
|
|
|
this.listenTo( button, 'execute', () => this._showUI() );
|
|
|
|
|
|
|
|
|
|
return button;
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_enableUserBalloonInteractions() {
|
|
|
|
|
// Close the panel on the Esc key press when the editable has focus and the balloon is visible.
|
|
|
|
|
this.editor.keystrokes.set( 'Esc', ( data, cancel ) => {
|
|
|
|
|
if ( this._isUIVisible ) {
|
|
|
|
|
this._hideUI();
|
|
|
|
|
cancel();
|
|
|
|
|
}
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
// Close on click outside of balloon panel element.
|
|
|
|
|
clickOutsideHandler( {
|
|
|
|
|
emitter: this._form,
|
|
|
|
|
activator: () => this._isFormInPanel,
|
|
|
|
|
contextElements: [ this._balloon.view.element ],
|
|
|
|
|
callback: () => this._hideUI()
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get _isUIVisible() {
|
|
|
|
|
const visibleView = this._balloon.visibleView;
|
|
|
|
|
|
|
|
|
|
return visibleView == this._form;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get _isFormInPanel() {
|
|
|
|
|
return this._balloon.hasView( this._form );
|
|
|
|
|
}
|
|
|
|
|
}
|