新增toolbar工具栏,位于标题栏和菜单栏下面,具有隐藏显示功能,工具栏中为一些快捷按钮.

This commit is contained in:
chriswang521 2023-05-22 10:38:56 +08:00
parent 5da8929599
commit 8d0ae4eba5
12 changed files with 739 additions and 11 deletions

View File

@ -2873,7 +2873,11 @@
"toggleZenMode": "切换禅模式",
"visible": "可见",
"zenMode": "禅模式",
"zenModeIcon": "表示禅模式"
"zenModeIcon": "表示禅模式",
"toolBarIcon": "表示工具栏",
"toggleToolBar": "切换工具栏",
"miShowToolBar": "显示工具栏",
"toolBar": "工具栏"
},
"vs/workbench/browser/actions/navigationActions": {
"focusNextPart": "专注下一部分",
@ -3611,6 +3615,30 @@
"userIsAdmin": "[管理员]",
"userIsSudo": "[超级用户]"
},
"vs/workbench/browser/parts/toolbar/toolbarPart": {
"newFile": "新建文本文件",
"newWindow": "新建窗口",
"undo": "撤销",
"redo": "恢复",
"navigatePrevious": "返回",
"navigateNext": "前进",
"moveLinesUp": "向上移动行",
"moveLinesDown" : "向下移动行",
"explorer": "资源管理器",
"Search": "搜索",
"Scm": "源代码管理",
"Run and Debug": "运行和调试",
"Extensions": "插件",
"Terminal": "终端",
"KeyboardShortcuts": "键盘快捷方式",
"Settings": "设置",
"ZoomIn": "放大",
"ZoomOut": "缩小",
"FullScreen": "全屏",
"ZenMode":"禅模式",
"hideToolBar":"隐藏工具栏",
"toolBarBackground":"工具栏背景"
},
"vs/workbench/browser/parts/views/treeView": {
"collapseAll": "全部折叠",
"command-error": "运行命令 {1} 错误: {0}。这可能是由提交 {1} 的扩展引起的。",
@ -3726,6 +3754,7 @@
"splitOnDragAndDrop": "通过将编辑器或文件放到编辑器区域的边缘,控制是否可以由拖放操作拆分编辑器组。",
"splitSizing": "拆分编辑器组时控制编辑器组大小。",
"statusBarVisibility": "控制工作台底部状态栏的可见性。",
"toolBarVisibility":"控制工作台中工具栏的可见性。",
"tabDescription": "控制编辑器标签的格式。",
"tabScrollbarHeight": "控制编辑器标题区域中用于选项卡和面包屑的滚动条的高度。",
"tabSizing": "控制编辑器选项卡的大小调整。当 \"#workbench.editor.showTabs#\" 处于禁用状态时,将忽略此值。",

View File

@ -31,6 +31,7 @@ import { ICommandActionTitle } from 'vs/platform/action/common/action';
// Register Icons
const menubarIcon = registerIcon('menuBar', Codicon.layoutMenubar, localize('menuBarIcon', "Represents the menu bar"));
const toolbarIcon = registerIcon('toolBar', Codicon.browser, localize('toolBarIcon', "Represents the tool bar"));
const activityBarLeftIcon = registerIcon('activity-bar-left', Codicon.layoutActivitybarLeft, localize('activityBarLeft', "Represents the activity bar in the left position"));
const activityBarRightIcon = registerIcon('activity-bar-right', Codicon.layoutActivitybarRight, localize('activityBarRight', "Represents the activity bar in the right position"));
const panelLeftIcon = registerIcon('panel-left', Codicon.layoutSidebarLeft, localize('panelLeft', "Represents a side bar in the left position"));
@ -68,6 +69,47 @@ registerAction2(class extends Action2 {
}
});
//kylin ide start, add Toggle Toolbar Layout
export class ToggleToolBarVisibilityAction extends Action2 {
static readonly ID = 'workbench.action.toggleToolBarVisibility';
static readonly LABEL = localize('toggleToolBar', 'Toggle Tool Bar Visibility');
private static readonly toolBarVisibleKey = 'workbench.toolBar.visible';
constructor() {
super({
id: ToggleToolBarVisibilityAction.ID,
title: { value: ToggleToolBarVisibilityAction.LABEL, original: 'Toggle Tool Bar Visibility' },
category: CATEGORIES.View,
f1: true
});
}
run(accessor: ServicesAccessor): void {
const layoutService = accessor.get(IWorkbenchLayoutService);
const configurationService = accessor.get(IConfigurationService);
const visibility = layoutService.isVisible(Parts.TOOLBAR_PART);
const newVisibilityValue = !visibility;
configurationService.updateValue(ToggleToolBarVisibilityAction.toolBarVisibleKey, newVisibilityValue);
}
}
registerAction2(ToggleToolBarVisibilityAction);
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
group: '2_workbench_layout',
command: {
id: ToggleToolBarVisibilityAction.ID,
title: localize({ key: 'miShowToolBar', comment: ['&& denotes a mnemonic'] }, 'Show &&Tool Bar'),
toggled: ContextKeyExpr.equals('config.workbench.toolBar.visible', true)
},
order: 4
});
//kylin ide end, add Toggle Toolbar Layout
// --- Toggle Activity Bar
export class ToggleActivityBarVisibilityAction extends Action2 {
@ -1146,6 +1188,7 @@ if (!isMacintosh || !isNative) {
}
ToggleVisibilityActions.push(...[
CreateToggleLayoutItem(ToggleToolBarVisibilityAction.ID, ContextKeyExpr.equals('config.workbench.toolBar.visible', true), localize('toolBar', "Tool Bar"), toolbarIcon),
CreateToggleLayoutItem(ToggleActivityBarVisibilityAction.ID, ContextKeyExpr.equals('config.workbench.activityBar.visible', true), localize('activityBar', "Activity Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: activityBarLeftIcon, iconB: activityBarRightIcon }),
CreateToggleLayoutItem(ToggleSidebarVisibilityAction.ID, SideBarVisibleContext, localize('sideBar', "Primary Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelLeftIcon, iconB: panelRightIcon }),
CreateToggleLayoutItem(ToggleAuxiliaryBarAction.ID, AuxiliaryBarVisibleContext, localize('secondarySideBar', "Secondary Side Bar"), { whenA: ContextKeyExpr.equals('config.workbench.sideBar.location', 'left'), iconA: panelRightIcon, iconB: panelLeftIcon }),

View File

@ -50,6 +50,7 @@ import { ActivitybarPart } from 'vs/workbench/browser/parts/activitybar/activity
import { AuxiliaryBarPart } from 'vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { LayoutStateKeys, LayoutStateModel, WorkbenchLayoutSettings } from 'vs/workbench/browser/layoutState';
import { IToolBarService } from 'vs/workbench/services/toolbar/common/toolBarService';
interface IWorkbenchLayoutWindowRuntimeState {
fullscreen: boolean;
@ -90,6 +91,7 @@ enum WorkbenchLayoutClasses {
PANEL_HIDDEN = 'nopanel',
AUXILIARYBAR_HIDDEN = 'noauxiliarybar',
STATUSBAR_HIDDEN = 'nostatusbar',
TOOLBAR_HIDDEN = 'notoolbar',
FULLSCREEN = 'fullscreen',
MAXIMIZED = 'maximized',
WINDOW_BORDER = 'border'
@ -168,6 +170,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
private auxiliaryBarPartView!: ISerializableView;
private editorPartView!: ISerializableView;
private statusBarPartView!: ISerializableView;
//kylin ide --- start
private toolBarPartView!: ISerializableView;
//kylin ide --- end
private environmentService!: IBrowserWorkbenchEnvironmentService;
private extensionService!: IExtensionService;
@ -221,6 +226,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
this.notificationService = accessor.get(INotificationService);
this.statusBarService = accessor.get(IStatusbarService);
accessor.get(IBannerService);
//kylin ide --- start
accessor.get(IToolBarService);
//kylin ide --- end
// Listeners
this.registerLayoutListeners();
@ -449,6 +457,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
this.setPanelAlignment(change.value as PanelAlignment);
}
if (change.key === LayoutStateKeys.TOOLBAR_HIDDEN) {
this.setToolBarHidden(change.value as boolean);
}
this.doUpdateLayoutConfiguration();
});
@ -951,6 +963,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
return !this.stateModel.getRuntimeValue(LayoutStateKeys.ACTIVITYBAR_HIDDEN);
case Parts.EDITOR_PART:
return !this.stateModel.getRuntimeValue(LayoutStateKeys.EDITOR_HIDDEN);
case Parts.TOOLBAR_PART:
return !this.stateModel.getRuntimeValue(LayoutStateKeys.TOOLBAR_HIDDEN);
default:
return false; // any other part cannot be hidden
}
@ -971,6 +985,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
return !this.stateModel.getRuntimeValue(LayoutStateKeys.ACTIVITYBAR_HIDDEN);
case Parts.EDITOR_PART:
return !this.stateModel.getRuntimeValue(LayoutStateKeys.EDITOR_HIDDEN);
case Parts.TOOLBAR_PART:
return !this.stateModel.getRuntimeValue(LayoutStateKeys.TOOLBAR_HIDDEN);
default:
return false; // any other part cannot be hidden
}
@ -1028,6 +1044,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
const takenHeight =
(this.isVisible(Parts.TITLEBAR_PART) ? this.titleBarPartView.minimumHeight : 0) +
(this.isVisible(Parts.TOOLBAR_PART) ? this.toolBarPartView.minimumHeight : 0) +
(this.isVisible(Parts.STATUSBAR_PART) ? this.statusBarPartView.minimumHeight : 0) +
(this.isVisible(Parts.PANEL_PART) && !isColumn ? this.panelPartView.minimumHeight : 0);
@ -1195,6 +1212,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
const auxiliaryBarPart = this.getPart(Parts.AUXILIARYBAR_PART);
const sideBar = this.getPart(Parts.SIDEBAR_PART);
const statusBar = this.getPart(Parts.STATUSBAR_PART);
// kylin ide --- start
// Add toolbar
const toolBar = this.getPart(Parts.TOOLBAR_PART);
// kylin ide --- end
// View references for all parts
this.titleBarPartView = titleBar;
@ -1205,6 +1226,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
this.panelPartView = panelPart;
this.auxiliaryBarPartView = auxiliaryBarPart;
this.statusBarPartView = statusBar;
//kylin ide --- start
this.toolBarPartView = toolBar;
//kylin ide --- end
const viewMap = {
[Parts.ACTIVITYBAR_PART]: this.activityBarPartView,
@ -1214,7 +1238,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
[Parts.PANEL_PART]: this.panelPartView,
[Parts.SIDEBAR_PART]: this.sideBarPartView,
[Parts.STATUSBAR_PART]: this.statusBarPartView,
[Parts.AUXILIARYBAR_PART]: this.auxiliaryBarPartView
[Parts.AUXILIARYBAR_PART]: this.auxiliaryBarPartView,
//kylin ide --- start
[Parts.TOOLBAR_PART]: this.toolBarPartView
//kylin ide --- end
};
const fromJSON = ({ type }: { type: Parts }) => viewMap[type];
@ -1229,7 +1256,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
this.workbenchGrid = workbenchGrid;
this.workbenchGrid.edgeSnapping = this.windowState.runtime.fullscreen;
for (const part of [titleBar, editorPart, activityBar, panelPart, sideBar, statusBar, auxiliaryBarPart]) {
//add toolbar
for (const part of [titleBar, editorPart, activityBar, panelPart, sideBar, statusBar, auxiliaryBarPart, toolBar]) {
this._register(part.onDidVisibilityChange((visible) => {
if (part === sideBar) {
this.setSideBarHidden(!visible, true);
@ -1396,6 +1424,22 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
}
//kylin ide --- start : set tool bar hidden
setToolBarHidden(hidden: boolean, skipLayout?: boolean): void {
this.stateModel.setRuntimeValue(LayoutStateKeys.TOOLBAR_HIDDEN, hidden);
// Adjust CSS
if (hidden) {
this.container.classList.add(WorkbenchLayoutClasses.TOOLBAR_HIDDEN);
} else {
this.container.classList.remove(WorkbenchLayoutClasses.TOOLBAR_HIDDEN);
}
// Propagate to grid
this.workbenchGrid.setViewVisible(this.toolBarPartView, !hidden);
}
//kylin ide --- end : set tool bar hidden
private setActivityBarHidden(hidden: boolean, skipLayout?: boolean): void {
// Propagate to grid
this.stateModel.setRuntimeValue(LayoutStateKeys.ACTIVITYBAR_HIDDEN, hidden);
@ -1432,6 +1476,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
!this.isVisible(Parts.PANEL_PART) ? WorkbenchLayoutClasses.PANEL_HIDDEN : undefined,
!this.isVisible(Parts.AUXILIARYBAR_PART) ? WorkbenchLayoutClasses.AUXILIARYBAR_HIDDEN : undefined,
!this.isVisible(Parts.STATUSBAR_PART) ? WorkbenchLayoutClasses.STATUSBAR_HIDDEN : undefined,
!this.isVisible(Parts.TOOLBAR_PART) ? WorkbenchLayoutClasses.TOOLBAR_HIDDEN : undefined,
this.windowState.runtime.fullscreen ? WorkbenchLayoutClasses.FULLSCREEN : undefined
]);
}
@ -1499,20 +1544,20 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
const preMoveAuxiliaryBarSize = !this.isVisible(Parts.AUXILIARYBAR_PART) ? Sizing.Invisible(this.workbenchGrid.getViewCachedVisibleSize(this.auxiliaryBarPartView) ?? this.auxiliaryBarPartView.minimumWidth) : this.workbenchGrid.getViewSize(this.auxiliaryBarPartView).width;
if (sideBarPosition === Position.LEFT) {
this.workbenchGrid.moveViewTo(this.activityBarPartView, [2, 0]);
this.workbenchGrid.moveViewTo(this.activityBarPartView, [3, 0]);
this.workbenchGrid.moveView(this.sideBarPartView, preMoveSideBarSize, sideBarSiblingToEditor ? this.editorPartView : this.activityBarPartView, sideBarSiblingToEditor ? Direction.Left : Direction.Right);
if (auxiliaryBarSiblingToEditor) {
this.workbenchGrid.moveView(this.auxiliaryBarPartView, preMoveAuxiliaryBarSize, this.editorPartView, Direction.Right);
} else {
this.workbenchGrid.moveViewTo(this.auxiliaryBarPartView, [2, -1]);
this.workbenchGrid.moveViewTo(this.auxiliaryBarPartView, [3, -1]);
}
} else {
this.workbenchGrid.moveViewTo(this.activityBarPartView, [2, -1]);
this.workbenchGrid.moveViewTo(this.activityBarPartView, [3, -1]);
this.workbenchGrid.moveView(this.sideBarPartView, preMoveSideBarSize, sideBarSiblingToEditor ? this.editorPartView : this.activityBarPartView, sideBarSiblingToEditor ? Direction.Right : Direction.Left);
if (auxiliaryBarSiblingToEditor) {
this.workbenchGrid.moveView(this.auxiliaryBarPartView, preMoveAuxiliaryBarSize, this.editorPartView, Direction.Left);
} else {
this.workbenchGrid.moveViewTo(this.auxiliaryBarPartView, [2, 0]);
this.workbenchGrid.moveViewTo(this.auxiliaryBarPartView, [3, 0]);
}
}
@ -1736,6 +1781,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
return this.setAuxiliaryBarHidden(hidden);
case Parts.PANEL_PART:
return this.setPanelHidden(hidden);
case Parts.TOOLBAR_PART:
return this.setToolBarHidden(hidden);
}
}
@ -1899,7 +1946,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
for (const neighborView of neighborViews) {
const neighborPart =
[Parts.ACTIVITYBAR_PART, Parts.EDITOR_PART, Parts.PANEL_PART, Parts.AUXILIARYBAR_PART, Parts.SIDEBAR_PART, Parts.STATUSBAR_PART, Parts.TITLEBAR_PART]
[Parts.ACTIVITYBAR_PART, Parts.EDITOR_PART, Parts.PANEL_PART, Parts.AUXILIARYBAR_PART, Parts.SIDEBAR_PART, Parts.STATUSBAR_PART, Parts.TOOLBAR_PART, Parts.TITLEBAR_PART]
.find(partId => this.getPart(partId) === neighborView && this.isVisible(partId));
if (neighborPart !== undefined) {
@ -2023,7 +2070,13 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
const bannerHeight = this.bannerPartView.minimumHeight;
const statusBarHeight = this.statusBarPartView.minimumHeight;
const activityBarWidth = this.activityBarPartView.minimumWidth;
const middleSectionHeight = height - titleBarHeight - statusBarHeight;
// kylin ide --- start
// Add toolbar
const toolBarHeight = this.toolBarPartView.minimumHeight;
// const middleRightSectionwidth = width - (this.stateModel.getRuntimeValue(LayoutStateKeys.TOOLBAR_VISIBLE) ? 0 : activityBarWidth);
// kylin ide --- end
const middleSectionHeight = height - titleBarHeight - statusBarHeight - toolBarHeight;
const activityBarNode: ISerializedLeafNode = {
type: 'leaf',
@ -2086,6 +2139,12 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
size: bannerHeight,
visible: false
},
{
type: 'leaf',
data: { type: Parts.TOOLBAR_PART },
size: toolBarHeight,
visible: !this.stateModel.getRuntimeValue(LayoutStateKeys.TOOLBAR_HIDDEN)
},
{
type: 'branch',
data: middleSection,

View File

@ -75,6 +75,7 @@ export const LayoutStateKeys = {
PANEL_HIDDEN: new RuntimeStateKey<boolean>('panel.hidden', StorageScope.WORKSPACE, StorageTarget.USER, true),
AUXILIARYBAR_HIDDEN: new RuntimeStateKey<boolean>('auxiliaryBar.hidden', StorageScope.WORKSPACE, StorageTarget.USER, true),
STATUSBAR_HIDDEN: new RuntimeStateKey<boolean>('statusBar.hidden', StorageScope.WORKSPACE, StorageTarget.USER, false, true),
TOOLBAR_HIDDEN: new RuntimeStateKey<boolean>('toolBar.hidden', StorageScope.WORKSPACE, StorageTarget.USER, false, true),
} as const;
@ -112,6 +113,10 @@ export class LayoutStateModel extends Disposable {
if (configurationChangeEvent.affectsConfiguration(LegacyWorkbenchLayoutSettings.SIDEBAR_POSITION)) {
this.setRuntimeValueAndFire(LayoutStateKeys.SIDEBAR_POSITON, positionFromString(this.configurationService.getValue(LegacyWorkbenchLayoutSettings.SIDEBAR_POSITION) ?? 'left'));
}
if (configurationChangeEvent.affectsConfiguration(LegacyWorkbenchLayoutSettings.TOOLBAR_VISIBLE)) {
this.setRuntimeValueAndFire(LayoutStateKeys.TOOLBAR_HIDDEN, !this.configurationService.getValue(LegacyWorkbenchLayoutSettings.TOOLBAR_VISIBLE));
}
}
private updateLegacySettingsFromState<T extends StorageKeyType>(key: RuntimeStateKey<T>, value: T): void {
@ -126,6 +131,8 @@ export class LayoutStateModel extends Disposable {
this.configurationService.updateValue(LegacyWorkbenchLayoutSettings.STATUSBAR_VISIBLE, !value);
} else if (key === LayoutStateKeys.SIDEBAR_POSITON) {
this.configurationService.updateValue(LegacyWorkbenchLayoutSettings.SIDEBAR_POSITION, positionToString(value as Position));
} else if (key === LayoutStateKeys.STATUSBAR_HIDDEN) {
this.configurationService.updateValue(LegacyWorkbenchLayoutSettings.TOOLBAR_VISIBLE, !value);
}
}
@ -146,6 +153,7 @@ export class LayoutStateModel extends Disposable {
this.stateCache.set(LayoutStateKeys.ACTIVITYBAR_HIDDEN.name, !this.configurationService.getValue(LegacyWorkbenchLayoutSettings.ACTIVITYBAR_VISIBLE));
this.stateCache.set(LayoutStateKeys.STATUSBAR_HIDDEN.name, !this.configurationService.getValue(LegacyWorkbenchLayoutSettings.STATUSBAR_VISIBLE));
this.stateCache.set(LayoutStateKeys.SIDEBAR_POSITON.name, positionFromString(this.configurationService.getValue(LegacyWorkbenchLayoutSettings.SIDEBAR_POSITION) ?? 'left'));
this.stateCache.set(LayoutStateKeys.TOOLBAR_HIDDEN.name, !this.configurationService.getValue(LegacyWorkbenchLayoutSettings.TOOLBAR_VISIBLE));
// Set dynamic defaults: part sizing and side bar visibility
const workbenchDimensions = getClientArea(this.container);
@ -222,6 +230,8 @@ export class LayoutStateModel extends Disposable {
case LayoutStateKeys.SIDEBAR_POSITON:
this.stateCache.set(key.name, this.configurationService.getValue(LegacyWorkbenchLayoutSettings.SIDEBAR_POSITION) ?? 'left');
break;
case LayoutStateKeys.TOOLBAR_HIDDEN:
this.stateCache.set(key.name, this.configurationService.getValue(LegacyWorkbenchLayoutSettings.TOOLBAR_VISIBLE));
}
}
@ -282,4 +292,5 @@ enum LegacyWorkbenchLayoutSettings {
ACTIVITYBAR_VISIBLE = 'workbench.activityBar.visible', // Deprecated to UI State
STATUSBAR_VISIBLE = 'workbench.statusBar.visible', // Deprecated to UI State
SIDEBAR_POSITION = 'workbench.sideBar.location', // Deprecated to UI State
TOOLBAR_VISIBLE = 'workbench.toolBar.visible',
}

View File

@ -0,0 +1,132 @@
/*----------------------------------------------------------------------------
* Copyright (c) KylinIdeTeam. 2022-2023. All rights reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* --------------------------------------------------------------------------- */
.monaco-workbench .part.toolbar {
box-sizing: border-box;
width: 100%;
padding: 0 70px;
overflow: hidden;
flex-shrink: 0;
align-items: center;
justify-content: center;
user-select: none;
-webkit-user-select: none;
zoom: 1;
/* prevent zooming */
line-height: 22px;
height: 22px;
display: flex;
}
.monaco-workbench .part.toolbar>.toolbar-drag-region {
top: 0;
left: 0;
display: block;
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
-webkit-app-region: drag;
}
.monaco-workbench .part.toolbar>.toolbar-title {
display: flex;
align-items: center;
height: 100%;
margin-left: 5px;
/* flex: 0 1 auto;
font-size: 16px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-left: auto;
margin-right: auto;
zoom: 1; prevent zooming */
}
.toolbar-title>.tool-item {
/* padding: 0 4px 3px; */
display: flex;
align-items: center;
height: 100%;
/* position: relative; */
margin: 3px 3px 0 3px;
}
.tool-item>.tool-item-icon {
width: 24px;
height: 24px;
cursor: pointer;
text-align: center;
/* vertical-align: middle; */
/* border:1px solid transparent; */
}
.tool-item-icon:hover {
/* background: #4d4d4d; */
border: 1px solid;
border-radius: 2px;
box-sizing: border-box;
}
.tool-item-icon:active {
/* background: #303030; */
border: 0px solid #6e6e6e;
border-radius: 2px;
box-sizing: border-box;
}
.tool-item-icon>.iconimg {
width: 18px;
height: 18px;
/* vertical-align: middle; */
display: inline-block;
}
/* Windows/Linux: Rules for custom title (icon, window controls) */
.monaco-workbench.web .part.toolbar,
.monaco-workbench.windows .part.toolbar,
.monaco-workbench.linux .part.toolbar {
padding: 0;
height: 30px;
line-height: 30px;
justify-content: left;
overflow: visible;
}
.monaco-workbench.web .part.toolbar>.window-title,
.monaco-workbench.windows .part.toolbar>.window-title,
.monaco-workbench.linux .part.toolbar>.window-title {
cursor: default;
}
.monaco-workbench.linux .part.toolbar>.window-title {
font-size: inherit;
}
.monaco-workbench.windows .part.toolbar>.resizer,
.monaco-workbench.linux .part.toolbar>.resizer {
-webkit-app-region: no-drag;
position: absolute;
top: 0;
width: 100%;
height: 20%;
}
.monaco-workbench.windows.fullscreen .part.toolbar>.resizer,
.monaco-workbench.linux.fullscreen .part.toolbar>.resizer {
display: none;
}

View File

@ -0,0 +1,408 @@
/*----------------------------------------------------------------------------
* Copyright (c) KylinIdeTeam. 2022-2023. All rights reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* --------------------------------------------------------------------------- */
import 'vs/css!./media/toolbarpart';
import { localize } from 'vs/nls';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { Part } from 'vs/workbench/browser/part';
import { MENUBAR_SELECTION_BACKGROUND, MENUBAR_SELECTION_BORDER, TITLE_BAR_ACTIVE_BACKGROUND, TITLE_BAR_BORDER, WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { URI } from 'vs/base/common/uri';
import { registerColor, transparent } from 'vs/platform/theme/common/colorRegistry';
import { Color } from 'vs/base/common/color';
import { addDisposableListener, EventHelper, EventType, $ } from 'vs/base/browser/dom';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { FileAccess } from 'vs/base/common/network';
import { IToolBarService } from 'vs/workbench/services/toolbar/common/toolBarService';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { IAction, toAction } from 'vs/base/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { dispose } from 'vs/base/common/lifecycle';
import { ToggleToolBarVisibilityAction } from 'vs/workbench/browser/actions/layoutActions';
import { Codicon, CSSIcon } from 'vs/base/common/codicons';
import { isWeb } from 'vs/base/common/platform';
// import { isMacintosh } from 'vs/base/common/platform';
// import { OpenFileFolderAction, OpenFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
export class ToolbarPart extends Part implements IToolBarService {
declare readonly _serviceBrand: undefined;
readonly minimumWidth: number = 0;
readonly maximumWidth: number = Number.POSITIVE_INFINITY;
readonly minimumHeight: number = 34;
readonly maximumHeight: number = 34;
constructor(
@IStorageService storageService: IStorageService,
@IThemeService themeService: IThemeService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IInstantiationService protected readonly instantiationService: IInstantiationService,
@ICommandService private readonly commandService: ICommandService,
@IContextMenuService private contextMenuService: IContextMenuService,
) {
super(Parts.TOOLBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
}
override createContentArea(parent: HTMLElement): HTMLElement {
this.element = parent;
const content = document.createElement('div');
content.classList.add('toolbar-title');
this.element.appendChild(content);
const toolitem = [
// 新建文本文件
{
url: FileAccess.asFileUri('./media/newfile.svg', require),
command: 'workbench.action.files.newUntitledFile',
arg: '',
title: localize('newFile', 'New Text File') + '(Ctrl+N)',
icon: Codicon.newFile
},
// 新建窗口
{
url: FileAccess.asFileUri('./media/newWindow.svg', require),
command: 'workbench.action.newWindow',
arg: '',
title: localize('newWindow', 'New Window') + '(Ctrl+Shift+N)',
icon: Codicon.emptyWindow
},
// //打开文件夹,有问题
// {
// url: FileAccess.asFileUri('./media/create.svg', require),
// command: isMacintosh ? 'workbench.action.files.openFileFolder' : 'workbench.action.files.openFolder',
// arg: '',
// title: localize('openFolder', 'Open Folder') + '(Ctrl+K Ctrl+O)',
// icon: Codicon.folderOpened
// },
// 撤销
{
url: FileAccess.asFileUri('./media/cancel.svg', require),
command: 'undo',
arg: '',
title: localize('undo', 'Undo') + '(Ctrl+Z)',
icon: Codicon.discard
},
//恢复
{
url: FileAccess.asFileUri('./media/redo.svg', require),
command: 'redo',
arg: '',
title: localize('redo', 'Redo') + '(Ctrl+Y)',
icon: Codicon.redo
},
// 返回
{
url: FileAccess.asFileUri('./media/back.svg', require),
command: 'workbench.action.navigateBack',
arg: '',
title: localize('navigatePrevious', 'Go Back') + '(Alt+LeftArrow)',
icon: Codicon.arrowLeft//Codicon.chevronLeft
},
//前进
{
url: FileAccess.asFileUri('./media/goahead.svg', require),
command: 'workbench.action.navigateForward',
arg: '',
title: localize('navigateNext', 'Go Forward') + '(Alt+RightArrow)',
icon: Codicon.arrowRight//Codicon.chevronRight
},
// 向上移动一行
{
url: FileAccess.asFileUri('./media/moveLinesUp.svg', require),
command: 'editor.action.moveLinesUpAction',
arg: '',
title: localize('moveLinesUp', 'moveLinesUp') + '(Alt+RightArrow)',
icon: Codicon.arrowUp
},
// 向下移动一行
{
url: FileAccess.asFileUri('./media/moveLinesDown.svg', require),
command: 'editor.action.moveLinesDownAction',
arg: '',
title: localize('moveLinesDown', 'moveLinesDown') + '(Alt+LeftArrow)',
icon: Codicon.arrowDown
},
//打开explorer
{
url: FileAccess.asFileUri('./media/explorer.svg', require),
command: 'workbench.view.explorer',
arg: '',
title: localize('explorer', 'explorer') + '(Ctrl+Shift+E)',
icon: Codicon.files
},
//开启搜索
{
url: FileAccess.asFileUri('./media/search.svg', require),
command: 'workbench.view.search',
arg: '',
title: localize('Search', 'Search') + '(Ctrl+Shift+F)',
icon: Codicon.search
},
//打开源代码管理
{
url: FileAccess.asFileUri('./media/scm.svg', require),
command: 'workbench.view.scm',
arg: '',
title: localize('Scm', 'Source Control') + '(Ctrl+Shift+G G)',
icon: Codicon.sourceControl
},
//打开debug
{
url: FileAccess.asFileUri('./media/debug.svg', require),
command: 'workbench.view.debug',
arg: '',
title: localize('Run and Debug', 'Run and Debug') + '(Ctrl+Shift+D)',
icon: Codicon.debugAlt
},
//开启插件
{
url: FileAccess.asFileUri('./media/extensions.svg', require),
command: 'workbench.view.extensions',
arg: '',
title: localize('Extensions', 'Extensions') + '(Ctrl+Shift+X)',
icon: Codicon.extensions
},
//开启关闭终端
{
url: FileAccess.asFileUri('./media/command.svg', require),
command: 'workbench.action.terminal.toggleTerminal',
arg: '',
title: localize('Terminal', 'Terminal') + '(Ctrl+`)',
icon: Codicon.terminal
},
//打开键盘快捷方式
{
url: FileAccess.asFileUri('./media/keyboardShortcuts.svg', require),
command: 'workbench.action.openGlobalKeybindings',
arg: '',
title: localize('KeyboardShortcuts', 'Keyboard Shortcuts') + '(Ctrl+K Ctrl+S)',
icon: Codicon.keyboard
},
//打开设置
{
url: FileAccess.asFileUri('./media/config-dark.svg', require),
command: 'workbench.action.openSettings',
arg: '',
title: localize('Settings', 'Settings') + '(Ctrl+,)',
icon: Codicon.gear
},
//图片问题svg不显示注释
// {
// url: FileAccess.asFileUri('./media/siderbar.svg', require),
// command: 'workbench.action.toggleSidebarVisibility',
// arg: '',
// title: localize('Siderbar', 'Siderbar') + '(Ctrl+B)',
// icon: undefined
// },
// {
// url: FileAccess.asFileUri('./media/panel.svg', require),
// command: 'workbench.action.togglePanel',
// arg: '',
// title: localize('Panel', 'Panel') + '(Ctrl+J)',
// icon: undefined
// },
//放大窗体
{
url: FileAccess.asFileUri('./media/zoomIn.svg', require),
command: 'workbench.action.zoomIn',
arg: '',
title: localize('ZoomIn', 'ZoomIn') + '(Ctrl+=)',
icon: Codicon.zoomIn
},
//缩小窗体
{
url: FileAccess.asFileUri('./media/zoomOut.svg', require),
command: 'workbench.action.zoomOut',
arg: '',
title: localize('ZoomOut', 'ZoomOut') + '(Ctrl+-)',
icon: Codicon.zoomOut
},
//全屏模式
{
url: FileAccess.asFileUri('./media/screenFull.svg', require),
command: 'workbench.action.toggleFullScreen',
arg: '',
title: localize('FullScreen', 'FullScreen') + '(F11)',
icon: Codicon.screenFull
},
//禅模式
{
url: FileAccess.asFileUri('./media/zenMode.svg', require),
command: 'workbench.action.toggleZenMode',
arg: '',
title: localize('ZenMode', 'ZenMode') + '(Ctrl+K Z)',
icon: Codicon.target
}
];
//添加分隔竖线
toolitem.forEach(item => {
if (item.command === 'undo' || item.command === 'workbench.view.explorer' || item.command === 'workbench.action.zoomIn') {
const toolitem = document.createElement('div');
toolitem.style.margin = '0 5px 0 5px';
toolitem.style.height = '23px';
toolitem.style.border = '0.5px solid';
toolitem.style.borderColor = '#5C5C5C';
content.appendChild(toolitem);
}
if (isWeb && (item.command === 'workbench.action.zoomIn' || item.command === 'workbench.action.zoomOut')) {
return;
}
this.createToolitem(content, item.url, item.command, item.arg, item.title, item.icon);
});
this.updateStyles();
// Context menu support 鼠标右键菜单
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e)));
return this.element;
}
private createToolitem(parent: HTMLElement, url: URI, cmd: string, arg: string, title: string, icon?: Codicon | undefined): void {
const toolitem = document.createElement('div');
toolitem.classList.add('tool-item');
const toolitemicon = document.createElement('div');
toolitemicon.classList.add('tool-item-icon');
//没有使用url的图片地址使用IDE中的默认icon
if (icon === undefined) {
const img = document.createElement('img');
img.title = title;
img.classList.add('tool-item-icon');
img.src = url.toString(true);
toolitemicon.appendChild(img);
} else {
const node = $(`span`);
node.title = title;
node.classList.add(...CSSIcon.asClassNameArray(icon));
toolitemicon.appendChild(node);
}
toolitem.appendChild(toolitemicon);
parent.appendChild(toolitem);
if (cmd.length > 0) {
this._register(addDisposableListener(toolitem, EventType.MOUSE_DOWN, _e => {
if (arg.length > 0) {
this.commandService.executeCommand(cmd, arg);
}
else {
this.commandService.executeCommand(cmd);
}
}));
}
}
//显示右键菜单内容
private showContextMenu(e: MouseEvent): void {
EventHelper.stop(e, true);
const event = new StandardMouseEvent(e);
let actions: IAction[] | undefined = undefined;
this.contextMenuService.showContextMenu({
getAnchor: () => ({ x: event.posx, y: event.posy }),
getActions: () => {
actions = this.getContextMenuActions(event);
return actions;
},
onHide: () => {
if (actions) {
dispose(actions);
}
}
});
}
//add context action 填充鼠标右键菜单的事件
private getContextMenuActions(_event: StandardMouseEvent): IAction[] {
const actions: IAction[] = [];
// Toggle Tool Bar
actions.push(toAction({ id: ToggleToolBarVisibilityAction.ID, label: localize('hideToolBar', 'Hide Tool Bar'), run: async () => this.instantiationService.invokeFunction(accessor => new ToggleToolBarVisibilityAction().run(accessor)) }));
// 此处可添加右键菜单
return actions;
}
override updateStyles() {
super.updateStyles();
// Part container
if (this.element) {
const TOOL_BAR_BACKGROUND = registerColor('toolBar.background', {
dark: transparent(TITLE_BAR_ACTIVE_BACKGROUND, 0.7),
light: transparent(TITLE_BAR_ACTIVE_BACKGROUND, 0.8),
hcDark: Color.black, hcLight: Color.white
}, localize('toolBarBackground', 'Tool bar background'));
const toolbarBackground = this.getColor(TOOL_BAR_BACKGROUND, (color, theme) => {
return color.isOpaque() ? color : color.makeOpaque(WORKBENCH_BACKGROUND(theme));
}) || '';
this.element.style.backgroundColor = toolbarBackground;
if (toolbarBackground && Color.fromHex(toolbarBackground).isLighter()) {
this.element.classList.add('light');
} else {
this.element.classList.remove('light');
}
const toolbarBorder = this.getColor(TITLE_BAR_BORDER);
this.element.style.borderBottom = toolbarBorder ? `1px solid ${toolbarBorder}` : '';
}
}
override layout(width: number, height: number): void {
super.layoutContents(width, height);
}
toJSON(): object {
return {
type: Parts.TOOLBAR_PART
};
}
}
registerThemingParticipant((theme, collector) => {
const toolBarHoverBg = theme.getColor(MENUBAR_SELECTION_BACKGROUND);
if (toolBarHoverBg) {
collector.addRule(`
.tool-item-icon:hover {
background: ${toolBarHoverBg};
border: 0px solid;
}
`);
}
const toolBarActiveBg = theme.getColor(TITLE_BAR_ACTIVE_BACKGROUND);
if (toolBarActiveBg) {
collector.addRule(`
.tool-item-icon:active {
background: ${toolBarActiveBg};
}
`);
}
const toolBarHoverBd = theme.getColor(MENUBAR_SELECTION_BORDER);
if (toolBarHoverBd) {
collector.addRule(`
.tool-item-icon:hover {
border-color: ${toolBarHoverBd};
}
`);
}
});
registerSingleton(IToolBarService, ToolbarPart);

View File

@ -382,6 +382,11 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
'default': true,
'description': localize('statusBarVisibility', "Controls the visibility of the status bar at the bottom of the workbench.")
},
'workbench.toolBar.visible': {
'type': 'boolean',
'default': true,
'description': localize('toolBarVisibility', "Controls the visibility of the tool bar in the workbench.")
},
'workbench.activityBar.visible': {
'type': 'boolean',
'default': true,

View File

@ -339,6 +339,10 @@ export class Workbench extends Layout {
for (const { id, role, classes, options } of [
{ id: Parts.TITLEBAR_PART, role: 'contentinfo', classes: ['titlebar'] },
{ id: Parts.BANNER_PART, role: 'banner', classes: ['banner'] },
// kylin ide --- start
// Add toolbar
{ id: Parts.TOOLBAR_PART, role: 'none', classes: ['toolbar'] },
// kylin ide --- end
{ id: Parts.ACTIVITYBAR_PART, role: 'none', classes: ['activitybar', this.getSideBarPosition() === Position.LEFT ? 'left' : 'right'] }, // Use role 'none' for some parts to make screen readers less chatty #114892
{ id: Parts.SIDEBAR_PART, role: 'none', classes: ['sidebar', this.getSideBarPosition() === Position.LEFT ? 'left' : 'right'] },
{ id: Parts.EDITOR_PART, role: 'main', classes: ['editor'], options: { restorePreviousState: this.willRestoreEditors() } },

View File

@ -20,7 +20,10 @@ export const enum Parts {
PANEL_PART = 'workbench.parts.panel',
AUXILIARYBAR_PART = 'workbench.parts.auxiliarybar',
EDITOR_PART = 'workbench.parts.editor',
STATUSBAR_PART = 'workbench.parts.statusbar'
STATUSBAR_PART = 'workbench.parts.statusbar',
//kylin ide --- start
TOOLBAR_PART = 'workbench.parts.toolbar' /* TOOLBAR_PART */
//kylin ide --- end
}
export const enum Position {
@ -165,6 +168,11 @@ export interface IWorkbenchLayoutService extends ILayoutService {
*/
getDimension(part: Parts): Dimension | undefined;
/**
* Set tool bar hidden or not
*/
setToolBarHidden(hidden: boolean): void;
/**
* Set part hidden or not
*/

View File

@ -0,0 +1,26 @@
/*----------------------------------------------------------------------------
* Copyright (c) KylinIDETeam. 2022-2023. All rights reserved.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* --------------------------------------------------------------------------- */
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const IToolBarService = createDecorator<IToolBarService>('toolbarService');
export interface IToolBarService {
readonly _serviceBrand: undefined;
}

View File

@ -598,6 +598,7 @@ export class TestLayoutService implements IWorkbenchLayoutService {
isTitleBarHidden(): boolean { return false; }
isStatusBarHidden(): boolean { return false; }
isActivityBarHidden(): boolean { return false; }
setToolBarHidden(_hidden: boolean): void { }
setActivityBarHidden(_hidden: boolean): void { }
setBannerHidden(_hidden: boolean): void { }
isSideBarHidden(): boolean { return false; }

View File

@ -46,7 +46,9 @@ import 'vs/workbench/browser/parts/paneCompositePart';
import 'vs/workbench/browser/parts/banner/bannerPart';
import 'vs/workbench/browser/parts/statusbar/statusbarPart';
import 'vs/workbench/browser/parts/views/viewsService';
//kylin ide --- start
import 'vs/workbench/browser/parts/toolbar/toolbarPart';
//kylin ide --- end
//#endregion