add click handler
This commit is contained in:
parent
60e589e689
commit
a889c03929
@ -13,7 +13,7 @@ function App(): ReactElement {
|
|||||||
<h1>nandsim</h1>
|
<h1>nandsim</h1>
|
||||||
<div className="Editor">
|
<div className="Editor">
|
||||||
<Toolbar editor={editor} canvasRef={canvasRef} />
|
<Toolbar editor={editor} canvasRef={canvasRef} />
|
||||||
<Canvas editor={editor} canvasRef={canvasRef} />
|
<Canvas editor={editor} canvasRef={canvasRef} width={800} height={800} />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { useEffect, type ReactElement, type RefObject } from "react";
|
|||||||
import { type Editor } from "./editor/Editor";
|
import { type Editor } from "./editor/Editor";
|
||||||
import { v2 } from "./editor/V2";
|
import { v2 } from "./editor/V2";
|
||||||
|
|
||||||
type Props = { editor: Editor; canvasRef: RefObject<HTMLCanvasElement | null> };
|
type Props = { editor: Editor; canvasRef: RefObject<HTMLCanvasElement | null>, width: number, height: number };
|
||||||
|
|
||||||
function Canvas({ editor, canvasRef }: Props): ReactElement {
|
function Canvas({ editor, canvasRef, width, height }: Props): ReactElement {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvasRef.current) return;
|
if (!canvasRef.current) return;
|
||||||
|
|
||||||
@ -16,9 +16,9 @@ function Canvas({ editor, canvasRef }: Props): ReactElement {
|
|||||||
<div className="Canvas">
|
<div className="Canvas">
|
||||||
<canvas
|
<canvas
|
||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
width={1000}
|
width={width}
|
||||||
height={1000}
|
height={height}
|
||||||
style={{ width: 1000, height: 1000, backgroundColor: "black" }}
|
style={{ width, height, backgroundColor: "black" }}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onMouseDown={(ev) => {
|
onMouseDown={(ev) => {
|
||||||
const pos = v2(ev.nativeEvent.offsetX, ev.nativeEvent.offsetY);
|
const pos = v2(ev.nativeEvent.offsetX, ev.nativeEvent.offsetY);
|
||||||
|
|||||||
@ -83,7 +83,7 @@ export class Board {
|
|||||||
this.hoveredOverOutput?.[0] === comp &&
|
this.hoveredOverOutput?.[0] === comp &&
|
||||||
this.hoveredOverOutput[1] === i
|
this.hoveredOverOutput[1] === i
|
||||||
) {
|
) {
|
||||||
c.strokeStyle = `#bbbbbb`;
|
c.strokeStyle = `#eee`;
|
||||||
c.lineWidth = 2;
|
c.lineWidth = 2;
|
||||||
c.beginPath();
|
c.beginPath();
|
||||||
c.arc(x + w, y + (i + 1) * pinSpace, 5, 0, Math.PI * 2);
|
c.arc(x + w, y + (i + 1) * pinSpace, 5, 0, Math.PI * 2);
|
||||||
@ -135,6 +135,55 @@ export class Board {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleMouseClick(
|
||||||
|
pos: V2,
|
||||||
|
inputPinClicked: (comp: Component, i: number) => void,
|
||||||
|
outputPinClicked: (comp: Component, i: number) => void,
|
||||||
|
componentClicked: (comp: Component) => void,
|
||||||
|
): "handled" | "not handled" {
|
||||||
|
for (const comp of this.components) {
|
||||||
|
const {
|
||||||
|
pos: { x, y },
|
||||||
|
def: {
|
||||||
|
size: { x: w, y: h },
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
},
|
||||||
|
} = comp;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!pointInsideRect(
|
||||||
|
pos,
|
||||||
|
comp.pos.sub(v2(5, 5)),
|
||||||
|
comp.def.size.add(v2(10, 10)),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const pinSpace = h / (inputs.length + 1);
|
||||||
|
for (let i = 0; i < inputs.length; ++i) {
|
||||||
|
if (v2(x, y + (i + 1) * pinSpace).distance(pos) < 5) {
|
||||||
|
inputPinClicked(comp, i);
|
||||||
|
return "handled";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const pinSpace = h / (outputs.length + 1);
|
||||||
|
for (let i = 0; i < outputs.length; ++i) {
|
||||||
|
if (v2(x + w, y + (i + 1) * pinSpace).distance(pos) < 5) {
|
||||||
|
outputPinClicked(comp, i);
|
||||||
|
return "handled";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
componentClicked(comp);
|
||||||
|
return "handled";
|
||||||
|
}
|
||||||
|
return "not handled";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ComponentRepo {
|
export class ComponentRepo {
|
||||||
|
|||||||
@ -23,9 +23,20 @@ export class Normal implements State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMouseDown(pos: V2): void {
|
onMouseDown(pos: V2): void {
|
||||||
|
if (
|
||||||
|
this.cx.board.handleMouseClick(
|
||||||
|
pos.sub(this.cx.offset),
|
||||||
|
(comp, i) => {},
|
||||||
|
(comp, i) => {},
|
||||||
|
(comp) => {},
|
||||||
|
) === "handled"
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
this.cx.addSelectionRect(pos);
|
this.cx.addSelectionRect(pos);
|
||||||
this.cx.transitionTo(new Selecting(this.cx));
|
this.cx.transitionTo(new Selecting(this.cx));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMouseMove(_deltaPos: V2, pos: V2): void {
|
onMouseMove(_deltaPos: V2, pos: V2): void {
|
||||||
this.cx.board.updateMouseHover(pos.sub(this.cx.offset));
|
this.cx.board.updateMouseHover(pos.sub(this.cx.offset));
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
import type { Cx, Tool } from "../Cx";
|
import type { Cx, Tool } from "../Cx";
|
||||||
import type { V2_ } from "../V2";
|
import type { V2 } from "../V2";
|
||||||
import type { State } from "../State";
|
import type { State } from "../State";
|
||||||
import { Normal } from "./Normal";
|
import { Normal } from "./Normal";
|
||||||
|
|
||||||
export class Selecting implements State {
|
export class Selecting implements State {
|
||||||
constructor(private cx: Cx) {}
|
constructor(private cx: Cx) {}
|
||||||
|
|
||||||
onMouseUp(_pos: V2_): void {
|
onMouseUp(_pos: V2): void {
|
||||||
this.cx.removeSelectionRect();
|
this.cx.removeSelectionRect();
|
||||||
this.cx.transitionTo(new Normal(this.cx));
|
this.cx.transitionTo(new Normal(this.cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseMove(deltaPos: V2_): void {
|
onMouseMove(deltaPos: V2): void {
|
||||||
this.cx.moveSelectionRect(deltaPos);
|
this.cx.moveSelectionRect(deltaPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user