mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Fix ##3479 ctrl+a select active cell output or preview markdown (#4981)
* Enable ctrl+a to select the output or markdown content when the cell is active * Moved toggleUserSelect into ngOnChanges * Resolve PR comments
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
<code-component [cellModel]="cellModel" [model]="model" [activeCellId]="activeCellId"></code-component>
|
<code-component [cellModel]="cellModel" [model]="model" [activeCellId]="activeCellId"></code-component>
|
||||||
</div>
|
</div>
|
||||||
<div style="flex: 0 0 auto; width: 100%; height: 100%; display: block">
|
<div style="flex: 0 0 auto; width: 100%; height: 100%; display: block">
|
||||||
<output-area-component *ngIf="cellModel.outputs && cellModel.outputs.length > 0" [cellModel]="cellModel">
|
<output-area-component *ngIf="cellModel.outputs && cellModel.outputs.length > 0" [cellModel]="cellModel" [activeCellId]="activeCellId">
|
||||||
</output-area-component>
|
</output-area-component>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
-->
|
-->
|
||||||
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: column">
|
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: column">
|
||||||
<div style="flex: 0 0 auto; user-select: initial;">
|
<div style="flex: 0 0 auto; user-select: none;">
|
||||||
<div #output ></div>
|
<div #output class="output-userselect" ></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
import 'vs/css!./code';
|
import 'vs/css!./code';
|
||||||
import 'vs/css!./media/output';
|
import 'vs/css!./media/output';
|
||||||
|
|
||||||
import { OnInit, Component, Input, Inject, ElementRef, ViewChild } from '@angular/core';
|
import { OnInit, Component, Input, Inject, ElementRef, ViewChild, SimpleChange } from '@angular/core';
|
||||||
import { AngularDisposable } from 'sql/base/node/lifecycle';
|
import { AngularDisposable } from 'sql/base/node/lifecycle';
|
||||||
import { nb } from 'azdata';
|
import { nb } from 'azdata';
|
||||||
import { ICellModel } from 'sql/workbench/parts/notebook/models/modelInterfaces';
|
import { ICellModel } from 'sql/workbench/parts/notebook/models/modelInterfaces';
|
||||||
@@ -14,8 +14,10 @@ import { MimeModel } from 'sql/workbench/parts/notebook/outputs/common/mimemodel
|
|||||||
import * as outputProcessor from 'sql/workbench/parts/notebook/outputs/common/outputProcessor';
|
import * as outputProcessor from 'sql/workbench/parts/notebook/outputs/common/outputProcessor';
|
||||||
import { RenderMimeRegistry } from 'sql/workbench/parts/notebook/outputs/registry';
|
import { RenderMimeRegistry } from 'sql/workbench/parts/notebook/outputs/registry';
|
||||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||||
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
|
|
||||||
export const OUTPUT_SELECTOR: string = 'output-component';
|
export const OUTPUT_SELECTOR: string = 'output-component';
|
||||||
|
const USER_SELECT_CLASS ='actionselect';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: OUTPUT_SELECTOR,
|
selector: OUTPUT_SELECTOR,
|
||||||
@@ -28,6 +30,7 @@ export class OutputComponent extends AngularDisposable implements OnInit {
|
|||||||
private _trusted: boolean;
|
private _trusted: boolean;
|
||||||
private _initialized: boolean = false;
|
private _initialized: boolean = false;
|
||||||
private readonly _minimumHeight = 30;
|
private readonly _minimumHeight = 30;
|
||||||
|
private _activeCellId: string;
|
||||||
registry: RenderMimeRegistry;
|
registry: RenderMimeRegistry;
|
||||||
|
|
||||||
|
|
||||||
@@ -47,6 +50,27 @@ export class OutputComponent extends AngularDisposable implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: { [propKey: string]: SimpleChange }) {
|
||||||
|
|
||||||
|
for (let propName in changes) {
|
||||||
|
if (propName === 'activeCellId') {
|
||||||
|
this.toggleUserSelect(this.isActive());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private toggleUserSelect(userSelect: boolean): void {
|
||||||
|
if (!this.outputElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (userSelect) {
|
||||||
|
DOM.addClass(this.outputElement.nativeElement, USER_SELECT_CLASS);
|
||||||
|
} else {
|
||||||
|
DOM.removeClass(this.outputElement.nativeElement, USER_SELECT_CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private renderOutput() {
|
private renderOutput() {
|
||||||
let node = this.outputElement.nativeElement;
|
let node = this.outputElement.nativeElement;
|
||||||
let output = this.cellOutput;
|
let output = this.cellOutput;
|
||||||
@@ -63,14 +87,21 @@ export class OutputComponent extends AngularDisposable implements OnInit {
|
|||||||
return this._trusted;
|
return this._trusted;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Input()
|
@Input() set trustedMode(value: boolean) {
|
||||||
set trustedMode(value: boolean) {
|
|
||||||
this._trusted = value;
|
this._trusted = value;
|
||||||
if (this._initialized) {
|
if (this._initialized) {
|
||||||
this.renderOutput();
|
this.renderOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Input() set activeCellId(value: string) {
|
||||||
|
this._activeCellId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get activeCellId(): string {
|
||||||
|
return this._activeCellId;
|
||||||
|
}
|
||||||
|
|
||||||
protected createRenderedMimetype(options: MimeModel.IOptions, node: HTMLElement): void {
|
protected createRenderedMimetype(options: MimeModel.IOptions, node: HTMLElement): void {
|
||||||
let mimeType = this.registry.preferredMimeType(
|
let mimeType = this.registry.preferredMimeType(
|
||||||
options.data,
|
options.data,
|
||||||
@@ -100,4 +131,7 @@ export class OutputComponent extends AngularDisposable implements OnInit {
|
|||||||
//this.setState({ node: node });
|
//this.setState({ node: node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protected isActive() {
|
||||||
|
return this.cellModel && this.cellModel.id === this.activeCellId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
-->
|
-->
|
||||||
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: column">
|
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: column">
|
||||||
<div #outputarea class="notebook-output" style="flex: 0 0 auto;">
|
<div #outputarea class="notebook-output" style="flex: 0 0 auto;">
|
||||||
<output-component *ngFor="let output of cellModel.outputs" [cellOutput]="output" [trustedMode] = "cellModel.trustedMode" [cellModel]="cellModel">
|
<output-component *ngFor="let output of cellModel.outputs" [cellOutput]="output" [trustedMode] = "cellModel.trustedMode" [cellModel]="cellModel" [activeCellId]="activeCellId">
|
||||||
</output-component>
|
</output-component>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -20,6 +20,8 @@ export class OutputAreaComponent extends AngularDisposable implements OnInit {
|
|||||||
@ViewChild('outputarea', { read: ElementRef }) private outputArea: ElementRef;
|
@ViewChild('outputarea', { read: ElementRef }) private outputArea: ElementRef;
|
||||||
@Input() cellModel: ICellModel;
|
@Input() cellModel: ICellModel;
|
||||||
|
|
||||||
|
private _activeCellId: string;
|
||||||
|
|
||||||
private readonly _minimumHeight = 30;
|
private readonly _minimumHeight = 30;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -41,6 +43,14 @@ export class OutputAreaComponent extends AngularDisposable implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Input() set activeCellId(value: string) {
|
||||||
|
this._activeCellId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get activeCellId(): string {
|
||||||
|
return this._activeCellId;
|
||||||
|
}
|
||||||
|
|
||||||
private updateTheme(theme: IColorTheme): void {
|
private updateTheme(theme: IColorTheme): void {
|
||||||
let outputElement = <HTMLElement>this.outputArea.nativeElement;
|
let outputElement = <HTMLElement>this.outputArea.nativeElement;
|
||||||
outputElement.style.borderTopColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
|
outputElement.style.borderTopColor = theme.getColor(themeColors.SIDE_BAR_BACKGROUND, true).toString();
|
||||||
|
|||||||
@@ -10,4 +10,8 @@ output-area-component .notebook-output {
|
|||||||
border-top-width: 0px;
|
border-top-width: 0px;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
padding: 5px 20px 0px;
|
padding: 5px 20px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.output-userselect.actionselect {
|
||||||
|
user-select: text;
|
||||||
}
|
}
|
||||||
@@ -11,7 +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 class ="notebook-preview" style="flex: 1 1 auto; user-select: initial;" (dblclick)="toggleEditMode()">
|
<div #preview class ="notebook-preview" style="flex: 1 1 auto" (dblclick)="toggleEditMode()">
|
||||||
</div>
|
</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 #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>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { Emitter } from 'vs/base/common/event';
|
import { Emitter } from 'vs/base/common/event';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||||
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
|
|
||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
import { CellView } from 'sql/workbench/parts/notebook/cellViews/interfaces';
|
import { CellView } from 'sql/workbench/parts/notebook/cellViews/interfaces';
|
||||||
@@ -24,6 +25,7 @@ import { NotebookModel } from 'sql/workbench/parts/notebook/models/notebookModel
|
|||||||
import { CellToggleMoreActions } from 'sql/workbench/parts/notebook/cellToggleMoreActions';
|
import { CellToggleMoreActions } from 'sql/workbench/parts/notebook/cellToggleMoreActions';
|
||||||
|
|
||||||
export const TEXT_SELECTOR: string = 'text-cell-component';
|
export const TEXT_SELECTOR: string = 'text-cell-component';
|
||||||
|
const USER_SELECT_CLASS ='actionselect';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: TEXT_SELECTOR,
|
selector: TEXT_SELECTOR,
|
||||||
@@ -112,6 +114,7 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
|
|||||||
if (propName === 'activeCellId') {
|
if (propName === 'activeCellId') {
|
||||||
let changedProp = changes[propName];
|
let changedProp = changes[propName];
|
||||||
this._activeCellId = changedProp.currentValue;
|
this._activeCellId = changedProp.currentValue;
|
||||||
|
this.toggleUserSelect(this.isActive());
|
||||||
// If the activeCellId is undefined (i.e. in an active cell update), don't unnecessarily set editMode to false;
|
// If the activeCellId is undefined (i.e. in an active cell update), don't unnecessarily set editMode to false;
|
||||||
// it will be set to true in a subsequent call to toggleEditMode()
|
// it will be set to true in a subsequent call to toggleEditMode()
|
||||||
if (changedProp.previousValue !== undefined) {
|
if (changedProp.previousValue !== undefined) {
|
||||||
@@ -202,6 +205,17 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private toggleUserSelect(userSelect: boolean): void {
|
||||||
|
if (!this.output) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (userSelect) {
|
||||||
|
DOM.addClass(this.output.nativeElement, USER_SELECT_CLASS);
|
||||||
|
} else {
|
||||||
|
DOM.removeClass(this.output.nativeElement, USER_SELECT_CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private setFocusAndScroll(): void {
|
private setFocusAndScroll(): void {
|
||||||
this.toggleEditMode(this.isActive());
|
this.toggleEditMode(this.isActive());
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ text-cell-component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
text-cell-component .notebook-preview {
|
text-cell-component .notebook-preview {
|
||||||
user-select: initial;
|
user-select: none;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notebook-preview.actionselect {
|
||||||
|
user-select: text;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user