diff --git a/extensions/notebook/package.json b/extensions/notebook/package.json
index 92243b400e..7825bedff5 100644
--- a/extensions/notebook/package.json
+++ b/extensions/notebook/package.json
@@ -131,8 +131,8 @@
"command": "jupyter.cmd.managePackages",
"title": "%title.managePackages%",
"icon": {
- "dark": "resources/dark/manage_inverse.svg",
- "light": "resources/light/manage.svg"
+ "dark": "resources/dark/packages_inverse.svg",
+ "light": "resources/light/packages.svg"
}
},
{
diff --git a/extensions/notebook/resources/dark/packages_inverse.svg b/extensions/notebook/resources/dark/packages_inverse.svg
new file mode 100644
index 0000000000..a46fb203d4
--- /dev/null
+++ b/extensions/notebook/resources/dark/packages_inverse.svg
@@ -0,0 +1,3 @@
+
diff --git a/extensions/notebook/resources/light/packages.svg b/extensions/notebook/resources/light/packages.svg
new file mode 100644
index 0000000000..5b75cda4c0
--- /dev/null
+++ b/extensions/notebook/resources/light/packages.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/sql/base/browser/ui/buttonMenu/buttonMenu.css b/src/sql/base/browser/ui/buttonMenu/buttonMenu.css
new file mode 100644
index 0000000000..3036c3afa3
--- /dev/null
+++ b/src/sql/base/browser/ui/buttonMenu/buttonMenu.css
@@ -0,0 +1,13 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+.button-menu .in-preview .monaco-dropdown {
+ height: auto;
+ padding: 0;
+}
+.button-menu.masked-pseudo-after.dropdown-arrow:after {
+ right: -2px;
+ width: 20px;
+}
diff --git a/src/sql/base/browser/ui/buttonMenu/buttonMenu.ts b/src/sql/base/browser/ui/buttonMenu/buttonMenu.ts
new file mode 100644
index 0000000000..81016ff455
--- /dev/null
+++ b/src/sql/base/browser/ui/buttonMenu/buttonMenu.ts
@@ -0,0 +1,113 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import 'vs/css!./buttonMenu';
+import { IAction, IActionRunner } from 'vs/base/common/actions';
+import { BaseActionViewItem, IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
+import { IDisposable } from 'vs/base/common/lifecycle';
+import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
+import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
+import { append, $, addClasses } from 'vs/base/browser/dom';
+import { IDropdownMenuOptions, DropdownMenu, IActionProvider, IContextMenuProvider, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';
+
+export class DropdownMenuActionViewItem extends BaseActionViewItem {
+ private menuActionsOrProvider: ReadonlyArray | IActionProvider;
+ private dropdownMenu: DropdownMenu | undefined;
+ private menuLabel?: string | undefined;
+ private contextMenuProvider: IContextMenuProvider;
+ private actionViewItemProvider?: IActionViewItemProvider;
+ private keybindings?: (action: IAction) => ResolvedKeybinding | undefined;
+ private cssClass: string | undefined;
+ private anchorAlignmentProvider: (() => AnchorAlignment) | undefined;
+
+ constructor(
+ action: IAction,
+ menuActionsOrProvider: ReadonlyArray | IActionProvider,
+ contextMenuProvider: IContextMenuProvider,
+ actionViewItemProvider: IActionViewItemProvider | undefined,
+ actionRunner: IActionRunner,
+ keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined,
+ cssClass: string | undefined,
+ menuLabel: string | undefined,
+ anchorAlignmentProvider?: () => AnchorAlignment) {
+
+ super(null, action);
+
+ this.menuActionsOrProvider = menuActionsOrProvider;
+ this.contextMenuProvider = contextMenuProvider;
+ this.actionViewItemProvider = actionViewItemProvider;
+ this.actionRunner = actionRunner;
+ this.keybindings = keybindings;
+ this.cssClass = cssClass;
+ this.menuLabel = menuLabel;
+ this.anchorAlignmentProvider = anchorAlignmentProvider;
+ }
+
+ render(container: HTMLElement): void {
+ const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {
+ this.element = append(el, $('a.action-label.button-menu'));
+ if (this.cssClass) {
+ addClasses(this.element, this.cssClass);
+ }
+ if (this.menuLabel) {
+ this.element.innerText = this.menuLabel;
+ }
+
+ this.element.tabIndex = 0;
+ this.element.setAttribute('role', 'button');
+ this.element.setAttribute('aria-haspopup', 'true');
+ this.element.title = this._action.label || '';
+
+ return null;
+ };
+
+ const options: IDropdownMenuOptions = {
+ contextMenuProvider: this.contextMenuProvider,
+ labelRenderer: labelRenderer
+ };
+
+ // Render the DropdownMenu around a simple action to toggle it
+ if (Array.isArray(this.menuActionsOrProvider)) {
+ options.actions = this.menuActionsOrProvider;
+ } else {
+ options.actionProvider = this.menuActionsOrProvider as IActionProvider;
+ }
+
+ this.dropdownMenu = this._register(new DropdownMenu(container, options));
+ this.dropdownMenu.menuOptions = {
+ actionViewItemProvider: this.actionViewItemProvider,
+ actionRunner: this.actionRunner,
+ getKeyBinding: this.keybindings,
+ context: this._context
+ };
+
+ if (this.anchorAlignmentProvider) {
+ const that = this;
+
+ this.dropdownMenu.menuOptions = {
+ ...this.dropdownMenu.menuOptions,
+ get anchorAlignment(): AnchorAlignment {
+ return that.anchorAlignmentProvider!();
+ }
+ };
+ }
+ }
+
+ setActionContext(newContext: unknown): void {
+ super.setActionContext(newContext);
+
+ if (this.dropdownMenu) {
+ if (this.dropdownMenu.menuOptions) {
+ this.dropdownMenu.menuOptions.context = newContext;
+ } else {
+ this.dropdownMenu.menuOptions = { context: newContext };
+ }
+ }
+ }
+
+ show(): void {
+ this.dropdownMenu?.show();
+ }
+}
diff --git a/src/sql/base/browser/ui/selectBox/media/selectBox.css b/src/sql/base/browser/ui/selectBox/media/selectBox.css
index 9263b51613..c8bb8fc244 100644
--- a/src/sql/base/browser/ui/selectBox/media/selectBox.css
+++ b/src/sql/base/browser/ui/selectBox/media/selectBox.css
@@ -15,6 +15,10 @@
}
.monaco-select-box {
- padding: 2px 8px;
- padding: 0 22px 0 6px !important; /* I don't like this but for now its fine */
+ padding: 0 22px 0 6px;
+}
+
+.monaco-inputbox > .wrapper > .input,
+.monaco-inputbox > .wrapper > .mirror {
+ padding-left: 6px !important;
}
diff --git a/src/sql/base/browser/ui/taskbar/media/taskbar.css b/src/sql/base/browser/ui/taskbar/media/taskbar.css
index 3fcd52d63e..acec293244 100644
--- a/src/sql/base/browser/ui/taskbar/media/taskbar.css
+++ b/src/sql/base/browser/ui/taskbar/media/taskbar.css
@@ -26,6 +26,7 @@
}
.carbon-taskbar.monaco-toolbar .monaco-action-bar.animated .actions-container {
+ box-sizing: border-box;
justify-content: flex-start;
padding-left: 15px;
flex-wrap: wrap;
diff --git a/src/sql/media/icons/action-collapse.svg b/src/sql/media/icons/action-collapse.svg
new file mode 100644
index 0000000000..955f68a2af
--- /dev/null
+++ b/src/sql/media/icons/action-collapse.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/sql/media/icons/action-expand.svg b/src/sql/media/icons/action-expand.svg
new file mode 100644
index 0000000000..6cf95b4505
--- /dev/null
+++ b/src/sql/media/icons/action-expand.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/sql/media/icons/clear.svg b/src/sql/media/icons/clear.svg
new file mode 100644
index 0000000000..ad97fac74d
--- /dev/null
+++ b/src/sql/media/icons/clear.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/sql/media/icons/code.svg b/src/sql/media/icons/code.svg
new file mode 100644
index 0000000000..083e3729dc
--- /dev/null
+++ b/src/sql/media/icons/code.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/sql/media/icons/common-icons.css b/src/sql/media/icons/common-icons.css
index 467b2c3429..f85aae7cc2 100644
--- a/src/sql/media/icons/common-icons.css
+++ b/src/sql/media/icons/common-icons.css
@@ -4,12 +4,12 @@
*--------------------------------------------------------------------------------------------*/
.vs .codicon.settings {
- background-image: url('settings.svg');
+ background-image: url("settings.svg");
}
.vs-dark .codicon.settings,
.hc-black .codicon.settings {
- background-image: url('settings_inverse.svg');
+ background-image: url("settings_inverse.svg");
}
.vs .codicon.backup,
@@ -123,21 +123,21 @@
.vs .codicon.scriptToClipboard,
.vs-dark .codicon.scriptToClipboard,
.hc-black .codicon.scriptToClipboard {
- background-image: url('script_to_clipboard.svg');
+ background-image: url("script_to_clipboard.svg");
background-repeat: no-repeat;
background-position: 2px center;
}
.vs .codicon.close,
.vs .codicon.remove {
- background: url('close.svg') center center no-repeat !important;
+ background: url("close.svg") center center no-repeat !important;
}
.vs-dark .codicon.close,
.hc-black .codicon.close,
.vs-dark .codicon.remove,
.hc-black .codicon.remove {
- background: url('close_inverse.svg') center center no-repeat !important;
+ background: url("close_inverse.svg") center center no-repeat !important;
}
.vs .codicon.filter {
@@ -181,20 +181,20 @@
.hc-black .codicon.toggle-more,
.vs-dark .codicon.toggle-more {
- background: url('ellipsis-inverse.svg') center center no-repeat;
+ background: url("ellipsis-inverse.svg") center center no-repeat;
}
.vs .codicon.toggle-more {
- background: url('ellipsis.svg') center center no-repeat;
+ background: url("ellipsis.svg") center center no-repeat;
}
.hc-black .codicon.new,
.vs-dark .codicon.new {
- background: url('new_inverse.svg') center center no-repeat;
+ background: url("new_inverse.svg") center center no-repeat;
}
.vs .codicon.new {
- background: url('new.svg') center center no-repeat;
+ background: url("new.svg") center center no-repeat;
}
.vs .codicon.new-query,
@@ -206,7 +206,7 @@
.vs .codicon.configure-dashboard,
.hc-black .codicon.configure-dashboard,
.vs-dark .codicon.configure-dashboard {
- background: url('configuredashboard.svg') center center no-repeat;
+ background: url("configuredashboard.svg") center center no-repeat;
}
.vs .codicon.edit,
@@ -217,95 +217,212 @@
.hc-black .codicon.pin,
.vs-dark .codicon.pin {
- background: url('pin_inverse.svg') center center no-repeat;
+ background: url("pin_inverse.svg") center center no-repeat;
}
.vs .codicon.pin {
- background: url('pin.svg') center center no-repeat;
+ background: url("pin.svg") center center no-repeat;
}
.hc-black .codicon.unpin,
.vs-dark .codicon.unpin {
- background: url('unpin_inverse.svg') center center no-repeat;
+ background: url("unpin_inverse.svg") center center no-repeat;
}
.vs .codicon.unpin {
- background: url('unpin.svg') center center no-repeat;
+ background: url("unpin.svg") center center no-repeat;
}
.vs .sql.codicon.pause {
- background-image: url('pause.svg')
+ background-image: url("pause.svg");
}
.vs-dark .sql.codicon.pause,
.hc-black .sql.codicon.pause {
- background-image: url('pause_inverse.svg')
+ background-image: url("pause_inverse.svg");
}
.vs .sql.codicon.continue {
- background-image: url('continue.svg')
+ background-image: url("continue.svg");
}
.vs-dark .sql.codicon.continue,
.hc-black .sql.codicon.continue {
- background-image: url('continue_inverse.svg')
+ background-image: url("continue_inverse.svg");
}
.vs .sql.codicon.checked {
- background-image: url('check.svg')
+ background-image: url("check.svg");
}
.vs-dark .sql.codicon.checked,
.hc-black .sql.codicon.checked {
- background-image: url('check_inverse.svg')
+ background-image: url("check_inverse.svg");
}
.vs .sql.codicon.start {
- background-image: url('start.svg')
+ background-image: url("start.svg");
}
.vs-dark .sql.codicon.start,
.hc-black .sql.codicon.start {
- background-image: url('start_inverse.svg')
+ background-image: url("start_inverse.svg");
}
.vs .sql.codicon.stop {
- background-image: url('stop.svg')
+ background-image: url("stop.svg");
}
.vs-dark .sql.codicon.stop,
.hc-black .sql.codicon.stop {
- background-image: url('stop_inverse.svg')
+ background-image: url("stop_inverse.svg");
}
/* Notebook cells */
.codicon.toolbarIconRunInactive {
- background-image: url('execute_cell_grey.svg');
+ background-image: url("execute_cell_grey.svg");
}
.codicon.toolbarIconRun {
- background-image: url('execute_cell.svg');
+ background-image: url("execute_cell.svg");
}
.codicon.toolbarIconRunError {
- background-image: url('execute_cell_error.svg');
+ background-image: url("execute_cell_error.svg");
}
.codicon.toolbarIconStop {
- background-image: url('stop_cell_solidanimation.svg');
+ background-image: url("stop_cell_solidanimation.svg");
}
.vs-dark .codicon.toolbarIconRunInactive {
- background-image: url('execute_cell_dark.svg');
+ background-image: url("execute_cell_dark.svg");
}
.vs-dark .codicon.toolbarIconRun {
- background-image: url('execute_cell_white.svg');
+ background-image: url("execute_cell_white.svg");
}
.hc-black .codicon.toolbarIconRunInactive {
- background-image: url('execute_cell_hc.svg');
+ background-image: url("execute_cell_hc.svg");
}
.hc-black .codicon.toolbarIconRun {
- background-image: url('execute_cell_orange_hc.svg');
+ background-image: url("execute_cell_orange_hc.svg");
}
.vs-dark .codicon.toolbarIconStop,
.hc-black .codicon.toolbarIconStop {
- background-image: url('stop_cell_solidanimation_inverse.svg');
+ background-image: url("stop_cell_solidanimation_inverse.svg");
+}
+
+/* Icons as masked elements for easy theme switching.
+Includes non-masked style declarations. */
+.masked-icon {
+ display: inline-block;
+ height: 20px;
+ width: 20px;
+ -webkit-mask-position: center;
+ -webkit-mask-repeat: no-repeat;
+ mask-position: center;
+ mask-repeat: no-repeat;
+ -webkit-mask-size: 50% 100%;
+ mask-size: 50% 100%;
+}
+
+.codicon.bold {
+ -webkit-mask-image: url("toolbar-bold.svg");
+ mask-image: url("toolbar-bold.svg");
+}
+.codicon.italic {
+ -webkit-mask-image: url("toolbar-italic.svg");
+ mask-image: url("toolbar-italic.svg");
+}
+.codicon.underline {
+ -webkit-mask-image: url("toolbar-underline.svg");
+ mask-image: url("toolbar-underline.svg");
+}
+.codicon.highlight {
+ -webkit-mask-image: url("toolbar-highlight.svg");
+ mask-image: url("toolbar-highlight.svg");
+}
+.codicon.code {
+ -webkit-mask-image: url("toolbar-code.svg");
+ mask-image: url("toolbar-code.svg");
+}
+.codicon.insert-link {
+ -webkit-mask-image: url("toolbar-link.svg");
+ mask-image: url("toolbar-link.svg");
+}
+.codicon.list {
+ -webkit-mask-image: url("toolbar-list.svg");
+ mask-image: url("toolbar-list.svg");
+}
+.codicon.ordered-list {
+ -webkit-mask-image: url("toolbar-ordered-list.svg");
+ mask-image: url("toolbar-ordered-list.svg");
+}
+.codicon.insert-image {
+ -webkit-mask-image: url("toolbar-image.svg");
+ mask-image: url("toolbar-image.svg");
+}
+.codicon.split-toggle-on {
+ -webkit-mask-image: url("toolbar-preview-toggle-on.svg");
+ mask-image: url("toolbar-preview-toggle-on.svg");
+}
+.codicon.split-toggle-off {
+ -webkit-mask-image: url("toolbar-preview-toggle-off.svg");
+ mask-image: url("toolbar-preview-toggle-off.svg");
+}
+.codicon.code {
+ -webkit-mask-image: url("code.svg");
+ mask-image: url("code.svg");
+}
+.codicon.markdown {
+ -webkit-mask-image: url("markdown.svg");
+ mask-image: url("markdown.svg");
+}
+
+.codicon:not(.masked-icon).icon-expand-cells {
+ background-image: url("action-expand.svg");
+}
+.codicon.masked-icon.icon-expand-cells {
+ background-image: none;
+ -webkit-mask-image: url("action-expand.svg");
+ mask-image: url("action-expand.svg");
+}
+
+.codicon:not(.masked-icon).icon-collapse-cells {
+ background-image: url("action-collapse.svg");
+}
+.codicon.masked-icon.icon-collapse-cells {
+ -webkit-mask-image: url("action-collapse.svg");
+ mask-image: url("action-collapse.svg");
+}
+
+.codicon:not(.masked-icon).icon-clear-results {
+ background-image: url("clear.svg");
+}
+.codicon.masked-icon.icon-clear-results {
+ -webkit-mask-image: url("clear.svg");
+ mask-image: url("clear.svg");
+}
+
+.codicon:not(.masked-icon).icon-shield {
+ background-image: url("shield.svg");
+}
+.codicon.masked-icon.icon-shield {
+ -webkit-mask-image: url("shield.svg");
+ mask-image: url("shield.svg");
+}
+
+.codicon:not(.masked-icon).icon-shield-x {
+ background-image: url("shield-x.svg");
+}
+.codicon.masked-icon.icon-shield-x {
+ -webkit-mask-image: url("shield-x.svg");
+ mask-image: url("shield-x.svg");
+}
+
+.codicon:not(.masked-icon).packages {
+ background-image: url("packages.svg");
+}
+.codicon.masked-icon.packages {
+ background-image: none;
+ -webkit-mask-image: url("packages.svg");
+ mask-image: url("packages.svg");
}
.codicon.arrow-up {
@@ -316,78 +433,95 @@
background-image: url("chevron_up_inverse.svg");
}
-.codicon.arrow-down {
+.codicon:not(.masked-icon).arrow-down {
background-image: url("chevron_down.svg");
}
-.vs-dark .codicon.arrow-down,
-.hc-black .codicon.arrow-down {
+.vs-dark .codicon:not(.masked-icon).arrow-down,
+.hc-black .codicon:not(.masked-icon).arrow-down {
background-image: url("chevron_down_inverse.svg");
}
-
-/* Icons as masked elements for easy theme switching */
-.codicon.bold {
- -webkit-mask-image: url('toolbar-bold.svg');
- mask-image: url('toolbar-bold.svg');
-}
-.codicon.italic {
- -webkit-mask-image: url('toolbar-italic.svg');
- mask-image: url('toolbar-italic.svg');
-}
-.codicon.highlight {
- -webkit-mask-image: url('toolbar-highlight.svg');
- mask-image: url('toolbar-highlight.svg');
-}
-.codicon.code {
- -webkit-mask-image: url('toolbar-code.svg');
- mask-image: url('toolbar-code.svg');
-}
-.codicon.insert-link {
- -webkit-mask-image: url('toolbar-link.svg');
- mask-image: url('toolbar-link.svg');
-}
-.codicon.list {
- -webkit-mask-image: url('toolbar-list.svg');
- mask-image: url('toolbar-list.svg');
-}
-.codicon.ordered-list {
- -webkit-mask-image: url('toolbar-ordered-list.svg');
- mask-image: url('toolbar-ordered-list.svg');
-}
-.codicon.insert-image {
- -webkit-mask-image: url('toolbar-image.svg');
- mask-image: url('toolbar-image.svg');
-}
-.codicon.split-toggle-on {
- -webkit-mask-image: url('toolbar-preview-toggle-on.svg');
- mask-image: url('toolbar-preview-toggle-on.svg');
-}
-.codicon.split-toggle-off {
- -webkit-mask-image: url('toolbar-preview-toggle-off.svg');
- mask-image: url('toolbar-preview-toggle-off.svg');
+.codicon.masked-icon.arrow-down {
+ background-image: none;
+ -webkit-mask-image: url("chevron_down.svg");
+ mask-image: url("chevron_down.svg");
+}
+
+.vs .codicon.new-blue {
+ background-image: url("new-blue.svg");
+}
+.vs .codicon.start-outline {
+ background-image: url("start-outline.svg");
+}
+
+/* Masked element inside pseudo element */
+.masked-pseudo {
+ background-image: none !important;
+}
+.masked-pseudo:before,
+.masked-pseudo-after:after {
+ content: "";
+ display: block;
+ position: absolute;
+ -webkit-mask-position: center;
+ -webkit-mask-repeat: no-repeat;
+ mask-position: center;
+ mask-repeat: no-repeat;
+ -webkit-mask-size: 50% 100%;
+ mask-size: 50% 100%;
+}
+.masked-pseudo:before {
+ height: 23px;
+ left: 0;
+ top: 2px;
+ width: 30px;
+}
+.masked-pseudo-after:after {
+ height: 23px;
+ right: 0;
+ top: 2px;
+ width: 30px;
+}
+.masked-pseudo-after.dropdown-arrow:after {
+ background-image: none;
+ -webkit-mask-image: url("chevron_down.svg");
+ mask-image: url("chevron_down.svg");
+}
+.masked-pseudo.add-new:before {
+ -webkit-mask-image: url("new.svg");
+ mask-image: url("new.svg");
+}
+.masked-pseudo.start-outline:before {
+ -webkit-mask-image: url("start-outline.svg");
+ mask-image: url("start-outline.svg");
+}
+
+.masked-pseudo.code:before {
+ -webkit-mask-image: url("code.svg");
+ mask-image: url("code.svg");
+}
+.masked-pseudo.markdown:before {
+ -webkit-mask-image: url("markdown.svg");
+ mask-image: url("markdown.svg");
}
-/* Cell toolbar icons */
.cell-tool-close {
- background-image: url('close-blue.svg');
+ background-image: url("close-blue.svg");
}
.cell-tool-edit {
- background-image: url('edit.svg');
-}
-.cell-tool-add {
- background-image: url('new-blue.svg');
+ background-image: url("edit.svg");
}
.cell-tool-move-up {
- background-image: url('down-arrow-blue.svg');
+ background-image: url("down-arrow-blue.svg");
transform: scale(-1);
}
.cell-tool-move-down {
- background-image: url('down-arrow-blue.svg');
+ background-image: url("down-arrow-blue.svg");
}
.cell-tool-delete {
- background-image: url('garbage-can-blue.svg');
+ background-image: url("garbage-can-blue.svg");
}
.cell-tool-more {
- background-image: url('ellipsis-blue.svg');
+ background-image: url("ellipsis-blue.svg");
}
.database-colored.codicon {
diff --git a/src/sql/media/icons/markdown.svg b/src/sql/media/icons/markdown.svg
new file mode 100644
index 0000000000..ce246b60cb
--- /dev/null
+++ b/src/sql/media/icons/markdown.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/sql/media/icons/packages.svg b/src/sql/media/icons/packages.svg
new file mode 100644
index 0000000000..5b75cda4c0
--- /dev/null
+++ b/src/sql/media/icons/packages.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/sql/media/icons/shield-x.svg b/src/sql/media/icons/shield-x.svg
new file mode 100644
index 0000000000..9ae38feedf
--- /dev/null
+++ b/src/sql/media/icons/shield-x.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/sql/media/icons/shield.svg b/src/sql/media/icons/shield.svg
new file mode 100644
index 0000000000..a458fa9c64
--- /dev/null
+++ b/src/sql/media/icons/shield.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/sql/media/icons/start-outline.svg b/src/sql/media/icons/start-outline.svg
new file mode 100644
index 0000000000..3464243804
--- /dev/null
+++ b/src/sql/media/icons/start-outline.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/sql/media/icons/toolbar-underline.svg b/src/sql/media/icons/toolbar-underline.svg
new file mode 100644
index 0000000000..0b3dc338a7
--- /dev/null
+++ b/src/sql/media/icons/toolbar-underline.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/sql/platform/theme/common/colorRegistry.ts b/src/sql/platform/theme/common/colorRegistry.ts
index 296055663c..15ea876d9e 100644
--- a/src/sql/platform/theme/common/colorRegistry.ts
+++ b/src/sql/platform/theme/common/colorRegistry.ts
@@ -42,19 +42,26 @@ export const gradientTwo = registerColor('gradientTwo', { light: gradientTwoColo
export const gradientBackground = registerColor('gradientBackground', { light: '#fff', dark: 'transparent', hc: 'transparent' }, nls.localize('gradientBackground', "The background color for the banner image gradient"));
// --- Notebook Colors
+export const notebookToolbarIcon = registerColor('notebook.notebookToolbarIcon', { light: '#0078D4', dark: '#3AA0F3', hc: '#FFFFFF' }, nls.localize('notebook.notebookToolbarIcon', "Notebook: Main toolbar icons"));
+export const notebookToolbarSelectBorder = registerColor('notebook.notebookToolbarSelectBorder', { light: '#A5A5A5', dark: '#8A8886', hc: '#2B56F2' }, nls.localize('notebook.notebookToolbarSelectBorder', "Notebook: Main toolbar select box border"));
+export const notebookToolbarSelectBackground = registerColor('notebook.notebookToolbarSelectBackground', { light: '#FFFFFF', dark: '#1B1A19', hc: '#000000' }, nls.localize('notebook.notebookToolbarSelectBackground', "Notebook: Main toolbar select box background"));
+export const notebookToolbarLines = registerColor('notebook.notebookToolbarLines', { light: '#D6D6D6', dark: '#323130', hc: '#2B56F2' }, nls.localize('notebook.notebookToolbarLines', "Notebook: Main toolbar bottom border and separator"));
+export const dropdownArrow = registerColor('notebook.dropdownArrow', { light: '#A5A5A5', dark: '#FFFFFF', hc: '#FFFFFF' }, nls.localize('notebook.dropdownArrow', "Notebook: Main toolbar dropdown arrow"));
+export const buttonMenuArrow = registerColor('notebook.buttonMenuArrow', { light: '#000000', dark: '#FFFFFF', hc: '#FFFFFF' }, nls.localize('notebook.buttonMenuArrow', "Notebook: Main toolbar custom buttonMenu dropdown arrow"));
+
export const toolbarBackground = registerColor('notebook.toolbarBackground', { light: '#F5F5F5', dark: '#252423', hc: '#000000' }, nls.localize('notebook.toolbarBackground', "Notebook: Markdown toolbar background"));
-export const toolbarIcon = registerColor('notebook.toolbarIcon', { light: '#323130', dark: '#FFFFFe', hc: '#FFFFFe' }, nls.localize('notebook.toolbarIcon', "Notebook: Markdown toolbar icons"));
+export const toolbarIcon = registerColor('notebook.toolbarIcon', { light: '#323130', dark: '#FFFFFF', hc: '#FFFFFF' }, nls.localize('notebook.toolbarIcon', "Notebook: Markdown toolbar icons"));
export const toolbarBottomBorder = registerColor('notebook.toolbarBottomBorder', { light: '#D4D4D4', dark: '#323130', hc: '#E86E58' }, nls.localize('notebook.toolbarBottomBorder', "Notebook: Markdown toolbar bottom border"));
// Notebook: All cells
-export const cellBorder = registerColor('notebook.cellBorder', { light: '#0078D4', dark: '#0078D4', hc: '#E86E58' }, nls.localize('notebook.cellBorder', "Notebook: Active cell border"));
+export const cellBorder = registerColor('notebook.cellBorder', { light: '#0078D4', dark: '#3AA0F3', hc: '#E86E58' }, nls.localize('notebook.cellBorder', "Notebook: Active cell border"));
// Notebook: Markdown cell
-export const markdownEditorBackground = registerColor('notebook.markdownEditorBackground', { light: '#FFFFFe', dark: '#1B1A19', hc: '#000000' }, nls.localize('notebook.markdownEditorBackground', "Notebook: Markdown editor background"));
+export const markdownEditorBackground = registerColor('notebook.markdownEditorBackground', { light: '#FFFFFF', dark: '#1B1A19', hc: '#000000' }, nls.localize('notebook.markdownEditorBackground', "Notebook: Markdown editor background"));
export const splitBorder = registerColor('notebook.splitBorder', { light: '#E6E6E6', dark: '#323130', hc: '#872412' }, nls.localize('notebook.splitBorder', "Notebook: Border between Markdown editor and preview"));
// Notebook: Code cell
export const codeEditorBackground = registerColor('notebook.codeEditorBackground', { light: '#F5F5F5', dark: '#333333', hc: '#000000' }, nls.localize('notebook.codeEditorBackground', "Notebook: Code editor background"));
-export const codeEditorBackgroundActive = registerColor('notebook.codeEditorBackgroundActive', { light: '#FFFFFe', dark: null, hc: null }, nls.localize('notebook.codeEditorBackgroundActive', "Notebook: Code editor background of active cell"));
-export const codeEditorLineNumber = registerColor('notebook.codeEditorLineNumber', { light: '#A19F9D', dark: '#A19F9D', hc: '#FFFFFe' }, nls.localize('notebook.codeEditorLineNumber', "Notebook: Code editor line numbers"));
-export const codeEditorToolbarIcon = registerColor('notebook.codeEditorToolbarIcon', { light: '#999999', dark: '#A19F9D', hc: '#FFFFFe' }, nls.localize('notebook.codeEditorToolbarIcon', "Notebook: Code editor toolbar icons"));
+export const codeEditorBackgroundActive = registerColor('notebook.codeEditorBackgroundActive', { light: '#FFFFFF', dark: null, hc: null }, nls.localize('notebook.codeEditorBackgroundActive', "Notebook: Code editor background of active cell"));
+export const codeEditorLineNumber = registerColor('notebook.codeEditorLineNumber', { light: '#A19F9D', dark: '#A19F9D', hc: '#FFFFFF' }, nls.localize('notebook.codeEditorLineNumber', "Notebook: Code editor line numbers"));
+export const codeEditorToolbarIcon = registerColor('notebook.codeEditorToolbarIcon', { light: '#999999', dark: '#A19F9D', hc: '#FFFFFF' }, nls.localize('notebook.codeEditorToolbarIcon', "Notebook: Code editor toolbar icons"));
export const codeEditorToolbarBackground = registerColor('notebook.codeEditorToolbarBackground', { light: '#EEEEEE', dark: '#333333', hc: '#000000' }, nls.localize('notebook.codeEditorToolbarBackground', "Notebook: Code editor toolbar background"));
export const codeEditorToolbarBorder = registerColor('notebook.codeEditorToolbarBorder', { light: '#C8C6C4', dark: '#333333', hc: '#000000' }, nls.localize('notebook.codeEditorToolbarBorder', "Notebook: Code editor toolbar right border"));
diff --git a/src/sql/workbench/contrib/notebook/browser/cellViews/markdownToolbar.component.ts b/src/sql/workbench/contrib/notebook/browser/cellViews/markdownToolbar.component.ts
index ed9cf102ab..52e8c2633a 100644
--- a/src/sql/workbench/contrib/notebook/browser/cellViews/markdownToolbar.component.ts
+++ b/src/sql/workbench/contrib/notebook/browser/cellViews/markdownToolbar.component.ts
@@ -21,6 +21,7 @@ export class MarkdownToolbarComponent {
public buttonBold = localize('buttonBold', "Bold");
public buttonItalic = localize('buttonItalic', "Italic");
+ public buttonUnderline = localize('buttonUnderline', "Underline");
public buttonHighlight = localize('buttonHighlight', "Highlight");
public buttonCode = localize('buttonCode', "Code");
public buttonLink = localize('buttonLink', "Link");
@@ -43,6 +44,7 @@ export class MarkdownToolbarComponent {
private initActionBar() {
let boldButton = this._instantiationService.createInstance(TransformMarkdownAction, 'notebook.boldText', '', 'bold', this.buttonBold, this.cellModel, MarkdownButtonType.BOLD);
let italicButton = this._instantiationService.createInstance(TransformMarkdownAction, 'notebook.italicText', '', 'italic', this.buttonItalic, this.cellModel, MarkdownButtonType.ITALIC);
+ let underlineButton = this._instantiationService.createInstance(TransformMarkdownAction, 'notebook.underlineText', '', 'underline', this.buttonUnderline, this.cellModel, MarkdownButtonType.UNDERLINE);
let highlightButton = this._instantiationService.createInstance(TransformMarkdownAction, 'notebook.highlightText', '', 'highlight', this.buttonHighlight, this.cellModel, MarkdownButtonType.HIGHLIGHT);
let codeButton = this._instantiationService.createInstance(TransformMarkdownAction, 'notebook.codeText', '', 'code', this.buttonCode, this.cellModel, MarkdownButtonType.CODE);
let linkButton = this._instantiationService.createInstance(TransformMarkdownAction, 'notebook.linkText', '', 'insert-link', this.buttonLink, this.cellModel, MarkdownButtonType.LINK);
@@ -56,6 +58,7 @@ export class MarkdownToolbarComponent {
this._actionBar.setContent([
{ action: boldButton },
{ action: italicButton },
+ { action: underlineButton },
{ action: highlightButton },
{ action: codeButton },
{ action: linkButton },
diff --git a/src/sql/workbench/contrib/notebook/browser/markdownToolbarActions.ts b/src/sql/workbench/contrib/notebook/browser/markdownToolbarActions.ts
index ba371a20ae..c6b5998fca 100644
--- a/src/sql/workbench/contrib/notebook/browser/markdownToolbarActions.ts
+++ b/src/sql/workbench/contrib/notebook/browser/markdownToolbarActions.ts
@@ -119,6 +119,8 @@ export class MarkdownTextTransformer {
return '**';
case MarkdownButtonType.ITALIC:
return '_';
+ case MarkdownButtonType.UNDERLINE:
+ return '';
case MarkdownButtonType.CODE:
return '```\n';
case MarkdownButtonType.LINK:
@@ -142,6 +144,8 @@ export class MarkdownTextTransformer {
return '**';
case MarkdownButtonType.ITALIC:
return '_';
+ case MarkdownButtonType.UNDERLINE:
+ return '';
case MarkdownButtonType.CODE:
return '\n```';
case MarkdownButtonType.LINK:
@@ -370,6 +374,7 @@ export class MarkdownTextTransformer {
export enum MarkdownButtonType {
BOLD,
ITALIC,
+ UNDERLINE,
CODE,
HIGHLIGHT,
LINK,
diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts
index 59b3090076..7997546a05 100644
--- a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts
+++ b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts
@@ -31,7 +31,8 @@ import * as notebookUtils from 'sql/workbench/services/notebook/browser/models/n
import { Deferred } from 'sql/base/common/promise';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
-import { KernelsDropdown, AttachToDropdown, AddCellAction, TrustedAction, RunAllCellsAction, ClearAllOutputsAction, CollapseCellsAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
+import { AddCellAction, KernelsDropdown, AttachToDropdown, TrustedAction, RunAllCellsAction, ClearAllOutputsAction, CollapseCellsAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
+import { DropdownMenuActionViewItem } from 'sql/base/browser/ui/buttonMenu/buttonMenu';
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
@@ -56,6 +57,7 @@ import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/not
import { IColorTheme } from 'vs/platform/theme/common/themeService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
+import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export const NOTEBOOK_SELECTOR: string = 'notebook-component';
@@ -83,6 +85,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
private _scrollTop: number;
private _navProvider: INavigationProvider;
private navigationResult: nb.NavigationResult;
+ public previewFeaturesEnabled: boolean = false;
constructor(
@Inject(forwardRef(() => ChangeDetectorRef)) private _changeRef: ChangeDetectorRef,
@@ -103,11 +106,15 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
@Inject(ITextFileService) private textFileService: ITextFileService,
@Inject(ILogService) private readonly logService: ILogService,
@Inject(ICommandService) private commandService: ICommandService,
- @Inject(IAdsTelemetryService) private adstelemetryService: IAdsTelemetryService
+ @Inject(IAdsTelemetryService) private adstelemetryService: IAdsTelemetryService,
+ @Inject(IConfigurationService) private _configurationService: IConfigurationService
) {
super();
this.updateProfile();
this.isLoading = true;
+ this._register(this._configurationService.onDidChangeConfiguration(e => {
+ this.previewFeaturesEnabled = this._configurationService.getValue('workbench.enablePreviewFeatures');
+ }));
}
private updateProfile(): void {
@@ -395,44 +402,114 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
}
protected initActionBar(): void {
- let kernelContainer = document.createElement('div');
- let kernelDropdown = this.instantiationService.createInstance(KernelsDropdown, kernelContainer, this.contextViewService, this.modelReady);
- kernelDropdown.render(kernelContainer);
- attachSelectBoxStyler(kernelDropdown, this.themeService);
+ this.previewFeaturesEnabled = this._configurationService.getValue('workbench.enablePreviewFeatures');
- let attachToContainer = document.createElement('div');
- let attachToDropdown = new AttachToDropdown(attachToContainer, this.contextViewService, this.modelReady,
- this.connectionManagementService, this.connectionDialogService, this.notificationService, this.capabilitiesService);
- attachToDropdown.render(attachToContainer);
- attachSelectBoxStyler(attachToDropdown, this.themeService);
+ if (this.previewFeaturesEnabled) {
+ let kernelContainer = document.createElement('li');
+ let kernelDropdown = this.instantiationService.createInstance(KernelsDropdown, kernelContainer, this.contextViewService, this.modelReady);
+ kernelDropdown.render(kernelContainer);
+ attachSelectBoxStyler(kernelDropdown, this.themeService);
- let addCodeCellButton = new AddCellAction('notebook.AddCodeCell', localize('code', "Code"), 'notebook-button icon-add');
- addCodeCellButton.cellType = CellTypes.Code;
+ let attachToContainer = document.createElement('li');
+ let attachToDropdown = new AttachToDropdown(attachToContainer, this.contextViewService, this.modelReady,
+ this.connectionManagementService, this.connectionDialogService, this.notificationService, this.capabilitiesService);
+ attachToDropdown.render(attachToContainer);
+ attachSelectBoxStyler(attachToDropdown, this.themeService);
- let addTextCellButton = new AddCellAction('notebook.AddTextCell', localize('text', "Text"), 'notebook-button icon-add');
- addTextCellButton.cellType = CellTypes.Markdown;
+ let spacerElement = document.createElement('li');
+ spacerElement.style.marginLeft = 'auto';
- this._runAllCellsAction = this.instantiationService.createInstance(RunAllCellsAction, 'notebook.runAllCells', localize('runAll', "Run Cells"), 'notebook-button icon-run-cells');
- let clearResultsButton = new ClearAllOutputsAction('notebook.ClearAllOutputs', localize('clearResults', "Clear Results"), 'notebook-button icon-clear-results');
+ let addCodeCellButton = new AddCellAction('notebook.AddCodeCell', localize('codePreview', "Code cell"), 'notebook-button masked-pseudo code');
+ addCodeCellButton.cellType = CellTypes.Code;
- this._trustedAction = this.instantiationService.createInstance(TrustedAction, 'notebook.Trusted');
- this._trustedAction.enabled = false;
+ let addTextCellButton = new AddCellAction('notebook.AddTextCell', localize('textPreview', "Markdown cell"), 'notebook-button masked-pseudo markdown');
+ addTextCellButton.cellType = CellTypes.Markdown;
- let collapseCellsAction = this.instantiationService.createInstance(CollapseCellsAction, 'notebook.collapseCells');
- let taskbar = this.toolbar.nativeElement;
- this._actionBar = new Taskbar(taskbar, { actionViewItemProvider: action => this.actionItemProvider(action as Action) });
- this._actionBar.context = this;
- this._actionBar.setContent([
- { action: addCodeCellButton },
- { action: addTextCellButton },
- { element: kernelContainer },
- { element: attachToContainer },
- { action: this._trustedAction },
- { action: this._runAllCellsAction },
- { action: clearResultsButton },
- { action: collapseCellsAction }
- ]);
+ this._runAllCellsAction = this.instantiationService.createInstance(RunAllCellsAction, 'notebook.runAllCells', localize('runAllPreview', "Run all"), 'notebook-button masked-pseudo start-outline');
+
+ let collapseCellsAction = this.instantiationService.createInstance(CollapseCellsAction, 'notebook.collapseCells', true);
+
+ let clearResultsButton = new ClearAllOutputsAction('notebook.ClearAllOutputs', true);
+
+ this._trustedAction = this.instantiationService.createInstance(TrustedAction, 'notebook.Trusted', true);
+ this._trustedAction.enabled = false;
+
+ let taskbar = this.toolbar.nativeElement;
+ this._actionBar = new Taskbar(taskbar, { actionViewItemProvider: action => this.actionItemProvider(action as Action) });
+ this._actionBar.context = this;
+ taskbar.classList.add('in-preview');
+
+ let buttonDropdownContainer = DOM.$('li.action-item');
+ buttonDropdownContainer.setAttribute('role', 'presentation');
+ let dropdownMenuActionViewItem = new DropdownMenuActionViewItem(
+ addCodeCellButton,
+ [addCodeCellButton, addTextCellButton],
+ this.contextMenuService,
+ undefined,
+ this._actionBar.actionRunner,
+ undefined,
+ 'codicon notebook-button masked-pseudo masked-pseudo-after add-new dropdown-arrow',
+ localize('addCell', "Cell"),
+ undefined
+ );
+ dropdownMenuActionViewItem.render(buttonDropdownContainer);
+ dropdownMenuActionViewItem.setActionContext(this);
+
+ this._actionBar.setContent([
+ { element: buttonDropdownContainer },
+ { action: this._runAllCellsAction },
+ { element: Taskbar.createTaskbarSeparator() },
+ { element: attachToContainer },
+ { element: kernelContainer },
+ { element: spacerElement },
+ { action: collapseCellsAction },
+ { action: clearResultsButton },
+ { action: this._trustedAction },
+ ]);
+ } else {
+ let kernelContainer = document.createElement('div');
+ let kernelDropdown = this.instantiationService.createInstance(KernelsDropdown, kernelContainer, this.contextViewService, this.modelReady);
+ kernelDropdown.render(kernelContainer);
+ attachSelectBoxStyler(kernelDropdown, this.themeService);
+
+ let attachToContainer = document.createElement('div');
+ let attachToDropdown = new AttachToDropdown(attachToContainer, this.contextViewService, this.modelReady,
+ this.connectionManagementService, this.connectionDialogService, this.notificationService, this.capabilitiesService);
+ attachToDropdown.render(attachToContainer);
+ attachSelectBoxStyler(attachToDropdown, this.themeService);
+
+ let addCodeCellButton = new AddCellAction('notebook.AddCodeCell', localize('code', "Code"), 'notebook-button icon-add');
+ addCodeCellButton.cellType = CellTypes.Code;
+
+ let addTextCellButton = new AddCellAction('notebook.AddTextCell', localize('text', "Text"), 'notebook-button icon-add');
+ addTextCellButton.cellType = CellTypes.Markdown;
+
+ this._runAllCellsAction = this.instantiationService.createInstance(RunAllCellsAction, 'notebook.runAllCells', localize('runAll', "Run Cells"), 'notebook-button icon-run-cells');
+
+ let clearResultsButton = new ClearAllOutputsAction('notebook.ClearAllOutputs', false);
+
+ this._trustedAction = this.instantiationService.createInstance(TrustedAction, 'notebook.Trusted', false);
+ this._trustedAction.enabled = false;
+
+ let collapseCellsAction = this.instantiationService.createInstance(CollapseCellsAction, 'notebook.collapseCells', false);
+
+ let taskbar = this.toolbar.nativeElement;
+ this._actionBar = new Taskbar(taskbar, { actionViewItemProvider: action => this.actionItemProvider(action as Action) });
+ this._actionBar.context = this;
+
+ this._actionBar.setContent([
+ { action: addCodeCellButton },
+ { action: addTextCellButton },
+ { element: kernelContainer },
+ { element: attachToContainer },
+ { action: this._trustedAction },
+ { action: this._runAllCellsAction },
+ { action: clearResultsButton },
+ { action: collapseCellsAction }
+ ]);
+ }
+
}
protected initNavSection(): void {
@@ -478,7 +555,12 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
// Check extensions to create ActionItem; otherwise, return undefined
// This is similar behavior that exists in MenuItemActionItem
if (action instanceof MenuItemAction) {
- return new LabeledMenuItemActionItem(action, this.keybindingService, this.contextMenuService, this.notificationService, 'notebook-button');
+
+ if (action.item.id.includes('jupyter.cmd') && this.previewFeaturesEnabled) {
+ action.tooltip = action.label;
+ action.label = '';
+ }
+ return new LabeledMenuItemActionItem(action, this.keybindingService, this.contextMenuService, this.notificationService, 'notebook-button fixed-width');
}
return undefined;
}
diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.css b/src/sql/workbench/contrib/notebook/browser/notebook.css
index f5caf031b3..e55d22747d 100644
--- a/src/sql/workbench/contrib/notebook/browser/notebook.css
+++ b/src/sql/workbench/contrib/notebook/browser/notebook.css
@@ -6,6 +6,10 @@
margin-top: 5px;
}
+.notebookEditor .taskbarSeparator {
+ margin: 0 16px 0 -8px;
+}
+
.notebookEditor .editor-toolbar {
border-bottom-style: solid;
border-width: 0px 0px 1px 0px;
@@ -44,6 +48,52 @@
font-size: 13px;
height: 21px;
}
+.notebookEditor .in-preview .actions-container .action-item .notebook-button {
+ display: flex;
+ background-size: 16px;
+}
+
+.notebookEditor
+ .in-preview
+ .actions-container
+ .action-item
+ .notebook-button.masked-pseudo {
+ padding-left: 30px;
+}
+.notebookEditor
+ .in-preview
+ .actions-container
+ .action-item
+ .notebook-button.masked-icon {
+ margin-right: 0;
+ padding-left: 18px;
+ width: 16px;
+}
+.notebookEditor .in-preview .actions-container .action-item:last-child {
+ margin-right: 8px;
+}
+.notebookEditor
+ .in-preview
+ .actions-container
+ .action-item:last-child
+ .notebook-button {
+ margin-right: 0;
+}
+.notebookEditor
+ .in-preview
+ .actions-container
+ .action-item:last-child
+ .notebook-button.fixed-width {
+ margin-left: 8px;
+ margin-right: -28px;
+}
+.notebookEditor
+ .in-preview
+ .actions-container
+ .action-item
+ .notebook-button.fixed-width {
+ width: 34px;
+}
.notebookEditor .labelOnLeftContainer {
min-width: 100px;
@@ -54,68 +104,89 @@
vertical-align: bottom;
}
-.notebookEditor .notebook-button.icon-add {
+.notebookEditor .in-preview .labelOnLeftContainer {
+ margin-right: 14px;
+}
+
+/* non-preview */
+.notebookEditor :not(.in-preview) .notebook-button.icon-add {
background-image: url("./media/light/add.svg");
}
-.vs-dark .notebookEditor .notebook-button.icon-add,
-.hc-black .notebookEditor .notebook-button.icon-add {
+.vs-dark .notebookEditor :not(.in-preview) .notebook-button.icon-add,
+.hc-black .notebookEditor :not(.in-preview) .notebook-button.icon-add {
background-image: url("./media/dark/add_inverse.svg");
}
-.notebookEditor .notebook-button.icon-run-cells {
+.notebookEditor :not(.in-preview) .notebook-button.icon-run-cells {
background-image: url("./media/light/run_cells.svg");
}
-.vs-dark .notebookEditor .notebook-button.icon-run-cells,
-.hc-black .notebookEditor .notebook-button.icon-run-cells {
+.vs-dark .notebookEditor :not(.in-preview) .notebook-button.icon-run-cells,
+.hc-black .notebookEditor :not(.in-preview) .notebook-button.icon-run-cells {
background-image: url("./media/dark/run_cells_inverse.svg");
}
-.notebookEditor .notebook-button.icon-trusted {
+.notebookEditor :not(.in-preview) .notebook-button.icon-trusted {
background-image: url("./media/light/trusted.svg");
}
-.vs-dark .notebookEditor .notebook-button.icon-trusted,
-.hc-black .notebookEditor .notebook-button.icon-trusted {
+.vs-dark .notebookEditor :not(.in-preview) .notebook-button.icon-trusted,
+.hc-black .notebookEditor :not(.in-preview) .notebook-button.icon-trusted {
background-image: url("./media/dark/trusted_inverse.svg");
}
-
-.notebookEditor .notebook-button.icon-notTrusted {
+.notebookEditor :not(.in-preview) .notebook-button.icon-notTrusted {
background-image: url("./media/light/nottrusted.svg");
}
-.vs-dark .notebookEditor .notebook-button.icon-notTrusted,
-.hc-black .notebookEditor .notebook-button.icon-notTrusted {
+.vs-dark .notebookEditor :not(.in-preview) .notebook-button.icon-notTrusted,
+.hc-black .notebookEditor :not(.in-preview) .notebook-button.icon-notTrusted {
background-image: url("./media/dark/nottrusted_inverse.svg");
}
-.notebookEditor .notebook-button.icon-show-cells {
+.notebookEditor :not(.in-preview) .notebook-button.icon-show-cells {
background-image: url("./media/light/show_code.svg");
}
-.vs-dark .notebookEditor .notebook-button.icon-show-cells,
-.hc-black .notebookEditor .notebook-button.icon-show-cells {
+.vs-dark .notebookEditor :not(.in-preview) .notebook-button.icon-show-cells,
+.hc-black .notebookEditor :not(.in-preview) .notebook-button.icon-show-cells {
background-image: url("./media/dark/show_code_inverse.svg");
}
-.notebookEditor .notebook-button.icon-hide-cells {
+.notebookEditor :not(.in-preview) .notebook-button.icon-hide-cells {
background-image: url("./media/light/hide_code.svg");
}
-.vs-dark .notebookEditor .notebook-button.icon-hide-cells,
-.hc-black .notebookEditor .notebook-button.icon-hide-cells {
+.vs-dark .notebookEditor :not(.in-preview) .notebook-button.icon-hide-cells,
+.hc-black .notebookEditor :not(.in-preview) .notebook-button.icon-hide-cells {
background-image: url("./media/dark/hide_code_inverse.svg");
}
-.notebookEditor .notebook-button.icon-clear-results {
+.notebookEditor :not(.in-preview) .notebook-button.icon-clear-results {
background-image: url("./media/light/clear_results.svg");
}
-.vs-dark .notebookEditor .notebook-button.icon-clear-results,
-.hc-black .notebookEditor .notebook-button.icon-clear-results {
+.vs-dark .notebookEditor :not(.in-preview) .notebook-button.icon-clear-results,
+.hc-black
+ .notebookEditor
+ :not(.in-preview)
+ .notebook-button.icon-clear-results {
background-image: url("./media/dark/clear_results_inverse.svg");
}
+/* non-preview */
+
+.notebookEditor .in-preview .carbon-taskbar.monaco-toolbar .monaco-select-box {
+ font-size: inherit;
+ border-radius: 0;
+ padding: 3px 22px 3px 6px;
+}
+.notebookEditor .in-preview .carbon-taskbar .action-item {
+ margin-right: 0;
+}
+.notebookEditor .in-preview .labelOnLeftContainer {
+ display: flex;
+ align-items: center;
+}
.moreActions .action-label.codicon.toggle-more {
height: 20px;
@@ -123,7 +194,7 @@
}
.moreActions.actionhidden {
- visibility: hidden
+ visibility: hidden;
}
.moreActions .monaco-action-bar {
margin-left: -12px;
@@ -144,12 +215,13 @@
}
.monaco-workbench .notebook-action.new-notebook {
- background: url('./media/light/new_notebook.svg') center center no-repeat;
+ background: url("./media/light/new_notebook.svg") center center no-repeat;
}
.vs-dark .monaco-workbench .notebook-action.new-notebook,
.hc-black .monaco-workbench .notebook-action.new-notebook {
- background: url('./media/dark/new_notebook_inverse.svg') center center no-repeat;
+ background: url("./media/dark/new_notebook_inverse.svg") center center
+ no-repeat;
}
.notebookEditor .book-nav {
@@ -209,7 +281,7 @@
}
.notebookEditor .hoverButton:active {
- transform:scale(1.05);
+ transform: scale(1.05);
}
.notebookEditor .hoverButton .addCodeIcon,
diff --git a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts
index 4777b31af9..6c2e12fa6a 100644
--- a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts
+++ b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts
@@ -31,8 +31,8 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
const msgLoading = localize('loading', "Loading kernels...");
const msgChanging = localize('changing', "Changing kernel...");
-const kernelLabel: string = localize('Kernel', "Kernel: ");
-const attachToLabel: string = localize('AttachTo', "Attach To: ");
+const attachToLabel: string = localize('AttachTo', "Attach to ");
+const kernelLabel: string = localize('Kernel', "Kernel ");
const msgLoadingContexts = localize('loadingContexts', "Loading contexts...");
const msgChangeConnection = localize('changeConnection', "Change Connection");
const msgSelectConnection = localize('selectConnection', "Select Connection");
@@ -64,13 +64,50 @@ export class AddCellAction extends Action {
}
}
-// Action to clear outputs of all code cells.
-export class ClearAllOutputsAction extends Action {
- constructor(
- id: string, label: string, cssClass: string
- ) {
- super(id, label, cssClass);
+export interface ITooltipState {
+ label: string;
+ baseClass: string;
+ iconClass: string;
+ maskedIconClass: string;
+ shouldToggleTooltip?: boolean;
+}
+export abstract class TooltipFromLabelAction extends Action {
+
+ constructor(id: string, protected state: ITooltipState) {
+ super(id, '');
+ this.updateLabelAndIcon();
}
+
+ private updateLabelAndIcon() {
+ if (this.state.shouldToggleTooltip) {
+ this.tooltip = this.state.label;
+ } else {
+ this.label = this.state.label;
+ }
+ let classes = this.state.baseClass ? `${this.state.baseClass} ${this.state.iconClass} ` : '';
+ if (this.state.shouldToggleTooltip) {
+ classes += this.state.maskedIconClass;
+ }
+ this.class = classes;
+ }
+}
+// Action to clear outputs of all code cells.
+export class ClearAllOutputsAction extends TooltipFromLabelAction {
+ private static readonly label = localize('clearResults', "Clear Results");
+ private static readonly baseClass = 'notebook-button';
+ private static readonly iconClass = 'icon-clear-results';
+ private static readonly maskedIconClass = 'masked-icon';
+
+ constructor(id: string, toggleTooltip: boolean) {
+ super(id, {
+ label: ClearAllOutputsAction.label,
+ baseClass: ClearAllOutputsAction.baseClass,
+ iconClass: ClearAllOutputsAction.iconClass,
+ maskedIconClass: ClearAllOutputsAction.maskedIconClass,
+ shouldToggleTooltip: toggleTooltip
+ });
+ }
+
public run(context: INotebookEditor): Promise {
return context.clearAllOutputs();
}
@@ -83,6 +120,7 @@ export interface IToggleableState {
toggleOnLabel: string;
toggleOffLabel: string;
toggleOffClass: string;
+ maskedIconClass?: string;
isOn: boolean;
}
@@ -99,7 +137,16 @@ export abstract class ToggleableAction extends Action {
} else {
this.label = this.state.isOn ? this.state.toggleOnLabel : this.state.toggleOffLabel;
}
- let classes = this.state.baseClass ? `${this.state.baseClass} ` : '';
+
+ let classes: string = '';
+
+ if (this.state.shouldToggleTooltip && this.state.maskedIconClass) {
+ //mask
+ classes = this.state.baseClass ? `${this.state.baseClass} ${this.state.maskedIconClass} ` : '';
+ } else {
+ //no mask
+ classes = this.state.baseClass ? `${this.state.baseClass} ` : '';
+ }
classes += this.state.isOn ? this.state.toggleOnClass : this.state.toggleOffClass;
this.class = classes;
}
@@ -115,20 +162,23 @@ export class TrustedAction extends ToggleableAction {
private static readonly trustedLabel = localize('trustLabel', "Trusted");
private static readonly notTrustedLabel = localize('untrustLabel', "Not Trusted");
private static readonly baseClass = 'notebook-button';
+ private static readonly previewTrustedCssClass = 'icon-shield';
private static readonly trustedCssClass = 'icon-trusted';
+ private static readonly previewNotTrustedCssClass = 'icon-shield-x';
private static readonly notTrustedCssClass = 'icon-notTrusted';
-
- // Properties
+ private static readonly maskedIconClass = 'masked-icon';
constructor(
- id: string
+ id: string, toggleTooltip: boolean
) {
super(id, {
baseClass: TrustedAction.baseClass,
toggleOnLabel: TrustedAction.trustedLabel,
- toggleOnClass: TrustedAction.trustedCssClass,
+ toggleOnClass: toggleTooltip === true ? TrustedAction.previewTrustedCssClass : TrustedAction.trustedCssClass,
toggleOffLabel: TrustedAction.notTrustedLabel,
- toggleOffClass: TrustedAction.notTrustedCssClass,
+ toggleOffClass: toggleTooltip === true ? TrustedAction.previewNotTrustedCssClass : TrustedAction.notTrustedCssClass,
+ maskedIconClass: TrustedAction.maskedIconClass,
+ shouldToggleTooltip: toggleTooltip,
isOn: false
});
}
@@ -177,16 +227,21 @@ export class CollapseCellsAction extends ToggleableAction {
private static readonly collapseCells = localize('collapseAllCells', "Collapse Cells");
private static readonly expandCells = localize('expandAllCells', "Expand Cells");
private static readonly baseClass = 'notebook-button';
+ private static readonly previewCollapseCssClass = 'icon-collapse-cells';
private static readonly collapseCssClass = 'icon-hide-cells';
+ private static readonly previewExpandCssClass = 'icon-expand-cells';
private static readonly expandCssClass = 'icon-show-cells';
+ private static readonly maskedIconClass = 'masked-icon';
- constructor(id: string) {
+ constructor(id: string, toggleTooltip: boolean) {
super(id, {
baseClass: CollapseCellsAction.baseClass,
toggleOnLabel: CollapseCellsAction.expandCells,
- toggleOnClass: CollapseCellsAction.expandCssClass,
+ toggleOnClass: toggleTooltip === true ? CollapseCellsAction.previewExpandCssClass : CollapseCellsAction.expandCssClass,
toggleOffLabel: CollapseCellsAction.collapseCells,
- toggleOffClass: CollapseCellsAction.collapseCssClass,
+ toggleOffClass: toggleTooltip === true ? CollapseCellsAction.previewCollapseCssClass : CollapseCellsAction.collapseCssClass,
+ maskedIconClass: CollapseCellsAction.maskedIconClass,
+ shouldToggleTooltip: toggleTooltip,
isOn: false
});
}
diff --git a/src/sql/workbench/contrib/notebook/browser/notebookStyles.ts b/src/sql/workbench/contrib/notebook/browser/notebookStyles.ts
index 347f613008..38f32f6bf9 100644
--- a/src/sql/workbench/contrib/notebook/browser/notebookStyles.ts
+++ b/src/sql/workbench/contrib/notebook/browser/notebookStyles.ts
@@ -8,7 +8,7 @@ import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/
import { SIDE_BAR_BACKGROUND, EDITOR_GROUP_HEADER_TABS_BACKGROUND } from 'vs/workbench/common/theme';
import { activeContrastBorder, contrastBorder, buttonBackground, textLinkForeground, textLinkActiveForeground, textPreformatForeground, textBlockQuoteBackground, textBlockQuoteBorder, buttonForeground, editorBackground, lighten } from 'vs/platform/theme/common/colorRegistry';
import { editorLineHighlight, editorLineHighlightBorder } from 'vs/editor/common/view/editorColorRegistry';
-import { cellBorder, markdownEditorBackground, splitBorder, codeEditorBackground, codeEditorBackgroundActive, codeEditorLineNumber, codeEditorToolbarIcon, codeEditorToolbarBackground, codeEditorToolbarBorder, toolbarBackground, toolbarIcon, toolbarBottomBorder } from 'sql/platform/theme/common/colorRegistry';
+import { cellBorder, notebookToolbarIcon, notebookToolbarLines, buttonMenuArrow, dropdownArrow, markdownEditorBackground, splitBorder, codeEditorBackground, codeEditorBackgroundActive, codeEditorLineNumber, codeEditorToolbarIcon, codeEditorToolbarBackground, codeEditorToolbarBorder, toolbarBackground, toolbarIcon, toolbarBottomBorder } from 'sql/platform/theme/common/colorRegistry';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BareResultsGridInfo, getBareResultsGridInfoStyles } from 'sql/workbench/contrib/query/browser/queryResultsEditor';
@@ -207,6 +207,25 @@ export function registerNotebookThemes(overrideEditorThemeSetting: boolean, conf
${getBareResultsGridInfoStyles(rawOptions)}
}`);
+ //Notebook toolbar masked icons
+ const notebookToolbarIconColor = theme.getColor(notebookToolbarIcon);
+ if (notebookToolbarIconColor) {
+ collector.addRule(`.notebookEditor .notebook-button.masked-icon { background-color: ${notebookToolbarIconColor};}`);
+ collector.addRule(`.notebookEditor .notebook-button.masked-pseudo:before { background-color: ${notebookToolbarIconColor};}`);
+ }
+ const notebookToolbarLinesColor = theme.getColor(notebookToolbarLines);
+ if (notebookToolbarLinesColor) {
+ collector.addRule(`.notebookEditor .editor-toolbar.actionbar-container { border-bottom-color: ${notebookToolbarLinesColor}!important;}`);
+ collector.addRule(`.notebookEditor .taskbarSeparator { background-color: ${notebookToolbarLinesColor};}`);
+ }
+ const dropdownArrowColor = theme.getColor(dropdownArrow);
+ if (dropdownArrowColor) {
+ collector.addRule(`.monaco-workbench .notebookEditor .select-container:after { color: ${dropdownArrowColor};}`);
+ }
+ const buttonMenuArrowColor = theme.getColor(buttonMenuArrow);
+ if (buttonMenuArrowColor) {
+ collector.addRule(`.notebookEditor .notebook-button.masked-pseudo-after:after { background-color: ${buttonMenuArrowColor};}`);
+ }
// Cell border
const cellBorderColor = theme.getColor(cellBorder);
diff --git a/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts b/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts
index 38bf4362bc..7598ea75d7 100644
--- a/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts
+++ b/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts
@@ -40,7 +40,7 @@ suite('Notebook Actions', function (): void {
});
test('Clear All Outputs Action', async function (): Promise {
- let action = new ClearAllOutputsAction('TestId', 'TestLabel', 'TestClass');
+ let action = new ClearAllOutputsAction('TestId', true);
// Normal use case
let mockNotebookComponent = TypeMoq.Mock.ofType(NotebookComponentStub);
@@ -63,7 +63,7 @@ suite('Notebook Actions', function (): void {
let mockNotification = TypeMoq.Mock.ofType(TestNotificationService);
mockNotification.setup(n => n.notify(TypeMoq.It.isAny()));
- let action = new TrustedAction('TestId');
+ let action = new TrustedAction('TestId', true);
assert.strictEqual(action.trusted, false, 'Should not be trusted by default');
// Normal use case
@@ -105,7 +105,7 @@ suite('Notebook Actions', function (): void {
});
test('Collapse Cells Action', async function (): Promise {
- let action = new CollapseCellsAction('TestId');
+ let action = new CollapseCellsAction('TestId', true);
assert.strictEqual(action.isCollapsed, false, 'Should not be collapsed by default');
let context = {