Skip to content

Commit 85dd134

Browse files
committed
improve dropdown menu placement for sidebar parts
1 parent 3af878c commit 85dd134

9 files changed

Lines changed: 40 additions & 9 deletions

File tree

src/vs/base/browser/contextmenu.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { IAction, IActionRunner } from 'vs/base/common/actions';
77
import { IActionItem } from 'vs/base/browser/ui/actionbar/actionbar';
88
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
99
import { SubmenuAction } from 'vs/base/browser/ui/menu/menu';
10+
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
1011

1112
export interface IContextMenuEvent {
1213
shiftKey?: boolean;
@@ -31,4 +32,5 @@ export interface IContextMenuDelegate {
3132
onHide?(didCancel: boolean): void;
3233
actionRunner?: IActionRunner;
3334
autoSelectFirstItem?: boolean;
35+
anchorAlignment?: AnchorAlignment;
3436
}

src/vs/base/browser/ui/dropdown/dropdown.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Gesture, EventType as GestureEventType } from 'vs/base/browser/touch';
88
import { ActionRunner, IAction, IActionRunner } from 'vs/base/common/actions';
99
import { BaseActionItem, IActionItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
1010
import { IDisposable } from 'vs/base/common/lifecycle';
11-
import { IContextViewProvider, IAnchor } from 'vs/base/browser/ui/contextview/contextview';
11+
import { IContextViewProvider, IAnchor, AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
1212
import { IMenuOptions } from 'vs/base/browser/ui/menu/menu';
1313
import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes';
1414
import { EventHelper, EventType, removeClass, addClass, append, $, addDisposableListener, addClasses } from 'vs/base/browser/dom';
@@ -249,7 +249,8 @@ export class DropdownMenu extends BaseDropdown {
249249
getKeyBinding: action => this.menuOptions && this.menuOptions.getKeyBinding ? this.menuOptions.getKeyBinding(action) : null,
250250
getMenuClassName: () => this.menuClassName,
251251
onHide: () => this.onHide(),
252-
actionRunner: this.menuOptions ? this.menuOptions.actionRunner : null
252+
actionRunner: this.menuOptions ? this.menuOptions.actionRunner : null,
253+
anchorAlignment: this.menuOptions.anchorAlignment
253254
});
254255
}
255256

