From b8bc977a8e820583fadca09f589a1c09ee6549c1 Mon Sep 17 00:00:00 2001 From: Joeri Exelmans Date: Sat, 18 Oct 2025 22:43:52 +0200 Subject: [PATCH] better looking simulation --- src/App/AST.css | 10 +++++++-- src/App/App.tsx | 14 ++++++------- src/App/RTHistory.tsx | 35 +++++++++++++------------------ src/App/ShowAST.tsx | 6 +++--- src/VisualEditor/VisualEditor.css | 2 +- src/VisualEditor/VisualEditor.tsx | 16 ++++++++------ 6 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/App/AST.css b/src/App/AST.css index ad90394..1dd14ed 100644 --- a/src/App/AST.css +++ b/src/App/AST.css @@ -1,11 +1,17 @@ details.active { - background-color: rgba(255, 140, 0, 0.2); + /* background-color: rgba(128, 72, 0, 0.855); + color: white; */ + + box-shadow: rgba(128, 72, 0, 0.856) 0 0 8; } details { border: 1px black solid; /* border-radius: 5px; */ background-color: white; - margin-bottom: 2px; + margin-bottom: 4px; padding-right: 2px; + color: black; + width: fit-content; + border-radius: 10px; } \ No newline at end of file diff --git a/src/App/App.tsx b/src/App/App.tsx index 6b222d7..fcf93cd 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -58,13 +58,10 @@ export function App() { if (refRightSideBar.current) { const el = refRightSideBar.current; - // console.log('scrolling to', el.scrollHeight); console.log('scrolling to:', el); setTimeout(() => { el.scrollIntoView({block: "end", behavior: "smooth"}); }, 100); - - // el.scrollTo(0, el.scrollHeight+1000); } } @@ -106,6 +103,11 @@ export function App() { }; }, []); + const highlightActive = (rtIdx !== undefined) && new Set([...rt[rtIdx].mode].filter(uid => { + const state = ast.uid2State.get(uid); + return state && state.parent?.kind !== "and"; + })) || new Set(); + return {/* Top bar */} {/* main */} - + {/* right sidebar */} - +
diff --git a/src/App/RTHistory.tsx b/src/App/RTHistory.tsx index 44d8dd9..19887d6 100644 --- a/src/App/RTHistory.tsx +++ b/src/App/RTHistory.tsx @@ -1,4 +1,4 @@ -import { Dispatch, SetStateAction } from "react"; +import { Dispatch, Ref, SetStateAction } from "react"; import { Statechart, stateDescription } from "../statecharts/abstract_syntax"; import { BigStep, Environment, Mode, RaisedEvent } from "../statecharts/runtime_types"; import { formatTime } from "./util"; @@ -10,23 +10,26 @@ type RTHistoryProps = { ast: Statechart, setRTIdx: Dispatch>, setTime: Dispatch>, + refRightSideBar: Ref, } -export function RTHistory({rt, rtIdx, ast, setRTIdx, setTime}: RTHistoryProps) { +export function RTHistory({rt, rtIdx, ast, setRTIdx, setTime, refRightSideBar}: RTHistoryProps) { function gotoRt(idx: number, timestamp: number) { setRTIdx(idx); setTime({kind: "paused", simtime: timestamp}); } - return rt.map((rt, idx) => <> -
gotoRt(idx, rt.simtime)}> -
({formatTime(rt.simtime)}, {rt.inputEvent || ""})
- - - {rt.outputEvents.length>0 &&
- {rt.outputEvents.map((e:RaisedEvent) => '^'+e.name).join(', ')} -
} -
); + return
+ {rt.map((r, idx) => <> +
gotoRt(idx, r.simtime)}> +
({formatTime(r.simtime)}, {r.inputEvent || ""})
+ + + {r.outputEvents.length>0 &&
+ {r.outputEvents.map((e:RaisedEvent) => '^'+e.name).join(', ')} +
} +
)} +
; } @@ -45,13 +48,5 @@ function ShowMode(props: {mode: Mode, statechart: Statechart}) { } function getActiveLeafs(mode: Mode, sc: Statechart) { - const toDelete = []; - for (const stateA of mode) { - for (const stateB of mode) { - if (sc.uid2State.get(stateA)!.parent === sc.uid2State.get(stateB)) { - toDelete.push(stateB); - } - } - } - return mode.difference(new Set(toDelete)); + return new Set([...mode].filter(uid => sc.uid2State.get(uid)?.children?.length === 0)); } diff --git a/src/App/ShowAST.tsx b/src/App/ShowAST.tsx index 9263ace..30c2547 100644 --- a/src/App/ShowAST.tsx +++ b/src/App/ShowAST.tsx @@ -32,11 +32,11 @@ export function ShowAction(props: {action: Action}) { } } -export function ShowAST(props: {root: ConcreteState | PseudoState, transitions: Map, rt: RT_Statechart | undefined}) { +export function ShowAST(props: {root: ConcreteState | PseudoState, transitions: Map, rt: RT_Statechart | undefined, highlightActive: Set}) { const description = stateDescription(props.root); const outgoing = props.transitions.get(props.root.uid) || []; - return
+ return
{props.root.kind}: {description} {props.root.kind !== "pseudo" && props.root.entryActions.length>0 && @@ -51,7 +51,7 @@ export function ShowAST(props: {root: ConcreteState | PseudoState, transitions: } {props.root.kind !== "pseudo" && props.root.children.length>0 && props.root.children.map(child => - + ) } {outgoing.length>0 && diff --git a/src/VisualEditor/VisualEditor.css b/src/VisualEditor/VisualEditor.css index 0e38881..6843774 100644 --- a/src/VisualEditor/VisualEditor.css +++ b/src/VisualEditor/VisualEditor.css @@ -46,7 +46,7 @@ /* fill-opacity: 0.2; */ /* stroke: rgb(100, 149, 237); */ /* stroke: */ - filter: drop-shadow( 0px 0px 6px rgba(0, 150, 255, 0.8)); + filter: drop-shadow( 0px 0px 6px rgba(128, 72, 0, 0.856)); /* stroke-width: 3px; */ } diff --git a/src/VisualEditor/VisualEditor.tsx b/src/VisualEditor/VisualEditor.tsx index c0c5e4f..7653099 100644 --- a/src/VisualEditor/VisualEditor.tsx +++ b/src/VisualEditor/VisualEditor.tsx @@ -61,14 +61,16 @@ export const sides: [RountanglePart, (r:Rect2D)=>Line2D][] = [ export type InsertMode = "and"|"or"|"pseudo"|"shallow"|"deep"|"transition"|"text"; type VisualEditorProps = { + ast: Statechart, setAST: Dispatch>, rt: BigStep|undefined, errors: TraceableError[], setErrors: Dispatch>, mode: InsertMode, + highlightActive: Set, }; -export function VisualEditor({setAST, rt, errors, setErrors, mode}: VisualEditorProps) { +export function VisualEditor({ast, setAST, rt, errors, setErrors, mode, highlightActive}: VisualEditorProps) { const [historyState, setHistoryState] = useState({current: emptyState, history: [], future: []}); const state = historyState.current; @@ -680,6 +682,8 @@ export function VisualEditor({setAST, rt, errors, setErrors, mode}: VisualEditor const active = rt?.mode || new Set(); + console.log(highlightActive); + const rootErrors = errors.filter(({shapeUid}) => shapeUid === "root").map(({message}) => message); return 0) && {rootErrors.join(' ')}} - {state.rountangles.map(rountangle => - { + return r.uid === rountangle.uid)?.parts || []} @@ -720,8 +724,8 @@ export function VisualEditor({setAST, rt, errors, setErrors, mode}: VisualEditor errors={errors .filter(({shapeUid}) => shapeUid === rountangle.uid) .map(({message}) => message)} - active={active.has(rountangle.uid)} - />)} + active={highlightActive.has(rountangle.uid)} + />})} {state.diamonds.map(diamond => <> shapeUid === diamond.uid) .map(({message}) => message)} - active={active.has(diamond.uid)}/> + active={false}/> )} {state.history.map(history => <>