From dfbcca5c14f66457ca39a3dafda5472b4717df24 Mon Sep 17 00:00:00 2001 From: Joeri Exelmans Date: Tue, 21 Oct 2025 17:25:04 +0200 Subject: [PATCH] user can select 'plant' from dropdown menu --- src/App/App.tsx | 45 +++++++++++++++++++++++-- src/App/BottomPanel.tsx | 2 -- src/Plant/DigitalWatch/DigitalWatch.tsx | 28 ++++++++++++--- src/Plant/Dummy/Dummy.tsx | 10 ++++++ src/Plant/Plant.ts | 1 + 5 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 src/Plant/Dummy/Dummy.tsx diff --git a/src/App/App.tsx b/src/App/App.tsx index 844209b..a41676a 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -1,4 +1,4 @@ -import { Dispatch, ReactElement, SetStateAction, useEffect, useRef, useState } from "react"; +import { createElement, Dispatch, ReactElement, SetStateAction, useEffect, useRef, useState } from "react"; import { emptyStatechart, Statechart } from "../statecharts/abstract_syntax"; import { handleInputEvent, initialize } from "../statecharts/interpreter"; @@ -18,8 +18,11 @@ import { TraceableError } from "../statecharts/parser"; import { getKeyHandler } from "./shortcut_handler"; import { BottomPanel } from "./BottomPanel"; import { emptyState } from "@/statecharts/concrete_syntax"; -import { usePersistentState } from "@/util/persistent_state"; import { PersistentDetails } from "./PersistentDetails"; +import { DigitalWatch, DigitalWatchPlant } from "@/Plant/DigitalWatch/DigitalWatch"; +import { DummyPlant } from "@/Plant/Dummy/Dummy"; +import { Plant } from "@/Plant/Plant"; +import { usePersistentState } from "@/util/persistent_state"; type EditHistory = { current: VisualEditorState, @@ -27,6 +30,11 @@ type EditHistory = { future: VisualEditorState[], } +const plants: [string, Plant][] = [ + ["dummy", DummyPlant], + ["digital watch", DigitalWatchPlant], +] + export function App() { const [mode, setMode] = useState("and"); const [historyState, setHistoryState] = useState({current: emptyState, history: [], future: []}); @@ -36,6 +44,9 @@ export function App() { const [rtIdx, setRTIdx] = useState(); const [time, setTime] = useState({kind: "paused", simtime: 0}); const [modal, setModal] = useState(null); + const [plantName, setPlantName] = usePersistentState("plant", "dummy"); + + const plant = plants.find(([pn, p]) => pn === plantName)![1]; const editorState = historyState.current; const setEditorState = (cb: (value: VisualEditorState) => VisualEditorState) => { @@ -192,6 +203,19 @@ export function App() { const highlightTransitions = (rtIdx === undefined) ? [] : rt[rtIdx].firedTransitions; + + const plantStates = []; + let ps = plant.initial(e => { + // ... + }); + for (let i=0; i {/* Modal dialog */} @@ -270,7 +294,8 @@ export function App() {
@@ -278,6 +303,20 @@ export function App() {
+ + + plant + + {rtIdx!==undefined && } + {/* */} + + diff --git a/src/App/BottomPanel.tsx b/src/App/BottomPanel.tsx index 5cc03eb..3bd47f2 100644 --- a/src/App/BottomPanel.tsx +++ b/src/App/BottomPanel.tsx @@ -5,7 +5,6 @@ import "./BottomPanel.css"; import head from "../head.svg" ; import { PersistentDetails } from "./PersistentDetails"; -import { DigitalWatch } from "@/Plant/DigitalWatch/DigitalWatch"; export function BottomPanel(props: {errors: TraceableError[]}) { const [greeting, setGreeting] = useState(<> "Welcome to StateBuddy, buddy!"
); @@ -18,7 +17,6 @@ export function BottomPanel(props: {errors: TraceableError[]}) { return
{greeting} - {props.errors.length > 0 &&
diff --git a/src/Plant/DigitalWatch/DigitalWatch.tsx b/src/Plant/DigitalWatch/DigitalWatch.tsx index c26f7f5..1a25c85 100644 --- a/src/Plant/DigitalWatch/DigitalWatch.tsx +++ b/src/Plant/DigitalWatch/DigitalWatch.tsx @@ -7,12 +7,15 @@ import digitalFont from "./digital-font.ttf"; import { Plant } from "../Plant"; import { RaisedEvent } from "@/statecharts/runtime_types"; -type DigitalWatchProps = { +type DigitalWatchState = { light: boolean; h: number; m: number; s: number; alarm: boolean; +} + +type DigitalWatchProps = DigitalWatchState & { callbacks: { onTopLeftPressed: () => void; onTopRightPressed: () => void; @@ -26,7 +29,7 @@ type DigitalWatchProps = { } export function DigitalWatch({light, h, m, s, alarm, callbacks}: DigitalWatchProps) { - const refText = useRef(null); + console.log(light, h, m); const twoDigits = (n: number) => ("0"+n.toString()).slice(-2); const hhmmss = `${twoDigits(h)}:${twoDigits(m)}:${twoDigits(s)}`; @@ -43,7 +46,7 @@ export function DigitalWatch({light, h, m, s, alarm, callbacks}: DigitalWatchPro : } - {hhmmss} + {hhmmss} callbacks.onTopLeftPressed()} @@ -87,6 +90,23 @@ export const DigitalWatchPlant: Plant = { { kind: "event", event: "bottomRightReleased" }, { kind: "event", event: "bottomLeftReleased" }, ], + initial: (raise: (event: RaisedEvent) => void) => ({ + light: false, + alarm: false, + h: 12, + m: 0, + s: 0, + callbacks: { + onTopLeftPressed: () => raise({ name: "topLeftPressed" }), + onTopRightPressed: () => raise({ name: "topRightPressed" }), + onBottomRightPressed: () => raise({ name: "bottomRightPressed" }), + onBottomLeftPressed: () => raise({ name: "bottomLeftPressed" }), + onTopLeftReleased: () => raise({ name: "topLeftReleased" }), + onTopRightReleased: () => raise({ name: "topRightReleased" }), + onBottomRightReleased: () => raise({ name: "bottomRightReleased" }), + onBottomLeftReleased: () => raise({ name: "bottomLeftReleased" }), + }, + }), reducer: (inputEvent: RaisedEvent, state: DigitalWatchProps) => { if (inputEvent.name === "setH") { return { ...state, h: inputEvent.param }; @@ -106,4 +126,4 @@ export const DigitalWatchPlant: Plant = { return state; // unknown event - ignore it }, render: DigitalWatch, -} \ No newline at end of file +} diff --git a/src/Plant/Dummy/Dummy.tsx b/src/Plant/Dummy/Dummy.tsx new file mode 100644 index 0000000..5be4403 --- /dev/null +++ b/src/Plant/Dummy/Dummy.tsx @@ -0,0 +1,10 @@ +import { RaisedEvent } from "@/statecharts/runtime_types"; +import { Plant } from "../Plant"; + +export const DummyPlant: Plant<{}> = { + inputEvents: [], + outputEvents: [], + initial: () => ({}), + reducer: (_inputEvent: RaisedEvent, _state: {}) => ({}), + render: (_state: {}) => <>, +} diff --git a/src/Plant/Plant.ts b/src/Plant/Plant.ts index 636b33a..b20aa16 100644 --- a/src/Plant/Plant.ts +++ b/src/Plant/Plant.ts @@ -6,6 +6,7 @@ export type Plant = { inputEvents: EventTrigger[]; outputEvents: EventTrigger[]; + initial: (raise: (event: RaisedEvent) => void) => StateType; reducer: (inputEvent: RaisedEvent, state: StateType) => StateType; render: (state: StateType) => ReactElement; }