diff options
Diffstat (limited to 'web/src/components/grid/drawGrid.ts')
| -rw-r--r-- | web/src/components/grid/drawGrid.ts | 188 |
1 files changed, 145 insertions, 43 deletions
diff --git a/web/src/components/grid/drawGrid.ts b/web/src/components/grid/drawGrid.ts index 8e64479..5ea17b6 100644 --- a/web/src/components/grid/drawGrid.ts +++ b/web/src/components/grid/drawGrid.ts @@ -1,21 +1,61 @@ -import colors from "tailwindcss/colors"; -import { PendingSelection, Selection } from "../../selection"; +import { RangeSelection, Selection } from "../../selection"; import { CellRef } from "../../types"; import { RenderedCell, RenderedGrid } from "./renderGrid"; -function fillBackground(ctx: CanvasRenderingContext2D, grid: RenderedGrid) { +interface GridColors { + bgFill: string; + borderStroke: string; + cellStroke: string; + selelectionRangeFill: string; + selectionRangeStroke: string; + activeCellStroke: string; +} + +export function getGridColors(el: HTMLElement): GridColors { + const style = window.getComputedStyle(el); + const color = (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"), + }; +} + +function excursion(ctx: CanvasRenderingContext2D, f: () => void) { + ctx.save(); + f(); + ctx.restore(); +} + +function fillBackground( + ctx: CanvasRenderingContext2D, + colors: GridColors, + grid: RenderedGrid, +) { ctx.clearRect(0, 0, grid.rect.width, grid.rect.height); - ctx.fillStyle = colors.neutral[900]; + ctx.fillStyle = colors.bgFill; ctx.fillRect(0, 0, grid.rect.width, grid.rect.height); } -function strokeGrid(ctx: CanvasRenderingContext2D, grid: RenderedGrid) { - ctx.strokeStyle = colors.neutral[700]; +function strokeGrid( + ctx: CanvasRenderingContext2D, + colors: GridColors, + grid: RenderedGrid, +) { + ctx.strokeStyle = colors.borderStroke; ctx.strokeRect(0.5, 0.5, grid.rect.width - 1, grid.rect.height - 1); } -function strokeGridLines(ctx: CanvasRenderingContext2D, grid: RenderedGrid) { - ctx.strokeStyle = colors.neutral[800]; +function strokeGridLines( + ctx: CanvasRenderingContext2D, + colors: GridColors, + grid: RenderedGrid, +) { + ctx.strokeStyle = colors.cellStroke; grid.renderedRows.forEach((row, renderedRowIndex) => { const isLastRow = renderedRowIndex === grid.renderedRows.length - 1; @@ -43,65 +83,127 @@ function getRenderedCell( return grid.renderedRows[renderedRowIndex]?.renderedCells[cellRef.cellIndex]; } -function drawPendingSelection( +function strokeActiveCell( ctx: CanvasRenderingContext2D, + colors: GridColors, grid: RenderedGrid, - selection: PendingSelection, -) {} + cell: RenderedCell, +) { + const isLastCell = cell.rect.bottomRight.x === grid.rect.bottomRight.x; + const isLastRow = cell.rect.bottomRight.y === grid.rect.bottomRight.y; -function drawSelection( + ctx.strokeStyle = colors.activeCellStroke; + ctx.lineWidth = 2; + + ctx.strokeRect( + cell.rect.topLeft.x + 1, + cell.rect.topLeft.y + 1, + isLastCell ? cell.rect.width - 2 : cell.rect.width - 1, + isLastRow ? cell.rect.height - 2 : cell.rect.height - 1, + ); +} + +function drawCellRange( ctx: CanvasRenderingContext2D, + colors: GridColors, grid: RenderedGrid, - selection: Selection, + start: CellRef, + end: CellRef, + { stroke }: { stroke: boolean }, ) { - if (selection.gridId !== grid.id) return; + const startCell = getRenderedCell(grid, start); + const endCell = getRenderedCell(grid, end); - const cell = getRenderedCell(grid, selection.activeCellRef); + if (!startCell || !endCell) return; - if (!cell) return; + const rect = startCell.rect.extend(endCell.rect); - const isLastCell = cell.rect.bottomRight.x === grid.rect.bottomRight.x; - const isLastRow = cell.rect.bottomRight.y === grid.rect.bottomRight.y; + const isRightEdge = rect.bottomRight.x === grid.rect.bottomRight.x; + const isBottomEdge = rect.bottomRight.y === grid.rect.bottomRight.y; + + ctx.fillStyle = colors.selelectionRangeFill; - // ctx.fillStyle = colors.green[4] + "30"; + ctx.fillRect( + rect.topLeft.x + 1, + rect.topLeft.y + 1, + isRightEdge ? rect.width - 2 : rect.width - 1, + isBottomEdge ? rect.height - 2 : rect.height - 1, + ); - // ctx.fillRect( - // cell.rect.topLeft.x + 1, - // cell.rect.topLeft.y + 1, - // cell.rect.width - 1, - // cell.rect.height - 1, - // ); + if (!stroke) return; - ctx.strokeStyle = colors.green[400]; - ctx.lineWidth = 2; + ctx.strokeStyle = colors.selectionRangeStroke; ctx.strokeRect( - cell.rect.topLeft.x + 1, - cell.rect.topLeft.y + 1, - isLastCell ? cell.rect.width - 2 : cell.rect.width - 1, - isLastRow ? cell.rect.height - 2 : cell.rect.height - 1, + rect.topLeft.x + 0.5, + rect.topLeft.y + 0.5, + isRightEdge ? rect.width - 1 : rect.width, + isBottomEdge ? rect.height - 1 : rect.height, ); } +function drawPendingSelection( + ctx: CanvasRenderingContext2D, + colors: GridColors, + grid: RenderedGrid, + selection: Selection, +) { + if (selection.gridId !== grid.id) return; + + const activeCell = getRenderedCell(grid, selection.activeCellRef); + + if (!activeCell) return; + + if (selection instanceof RangeSelection) { + excursion(ctx, () => { + drawCellRange(ctx, colors, grid, selection.range[0], selection.range[1], { + stroke: false, + }); + }); + } + + excursion(ctx, () => strokeActiveCell(ctx, colors, grid, activeCell)); +} + +function drawSelection( + ctx: CanvasRenderingContext2D, + colors: GridColors, + grid: RenderedGrid, + selection: Selection, +) { + if (selection.gridId !== grid.id) return; + + const activeCell = getRenderedCell(grid, selection.activeCellRef); + + if (!activeCell) return; + + if (selection instanceof RangeSelection) { + excursion(ctx, () => { + drawCellRange(ctx, colors, grid, selection.range[0], selection.range[1], { + stroke: true, + }); + }); + } + + excursion(ctx, () => strokeActiveCell(ctx, colors, grid, activeCell)); +} + export default function drawGrid( ctx: CanvasRenderingContext2D, + colors: GridColors, grid: RenderedGrid, selection?: Selection, - pendingSelection?: PendingSelection, + pendingSelection?: Selection, ) { - const excursion = (f: () => void) => { - ctx.save(); - f(); - ctx.restore(); - }; - - excursion(() => fillBackground(ctx, grid)); - excursion(() => strokeGridLines(ctx, grid)); - excursion(() => strokeGrid(ctx, grid)); + excursion(ctx, () => fillBackground(ctx, colors, grid)); + excursion(ctx, () => strokeGridLines(ctx, colors, grid)); + excursion(ctx, () => strokeGrid(ctx, colors, grid)); if (pendingSelection) { - excursion(() => drawPendingSelection(ctx, grid, pendingSelection)); + excursion(ctx, () => + drawPendingSelection(ctx, colors, grid, pendingSelection), + ); } else if (selection) { - excursion(() => drawSelection(ctx, grid, selection)); + excursion(ctx, () => drawSelection(ctx, colors, grid, selection)); } } |
