pseudo-states appear to be working + variables only exist within the scope where they are created
This commit is contained in:
parent
db1479bfc4
commit
d4930eb13d
22 changed files with 742 additions and 569 deletions
|
|
@ -1,28 +1,3 @@
|
|||
/* .layoutVertical {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
.panel {
|
||||
height: 1.5rem;
|
||||
background-color: lightgrey;
|
||||
}
|
||||
.layout {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: calc(100vh - 1.5rem);
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
flex: 0 0 content;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.content {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
} */
|
||||
|
||||
details {
|
||||
padding-left: 20;
|
||||
/* margin-left: 30; */
|
||||
|
|
@ -68,4 +43,10 @@ summary {
|
|||
}
|
||||
.toolbar > input {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
button.active {
|
||||
border: solid blue 2px;
|
||||
background-color: rgba(0,0,255,0.2);
|
||||
color: black;
|
||||
}
|
||||
|
|
@ -12,9 +12,10 @@ import "./App.css";
|
|||
import { Box, Stack } from "@mui/material";
|
||||
import { TopPanel } from "./TopPanel";
|
||||
import { RTHistory } from "./RTHistory";
|
||||
import { AST } from "./AST";
|
||||
import { ShowAST } from "./ShowAST";
|
||||
import { TraceableError } from "../statecharts/parser";
|
||||
import { getKeyHandler } from "./shortcut_handler";
|
||||
import { BottomPanel } from "./BottomPanel";
|
||||
|
||||
export function App() {
|
||||
const [mode, setMode] = useState<InsertMode>("and");
|
||||
|
|
@ -106,7 +107,7 @@ export function App() {
|
|||
{...{ast, time, setTime, onInit, onClear, onRaise, mode, setMode}}
|
||||
/>
|
||||
</Box>
|
||||
<Stack direction="row" sx={{height:'calc(100vh - 32px)'}}>
|
||||
<Stack direction="row" sx={{height:'calc(100vh - 64px)'}}>
|
||||
{/* main */}
|
||||
<Box sx={{flexGrow:1, overflow:'auto'}}>
|
||||
<VisualEditor {...{ast, setAST, rt: rt.at(rtIdx!), setRT, errors, setErrors, mode}}/>
|
||||
|
|
@ -117,14 +118,17 @@ export function App() {
|
|||
borderLeft: 1,
|
||||
borderColor: "divider",
|
||||
flex: '0 0 content',
|
||||
paddingRight: 1,
|
||||
paddingLeft: 1,
|
||||
// paddingRight: 1,
|
||||
// paddingLeft: 1,
|
||||
}}>
|
||||
<AST {...{...ast, rt: rt.at(rtIdx!)}}/>
|
||||
<ShowAST {...{...ast, rt: rt.at(rtIdx!)}}/>
|
||||
<br/>
|
||||
<RTHistory {...{ast, rt, rtIdx, setTime, setRTIdx}}/>
|
||||
</Box>
|
||||
</Stack>
|
||||
<Box>
|
||||
<BottomPanel {...{errors}}/>
|
||||
</Box>
|
||||
</Stack>;
|
||||
}
|
||||
|
||||
|
|
|
|||
3
src/App/BottomPanel.css
Normal file
3
src/App/BottomPanel.css
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
.errorStatus {
|
||||
color: rgb(230,0,0);
|
||||
}
|
||||
10
src/App/BottomPanel.tsx
Normal file
10
src/App/BottomPanel.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { TraceableError } from "../statecharts/parser";
|
||||
|
||||
import "./BottomPanel.css";
|
||||
|
||||
export function BottomPanel(props: {errors: TraceableError[]}) {
|
||||
return <div className="toolbar">
|
||||
<div className="errorStatus">{
|
||||
props.errors.length>0 && <>{props.errors.length} errors {props.errors.map(({message})=>message).join(',')}</>}</div>
|
||||
</div>;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { ConcreteState, stateDescription, Transition } from "../statecharts/abstract_syntax";
|
||||
import { ConcreteState, PseudoState, stateDescription, Transition } from "../statecharts/abstract_syntax";
|
||||
import { Action, Expression } from "../statecharts/label_ast";
|
||||
import { RT_Statechart } from "../statecharts/runtime_types";
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ export function ShowAction(props: {action: Action}) {
|
|||
}
|
||||
}
|
||||
|
||||
export function AST(props: {root: ConcreteState, transitions: Map<string, Transition[]>, rt: RT_Statechart | undefined}) {
|
||||
export function ShowAST(props: {root: ConcreteState | PseudoState, transitions: Map<string, Transition[]>, rt: RT_Statechart | undefined}) {
|
||||
const description = stateDescription(props.root);
|
||||
const outgoing = props.transitions.get(props.root.uid) || [];
|
||||
|
||||
|
|
@ -49,9 +49,9 @@ export function AST(props: {root: ConcreteState, transitions: Map<string, Transi
|
|||
<div> exit / <ShowAction action={action}/></div>
|
||||
)
|
||||
}
|
||||
{props.root.children.length>0 &&
|
||||
{props.root.kind !== "pseudo" && props.root.children.length>0 &&
|
||||
props.root.children.map(child =>
|
||||
<AST root={child} transitions={props.transitions} rt={props.rt} />
|
||||
<ShowAST root={child} transitions={props.transitions} rt={props.rt} />
|
||||
)
|
||||
}
|
||||
{outgoing.length>0 &&
|
||||
|
|
@ -10,10 +10,11 @@ import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
|||
import BoltIcon from '@mui/icons-material/Bolt';
|
||||
import SkipNextIcon from '@mui/icons-material/SkipNext';
|
||||
import TrendingFlatIcon from '@mui/icons-material/TrendingFlat';
|
||||
import AccessAlarmIcon from '@mui/icons-material/AccessAlarm';
|
||||
import StopIcon from '@mui/icons-material/Stop';
|
||||
|
||||
import { formatTime } from "./util";
|
||||
import { InsertMode } from "../VisualEditor/VisualEditor";
|
||||
import { DiamondShape } from "../VisualEditor/RountangleSVG";
|
||||
|
||||
export type TopPanelProps = {
|
||||
rt?: BigStep,
|
||||
|
|
@ -33,16 +34,21 @@ function RountangleIcon(props: {kind: string}) {
|
|||
x={1} y={1}
|
||||
width={18} height={18}
|
||||
className={`rountangle ${props.kind}`}
|
||||
style={props.kind === "or" ? {strokeDasharray: '3 2'}: {}}
|
||||
style={{...(props.kind === "or" ? {strokeDasharray: '3 2'}: {}), strokeWidth: 1.2}}
|
||||
/>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
function PseudoStateIcon(props: {}) {
|
||||
return <svg width={20} height={20}>
|
||||
<g transform="translate(2,1)">
|
||||
<DiamondShape geometry={{topLeft:{x:0,y:0}, size:{x:16,y:18}}} extraAttrs={{className: 'rountangle pseudo'}}/>
|
||||
</g>
|
||||
const w=20, h=20;
|
||||
return <svg width={w} height={h}>
|
||||
<polygon
|
||||
points={`
|
||||
${w/2} ${1},
|
||||
${w-1} ${h/2},
|
||||
${w/2} ${h-1},
|
||||
${1} ${h/2},
|
||||
`} fill="white" stroke="black" strokeWidth={1.2}/>
|
||||
</svg>;
|
||||
}
|
||||
|
||||
|
|
@ -101,28 +107,29 @@ export function TopPanel({rt, time, setTime, onInit, onClear, onRaise, ast, mode
|
|||
|
||||
return <>
|
||||
<div className="toolbar">
|
||||
{([
|
||||
["and", "AND-states", <RountangleIcon kind="and"/>],
|
||||
["or", "OR-states", <RountangleIcon kind="or"/>],
|
||||
["pseudo", "pseudo-states", <PseudoStateIcon/>],
|
||||
["transition", "transitions", <TrendingFlatIcon fontSize="small"/>],
|
||||
["text", "text", <>T</>],
|
||||
] as [InsertMode, string, ReactElement][]).map(([m, hint, buttonTxt]) =>
|
||||
<button
|
||||
title={"insert "+hint}
|
||||
disabled={mode===m}
|
||||
onClick={() => setMode(m)}
|
||||
>{buttonTxt}</button>)}
|
||||
</div>
|
||||
 
|
||||
<div className="toolbar">
|
||||
<button title="(re)initialize simulation" onClick={onInit} ><CachedIcon fontSize="small"/><PlayArrowIcon fontSize="small"/></button>
|
||||
<button title="clear the simulation" onClick={onClear} disabled={!rt}><ClearIcon fontSize="small"/></button>
|
||||
{([
|
||||
["and", "AND-states", <RountangleIcon kind="and"/>],
|
||||
["or", "OR-states", <RountangleIcon kind="or"/>],
|
||||
["pseudo", "pseudo-states", <PseudoStateIcon/>],
|
||||
["transition", "transitions", <TrendingFlatIcon fontSize="small"/>],
|
||||
["text", "text", <> T </>],
|
||||
] as [InsertMode, string, ReactElement][]).map(([m, hint, buttonTxt]) =>
|
||||
<button
|
||||
title={"insert "+hint}
|
||||
disabled={mode===m}
|
||||
className={mode===m ? "active":""}
|
||||
onClick={() => setMode(m)}
|
||||
>{buttonTxt}</button>)}
|
||||
|
||||
 
|
||||
|
||||
<button title="pause the simulation" disabled={!rt || time.kind==="paused"} onClick={() => onChangePaused(true, performance.now())}><PauseIcon fontSize="small"/></button>
|
||||
<button title="run the simulation in real time" disabled={!rt || time.kind==="realtime"} onClick={() => onChangePaused(false, performance.now())}><PlayArrowIcon fontSize="small"/></button>
|
||||
<button title="(re)initialize simulation" onClick={onInit} ><PlayArrowIcon fontSize="small"/><CachedIcon fontSize="small"/></button>
|
||||
<button title="clear the simulation" onClick={onClear} disabled={!rt}><StopIcon fontSize="small"/></button>
|
||||
|
||||
 
|
||||
|
||||
<button title="pause the simulation" disabled={!rt || time.kind==="paused"} className={(rt && time.kind==="paused") ? "active":""} onClick={() => onChangePaused(true, performance.now())}><PauseIcon fontSize="small"/></button>
|
||||
<button title="run the simulation in real time" disabled={!rt || time.kind==="realtime"} className={(rt && time.kind==="realtime") ? "active":""} onClick={() => onChangePaused(false, performance.now())}><PlayArrowIcon fontSize="small"/></button>
|
||||
|
||||
{/* <ToggleButtonGroup value={time.kind} exclusive onChange={(_,newValue) => onChangePaused(newValue==="paused", performance.now())} size="small">
|
||||
<ToggleButton disableRipple value="paused" disabled={!rt}><PauseIcon/></ToggleButton>
|
||||
|
|
@ -155,12 +162,15 @@ export function TopPanel({rt, time, setTime, onInit, onClear, onRaise, ast, mode
|
|||
return {kind: "realtime", scale: time.scale, since: {simtime: nextTimedTransition[0], wallclktime: now}};
|
||||
}
|
||||
});
|
||||
}}><SkipNextIcon fontSize="small"/></button>
|
||||
}}><SkipNextIcon fontSize="small"/><AccessAlarmIcon fontSize="small"/></button>
|
||||
|
||||
 
|
||||
|
||||
{ast.inputEvents &&
|
||||
<>
|
||||
{ast.inputEvents.map(({event, paramName}) =>
|
||||
<> <button title={`raise input event '${event}'`} disabled={!rt} onClick={() => {
|
||||
<><button title={`raise input event '${event}'`} disabled={!rt} onClick={() => {
|
||||
// @ts-ignore
|
||||
const param = document.getElementById(`input-${event}-param`)?.value;
|
||||
let paramParsed;
|
||||
try {
|
||||
|
|
@ -176,7 +186,7 @@ export function TopPanel({rt, time, setTime, onInit, onClear, onRaise, ast, mode
|
|||
}}>
|
||||
<BoltIcon fontSize="small"/>
|
||||
{event}
|
||||
</button>{paramName && <><input id={`input-${event}-param`} style={{width: 20}} placeholder={paramName}/></>}</>)}
|
||||
</button>{paramName && <><input id={`input-${event}-param`} style={{width: 20}} placeholder={paramName}/></>} </>)}
|
||||
</>
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue