Skip to content

Commit 58ee88d

Browse files
authored
feat: IrisGridTheme iconSize (#2123)
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.
1 parent 50f2a6d commit 58ee88d

57 files changed

Lines changed: 61 additions & 54 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

packages/grid/src/GridRenderer.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,11 +1082,12 @@ export class GridRenderer {
10821082
context.beginPath();
10831083
for (let i = 0; i < depth - depthDiff; i += 1) {
10841084
const lineX =
1085-
columnX +
1086-
i * treeDepthIndent +
1087-
treeDepthIndent * 0.5 +
1088-
treeHorizontalPadding +
1089-
0.5;
1085+
Math.floor(
1086+
columnX +
1087+
i * treeDepthIndent +
1088+
treeDepthIndent * 0.5 +
1089+
treeHorizontalPadding
1090+
) + 0.5; // The 0.5 makes the line crisp https://stackoverflow.com/questions/9311428/draw-single-pixel-line-in-html5-canvas
10901091
context.moveTo(lineX, rowY);
10911092
context.lineTo(lineX, rowY + rowHeight);
10921093
}
@@ -1098,18 +1099,19 @@ export class GridRenderer {
10981099
context.beginPath();
10991100
for (let i = depth - depthDiff; i < depth; i += 1) {
11001101
const lineX =
1101-
columnX +
1102-
i * treeDepthIndent +
1103-
treeDepthIndent * 0.5 +
1104-
treeHorizontalPadding +
1105-
0.5;
1102+
Math.floor(
1103+
columnX +
1104+
i * treeDepthIndent +
1105+
treeDepthIndent * 0.5 +
1106+
treeHorizontalPadding
1107+
) + 0.5;
11061108
context.moveTo(lineX, rowY);
1107-
context.lineTo(lineX, rowY + Math.ceil(rowHeight / 2));
1109+
context.lineTo(lineX, rowY + Math.floor(rowHeight / 2));
11081110
// extra moveTo prevents halfpixel in corner
1109-
context.moveTo(lineX - 0.5, rowY + Math.ceil(rowHeight / 2) + 0.5);
1111+
context.moveTo(lineX - 0.5, rowY + Math.floor(rowHeight / 2) + 0.5);
11101112
context.lineTo(
11111113
lineX + treeDepthIndent - 0.5,
1112-
rowY + Math.ceil(rowHeight / 2) + 0.5
1114+
rowY + Math.floor(rowHeight / 2) + 0.5
11131115
);
11141116
}
11151117
context.stroke();

packages/iris-grid/src/IrisGrid.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1498,7 +1498,7 @@ class IrisGrid extends Component<IrisGridProps, IrisGridState> {
14981498
return rowIndex != null ? modelRows.get(rowIndex) : null;
14991499
}
15001500

1501-
getTheme(): Partial<IrisGridThemeType> {
1501+
getTheme(): IrisGridThemeType {
15021502
const { model, theme } = this.props;
15031503

15041504
return this.getCachedTheme(

packages/iris-grid/src/IrisGridCellRendererUtils.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ class IrisGridCellRendererUtils {
1313
isExpanded: boolean
1414
): void {
1515
context.save();
16-
const { x1, y1 } = treeBox;
16+
const { theme } = state;
17+
const { iconSize } = theme;
18+
const { x1, x2, y1, y2 } = treeBox;
1719
const markerIcon = isExpanded
18-
? getIcon('caretDown')
19-
: getIcon('caretRight');
20-
const iconX = columnX + x1 - 2;
21-
const iconY = rowY + y1 + 2.5;
20+
? getIcon('caretDown', iconSize)
21+
: getIcon('caretRight', iconSize);
22+
23+
const iconX = columnX + (x1 + x2) / 2 - iconSize / 2; // Midpoint of the tree box minus half the icon width
24+
const iconY = rowY + (y2 - y1 - iconSize) / 2; // y2 - y1 is effectively rowHeight
2225

2326
context.fillStyle = color;
2427
context.textAlign = 'center';
Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { memoizeClear } from '@deephaven/grid';
22
import {
3-
dhSortDown,
4-
dhSortUp,
53
vsTriangleDown,
64
vsTriangleRight,
5+
vsTriangleUp,
76
vsLinkExternal,
87
IconDefinition,
98
} from '@deephaven/icons';
109

11-
export const ICON_SIZE = 16;
12-
1310
export type IconName =
1411
| 'sortUp'
1512
| 'sortDown'
@@ -18,15 +15,15 @@ export type IconName =
1815
| 'cellOverflow';
1916

2017
const iconMap = new Map<IconName, IconDefinition>([
21-
['sortUp', dhSortUp],
22-
['sortDown', dhSortDown],
18+
['sortUp', vsTriangleUp],
19+
['sortDown', vsTriangleDown],
2320
['caretDown', vsTriangleDown],
2421
['caretRight', vsTriangleRight],
2522
['cellOverflow', vsLinkExternal],
2623
]);
2724

2825
const makeIcon = memoizeClear(
29-
(name: IconName) => {
26+
(name: IconName, size: number) => {
3027
const faIcon = iconMap.get(name);
3128
if (faIcon === undefined) {
3229
throw new Error('Icon is undefined');
@@ -38,15 +35,15 @@ const makeIcon = memoizeClear(
3835
const icon = new Path2D(path);
3936
const scaledIcon = new Path2D();
4037
const scaleMatrix = {
41-
a: ICON_SIZE / faIcon.icon[0],
42-
d: ICON_SIZE / faIcon.icon[1],
38+
a: size / faIcon.icon[0],
39+
d: size / faIcon.icon[1],
4340
};
4441
scaledIcon.addPath(icon, scaleMatrix);
4542
return scaledIcon;
4643
},
4744
{ max: 1000 }
4845
);
4946

50-
export function getIcon(name: IconName): Path2D {
51-
return makeIcon(name);
47+
export function getIcon(name: IconName, size: number): Path2D {
48+
return makeIcon(name, size);
5249
}

packages/iris-grid/src/IrisGridRenderer.ts

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
/* eslint react/destructuring-assignment: "off" */
21
/* eslint class-methods-use-this: "off" */
3-
/* eslint no-param-reassign: "off" */
42
import {
53
BoundedAxisRange,
64
Coordinate,
@@ -69,15 +67,15 @@ export class IrisGridRenderer extends GridRenderer {
6967

7068
protected dataBarCellRenderer = new IrisGridDataBarCellRenderer();
7169

72-
getSortIcon(sort: dh.Sort | null): Path2D | null {
70+
getSortIcon(sort: dh.Sort | null, size: number): Path2D | null {
7371
if (!sort) {
7472
return null;
7573
}
7674
if (sort.direction === TableUtils.sortDirection.ascending) {
77-
return getIcon(ICON_NAMES.SORT_UP);
75+
return getIcon(ICON_NAMES.SORT_UP, size);
7876
}
7977
if (sort.direction === TableUtils.sortDirection.descending) {
80-
return getIcon(ICON_NAMES.SORT_DOWN);
78+
return getIcon(ICON_NAMES.SORT_DOWN, size);
8179
}
8280
return null;
8381
}
@@ -135,7 +133,7 @@ export class IrisGridRenderer extends GridRenderer {
135133
mouseX: Coordinate | null;
136134
mouseY: Coordinate | null;
137135
metrics: GridMetrics | undefined;
138-
theme: GridThemeType;
136+
theme: IrisGridThemeType;
139137
}): {
140138
left: Coordinate | null;
141139
top: Coordinate | null;
@@ -173,6 +171,7 @@ export class IrisGridRenderer extends GridRenderer {
173171
cellHorizontalPadding,
174172
overflowButtonColor,
175173
overflowButtonHoverColor,
174+
iconSize,
176175
} = theme;
177176

178177
context.save();
@@ -191,9 +190,12 @@ export class IrisGridRenderer extends GridRenderer {
191190
} else if (overflowButtonColor != null) {
192191
context.fillStyle = overflowButtonColor;
193192
}
194-
const icon = getIcon(ICON_NAMES.CELL_OVERFLOW);
195-
if (buttonLeft != null && buttonTop != null) {
196-
context.translate(buttonLeft + cellHorizontalPadding, buttonTop + 2);
193+
const icon = getIcon(ICON_NAMES.CELL_OVERFLOW, iconSize);
194+
if (buttonLeft != null && buttonTop != null && buttonHeight != null) {
195+
context.translate(
196+
buttonLeft + cellHorizontalPadding,
197+
buttonTop + (buttonHeight - iconSize) / 2
198+
);
197199
}
198200
context.fill(icon);
199201

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

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

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

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

518521
context.save();
519522

packages/iris-grid/src/IrisGridTextCellRenderer.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ import {
55
DEFAULT_FONT_WIDTH,
66
getOrThrow,
77
GridMetrics,
8-
GridThemeType,
98
GridUtils,
109
TextCellRenderer,
1110
VisibleIndex,
1211
} from '@deephaven/grid';
1312
import { TableUtils } from '@deephaven/jsapi-utils';
1413
import { IrisGridRenderState } from './IrisGridRenderer';
15-
import { ICON_SIZE } from './IrisGridIcons';
1614
import IrisGridCellRendererUtils from './IrisGridCellRendererUtils';
15+
import type { IrisGridThemeType } from './IrisGridTheme';
1716

1817
class IrisGridTextCellRenderer extends TextCellRenderer {
1918
drawCellContent(
@@ -85,7 +84,7 @@ class IrisGridTextCellRenderer extends TextCellRenderer {
8584
mouseX: Coordinate | null,
8685
mouseY: Coordinate | null,
8786
metrics: GridMetrics | undefined,
88-
theme: GridThemeType
87+
theme: IrisGridThemeType
8988
): {
9089
left: Coordinate | null;
9190
top: Coordinate | null;
@@ -107,9 +106,9 @@ class IrisGridTextCellRenderer extends TextCellRenderer {
107106
}
108107

109108
const { width: gridWidth, verticalBarWidth } = metrics;
110-
const { cellHorizontalPadding } = theme;
109+
const { cellHorizontalPadding, iconSize } = theme;
111110

112-
const width = ICON_SIZE + 2 * cellHorizontalPadding;
111+
const width = iconSize + 2 * cellHorizontalPadding;
113112
const height = rowHeight;
114113
// Right edge of column or of visible grid, whichever is smaller
115114
const right = Math.min(

packages/iris-grid/src/IrisGridTheme.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export type IrisGridThemeType = GridThemeType & {
4646
overflowButtonColor: GridColor;
4747
overflowButtonHoverColor: GridColor;
4848
floatingGridRowColor: NullableGridColor;
49+
iconSize: number;
4950
};
5051

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

153155
activeCellSelectionBorderWidth:
154156
parseInt(IrisGridTheme['active-cell-selection-border-width'], 10) || 2,
@@ -182,5 +184,5 @@ export function createDefaultIrisGridTheme(): IrisGridThemeType {
182184
positiveBarColor: IrisGridTheme['positive-bar-color'],
183185
negativeBarColor: IrisGridTheme['negative-bar-color'],
184186
markerBarColor: IrisGridTheme['marker-bar-color'],
185-
});
187+
} satisfies IrisGridThemeType);
186188
}

packages/iris-grid/src/__snapshots__/IrisGridTheme.test.ts.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ exports[`createDefaultIrisGridTheme should derive the default Iris grid theme 1`
5757
"headerSeparatorHoverColor": "IrisGridTheme['header-separator-hover-color']",
5858
"headerSortBarColor": "IrisGridTheme['header-sort-bar-color']",
5959
"hyperlinkColor": "IrisGridTheme['hyperlink-color']",
60+
"iconSize": 16,
6061
"linkerColumnHoverBackgroundColor": "IrisGridTheme['linker-column-hover-bg']",
6162
"markerBarColor": "IrisGridTheme['marker-bar-color']",
6263
"maxColumnWidth": 600,

packages/iris-grid/src/mousehandlers/IrisGridCellOverflowMouseHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class IrisGridCellOverflowMouseHandler extends GridMouseHandler {
5151
const { model } = props;
5252

5353
const { canvasContext: context } = grid;
54-
const theme = grid.getTheme();
54+
const theme = this.irisGrid.getTheme();
5555
const rendererState = {
5656
context,
5757
mouseX: x,
27 Bytes

0 commit comments

Comments
 (0)