|
|
@@ -162,21 +162,35 @@ class _NodeView extends StatelessWidget {
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
final scheme = Theme.of(context).colorScheme;
|
|
|
- // 点中某个节点 → 光标落到它后面(符合"接着往下打"的直觉)
|
|
|
- return GestureDetector(
|
|
|
- onTap: () => onCursor(SlotPath(parent.steps, index + 1)),
|
|
|
- behavior: HitTestBehavior.opaque,
|
|
|
- child: switch (node) {
|
|
|
- LitNode l => _literal(l, scheme),
|
|
|
- FuncNode f => _function(context, f),
|
|
|
- FracNode f => _fraction(context, f),
|
|
|
- PowNode p => _power(context, p),
|
|
|
- GroupNode g => _group(context, g),
|
|
|
- PostfixNode p => _row([
|
|
|
- _slot(context, p.operand, parent.push(index, 0)),
|
|
|
- _text(p.op, size),
|
|
|
- ]),
|
|
|
- },
|
|
|
+ final body = switch (node) {
|
|
|
+ LitNode l => _literal(l, scheme),
|
|
|
+ FuncNode f => _function(context, f),
|
|
|
+ FracNode f => _fraction(context, f),
|
|
|
+ PowNode p => _power(context, p),
|
|
|
+ GroupNode g => _group(context, g),
|
|
|
+ PostfixNode p => _row([
|
|
|
+ _slot(context, p.operand, parent.push(index, 0)),
|
|
|
+ _text(p.op, size),
|
|
|
+ ]),
|
|
|
+ };
|
|
|
+
|
|
|
+ // 点节点的**左半边**把光标放到它前面,右半边放到它后面。
|
|
|
+ //
|
|
|
+ // 之前无论点哪都落到"后面",于是偏移 0(表达式最前面)那个位置永远够不着 ——
|
|
|
+ // 用户只能把光标停在第一个字符之后,回不到行首。
|
|
|
+ //
|
|
|
+ // 宽度用 Builder 拿:Builder 自身不是 RenderObject,findRenderObject()
|
|
|
+ // 会往下找到 GestureDetector 那个 box,尺寸正是节点的尺寸。
|
|
|
+ return Builder(
|
|
|
+ builder: (inner) => GestureDetector(
|
|
|
+ behavior: HitTestBehavior.opaque,
|
|
|
+ onTapDown: (d) {
|
|
|
+ final box = inner.findRenderObject() as RenderBox?;
|
|
|
+ final before = d.localPosition.dx < (box?.size.width ?? 0) / 2;
|
|
|
+ onCursor(SlotPath(parent.steps, before ? index : index + 1));
|
|
|
+ },
|
|
|
+ child: body,
|
|
|
+ ),
|
|
|
);
|
|
|
}
|
|
|
|