diff --git a/src/VisualEditor/VisualEditor.tsx b/src/VisualEditor/VisualEditor.tsx index 62ce237..7758798 100644 --- a/src/VisualEditor/VisualEditor.tsx +++ b/src/VisualEditor/VisualEditor.tsx @@ -4,7 +4,7 @@ import { ArcDirection, Line2D, Rect2D, Vec2D, addV2D, arcDirection, area, euclid import "./VisualEditor.css"; import { getBBoxInSvgCoords } from "./svg_helper"; -import { VisualEditorState, Rountangle, emptyState, Arrow, ArrowPart, RountanglePart, findNearestRountangleSide, findNearestArrow, Text } from "./editor_types"; +import { VisualEditorState, Rountangle, emptyState, Arrow, ArrowPart, RountanglePart, findNearestRountangleSide, findNearestArrow, Text, findRountangle } from "./editor_types"; import { parseStatechart } from "./parser"; import { CORNER_HELPER_OFFSET, CORNER_HELPER_RADIUS, MIN_ROUNTANGLE_SIZE, ROUNTANGLE_RADIUS } from "./parameters"; @@ -401,6 +401,7 @@ export function VisualEditor() { const side2ArrowMap = new Map>(); const text2ArrowMap = new Map(); const arrow2TextMap = new Map(); + const text2RountangleMap = new Map(); for (const arrow of state.arrows) { const startSide = findNearestRountangleSide(arrow, "start", state.rountangles); const endSide = findNearestRountangleSide(arrow, "end", state.rountangles); @@ -421,17 +422,26 @@ export function VisualEditor() { for (const text of state.texts) { const nearestArrow = findNearestArrow(text.topLeft, state.arrows); if (nearestArrow) { + // prioritize text belonging to arrows: text2ArrowMap.set(text.uid, nearestArrow.uid); const textsOfArrow = arrow2TextMap.get(nearestArrow.uid) || []; textsOfArrow.push(text.uid); arrow2TextMap.set(nearestArrow.uid, textsOfArrow); } + else { + // no arrow, then the text belongs to the rountangle it is in + const rountangle = findRountangle(text.topLeft, state.rountangles); + if (rountangle) { + text2RountangleMap.set(text.uid, rountangle.uid); + } + } } // for visual feedback, when selecting/moving one thing, we also highlight (in green) all the things that belong to the thing we selected. const sidesToHighlight: {[key: string]: RountanglePart[]} = {}; const arrowsToHighlight: {[key: string]: boolean} = {}; const textsToHighlight: {[key: string]: boolean} = {}; + const rountanglesToHighlight: {[key: string]: boolean} = {}; for (const selected of selection) { const sides = arrow2SideMap.get(selected.uid); if (sides) { @@ -455,6 +465,10 @@ export function VisualEditor() { if (arrow2) { arrowsToHighlight[arrow2] = true; } + const rountangleUid = text2RountangleMap.get(selected.uid) + if (rountangleUid) { + rountanglesToHighlight[rountangleUid] = true; + } } const rootErrors = errors.filter(([uid]) => uid === "root").map(err=>err[1]); @@ -484,7 +498,7 @@ export function VisualEditor() { key={rountangle.uid} rountangle={rountangle} selected={selection.find(r => r.uid === rountangle.uid)?.parts || []} - highlight={sidesToHighlight[rountangle.uid] || []} + highlight={[...(sidesToHighlight[rountangle.uid] || []), ...(rountanglesToHighlight[rountangle.uid]?["left","right","top","bottom"]:[])]} errors={errors.filter(([uid,msg])=>uid===rountangle.uid).map(err=>err[1])} />)} diff --git a/src/VisualEditor/editor_types.ts b/src/VisualEditor/editor_types.ts index 90b4d9a..22359c5 100644 --- a/src/VisualEditor/editor_types.ts +++ b/src/VisualEditor/editor_types.ts @@ -1,4 +1,4 @@ -import { Rect2D, Vec2D, Line2D, euclideanDistance, intersectLines, isWithin, lineBBox } from "./geometry"; +import { Rect2D, Vec2D, Line2D, euclideanDistance, intersectLines, isWithin, lineBBox, isEntirelyWithin } from "./geometry"; import { ARROW_SNAP_THRESHOLD, TEXT_SNAP_THRESHOLD } from "./parameters"; import { sides } from "./VisualEditor"; @@ -106,3 +106,12 @@ export function findNearestArrow(point: Vec2D, candidates: Arrow[]): Arrow | und return best; } + +// precondition: candidates are sorted from big to small +export function findRountangle(point: Vec2D, candidates: Rountangle[]): Rountangle | undefined { + for (let i=candidates.length-1; i>=0; i--) { + if (isWithin(point, candidates[i])) { + return candidates[i]; + } + } +} diff --git a/src/VisualEditor/interpreter.ts b/src/VisualEditor/interpreter.ts index f95279c..429ceab 100644 --- a/src/VisualEditor/interpreter.ts +++ b/src/VisualEditor/interpreter.ts @@ -23,4 +23,5 @@ export function recursiveEnter(state: ConcreteState): RT_ConcreteState { current_rt: recursiveEnter(currentState), }; } -} \ No newline at end of file +} +