From 6a310670aae4d289b90312da88b71c3348c9d0d8 Mon Sep 17 00:00:00 2001 From: David Kutugata Date: Tue, 6 Aug 2019 14:19:23 -0700 Subject: [PATCH 1/2] row height on data viewer now scales to the font size of VS code --- news/2 Fixes/6614.md | 1 + src/client/common/application/webPanel.ts | 8 +-- src/client/datascience/codeCssGenerator.ts | 60 +++++++++---------- .../datascience/data-viewing/dataViewer.ts | 8 +-- .../data-explorer/mainPanel.tsx | 14 ++++- .../data-explorer/reactSlickGrid.tsx | 22 +++++-- .../react-common/styleInjector.tsx | 5 ++ 7 files changed, 72 insertions(+), 46 deletions(-) create mode 100644 news/2 Fixes/6614.md diff --git a/news/2 Fixes/6614.md b/news/2 Fixes/6614.md new file mode 100644 index 000000000000..e0610aa6248b --- /dev/null +++ b/news/2 Fixes/6614.md @@ -0,0 +1 @@ +Make data viewer change row height according to font size in settings. \ No newline at end of file diff --git a/src/client/common/application/webPanel.ts b/src/client/common/application/webPanel.ts index c72c42646e49..093d3882ba98 100644 --- a/src/client/common/application/webPanel.ts +++ b/src/client/common/application/webPanel.ts @@ -36,7 +36,7 @@ export class WebPanel implements IWebPanel { this.panel = window.createWebviewPanel( title.toLowerCase().replace(' ', ''), title, - {viewColumn , preserveFocus: true}, + { viewColumn, preserveFocus: true }, { enableScripts: true, retainContextWhenHidden: true, @@ -58,11 +58,11 @@ export class WebPanel implements IWebPanel { } } - public isVisible() : boolean { + public isVisible(): boolean { return this.panel ? this.panel.visible : false; } - public isActive() : boolean { + public isActive(): boolean { return this.panel ? this.panel.active : false; } @@ -121,7 +121,7 @@ export class WebPanel implements IWebPanel { private generateReactHtml(mainScriptPath: string, embeddedCss?: string, settings?: any) { const uriBasePath = Uri.file(`${path.dirname(mainScriptPath)}/`); const uriPath = Uri.file(mainScriptPath); - const uriBase = uriBasePath.with({ scheme: 'vscode-resource'}); + const uriBase = uriBasePath.with({ scheme: 'vscode-resource' }); const uri = uriPath.with({ scheme: 'vscode-resource' }); const locDatabase = localize.getCollectionJSON(); const style = embeddedCss ? embeddedCss : ''; diff --git a/src/client/datascience/codeCssGenerator.ts b/src/client/datascience/codeCssGenerator.ts index f61e2b179f9f..4f5882237df7 100644 --- a/src/client/datascience/codeCssGenerator.ts +++ b/src/client/datascience/codeCssGenerator.ts @@ -23,8 +23,8 @@ const ThreeColorRegEx = /^#?([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])$/; // These are based on the colors generated by 'Default Light+' and are only set when we // are ignoring themes. //tslint:disable:no-multiline-string object-literal-key-quotes -const DefaultCssVars: { [key: string] : string } = { - 'light' : ` +const DefaultCssVars: { [key: string]: string } = { + 'light': ` :root { --override-widget-background: #f3f3f3; --override-foreground: #000000; @@ -38,7 +38,7 @@ const DefaultCssVars: { [key: string] : string } = { --override-peek-background: #f2f8fc; } `, - 'dark' : ` + 'dark': ` :root { --override-widget-background: #1e1e1e; --override-foreground: #d4d4d4; @@ -56,25 +56,25 @@ const DefaultCssVars: { [key: string] : string } = { // These colors below should match colors that come from either the Default Light+ theme or the Default Dark+ theme. // They are used when we can't find a theme json file. -const DefaultColors: { [key: string] : string } = { - 'light.comment' : '#008000', +const DefaultColors: { [key: string]: string } = { + 'light.comment': '#008000', 'light.constant.numeric': '#09885a', - 'light.string' : '#a31515', - 'light.keyword.control' : '#AF00DB', + 'light.string': '#a31515', + 'light.keyword.control': '#AF00DB', 'light.keyword.operator': '#000000', - 'light.variable' : '#001080', + 'light.variable': '#001080', 'light.entity.name.type': '#267f99', 'light.support.function': '#795E26', - 'light.punctuation' : '#000000', - 'dark.comment' : '#6A9955', - 'dark.constant.numeric' : '#b5cea8', - 'dark.string' : '#ce9178', - 'dark.keyword.control' : '#C586C0', - 'dark.keyword.operator' : '#d4d4d4', - 'dark.variable' : '#9CDCFE', - 'dark.entity.name.type' : '#4EC9B0', - 'dark.support.function' : '#DCDCAA', - 'dark.punctuation' : '#1e1e1e' + 'light.punctuation': '#000000', + 'dark.comment': '#6A9955', + 'dark.constant.numeric': '#b5cea8', + 'dark.string': '#ce9178', + 'dark.keyword.control': '#C586C0', + 'dark.keyword.operator': '#d4d4d4', + 'dark.variable': '#9CDCFE', + 'dark.entity.name.type': '#4EC9B0', + 'dark.support.function': '#DCDCAA', + 'dark.punctuation': '#1e1e1e' }; interface IApplyThemeArgs { @@ -105,11 +105,11 @@ export class CodeCssGenerator implements ICodeCssGenerator { return this.applyThemeData(isDark, theme, '', this.generateCss.bind(this)); } - public generateMonacoTheme(isDark: boolean, theme: string) : Promise { + public generateMonacoTheme(isDark: boolean, theme: string): Promise { return this.applyThemeData(isDark, theme, {}, this.generateMonacoThemeObject.bind(this)); } - private async applyThemeData(isDark: boolean, theme: string, defaultT: T, applier: (args: IApplyThemeArgs) => T) : Promise { + private async applyThemeData(isDark: boolean, theme: string, defaultT: T, applier: (args: IApplyThemeArgs) => T): Promise { let result = defaultT; try { // First compute our current theme. @@ -132,8 +132,8 @@ export class CodeCssGenerator implements ICodeCssGenerator { result = applier({ tokenColors, baseColors, fontFamily, fontSize, isDark: isDarkUpdated, defaultStyle: ignoreTheme ? LightTheme : undefined }); } else if (tokenColors === null && fontFamily && fontSize) { // No colors found. See if we can figure out what type of theme we have - const style = isDark ? DarkTheme : LightTheme ; - result = applier({ fontFamily, fontSize, isDark: isDarkUpdated, defaultStyle: style}); + const style = isDark ? DarkTheme : LightTheme; + result = applier({ fontFamily, fontSize, isDark: isDarkUpdated, defaultStyle: style }); } } } catch (err) { @@ -144,14 +144,14 @@ export class CodeCssGenerator implements ICodeCssGenerator { return result; } - private getScopes(entry: any) : JSONArray { + private getScopes(entry: any): JSONArray { if (entry && entry.scope) { return Array.isArray(entry.scope) ? entry.scope as JSONArray : entry.scope.toString().split(','); } return []; } - private matchTokenColor(tokenColors: JSONArray, scope: string) : number { + private matchTokenColor(tokenColors: JSONArray, scope: string): number { return tokenColors.findIndex((entry: any) => { const scopeArray = this.getScopes(entry); if (scopeArray.find(v => v !== null && v !== undefined && v.toString().trim() === scope)) { @@ -184,7 +184,7 @@ export class CodeCssGenerator implements ICodeCssGenerator { return { color: this.getDefaultColor(defaultStyle, scope), fontStyle: 'normal' }; } - private getDefaultColor(style: string | undefined, scope: string) : string { + private getDefaultColor(style: string | undefined, scope: string): string { return style ? DefaultColors[`${style}.${scope}`] : 'var(--override-foreground, var(--vscode-editor-foreground))'; } @@ -210,14 +210,14 @@ export class CodeCssGenerator implements ICodeCssGenerator { --code-font-size: ${args.fontSize}px; } - ${args.defaultStyle ? DefaultCssVars[args.defaultStyle] : undefined } + ${args.defaultStyle ? DefaultCssVars[args.defaultStyle] : undefined} `; } // Based on this data here: // https://github.com/Microsoft/vscode/blob/master/src/vs/editor/standalone/common/themes.ts#L13 // tslint:disable: max-func-body-length - private generateMonacoThemeObject(args: IApplyThemeArgs) : monacoEditor.editor.IStandaloneThemeData { + private generateMonacoThemeObject(args: IApplyThemeArgs): monacoEditor.editor.IStandaloneThemeData { const result: monacoEditor.editor.IStandaloneThemeData = { base: args.isDark ? 'vs-dark' : 'vs', inherit: false, @@ -295,7 +295,7 @@ export class CodeCssGenerator implements ICodeCssGenerator { }); } else { // Otherwise use our default values. - result.base = args.defaultStyle === DarkTheme ? 'vs-dark' : 'vs'; + result.base = args.defaultStyle === DarkTheme ? 'vs-dark' : 'vs'; result.inherit = true; if (args.defaultStyle) { @@ -325,8 +325,8 @@ export class CodeCssGenerator implements ICodeCssGenerator { return [...colors1, ...colors2]; } - private mergeBaseColors = (colors1: JSONObject, colors2: JSONObject) : JSONObject => { - return {...colors1, ...colors2}; + private mergeBaseColors = (colors1: JSONObject, colors2: JSONObject): JSONObject => { + return { ...colors1, ...colors2 }; } private readTokenColors = async (themeFile: string): Promise => { diff --git a/src/client/datascience/data-viewing/dataViewer.ts b/src/client/datascience/data-viewing/dataViewer.ts index 3dcee41e4856..f4c7f05a6bf9 100644 --- a/src/client/datascience/data-viewing/dataViewer.ts +++ b/src/client/datascience/data-viewing/dataViewer.ts @@ -25,7 +25,7 @@ import { DataViewerMessages, IDataViewerMapping, IGetRowsRequest } from './types @injectable() export class DataViewer extends WebViewHost implements IDataViewer, IDisposable { private disposed: boolean = false; - private variable : IJupyterVariable | undefined; + private variable: IJupyterVariable | undefined; private rowsTimer: StopWatch | undefined; private pendingRowsCount: number = 0; @@ -37,7 +37,7 @@ export class DataViewer extends WebViewHost implements IData @inject(IWorkspaceService) workspaceService: IWorkspaceService, @inject(IJupyterVariables) private variableManager: IJupyterVariables, @inject(IApplicationShell) private applicationShell: IApplicationShell - ) { + ) { super( configuration, provider, @@ -90,13 +90,13 @@ export class DataViewer extends WebViewHost implements IData super.onMessage(message, payload); } - private async prepVariable(variable: IJupyterVariable) : Promise { + private async prepVariable(variable: IJupyterVariable): Promise { this.rowsTimer = new StopWatch(); const output = await this.variableManager.getDataFrameInfo(variable); // Log telemetry about number of rows try { - sendTelemetryEvent(Telemetry.ShowDataViewer, 0, {rows: output.rowCount ? output.rowCount : 0, columns: output.columns ? output.columns.length : 0 }); + sendTelemetryEvent(Telemetry.ShowDataViewer, 0, { rows: output.rowCount ? output.rowCount : 0, columns: output.columns ? output.columns.length : 0 }); // Count number of rows to fetch so can send telemetry on how long it took. this.pendingRowsCount = output.rowCount ? output.rowCount : 0; diff --git a/src/datascience-ui/data-explorer/mainPanel.tsx b/src/datascience-ui/data-explorer/mainPanel.tsx index 76d80022a794..b1ac07d18c01 100644 --- a/src/datascience-ui/data-explorer/mainPanel.tsx +++ b/src/datascience-ui/data-explorer/mainPanel.tsx @@ -40,6 +40,7 @@ interface IMainPanelState { totalRowCount: number; filters: {}; indexColumn: string; + styleReady: boolean; } export class MainPanel extends React.Component implements IMessageHandler { @@ -65,7 +66,8 @@ export class MainPanel extends React.Component totalRowCount: data.rows.length, fetchedRowCount: 0, filters: {}, - indexColumn: data.primaryKeys[0] + indexColumn: data.primaryKeys[0], + styleReady: false }; // Fire off a timer to mimic dynamic loading @@ -79,7 +81,8 @@ export class MainPanel extends React.Component totalRowCount: 0, fetchedRowCount: 0, filters: {}, - indexColumn: 'index' + indexColumn: 'index', + styleReady: false }; } } @@ -110,10 +113,11 @@ export class MainPanel extends React.Component return (
{progressBar} - {this.state.totalRowCount > 0 && this.renderGrid()} + {this.state.totalRowCount > 0 && this.state.styleReady && this.renderGrid()}
); } @@ -140,6 +144,10 @@ export class MainPanel extends React.Component return false; } + private saveReadyState = () => { + this.setState({styleReady: true}); + } + private renderGrid() { const filterRowsText = getLocString('DataScience.filterRowsButton', 'Filter Rows'); const filterRowsTooltip = getLocString('DataScience.filterRowsTooltip', 'Click to filter.'); diff --git a/src/datascience-ui/data-explorer/reactSlickGrid.tsx b/src/datascience-ui/data-explorer/reactSlickGrid.tsx index 1b53cea57504..224842ca37be 100644 --- a/src/datascience-ui/data-explorer/reactSlickGrid.tsx +++ b/src/datascience-ui/data-explorer/reactSlickGrid.tsx @@ -34,7 +34,6 @@ import './reactSlickGrid.css'; const MinColumnWidth = 70; const MaxColumnWidth = 500; -const RowHeightAdjustment = 4; export interface ISlickRow extends Slick.SlickData { id: string; @@ -147,13 +146,13 @@ export class ReactSlickGrid extends React.Component = { + const options: Slick.GridOptions = { asyncEditorLoading: true, editable: false, enableCellNavigation: true, @@ -161,7 +160,7 @@ export class ReactSlickGrid extends React.Component { @@ -366,7 +378,7 @@ export class ReactSlickGrid extends React.Component Date: Tue, 6 Aug 2019 14:31:40 -0700 Subject: [PATCH 2/2] refactored constructor in the data viewer mainPanel.tsx --- src/datascience-ui/data-explorer/mainPanel.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/datascience-ui/data-explorer/mainPanel.tsx b/src/datascience-ui/data-explorer/mainPanel.tsx index b1ac07d18c01..bb1acc02a42f 100644 --- a/src/datascience-ui/data-explorer/mainPanel.tsx +++ b/src/datascience-ui/data-explorer/mainPanel.tsx @@ -71,9 +71,7 @@ export class MainPanel extends React.Component }; // Fire off a timer to mimic dynamic loading - setTimeout(() => { - this.handleGetAllRowsResponse({data: data.rows}); - }, 1000); + setTimeout(() => this.handleGetAllRowsResponse({data: data.rows}), 1000); } else { this.state = { gridColumns: [],