Path: blob/main/src/vs/sessions/browser/parts/panelPart.ts
13395 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import '../../../workbench/browser/parts/panel/media/panelpart.css';6import './media/panelPart.css';7import { IAction } from '../../../base/common/actions.js';8import { ActionsOrientation } from '../../../base/browser/ui/actionbar/actionbar.js';9import { ActivePanelContext, PanelFocusContext } from '../../../workbench/common/contextkeys.js';10import { IWorkbenchLayoutService, Parts, Position } from '../../../workbench/services/layout/browser/layoutService.js';11import { IStorageService } from '../../../platform/storage/common/storage.js';12import { IContextMenuService } from '../../../platform/contextview/browser/contextView.js';13import { IKeybindingService } from '../../../platform/keybinding/common/keybinding.js';14import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';15import { IThemeService } from '../../../platform/theme/common/themeService.js';16import { PANEL_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BORDER } from '../../../workbench/common/theme.js';17import { agentsBadgeBackground, agentsBadgeForeground, agentsPanelBackground, agentsPanelBorder, agentsPanelForeground } from '../../common/theme.js';18import { INotificationService } from '../../../platform/notification/common/notification.js';19import { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';20import { assertReturnsDefined } from '../../../base/common/types.js';21import { IExtensionService } from '../../../workbench/services/extensions/common/extensions.js';22import { IViewDescriptorService, ViewContainerLocation } from '../../../workbench/common/views.js';23import { HoverPosition } from '../../../base/browser/ui/hover/hoverWidget.js';24import { IMenuService } from '../../../platform/actions/common/actions.js';25import { Menus } from '../menus.js';26import { AbstractPaneCompositePart, CompositeBarPosition } from '../../../workbench/browser/parts/paneCompositePart.js';27import { Part } from '../../../workbench/browser/part.js';28import { IPaneCompositeBarOptions } from '../../../workbench/browser/parts/paneCompositeBar.js';29import { IHoverService } from '../../../platform/hover/browser/hover.js';30import { IConfigurationService } from '../../../platform/configuration/common/configuration.js';31import { Extensions } from '../../../workbench/browser/panecomposite.js';3233/**34* Panel part specifically for agent sessions workbench.35* This is a simplified version of the PanelPart for agent session contexts.36*/37export class PanelPart extends AbstractPaneCompositePart {3839//#region IView4041readonly minimumWidth: number = 300;42readonly maximumWidth: number = Number.POSITIVE_INFINITY;43readonly minimumHeight: number = 77;44readonly maximumHeight: number = Number.POSITIVE_INFINITY;4546get preferredHeight(): number | undefined {47return this.layoutService.mainContainerDimension.height * 0.4;48}4950get preferredWidth(): number | undefined {51const activeComposite = this.getActivePaneComposite();5253if (!activeComposite) {54return undefined;55}5657const width = activeComposite.getOptimalWidth();58if (typeof width !== 'number') {59return undefined;60}6162return Math.max(width, 300);63}6465//#endregion6667static readonly activePanelSettingsKey = 'workbench.agentsession.panelpart.activepanelid';6869/** Visual margin values for the card-like appearance */70static readonly MARGIN_BOTTOM = 10;71static readonly MARGIN_LEFT = 10;72static readonly MARGIN_RIGHT = 10;7374constructor(75@INotificationService notificationService: INotificationService,76@IStorageService storageService: IStorageService,77@IContextMenuService contextMenuService: IContextMenuService,78@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,79@IKeybindingService keybindingService: IKeybindingService,80@IHoverService hoverService: IHoverService,81@IInstantiationService instantiationService: IInstantiationService,82@IThemeService themeService: IThemeService,83@IViewDescriptorService viewDescriptorService: IViewDescriptorService,84@IContextKeyService contextKeyService: IContextKeyService,85@IExtensionService extensionService: IExtensionService,86@IMenuService menuService: IMenuService,87@IConfigurationService private readonly configurationService: IConfigurationService88) {89super(90Parts.PANEL_PART,91{ hasTitle: true, trailingSeparator: true },92PanelPart.activePanelSettingsKey,93ActivePanelContext.bindTo(contextKeyService),94PanelFocusContext.bindTo(contextKeyService),95'panel',96'panel',97undefined,98PANEL_TITLE_BORDER,99ViewContainerLocation.Panel,100Extensions.Panels,101Menus.PanelTitle,102notificationService,103storageService,104contextMenuService,105layoutService,106keybindingService,107hoverService,108instantiationService,109themeService,110viewDescriptorService,111contextKeyService,112extensionService,113menuService,114);115116this._register(this.configurationService.onDidChangeConfiguration(e => {117if (e.affectsConfiguration('workbench.panel.showLabels')) {118this.updateCompositeBar(true);119}120}));121}122123override updateStyles(): void {124super.updateStyles();125126const container = assertReturnsDefined(this.getContainer());127128// Store background and border as CSS variables for the card styling on .part129container.style.setProperty('--part-background', this.getColor(agentsPanelBackground) || '');130container.style.setProperty('--part-border-color', this.getColor(agentsPanelBorder) || 'transparent');131container.style.setProperty('--part-foreground', this.getColor(agentsPanelForeground) || '');132container.style.backgroundColor = this.getColor(agentsPanelBackground) || '';133134// Clear inline borders - the card appearance uses CSS border-radius instead135container.style.borderTopColor = '';136container.style.borderTopStyle = '';137container.style.borderTopWidth = '';138}139140protected getCompositeBarOptions(): IPaneCompositeBarOptions {141return {142partContainerClass: 'panel',143pinnedViewContainersKey: 'workbench.agentsession.panel.pinnedPanels',144placeholderViewContainersKey: 'workbench.agentsession.panel.placeholderPanels',145viewContainersWorkspaceStateKey: 'workbench.agentsession.panel.viewContainersWorkspaceState',146icon: this.configurationService.getValue('workbench.panel.showLabels') === false,147orientation: ActionsOrientation.HORIZONTAL,148recomputeSizes: true,149activityHoverOptions: {150position: () => this.layoutService.getPanelPosition() === Position.BOTTOM && !this.layoutService.isPanelMaximized() ? HoverPosition.ABOVE : HoverPosition.BELOW,151},152fillExtraContextMenuActions: actions => this.fillExtraContextMenuActions(actions),153compositeSize: 0,154iconSize: 16,155compact: true,156overflowActionSize: 44,157colors: theme => ({158activeBackgroundColor: theme.getColor(agentsPanelBackground),159inactiveBackgroundColor: theme.getColor(agentsPanelBackground),160activeBorderBottomColor: theme.getColor(PANEL_ACTIVE_TITLE_BORDER),161activeForegroundColor: theme.getColor(PANEL_ACTIVE_TITLE_FOREGROUND),162inactiveForegroundColor: theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND),163badgeBackground: theme.getColor(agentsBadgeBackground),164badgeForeground: theme.getColor(agentsBadgeForeground),165dragAndDropBorder: theme.getColor(PANEL_DRAG_AND_DROP_BORDER)166})167};168}169170private fillExtraContextMenuActions(_actions: IAction[]): void { }171172override layout(width: number, height: number, top: number, left: number): void {173if (!this.layoutService.isVisible(Parts.PANEL_PART)) {174return;175}176177// Layout content with reduced dimensions to account for visual margins and border178const borderTotal = 2; // 1px border on each side179const marginLeft = this.layoutService.isVisible(Parts.SIDEBAR_PART) ? 0 : PanelPart.MARGIN_LEFT;180super.layout(181width - marginLeft - PanelPart.MARGIN_RIGHT - borderTotal,182height - PanelPart.MARGIN_BOTTOM - borderTotal,183top, left184);185186// Restore the full grid-allocated dimensions so that Part.relayout() works correctly.187Part.prototype.layout.call(this, width, height, top, left);188}189190protected override shouldShowCompositeBar(): boolean {191return true;192}193194protected getCompositeBarPosition(): CompositeBarPosition {195return CompositeBarPosition.TITLE;196}197198toJSON(): object {199return {200type: Parts.PANEL_PART201};202}203}204205206