17
17
import debounce = require( 'lodash.debounce' ) ;
18
18
import { inject , injectable , named } from 'inversify' ;
19
19
// eslint-disable-next-line max-len
20
- import { CommandMenuNode , CommandRegistry , CompoundMenuNode , ContributionProvider , Disposable , DisposableCollection , Emitter , Event , MenuModelRegistry , MenuPath } from '../../../common' ;
20
+ import { CommandMenuNode , CommandRegistry , CompoundMenuNode , ContributionProvider , Disposable , DisposableCollection , Emitter , Event , MenuModelRegistry , MenuNode , MenuPath } from '../../../common' ;
21
21
import { ContextKeyService } from '../../context-key-service' ;
22
22
import { FrontendApplicationContribution } from '../../frontend-application' ;
23
23
import { Widget } from '../../widgets' ;
24
- import { MenuDelegate , ReactTabBarToolbarItem , TabBarToolbarItem } from './tab-bar-toolbar-types' ;
24
+ import { AnyToolbarItem , ConditionalToolbarItem , MenuDelegate , MenuToolbarItem , ReactTabBarToolbarItem , TabBarToolbarItem } from './tab-bar-toolbar-types' ;
25
25
import { ToolbarMenuNodeWrapper } from './tab-bar-toolbar-menu-adapters' ;
26
26
27
27
/**
@@ -103,10 +103,7 @@ export class TabBarToolbarRegistry implements FrontendApplicationContribution {
103
103
}
104
104
const result : Array < TabBarToolbarItem | ReactTabBarToolbarItem > = [ ] ;
105
105
for ( const item of this . items . values ( ) ) {
106
- const visible = TabBarToolbarItem . is ( item )
107
- ? this . commandRegistry . isVisible ( item . command , widget )
108
- : ( ! item . isVisible || item . isVisible ( widget ) ) ;
109
- if ( visible && ( ! item . when || this . contextKeyService . match ( item . when , widget . node ) ) ) {
106
+ if ( this . isItemVisible ( item , widget ) ) {
110
107
result . push ( item ) ;
111
108
}
112
109
}
@@ -139,6 +136,83 @@ export class TabBarToolbarRegistry implements FrontendApplicationContribution {
139
136
return result ;
140
137
}
141
138
139
+ /**
140
+ * Query whether a toolbar `item` should be shown in the toolbar.
141
+ * This implementation delegates to item-specific checks according to their type.
142
+ *
143
+ * @param item a menu toolbar item
144
+ * @param widget the widget that is updating the toolbar
145
+ * @returns `false` if the `item` should be suppressed, otherwise `true`
146
+ */
147
+ protected isItemVisible ( item : TabBarToolbarItem | ReactTabBarToolbarItem , widget : Widget ) : boolean {
148
+ if ( TabBarToolbarItem . is ( item ) && item . command && ! this . isTabBarToolbarItemVisible ( item , widget ) ) {
149
+ return false ;
150
+ }
151
+ if ( MenuToolbarItem . is ( item ) && ! this . isMenuToolbarItemVisible ( item , widget ) ) {
152
+ return false ;
153
+ }
154
+ if ( AnyToolbarItem . isConditional ( item ) && ! this . isConditionalItemVisible ( item , widget ) ) {
155
+ return false ;
156
+ }
157
+ // The item is not vetoed. Accept it
158
+ return true ;
159
+ }
160
+
161
+ /**
162
+ * Query whether a conditional toolbar `item` should be shown in the toolbar.
163
+ * This implementation delegates to the `item`'s own intrinsic conditionality.
164
+ *
165
+ * @param item a menu toolbar item
166
+ * @param widget the widget that is updating the toolbar
167
+ * @returns `false` if the `item` should be suppressed, otherwise `true`
168
+ */
169
+ protected isConditionalItemVisible ( item : ConditionalToolbarItem , widget : Widget ) : boolean {
170
+ if ( item . isVisible && ! item . isVisible ( widget ) ) {
171
+ return false ;
172
+ }
173
+ if ( item . when && ! this . contextKeyService . match ( item . when , widget . node ) ) {
174
+ return false ;
175
+ }
176
+ return true ;
177
+ }
178
+
179
+ /**
180
+ * Query whether a tab-bar toolbar `item` that has a command should be shown in the toolbar.
181
+ * This implementation returns `false` if the `item`'s command is not visible in the
182
+ * `widget` according to the command registry.
183
+ *
184
+ * @param item a tab-bar toolbar item that has a non-empty `command`
185
+ * @param widget the widget that is updating the toolbar
186
+ * @returns `false` if the `item` should be suppressed, otherwise `true`
187
+ */
188
+ protected isTabBarToolbarItemVisible ( item : TabBarToolbarItem , widget : Widget ) : boolean {
189
+ return this . commandRegistry . isVisible ( item . command , widget ) ;
190
+ }
191
+
192
+ /**
193
+ * Query whether a menu toolbar `item` should be shown in the toolbar.
194
+ * This implementation returns `false` if the `item` does not have any actual menu to show.
195
+ *
196
+ * @param item a menu toolbar item
197
+ * @param widget the widget that is updating the toolbar
198
+ * @returns `false` if the `item` should be suppressed, otherwise `true`
199
+ */
200
+ protected isMenuToolbarItemVisible ( item : MenuToolbarItem , widget : Widget ) : boolean {
201
+ const menu = this . menuRegistry . getMenu ( item . menuPath ) ;
202
+ const isVisible : ( node : MenuNode ) => boolean = node =>
203
+ node . children ?. length
204
+ // Either the node is a sub-menu that has some visible child ...
205
+ ? node . children ?. some ( isVisible )
206
+ // ... or there is a command ...
207
+ : ! ! node . command
208
+ // ... that is visible ...
209
+ && this . commandRegistry . isVisible ( node . command , widget )
210
+ // ... and a "when" clause does not suppress the menu node.
211
+ && ( ! node . when || this . contextKeyService . match ( node . when , widget ?. node ) ) ;
212
+
213
+ return isVisible ( menu ) ;
214
+ }
215
+
142
216
unregisterItem ( itemOrId : TabBarToolbarItem | ReactTabBarToolbarItem | string ) : void {
143
217
const id = typeof itemOrId === 'string' ? itemOrId : itemOrId . id ;
144
218
if ( this . items . delete ( id ) ) {
@@ -147,7 +221,7 @@ export class TabBarToolbarRegistry implements FrontendApplicationContribution {
147
221
}
148
222
149
223
registerMenuDelegate ( menuPath : MenuPath , when ?: string | ( ( widget : Widget ) => boolean ) ) : Disposable {
150
- const id = menuPath . join ( menuDelegateSeparator ) ;
224
+ const id = this . toElementId ( menuPath ) ;
151
225
if ( ! this . menuDelegates . has ( id ) ) {
152
226
const isVisible : MenuDelegate [ 'isVisible' ] = ! when
153
227
? yes
@@ -163,8 +237,20 @@ export class TabBarToolbarRegistry implements FrontendApplicationContribution {
163
237
}
164
238
165
239
unregisterMenuDelegate ( menuPath : MenuPath ) : void {
166
- if ( this . menuDelegates . delete ( menuPath . join ( menuDelegateSeparator ) ) ) {
240
+ if ( this . menuDelegates . delete ( this . toElementId ( menuPath ) ) ) {
167
241
this . fireOnDidChange ( ) ;
168
242
}
169
243
}
244
+
245
+ /**
246
+ * Generate a single ID string from a menu path that
247
+ * is likely to be unique amongst the items in the toolbar.
248
+ *
249
+ * @param menuPath a menubar path
250
+ * @returns a likely unique ID based on the path
251
+ */
252
+ toElementId ( menuPath : MenuPath ) : string {
253
+ return menuPath . join ( menuDelegateSeparator ) ;
254
+ }
255
+
170
256
}
0 commit comments