This commit is contained in:
Sandeep Somavarapu 2025-06-10 10:33:30 +02:00 committed by GitHub
parent 5d58232005
commit 997f77944b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 102 additions and 187 deletions

View File

@ -210,7 +210,6 @@ export class MenuId {
static readonly SidebarTitle = new MenuId('SidebarTitle');
static readonly PanelTitle = new MenuId('PanelTitle');
static readonly AuxiliaryBarTitle = new MenuId('AuxiliaryBarTitle');
static readonly AuxiliaryBarHeader = new MenuId('AuxiliaryBarHeader');
static readonly TerminalInstanceContext = new MenuId('TerminalInstanceContext');
static readonly TerminalEditorInstanceContext = new MenuId('TerminalEditorInstanceContext');
static readonly TerminalNewDropdownContext = new MenuId('TerminalNewDropdownContext');

View File

@ -1,103 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IAction } from '../../base/common/actions.js';
import { Disposable, DisposableStore, IDisposable } from '../../base/common/lifecycle.js';
import { Emitter, Event } from '../../base/common/event.js';
import { MenuId, IMenuService, IMenu, SubmenuItemAction, IMenuActionOptions } from '../../platform/actions/common/actions.js';
import { IContextKeyService } from '../../platform/contextkey/common/contextkey.js';
import { getActionBarActions } from '../../platform/actions/browser/menuEntryActionViewItem.js';
class MenuActions extends Disposable {
private readonly menu: IMenu;
private _primaryActions: IAction[] = [];
get primaryActions() { return this._primaryActions; }
private _secondaryActions: IAction[] = [];
get secondaryActions() { return this._secondaryActions; }
private readonly _onDidChange = this._register(new Emitter<void>());
readonly onDidChange = this._onDidChange.event;
private readonly disposables = this._register(new DisposableStore());
constructor(
menuId: MenuId,
private readonly options: IMenuActionOptions | undefined,
private readonly menuService: IMenuService,
private readonly contextKeyService: IContextKeyService
) {
super();
this.menu = this._register(menuService.createMenu(menuId, contextKeyService));
this._register(this.menu.onDidChange(() => this.updateActions()));
this.updateActions();
}
private updateActions(): void {
this.disposables.clear();
const newActions = getActionBarActions(this.menu.getActions(this.options));
this._primaryActions = newActions.primary;
this._secondaryActions = newActions.secondary;
this.disposables.add(this.updateSubmenus([...this._primaryActions, ...this._secondaryActions], {}));
this._onDidChange.fire();
}
private updateSubmenus(actions: readonly IAction[], submenus: Record<string, IMenu>): IDisposable {
const disposables = new DisposableStore();
for (const action of actions) {
if (action instanceof SubmenuItemAction && !submenus[action.item.submenu.id]) {
const menu = submenus[action.item.submenu.id] = disposables.add(this.menuService.createMenu(action.item.submenu, this.contextKeyService));
disposables.add(menu.onDidChange(() => this.updateActions()));
disposables.add(this.updateSubmenus(action.actions, submenus));
}
}
return disposables;
}
}
export class CompositeMenuActions extends Disposable {
private readonly menuActions: MenuActions;
private _onDidChange = this._register(new Emitter<void>());
readonly onDidChange: Event<void> = this._onDidChange.event;
constructor(
readonly menuId: MenuId,
private readonly contextMenuId: MenuId | undefined,
private readonly options: IMenuActionOptions | undefined,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IMenuService private readonly menuService: IMenuService,
) {
super();
this.menuActions = this._register(new MenuActions(menuId, this.options, menuService, contextKeyService));
this._register(this.menuActions.onDidChange(() => this._onDidChange.fire()));
}
getPrimaryActions(): IAction[] {
return this.menuActions.primaryActions;
}
getSecondaryActions(): IAction[] {
return this.menuActions.secondaryActions;
}
getContextMenuActions(): IAction[] {
if (this.contextMenuId) {
const menu = this.menuService.getMenuActions(this.contextMenuId, this.contextKeyService, this.options);
return getActionBarActions(menu).secondary;
}
return [];
}
}

View File

