Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.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/auxiliaryBarPart.css';
7
import { localize } from '../../../../nls.js';
8
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';
9
import { IContextMenuService } from '../../../../platform/contextview/browser/contextView.js';
10
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
11
import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
12
import { INotificationService } from '../../../../platform/notification/common/notification.js';
13
import { IStorageService } from '../../../../platform/storage/common/storage.js';
14
import { contrastBorder } from '../../../../platform/theme/common/colorRegistry.js';
15
import { IThemeService } from '../../../../platform/theme/common/themeService.js';
16
import { ActiveAuxiliaryContext, AuxiliaryBarFocusContext } from '../../../common/contextkeys.js';
17
import { ACTIVITY_BAR_BADGE_BACKGROUND, ACTIVITY_BAR_BADGE_FOREGROUND, ACTIVITY_BAR_TOP_ACTIVE_BORDER, ACTIVITY_BAR_TOP_DRAG_AND_DROP_BORDER, ACTIVITY_BAR_TOP_FOREGROUND, ACTIVITY_BAR_TOP_INACTIVE_FOREGROUND, PANEL_ACTIVE_TITLE_BORDER, PANEL_ACTIVE_TITLE_FOREGROUND, PANEL_DRAG_AND_DROP_BORDER, PANEL_INACTIVE_TITLE_FOREGROUND, SIDE_BAR_BACKGROUND, SIDE_BAR_BORDER, SIDE_BAR_TITLE_BORDER, SIDE_BAR_FOREGROUND } from '../../../common/theme.js';
18
import { IViewDescriptorService } from '../../../common/views.js';
19
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
20
import { ActivityBarPosition, IWorkbenchLayoutService, LayoutSettings, Parts, Position } from '../../../services/layout/browser/layoutService.js';
21
import { HoverPosition } from '../../../../base/browser/ui/hover/hoverWidget.js';
22
import { IAction, Separator, SubmenuAction, toAction } from '../../../../base/common/actions.js';
23
import { ToggleAuxiliaryBarAction } from './auxiliaryBarActions.js';
24
import { assertReturnsDefined } from '../../../../base/common/types.js';
25
import { LayoutPriority } from '../../../../base/browser/ui/splitview/splitview.js';
26
import { ToggleSidebarPositionAction } from '../../actions/layoutActions.js';
27
import { ICommandService } from '../../../../platform/commands/common/commands.js';
28
import { AbstractPaneCompositePart, CompositeBarPosition } from '../paneCompositePart.js';
29
import { ActionsOrientation } from '../../../../base/browser/ui/actionbar/actionbar.js';
30
import { IPaneCompositeBarOptions } from '../paneCompositeBar.js';
31
import { IMenuService, MenuId } from '../../../../platform/actions/common/actions.js';
32
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
33
import { getContextMenuActions } from '../../../../platform/actions/browser/menuEntryActionViewItem.js';
34
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
35
36
interface IAuxiliaryBarPartConfiguration {
37
position: ActivityBarPosition;
38
39
canShowLabels: boolean;
40
showLabels: boolean;
41
}
42
43
export class AuxiliaryBarPart extends AbstractPaneCompositePart {
44
45
static readonly activeViewSettingsKey = 'workbench.auxiliarybar.activepanelid';
46
static readonly pinnedViewsKey = 'workbench.auxiliarybar.pinnedPanels';
47
static readonly placeholdeViewContainersKey = 'workbench.auxiliarybar.placeholderPanels';
48
static readonly viewContainersWorkspaceStateKey = 'workbench.auxiliarybar.viewContainersWorkspaceState';
49
50
// Use the side bar dimensions
51
override readonly minimumWidth: number = 170;
52
override readonly maximumWidth: number = Number.POSITIVE_INFINITY;
53
override readonly minimumHeight: number = 0;
54
override readonly maximumHeight: number = Number.POSITIVE_INFINITY;
55
56
get preferredHeight(): number | undefined {
57
// Don't worry about titlebar or statusbar visibility
58
// The difference is minimal and keeps this function clean
59
return this.layoutService.mainContainerDimension.height * 0.4;
60
}
61
62
get preferredWidth(): number | undefined {
63
const activeComposite = this.getActivePaneComposite();
64
65
if (!activeComposite) {
66
return;
67
}
68
69
const width = activeComposite.getOptimalWidth();
70
if (typeof width !== 'number') {
71
return;
72
}
73
74
return Math.max(width, 300);
75
}
76
77
readonly priority = LayoutPriority.Low;
78
79
private configuration: IAuxiliaryBarPartConfiguration;
80
81
constructor(
82
@INotificationService notificationService: INotificationService,
83
@IStorageService storageService: IStorageService,
84
@IContextMenuService contextMenuService: IContextMenuService,
85
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
86
@IKeybindingService keybindingService: IKeybindingService,
87
@IHoverService hoverService: IHoverService,
88
@IInstantiationService instantiationService: IInstantiationService,
89
@IThemeService themeService: IThemeService,
90
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
91
@IContextKeyService contextKeyService: IContextKeyService,
92
@IExtensionService extensionService: IExtensionService,
93
@ICommandService private commandService: ICommandService,
94
@IMenuService menuService: IMenuService,
95
@IConfigurationService private readonly configurationService: IConfigurationService
96
) {
97
super(
98
Parts.AUXILIARYBAR_PART,
99
{
100
hasTitle: true,
101
borderWidth: () => (this.getColor(SIDE_BAR_BORDER) || this.getColor(contrastBorder)) ? 1 : 0,
102
},
103
AuxiliaryBarPart.activeViewSettingsKey,
104
ActiveAuxiliaryContext.bindTo(contextKeyService),
105
AuxiliaryBarFocusContext.bindTo(contextKeyService),
106
'auxiliarybar',
107
'auxiliarybar',
108
undefined,
109
SIDE_BAR_TITLE_BORDER,
110
notificationService,
111
storageService,
112
contextMenuService,
113
layoutService,
114
keybindingService,
115
hoverService,
116
instantiationService,
117
themeService,
118
viewDescriptorService,
119
contextKeyService,
120
extensionService,
121
menuService,
122
);
123
124
this.configuration = this.resolveConfiguration();
125
126
this._register(configurationService.onDidChangeConfiguration(e => {
127
if (e.affectsConfiguration(LayoutSettings.ACTIVITY_BAR_LOCATION)) {
128
this.configuration = this.resolveConfiguration();
129
this.onDidChangeActivityBarLocation();
130
} else if (e.affectsConfiguration('workbench.secondarySideBar.showLabels')) {
131
this.configuration = this.resolveConfiguration();
132
this.updateCompositeBar(true);
133
}
134
}));
135
}
136
137
private resolveConfiguration(): IAuxiliaryBarPartConfiguration {
138
const position = this.configurationService.getValue<ActivityBarPosition>(LayoutSettings.ACTIVITY_BAR_LOCATION);
139
140
const canShowLabels = position !== ActivityBarPosition.TOP && position !== ActivityBarPosition.BOTTOM; // use same style as activity bar in this case
141
const showLabels = canShowLabels && this.configurationService.getValue('workbench.secondarySideBar.showLabels') !== false;
142
143
return { position, canShowLabels, showLabels };
144
}
145
146
private onDidChangeActivityBarLocation(): void {
147
this.updateCompositeBar();
148
149
const id = this.getActiveComposite()?.getId();
150
if (id) {
151
this.onTitleAreaUpdate(id);
152
}
153
}
154
155
override updateStyles(): void {
156
super.updateStyles();
157
158
const container = assertReturnsDefined(this.getContainer());
159
container.style.backgroundColor = this.getColor(SIDE_BAR_BACKGROUND) || '';
160
const borderColor = this.getColor(SIDE_BAR_BORDER) || this.getColor(contrastBorder);
161
const isPositionLeft = this.layoutService.getSideBarPosition() === Position.RIGHT;
162
163
container.style.color = this.getColor(SIDE_BAR_FOREGROUND) || '';
164
165
container.style.borderLeftColor = borderColor ?? '';
166
container.style.borderRightColor = borderColor ?? '';
167
168
container.style.borderLeftStyle = borderColor && !isPositionLeft ? 'solid' : 'none';
169
container.style.borderRightStyle = borderColor && isPositionLeft ? 'solid' : 'none';
170
171
container.style.borderLeftWidth = borderColor && !isPositionLeft ? '1px' : '0px';
172
container.style.borderRightWidth = borderColor && isPositionLeft ? '1px' : '0px';
173
}
174
175
protected getCompositeBarOptions(): IPaneCompositeBarOptions {
176
const $this = this;
177
return {
178
partContainerClass: 'auxiliarybar',
179
pinnedViewContainersKey: AuxiliaryBarPart.pinnedViewsKey,
180
placeholderViewContainersKey: AuxiliaryBarPart.placeholdeViewContainersKey,
181
viewContainersWorkspaceStateKey: AuxiliaryBarPart.viewContainersWorkspaceStateKey,
182
icon: !this.configuration.showLabels,
183
orientation: ActionsOrientation.HORIZONTAL,
184
recomputeSizes: true,
185
activityHoverOptions: {
186
position: () => this.getCompositeBarPosition() === CompositeBarPosition.BOTTOM ? HoverPosition.ABOVE : HoverPosition.BELOW,
187
},
188
fillExtraContextMenuActions: actions => this.fillExtraContextMenuActions(actions),
189
compositeSize: 0,
190
iconSize: 16,
191
// Add 10px spacing if the overflow action is visible to no confuse the user with ... between the toolbars
192
get overflowActionSize() { return $this.getCompositeBarPosition() === CompositeBarPosition.TITLE ? 40 : 30; },
193
colors: theme => ({
194
activeBackgroundColor: theme.getColor(SIDE_BAR_BACKGROUND),
195
inactiveBackgroundColor: theme.getColor(SIDE_BAR_BACKGROUND),
196
get activeBorderBottomColor() { return $this.getCompositeBarPosition() === CompositeBarPosition.TITLE ? theme.getColor(PANEL_ACTIVE_TITLE_BORDER) : theme.getColor(ACTIVITY_BAR_TOP_ACTIVE_BORDER); },
197
get activeForegroundColor() { return $this.getCompositeBarPosition() === CompositeBarPosition.TITLE ? theme.getColor(PANEL_ACTIVE_TITLE_FOREGROUND) : theme.getColor(ACTIVITY_BAR_TOP_FOREGROUND); },
198
get inactiveForegroundColor() { return $this.getCompositeBarPosition() === CompositeBarPosition.TITLE ? theme.getColor(PANEL_INACTIVE_TITLE_FOREGROUND) : theme.getColor(ACTIVITY_BAR_TOP_INACTIVE_FOREGROUND); },
199
badgeBackground: theme.getColor(ACTIVITY_BAR_BADGE_BACKGROUND),
200
badgeForeground: theme.getColor(ACTIVITY_BAR_BADGE_FOREGROUND),
201
get dragAndDropBorder() { return $this.getCompositeBarPosition() === CompositeBarPosition.TITLE ? theme.getColor(PANEL_DRAG_AND_DROP_BORDER) : theme.getColor(ACTIVITY_BAR_TOP_DRAG_AND_DROP_BORDER); }
202
}),
203
compact: true
204
};
205
}
206
207
private fillExtraContextMenuActions(actions: IAction[]): void {
208
const currentPositionRight = this.layoutService.getSideBarPosition() === Position.LEFT;
209
210
if (this.getCompositeBarPosition() === CompositeBarPosition.TITLE) {
211
const viewsSubmenuAction = this.getViewsSubmenuAction();
212
if (viewsSubmenuAction) {
213
actions.push(new Separator());
214
actions.push(viewsSubmenuAction);
215
}
216
}
217
218
const activityBarPositionMenu = this.menuService.getMenuActions(MenuId.ActivityBarPositionMenu, this.contextKeyService, { shouldForwardArgs: true, renderShortTitle: true });
219
const positionActions = getContextMenuActions(activityBarPositionMenu).secondary;
220
221
const toggleShowLabelsAction = toAction({
222
id: 'workbench.action.auxiliarybar.toggleShowLabels',
223
label: this.configuration.showLabels ? localize('showIcons', "Show Icons") : localize('showLabels', "Show Labels"),
224
enabled: this.configuration.canShowLabels,
225
run: () => this.configurationService.updateValue('workbench.secondarySideBar.showLabels', !this.configuration.showLabels)
226
});
227
228
actions.push(...[
229
new Separator(),
230
new SubmenuAction('workbench.action.panel.position', localize('activity bar position', "Activity Bar Position"), positionActions),
231
toAction({ id: ToggleSidebarPositionAction.ID, label: currentPositionRight ? localize('move second side bar left', "Move Secondary Side Bar Left") : localize('move second side bar right', "Move Secondary Side Bar Right"), run: () => this.commandService.executeCommand(ToggleSidebarPositionAction.ID) }),
232
toggleShowLabelsAction,
233
toAction({ id: ToggleAuxiliaryBarAction.ID, label: localize('hide second side bar', "Hide Secondary Side Bar"), run: () => this.commandService.executeCommand(ToggleAuxiliaryBarAction.ID) })
234
]);
235
}
236
237
protected shouldShowCompositeBar(): boolean {
238
return this.configuration.position !== ActivityBarPosition.HIDDEN;
239
}
240
241
protected getCompositeBarPosition(): CompositeBarPosition {
242
switch (this.configuration.position) {
243
case ActivityBarPosition.TOP: return CompositeBarPosition.TOP;
244
case ActivityBarPosition.BOTTOM: return CompositeBarPosition.BOTTOM;
245
case ActivityBarPosition.HIDDEN: return CompositeBarPosition.TITLE;
246
case ActivityBarPosition.DEFAULT: return CompositeBarPosition.TITLE;
247
default: return CompositeBarPosition.TITLE;
248
}
249
}
250
251
override toJSON(): object {
252
return {
253
type: Parts.AUXILIARYBAR_PART
254
};
255
}
256
}
257
258