@@ -131,11 +131,14 @@ export default class ContextualToolbar extends Plugin {
131131 /**
132132 * Adds panel view to the {@link : #_balloon} and attaches panel to the selection.
133133 *
134+ * Fires {@link #event:beforeShow} event just before displaying the panel.
135+ *
134136 * @protected
135137 * @return {Promise } A promise resolved when the {@link #toolbarView} {@link module:ui/view~View#init} is done.
136138 */
137139 _showPanel ( ) {
138140 const editingView = this . editor . editing . view ;
141+ let isStopped = false ;
139142
140143 // Do not add toolbar to the balloon stack twice.
141144 if ( this . _balloon . hasView ( this . toolbarView ) ) {
@@ -147,17 +150,39 @@ export default class ContextualToolbar extends Plugin {
147150 return Promise . resolve ( ) ;
148151 }
149152
150- // Update panel position when selection changes while balloon will be opened (by a collaboration).
151- this . listenTo ( this . editor . editing . view , 'render' , ( ) => {
152- this . _balloon . updatePosition ( this . _getBalloonPositionData ( ) ) ;
153+ const showPromise = new Promise ( ( resolve ) => {
154+ // If `beforeShow` event is not stopped by any external code then panel will be displayed.
155+ this . once ( 'beforeShow' , ( ) => {
156+ if ( isStopped ) {
157+ resolve ( ) ;
158+
159+ return ;
160+ }
161+
162+ // Update panel position when selection changes while balloon will be opened
163+ // (by an external document changes).
164+ this . listenTo ( editingView , 'render' , ( ) => {
165+ this . _balloon . updatePosition ( this . _getBalloonPositionData ( ) ) ;
166+ } ) ;
167+
168+ resolve (
169+ // Add panel to the common editor contextual balloon.
170+ this . _balloon . add ( {
171+ view : this . toolbarView ,
172+ position : this . _getBalloonPositionData ( ) ,
173+ balloonClassName : 'ck-toolbar-container'
174+ } )
175+ ) ;
176+ } ) ;
177+ } , { priority : 'lowest' } ) ;
178+
179+ // Fire this event to inform that `ContextualToolbar` is going to be shown.
180+ // Helper function for preventing the panel from being displayed is passed along with the event.
181+ this . fire ( 'beforeShow' , ( ) => {
182+ isStopped = true ;
153183 } ) ;
154184
155- // Add panel to the common editor contextual balloon.
156- return this . _balloon . add ( {
157- view : this . toolbarView ,
158- position : this . _getBalloonPositionData ( ) ,
159- balloonClassName : 'ck-toolbar-container'
160- } ) ;
185+ return showPromise ;
161186 }
162187
163188 /**
@@ -210,6 +235,15 @@ export default class ContextualToolbar extends Plugin {
210235 super . destroy ( ) ;
211236 }
212237
238+ /**
239+ * This event is fired just before the toolbar shows.
240+ * Using this event, an external code can prevent ContextualToolbar
241+ * from being displayed by calling a `stop` function which is passed along with this event.
242+ *
243+ * @event beforeShow
244+ * @param {Function } stop Calling this function prevents panel from being displayed.
245+ */
246+
213247 /**
214248 * This is internal plugin event which is fired 200 ms after model selection last change.
215249 * This is to makes easy test debounced action without need to use `setTimeout`.
0 commit comments