Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: IrisGridTheme iconSize (#2123)
Browse files Browse the repository at this point in the history
This is part of the work needed for #885 that I felt would be better as
a separate PR.

Snapshot changes are going to be slightly shifted sort icon and vertical
center + slight left shift on tree table arrows.
mattrunyon authored and mofojed committed Jan 6, 2025
1 parent 86439b3 commit 6d86403
Showing 57 changed files with 61 additions and 54 deletions.
28 changes: 15 additions & 13 deletions packages/grid/src/GridRenderer.ts
Original file line number Diff line number Diff line change
@@ -1082,11 +1082,12 @@ export class GridRenderer {
context.beginPath();
for (let i = 0; i < depth - depthDiff; i += 1) {
const lineX =
columnX +
i * treeDepthIndent +
treeDepthIndent * 0.5 +
treeHorizontalPadding +
0.5;
Math.floor(
columnX +
i * treeDepthIndent +
treeDepthIndent * 0.5 +
treeHorizontalPadding
) + 0.5; // The 0.5 makes the line crisp https://stackoverflow.com/questions/9311428/draw-single-pixel-line-in-html5-canvas
context.moveTo(lineX, rowY);
context.lineTo(lineX, rowY + rowHeight);
}
@@ -1098,18 +1099,19 @@ export class GridRenderer {
context.beginPath();
for (let i = depth - depthDiff; i < depth; i += 1) {
const lineX =
columnX +
i * treeDepthIndent +
treeDepthIndent * 0.5 +
treeHorizontalPadding +
0.5;
Math.floor(
columnX +
i * treeDepthIndent +
treeDepthIndent * 0.5 +
treeHorizontalPadding
) + 0.5;
context.moveTo(lineX, rowY);
context.lineTo(lineX, rowY + Math.ceil(rowHeight / 2));
context.lineTo(lineX, rowY + Math.floor(rowHeight / 2));
// extra moveTo prevents halfpixel in corner
context.moveTo(lineX - 0.5, rowY + Math.ceil(rowHeight / 2) + 0.5);
context.moveTo(lineX - 0.5, rowY + Math.floor(rowHeight / 2) + 0.5);
context.lineTo(
lineX + treeDepthIndent - 0.5,
rowY + Math.ceil(rowHeight / 2) + 0.5
rowY + Math.floor(rowHeight / 2) + 0.5
);
}
context.stroke();
2 changes: 1 addition & 1 deletion packages/iris-grid/src/IrisGrid.tsx
Original file line number Diff line number Diff line change
@@ -1498,7 +1498,7 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {
return rowIndex != null ? modelRows.get(rowIndex) : null;
}

getTheme(): Partial<IrisGridThemeType> {
getTheme(): IrisGridThemeType {
const { model, theme } = this.props;

return this.getCachedTheme(
13 changes: 8 additions & 5 deletions packages/iris-grid/src/IrisGridCellRendererUtils.ts
Original file line number Diff line number Diff line change
@@ -13,12 +13,15 @@ class IrisGridCellRendererUtils {
isExpanded: boolean
): void {
context.save();
const { x1, y1 } = treeBox;
const { theme } = state;
const { iconSize } = theme;
const { x1, x2, y1, y2 } = treeBox;
const markerIcon = isExpanded
? getIcon('caretDown')
: getIcon('caretRight');
const iconX = columnX + x1 - 2;
const iconY = rowY + y1 + 2.5;
? getIcon('caretDown', iconSize)
: getIcon('caretRight', iconSize);

const iconX = columnX + (x1 + x2) / 2 - iconSize / 2; // Midpoint of the tree box minus half the icon width
const iconY = rowY + (y2 - y1 - iconSize) / 2; // y2 - y1 is effectively rowHeight

context.fillStyle = color;
context.textAlign = 'center';
19 changes: 8 additions & 11 deletions packages/iris-grid/src/IrisGridIcons.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { memoizeClear } from '@deephaven/grid';
import {
dhSortDown,
dhSortUp,
vsTriangleDown,
vsTriangleRight,
vsTriangleUp,
vsLinkExternal,
IconDefinition,
} from '@deephaven/icons';

export const ICON_SIZE = 16;

export type IconName =
| 'sortUp'
| 'sortDown'
@@ -18,15 +15,15 @@ export type IconName =
| 'cellOverflow';

const iconMap = new Map<IconName, IconDefinition>([
['sortUp', dhSortUp],
['sortDown', dhSortDown],
['sortUp', vsTriangleUp],
['sortDown', vsTriangleDown],
['caretDown', vsTriangleDown],
['caretRight', vsTriangleRight],
['cellOverflow', vsLinkExternal],
]);

const makeIcon = memoizeClear(
(name: IconName) => {
(name: IconName, size: number) => {
const faIcon = iconMap.get(name);
if (faIcon === undefined) {
throw new Error('Icon is undefined');
@@ -38,15 +35,15 @@ const makeIcon = memoizeClear(
const icon = new Path2D(path);
const scaledIcon = new Path2D();
const scaleMatrix = {
a: ICON_SIZE / faIcon.icon[0],
d: ICON_SIZE / faIcon.icon[1],
a: size / faIcon.icon[0],
d: size / faIcon.icon[1],
};
scaledIcon.addPath(icon, scaleMatrix);
return scaledIcon;
},
{ max: 1000 }
);

export function getIcon(name: IconName): Path2D {
return makeIcon(name);
export function getIcon(name: IconName, size: number): Path2D {
return makeIcon(name, size);
}
37 changes: 20 additions & 17 deletions packages/iris-grid/src/IrisGridRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/* eslint react/destructuring-assignment: "off" */
/* eslint class-methods-use-this: "off" */
/* eslint no-param-reassign: "off" */
import {
BoundedAxisRange,
Coordinate,
@@ -69,15 +67,15 @@ export class IrisGridRenderer extends GridRenderer {

protected dataBarCellRenderer = new IrisGridDataBarCellRenderer();

getSortIcon(sort: dh.Sort | null): Path2D | null {
getSortIcon(sort: dh.Sort | null, size: number): Path2D | null {
if (!sort) {
return null;
}
if (sort.direction === TableUtils.sortDirection.ascending) {
return getIcon(ICON_NAMES.SORT_UP);
return getIcon(ICON_NAMES.SORT_UP, size);
}
if (sort.direction === TableUtils.sortDirection.descending) {
return getIcon(ICON_NAMES.SORT_DOWN);
return getIcon(ICON_NAMES.SORT_DOWN, size);
}
return null;
}
@@ -135,7 +133,7 @@ export class IrisGridRenderer extends GridRenderer {
mouseX: Coordinate | null;
mouseY: Coordinate | null;
metrics: GridMetrics | undefined;
theme: GridThemeType;
theme: IrisGridThemeType;
}): {
left: Coordinate | null;
top: Coordinate | null;
@@ -173,6 +171,7 @@ export class IrisGridRenderer extends GridRenderer {
cellHorizontalPadding,
overflowButtonColor,
overflowButtonHoverColor,
iconSize,
} = theme;

context.save();
@@ -191,9 +190,12 @@ export class IrisGridRenderer extends GridRenderer {
} else if (overflowButtonColor != null) {
context.fillStyle = overflowButtonColor;
}
const icon = getIcon(ICON_NAMES.CELL_OVERFLOW);
if (buttonLeft != null && buttonTop != null) {
context.translate(buttonLeft + cellHorizontalPadding, buttonTop + 2);
const icon = getIcon(ICON_NAMES.CELL_OVERFLOW, iconSize);
if (buttonLeft != null && buttonTop != null && buttonHeight != null) {
context.translate(
buttonLeft + cellHorizontalPadding,
buttonTop + (buttonHeight - iconSize) / 2
);
}
context.fill(icon);

@@ -470,7 +472,8 @@ export class IrisGridRenderer extends GridRenderer {
fontWidths,
} = metrics;

const { headerHorizontalPadding } = theme;
const { headerHorizontalPadding, iconSize: themeIconSize } = theme;
const iconSize = Math.round(themeIconSize * 0.75); // The vsTriangle icons are a bit bigger than we want
const columnWidth = getOrThrow(allColumnWidths, index, 0);
const columnX = getOrThrow(allColumnXs, index) + gridX;
const modelColumn = modelColumns.get(index);
@@ -491,7 +494,7 @@ export class IrisGridRenderer extends GridRenderer {
return;
}

const icon = this.getSortIcon(sort);
const icon = this.getSortIcon(sort, iconSize);
if (!icon) {
return;
}
@@ -506,14 +509,14 @@ export class IrisGridRenderer extends GridRenderer {
const textWidth = text.length * fontWidth;
const textRight = gridX + columnX + textWidth + headerHorizontalPadding;
let { maxX } = bounds;
maxX -= headerHorizontalPadding;
const defaultX =
gridX + columnX + columnWidth - headerHorizontalPadding - 1;
maxX -= headerHorizontalPadding; // Right visible edge of the headers
// Right edge of the column. The icon has its own horizontal padding
const defaultX = gridX + columnX + columnWidth - iconSize;

// If the text is partially off the screen, put the icon to the right of the text
// else put it at the right edge of the column/grid (whichever is smaller)
const x = textRight > maxX ? textRight + 1 : Math.min(maxX, defaultX);
const yOffset =
sort.direction === TableUtils.sortDirection.ascending ? -6 : -12;
const y = columnHeaderHeight * 0.5 + yOffset;
const y = (columnHeaderHeight - iconSize) * 0.5;

context.save();

9 changes: 4 additions & 5 deletions packages/iris-grid/src/IrisGridTextCellRenderer.ts
Original file line number Diff line number Diff line change
@@ -5,15 +5,14 @@ import {
DEFAULT_FONT_WIDTH,
getOrThrow,
GridMetrics,
GridThemeType,
GridUtils,
TextCellRenderer,
VisibleIndex,
} from '@deephaven/grid';
import { TableUtils } from '@deephaven/jsapi-utils';
import { IrisGridRenderState } from './IrisGridRenderer';
import { ICON_SIZE } from './IrisGridIcons';
import IrisGridCellRendererUtils from './IrisGridCellRendererUtils';
import type { IrisGridThemeType } from './IrisGridTheme';

class IrisGridTextCellRenderer extends TextCellRenderer {
drawCellContent(
@@ -85,7 +84,7 @@ class IrisGridTextCellRenderer extends TextCellRenderer {
mouseX: Coordinate | null,
mouseY: Coordinate | null,
metrics: GridMetrics | undefined,
theme: GridThemeType
theme: IrisGridThemeType
): {
left: Coordinate | null;
top: Coordinate | null;
@@ -107,9 +106,9 @@ class IrisGridTextCellRenderer extends TextCellRenderer {
}

const { width: gridWidth, verticalBarWidth } = metrics;
const { cellHorizontalPadding } = theme;
const { cellHorizontalPadding, iconSize } = theme;

const width = ICON_SIZE + 2 * cellHorizontalPadding;
const width = iconSize + 2 * cellHorizontalPadding;
const height = rowHeight;
// Right edge of column or of visible grid, whichever is smaller
const right = Math.min(
4 changes: 3 additions & 1 deletion packages/iris-grid/src/IrisGridTheme.ts
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@ export type IrisGridThemeType = GridThemeType & {
overflowButtonColor: GridColor;
overflowButtonHoverColor: GridColor;
floatingGridRowColor: NullableGridColor;
iconSize: number;
};

/**
@@ -149,6 +150,7 @@ export function createDefaultIrisGridTheme(): IrisGridThemeType {
sortHeaderBarHeight: 2,
reverseHeaderBarHeight: 4,
filterBarHorizontalPadding: 4,
iconSize: 16,

activeCellSelectionBorderWidth:
parseInt(IrisGridTheme['active-cell-selection-border-width'], 10) || 2,
@@ -182,5 +184,5 @@ export function createDefaultIrisGridTheme(): IrisGridThemeType {
positiveBarColor: IrisGridTheme['positive-bar-color'],
negativeBarColor: IrisGridTheme['negative-bar-color'],
markerBarColor: IrisGridTheme['marker-bar-color'],
});
} satisfies IrisGridThemeType);
}
Original file line number Diff line number Diff line change
@@ -57,6 +57,7 @@ exports[`createDefaultIrisGridTheme should derive the default Iris grid theme 1`
"headerSeparatorHoverColor": "IrisGridTheme['header-separator-hover-color']",
"headerSortBarColor": "IrisGridTheme['header-sort-bar-color']",
"hyperlinkColor": "IrisGridTheme['hyperlink-color']",
"iconSize": 16,
"linkerColumnHoverBackgroundColor": "IrisGridTheme['linker-column-hover-bg']",
"markerBarColor": "IrisGridTheme['marker-bar-color']",
"maxColumnWidth": 600,
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ class IrisGridCellOverflowMouseHandler extends GridMouseHandler {
const { model } = props;

const { canvasContext: context } = grid;
const theme = grid.getTheme();
const theme = this.irisGrid.getTheme();
const rendererState = {
context,
mouseX: x,
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/context-menu.spec.ts-snapshots/sort-by-1-chromium-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/context-menu.spec.ts-snapshots/sort-by-1-firefox-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/context-menu.spec.ts-snapshots/sort-by-1-webkit-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/context-menu.spec.ts-snapshots/sort-by-2-chromium-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/context-menu.spec.ts-snapshots/sort-by-2-webkit-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/styleguide.spec.ts-snapshots/grids-iris-chromium-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/styleguide.spec.ts-snapshots/grids-iris-firefox-linux.png
Binary file modified tests/styleguide.spec.ts-snapshots/grids-iris-webkit-linux.png

0 comments on commit 6d86403

Please sign in to comment.