progress bar shows how long until next timer elapse
This commit is contained in:
parent
bdc2a66b1c
commit
632cf9b542
3 changed files with 28 additions and 9 deletions
|
|
@ -17,7 +17,6 @@ import { useUrlHashState } from "../hooks/useUrlHashState";
|
||||||
import { plants } from "./plants";
|
import { plants } from "./plants";
|
||||||
import { emptyState } from "@/statecharts/concrete_syntax";
|
import { emptyState } from "@/statecharts/concrete_syntax";
|
||||||
import { ModalOverlay } from "./Modals/ModalOverlay";
|
import { ModalOverlay } from "./Modals/ModalOverlay";
|
||||||
import { usePersistentState } from "@/hooks/usePersistentState";
|
|
||||||
|
|
||||||
export type EditHistory = {
|
export type EditHistory = {
|
||||||
current: VisualEditorState,
|
current: VisualEditorState,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import { Dispatch, memo, SetStateAction, useCallback, useEffect } from "react";
|
||||||
import { KeyInfoHidden, KeyInfoVisible } from "./KeyInfo";
|
import { KeyInfoHidden, KeyInfoVisible } from "./KeyInfo";
|
||||||
import { setRealtime, TimeMode } from "@/statecharts/time";
|
import { setRealtime, TimeMode } from "@/statecharts/time";
|
||||||
|
|
||||||
|
import SpeedIcon from '@mui/icons-material/Speed';
|
||||||
|
|
||||||
export const SpeedControl = memo(function SpeedControl({showKeys, timescale, setTimescale, setTime}: {showKeys: boolean, timescale: number, setTimescale: Dispatch<SetStateAction<number>>, setTime: Dispatch<SetStateAction<TimeMode>>}) {
|
export const SpeedControl = memo(function SpeedControl({showKeys, timescale, setTimescale, setTime}: {showKeys: boolean, timescale: number, setTimescale: Dispatch<SetStateAction<number>>, setTime: Dispatch<SetStateAction<TimeMode>>}) {
|
||||||
|
|
||||||
const onTimeScaleChange = useCallback((newValue: string, wallclktime: number) => {
|
const onTimeScaleChange = useCallback((newValue: string, wallclktime: number) => {
|
||||||
|
|
@ -51,7 +53,7 @@ export const SpeedControl = memo(function SpeedControl({showKeys, timescale, set
|
||||||
|
|
||||||
const KeyInfo = showKeys ? KeyInfoVisible : KeyInfoHidden;
|
const KeyInfo = showKeys ? KeyInfoVisible : KeyInfoHidden;
|
||||||
return <>
|
return <>
|
||||||
<label htmlFor="number-timescale">speed</label>
|
<label htmlFor="number-timescale"><SpeedIcon fontSize="small"/></label>
|
||||||
<KeyInfo keyInfo={<kbd>S</kbd>}>
|
<KeyInfo keyInfo={<kbd>S</kbd>}>
|
||||||
<button title="slower" onClick={onSlower}>÷2</button>
|
<button title="slower" onClick={onSlower}>÷2</button>
|
||||||
</KeyInfo>
|
</KeyInfo>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Dispatch, memo, ReactElement, SetStateAction, useCallback, useEffect, useState } from "react";
|
import { Dispatch, memo, ReactElement, SetStateAction, useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { TimerElapseEvent, Timers } from "../../statecharts/runtime_types";
|
import { TimerElapseEvent, Timers } from "../../statecharts/runtime_types";
|
||||||
import { getSimTime, setPaused, setRealtime, TimeMode } from "../../statecharts/time";
|
import { getSimTime, setPaused, setRealtime, TimeMode } from "../../statecharts/time";
|
||||||
import { InsertMode } from "./InsertModes";
|
import { InsertMode } from "./InsertModes";
|
||||||
|
|
@ -13,6 +13,9 @@ import DarkModeIcon from '@mui/icons-material/DarkMode';
|
||||||
import LightModeIcon from '@mui/icons-material/LightMode';
|
import LightModeIcon from '@mui/icons-material/LightMode';
|
||||||
import BrightnessAutoIcon from '@mui/icons-material/BrightnessAuto';
|
import BrightnessAutoIcon from '@mui/icons-material/BrightnessAuto';
|
||||||
|
|
||||||
|
import SpeedIcon from '@mui/icons-material/Speed';
|
||||||
|
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||||
|
|
||||||
import AccessAlarmIcon from '@mui/icons-material/AccessAlarm';
|
import AccessAlarmIcon from '@mui/icons-material/AccessAlarm';
|
||||||
import CachedIcon from '@mui/icons-material/Cached';
|
import CachedIcon from '@mui/icons-material/Cached';
|
||||||
import InfoOutlineIcon from '@mui/icons-material/InfoOutline';
|
import InfoOutlineIcon from '@mui/icons-material/InfoOutline';
|
||||||
|
|
@ -52,7 +55,7 @@ export type TopPanelProps = {
|
||||||
const ShortCutShowKeys = <kbd>~</kbd>;
|
const ShortCutShowKeys = <kbd>~</kbd>;
|
||||||
|
|
||||||
export const TopPanel = memo(function TopPanel({trace, time, setTime, onUndo, onRedo, onRotate, onInit, onClear, onBack, insertMode, setInsertMode, setModal, zoom, setZoom, showKeys, setShowKeys, editHistory}: TopPanelProps) {
|
export const TopPanel = memo(function TopPanel({trace, time, setTime, onUndo, onRedo, onRotate, onInit, onClear, onBack, insertMode, setInsertMode, setModal, zoom, setZoom, showKeys, setShowKeys, editHistory}: TopPanelProps) {
|
||||||
const [displayTime, setDisplayTime] = useState("0.000");
|
const [displayTime, setDisplayTime] = useState(0);
|
||||||
const [timescale, setTimescale] = usePersistentState("timescale", 1);
|
const [timescale, setTimescale] = usePersistentState("timescale", 1);
|
||||||
|
|
||||||
const config = trace && trace.trace[trace.idx];
|
const config = trace && trace.trace[trace.idx];
|
||||||
|
|
@ -62,9 +65,16 @@ export const TopPanel = memo(function TopPanel({trace, time, setTime, onUndo, on
|
||||||
const updateDisplayedTime = useCallback(() => {
|
const updateDisplayedTime = useCallback(() => {
|
||||||
const now = Math.round(performance.now());
|
const now = Math.round(performance.now());
|
||||||
const timeMs = getSimTime(time, now);
|
const timeMs = getSimTime(time, now);
|
||||||
setDisplayTime(formatTime(timeMs));
|
setDisplayTime((timeMs));
|
||||||
}, [time, setDisplayTime]);
|
}, [time, setDisplayTime]);
|
||||||
|
|
||||||
|
const formattedDisplayTime = useMemo(() => formatTime(displayTime), [displayTime]);
|
||||||
|
|
||||||
|
// const lastSimTime = useMemo(() => time.kind === "realtime" ? time.since.simtime : time.simtime, [time]);
|
||||||
|
|
||||||
|
const lastSimTime = config?.simtime || 0;
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// This has no effect on statechart execution. In between events, the statechart is doing nothing. However, by updating the displayed time, we give the illusion of continuous progress.
|
// This has no effect on statechart execution. In between events, the statechart is doing nothing. However, by updating the displayed time, we give the illusion of continuous progress.
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
|
|
@ -105,6 +115,9 @@ export const TopPanel = memo(function TopPanel({trace, time, setTime, onUndo, on
|
||||||
}
|
}
|
||||||
}, [nextTimedTransition, setTime]);
|
}, [nextTimedTransition, setTime]);
|
||||||
|
|
||||||
|
|
||||||
|
console.log({lastSimTime, displayTime, nxt: nextTimedTransition?.[0]});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onKeyDown = (e: KeyboardEvent) => {
|
const onKeyDown = (e: KeyboardEvent) => {
|
||||||
// don't capture keyboard events when focused on an input element:
|
// don't capture keyboard events when focused on an input element:
|
||||||
|
|
@ -228,15 +241,20 @@ export const TopPanel = memo(function TopPanel({trace, time, setTime, onUndo, on
|
||||||
{/* time, next */}
|
{/* time, next */}
|
||||||
<div className="toolbarGroup">
|
<div className="toolbarGroup">
|
||||||
<div className="toolbarGroup">
|
<div className="toolbarGroup">
|
||||||
<label htmlFor="time">time (s)</label>
|
<label htmlFor="time"><AccessTimeIcon fontSize="small"/></label>
|
||||||
<input title="the current simulated time" id="time" disabled={!config} value={displayTime} readOnly={true} className="readonlyTextBox" />
|
<progress style={{position:'absolute', width: 60, marginTop: 23, height: 2, background: 'rgba(0,0,0,0)', border: 0, accentColor: 'var(--accent-border-color)', appearance: 'none'}} max={1} value={(displayTime-lastSimTime)/((nextTimedTransition?.[0]||Infinity)-lastSimTime)}/>
|
||||||
|
<input title="the current simulated time" id="time" disabled={!config} value={formattedDisplayTime} readOnly={true} className="readonlyTextBox" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
 
|
 
|
||||||
<div className="toolbarGroup">
|
<div className="toolbarGroup">
|
||||||
<label htmlFor="next-timeout">next (s)</label>
|
<label htmlFor="next-timeout"><AccessAlarmIcon fontSize="small"/></label>
|
||||||
<input title="next point in simulated time where a timed transition may fire" id="next-timeout" disabled={!config} value={nextTimedTransition ? formatTime(nextTimedTransition[0]) : '+inf'} readOnly={true} className="readonlyTextBox"/>
|
<input title="next point in simulated time where a timed transition may fire" id="next-timeout" disabled={!config} value={nextTimedTransition ? formatTime(nextTimedTransition[0]) : '+inf'} readOnly={true} className="readonlyTextBox"/>
|
||||||
<KeyInfo keyInfo={<kbd>Tab</kbd>}>
|
<KeyInfo keyInfo={<kbd>Tab</kbd>}>
|
||||||
<button title="advance time just enough for the next timer to elapse" disabled={nextTimedTransition===undefined} onClick={onSkip}><SkipNextIcon fontSize="small"/><AccessAlarmIcon fontSize="small"/></button>
|
<button title="advance time just enough for the next timer to elapse" disabled={nextTimedTransition===undefined} onClick={onSkip}>
|
||||||
|
<SkipNextIcon fontSize="small"/>
|
||||||
|
</button>
|
||||||
</KeyInfo>
|
</KeyInfo>
|
||||||
 
|
 
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue