Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/2 Fixes/6614.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make data viewer change row height according to font size in settings.
8 changes: 4 additions & 4 deletions src/client/common/application/webPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
}

Expand Down Expand Up @@ -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 : '';
Expand Down
60 changes: 30 additions & 30 deletions src/client/datascience/codeCssGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -38,7 +38,7 @@ const DefaultCssVars: { [key: string] : string } = {
--override-peek-background: #f2f8fc;
}
`,
'dark' : `
'dark': `
:root {
--override-widget-background: #1e1e1e;
--override-foreground: #d4d4d4;
Expand All @@ -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 {
Expand Down Expand Up @@ -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<JSONObject> {
public generateMonacoTheme(isDark: boolean, theme: string): Promise<JSONObject> {
return this.applyThemeData(isDark, theme, {}, this.generateMonacoThemeObject.bind(this));
}

private async applyThemeData<T>(isDark: boolean, theme: string, defaultT: T, applier: (args: IApplyThemeArgs) => T) : Promise<T> {
private async applyThemeData<T>(isDark: boolean, theme: string, defaultT: T, applier: (args: IApplyThemeArgs) => T): Promise<T> {
let result = defaultT;
try {
// First compute our current theme.
Expand All @@ -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) {
Expand All @@ -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)) {
Expand Down Expand Up @@ -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))';
}

Expand All @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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<JSONArray> => {
Expand Down
8 changes: 4 additions & 4 deletions src/client/datascience/data-viewing/dataViewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { DataViewerMessages, IDataViewerMapping, IGetRowsRequest } from './types
@injectable()
export class DataViewer extends WebViewHost<IDataViewerMapping> implements IDataViewer, IDisposable {
private disposed: boolean = false;
private variable : IJupyterVariable | undefined;
private variable: IJupyterVariable | undefined;
private rowsTimer: StopWatch | undefined;
private pendingRowsCount: number = 0;

Expand All @@ -37,7 +37,7 @@ export class DataViewer extends WebViewHost<IDataViewerMapping> implements IData
@inject(IWorkspaceService) workspaceService: IWorkspaceService,
@inject(IJupyterVariables) private variableManager: IJupyterVariables,
@inject(IApplicationShell) private applicationShell: IApplicationShell
) {
) {
super(
configuration,
provider,
Expand Down Expand Up @@ -90,13 +90,13 @@ export class DataViewer extends WebViewHost<IDataViewerMapping> implements IData
super.onMessage(message, payload);
}

private async prepVariable(variable: IJupyterVariable) : Promise<IJupyterVariable> {
private async prepVariable(variable: IJupyterVariable): Promise<IJupyterVariable> {
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;
Expand Down
18 changes: 12 additions & 6 deletions src/datascience-ui/data-explorer/mainPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ interface IMainPanelState {
totalRowCount: number;
filters: {};
indexColumn: string;
styleReady: boolean;
}

export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> implements IMessageHandler {
Expand All @@ -65,21 +66,21 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState>
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
setTimeout(() => {
this.handleGetAllRowsResponse({data: data.rows});
}, 1000);
setTimeout(() => this.handleGetAllRowsResponse({data: data.rows}), 1000);
} else {
this.state = {
gridColumns: [],
gridRows: [],
totalRowCount: 0,
fetchedRowCount: 0,
filters: {},
indexColumn: 'index'
indexColumn: 'index',
styleReady: false
};
}
}
Expand Down Expand Up @@ -110,10 +111,11 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState>
return (
<div className='main-panel' ref={this.container}>
<StyleInjector
onReady={this.saveReadyState}
expectingDark={this.props.baseTheme !== 'vscode-light'}
postOffice={this.postOffice} />
{progressBar}
{this.state.totalRowCount > 0 && this.renderGrid()}
{this.state.totalRowCount > 0 && this.state.styleReady && this.renderGrid()}
</div>
);
}
Expand All @@ -140,6 +142,10 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState>
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.');
Expand Down
22 changes: 17 additions & 5 deletions src/datascience-ui/data-explorer/reactSlickGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import './reactSlickGrid.css';

const MinColumnWidth = 70;
const MaxColumnWidth = 500;
const RowHeightAdjustment = 4;

export interface ISlickRow extends Slick.SlickData {
id: string;
Expand Down Expand Up @@ -147,21 +146,21 @@ export class ReactSlickGrid extends React.Component<ISlickGridProps, ISlickGridS

if (this.containerRef.current) {
// Compute font size. Default to 15 if not found.
let fontSize = parseInt(getComputedStyle(this.containerRef.current).getPropertyValue('--vscode-font-size'), 10);
let fontSize = parseInt(getComputedStyle(this.containerRef.current).getPropertyValue('--code-font-size'), 10);
if (isNaN(fontSize)) {
fontSize = 15;
}

// Setup options for the grid
const options : Slick.GridOptions<Slick.SlickData> = {
const options: Slick.GridOptions<Slick.SlickData> = {
asyncEditorLoading: true,
editable: false,
enableCellNavigation: true,
showHeaderRow: true,
enableColumnReorder: false,
explicitInitialization: false,
viewportClass: 'react-grid',
rowHeight: fontSize + RowHeightAdjustment
rowHeight: this.getAppropiateRowHeight(fontSize)
};

// Transform columns so they are sortable and stylable
Expand Down Expand Up @@ -296,6 +295,19 @@ export class ReactSlickGrid extends React.Component<ISlickGridProps, ISlickGridS
args.grid.render();
}

private getAppropiateRowHeight(fontSize: number): number {
switch (true) {
case (fontSize < 15):
return fontSize + 4;
case (fontSize < 20):
return fontSize + 8;
case (fontSize < 30):
return fontSize + 10;
default:
return fontSize + 12;
}
}

// If the slickgrid gets focus and nothing is selected select the first item
// so that you can keyboard navigate from there
private slickgridFocus = (_e: any): void => {
Expand Down Expand Up @@ -366,7 +378,7 @@ export class ReactSlickGrid extends React.Component<ISlickGridProps, ISlickGridS
const document = this.containerRef.current.ownerDocument;
if (document) {
const cssOverrideNode = document.createElement('style');
const rule = `.${gridName} .slick-cell {height: ${this.state.fontSize + RowHeightAdjustment}px;}`;
const rule = `.${gridName} .slick-cell {height: ${this.getAppropiateRowHeight(this.state.fontSize)}px;}`;
cssOverrideNode.setAttribute('type', 'text/css');
cssOverrideNode.setAttribute('rel', 'stylesheet');
cssOverrideNode.appendChild(document.createTextNode(rule));
Expand Down
5 changes: 5 additions & 0 deletions src/datascience-ui/react-common/styleInjector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface IStyleInjectorProps {
postOffice: PostOffice;
darkChanged?(newDark: boolean): void;
monacoThemeChanged?(theme: string): void;
onReady?(): void;
}

interface IStyleInjectorState {
Expand Down Expand Up @@ -105,6 +106,10 @@ export class StyleInjector extends React.Component<IStyleInjectorProps, IStyleIn
theme: response.theme,
knownDark: computedKnownDark
});

if (this.props.onReady) {
this.props.onReady();
}
}
}

Expand Down