From 74592676444cdb9bdc2fef5dc8c483667b557a5e Mon Sep 17 00:00:00 2001 From: Josh Kingsley Date: Sun, 26 Oct 2025 22:13:31 +0200 Subject: feat(web): draw cell values --- web/src/components/grid/drawGrid.ts | 89 ++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 32 deletions(-) (limited to 'web/src/components/grid/drawGrid.ts') diff --git a/web/src/components/grid/drawGrid.ts b/web/src/components/grid/drawGrid.ts index 1b94254..498abd5 100644 --- a/web/src/components/grid/drawGrid.ts +++ b/web/src/components/grid/drawGrid.ts @@ -2,26 +2,30 @@ import { RangeSelection, Selection } from "../../selection"; import { CellRef } from "../../types"; import { getRenderedCell, RenderedCell, RenderedGrid } from "./renderGrid"; -interface GridColors { +interface GridStyles { bgFill: string; borderStroke: string; cellStroke: string; selelectionRangeFill: string; selectionRangeStroke: string; activeCellStroke: string; + cellValueFont: string; + cellValueLineHeight: string; } -export function getGridColors(el: HTMLElement): GridColors { +export function getGridStyles(el: HTMLElement): GridStyles { const style = window.getComputedStyle(el); - const color = (k: string) => style.getPropertyValue(k); + const prop = (k: string) => style.getPropertyValue(k); return { - bgFill: color("--grid-bg-fill"), - borderStroke: color("--grid-border-stroke"), - cellStroke: color("--grid-cell-stroke"), - selelectionRangeFill: color("--grid-selection-range-fill"), - selectionRangeStroke: color("--grid-selection-range-stroke"), - activeCellStroke: color("--grid-active-cell-stroke"), + bgFill: prop("--grid-bg-fill"), + borderStroke: prop("--grid-border-stroke"), + cellStroke: prop("--grid-cell-stroke"), + selelectionRangeFill: prop("--grid-selection-range-fill"), + selectionRangeStroke: prop("--grid-selection-range-stroke"), + activeCellStroke: prop("--grid-active-cell-stroke"), + cellValueFont: prop("font"), + cellValueLineHeight: prop("line-height"), }; } @@ -33,29 +37,29 @@ function excursion(ctx: CanvasRenderingContext2D, f: () => void) { function fillBackground( ctx: CanvasRenderingContext2D, - colors: GridColors, + styles: GridStyles, grid: RenderedGrid, ) { ctx.clearRect(0, 0, grid.rect.width, grid.rect.height); - ctx.fillStyle = colors.bgFill; + ctx.fillStyle = styles.bgFill; ctx.fillRect(0, 0, grid.rect.width, grid.rect.height); } function strokeGrid( ctx: CanvasRenderingContext2D, - colors: GridColors, + styles: GridStyles, grid: RenderedGrid, ) { - ctx.strokeStyle = colors.borderStroke; + ctx.strokeStyle = styles.borderStroke; ctx.strokeRect(0.5, 0.5, grid.rect.width - 1, grid.rect.height - 1); } function strokeGridLines( ctx: CanvasRenderingContext2D, - colors: GridColors, + styles: GridStyles, grid: RenderedGrid, ) { - ctx.strokeStyle = colors.cellStroke; + ctx.strokeStyle = styles.cellStroke; grid.renderedRows.forEach((row, renderedRowIndex) => { const isLastRow = renderedRowIndex === grid.renderedRows.length - 1; @@ -76,14 +80,14 @@ function strokeGridLines( function strokeActiveCell( ctx: CanvasRenderingContext2D, - colors: GridColors, + styles: GridStyles, grid: RenderedGrid, cell: RenderedCell, ) { const isLastCell = cell.rect.bottomRight.x === grid.rect.bottomRight.x; const isLastRow = cell.rect.bottomRight.y === grid.rect.bottomRight.y; - ctx.strokeStyle = colors.activeCellStroke; + ctx.strokeStyle = styles.activeCellStroke; ctx.lineWidth = 2; ctx.strokeRect( @@ -96,7 +100,7 @@ function strokeActiveCell( function drawCellRange( ctx: CanvasRenderingContext2D, - colors: GridColors, + styles: GridStyles, grid: RenderedGrid, start: CellRef, end: CellRef, @@ -112,7 +116,7 @@ function drawCellRange( const isRightEdge = rect.bottomRight.x === grid.rect.bottomRight.x; const isBottomEdge = rect.bottomRight.y === grid.rect.bottomRight.y; - ctx.fillStyle = colors.selelectionRangeFill; + ctx.fillStyle = styles.selelectionRangeFill; ctx.fillRect( rect.topLeft.x + 1, @@ -123,7 +127,7 @@ function drawCellRange( if (!stroke) return; - ctx.strokeStyle = colors.selectionRangeStroke; + ctx.strokeStyle = styles.selectionRangeStroke; ctx.strokeRect( rect.topLeft.x + 0.5, @@ -135,7 +139,7 @@ function drawCellRange( function drawPendingSelection( ctx: CanvasRenderingContext2D, - colors: GridColors, + styles: GridStyles, grid: RenderedGrid, selection: Selection, ) { @@ -147,18 +151,18 @@ function drawPendingSelection( if (selection instanceof RangeSelection) { excursion(ctx, () => { - drawCellRange(ctx, colors, grid, selection.range[0], selection.range[1], { + drawCellRange(ctx, styles, grid, selection.range[0], selection.range[1], { stroke: false, }); }); } - excursion(ctx, () => strokeActiveCell(ctx, colors, grid, activeCell)); + excursion(ctx, () => strokeActiveCell(ctx, styles, grid, activeCell)); } function drawSelection( ctx: CanvasRenderingContext2D, - colors: GridColors, + styles: GridStyles, grid: RenderedGrid, selection: Selection, ) { @@ -170,31 +174,52 @@ function drawSelection( if (selection instanceof RangeSelection) { excursion(ctx, () => { - drawCellRange(ctx, colors, grid, selection.range[0], selection.range[1], { + drawCellRange(ctx, styles, grid, selection.range[0], selection.range[1], { stroke: true, }); }); } - excursion(ctx, () => strokeActiveCell(ctx, colors, grid, activeCell)); + excursion(ctx, () => strokeActiveCell(ctx, styles, grid, activeCell)); +} + +function drawCellValues( + ctx: CanvasRenderingContext2D, + styles: GridStyles, + grid: RenderedGrid, +) { + grid.renderedRows.forEach((row) => + row.renderedCells.forEach((cell) => { + if (!cell.value) return; + ctx.fillStyle = "white"; + ctx.textAlign = "center"; + ctx.font = styles.cellValueFont; + ctx.fillText( + cell.value, + cell.rect.center.x, + cell.rect.center.y + parseInt(styles.cellValueLineHeight) / 4, + ); + }), + ); } export default function drawGrid( ctx: CanvasRenderingContext2D, - colors: GridColors, + styles: GridStyles, grid: RenderedGrid, selection?: Selection, pendingSelection?: Selection, ) { - excursion(ctx, () => fillBackground(ctx, colors, grid)); - excursion(ctx, () => strokeGridLines(ctx, colors, grid)); - excursion(ctx, () => strokeGrid(ctx, colors, grid)); + excursion(ctx, () => fillBackground(ctx, styles, grid)); + excursion(ctx, () => strokeGridLines(ctx, styles, grid)); + excursion(ctx, () => strokeGrid(ctx, styles, grid)); + excursion(ctx, () => drawCellValues(ctx, styles, grid)); if (pendingSelection) { excursion(ctx, () => - drawPendingSelection(ctx, colors, grid, pendingSelection), + drawPendingSelection(ctx, styles, grid, pendingSelection), ); } else if (selection) { - excursion(ctx, () => drawSelection(ctx, colors, grid, selection)); + excursion(ctx, () => drawSelection(ctx, styles, grid, selection)); } } -- cgit v1.2.3