@@ -270,10 +271,11 @@ export class DropdownMenuActionItem extends BaseActionItem {
270271
private actionItemProvider: IActionItemProvider;
271272
private keybindings: (action: IAction) => ResolvedKeybinding;
272273
private clazz: string;
274+
private anchorAlignmentProvider: () => AnchorAlignment;
273275

274-
constructor(action: IAction, menuActions: IAction[], contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider, actionRunner: IActionRunner, keybindings: (action: IAction) => ResolvedKeybinding, clazz: string);
275-
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider, actionRunner: IActionRunner, keybindings: (action: IAction) => ResolvedKeybinding, clazz: string);
276-
constructor(action: IAction, menuActionsOrProvider: any, contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider, actionRunner: IActionRunner, keybindings: (action: IAction) => ResolvedKeybinding, clazz: string) {
276+
constructor(action: IAction, menuActions: IAction[], contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider, actionRunner: IActionRunner, keybindings: (action: IAction) => ResolvedKeybinding, clazz: string, anchorAlignmentProvider?: () => AnchorAlignment);
277+
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider, actionRunner: IActionRunner, keybindings: (action: IAction) => ResolvedKeybinding, clazz: string, anchorAlignmentProvider?: () => AnchorAlignment);
278+
constructor(action: IAction, menuActionsOrProvider: any, contextMenuProvider: IContextMenuProvider, actionItemProvider: IActionItemProvider, actionRunner: IActionRunner, keybindings: (action: IAction) => ResolvedKeybinding, clazz: string, anchorAlignmentProvider?: () => AnchorAlignment) {
277279
super(null, action);
278280

279281
this.menuActionsOrProvider = menuActionsOrProvider;
@@ -282,6 +284,7 @@ export class DropdownMenuActionItem extends BaseActionItem {
282284
this.actionRunner = actionRunner;
283285
this.keybindings = keybindings;
284286
this.clazz = clazz;
287+
this.anchorAlignmentProvider = anchorAlignmentProvider;
285288
}
286289

287290
render(container: HTMLElement): void {
@@ -311,11 +314,15 @@ export class DropdownMenuActionItem extends BaseActionItem {
311314

312315
this.dropdownMenu = this._register(new DropdownMenu(container, options));
313316

317+
const that = this;
314318
this.dropdownMenu.menuOptions = {
315319
actionItemProvider: this.actionItemProvider,
316320
actionRunner: this.actionRunner,
317321
getKeyBinding: this.keybindings,
318-
context: this._context
322+
context: this._context,
323+
get anchorAlignment(): AnchorAlignment {
324+
return that.anchorAlignmentProvider();
325+
}
319326
};
320327
}
321328

src/vs/base/browser/ui/menu/menu.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
1414
import { RunOnceScheduler } from 'vs/base/common/async';
1515
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
1616
import { Color } from 'vs/base/common/color';
17+
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
1718

1819
export const MENU_MNEMONIC_REGEX: RegExp = /\(&{1,2}(.)\)|&{1,2}(.)/;
1920
export const MENU_ESCAPED_MNEMONIC_REGEX: RegExp = /(?:&){1,2}(.)/;
@@ -25,6 +26,7 @@ export interface IMenuOptions {
2526
getKeyBinding?: (action: IAction) => ResolvedKeybinding;
2627
ariaLabel?: string;
2728
enableMnemonics?: boolean;
29+
anchorAlignment?: AnchorAlignment;
2830
}
2931

3032
export interface IMenuStyles {

src/vs/base/browser/ui/toolbar/toolbar.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ActionBar, ActionsOrientation, IActionItemProvider } from 'vs/base/brow
1010
import { IContextMenuProvider, DropdownMenuActionItem } from 'vs/base/browser/ui/dropdown/dropdown';
1111
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
1212
import { Disposable } from 'vs/base/common/lifecycle';
13+
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
1314

1415
export const CONTEXT = 'context.toolbar';
1516

@@ -20,6 +21,7 @@ export interface IToolBarOptions {
2021
getKeyBinding?: (action: IAction) => ResolvedKeybinding;
2122
actionRunner?: IActionRunner;
2223
toggleMenuTitle?: string;
24+
anchorAlignmentProvider?: () => AnchorAlignment;
2325
}
2426

2527
/**
@@ -67,7 +69,8 @@ export class ToolBar extends Disposable {
6769
this.options.actionItemProvider,
6870
this.actionRunner,
6971
this.options.getKeyBinding,
70-
'toolbar-toggle-more'
72+
'toolbar-toggle-more',
73+
this.options.anchorAlignmentProvider
7174
);
7275
this.toggleMenuActionItem.setActionContext(this.actionBar.context);
7376

src/vs/platform/contextview/browser/contextMenuHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export class ContextMenuHandler {
6060
this.contextViewService.showContextView({
6161
getAnchor: () => delegate.getAnchor(),
6262
canRelayout: false,
63+
anchorAlignment: delegate.anchorAlignment,
6364

6465
render: (container) => {
6566
this.menuContainerElement = container;

src/vs/platform/contextview/browser/contextView.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
77
import { Event } from 'vs/base/common/event';
88
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
99
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
10+
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
1011

1112
export const IContextViewService = createDecorator<IContextViewService>('contextViewService');
1213

@@ -17,6 +18,7 @@ export interface IContextViewService {
1718
showContextView(delegate: IContextViewDelegate): void;
1819
hideContextView(data?: any): void;
1920
layout(): void;
21+
anchorAlignment?: AnchorAlignment;
2022
}
2123

2224
export interface IContextViewDelegate {
@@ -27,6 +29,7 @@ export interface IContextViewDelegate {
2729
render(container: HTMLElement): IDisposable;
2830
onDOMEvent?(e: any, activeElement: HTMLElement): void;
2931
onHide?(data?: any): void;
32+
anchorAlignment?: AnchorAlignment;
3033
}
3134

3235
export const IContextMenuService = createDecorator<IContextMenuService>('contextMenuService');

src/vs/workbench/browser/parts/compositePart.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
3131
import { attachProgressBarStyler } from 'vs/platform/theme/common/styler';
3232
import { INotificationService } from 'vs/platform/notification/common/notification';
3333
import { Dimension, append, $, addClass, hide, show, addClasses } from 'vs/base/browser/dom';
34+
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
3435

3536
export interface ICompositeTitleLabel {
3637

@@ -391,7 +392,8 @@ export abstract class CompositePart<T extends Composite> extends Part {
391392
this.toolBar = this._register(new ToolBar(titleActionsContainer, this.contextMenuService, {
392393
actionItemProvider: action => this.actionItemProvider(action as Action),
393394
orientation: ActionsOrientation.HORIZONTAL,
394-
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id)
395+
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
396+
anchorAlignmentProvider: () => this.getTitleAreaDropDownAnchorAlignment()
395397
}));
396398

397399
return titleArea;
@@ -453,6 +455,10 @@ export abstract class CompositePart<T extends Composite> extends Part {
453455
return [];
454456
}
455457

458+
protected getTitleAreaDropDownAnchorAlignment(): AnchorAlignment {
459+
return AnchorAlignment.RIGHT;
460+
}
461+
456462
layout(dimension: Dimension): Dimension[] {
457463

458464
// Pass to super

src/vs/workbench/browser/parts/editor/titleControl.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput
3737
import { ResourceContextKey } from 'vs/workbench/common/resources';
3838
import { Themable } from 'vs/workbench/common/theme';
3939
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
40+
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
4041

4142
export interface IToolbarActions {
4243
primary: IAction[];
@@ -119,7 +120,8 @@ export abstract class TitleControl extends Themable {
119120
orientation: ActionsOrientation.HORIZONTAL,
120121
ariaLabel: localize('araLabelEditorActions', "Editor actions"),
121122
getKeyBinding: action => this.getKeybinding(action),
122-
actionRunner: this._register(new EditorCommandsContextActionRunner(context))
123+
actionRunner: this._register(new EditorCommandsContextActionRunner(context)),
124+
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
123125
}));
124126

125127
// Context

src/vs/workbench/browser/parts/sidebar/sidebarPart.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
2929
import { Dimension, EventType, addDisposableListener, trackFocus } from 'vs/base/browser/dom';
3030
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
3131
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
32+
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
3233

3334
const SideBarFocusContextId = 'sideBarFocus';
3435
export const SidebarFocusContext = new RawContextKey<boolean>(SideBarFocusContextId, false);
@@ -162,6 +163,10 @@ export class SidebarPart extends CompositePart<Viewlet> {
162163
return super.layout(dimension);
163164
}
164165

166+
protected getTitleAreaDropDownAnchorAlignment(): AnchorAlignment {
167+
return this.partService.getSideBarPosition() === SideBarPosition.LEFT ? AnchorAlignment.LEFT : AnchorAlignment.RIGHT;
168+
}
169+
165170
private onTitleAreaContextMenu(event: StandardMouseEvent): void {
166171
const activeViewlet = this.getActiveViewlet() as Viewlet;
167172
if (activeViewlet) {

0 commit comments

Comments
 (0)