fix: plant steps were wrongly showing statechart output events
This commit is contained in:
parent
8ed9267cb7
commit
f5c427d61b
11 changed files with 104 additions and 33 deletions
|
|
@ -33,6 +33,9 @@ details:has(+ details) {
|
||||||
background-color: rgba(0,0,255,0.2);
|
background-color: rgba(0,0,255,0.2);
|
||||||
border: solid blue 1px;
|
border: solid blue 1px;
|
||||||
}
|
}
|
||||||
|
.runtimeState.plantStep:not(.active) {
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
}
|
||||||
.runtimeState.plantStep * {
|
.runtimeState.plantStep * {
|
||||||
color: grey;
|
color: grey;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ import { Dispatch, ReactElement, SetStateAction, useCallback, useEffect, useMemo
|
||||||
|
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
|
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
|
||||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
|
||||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
|
||||||
import SaveOutlinedIcon from '@mui/icons-material/SaveOutlined';
|
|
||||||
import CachedOutlinedIcon from '@mui/icons-material/CachedOutlined';
|
import CachedOutlinedIcon from '@mui/icons-material/CachedOutlined';
|
||||||
|
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
||||||
|
import SaveOutlinedIcon from '@mui/icons-material/SaveOutlined';
|
||||||
|
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||||
|
|
||||||
import { Statechart } from "@/statecharts/abstract_syntax";
|
import { Statechart } from "@/statecharts/abstract_syntax";
|
||||||
import { detectConnections } from "@/statecharts/detect_connections";
|
import { detectConnections } from "@/statecharts/detect_connections";
|
||||||
|
|
@ -18,7 +18,7 @@ import { parseStatechart } from "../statecharts/parser";
|
||||||
import { BigStep, RaisedEvent } from "../statecharts/runtime_types";
|
import { BigStep, RaisedEvent } from "../statecharts/runtime_types";
|
||||||
import { getSimTime, getWallClkDelay, TimeMode } from "../statecharts/time";
|
import { getSimTime, getWallClkDelay, TimeMode } from "../statecharts/time";
|
||||||
import { BottomPanel } from "./BottomPanel";
|
import { BottomPanel } from "./BottomPanel";
|
||||||
import { PersistentDetails } from "./PersistentDetails";
|
import { PersistentDetails, PersistentDetailsLocalStorage } from "./PersistentDetails";
|
||||||
import { digitalWatchPlant } from "./Plant/DigitalWatch/DigitalWatch";
|
import { digitalWatchPlant } from "./Plant/DigitalWatch/DigitalWatch";
|
||||||
import { dummyPlant } from "./Plant/Dummy/Dummy";
|
import { dummyPlant } from "./Plant/Dummy/Dummy";
|
||||||
import { microwavePlant } from "./Plant/Microwave/Microwave";
|
import { microwavePlant } from "./Plant/Microwave/Microwave";
|
||||||
|
|
@ -26,14 +26,11 @@ import { Plant } from "./Plant/Plant";
|
||||||
import { trafficLightPlant } from "./Plant/TrafficLight/TrafficLight";
|
import { trafficLightPlant } from "./Plant/TrafficLight/TrafficLight";
|
||||||
import { RTHistory } from "./RTHistory";
|
import { RTHistory } from "./RTHistory";
|
||||||
import { ShowAST, ShowInputEvents, ShowInternalEvents, ShowOutputEvents } from "./ShowAST";
|
import { ShowAST, ShowInputEvents, ShowInternalEvents, ShowOutputEvents } from "./ShowAST";
|
||||||
import { InsertMode } from "./TopPanel/InsertModes";
|
|
||||||
import { TopPanel } from "./TopPanel/TopPanel";
|
import { TopPanel } from "./TopPanel/TopPanel";
|
||||||
import { VisualEditor, VisualEditorState } from "./VisualEditor/VisualEditor";
|
import { VisualEditor, VisualEditorState } from "./VisualEditor/VisualEditor";
|
||||||
import { checkProperty, PropertyCheckResult } from "./check_property";
|
import { checkProperty, PropertyCheckResult } from "./check_property";
|
||||||
import { usePersistentState } from "./persistent_state";
|
|
||||||
import { useEditor } from "./useEditor";
|
import { useEditor } from "./useEditor";
|
||||||
import { useUrlHashState } from "./useUrlHashState";
|
import { useUrlHashState } from "./useUrlHashState";
|
||||||
import { formatTime } from "@/util/util";
|
|
||||||
|
|
||||||
export type EditHistory = {
|
export type EditHistory = {
|
||||||
current: VisualEditorState,
|
current: VisualEditorState,
|
||||||
|
|
@ -112,6 +109,10 @@ export function App() {
|
||||||
setInsertMode,
|
setInsertMode,
|
||||||
plantName,
|
plantName,
|
||||||
setPlantName,
|
setPlantName,
|
||||||
|
showConnections,
|
||||||
|
setShowConnections,
|
||||||
|
showProperties,
|
||||||
|
setShowProperties,
|
||||||
showExecutionTrace,
|
showExecutionTrace,
|
||||||
setShowExecutionTrace,
|
setShowExecutionTrace,
|
||||||
showPlantTrace,
|
showPlantTrace,
|
||||||
|
|
@ -417,33 +418,33 @@ export function App() {
|
||||||
style={{flex: '0 0 content', backgroundColor: ''}}
|
style={{flex: '0 0 content', backgroundColor: ''}}
|
||||||
>
|
>
|
||||||
{/* State tree */}
|
{/* State tree */}
|
||||||
<PersistentDetails localStorageKey="showStateTree" initiallyOpen={true}>
|
<PersistentDetailsLocalStorage localStorageKey="showStateTree" initiallyOpen={true}>
|
||||||
<summary>state tree</summary>
|
<summary>state tree</summary>
|
||||||
<ul>
|
<ul>
|
||||||
{ast && <ShowAST {...{...ast, trace, highlightActive}}/>}
|
{ast && <ShowAST {...{...ast, trace, highlightActive}}/>}
|
||||||
</ul>
|
</ul>
|
||||||
</PersistentDetails>
|
</PersistentDetailsLocalStorage>
|
||||||
{/* Input events */}
|
{/* Input events */}
|
||||||
<PersistentDetails localStorageKey="showInputEvents" initiallyOpen={true}>
|
<PersistentDetailsLocalStorage localStorageKey="showInputEvents" initiallyOpen={true}>
|
||||||
<summary>input events</summary>
|
<summary>input events</summary>
|
||||||
{ast && <ShowInputEvents
|
{ast && <ShowInputEvents
|
||||||
inputEvents={ast.inputEvents}
|
inputEvents={ast.inputEvents}
|
||||||
onRaise={(e,p) => onRaise("debug."+e,p)}
|
onRaise={(e,p) => onRaise("debug."+e,p)}
|
||||||
disabled={trace===null || trace.trace[trace.idx].kind === "error"}
|
disabled={trace===null || trace.trace[trace.idx].kind === "error"}
|
||||||
showKeys={showKeys}/>}
|
showKeys={showKeys}/>}
|
||||||
</PersistentDetails>
|
</PersistentDetailsLocalStorage>
|
||||||
{/* Internal events */}
|
{/* Internal events */}
|
||||||
<PersistentDetails localStorageKey="showInternalEvents" initiallyOpen={true}>
|
<PersistentDetailsLocalStorage localStorageKey="showInternalEvents" initiallyOpen={true}>
|
||||||
<summary>internal events</summary>
|
<summary>internal events</summary>
|
||||||
{ast && <ShowInternalEvents internalEvents={ast.internalEvents}/>}
|
{ast && <ShowInternalEvents internalEvents={ast.internalEvents}/>}
|
||||||
</PersistentDetails>
|
</PersistentDetailsLocalStorage>
|
||||||
{/* Output events */}
|
{/* Output events */}
|
||||||
<PersistentDetails localStorageKey="showOutputEvents" initiallyOpen={true}>
|
<PersistentDetailsLocalStorage localStorageKey="showOutputEvents" initiallyOpen={true}>
|
||||||
<summary>output events</summary>
|
<summary>output events</summary>
|
||||||
{ast && <ShowOutputEvents outputEvents={ast.outputEvents}/>}
|
{ast && <ShowOutputEvents outputEvents={ast.outputEvents}/>}
|
||||||
</PersistentDetails>
|
</PersistentDetailsLocalStorage>
|
||||||
{/* Plant */}
|
{/* Plant */}
|
||||||
<PersistentDetails localStorageKey="showPlant" initiallyOpen={true}>
|
<PersistentDetailsLocalStorage localStorageKey="showPlant" initiallyOpen={true}>
|
||||||
<summary>plant</summary>
|
<summary>plant</summary>
|
||||||
<select
|
<select
|
||||||
disabled={trace!==null}
|
disabled={trace!==null}
|
||||||
|
|
@ -458,9 +459,9 @@ export function App() {
|
||||||
{<plant.render state={plant.cleanupState(plantState)} speed={speed}
|
{<plant.render state={plant.cleanupState(plantState)} speed={speed}
|
||||||
raiseUIEvent={e => onRaise("plant.ui."+e.name, e.param)}
|
raiseUIEvent={e => onRaise("plant.ui."+e.name, e.param)}
|
||||||
/>}
|
/>}
|
||||||
</PersistentDetails>
|
</PersistentDetailsLocalStorage>
|
||||||
{/* Connections */}
|
{/* Connections */}
|
||||||
<PersistentDetails localStorageKey="showConnEditor" initiallyOpen={false}>
|
<PersistentDetails state={showConnections} setState={setShowConnections}>
|
||||||
<summary>connections</summary>
|
<summary>connections</summary>
|
||||||
<button title="auto-connect (name-based)" className={autoConnect?"active":""}
|
<button title="auto-connect (name-based)" className={autoConnect?"active":""}
|
||||||
onClick={() => setAutoConnect(c => !c)}>
|
onClick={() => setAutoConnect(c => !c)}>
|
||||||
|
|
@ -469,8 +470,13 @@ export function App() {
|
||||||
{ast && ConnEditor(ast, plant, plantConns, setPlantConns)}
|
{ast && ConnEditor(ast, plant, plantConns, setPlantConns)}
|
||||||
</PersistentDetails>
|
</PersistentDetails>
|
||||||
{/* Properties */}
|
{/* Properties */}
|
||||||
<PersistentDetails localStorageKey="showProperty" initiallyOpen={false}>
|
<details open={showProperties} onToggle={e => setShowProperties(e.newState === "open")}>
|
||||||
<summary>properties</summary>
|
<summary>properties</summary>
|
||||||
|
{plant && <div>
|
||||||
|
available signals:
|
||||||
|
|
||||||
|
{plant.signals.join(', ')}
|
||||||
|
</div>}
|
||||||
{properties.map((property, i) => {
|
{properties.map((property, i) => {
|
||||||
const result = propertyResults && propertyResults[i];
|
const result = propertyResults && propertyResults[i];
|
||||||
let violated = null, propertyError = null;
|
let violated = null, propertyError = null;
|
||||||
|
|
@ -495,7 +501,7 @@ export function App() {
|
||||||
<AddIcon fontSize="small"/> add property
|
<AddIcon fontSize="small"/> add property
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</PersistentDetails>
|
</details>
|
||||||
{/* Traces */}
|
{/* Traces */}
|
||||||
<details open={showExecutionTrace} onToggle={e => setShowExecutionTrace(e.newState === "open")}><summary>execution trace</summary>
|
<details open={showExecutionTrace} onToggle={e => setShowExecutionTrace(e.newState === "open")}><summary>execution trace</summary>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -517,9 +523,9 @@ export function App() {
|
||||||
</div>
|
</div>
|
||||||
<div className="toolbar">
|
<div className="toolbar">
|
||||||
<input id="checkbox-show-plant-items" type="checkbox" checked={showPlantTrace} onChange={e => setShowPlantTrace(e.target.checked)}/>
|
<input id="checkbox-show-plant-items" type="checkbox" checked={showPlantTrace} onChange={e => setShowPlantTrace(e.target.checked)}/>
|
||||||
<label htmlFor="checkbox-show-plant-items">show plant steps</label>
|
<label title="plant steps are steps where only the state of the plant changed" htmlFor="checkbox-show-plant-items">show plant steps</label>
|
||||||
<input id="checkbox-autoscroll" type="checkbox" checked={autoScroll} onChange={e => setAutoScroll(e.target.checked)}/>
|
<input id="checkbox-autoscroll" type="checkbox" checked={autoScroll} onChange={e => setAutoScroll(e.target.checked)}/>
|
||||||
<label htmlFor="checkbox-autoscroll">auto-scroll</label>
|
<label title="automatically scroll down event trace when new events occur" htmlFor="checkbox-autoscroll">auto-scroll</label>
|
||||||
 
|
 
|
||||||
<button title="save current trace" disabled={trace === null} onClick={() => onSaveTrace()}>
|
<button title="save current trace" disabled={trace === null} onClick={() => onSaveTrace()}>
|
||||||
<SaveOutlinedIcon fontSize="small"/> save trace
|
<SaveOutlinedIcon fontSize="small"/> save trace
|
||||||
|
|
@ -617,9 +623,9 @@ function ConnEditor(ast: Statechart, plant: Plant<any, any>, plantConns: Conns,
|
||||||
</select>
|
</select>
|
||||||
</div>)]}
|
</div>)]}
|
||||||
|
|
||||||
{/* Plant UI events can go to SC or to Plant */}
|
{/* Plant UI events typically go to the Plant */}
|
||||||
{plant.uiEvents.map(e => <div style={{width:'100%', textAlign:'right'}}>
|
{plant.uiEvents.map(e => <div style={{width:'100%', textAlign:'right'}}>
|
||||||
<label htmlFor={`select-dst-plant-ui-${e.event}`} style={{width:'50%'}}>ui.{e.event} → </label>
|
<label htmlFor={`select-dst-plant-ui-${e.event}`} style={{width:'50%', color: 'grey'}}>ui.{e.event} → </label>
|
||||||
<select id={`select-dst-plant-ui-${e.event}`}
|
<select id={`select-dst-plant-ui-${e.event}`}
|
||||||
style={{width:'50%'}}
|
style={{width:'50%'}}
|
||||||
value={plantConns['plant.ui.'+e.event]?.join('.')}
|
value={plantConns['plant.ui.'+e.event]?.join('.')}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { TraceableError } from "../statecharts/parser";
|
||||||
import "./BottomPanel.css";
|
import "./BottomPanel.css";
|
||||||
|
|
||||||
import logo from "../../artwork/logo-playful.svg";
|
import logo from "../../artwork/logo-playful.svg";
|
||||||
import { PersistentDetails } from "./PersistentDetails";
|
import { PersistentDetailsLocalStorage } from "./PersistentDetails";
|
||||||
|
|
||||||
export function BottomPanel(props: {errors: TraceableError[]}) {
|
export function BottomPanel(props: {errors: TraceableError[]}) {
|
||||||
const [greeting, setGreeting] = useState(
|
const [greeting, setGreeting] = useState(
|
||||||
|
|
@ -24,7 +24,7 @@ export function BottomPanel(props: {errors: TraceableError[]}) {
|
||||||
{greeting}
|
{greeting}
|
||||||
{props.errors.length > 0 &&
|
{props.errors.length > 0 &&
|
||||||
<div className="errorStatus">
|
<div className="errorStatus">
|
||||||
<PersistentDetails initiallyOpen={false} localStorageKey="errorsExpanded">
|
<PersistentDetailsLocalStorage initiallyOpen={false} localStorageKey="errorsExpanded">
|
||||||
<summary>{props.errors.length} errors</summary>
|
<summary>{props.errors.length} errors</summary>
|
||||||
<div style={{maxHeight: '25vh', overflow: 'auto'}}>
|
<div style={{maxHeight: '25vh', overflow: 'auto'}}>
|
||||||
{props.errors.map(({message, shapeUid})=>
|
{props.errors.map(({message, shapeUid})=>
|
||||||
|
|
@ -32,7 +32,7 @@ export function BottomPanel(props: {errors: TraceableError[]}) {
|
||||||
{shapeUid}: {message}
|
{shapeUid}: {message}
|
||||||
</div>)}
|
</div>)}
|
||||||
</div>
|
</div>
|
||||||
</PersistentDetails>
|
</PersistentDetailsLocalStorage>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>;
|
</div>;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { usePersistentState } from "@/App/persistent_state"
|
import { usePersistentState } from "@/App/persistent_state"
|
||||||
import { DetailsHTMLAttributes, PropsWithChildren } from "react";
|
import { DetailsHTMLAttributes, Dispatch, PropsWithChildren, SetStateAction } from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
localStorageKey: string,
|
localStorageKey: string,
|
||||||
|
|
@ -7,9 +7,15 @@ type Props = {
|
||||||
} & DetailsHTMLAttributes<HTMLDetailsElement>;
|
} & DetailsHTMLAttributes<HTMLDetailsElement>;
|
||||||
|
|
||||||
// A <details> node that remembers whether it was open or closed by storing that state in localStorage.
|
// A <details> node that remembers whether it was open or closed by storing that state in localStorage.
|
||||||
export function PersistentDetails({localStorageKey, initiallyOpen, children, ...rest}: PropsWithChildren<Props>) {
|
export function PersistentDetailsLocalStorage({localStorageKey, initiallyOpen, children, ...rest}: PropsWithChildren<Props>) {
|
||||||
const [open, setOpen] = usePersistentState(localStorageKey, initiallyOpen);
|
const [open, setOpen] = usePersistentState(localStorageKey, initiallyOpen);
|
||||||
return <details open={open} onToggle={e => setOpen(e.newState === "open")} {...rest}>
|
return <details open={open} onToggle={e => setOpen(e.newState === "open")} {...rest}>
|
||||||
{children}
|
{children}
|
||||||
</details>;
|
</details>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function PersistentDetails({state, setState, children, ...rest}: PropsWithChildren<{state: boolean, setState: Dispatch<SetStateAction<boolean>>}>) {
|
||||||
|
return <details open={state} onToggle={e => setState(e.newState === "open")} {...rest}>
|
||||||
|
{children}
|
||||||
|
</details>;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,4 +156,21 @@ export const digitalWatchPlant = makeStatechartPlant({
|
||||||
{ kind: "event", event: "bottomRightMouseUp" },
|
{ kind: "event", event: "bottomRightMouseUp" },
|
||||||
{ kind: "event", event: "bottomLeftMouseUp" },
|
{ kind: "event", event: "bottomLeftMouseUp" },
|
||||||
],
|
],
|
||||||
|
signals: [
|
||||||
|
"lightOn",
|
||||||
|
"beep",
|
||||||
|
"alarmOn",
|
||||||
|
"displayingTime",
|
||||||
|
"displayingAlarm",
|
||||||
|
"displayingChrono",
|
||||||
|
"hideH",
|
||||||
|
"hideM",
|
||||||
|
"hideS",
|
||||||
|
|
||||||
|
// these properties are true for as long as the mouse button is down:
|
||||||
|
"topLeftPressed",
|
||||||
|
"topRightPressed",
|
||||||
|
"bottomRightPressed",
|
||||||
|
"bottomLeftPressed",
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,5 @@ export const dummyPlant: Plant<{}, {}> = {
|
||||||
execution: dummyExecution,
|
execution: dummyExecution,
|
||||||
cleanupState: ({}) => ({}),
|
cleanupState: ({}) => ({}),
|
||||||
render: ({}) => <></>,
|
render: ({}) => <></>,
|
||||||
|
signals: [],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,16 @@ const microwavePlantSpec: StatechartPlantSpec<MicrowaveState> = {
|
||||||
{kind: "event", event: "incTimeMouseDown"},
|
{kind: "event", event: "incTimeMouseDown"},
|
||||||
{kind: "event", event: "incTimeMouseUp"},
|
{kind: "event", event: "incTimeMouseUp"},
|
||||||
],
|
],
|
||||||
|
signals: [
|
||||||
|
"bellRinging",
|
||||||
|
"magnetronRunning",
|
||||||
|
"doorOpen",
|
||||||
|
|
||||||
|
// these booleans are true for as long as the respective button is pressed (i.e., mouse button is down)
|
||||||
|
"startPressed",
|
||||||
|
"stopPressed",
|
||||||
|
"incTimePressed",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const microwavePlant = makeStatechartPlant(microwavePlantSpec);
|
export const microwavePlant = makeStatechartPlant(microwavePlantSpec);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ export type Plant<StateType, CleanStateType> = {
|
||||||
inputEvents: EventTrigger[];
|
inputEvents: EventTrigger[];
|
||||||
outputEvents: EventTrigger[];
|
outputEvents: EventTrigger[];
|
||||||
|
|
||||||
|
signals: string[]; // signal names. all signals are booleans.
|
||||||
|
|
||||||
execution: TimedReactive<StateType>;
|
execution: TimedReactive<StateType>;
|
||||||
cleanupState: (state: StateType) => CleanStateType;
|
cleanupState: (state: StateType) => CleanStateType;
|
||||||
render: (props: PlantRenderProps<CleanStateType>) => ReactNode;
|
render: (props: PlantRenderProps<CleanStateType>) => ReactNode;
|
||||||
|
|
@ -59,9 +61,10 @@ export type StatechartPlantSpec<CleanStateType> = {
|
||||||
ast: Statechart,
|
ast: Statechart,
|
||||||
cleanupState: (rtConfig: RT_Statechart) => CleanStateType,
|
cleanupState: (rtConfig: RT_Statechart) => CleanStateType,
|
||||||
render: (props: PlantRenderProps<CleanStateType>) => ReactNode,
|
render: (props: PlantRenderProps<CleanStateType>) => ReactNode,
|
||||||
|
signals: string[],
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeStatechartPlant<CleanStateType>({uiEvents, ast, cleanupState, render}: StatechartPlantSpec<CleanStateType>): Plant<BigStep, CleanStateType> {
|
export function makeStatechartPlant<CleanStateType>({uiEvents, ast, cleanupState, render, signals}: StatechartPlantSpec<CleanStateType>): Plant<BigStep, CleanStateType> {
|
||||||
return {
|
return {
|
||||||
uiEvents,
|
uiEvents,
|
||||||
inputEvents: ast.inputEvents,
|
inputEvents: ast.inputEvents,
|
||||||
|
|
@ -69,6 +72,7 @@ export function makeStatechartPlant<CleanStateType>({uiEvents, ast, cleanupState
|
||||||
execution: statechartExecution(ast),
|
execution: statechartExecution(ast),
|
||||||
cleanupState,
|
cleanupState,
|
||||||
render,
|
render,
|
||||||
|
signals,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,13 @@ const trafficLightPlantSpec: StatechartPlantSpec<TrafficLightState> = {
|
||||||
uiEvents: [
|
uiEvents: [
|
||||||
{kind: "event", event: "policeInterrupt"},
|
{kind: "event", event: "policeInterrupt"},
|
||||||
],
|
],
|
||||||
|
signals: [
|
||||||
|
"redOn",
|
||||||
|
"yellowOn",
|
||||||
|
"greenOn",
|
||||||
|
"timerGreen",
|
||||||
|
"timerValue",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
export const trafficLightPlant = makeStatechartPlant(trafficLightPlantSpec);
|
export const trafficLightPlant = makeStatechartPlant(trafficLightPlantSpec);
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ function RTEventParam(props: {param?: any}) {
|
||||||
|
|
||||||
export const RTHistoryItem = memo(function RTHistoryItem({ast, idx, item, prevItem, isPlantStep, active, onMouseDown, propertyStatus}: {idx: number, ast: Statechart, item: TraceItem, prevItem?: TraceItem, isPlantStep: boolean, active: boolean, onMouseDown: (idx: number, timestamp: number) => void, propertyStatus: PropertyStatus}) {
|
export const RTHistoryItem = memo(function RTHistoryItem({ast, idx, item, prevItem, isPlantStep, active, onMouseDown, propertyStatus}: {idx: number, ast: Statechart, item: TraceItem, prevItem?: TraceItem, isPlantStep: boolean, active: boolean, onMouseDown: (idx: number, timestamp: number) => void, propertyStatus: PropertyStatus}) {
|
||||||
if (item.kind === "bigstep") {
|
if (item.kind === "bigstep") {
|
||||||
|
const outputEvents = isPlantStep ? item.state.plant.outputEvents : item.state.sc.outputEvents;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const newStates = item.state.sc.mode.difference(prevItem?.state.sc.mode || new Set());
|
const newStates = item.state.sc.mode.difference(prevItem?.state.sc.mode || new Set());
|
||||||
return <div
|
return <div
|
||||||
|
|
@ -104,8 +105,8 @@ export const RTHistoryItem = memo(function RTHistoryItem({ast, idx, item, prevIt
|
||||||
</div>
|
</div>
|
||||||
<ShowMode mode={newStates} statechart={ast}/>
|
<ShowMode mode={newStates} statechart={ast}/>
|
||||||
<ShowEnvironment environment={item.state.sc.environment}/>
|
<ShowEnvironment environment={item.state.sc.environment}/>
|
||||||
{item.state.sc.outputEvents.length>0 && <>^
|
{outputEvents.length>0 && <>^
|
||||||
{item.state.sc.outputEvents.map((e:RaisedEvent) => <span className="outputEvent">{e.name}<RTEventParam param={e.param}/></span>)}
|
{outputEvents.map((e:RaisedEvent) => <span className="outputEvent">{e.name}<RTEventParam param={e.param}/></span>)}
|
||||||
</>}
|
</>}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { Conns } from "@/statecharts/timed_reactive";
|
||||||
export function useUrlHashState(editorState: VisualEditorState | null, setEditHistory: Dispatch<SetStateAction<EditHistory|null>>) {
|
export function useUrlHashState(editorState: VisualEditorState | null, setEditHistory: Dispatch<SetStateAction<EditHistory|null>>) {
|
||||||
|
|
||||||
// i should probably put all these things into a single object, the 'app state'...
|
// i should probably put all these things into a single object, the 'app state'...
|
||||||
const [autoScroll, setAutoScroll] = useState(true);
|
const [autoScroll, setAutoScroll] = useState(false);
|
||||||
const [autoConnect, setAutoConnect] = useState(true);
|
const [autoConnect, setAutoConnect] = useState(true);
|
||||||
const [plantConns, setPlantConns] = useState<Conns>({});
|
const [plantConns, setPlantConns] = useState<Conns>({});
|
||||||
const [showKeys, setShowKeys] = useState(true);
|
const [showKeys, setShowKeys] = useState(true);
|
||||||
|
|
@ -16,6 +16,8 @@ export function useUrlHashState(editorState: VisualEditorState | null, setEditHi
|
||||||
const [insertMode, setInsertMode] = useState<InsertMode>("and");
|
const [insertMode, setInsertMode] = useState<InsertMode>("and");
|
||||||
const [plantName, setPlantName] = useState("dummy");
|
const [plantName, setPlantName] = useState("dummy");
|
||||||
|
|
||||||
|
const [showConnections, setShowConnections] = useState(false);
|
||||||
|
const [showProperties, setShowProperties] = useState(false);
|
||||||
const [showExecutionTrace, setShowExecutionTrace] = useState(true);
|
const [showExecutionTrace, setShowExecutionTrace] = useState(true);
|
||||||
const [showPlantTrace, setShowPlantTrace] = useState(false);
|
const [showPlantTrace, setShowPlantTrace] = useState(false);
|
||||||
const [properties, setProperties] = useState<string[]>([]);
|
const [properties, setProperties] = useState<string[]>([]);
|
||||||
|
|
@ -82,6 +84,12 @@ export function useUrlHashState(editorState: VisualEditorState | null, setEditHi
|
||||||
if (recoveredState.insertMode !== undefined) {
|
if (recoveredState.insertMode !== undefined) {
|
||||||
setInsertMode(recoveredState.insertMode);
|
setInsertMode(recoveredState.insertMode);
|
||||||
}
|
}
|
||||||
|
if (recoveredState.showConnections !== undefined) {
|
||||||
|
setShowConnections(recoveredState.showConnections);
|
||||||
|
}
|
||||||
|
if (recoveredState.showProperties !== undefined) {
|
||||||
|
setShowProperties(recoveredState.showProperties);
|
||||||
|
}
|
||||||
if (recoveredState.showExecutionTrace !== undefined) {
|
if (recoveredState.showExecutionTrace !== undefined) {
|
||||||
setShowExecutionTrace(recoveredState.showExecutionTrace);
|
setShowExecutionTrace(recoveredState.showExecutionTrace);
|
||||||
}
|
}
|
||||||
|
|
@ -123,6 +131,8 @@ export function useUrlHashState(editorState: VisualEditorState | null, setEditHi
|
||||||
insertMode,
|
insertMode,
|
||||||
plantName,
|
plantName,
|
||||||
editorState,
|
editorState,
|
||||||
|
showConnections,
|
||||||
|
showProperties,
|
||||||
showExecutionTrace,
|
showExecutionTrace,
|
||||||
showPlantTrace,
|
showPlantTrace,
|
||||||
properties,
|
properties,
|
||||||
|
|
@ -149,6 +159,8 @@ export function useUrlHashState(editorState: VisualEditorState | null, setEditHi
|
||||||
zoom,
|
zoom,
|
||||||
insertMode,
|
insertMode,
|
||||||
plantName,
|
plantName,
|
||||||
|
showConnections,
|
||||||
|
showProperties,
|
||||||
showExecutionTrace,
|
showExecutionTrace,
|
||||||
showPlantTrace,
|
showPlantTrace,
|
||||||
properties,
|
properties,
|
||||||
|
|
@ -171,6 +183,10 @@ export function useUrlHashState(editorState: VisualEditorState | null, setEditHi
|
||||||
setInsertMode,
|
setInsertMode,
|
||||||
plantName,
|
plantName,
|
||||||
setPlantName,
|
setPlantName,
|
||||||
|
showConnections,
|
||||||
|
setShowConnections,
|
||||||
|
showProperties,
|
||||||
|
setShowProperties,
|
||||||
showExecutionTrace,
|
showExecutionTrace,
|
||||||
setShowExecutionTrace,
|
setShowExecutionTrace,
|
||||||
showPlantTrace,
|
showPlantTrace,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue