|
|
@@ -108,12 +108,16 @@ class _SlotView extends StatelessWidget {
|
|
|
required this.onTapNode,
|
|
|
required this.onLongPressNode,
|
|
|
required this.onTapSlot,
|
|
|
+ this.vpad = 3,
|
|
|
});
|
|
|
|
|
|
final ExprDoc doc;
|
|
|
final SeqNode seq;
|
|
|
final SlotPath path;
|
|
|
final double size;
|
|
|
+
|
|
|
+ /// 上下内边距。上下限这种要紧贴运算符的地方传 0。
|
|
|
+ final double vpad;
|
|
|
final void Function(SlotPath parent, int index, bool before) onTapNode;
|
|
|
final void Function(SlotPath parent, int index) onLongPressNode;
|
|
|
final void Function(SlotPath path, SeqNode seq) onTapSlot;
|
|
|
@@ -131,7 +135,7 @@ class _SlotView extends StatelessWidget {
|
|
|
onTap: () => onTapSlot(path, seq),
|
|
|
behavior: HitTestBehavior.opaque,
|
|
|
child: Container(
|
|
|
- padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 3),
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 2, vertical: vpad),
|
|
|
// 空槽只有一个光标那么宽(2.5px),手指点不到 —— 而"点光标处弹粘贴"
|
|
|
// 恰恰最常在空槽里用(先按 ln 再粘参数)。给个最小的可点面积。
|
|
|
constraints: focused && seq.isEmpty
|
|
|
@@ -414,16 +418,26 @@ class _NodeView extends StatelessWidget {
|
|
|
Widget _bigOp(BuildContext context, BigOpNode b) {
|
|
|
final body = _slot(context, b.body, parent.push(index, 0));
|
|
|
final variable = _slot(context, b.variable, parent.push(index, 1));
|
|
|
- final lower = _slot(context, b.lower, parent.push(index, 2), scale: 0.5);
|
|
|
- final upper = _slot(context, b.upper, parent.push(index, 3), scale: 0.5);
|
|
|
+ // 上下限紧贴运算符:槽的上下内边距收掉,再往中间拽几像素
|
|
|
+ final lower = Transform.translate(
|
|
|
+ offset: const Offset(0, -3),
|
|
|
+ child: _slot(context, b.lower, parent.push(index, 2),
|
|
|
+ scale: 0.5, vpad: 0),
|
|
|
+ );
|
|
|
+ final upper = Transform.translate(
|
|
|
+ offset: const Offset(0, 3),
|
|
|
+ child: _slot(context, b.upper, parent.push(index, 3),
|
|
|
+ scale: 0.5, vpad: 0),
|
|
|
+ );
|
|
|
|
|
|
if (b.kind == 'Limit') {
|
|
|
// lim 下面写"x→0"
|
|
|
final under = Row(
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
children: [
|
|
|
- _slot(context, b.variable, parent.push(index, 1), scale: 0.6),
|
|
|
- Text('→', style: _mathStyle(context, 0.6)),
|
|
|
+ _slot(context, b.variable, parent.push(index, 1),
|
|
|
+ scale: 0.6, vpad: 0),
|
|
|
+ Text('→', style: _mathStyle(context, 0.6).copyWith(height: 1.0)),
|
|
|
lower,
|
|
|
],
|
|
|
);
|
|
|
@@ -431,8 +445,8 @@ class _NodeView extends StatelessWidget {
|
|
|
Column(
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
children: [
|
|
|
- Text('lim', style: _mathStyle(context, 0.95)),
|
|
|
- under,
|
|
|
+ Text('lim', style: _mathStyle(context, 0.95).copyWith(height: 1.0)),
|
|
|
+ Transform.translate(offset: const Offset(0, -2), child: under),
|
|
|
],
|
|
|
),
|
|
|
body,
|
|
|
@@ -446,13 +460,15 @@ class _NodeView extends StatelessWidget {
|
|
|
_ => '∑',
|
|
|
};
|
|
|
|
|
|
+ // height: 1.0 把字体自带的行距空白压掉 —— 默认行高约 1.16em,
|
|
|
+ // 37 号字上下各多出好几个像素,看着就是"离运算符很远"。
|
|
|
final stack = Column(
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
children: [
|
|
|
// 上下限**始终渲染** —— 空的时候画成小占位框。
|
|
|
// 不渲染的话不定积分的两个限槽就成了够不着的死结构,永远填不进去。
|
|
|
upper,
|
|
|
- Text(glyph, style: _mathStyle(context, 1.7)),
|
|
|
+ Text(glyph, style: _mathStyle(context, 1.7).copyWith(height: 1.0)),
|
|
|
lower,
|
|
|
],
|
|
|
);
|
|
|
@@ -478,12 +494,13 @@ class _NodeView extends StatelessWidget {
|
|
|
/// Transform 只改视觉、不改布局,占位仍是原尺寸 —— 结果就是"字看着小了
|
|
|
/// 但离运算符老远"(用户实测反馈)。直接把 size 传下去,布局才会跟着缩。
|
|
|
Widget _slot(BuildContext context, SeqNode seq, SlotPath path,
|
|
|
- {double scale = 1}) =>
|
|
|
+ {double scale = 1, double vpad = 3}) =>
|
|
|
_SlotView(
|
|
|
doc: doc,
|
|
|
seq: seq,
|
|
|
path: path,
|
|
|
size: size * scale,
|
|
|
+ vpad: vpad,
|
|
|
onTapNode: onTapNode,
|
|
|
onLongPressNode: onLongPressNode,
|
|
|
onTapSlot: onTapSlot,
|