space.dart
3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import '../../render/layout/reset_baseline.dart';
import '../options.dart';
import '../size.dart';
import '../syntax_tree.dart';
import '../types.dart';
/// Space node. Also used for equation alignment.
class SpaceNode extends LeafNode {
/// Height.
final Measurement height;
/// Width.
final Measurement width;
/// Depth.
final Measurement depth;
/// Vertical shift.
///
/// For the sole purpose of `\rule`
final Measurement shift;
/// Break penalty for a manual line breaking command.
///
/// Related TeX command: \nobreak, \allowbreak, \penalty<number>.
///
/// Should be null for normal space commands.
final int? breakPenalty;
/// Whether to fill with text color.
final bool fill;
final Mode mode;
final bool alignerOrSpacer;
SpaceNode({
required this.height,
required this.width,
this.shift = Measurement.zero,
this.depth = Measurement.zero,
this.breakPenalty,
this.fill = false,
// this.background,
required this.mode,
this.alignerOrSpacer = false,
});
SpaceNode.alignerOrSpacer()
: height = Measurement.zero,
width = Measurement.zero,
shift = Measurement.zero,
depth = Measurement.zero,
breakPenalty = null,
fill = true,
// background = null,
mode = Mode.math,
alignerOrSpacer = true;
@override
BuildResult buildWidget(
MathOptions options, List<BuildResult?> childBuildResults) {
if (alignerOrSpacer == true) {
return BuildResult(
options: options,
widget: Container(height: 0.0),
);
}
final height = this.height.toLpUnder(options);
final depth = this.depth.toLpUnder(options);
final width = this.width.toLpUnder(options);
final shift = this.shift.toLpUnder(options);
final topMost = math.max(height, -depth) + shift;
final bottomMost = math.min(height, -depth) + shift;
return BuildResult(
options: options,
widget: ResetBaseline(
height: topMost,
child: Container(
color: fill ? options.color : null,
height: topMost - bottomMost,
width: math.max(0.0, width),
),
),
);
}
@override
AtomType get leftType => AtomType.spacing;
@override
AtomType get rightType => AtomType.spacing;
@override
bool shouldRebuildWidget(MathOptions oldOptions, MathOptions newOptions) =>
oldOptions.sizeMultiplier != newOptions.sizeMultiplier;
@override
Map<String, Object?> toJson() => super.toJson()
..addAll({
'mode': mode.toString(),
'height': height.toString(),
'width': width.toString(),
if (depth != Measurement.zero) 'depth': depth.toString(),
if (shift != Measurement.zero) 'shift': shift.toString(),
// if (noBreak != false) 'noBreak': noBreak,
if (breakPenalty != null) 'breakPenalty': breakPenalty,
if (fill != false) 'fill': fill,
if (alignerOrSpacer != false) 'alignerOrSpacer': alignerOrSpacer,
});
}