10551 - Notebook UI: Added cell toolbar component (#10558)

* 10551 - Notebook UI: Added cell toolbar component, actions scaffolding, styles and theme colors. Removed markup for legacy, hidden hover buttons. Updated instaces of icon class: mask to masked-icon.

* Uncommented lines for CellToggleMoreActions so we can see how the ellipses currently work.

* Added EditCellAction which toggles between two icons.

* Cleaned up comments and removed some unused code.

* Copied DeleteCellAction into celltoolbarActions

* Connecting model and cell model to toolbar component for necessary context.

* Pass in cell + nb model from notebook component

* Adding context for EditCellAction so we can activate a cell via icon.

* Removed my copy of AddCellAction and simply referred to the existing one.

* Fixes to propogate cell model edit mode changes

* Added onCellModeChanged event registration to code.component.

* Moved cellToggleMoreActions into cellToolbarActions. Suppressing ellipses in code and textCell components.

* Fix adding cells

* Copied and modified ToggleMoreWidgetAction for use in cellToolbarActions. Instantiating cellToggleMoreActions and adding to toolbar.

* Removed unused markup, code and styles. Moved cell toolbar template into compoent.

* Removed double-click from textCell. Changed message to indicate where content goes - without it the cell does not have dimension and cannot be found by the user.

* Removed unused code file.

* Fixing my boo boo

* Updated AddCellAction with null coalescer. Set Promise to type: void.

Co-authored-by: chlafreniere <hichise@gmail.com>
This commit is contained in:
Hale Rankin
2020-05-29 18:27:36 -07:00
committed by GitHub
parent 98ce3c74e6
commit b2e0291a95
15 changed files with 298 additions and 352 deletions

View File

@@ -128,13 +128,13 @@
background-position: 2px center; background-position: 2px center;
} }
.vs .codicon.close, .vs .codicon:not(.masked-icon).close,
.vs .codicon.remove { .vs .codicon:not(.masked-icon).remove {
background: url("close.svg") center center no-repeat !important; background: url('close.svg') center center no-repeat !important;
} }
.vs-dark .codicon.close, .vs-dark .codicon:not(.masked-icon).close,
.hc-black .codicon.close, .hc-black .codicon:not(.masked-icon).close,
.vs-dark .codicon.remove, .vs-dark .codicon.remove,
.hc-black .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;
@@ -188,12 +188,12 @@
background: url("ellipsis.svg") center center no-repeat; background: url("ellipsis.svg") center center no-repeat;
} }
.hc-black .codicon.new, .hc-black .codicon:not(.masked-icon).new,
.vs-dark .codicon.new { .vs-dark .codicon:not(.masked-icon).new {
background: url("new_inverse.svg") center center no-repeat; background: url("new_inverse.svg") center center no-repeat;
} }
.vs .codicon.new { .vs .codicon:not(.masked-icon).new {
background: url("new.svg") center center no-repeat; background: url("new.svg") center center no-repeat;
} }
@@ -446,11 +446,11 @@ Includes non-masked style declarations. */
mask-image: url("chevron_down.svg"); mask-image: url("chevron_down.svg");
} }
.vs .codicon.new-blue { .vs .codicon:not(.masked-icon).new-blue {
background-image: url("new-blue.svg"); background-image: url('new-blue.svg');
} }
.vs .codicon.start-outline { .vs .codicon:not(.masked-icon).start-outline {
background-image: url("start-outline.svg"); background-image: url('start-outline.svg');
} }
/* Masked element inside pseudo element */ /* Masked element inside pseudo element */
@@ -504,24 +504,41 @@ Includes non-masked style declarations. */
mask-image: url("markdown.svg"); mask-image: url("markdown.svg");
} }
.cell-tool-close { .codicon.masked-icon.new {
background-image: url("close-blue.svg"); background-image: none;
-webkit-mask-image: url('new.svg');
mask-image: url('new.svg');
} }
.cell-tool-edit { .codicon.masked-icon.close {
background-image: url("edit.svg"); background-image: none;
-webkit-mask-image: url('close-blue.svg');
mask-image: url('close-blue.svg');
} }
.cell-tool-move-up { .codicon.masked-icon.edit {
background-image: url("down-arrow-blue.svg"); background-image: none;
-webkit-mask-image: url('edit.svg');
mask-image: url('edit.svg');
}
.codicon.masked-icon.move-up {
transform: scale(-1); transform: scale(-1);
background-image: none;
-webkit-mask-image: url('down-arrow-blue.svg');
mask-image: url('down-arrow-blue.svg');
} }
.cell-tool-move-down { .codicon.masked-icon.move-down {
background-image: url("down-arrow-blue.svg"); background-image: none;
-webkit-mask-image: url('down-arrow-blue.svg');
mask-image: url('down-arrow-blue.svg');
} }
.cell-tool-delete { .codicon.masked-icon.delete {
background-image: url("garbage-can-blue.svg"); background-image: none;
-webkit-mask-image: url('garbage-can-blue.svg');
mask-image: url('garbage-can-blue.svg');
} }
.cell-tool-more { .codicon.masked-icon.more {
background-image: url("ellipsis-blue.svg"); background-image: none;
-webkit-mask-image: url('ellipsis-blue.svg');
mask-image: url('ellipsis-blue.svg');
} }
.database-colored.codicon { .database-colored.codicon {

View File

@@ -3,33 +3,103 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ElementRef } from '@angular/core';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { ActionBar, ActionsOrientation, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { getErrorMessage } from 'vs/base/common/errors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { INotificationService } from 'vs/platform/notification/common/notification';
import * as DOM from 'vs/base/browser/dom'; import { Action, IAction } from 'vs/base/common/actions';
import { ActionBar, Separator, ActionsOrientation } from 'vs/base/browser/ui/actionbar/actionbar';
import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
import { CellActionBase, CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions'; import { CellActionBase, CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions';
import { CellTypes, CellType } from 'sql/workbench/services/notebook/common/contracts';
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { ToggleMoreWidgetAction } from 'sql/workbench/contrib/dashboard/browser/core/actions';
import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell'; import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell';
import { Action } from 'vs/base/common/actions'; import { CellTypes, CellType } from 'sql/workbench/services/notebook/common/contracts';
import { ToggleableAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
import { firstIndex } from 'vs/base/common/arrays'; import { firstIndex } from 'vs/base/common/arrays';
import { getErrorMessage } from 'vs/base/common/errors';
import Severity from 'vs/base/common/severity';
import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
export const HIDDEN_CLASS = 'actionhidden';
export class EditCellAction extends ToggleableAction {
// Constants
private static readonly editLabel = localize('editLabel', "Edit");
private static readonly closeLabel = localize('closeLabel', "Close");
private static readonly baseClass = 'codicon';
private static readonly editCssClass = 'edit';
private static readonly closeCssClass = 'close';
private static readonly maskedIconClass = 'masked-icon';
constructor(
id: string, toggleTooltip: boolean, isEditMode: boolean
) {
super(id, {
baseClass: EditCellAction.baseClass,
toggleOnLabel: EditCellAction.closeLabel,
toggleOnClass: EditCellAction.closeCssClass,
toggleOffLabel: EditCellAction.editLabel,
toggleOffClass: EditCellAction.editCssClass,
maskedIconClass: EditCellAction.maskedIconClass,
shouldToggleTooltip: toggleTooltip,
isOn: isEditMode
});
}
public get editMode(): boolean {
return this.state.isOn;
}
public set editMode(value: boolean) {
this.toggle(value);
}
public run(context: CellContext): Promise<boolean> {
let self = this;
return new Promise<boolean>((resolve, reject) => {
try {
self.editMode = !self.editMode;
context.cell.isEditMode = self.editMode;
resolve(true);
} catch (e) {
reject(e);
}
});
}
}
export class DeleteCellAction extends CellActionBase {
constructor(
id: string,
cssClass: string,
label: string,
@INotificationService notificationService: INotificationService
) {
super(id, label, undefined, notificationService);
this._cssClass = cssClass;
this._tooltip = label;
this._label = '';
}
doRun(context: CellContext): Promise<void> {
try {
context.model.deleteCell(context.cell);
} catch (error) {
let message = getErrorMessage(error);
this.notificationService.notify({
severity: Severity.Error,
message: message
});
}
return Promise.resolve();
}
}
export class CellToggleMoreActions { export class CellToggleMoreActions {
private _actions: (Action | CellActionBase)[] = []; private _actions: (Action | CellActionBase)[] = [];
private _moreActions: ActionBar; private _moreActions: ActionBar;
private _moreActionsElement: HTMLElement; private _moreActionsElement: HTMLElement;
constructor( constructor(
@IInstantiationService private instantiationService: IInstantiationService) { @IInstantiationService private instantiationService: IInstantiationService
) {
this._actions.push( this._actions.push(
instantiationService.createInstance(RunCellsAction, 'runAllBefore', localize('runAllBefore', "Run Cells Before"), false), instantiationService.createInstance(RunCellsAction, 'runAllBefore', localize('runAllBefore', "Run Cells Before"), false),
instantiationService.createInstance(RunCellsAction, 'runAllAfter', localize('runAllAfter', "Run Cells After"), true), instantiationService.createInstance(RunCellsAction, 'runAllAfter', localize('runAllAfter', "Run Cells After"), true),
@@ -44,14 +114,11 @@ export class CellToggleMoreActions {
instantiationService.createInstance(CollapseCellAction, 'expandCell', localize('expandCell', "Expand Cell"), false), instantiationService.createInstance(CollapseCellAction, 'expandCell', localize('expandCell', "Expand Cell"), false),
new Separator(), new Separator(),
instantiationService.createInstance(ClearCellOutputAction, 'clear', localize('clear', "Clear Result")), instantiationService.createInstance(ClearCellOutputAction, 'clear', localize('clear', "Clear Result")),
new Separator(),
instantiationService.createInstance(DeleteCellAction, 'delete', localize('delete', "Delete")),
); );
} }
public onInit(elementRef: ElementRef, model: NotebookModel, cellModel: ICellModel) { public onInit(elementRef: HTMLElement, context: CellContext) {
let context = new CellContext(model, cellModel); this._moreActionsElement = <HTMLElement>elementRef;
this._moreActionsElement = <HTMLElement>elementRef.nativeElement;
if (this._moreActionsElement.childNodes.length > 0) { if (this._moreActionsElement.childNodes.length > 0) {
this._moreActionsElement.removeChild(this._moreActionsElement.childNodes[0]); this._moreActionsElement.removeChild(this._moreActionsElement.childNodes[0]);
} }
@@ -59,18 +126,7 @@ export class CellToggleMoreActions {
this._moreActions.context = { target: this._moreActionsElement }; this._moreActions.context = { target: this._moreActionsElement };
let validActions = this._actions.filter(a => a instanceof Separator || a instanceof CellActionBase && a.canRun(context)); let validActions = this._actions.filter(a => a instanceof Separator || a instanceof CellActionBase && a.canRun(context));
this.removeDuplicatedAndStartingSeparators(validActions); this.removeDuplicatedAndStartingSeparators(validActions);
this._moreActions.push(this.instantiationService.createInstance(ToggleMoreWidgetAction, validActions, context), { icon: true, label: false }); this._moreActions.push(this.instantiationService.createInstance(ToggleMoreActions, validActions, context), { icon: true, label: false });
}
public toggleVisible(visible: boolean): void {
if (!this._moreActionsElement) {
return;
}
if (visible) {
DOM.addClass(this._moreActionsElement, HIDDEN_CLASS);
} else {
DOM.removeClass(this._moreActionsElement, HIDDEN_CLASS);
}
} }
private removeDuplicatedAndStartingSeparators(actions: (Action | CellActionBase)[]): void { private removeDuplicatedAndStartingSeparators(actions: (Action | CellActionBase)[]): void {
@@ -93,6 +149,7 @@ export class CellToggleMoreActions {
} }
} }
export class AddCellFromContextAction extends CellActionBase { export class AddCellFromContextAction extends CellActionBase {
constructor( constructor(
id: string, label: string, private cellType: CellType, private isAfter: boolean, id: string, label: string, private cellType: CellType, private isAfter: boolean,
@@ -121,28 +178,6 @@ export class AddCellFromContextAction extends CellActionBase {
} }
} }
export class DeleteCellAction extends CellActionBase {
constructor(id: string, label: string,
@INotificationService notificationService: INotificationService
) {
super(id, label, undefined, notificationService);
}
doRun(context: CellContext): Promise<void> {
try {
context.model.deleteCell(context.cell);
} catch (error) {
let message = getErrorMessage(error);
this.notificationService.notify({
severity: Severity.Error,
message: message
});
}
return Promise.resolve();
}
}
export class ClearCellOutputAction extends CellActionBase { export class ClearCellOutputAction extends CellActionBase {
constructor(id: string, label: string, constructor(id: string, label: string,
@INotificationService notificationService: INotificationService @INotificationService notificationService: INotificationService
@@ -249,3 +284,27 @@ export class CollapseCellAction extends CellActionBase {
return Promise.resolve(); return Promise.resolve();
} }
} }
export class ToggleMoreActions extends Action {
private static readonly ID = 'toggleMore';
private static readonly LABEL = localize('toggleMore', "Toggle More");
private static readonly ICON = 'masked-icon more';
constructor(
private readonly _actions: Array<IAction>,
private readonly _context: CellContext,
@IContextMenuService private readonly _contextMenuService: IContextMenuService
) {
super(ToggleMoreActions.ID, ToggleMoreActions.LABEL, ToggleMoreActions.ICON);
}
run(context: StandardKeyboardEvent): Promise<boolean> {
this._contextMenuService.showContextMenu({
getAnchor: () => context.target,
getActions: () => this._actions,
getActionsContext: () => this._context
});
return Promise.resolve(true);
}
}

View File

@@ -1,15 +0,0 @@
<!--
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-->
<ul class="cell-toolbar">
<li><a class="cell-tool-edit" role="button" href="#" (click)="toolbarToggleEditMode()"><span class="offscreen">{{buttonEdit}}</span></a></li>
<li><a class="cell-tool-close" role="button" href="#" (click)="toolbarUnselectActiveCell()"><span class="offscreen">{{buttonClose}}</span></a></li>
<li><a class="cell-tool-add" role="button" href="#"><span class="offscreen">{{buttonAdd}}</span></a></li>
<li><a class="cell-tool-move-down" role="button" href="#"><span class="offscreen">{{buttonMoveDown}}</span></a></li>
<li><a class="cell-tool-move-up" role="button" href="#"><span class="offscreen">{{buttonMoveUp}}</span></a></li>
<li><a class="cell-tool-delete" role="button" href="#"><span class="offscreen">{{buttonDelete}}</span></a></li>
<li><div #moreactions class="cell-tool-more"></div></li>
</ul>

View File

@@ -2,25 +2,96 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import 'vs/css!./cellToolbar';
import { Component } from '@angular/core'; import 'vs/css!./cellToolbar';
import * as DOM from 'vs/base/browser/dom';
import { Component, Inject, ViewChild, ElementRef, Input } from '@angular/core';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { DeleteCellAction, EditCellAction, CellToggleMoreActions } from 'sql/workbench/contrib/notebook/browser/cellToolbarActions';
import { AddCellAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
import { CellTypes } from 'sql/workbench/services/notebook/common/contracts';
import { DropdownMenuActionViewItem } from 'sql/base/browser/ui/buttonMenu/buttonMenu';
import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
import { CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions';
export const CELL_TOOLBAR_SELECTOR: string = 'cell-toolbar-component'; export const CELL_TOOLBAR_SELECTOR: string = 'cell-toolbar-component';
@Component({ @Component({
selector: CELL_TOOLBAR_SELECTOR, selector: CELL_TOOLBAR_SELECTOR,
templateUrl: decodeURI(require.toUrl('./cellToolbar.component.html')) template: `<div #celltoolbar></div>`
}) })
export class CellToolbarComponent { export class CellToolbarComponent {
@ViewChild('celltoolbar', { read: ElementRef }) private celltoolbar: ElementRef;
public buttonEdit = localize('buttonEdit', "Edit"); public buttonEdit = localize('buttonEdit', "Edit");
public buttonClose = localize('buttonClose', "Close"); public buttonClose = localize('buttonClose', "Close");
public buttonAdd = localize('buttonAdd', "Add new cell"); public buttonAdd = localize('buttonAdd', "Add new cell");
public buttonMoveDown = localize('buttonMoveDown', "Move cell down");
public buttonMoveUp = localize('buttonMoveUp', "Move cell up");
public buttonDelete = localize('buttonDelete', "Delete cell"); public buttonDelete = localize('buttonDelete', "Delete cell");
constructor() { @Input() cellModel: ICellModel;
@Input() model: NotebookModel;
private _actionBar: Taskbar;
private _editCellAction: EditCellAction;
public _cellToggleMoreActions: CellToggleMoreActions;
constructor(
@Inject(IInstantiationService) private instantiationService: IInstantiationService,
@Inject(IContextMenuService) private contextMenuService: IContextMenuService
) {
this._cellToggleMoreActions = this.instantiationService.createInstance(CellToggleMoreActions);
}
ngOnInit() {
this.initActionBar();
}
protected initActionBar(): void {
let context = new CellContext(this.model, this.cellModel);
let taskbar = <HTMLElement>this.celltoolbar.nativeElement;
this._actionBar = new Taskbar(taskbar);
this._actionBar.context = context;
let addCodeCellButton = new AddCellAction('notebook.AddCodeCell', localize('codePreview', "Code cell"), 'notebook-button masked-pseudo code');
addCodeCellButton.cellType = CellTypes.Code;
let addTextCellButton = new AddCellAction('notebook.AddTextCell', localize('textPreview', "Markdown cell"), 'notebook-button masked-pseudo markdown');
addTextCellButton.cellType = CellTypes.Markdown;
let deleteButton = this.instantiationService.createInstance(DeleteCellAction, 'delete', 'codicon masked-icon delete', localize('delete', "Delete"));
let moreActionsContainer = DOM.$('li.action-item');
this._cellToggleMoreActions = this.instantiationService.createInstance(CellToggleMoreActions);
this._cellToggleMoreActions.onInit(moreActionsContainer, context);
this._editCellAction = this.instantiationService.createInstance(EditCellAction, 'notebook.editCell', true, this.cellModel.isEditMode);
this._editCellAction.enabled = true;
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 masked-icon new',
localize('addCell', "Cell"),
undefined
);
dropdownMenuActionViewItem.render(buttonDropdownContainer);
dropdownMenuActionViewItem.setActionContext(context);
this._actionBar.setContent([
{ action: this._editCellAction },
{ element: buttonDropdownContainer },
{ action: deleteButton },
{ element: moreActionsContainer }
]);
} }
} }

View File

@@ -4,44 +4,41 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
cell-toolbar-component { cell-toolbar-component {
border-width: 1px;
border-style: solid;
position: absolute; position: absolute;
left: 25px; left: 20px;
top: -21px; top: -20px;
} }
cell-toolbar-component ul { cell-toolbar-component .carbon-taskbar .monaco-action-bar.animated {
display: inline-block; padding: 0;
}
cell-toolbar-component .carbon-taskbar.monaco-toolbar .monaco-action-bar.animated ul.actions-container {
display: flex;
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 5px 10px 0 10px; padding: 0;
} }
cell-toolbar-component li { cell-toolbar-component ul.actions-container li.action-item {
display: inline-block; display: inline-flex;
margin-right: 4px; margin-right: 0;
text-align: center; text-align: center;
} }
cell-toolbar-component li:last-child { cell-toolbar-component ul.actions-container li:last-child {
margin-right: 0; margin-right: 0;
} }
cell-toolbar-component .carbon-taskbar .action-label {
cell-toolbar-component li a { padding: 0;
background: 50% 50% no-repeat;
display: block;
height: 16px;
width: 16px;
} }
cell-toolbar-component .monaco-action-bar .action-label {
cell-toolbar-component li div { margin-right: 0;
background: 50% 50% no-repeat;
height: 16px;
width: 16px;
} }
cell-toolbar-component ul.actions-container li a.masked-icon {
cell-toolbar-component .offscreen { display: flex;
height: 1px; height: 24px;
text-indent: -999999px; width: 29px;
margin-top: -1px;
position: absolute;
} }

View File

@@ -11,7 +11,6 @@
<div style="flex: 1 1 auto; overflow: hidden;"> <div style="flex: 1 1 auto; overflow: hidden;">
<div #editor class="editor"></div> <div #editor class="editor"></div>
</div> </div>
<div #moreactions class="moreActions" style="flex: 0 0 auto; flex-flow:column;width: 20px; min-height: 20px; max-height: 20px; padding-top: 0px; orientation: portrait"></div>
</div> </div>
<collapse-component *ngIf="cellModel.cellType === 'code' && cellModel.source && cellModel.source.length > 1" [cellModel]="cellModel" [activeCellId]="activeCellId"></collapse-component> <collapse-component *ngIf="cellModel.cellType === 'code' && cellModel.source && cellModel.source.length > 1" [cellModel]="cellModel" [activeCellId]="activeCellId"></collapse-component>
</div> </div>

View File

@@ -7,7 +7,6 @@ import 'vs/css!./code';
import { OnInit, Component, Input, Inject, ElementRef, ViewChild, Output, EventEmitter, OnChanges, SimpleChange, forwardRef, ChangeDetectorRef } from '@angular/core'; import { OnInit, Component, Input, Inject, ElementRef, ViewChild, Output, EventEmitter, OnChanges, SimpleChange, forwardRef, ChangeDetectorRef } from '@angular/core';
import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryTextEditor'; import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryTextEditor';
import { CellToggleMoreActions } from 'sql/workbench/contrib/notebook/browser/cellToggleMoreActions';
import { ICellModel, CellExecutionState } from 'sql/workbench/services/notebook/browser/models/modelInterfaces'; import { ICellModel, CellExecutionState } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar'; import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { RunCellAction, CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions'; import { RunCellAction, CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions';
@@ -26,7 +25,6 @@ import { CellTypes } from 'sql/workbench/services/notebook/common/contracts';
import { OVERRIDE_EDITOR_THEMING_SETTING } from 'sql/workbench/services/notebook/browser/notebookService'; import { OVERRIDE_EDITOR_THEMING_SETTING } from 'sql/workbench/services/notebook/browser/notebookService';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { CollapseComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/collapse.component';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { CellView } from 'sql/workbench/contrib/notebook/browser/cellViews/interfaces'; import { CellView } from 'sql/workbench/contrib/notebook/browser/cellViews/interfaces';
import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput';
@@ -48,9 +46,7 @@ const DEFAULT_OR_LOCAL_CONTEXT_ID = '-1';
}) })
export class CodeComponent extends CellView implements OnInit, OnChanges { export class CodeComponent extends CellView implements OnInit, OnChanges {
@ViewChild('toolbar', { read: ElementRef }) private toolbarElement: ElementRef; @ViewChild('toolbar', { read: ElementRef }) private toolbarElement: ElementRef;
@ViewChild('moreactions', { read: ElementRef }) private moreActionsElementRef: ElementRef;
@ViewChild('editor', { read: ElementRef }) private codeElement: ElementRef; @ViewChild('editor', { read: ElementRef }) private codeElement: ElementRef;
@ViewChild(CollapseComponent) private collapseComponent: CollapseComponent;
public get cellModel(): ICellModel { public get cellModel(): ICellModel {
return this._cellModel; return this._cellModel;
@@ -83,14 +79,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
this._activeCellId = value; this._activeCellId = value;
} }
@Input() set hover(value: boolean) {
this.cellModel.hover = value;
if (!this.isActive()) {
// Only make a change if we're not active, since this has priority
this.toggleActionsVisibility(this.cellModel.hover);
}
}
protected _actionBar: Taskbar; protected _actionBar: Taskbar;
private readonly _minimumHeight = 30; private readonly _minimumHeight = 30;
private readonly _maximumHeight = 4000; private readonly _maximumHeight = 4000;
@@ -100,7 +88,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
private _editorModel: ITextModel; private _editorModel: ITextModel;
private _model: NotebookModel; private _model: NotebookModel;
private _activeCellId: string; private _activeCellId: string;
private _cellToggleMoreActions: CellToggleMoreActions;
private _layoutEmitter = new Emitter<void>(); private _layoutEmitter = new Emitter<void>();
constructor( constructor(
@@ -113,7 +100,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
@Inject(ILogService) private readonly logService: ILogService @Inject(ILogService) private readonly logService: ILogService
) { ) {
super(); super();
this._cellToggleMoreActions = this._instantiationService.createInstance(CellToggleMoreActions);
this._register(Event.debounce(this._layoutEmitter.event, (l, e) => e, 250, /*leading=*/false) this._register(Event.debounce(this._layoutEmitter.event, (l, e) => e, 250, /*leading=*/false)
(() => this.layout())); (() => this.layout()));
// Handle disconnect on removal of the cell, if it was the active cell // Handle disconnect on removal of the cell, if it was the active cell
@@ -134,7 +120,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
let changedProp = changes[propName]; let changedProp = changes[propName];
let isActive = this.cellModel.id === changedProp.currentValue; let isActive = this.cellModel.id === changedProp.currentValue;
this.updateConnectionState(isActive); this.updateConnectionState(isActive);
this.toggleActionsVisibility(isActive);
if (this._editor) { if (this._editor) {
this._editor.toggleEditorSelected(isActive); this._editor.toggleEditorSelected(isActive);
} }
@@ -288,7 +273,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
this._actionBar.setContent([ this._actionBar.setContent([
{ action: runCellAction } { action: runCellAction }
]); ]);
this._cellToggleMoreActions.onInit(this.moreActionsElementRef, this.model, this.cellModel);
} }
/// Editor Functions /// Editor Functions
@@ -334,9 +318,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
private updateTheme(theme: IColorTheme): void { private updateTheme(theme: IColorTheme): void {
let toolbarEl = <HTMLElement>this.toolbarElement.nativeElement; let toolbarEl = <HTMLElement>this.toolbarElement.nativeElement;
toolbarEl.style.borderRightColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString(); toolbarEl.style.borderRightColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
let moreActionsEl = <HTMLElement>this.moreActionsElementRef.nativeElement;
moreActionsEl.style.borderRightColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
} }
private setFocusAndScroll(): void { private setFocusAndScroll(): void {
@@ -354,14 +335,6 @@ export class CodeComponent extends CellView implements OnInit, OnChanges {
return this.cellModel && this.cellModel.id === this.activeCellId; return this.cellModel && this.cellModel.id === this.activeCellId;
} }
protected toggleActionsVisibility(isActiveOrHovered: boolean) {
this._cellToggleMoreActions.toggleVisible(!isActiveOrHovered);
if (this.collapseComponent) {
this.collapseComponent.toggleIconVisibility(isActiveOrHovered);
}
}
private onCellCollapse(isCollapsed: boolean): void { private onCellCollapse(isCollapsed: boolean): void {
let editorWidget = this._editor.getControl() as ICodeEditor; let editorWidget = this._editor.getControl() as ICodeEditor;
if (isCollapsed) { if (isCollapsed) {

View File

@@ -18,7 +18,7 @@
display: block; display: block;
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 4px 16px; padding: 10px 16px 4px 16px;
} }
.markdown-toolbar .carbon-taskbar li.action-item { .markdown-toolbar .carbon-taskbar li.action-item {
display: inline-block; display: inline-block;

View File

@@ -11,9 +11,7 @@
</code-component> </code-component>
</div> </div>
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: row"> <div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: row">
<div #preview link-handler [isTrusted]="isTrusted" [notebookUri]="notebookUri" class="notebook-preview" style="flex: 1 1 auto" (dblclick)="toggleEditMode()"> <div #preview link-handler [isTrusted]="isTrusted" [notebookUri]="notebookUri" class="notebook-preview" style="flex: 1 1 auto">
</div>
<div #moreactions class="moreActions" style="flex: 0 0 auto; display: flex; flex-flow:column;width: 20px; min-height: 20px; max-height: 20px; padding-top: 0px; orientation: portrait">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -23,7 +23,6 @@ import { CellView } from 'sql/workbench/contrib/notebook/browser/cellViews/inter
import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces'; import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel'; import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
import { ISanitizer, defaultSanitizer } from 'sql/workbench/services/notebook/browser/outputs/sanitizer'; import { ISanitizer, defaultSanitizer } from 'sql/workbench/services/notebook/browser/outputs/sanitizer';
import { CellToggleMoreActions } from 'sql/workbench/contrib/notebook/browser/cellToggleMoreActions';
import { CodeComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/code.component'; import { CodeComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/code.component';
import { NotebookRange, ICellEditorProvider } from 'sql/workbench/services/notebook/browser/notebookService'; import { NotebookRange, ICellEditorProvider } from 'sql/workbench/services/notebook/browser/notebookService';
import { IColorTheme } from 'vs/platform/theme/common/themeService'; import { IColorTheme } from 'vs/platform/theme/common/themeService';
@@ -38,7 +37,6 @@ const USER_SELECT_CLASS = 'actionselect';
}) })
export class TextCellComponent extends CellView implements OnInit, OnChanges { export class TextCellComponent extends CellView implements OnInit, OnChanges {
@ViewChild('preview', { read: ElementRef }) private output: ElementRef; @ViewChild('preview', { read: ElementRef }) private output: ElementRef;
@ViewChild('moreactions', { read: ElementRef }) private moreActionsElementRef: ElementRef;
@ViewChildren(CodeComponent) private markdowncodeCell: QueryList<CodeComponent>; @ViewChildren(CodeComponent) private markdowncodeCell: QueryList<CodeComponent>;
@Input() cellModel: ICellModel; @Input() cellModel: ICellModel;
@@ -51,14 +49,6 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
this._activeCellId = value; this._activeCellId = value;
} }
@Input() set hover(value: boolean) {
this._hover = value;
if (!this.isActive()) {
// Only make a change if we're not active, since this has priority
this.updateMoreActions();
}
}
@HostListener('document:keydown.escape', ['$event']) @HostListener('document:keydown.escape', ['$event'])
handleKeyboardEvent() { handleKeyboardEvent() {
if (this.isEditMode) { if (this.isEditMode) {
@@ -84,8 +74,6 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
private _activeCellId: string; private _activeCellId: string;
private readonly _onDidClickLink = this._register(new Emitter<URI>()); private readonly _onDidClickLink = this._register(new Emitter<URI>());
public readonly onDidClickLink = this._onDidClickLink.event; public readonly onDidClickLink = this._onDidClickLink.event;
private _cellToggleMoreActions: CellToggleMoreActions;
private _hover: boolean;
private markdownRenderer: NotebookMarkdownRenderer; private markdownRenderer: NotebookMarkdownRenderer;
private markdownResult: IMarkdownRenderResult; private markdownResult: IMarkdownRenderResult;
public previewFeaturesEnabled: boolean = false; public previewFeaturesEnabled: boolean = false;
@@ -98,7 +86,6 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
) { ) {
super(); super();
this.isEditMode = true; this.isEditMode = true;
this._cellToggleMoreActions = this._instantiationService.createInstance(CellToggleMoreActions);
this.markdownRenderer = this._instantiationService.createInstance(NotebookMarkdownRenderer); this.markdownRenderer = this._instantiationService.createInstance(NotebookMarkdownRenderer);
this._register(toDisposable(() => { this._register(toDisposable(() => {
if (this.markdownResult) { if (this.markdownResult) {
@@ -143,11 +130,15 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
this.previewFeaturesEnabled = this._configurationService.getValue('workbench.enablePreviewFeatures'); this.previewFeaturesEnabled = this._configurationService.getValue('workbench.enablePreviewFeatures');
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this)); this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
this.updateTheme(this.themeService.getColorTheme()); this.updateTheme(this.themeService.getColorTheme());
this._cellToggleMoreActions.onInit(this.moreActionsElementRef, this.model, this.cellModel);
this.setFocusAndScroll(); this.setFocusAndScroll();
this._register(this.cellModel.onOutputsChanged(e => { this._register(this.cellModel.onOutputsChanged(e => {
this.updatePreview(); this.updatePreview();
})); }));
this._register(this.cellModel.onCellModeChanged(mode => {
if (mode !== this.isEditMode) {
this.toggleEditMode(mode);
}
}));
} }
ngOnChanges(changes: { [propKey: string]: SimpleChange }) { ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
@@ -191,7 +182,7 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
if (trustedChanged || contentChanged) { if (trustedChanged || contentChanged) {
this._lastTrustedMode = this.cellModel.trustedMode; this._lastTrustedMode = this.cellModel.trustedMode;
if ((!cellModelSourceJoined) && !this.isEditMode) { if ((!cellModelSourceJoined) && !this.isEditMode) {
this._content = localize('doubleClickEdit', "Double-click to edit"); this._content = localize('addContent', "Add content here...");
} else { } else {
this._content = this.cellModel.source; this._content = this.cellModel.source;
} }
@@ -224,9 +215,6 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
private updateTheme(theme: IColorTheme): void { private updateTheme(theme: IColorTheme): void {
let outputElement = <HTMLElement>this.output.nativeElement; let outputElement = <HTMLElement>this.output.nativeElement;
outputElement.style.borderTopColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString(); outputElement.style.borderTopColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
let moreActionsEl = <HTMLElement>this.moreActionsElementRef.nativeElement;
moreActionsEl.style.borderRightColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
} }
public handleContentChanged(): void { public handleContentChanged(): void {
@@ -236,20 +224,10 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
public toggleEditMode(editMode?: boolean): void { public toggleEditMode(editMode?: boolean): void {
this.isEditMode = editMode !== undefined ? editMode : !this.isEditMode; this.isEditMode = editMode !== undefined ? editMode : !this.isEditMode;
this.cellModel.isEditMode = this.isEditMode; this.cellModel.isEditMode = this.isEditMode;
this.updateMoreActions();
this.updatePreview(); this.updatePreview();
this._changeRef.detectChanges(); this._changeRef.detectChanges();
} }
private updateMoreActions(): void {
if (!this.isEditMode && (this.isActive() || this._hover)) {
this.toggleMoreActionsButton(true);
}
else {
this.toggleMoreActionsButton(false);
}
}
private toggleUserSelect(userSelect: boolean): void { private toggleUserSelect(userSelect: boolean): void {
if (!this.output) { if (!this.output) {
return; return;
@@ -273,10 +251,6 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
return this.cellModel && this.cellModel.id === this.activeCellId; return this.cellModel && this.cellModel.id === this.activeCellId;
} }
protected toggleMoreActionsButton(isActiveOrHovered: boolean) {
this._cellToggleMoreActions.toggleVisible(!isActiveOrHovered);
}
public deltaDecorations(newDecorationRange: NotebookRange, oldDecorationRange: NotebookRange): void { public deltaDecorations(newDecorationRange: NotebookRange, oldDecorationRange: NotebookRange): void {
if (oldDecorationRange) { if (oldDecorationRange) {
this.removeDecoration(oldDecorationRange); this.removeDecoration(oldDecorationRange);

View File

@@ -9,35 +9,14 @@
</div> </div>
<div #container class="scrollable" style="flex: 1 1 auto; position: relative; outline: none" (click)="unselectActiveCell()" (scroll)="scrollHandler($event)"> <div #container class="scrollable" style="flex: 1 1 auto; position: relative; outline: none" (click)="unselectActiveCell()" (scroll)="scrollHandler($event)">
<loading-spinner [loading]="isLoading"></loading-spinner> <loading-spinner [loading]="isLoading"></loading-spinner>
<div class="hoverButtonsContainer" *ngIf="(cells && cells.length > 0) && !isLoading">
<span class="containerBackground"></span>
<button class="hoverButton" (click)="addCell('code', 0, $event)">
<div class="addCodeIcon"></div>
<span>{{addCodeLabel}}</span>
</button>
<button class="hoverButton" (click)="addCell('markdown', 0, $event)">
<div class="addTextIcon"></div>
<span>{{addTextLabel}}</span>
</button>
</div>
<div *ngFor="let cell of cells"> <div *ngFor="let cell of cells">
<div class="notebook-cell" (click)="selectCell(cell, $event)" [class.active]="cell.active"> <div class="notebook-cell" (click)="selectCell(cell, $event)" [class.active]="cell.active">
<cell-toolbar-component *ngIf="cell.active" [cellModel]="cell" [model]="model"></cell-toolbar-component>
<code-cell-component *ngIf="cell.cellType === 'code'" [cellModel]="cell" [model]="model" [activeCellId]="activeCellId"> <code-cell-component *ngIf="cell.cellType === 'code'" [cellModel]="cell" [model]="model" [activeCellId]="activeCellId">
</code-cell-component> </code-cell-component>
<text-cell-component *ngIf="cell.cellType === 'markdown'" [cellModel]="cell" [model]="model" [activeCellId]="activeCellId"> <text-cell-component *ngIf="cell.cellType === 'markdown'" [cellModel]="cell" [model]="model" [activeCellId]="activeCellId">
</text-cell-component> </text-cell-component>
</div> </div>
<div class="hoverButtonsContainer">
<span class="containerBackground"></span>
<button class="hoverButton" (click)="addCell('code', findCellIndex(cell) + 1, $event)">
<div class="addCodeIcon"></div>
<span>{{addCodeLabel}}</span>
</button>
<button class="hoverButton" (click)="addCell('markdown', findCellIndex(cell) + 1, $event)">
<div class="addTextIcon"></div>
<span>{{addTextLabel}}</span>
</button>
</div>
</div> </div>
<div class="notebook-cell" *ngIf="(!cells || !cells.length) && !isLoading"> <div class="notebook-cell" *ngIf="(!cells || !cells.length) && !isLoading">
<placeholder-cell-component [cellModel]="cell" [model]="model"> <placeholder-cell-component [cellModel]="cell" [model]="model">

View File

@@ -2,8 +2,9 @@
* Copyright (c) Microsoft Corporation. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
.notebookEditor .scrollable { .notebookEditor .scrollable {
margin-top: 5px; padding-top: 6px;
} }
.notebookEditor .taskbarSeparator { .notebookEditor .taskbarSeparator {
@@ -19,7 +20,7 @@
border-color: transparent; border-color: transparent;
border-style: solid; border-style: solid;
border-width: 1px 1px 1px 4px; border-width: 1px 1px 1px 4px;
margin: 1px 20px; margin: 16px;
position: relative; position: relative;
} }
@@ -236,54 +237,6 @@
margin-right: 10px; margin-right: 10px;
} }
.notebookEditor .hoverButtonsContainer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: 100%;
padding: 0px 20px;
margin: 1px 0px;
box-sizing: border-box;
}
.notebookEditor .hoverButtonsContainer .containerBackground {
position: absolute;
width: auto;
left: 20px;
right: 20px;
height: 1px;
z-index: 0;
visibility: hidden;
}
.notebookEditor .hoverButtonsContainer:hover .containerBackground {
visibility: visible;
}
.notebookEditor .hoverButtonsContainer .hoverButton {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin: 3px 2px;
padding: 4px 12px;
font-size: 12px;
box-sizing: border-box;
border-width: 1px;
border-style: solid;
z-index: 1;
visibility: hidden;
}
.notebookEditor .hoverButtonsContainer:hover .hoverButton {
visibility: visible;
}
.notebookEditor .hoverButton:active {
transform: scale(1.05);
}
.notebookEditor .hoverButton .addCodeIcon, .notebookEditor .hoverButton .addCodeIcon,
.notebookEditor .hoverButton .addTextIcon { .notebookEditor .hoverButton .addTextIcon {
display: inline-block; display: inline-block;
@@ -295,24 +248,6 @@
margin-right: 4px; margin-right: 4px;
} }
.notebookEditor .hoverButton .addCodeIcon {
background-image: url("./media/light/add_code.svg");
}
.vs-dark .notebookEditor .hoverButton .addCodeIcon,
.hc-black .notebookEditor .hoverButton .addCodeIcon {
background-image: url("./media/dark/add_code_inverse.svg");
}
.notebookEditor .hoverButton .addTextIcon {
background-image: url("./media/light/add_text.svg");
}
.vs-dark .notebookEditor .hoverButton .addTextIcon,
.hc-black .notebookEditor .hoverButton .addTextIcon {
background-image: url("./media/dark/add_text_inverse.svg");
}
.monaco-workbench.mac .notebookEditor .select-container { .monaco-workbench.mac .notebookEditor .select-container {
padding-top: 2px; padding-top: 2px;
} }

View File

@@ -28,6 +28,7 @@ import { find, firstIndex } from 'vs/base/common/arrays';
import { INotebookEditor } from 'sql/workbench/services/notebook/browser/notebookService'; import { INotebookEditor } from 'sql/workbench/services/notebook/browser/notebookService';
import { NotebookComponent } from 'sql/workbench/contrib/notebook/browser/notebook.component'; import { NotebookComponent } from 'sql/workbench/contrib/notebook/browser/notebook.component';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions';
const msgLoading = localize('loading', "Loading kernels..."); const msgLoading = localize('loading', "Loading kernels...");
const msgChanging = localize('changing', "Changing kernel..."); const msgChanging = localize('changing', "Changing kernel...");
@@ -49,18 +50,29 @@ export class AddCellAction extends Action {
) { ) {
super(id, label, cssClass); super(id, label, cssClass);
} }
public async run(context: INotebookEditor): Promise<any> { public async run(context: INotebookEditor | CellContext): Promise<void> {
//Add Cell after current selected cell.
let index = 0; let index = 0;
if (context && context.cells) { if (context instanceof CellContext) {
let notebookcomponent = context as NotebookComponent; if (context?.model?.cells) {
let id = notebookcomponent.activeCellId; let activeCellId = context.model.activeCell.id;
if (id) { if (activeCellId) {
index = context.cells.findIndex(cell => cell.id === id); index = context.model.cells.findIndex(cell => cell.id === activeCellId) + 1;
index = index + 1; }
} }
if (context?.model) {
context.model.addCell(this.cellType, index);
}
} else {
//Add Cell after current selected cell.
if (context?.cells) {
let notebookcomponent = context as NotebookComponent;
let id = notebookcomponent.activeCellId;
if (id) {
index = context.cells.findIndex(cell => cell.id === id) + 1;
}
}
context.addCell(this.cellType, index);
} }
context.addCell(this.cellType, index);
} }
} }

View File

@@ -6,9 +6,9 @@ import 'vs/css!./notebook';
import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService'; import { registerThemingParticipant, IColorTheme, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { SIDE_BAR_BACKGROUND, EDITOR_GROUP_HEADER_TABS_BACKGROUND } from 'vs/workbench/common/theme'; 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 { activeContrastBorder, contrastBorder, buttonBackground, textLinkForeground, textLinkActiveForeground, textPreformatForeground, textBlockQuoteBackground, textBlockQuoteBorder, buttonForeground } from 'vs/platform/theme/common/colorRegistry';
import { editorLineHighlight, editorLineHighlightBorder } from 'vs/editor/common/view/editorColorRegistry'; import { editorLineHighlight, editorLineHighlightBorder } from 'vs/editor/common/view/editorColorRegistry';
import { cellBorder, notebookToolbarIcon, notebookToolbarLines, buttonMenuArrow, dropdownArrow, 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, notebookToolbarSelectBackground } from 'sql/platform/theme/common/colorRegistry';
import { IDisposable } from 'vs/base/common/lifecycle'; import { IDisposable } from 'vs/base/common/lifecycle';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BareResultsGridInfo, getBareResultsGridInfoStyles } from 'sql/workbench/contrib/query/browser/queryResultsEditor'; import { BareResultsGridInfo, getBareResultsGridInfoStyles } from 'sql/workbench/contrib/query/browser/queryResultsEditor';
@@ -34,49 +34,6 @@ export function registerNotebookThemes(overrideEditorThemeSetting: boolean, conf
`); `);
} }
if (buttonBackgroundColor) {
let lighterBackgroundColor = lighten(buttonBackgroundColor, 0.825)(theme);
collector.addRule(`
.notebookEditor .hoverButton {
border-color: ${buttonBackgroundColor};
}
.notebookEditor .hoverButton:active,
.notebookEditor .hoverButton:hover {
background-color: ${buttonBackgroundColor};
}
.notebookEditor .hoverButton {
color: ${buttonBackgroundColor};
}
.vs-dark .notebookEditor .hoverButton {
border-color: ${lighterBackgroundColor};
}
.vs-dark .notebookEditor .hoverButton:active,
.vs-dark .notebookEditor .hoverButton:hover {
background-color: ${lighterBackgroundColor};
}
.vs-dark .notebookEditor .hoverButton {
color: ${lighterBackgroundColor};
}
`);
}
const backgroundColor = theme.getColor(editorBackground);
if (backgroundColor) {
collector.addRule(`
.notebookEditor .hoverButton {
background-color: ${backgroundColor};
}
.notebookEditor .hoverButton:active,
.notebookEditor .hoverButton:hover {
color: ${backgroundColor};
}
.hc-black .notebookEditor .hoverButton:active,
.hc-black .notebookEditor .hoverButton:hover {
color: ${backgroundColor};
}
`);
}
const inactiveBorder = theme.getColor(SIDE_BAR_BACKGROUND); const inactiveBorder = theme.getColor(SIDE_BAR_BACKGROUND);
const notebookLineHighlight = theme.getColor(EDITOR_GROUP_HEADER_TABS_BACKGROUND); const notebookLineHighlight = theme.getColor(EDITOR_GROUP_HEADER_TABS_BACKGROUND);
// Code editor style overrides - only applied if user chooses this as preferred option // Code editor style overrides - only applied if user chooses this as preferred option
@@ -100,13 +57,6 @@ export function registerNotebookThemes(overrideEditorThemeSetting: boolean, conf
// Inactive border // Inactive border
if (inactiveBorder) { if (inactiveBorder) {
// Standard notebook cell behavior
collector.addRule(`
.notebookEditor .hoverButtonsContainer .containerBackground {
background-color: ${inactiveBorder};
}
`);
// Ensure there's always a line between editor and output // Ensure there's always a line between editor and output
collector.addRule(` collector.addRule(`
.notebookEditor .notebook-cell.active code-component { .notebookEditor .notebook-cell.active code-component {
@@ -129,16 +79,6 @@ export function registerNotebookThemes(overrideEditorThemeSetting: boolean, conf
outline-width: 1px; outline-width: 1px;
outline-style: solid; outline-style: solid;
} }
.hc-black .notebookEditor .hoverButton {
color: ${hcOutline};
}
.hc-black .notebookEditor .hoverButton:not(:active) {
border-color: ${hcOutline};
}
.hc-black .notebookEditor .hoverButton:active,
.hc-black .notebookEditor .hoverButton:hover {
background-color: ${hcOutline};
}
`); `);
} }
@@ -227,10 +167,17 @@ export function registerNotebookThemes(overrideEditorThemeSetting: boolean, conf
collector.addRule(`.notebookEditor .notebook-button.masked-pseudo-after:after { background-color: ${buttonMenuArrowColor};}`); collector.addRule(`.notebookEditor .notebook-button.masked-pseudo-after:after { background-color: ${buttonMenuArrowColor};}`);
} }
// Cell border // Active cell border, cell toolbar border, cell toolbar icons
const cellBorderColor = theme.getColor(cellBorder); const cellBorderColor = theme.getColor(cellBorder);
if (cellBorderColor) { if (cellBorderColor) {
collector.addRule(`.notebookEditor .notebook-cell.active { border-color: ${cellBorderColor};}`); collector.addRule(`.notebookEditor .notebook-cell.active { border-color: ${cellBorderColor};}`);
collector.addRule(`.notebookEditor .notebook-cell.active cell-toolbar-component { border-color: ${cellBorderColor};}`);
collector.addRule(`.notebookEditor .notebook-cell.active cell-toolbar-component .codicon { background-color: ${cellBorderColor};}`);
}
// Cell toolbar background
const notebookToolbarSelectBackgroundColor = theme.getColor(notebookToolbarSelectBackground);
if (notebookToolbarSelectBackgroundColor) {
collector.addRule(`.notebookEditor .notebook-cell.active cell-toolbar-component { background-color: ${notebookToolbarSelectBackgroundColor};}`);
} }
// Markdown editor toolbar // Markdown editor toolbar

View File

@@ -378,7 +378,7 @@ export class NotebookModel extends Disposable implements INotebookModel {
} }
// Set newly created cell as active cell // Set newly created cell as active cell
this.updateActiveCell(cell); this.updateActiveCell(cell);
cell.isEditMode = true;
this._contentChangedEmitter.fire({ this._contentChangedEmitter.fire({
changeType: NotebookChangeType.CellsModified, changeType: NotebookChangeType.CellsModified,
cells: [cell], cells: [cell],