From 70ad562bdeefce0441a90b468076ce9a4d215a94 Mon Sep 17 00:00:00 2001 From: sfja Date: Mon, 11 May 2026 23:36:53 +0200 Subject: [PATCH] add placing --- editor/src/App.tsx | 9 +++++---- editor/src/Canvas.tsx | 14 ++++++-------- editor/src/Editor.ts | 43 +++++++++++++++++++++++++++++++++--------- editor/src/Toolbar.tsx | 11 +++++++---- 4 files changed, 52 insertions(+), 25 deletions(-) diff --git a/editor/src/App.tsx b/editor/src/App.tsx index 70717bb..b65f642 100644 --- a/editor/src/App.tsx +++ b/editor/src/App.tsx @@ -1,18 +1,19 @@ -import { useState, type ReactElement } from "react"; +import { useRef, useState, type ReactElement } from "react"; import "./style.css"; import Canvas from "./Canvas"; import { Editor } from "./Editor"; import Toolbar from "./Toolbar"; function App(): ReactElement { - const [editor] = useState(new Editor()); + const [editor] = useState(() => new Editor()); + const canvasRef = useRef(null); return ( <>

nandsim

- - + +
); diff --git a/editor/src/Canvas.tsx b/editor/src/Canvas.tsx index 6aae2fc..336a039 100644 --- a/editor/src/Canvas.tsx +++ b/editor/src/Canvas.tsx @@ -1,22 +1,20 @@ -import { useEffect, useRef, type ReactElement } from "react"; +import { useEffect, useRef, type ReactElement, type RefObject } from "react"; import { V2, type Editor } from "./Editor"; -type Props = { editor: Editor }; - -function Canvas({ editor }: Props): ReactElement { - const ref = useRef(null); +type Props = { editor: Editor; canvasRef: RefObject }; +function Canvas({ editor, canvasRef }: Props): ReactElement { useEffect(() => { - if (!ref.current) return; + if (!canvasRef.current) return; - editor.render(ref.current); + editor.render(canvasRef.current); }); return ( <>
(S: S) { - this.state = new S(this); + transitionTo(newState: State) { + this.state = newState; this.notifyListeners(); } @@ -188,19 +188,21 @@ class Normal implements State { selectTool(tool: Tool): void { switch (tool) { case "pan": - this.cx.transitionTo(Panning); + this.cx.transitionTo(new Panning(this.cx)); break; + case "and": + this.cx.transitionTo(new Placing(this.cx, "and")); } } onMouseDown(pos: V2): void { this.cx.addSelectionRect(pos); - this.cx.transitionTo(Selecting); + this.cx.transitionTo(new Selecting(this.cx)); } onKeyDown(key: string): void { if (key === "Shift") { - this.cx.transitionTo(Panning); + this.cx.transitionTo(new Panning(this.cx)); return; } } @@ -231,20 +233,20 @@ class Panning implements State { onKeyDown(key: string): void { if (key === "Escape") { - this.cx.transitionTo(Normal); + this.cx.transitionTo(new Normal(this.cx)); return; } } onKeyUp(key: string): void { if (key === "Shift") { - this.cx.transitionTo(Normal); + this.cx.transitionTo(new Normal(this.cx)); return; } } selectTool(tool: Tool): void { - this.cx.transitionTo(Normal); + this.cx.transitionTo(new Normal(this.cx)); this.cx.selectTool(tool); } @@ -263,7 +265,7 @@ class Selecting implements State { onMouseUp(_pos: V2): void { this.cx.removeSelectionRect(); - this.cx.transitionTo(Normal); + this.cx.transitionTo(new Normal(this.cx)); } onMouseMove(deltaPos: V2): void { @@ -275,4 +277,27 @@ class Selecting implements State { } } +class Placing implements State { + constructor( + private cx: Cx, + private tool: Tool, + ) {} + + onMouseUp(pos: V2): void { + this.cx.transitionTo(new Normal(this.cx)); + console.log("place"); + } + + onKeyDown(key: string): void { + if (key === "Escape") { + this.cx.transitionTo(new Normal(this.cx)); + return; + } + } + + selectedTool(): Tool | null { + return this.tool; + } +} + type Tool = "select" | "pan" | "and"; diff --git a/editor/src/Toolbar.tsx b/editor/src/Toolbar.tsx index 41ada01..86164a5 100644 --- a/editor/src/Toolbar.tsx +++ b/editor/src/Toolbar.tsx @@ -1,14 +1,14 @@ -import { useEffect, useState, type ReactElement } from "react"; +import { useEffect, useState, type ReactElement, type RefObject } from "react"; import type { Editor } from "./Editor"; -type Props = { editor: Editor }; +type Props = { editor: Editor; canvasRef: RefObject }; function useUpdate(): [number, () => void] { const [value, setValue] = useState(0); return [value, () => setValue(value + 1)] as const; } -function Toolbar({ editor }: Props): ReactElement { +function Toolbar({ editor, canvasRef }: Props): ReactElement { const [uid, update] = useUpdate(); useEffect(() => { @@ -23,7 +23,10 @@ function Toolbar({ editor }: Props): ReactElement {