Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/browser/parts/panel/panelPart.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import './media/panelpart.css';
7
import { localize } from '../../../../nls.js';
8
import { IAction, Separator, SubmenuAction, toAction } from '../../../../base/common/actions.js';
9
import { ActionsOrientation } from '../../../../base/browser/ui/actionbar/actionbar.js';
10
import { ActivePanelContext, PanelFocusContext } from '../../../common/contextkeys.js';
11
import { IWorkbenchLayoutService, Parts, Position } from '../../../services/layout/browser/layoutService.js';
12
import { IStorageService } from '../../../../platform/storage/common/storage.js';
13
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';
14
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
15
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
16
import { TogglePanelAction } from './panelActions.js';
17
import { IThemeService } from '../../../../platform/theme/common/themeService.js';
18
import { PANEL_BACKGROUND, PANEL_BORDER, PANEL_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_INACTIVE_TITLE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_DRAG_AND_DROP_BORDER, PANEL_TITLE_BADGE_BACKGROUND, PANEL_TITLE_BADGE_FOREGROUND } from '../../../common/theme.js';
19
import { contrastBorder } from '../../../../platform/theme/common/colorRegistry.js';
20
import { INotificationService } from '../../../../platform/notification/common/notification.js';
21
import { Dimension } from '../../../../base/browser/dom.js';
22
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
23
import { assertReturnsDefined } from '../../../../base/common/types.js';
24
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
25
import { IViewDescriptorService } from '../../../common/views.js';
26
import { HoverPosition } from '../../../../base/browser/ui/hover/hoverWidget.js';
27
import { IMenuService, MenuId } from '../../../../platform/actions/common/actions.js';
28
import { AbstractPaneCompositePart, CompositeBarPosition } from '../paneCompositePart.js';
29
import { ICommandService } from '../../../../platform/commands/common/commands.js';
30
import { getContextMenuActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
31
import { IPaneCompositeBarOptions } from '../paneCompositeBar.js';
32
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
33
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
34
35
export class PanelPart extends AbstractPaneCompositePart {
36
37
//#region IView
38
39
readonly minimumWidth: number = 300;
40
readonly maximumWidth: number = Number.POSITIVE_INFINITY;
41
readonly minimumHeight: number = 77;
42
readonly maximumHeight: number = Number.POSITIVE_INFINITY;
43
44
get preferredHeight(): number | undefined {
45
// Don't worry about titlebar or statusbar visibility
46
// The difference is minimal and keeps this function clean
47
return this.layoutService.mainContainerDimension.height * 0.4;
48
}
49
50
get preferredWidth(): number | undefined {
51
const activeComposite = this.getActivePaneComposite();
52
53
if (!activeComposite) {
54
return;
55
}
56
57
const width = activeComposite.getOptimalWidth();
58
if (typeof width !== 'number') {
59
return;
60
}
61
62
return Math.max(width, 300);
63
}
64
65
//#endregion
66
67
static readonly activePanelSettingsKey = 'workbench.panelpart.activepanelid';
68
69
constructor(
70
@INotificationService notificationService: INotificationService,
71
@IStorageService storageService: IStorageService,
72
@IContextMenuService contextMenuService: IContextMenuService,
73
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
74
@IKeybindingService keybindingService: IKeybindingService,
75
@IHoverService hoverService: IHoverService,
76
@IInstantiationService instantiationService: IInstantiationService,
77
@IThemeService themeService: IThemeService,
78
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
79
@IContextKeyService contextKeyService: IContextKeyService,
80
@IExtensionService extensionService: IExtensionService,
81
@ICommandService private commandService: ICommandService,
82
@IMenuService menuService: IMenuService,
83
@IConfigurationService private configurationService: IConfigurationService
84
) {
85
super(
86
Parts.PANEL_PART,
87
{ hasTitle: true },
88
PanelPart.activePanelSettingsKey,
89
ActivePanelContext.bindTo(contextKeyService),
90
PanelFocusContext.bindTo(contextKeyService),
91
'panel',
92
'panel',
93
undefined,
94
PANEL_TITLE_BORDER,
95
notificationService,
96
storageService,
97
contextMenuService,
98
layoutService,
99
keybindingService,
100
hoverService,
101
instantiationService,
102
themeService,
103
viewDescriptorService,
104
contextKeyService,
105
extensionService,
106
menuService,
107
);
108
109
this._register(this.configurationService.onDidChangeConfiguration(e => {
110
if (e.affectsConfiguration('workbench.panel.showLabels')) {
111
this.updateCompositeBar(true);
112
}
113
}));
114
}
115
116
override updateStyles(): void {
117
super.updateStyles();
118
119
const container = assertReturnsDefined(this.getContainer());
120
container.style.backgroundColor = this.getColor(PANEL_BACKGROUND) || '';
121
const borderColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder) || '';
122
container.style.borderLeftColor = borderColor;
123
container.style.borderRightColor = borderColor;
124
container.style.borderBottomColor = borderColor;
125
126
const title = this.getTitleArea();
127
if (title) {
128
title.style.borderTopColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder) || '';
129
}
130
}
131
132
protected getCompositeBarOptions(): IPaneCompositeBarOptions {
133
return {
134
partContainerClass: 'panel',
135
pinnedViewContainersKey: 'workbench.panel.pinnedPanels',
136
placeholderViewContainersKey: 'workbench.panel.placeholderPanels',
137
viewContainersWorkspaceStateKey: 'workbench.panel.viewContainersWorkspaceState',
138
icon: this.configurationService.getValue('workbench.panel.showLabels') === false,
139
orientation: ActionsOrientation.HORIZONTAL,
140
recomputeSizes: true,
141
activityHoverOptions: {
142
position: () => this.layoutService.getPanelPosition() === Position.BOTTOM && !this.layoutService.isPanelMaximized() ? HoverPosition.ABOVE : HoverPosition.BELOW,
143
},
144
fillExtraContextMenuActions: actions => this.fillExtraContextMenuActions(actions),
145
compositeSize: 0,
146
iconSize: 16,
147
compact: true, // Only applies to icons, not labels
148
overflowActionSize: 44,
149
colors: theme => ({
150
activeBackgroundColor: theme.getColor(PANEL_BACKGROUND), // Background color for overflow action
151
inactiveBackgroundColor: theme.getColor(PANEL_BACKGROUND), // Background color for overflow action
152
activeBorderBottomColor: theme.getColor(PANEL_ACTIVE_TITLE_BORDER),
153
activeForegroundColor: theme.getColor(PANEL_ACTIVE_TITLE_FOREGROUND),
154
inactiveForegroundColor: theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND),
155
badgeBackground: theme.getColor(PANEL_TITLE_BADGE_BACKGROUND),
156
badgeForeground: theme.getColor(PANEL_TITLE_BADGE_FOREGROUND),
157
dragAndDropBorder: theme.getColor(PANEL_DRAG_AND_DROP_BORDER)
158
})
159
};
160
}
161
162
private fillExtraContextMenuActions(actions: IAction[]): void {
163
if (this.getCompositeBarPosition() === CompositeBarPosition.TITLE) {
164
const viewsSubmenuAction = this.getViewsSubmenuAction();
165
if (viewsSubmenuAction) {
166
actions.push(new Separator());
167
actions.push(viewsSubmenuAction);
168
}
169
}
170
171
const panelPositionMenu = this.menuService.getMenuActions(MenuId.PanelPositionMenu, this.contextKeyService, { shouldForwardArgs: true });
172
const panelAlignMenu = this.menuService.getMenuActions(MenuId.PanelAlignmentMenu, this.contextKeyService, { shouldForwardArgs: true });
173
const positionActions = getContextMenuActions(panelPositionMenu).secondary;
174
const alignActions = getContextMenuActions(panelAlignMenu).secondary;
175
176
const panelShowLabels = this.configurationService.getValue<boolean | undefined>('workbench.panel.showLabels');
177
const toggleShowLabelsAction = toAction({
178
id: 'workbench.action.panel.toggleShowLabels',
179
label: panelShowLabels ? localize('showIcons', "Show Icons") : localize('showLabels', "Show Labels"),
180
run: () => this.configurationService.updateValue('workbench.panel.showLabels', !panelShowLabels)
181
});
182
183
actions.push(...[
184
new Separator(),
185
new SubmenuAction('workbench.action.panel.position', localize('panel position', "Panel Position"), positionActions),
186
new SubmenuAction('workbench.action.panel.align', localize('align panel', "Align Panel"), alignActions),
187
toggleShowLabelsAction,
188
toAction({ id: TogglePanelAction.ID, label: localize('hidePanel', "Hide Panel"), run: () => this.commandService.executeCommand(TogglePanelAction.ID) }),
189
]);
190
}
191
192
override layout(width: number, height: number, top: number, left: number): void {
193
let dimensions: Dimension;
194
switch (this.layoutService.getPanelPosition()) {
195
case Position.RIGHT:
196
dimensions = new Dimension(width - 1, height); // Take into account the 1px border when layouting
197
break;
198
case Position.TOP:
199
dimensions = new Dimension(width, height - 1); // Take into account the 1px border when layouting
200
break;
201
default:
202
dimensions = new Dimension(width, height);
203
break;
204
}
205
206
// Layout contents
207
super.layout(dimensions.width, dimensions.height, top, left);
208
}
209
210
protected override shouldShowCompositeBar(): boolean {
211
return true;
212
}
213
214
protected getCompositeBarPosition(): CompositeBarPosition {
215
return CompositeBarPosition.TITLE;
216
}
217
218
toJSON(): object {
219
return {
220
type: Parts.PANEL_PART
221
};
222
}
223
}
224
225