5
5
6
6
import { Action , IAction , Separator , SubmenuAction } from 'vs/base/common/actions' ;
7
7
import { CSSIcon } from 'vs/base/common/codicons' ;
8
- import { Emitter , Event } from 'vs/base/common/event' ;
9
- import { Iterable } from 'vs/base/common/iterator' ;
8
+ import { Event , MicrotaskEmitter } from 'vs/base/common/event' ;
10
9
import { DisposableStore , IDisposable , toDisposable } from 'vs/base/common/lifecycle' ;
11
10
import { LinkedList } from 'vs/base/common/linkedList' ;
12
11
import { ICommandAction , ICommandActionTitle , Icon , ILocalizedString } from 'vs/platform/action/common/action' ;
@@ -234,12 +233,46 @@ export interface IMenuRegistryChangeEvent {
234
233
has ( id : MenuId ) : boolean ;
235
234
}
236
235
236
+ class MenuRegistryChangeEvent {
237
+
238
+ private static _all = new Map < MenuId , MenuRegistryChangeEvent > ( ) ;
239
+
240
+ static for ( id : MenuId ) : MenuRegistryChangeEvent {
241
+ let value = this . _all . get ( id ) ;
242
+ if ( ! value ) {
243
+ value = new MenuRegistryChangeEvent ( id ) ;
244
+ this . _all . set ( id , value ) ;
245
+ }
246
+ return value ;
247
+ }
248
+
249
+ static merge ( events : IMenuRegistryChangeEvent [ ] ) : IMenuRegistryChangeEvent {
250
+ const ids = new Set < MenuId > ( ) ;
251
+ for ( const item of events ) {
252
+ if ( item instanceof MenuRegistryChangeEvent ) {
253
+ ids . add ( item . id ) ;
254
+ }
255
+ }
256
+ return ids ;
257
+ }
258
+
259
+ readonly has : ( id : MenuId ) => boolean ;
260
+
261
+ private constructor ( private readonly id : MenuId ) {
262
+ this . has = candidate => candidate === id ;
263
+ }
264
+ }
265
+
237
266
export interface IMenuRegistry {
238
267
readonly onDidChangeMenu : Event < IMenuRegistryChangeEvent > ;
239
- addCommands ( newCommands : Iterable < ICommandAction > ) : IDisposable ;
240
268
addCommand ( userCommand : ICommandAction ) : IDisposable ;
241
269
getCommand ( id : string ) : ICommandAction | undefined ;
242
270
getCommands ( ) : ICommandsMap ;
271
+
272
+ /**
273
+ * @deprecated Use `appendMenuItem` or most likely use `registerAction2` instead. There should be no strong
274
+ * reason to use this directly.
275
+ */
243
276
appendMenuItems ( items : Iterable < { id : MenuId ; item : IMenuItem | ISubmenuItem } > ) : IDisposable ;
244
277
appendMenuItem ( menu : MenuId , item : IMenuItem | ISubmenuItem ) : IDisposable ;
245
278
getMenuItems ( loc : MenuId ) : Array < IMenuItem | ISubmenuItem > ;
@@ -249,30 +282,19 @@ export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry {
249
282
250
283
private readonly _commands = new Map < string , ICommandAction > ( ) ;
251
284
private readonly _menuItems = new Map < MenuId , LinkedList < IMenuItem | ISubmenuItem > > ( ) ;
252
- private readonly _onDidChangeMenu = new Emitter < IMenuRegistryChangeEvent > ( ) ;
285
+ private readonly _onDidChangeMenu = new MicrotaskEmitter < IMenuRegistryChangeEvent > ( {
286
+ merge : MenuRegistryChangeEvent . merge
287
+ } ) ;
253
288
254
289
readonly onDidChangeMenu : Event < IMenuRegistryChangeEvent > = this . _onDidChangeMenu . event ;
255
290
256
291
addCommand ( command : ICommandAction ) : IDisposable {
257
- return this . addCommands ( Iterable . single ( command ) ) ;
258
- }
259
-
260
- private readonly _commandPaletteChangeEvent : IMenuRegistryChangeEvent = {
261
- has : id => id === MenuId . CommandPalette
262
- } ;
292
+ this . _commands . set ( command . id , command ) ;
293
+ this . _onDidChangeMenu . fire ( MenuRegistryChangeEvent . for ( MenuId . CommandPalette ) ) ;
263
294
264
- addCommands ( commands : Iterable < ICommandAction > ) : IDisposable {
265
- for ( const command of commands ) {
266
- this . _commands . set ( command . id , command ) ;
267
- }
268
- this . _onDidChangeMenu . fire ( this . _commandPaletteChangeEvent ) ;
269
295
return toDisposable ( ( ) => {
270
- let didChange = false ;
271
- for ( const command of commands ) {
272
- didChange = this . _commands . delete ( command . id ) || didChange ;
273
- }
274
- if ( didChange ) {
275
- this . _onDidChangeMenu . fire ( this . _commandPaletteChangeEvent ) ;
296
+ if ( this . _commands . delete ( command . id ) ) {
297
+ this . _onDidChangeMenu . fire ( MenuRegistryChangeEvent . for ( MenuId . CommandPalette ) ) ;
276
298
}
277
299
} ) ;
278
300
}
@@ -288,35 +310,22 @@ export const MenuRegistry: IMenuRegistry = new class implements IMenuRegistry {
288
310
}
289
311
290
312
appendMenuItem ( id : MenuId , item : IMenuItem | ISubmenuItem ) : IDisposable {
291
- return this . appendMenuItems ( Iterable . single ( { id, item } ) ) ;
313
+ let list = this . _menuItems . get ( id ) ;
314
+ if ( ! list ) {
315
+ list = new LinkedList ( ) ;
316
+ this . _menuItems . set ( id , list ) ;
317
+ }
318
+ const rm = list . push ( item ) ;
319
+ this . _onDidChangeMenu . fire ( MenuRegistryChangeEvent . for ( id ) ) ;
320
+ return toDisposable ( rm ) ;
292
321
}
293
322
294
323
appendMenuItems ( items : Iterable < { id : MenuId ; item : IMenuItem | ISubmenuItem } > ) : IDisposable {
295
-
296
- const changedIds = new Set < MenuId > ( ) ;
297
- const toRemove = new LinkedList < Function > ( ) ;
298
-
324
+ const result = new DisposableStore ( ) ;
299
325
for ( const { id, item } of items ) {
300
- let list = this . _menuItems . get ( id ) ;
301
- if ( ! list ) {
302
- list = new LinkedList ( ) ;
303
- this . _menuItems . set ( id , list ) ;
304
- }
305
- toRemove . push ( list . push ( item ) ) ;
306
- changedIds . add ( id ) ;
326
+ result . add ( this . appendMenuItem ( id , item ) ) ;
307
327
}
308
-
309
- this . _onDidChangeMenu . fire ( changedIds ) ;
310
-
311
- return toDisposable ( ( ) => {
312
- if ( toRemove . size > 0 ) {
313
- for ( const fn of toRemove ) {
314
- fn ( ) ;
315
- }
316
- this . _onDidChangeMenu . fire ( changedIds ) ;
317
- toRemove . clear ( ) ;
318
- }
319
- } ) ;
328
+ return result ;
320
329
}
321
330
322
331
getMenuItems ( id : MenuId ) : Array < IMenuItem | ISubmenuItem > {
@@ -568,7 +577,9 @@ export function registerAction2(ctor: { new(): Action2 }): IDisposable {
568
577
569
578
// menu
570
579
if ( Array . isArray ( menu ) ) {
571
- disposables . add ( MenuRegistry . appendMenuItems ( menu . map ( item => ( { id : item . id , item : { command, ...item } } ) ) ) ) ;
580
+ for ( const item of menu ) {
581
+ disposables . add ( MenuRegistry . appendMenuItem ( item . id , { command, ...item } ) ) ;
582
+ }
572
583
573
584
} else if ( menu ) {
574
585
disposables . add ( MenuRegistry . appendMenuItem ( menu . id , { command, ...menu } ) ) ;
0 commit comments