@@ -25,6 +25,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
25
25
import { IContextMenuService , IContextViewService } from 'vs/platform/contextview/browser/contextView' ;
26
26
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding' ;
27
27
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry' ;
28
+ import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
28
29
29
30
export class ContextMenuController implements IEditorContribution {
30
31
@@ -44,7 +45,8 @@ export class ContextMenuController implements IEditorContribution {
44
45
@IContextViewService private readonly _contextViewService : IContextViewService ,
45
46
@IContextKeyService private readonly _contextKeyService : IContextKeyService ,
46
47
@IKeybindingService private readonly _keybindingService : IKeybindingService ,
47
- @IMenuService private readonly _menuService : IMenuService
48
+ @IMenuService private readonly _menuService : IMenuService ,
49
+ @IConfigurationService private readonly _configurationService : IConfigurationService ,
48
50
) {
49
51
this . _editor = editor ;
50
52
@@ -98,6 +100,10 @@ export class ContextMenuController implements IEditorContribution {
98
100
e . event . preventDefault ( ) ;
99
101
e . event . stopPropagation ( ) ;
100
102
103
+ if ( e . target . type === MouseTargetType . SCROLLBAR ) {
104
+ return this . _showScrollbarContextMenu ( { x : e . event . posx - 1 , width : 2 , y : e . event . posy - 1 , height : 2 } ) ;
105
+ }
106
+
101
107
if ( e . target . type !== MouseTargetType . CONTENT_TEXT && e . target . type !== MouseTargetType . CONTENT_EMPTY && e . target . type !== MouseTargetType . TEXTAREA ) {
102
108
return ; // only support mouse click into text or native context menu key for now
103
109
}
@@ -138,11 +144,6 @@ export class ContextMenuController implements IEditorContribution {
138
144
return ;
139
145
}
140
146
141
- if ( ! this . _contextMenuService ) {
142
- this . _editor . focus ( ) ;
143
- return ; // We need the context menu service to function
144
- }
145
-
146
147
// Find actions available for menu
147
148
const menuActions = this . _getMenuActions ( this . _editor . getModel ( ) ,
148
149
this . _editor . isSimpleWidget ? MenuId . SimpleEditorContext : MenuId . EditorContext ) ;
@@ -257,6 +258,133 @@ export class ContextMenuController implements IEditorContribution {
257
258
} ) ;
258
259
}
259
260
261
+ private _showScrollbarContextMenu ( anchor : IAnchor ) : void {
262
+ if ( ! this . _editor . hasModel ( ) ) {
263
+ return ;
264
+ }
265
+
266
+ const minimapOptions = this . _editor . getOption ( EditorOption . minimap ) ;
267
+
268
+ let lastId = 0 ;
269
+ const createAction = ( opts : { label : string ; enabled ?: boolean ; checked ?: boolean ; run : ( ) => void } ) : IAction => {
270
+ return {
271
+ id : `menu-action-${ ++ lastId } ` ,
272
+ label : opts . label ,
273
+ tooltip : '' ,
274
+ class : undefined ,
275
+ enabled : ( typeof opts . enabled === 'undefined' ? true : opts . enabled ) ,
276
+ checked : opts . checked ,
277
+ run : opts . run ,
278
+ dispose : ( ) => null
279
+ } ;
280
+ } ;
281
+ const createSubmenuAction = ( label : string , actions : IAction [ ] ) : SubmenuAction => {
282
+ return new SubmenuAction (
283
+ `menu-action-${ ++ lastId } ` ,
284
+ label ,
285
+ actions ,
286
+ undefined
287
+ ) ;
288
+ } ;
289
+ const createEnumAction = < T > ( label : string , enabled : boolean , configName : string , configuredValue : T , options : { label : string ; value : T } [ ] ) : IAction => {
290
+ if ( ! enabled ) {
291
+ return createAction ( { label, enabled, run : ( ) => { } } ) ;
292
+ }
293
+ const createRunner = ( value : T ) => {
294
+ return ( ) => {
295
+ this . _configurationService . updateValue ( configName , value ) ;
296
+ } ;
297
+ } ;
298
+ const actions : IAction [ ] = [ ] ;
299
+ for ( const option of options ) {
300
+ actions . push ( createAction ( {
301
+ label : option . label ,
302
+ checked : configuredValue === option . value ,
303
+ run : createRunner ( option . value )
304
+ } ) ) ;
305
+ }
306
+ return createSubmenuAction (
307
+ label ,
308
+ actions
309
+ ) ;
310
+ } ;
311
+
312
+ const actions : IAction [ ] = [ ] ;
313
+ actions . push ( createAction ( {
314
+ label : nls . localize ( 'context.minimap.showMinimap' , "Show Minimap" ) ,
315
+ checked : minimapOptions . enabled ,
316
+ run : ( ) => {
317
+ this . _configurationService . updateValue ( `editor.minimap.enabled` , ! minimapOptions . enabled ) ;
318
+ }
319
+ } ) ) ;
320
+ actions . push ( new Separator ( ) ) ;
321
+ actions . push ( createAction ( {
322
+ label : nls . localize ( 'context.minimap.renderCharacters' , "Render Characters" ) ,
323
+ enabled : minimapOptions . enabled ,
324
+ checked : minimapOptions . renderCharacters ,
325
+ run : ( ) => {
326
+ this . _configurationService . updateValue ( `editor.minimap.renderCharacters` , ! minimapOptions . renderCharacters ) ;
327
+ }
328
+ } ) ) ;
329
+ actions . push ( createEnumAction < 'proportional' | 'fill' | 'fit' > (
330
+ nls . localize ( 'context.minimap.size' , "Size" ) ,
331
+ minimapOptions . enabled ,
332
+ 'editor.minimap.size' ,
333
+ minimapOptions . size ,
334
+ [ {
335
+ label : nls . localize ( 'context.minimap.size.proportional' , "Proportional" ) ,
336
+ value : 'proportional'
337
+ } , {
338
+ label : nls . localize ( 'context.minimap.size.fill' , "Fill" ) ,
339
+ value : 'fill'
340
+ } , {
341
+ label : nls . localize ( 'context.minimap.size.fit' , "Fit" ) ,
342
+ value : 'fit'
343
+ } ]
344
+ ) ) ;
345
+ actions . push ( createEnumAction < number > (
346
+ nls . localize ( 'context.minimap.scale' , "Scale" ) ,
347
+ minimapOptions . enabled ,
348
+ 'editor.minimap.scale' ,
349
+ minimapOptions . scale ,
350
+ [ {
351
+ label : nls . localize ( 'context.minimap.scale.1' , "1" ) ,
352
+ value : 1
353
+ } , {
354
+ label : nls . localize ( 'context.minimap.scale.2' , "2" ) ,
355
+ value : 2
356
+ } , {
357
+ label : nls . localize ( 'context.minimap.scale.3' , "3" ) ,
358
+ value : 3
359
+ } ]
360
+ ) ) ;
361
+ actions . push ( createEnumAction < 'always' | 'mouseover' > (
362
+ nls . localize ( 'context.minimap.slider' , "Slider" ) ,
363
+ minimapOptions . enabled ,
364
+ 'editor.minimap.showSlider' ,
365
+ minimapOptions . showSlider ,
366
+ [ {
367
+ label : nls . localize ( 'context.minimap.slider.mouseover' , "Mouse Over" ) ,
368
+ value : 'mouseover'
369
+ } , {
370
+ label : nls . localize ( 'context.minimap.slider.always' , "Always" ) ,
371
+ value : 'always'
372
+ } ]
373
+ ) ) ;
374
+
375
+ const useShadowDOM = this . _editor . getOption ( EditorOption . useShadowDOM ) && ! isIOS ; // Do not use shadow dom on IOS #122035
376
+ this . _contextMenuIsBeingShownCount ++ ;
377
+ this . _contextMenuService . showContextMenu ( {
378
+ domForShadowRoot : useShadowDOM ? this . _editor . getDomNode ( ) : undefined ,
379
+ getAnchor : ( ) => anchor ,
380
+ getActions : ( ) => actions ,
381
+ onHide : ( wasCancelled : boolean ) => {
382
+ this . _contextMenuIsBeingShownCount -- ;
383
+ this . _editor . focus ( ) ;
384
+ }
385
+ } ) ;
386
+ }
387
+
260
388
private _keybindingFor ( action : IAction ) : ResolvedKeybinding | undefined {
261
389
return this . _keybindingService . lookupKeybinding ( action . id ) ;
262
390
}
0 commit comments