summaryrefslogtreecommitdiff
path: root/web/src/components/grid/drawGrid.ts
diff options
context:
space:
mode:
Diffstat (limited to 'web/src/components/grid/drawGrid.ts')
-rw-r--r--web/src/components/grid/drawGrid.ts188
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));
}
}