diff options
Diffstat (limited to 'web')
| -rw-r--r-- | web/src/components/grid/drawGrid.ts | 89 | ||||
| -rw-r--r-- | web/src/components/grid/index.css | 1 | ||||
| -rw-r--r-- | web/src/components/grid/index.ts | 12 | ||||
| -rw-r--r-- | web/src/index.ts | 3 | ||||
| -rw-r--r-- | web/src/math/Rect.ts | 7 |
5 files changed, 71 insertions, 41 deletions
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)); } } diff --git a/web/src/components/grid/index.css b/web/src/components/grid/index.css index 825a74a..477d40e 100644 --- a/web/src/components/grid/index.css +++ b/web/src/components/grid/index.css @@ -11,6 +11,7 @@ ntv-grid { transparent ); --grid-selection-range-stroke: var(--color-green-400); + font-size: 14px; } ntv-grid > canvas { diff --git a/web/src/components/grid/index.ts b/web/src/components/grid/index.ts index 15f26a9..7d12a84 100644 --- a/web/src/components/grid/index.ts +++ b/web/src/components/grid/index.ts @@ -1,7 +1,7 @@ import h, { type CreateElement } from "../../html"; import { CellRef } from "../../types"; import cellAtCoord from "./cellAtCoord"; -import drawGrid, { getGridColors } from "./drawGrid"; +import drawGrid, { getGridStyles } from "./drawGrid"; import "./index.css"; class NotiveGridElement extends HTMLElement { @@ -28,11 +28,7 @@ class NotiveGridElement extends HTMLElement { } window.addEventListener("ntv:selectionchange", () => this.draw()); - window.addEventListener("ntv:grid:change", (event) => { - if (event.detail.gridId === this.gridId) { - this.draw(); - } - }); + window.addEventListener("ntv:grid:change", () => this.draw()); this.canvasEl.addEventListener( "mousedown", @@ -55,11 +51,11 @@ class NotiveGridElement extends HTMLElement { this.canvasEl.setAttribute("width", grid.rect.width + "px"); this.canvasEl.setAttribute("height", grid.rect.height + "px"); - const colors = getGridColors(this); + const styles = getGridStyles(this); drawGrid( ctx, - colors, + styles, grid, window.notive.selection, window.notive.pendingSelection, diff --git a/web/src/index.ts b/web/src/index.ts index 35af24c..f08aedc 100644 --- a/web/src/index.ts +++ b/web/src/index.ts @@ -7,8 +7,9 @@ import renderGrid, { } from "./components/grid/renderGrid"; function defaultDoc(): Doc { - const defaultCells: Cell[] = Array.from({ length: 16 }, () => ({ + const defaultCells: Cell[] = Array.from({ length: 16 }, (_, i) => ({ widthRatio: new Ratio(1, 16), + value: i.toString(), })); return { diff --git a/web/src/math/Rect.ts b/web/src/math/Rect.ts index e26fbae..f52a2f7 100644 --- a/web/src/math/Rect.ts +++ b/web/src/math/Rect.ts @@ -40,6 +40,13 @@ export default class Rect { ); } + get center(): Coord { + return new Coord( + this.topLeft.x + (this.bottomRight.x - this.topLeft.x) / 2, + this.topLeft.y + (this.bottomRight.y - this.topLeft.y) / 2, + ); + } + /** Determine if this rectangle contains the point at `coord`. */ containsCoord(coord: Coord): boolean { return ( |
