diff --git a/src/App/App.tsx b/src/App/App.tsx
index 26e6927..47743f3 100644
--- a/src/App/App.tsx
+++ b/src/App/App.tsx
@@ -184,7 +184,7 @@ export function App() {
flexGrow:1,
overflow:'auto',
}}>
-
+
{/* right sidebar */}
diff --git a/src/App/TextDialog.tsx b/src/App/TextDialog.tsx
new file mode 100644
index 0000000..110a789
--- /dev/null
+++ b/src/App/TextDialog.tsx
@@ -0,0 +1,26 @@
+import { Dispatch, ReactElement, SetStateAction, useState } from "react";
+
+export function TextDialog(props: {setModal: Dispatch>, text: string, done: (newText: string|undefined) => void}) {
+ const [text, setText] = useState(props.text);
+ function onKeyDown(e: KeyboardEvent) {
+ if (e.key === "Enter") {
+ if (!e.shiftKey) {
+ e.preventDefault();
+ props.done(text);
+ props.setModal(null);
+ }
+ }
+ if (e.key === "Escape") {
+ props.setModal(null);
+ e.stopPropagation();
+ }
+ e.stopPropagation();
+ }
+ return
+
+
+
+ Tip: Shift+Enter to insert newline.
+
+ ;
+}
\ No newline at end of file
diff --git a/src/App/TopPanel.tsx b/src/App/TopPanel.tsx
index 46ad441..721cdd7 100644
--- a/src/App/TopPanel.tsx
+++ b/src/App/TopPanel.tsx
@@ -75,38 +75,40 @@ export function TopPanel({rt, rtIdx, time, setTime, onInit, onClear, onRaise, on
useEffect(() => {
const onKeyDown = (e: KeyboardEvent) => {
- if (e.key === " ") {
- e.preventDefault();
- if (rt)
- onChangePaused(time.kind !== "paused", Math.round(performance.now()));
- };
- if (e.key === "i") {
- e.preventDefault();
- onInit();
- }
- if (e.key === "c") {
- e.preventDefault();
- onClear();
- }
- if (e.key === "Tab") {
- e.preventDefault();
- onSkip();
- }
- if (e.key === "s") {
- e.preventDefault();
- onSlower();
- }
- if (e.key === "f") {
- e.preventDefault();
- onFaster();
- }
- if (e.key === "`") {
- e.preventDefault();
- setShowKeys(show => !show);
- }
- if (e.key === "Backspace") {
- e.preventDefault();
- onBack();
+ if (!e.ctrlKey) {
+ if (e.key === " ") {
+ e.preventDefault();
+ if (rt)
+ onChangePaused(time.kind !== "paused", Math.round(performance.now()));
+ };
+ if (e.key === "i") {
+ e.preventDefault();
+ onInit();
+ }
+ if (e.key === "c") {
+ e.preventDefault();
+ onClear();
+ }
+ if (e.key === "Tab") {
+ e.preventDefault();
+ onSkip();
+ }
+ if (e.key === "s") {
+ e.preventDefault();
+ onSlower();
+ }
+ if (e.key === "f") {
+ e.preventDefault();
+ onFaster();
+ }
+ if (e.key === "`") {
+ e.preventDefault();
+ setShowKeys(show => !show);
+ }
+ if (e.key === "Backspace") {
+ e.preventDefault();
+ onBack();
+ }
}
};
window.addEventListener("keydown", onKeyDown);
diff --git a/src/App/shortcut_handler.ts b/src/App/shortcut_handler.ts
index e74228c..824a245 100644
--- a/src/App/shortcut_handler.ts
+++ b/src/App/shortcut_handler.ts
@@ -3,26 +3,28 @@ import { InsertMode } from "../VisualEditor/VisualEditor";
export function getKeyHandler(setMode: Dispatch>) {
return function onKeyDown(e: KeyboardEvent) {
- if (e.key === "a") {
- setMode("and");
- }
- if (e.key === "o") {
- setMode("or");
- }
- if (e.key === "p") {
- setMode("pseudo");
- }
- if (e.key === "t") {
- setMode("transition");
- }
- if (e.key === "x") {
- setMode("text");
- }
- if (e.key === "h") {
- setMode(oldMode => {
- if (oldMode === "shallow") return "deep";
- return "shallow";
- })
+ if (!e.ctrlKey) {
+ if (e.key === "a") {
+ setMode("and");
+ }
+ if (e.key === "o") {
+ setMode("or");
+ }
+ if (e.key === "p") {
+ setMode("pseudo");
+ }
+ if (e.key === "t") {
+ setMode("transition");
+ }
+ if (e.key === "x") {
+ setMode("text");
+ }
+ if (e.key === "h") {
+ setMode(oldMode => {
+ if (oldMode === "shallow") return "deep";
+ return "shallow";
+ })
+ }
}
}
}
diff --git a/src/VisualEditor/TextSVG.tsx b/src/VisualEditor/TextSVG.tsx
index 2990e38..87b68cd 100644
--- a/src/VisualEditor/TextSVG.tsx
+++ b/src/VisualEditor/TextSVG.tsx
@@ -1,7 +1,9 @@
+import { TextDialog } from "@/App/TextDialog";
import { TraceableError } from "..//statecharts/parser";
import {Text} from "../statecharts/concrete_syntax";
+import { Dispatch, ReactElement, SetStateAction } from "react";
-export function TextSVG(props: {text: Text, error: TraceableError|undefined, selected: boolean, highlight: boolean, onEdit: (newText: string) => void}) {
+export function TextSVG(props: {text: Text, error: TraceableError|undefined, selected: boolean, highlight: boolean, onEdit: (newText: string) => void, setModal: Dispatch>}) {
const commonProps = {
"data-uid": props.text.uid,
"data-parts": "text",
@@ -9,6 +11,7 @@ export function TextSVG(props: {text: Text, error: TraceableError|undefined, sel
className: "draggableText"
+ (props.selected ? " selected":"")
+ (props.highlight ? " highlight":""),
+ style: {whiteSpace: "preserve"},
}
let textNode;
@@ -32,12 +35,13 @@ export function TextSVG(props: {text: Text, error: TraceableError|undefined, sel
key={props.text.uid}
transform={`translate(${props.text.topLeft.x} ${props.text.topLeft.y})`}
onDoubleClick={() => {
- const newText = prompt("", props.text.text);
- if (newText) {
- props.onEdit(newText);
- }
+ props.setModal( {
+ if (newText) {
+ props.onEdit(newText);
+ }
+ }} />)
}}>
{textNode}
- {props.text.text}
+ {props.text.text}
;
}
\ No newline at end of file
diff --git a/src/VisualEditor/VisualEditor.tsx b/src/VisualEditor/VisualEditor.tsx
index bb0e88e..f0cb80f 100644
--- a/src/VisualEditor/VisualEditor.tsx
+++ b/src/VisualEditor/VisualEditor.tsx
@@ -1,4 +1,4 @@
-import { Dispatch, SetStateAction, useEffect, useMemo, useRef, useState } from "react";
+import { Dispatch, ReactElement, SetStateAction, useEffect, useMemo, useRef, useState } from "react";
import { Statechart } from "../statecharts/abstract_syntax";
import { Arrow, ArrowPart, Diamond, History, Rountangle, RountanglePart, Text, VisualEditorState, emptyState } from "../statecharts/concrete_syntax";
@@ -68,9 +68,10 @@ type VisualEditorProps = {
mode: InsertMode,
highlightActive: Set,
highlightTransitions: string[],
+ setModal: Dispatch>,
};
-export function VisualEditor({ast, setAST, rt, errors, setErrors, mode, highlightActive, highlightTransitions}: VisualEditorProps) {
+export function VisualEditor({ast, setAST, rt, errors, setErrors, mode, highlightActive, highlightTransitions, setModal}: VisualEditorProps) {
const [historyState, setHistoryState] = useState({current: emptyState, history: [], future: []});
const state = historyState.current;
@@ -324,7 +325,7 @@ export function VisualEditor({ast, setAST, rt, errors, setErrors, mode, highligh
setSelection([]);
};
- const onMouseMove = (e: {pageX: number, pageY: number}) => {
+ const onMouseMove = (e: {pageX: number, pageY: number, movementX: number, movementY: number}) => {
const currentPointer = getCurrentPointer(e);
if (dragging) {
// const pointerDelta = subtractV2D(currentPointer, dragging.lastMousePos);
@@ -812,6 +813,7 @@ export function VisualEditor({ast, setAST, rt, errors, setErrors, mode, highligh
selected={Boolean(selection.find(s => s.uid === txt.uid)?.parts?.length)}
highlight={textsToHighlight.hasOwnProperty(txt.uid)}
onEdit={newText => onEditText(txt, newText)}
+ setModal={setModal}
/>
})}