@ -26,15 +26,11 @@ import { LayoutPriority } from '../../../../base/browser/ui/splitview/splitview.
import { ToggleSidebarPositionAction } from '../../actions/layoutActions.js';
import { ICommandService } from '../../../../platform/commands/common/commands.js';
import { AbstractPaneCompositePart, CompositeBarPosition } from '../paneCompositePart.js';
import { ActionsOrientation, IActionViewItem, prepareActions } from '../../../../base/browser/ui/actionbar/actionbar.js';
import { ActionsOrientation } from '../../../../base/browser/ui/actionbar/actionbar.js';
import { IPaneCompositeBarOptions } from '../paneCompositeBar.js';
import { IMenuService, MenuId } from '../../../../platform/actions/common/actions.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { getContextMenuActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
import { $ } from '../../../../base/browser/dom.js';
import { HiddenItemStrategy, WorkbenchToolBar } from '../../../../platform/actions/browser/toolbar.js';
import { ActionViewItem, IActionViewItemOptions } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
import { CompositeMenuActions } from '../../actions.js';
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
interface IAuxiliaryBarPartConfiguration {
@ -252,35 +248,6 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
}
}
protected override createHeaderArea() {
const headerArea = super.createHeaderArea();
const globalHeaderContainer = $('.auxiliary-bar-global-header');
// Add auxillary header action
const menu = this.headerFooterCompositeBarDispoables.add(this.instantiationService.createInstance(CompositeMenuActions, MenuId.AuxiliaryBarHeader, undefined, undefined));
const toolBar = this.headerFooterCompositeBarDispoables.add(this.instantiationService.createInstance(WorkbenchToolBar, globalHeaderContainer, {
actionViewItemProvider: (action, options) => this.headerActionViewItemProvider(action, options),
orientation: ActionsOrientation.HORIZONTAL,
hiddenItemStrategy: HiddenItemStrategy.NoHide,
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
}));
toolBar.setActions(prepareActions(menu.getPrimaryActions()));
this.headerFooterCompositeBarDispoables.add(menu.onDidChange(() => toolBar.setActions(prepareActions(menu.getPrimaryActions()))));
headerArea.appendChild(globalHeaderContainer);
return headerArea;
}
private headerActionViewItemProvider(action: IAction, options: IActionViewItemOptions): IActionViewItem | undefined {
if (action.id === ToggleAuxiliaryBarAction.ID) {
return this.instantiationService.createInstance(ActionViewItem, undefined, action, options);
}
return undefined;
}
override toJSON(): object {
return {
type: Parts.AUXILIARYBAR_PART

View File

@ -29,9 +29,8 @@ import { localize } from '../../../nls.js';
import { CompositeDragAndDropObserver, toggleDropEffect } from '../dnd.js';
import { EDITOR_DRAG_AND_DROP_BACKGROUND } from '../../common/theme.js';
import { IPartOptions } from '../part.js';
import { CompositeMenuActions } from '../actions.js';
import { IMenuService, MenuId } from '../../../platform/actions/common/actions.js';
import { ActionsOrientation, prepareActions } from '../../../base/browser/ui/actionbar/actionbar.js';
import { ActionsOrientation } from '../../../base/browser/ui/actionbar/actionbar.js';
import { Gesture, EventType as GestureEventType } from '../../../base/browser/touch.js';
import { StandardMouseEvent } from '../../../base/browser/mouseEvent.js';
import { IAction, SubmenuAction } from '../../../base/common/actions.js';
@ -39,7 +38,7 @@ import { Composite } from '../composite.js';
import { ViewsSubMenu } from './views/viewPaneContainer.js';
import { getActionBarActions } from '../../../platform/actions/browser/menuEntryActionViewItem.js';
import { IHoverService } from '../../../platform/hover/browser/hover.js';
import { HiddenItemStrategy, WorkbenchToolBar } from '../../../platform/actions/browser/toolbar.js';
import { HiddenItemStrategy, MenuWorkbenchToolBar } from '../../../platform/actions/browser/toolbar.js';
import { DeferredPromise } from '../../../base/common/async.js';
export enum CompositeBarPosition {
@ -128,8 +127,8 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
private compositeBarPosition: CompositeBarPosition | undefined = undefined;
private emptyPaneMessageElement: HTMLElement | undefined;
private globalToolBar: WorkbenchToolBar | undefined;
private readonly globalActions: CompositeMenuActions;
private readonly globalActionsMenuId: MenuId;
private globalToolBar: MenuWorkbenchToolBar | undefined;
private blockOpening: DeferredPromise<PaneComposite | undefined> | undefined = undefined;
protected contentDimension: Dimension | undefined;
@ -190,15 +189,13 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
);
this.location = location;
this.globalActions = this._register(this.instantiationService.createInstance(CompositeMenuActions, globalActionsMenuId, undefined, undefined));
this.globalActionsMenuId = globalActionsMenuId;
this.registerListeners();
}
private registerListeners(): void {
this._register(this.onDidPaneCompositeOpen(composite => this.onDidOpen(composite)));
this._register(this.onDidPaneCompositeClose(this.onDidClose, this));
this._register(this.globalActions.onDidChange(() => this.updateGlobalToolbarActions()));
this._register(this.registry.onDidDeregister((viewletDescriptor: PaneCompositeDescriptor) => {
@ -357,17 +354,19 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
const globalTitleActionsContainer = titleArea.appendChild($('.global-actions'));
// Global Actions Toolbar
this.globalToolBar = this._register(this.instantiationService.createInstance(WorkbenchToolBar, globalTitleActionsContainer, {
actionViewItemProvider: (action, options) => this.actionViewItemProvider(action, options),
orientation: ActionsOrientation.HORIZONTAL,
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
anchorAlignmentProvider: () => this.getTitleAreaDropDownAnchorAlignment(),
toggleMenuTitle: localize('moreActions', "More Actions..."),
hoverDelegate: this.toolbarHoverDelegate,
hiddenItemStrategy: HiddenItemStrategy.NoHide
}));
this.updateGlobalToolbarActions();
this.globalToolBar = this._register(this.instantiationService.createInstance(MenuWorkbenchToolBar,
globalTitleActionsContainer,
this.globalActionsMenuId,
{
actionViewItemProvider: (action, options) => this.actionViewItemProvider(action, options),
orientation: ActionsOrientation.HORIZONTAL,
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
anchorAlignmentProvider: () => this.getTitleAreaDropDownAnchorAlignment(),
toggleMenuTitle: localize('moreActions', "More Actions..."),
hoverDelegate: this.toolbarHoverDelegate,
hiddenItemStrategy: HiddenItemStrategy.NoHide
}
));
return titleArea;
}
@ -628,12 +627,6 @@ export abstract class AbstractPaneCompositePart extends CompositePart<PaneCompos
}
}
private updateGlobalToolbarActions(): void {
const primaryActions = this.globalActions.getPrimaryActions();
const secondaryActions = this.globalActions.getSecondaryActions();
this.globalToolBar?.setActions(prepareActions(primaryActions), prepareActions(secondaryActions));
}
protected getToolbarWidth(): number {
if (!this.toolBar || this.compositeBarPosition !== CompositeBarPosition.TITLE) {
return 0;

View File

@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IAction } from '../../../../base/common/actions.js';
import { Emitter, Event } from '../../../../base/common/event.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { getActionBarActions, PrimaryAndSecondaryActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
import { MenuId, IMenuActionOptions, IMenuService, IMenu } from '../../../../platform/actions/common/actions.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
import { IViewDescriptorService, ViewContainer, ViewContainerLocationToString } from '../../../common/views.js';
export class ViewMenuActions extends Disposable {
private readonly menu: IMenu;
private readonly _onDidChange = this._register(new Emitter<void>());
readonly onDidChange = this._onDidChange.event;
constructor(
readonly menuId: MenuId,
private readonly contextMenuId: MenuId | undefined,
private readonly options: IMenuActionOptions | undefined,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IMenuService private readonly menuService: IMenuService,
) {
super();
this.menu = this._register(menuService.createMenu(menuId, contextKeyService, { emitEventsForSubmenuChanges: true }));
this._register(this.menu.onDidChange(() => {
this.actions = undefined;
this._onDidChange.fire();
}));
}
private actions: PrimaryAndSecondaryActions | undefined;
private getActions(): PrimaryAndSecondaryActions {
if (!this.actions) {
this.actions = getActionBarActions(this.menu.getActions(this.options));
}
return this.actions;
}
getPrimaryActions(): IAction[] {
return this.getActions().primary;
}
getSecondaryActions(): IAction[] {
return this.getActions().secondary;
}
getContextMenuActions(): IAction[] {
if (this.contextMenuId) {
const menu = this.menuService.getMenuActions(this.contextMenuId, this.contextKeyService, this.options);
return getActionBarActions(menu).secondary;
}
return [];
}
}
export class ViewContainerMenuActions extends ViewMenuActions {
constructor(
element: HTMLElement,
viewContainer: ViewContainer,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
@IContextKeyService contextKeyService: IContextKeyService,
@IMenuService menuService: IMenuService,
) {
const scopedContextKeyService = contextKeyService.createScoped(element);
scopedContextKeyService.createKey('viewContainer', viewContainer.id);
const viewContainerLocationKey = scopedContextKeyService.createKey('viewContainerLocation', ViewContainerLocationToString(viewDescriptorService.getViewContainerLocation(viewContainer)!));
super(MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext, { shouldForwardArgs: true, renderShortTitle: true }, scopedContextKeyService, menuService);
this._register(scopedContextKeyService);
this._register(Event.filter(viewDescriptorService.onDidChangeContainerLocation, e => e.viewContainer === viewContainer)(() => viewContainerLocationKey.set(ViewContainerLocationToString(viewDescriptorService.getViewContainerLocation(viewContainer)!))));
}
}

View File

@ -40,7 +40,6 @@ import { ScrollbarVisibility } from '../../../../base/common/scrollable.js';
import { URI } from '../../../../base/common/uri.js';
import { registerIcon } from '../../../../platform/theme/common/iconRegistry.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { CompositeMenuActions } from '../../actions.js';
import { IDropdownMenuActionViewItemOptions } from '../../../../base/browser/ui/dropdown/dropdownActionViewItem.js';
import { WorkbenchToolBar } from '../../../../platform/actions/browser/toolbar.js';
import { FilterWidget, IFilterWidgetOptions } from './viewFilter.js';
@ -55,6 +54,7 @@ import { IListStyles } from '../../../../base/browser/ui/list/listWidget.js';
import { PANEL_BACKGROUND, PANEL_SECTION_DRAG_AND_DROP_BACKGROUND, PANEL_STICKY_SCROLL_BACKGROUND, PANEL_STICKY_SCROLL_BORDER, PANEL_STICKY_SCROLL_SHADOW, SIDE_BAR_BACKGROUND, SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_STICKY_SCROLL_BACKGROUND, SIDE_BAR_STICKY_SCROLL_BORDER, SIDE_BAR_STICKY_SCROLL_SHADOW } from '../../../common/theme.js';
import { IAccessibleViewInformationService } from '../../../services/accessibility/common/accessibleViewInformationService.js';
import { renderLabelWithIcons } from '../../../../base/browser/ui/iconLabel/iconLabels.js';
import { ViewMenuActions } from './viewMenuActions.js';
export enum ViewPaneShowActions {
/** Show the actions when the view is hovered. This is the default behavior. */
@ -340,7 +340,7 @@ export abstract class ViewPane extends Pane implements IView {
return this._singleViewPaneContainerTitle;
}
readonly menuActions: CompositeMenuActions;
readonly menuActions: ViewMenuActions;
private progressBar!: ProgressBar;
private progressIndicator!: IProgressIndicator;
@ -388,7 +388,7 @@ export abstract class ViewPane extends Pane implements IView {
this._register(Event.filter(viewDescriptorService.onDidChangeLocation, e => e.views.some(view => view.id === this.id))(() => viewLocationKey.set(ViewContainerLocationToString(viewDescriptorService.getViewLocationById(this.id)!))));
const childInstantiationService = this._register(this.instantiationService.createChild(new ServiceCollection([IContextKeyService, this.scopedContextKeyService])));
this.menuActions = this._register(childInstantiationService.createInstance(CompositeMenuActions, options.titleMenuId ?? MenuId.ViewTitle, MenuId.ViewTitleContext, { shouldForwardArgs: !options.donotForwardArgs, renderShortTitle: true }));
this.menuActions = this._register(childInstantiationService.createInstance(ViewMenuActions, options.titleMenuId ?? MenuId.ViewTitle, MenuId.ViewTitleContext, { shouldForwardArgs: !options.donotForwardArgs, renderShortTitle: true }));
this._register(this.menuActions.onDidChange(() => this.updateActions()));
}

View File

@ -18,7 +18,7 @@ import { assertReturnsDefined } from '../../../../base/common/types.js';
import './media/paneviewlet.css';
import * as nls from '../../../../nls.js';
import { createActionViewItem } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
import { Action2, IAction2Options, IMenuService, ISubmenuItem, MenuId, MenuRegistry, registerAction2 } from '../../../../platform/actions/common/actions.js';
import { Action2, IAction2Options, ISubmenuItem, MenuId, MenuRegistry, registerAction2 } from '../../../../platform/actions/common/actions.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';
@ -29,19 +29,19 @@ import { ITelemetryService } from '../../../../platform/telemetry/common/telemet
import { activeContrastBorder, asCssVariable } from '../../../../platform/theme/common/colorRegistry.js';
import { IThemeService, Themable } from '../../../../platform/theme/common/themeService.js';
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
import { CompositeMenuActions } from '../../actions.js';
import { CompositeDragAndDropObserver, toggleDropEffect } from '../../dnd.js';
import { ViewPane } from './viewPane.js';
import { IViewletViewOptions } from './viewsViewlet.js';
import { Component } from '../../../common/component.js';
import { PANEL_SECTION_BORDER, PANEL_SECTION_DRAG_AND_DROP_BACKGROUND, PANEL_SECTION_HEADER_BACKGROUND, PANEL_SECTION_HEADER_BORDER, PANEL_SECTION_HEADER_FOREGROUND, SIDE_BAR_DRAG_AND_DROP_BACKGROUND, SIDE_BAR_SECTION_HEADER_BACKGROUND, SIDE_BAR_SECTION_HEADER_BORDER, SIDE_BAR_SECTION_HEADER_FOREGROUND } from '../../../common/theme.js';
import { IAddedViewDescriptorRef, ICustomViewDescriptor, IView, IViewContainerModel, IViewDescriptor, IViewDescriptorRef, IViewDescriptorService, IViewPaneContainer, ViewContainer, ViewContainerLocation, ViewContainerLocationToString, ViewVisibilityState } from '../../../common/views.js';
import { IAddedViewDescriptorRef, ICustomViewDescriptor, IView, IViewContainerModel, IViewDescriptor, IViewDescriptorRef, IViewDescriptorService, IViewPaneContainer, ViewContainer, ViewContainerLocation, ViewVisibilityState } from '../../../common/views.js';
import { IViewsService } from '../../../services/views/common/viewsService.js';
import { FocusedViewContext } from '../../../common/contextkeys.js';
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
import { isHorizontal, IWorkbenchLayoutService, LayoutSettings } from '../../../services/layout/browser/layoutService.js';
import { IBaseActionViewItemOptions } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
import { ILogService } from '../../../../platform/log/common/log.js';
import { ViewContainerMenuActions } from './viewMenuActions.js';
export const ViewsSubMenu = new MenuId('Views');
MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, {
@ -288,23 +288,6 @@ class ViewPaneDropOverlay extends Themable {
}
}
class ViewContainerMenuActions extends CompositeMenuActions {
constructor(
element: HTMLElement,
viewContainer: ViewContainer,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
@IContextKeyService contextKeyService: IContextKeyService,
@IMenuService menuService: IMenuService,
) {
const scopedContextKeyService = contextKeyService.createScoped(element);
scopedContextKeyService.createKey('viewContainer', viewContainer.id);
const viewContainerLocationKey = scopedContextKeyService.createKey('viewContainerLocation', ViewContainerLocationToString(viewDescriptorService.getViewContainerLocation(viewContainer)!));
super(MenuId.ViewContainerTitle, MenuId.ViewContainerTitleContext, { shouldForwardArgs: true, renderShortTitle: true }, scopedContextKeyService, menuService);
this._register(scopedContextKeyService);
this._register(Event.filter(viewDescriptorService.onDidChangeContainerLocation, e => e.viewContainer === viewContainer)(() => viewContainerLocationKey.set(ViewContainerLocationToString(viewDescriptorService.getViewContainerLocation(viewContainer)!))));
}
}
export class ViewPaneContainer extends Component implements IViewPaneContainer {
readonly viewContainer: ViewContainer;
@ -363,7 +346,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
}
private _menuActions?: ViewContainerMenuActions;
get menuActions(): CompositeMenuActions | undefined {
get menuActions(): ViewContainerMenuActions | undefined {
return this._menuActions;
}