buildWidget method
Compose Flutter widget with child widgets already built
Subclasses should override this method. This method provides a general description of the layout of this math node. The child nodes are built in prior. This method is only responsible for the placement of those child widgets accroding to the layout & other interactions.
Please ensure children works in the same order as updateChildren, computeChildOptions, and buildWidget.
Implementation
@override
BuildResult buildWidget(
MathOptions options, List<BuildResult?> childBuildResults) {
final large =
allowLargeOp && (options.style.size == MathStyle.display.size);
final font = large
? FontOptions(fontFamily: 'Size2')
: FontOptions(fontFamily: 'Size1');
Widget operatorWidget;
CharacterMetrics symbolMetrics;
if (!_stashedOvalNaryOperator.containsKey(operator)) {
final lookupResult = lookupChar(operator, font, Mode.math);
if (lookupResult == null) {
symbolMetrics = const CharacterMetrics(0, 0, 0, 0, 0);
operatorWidget = Container();
} else {
symbolMetrics = lookupResult;
final symbolWidget =
makeChar(operator, font, symbolMetrics, options, needItalic: true);
operatorWidget = symbolWidget;
}
} else {
final baseSymbol = _stashedOvalNaryOperator[operator]!;
symbolMetrics = lookupChar(baseSymbol, font, Mode.math)!;
final baseSymbolWidget =
makeChar(baseSymbol, font, symbolMetrics, options, needItalic: true);
final oval = staticSvg(
'${operator == '\u222F' ? 'oiint' : 'oiiint'}'
'Size${large ? '2' : '1'}',
options);
operatorWidget = Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ResetDimension(
horizontalAlignment: CrossAxisAlignment.start,
width: 0.0,
child: ShiftBaseline(
offset: large ? 0.08.cssEm.toLpUnder(options) : 0.0,
child: oval,
),
),
baseSymbolWidget,
],
);
}
// Attach limits to the base symbol
if (lowerLimit != null || upperLimit != null) {
// Should we place the limit as under/over or sub/sup
final shouldLimits = limits ??
(_naryDefaultLimit.contains(operator) &&
options.style.size == MathStyle.display.size);
final italic = symbolMetrics.italic.cssEm.toLpUnder(options);
if (!shouldLimits) {
operatorWidget = Multiscripts(
isBaseCharacterBox: false,
baseResult: BuildResult(
widget: operatorWidget, options: options, italic: italic),
subResult: childBuildResults[0],
supResult: childBuildResults[1],
);
} else {
final spacing =
options.fontMetrics.bigOpSpacing5.cssEm.toLpUnder(options);
operatorWidget = Padding(
padding: EdgeInsets.only(
top: upperLimit != null ? spacing : 0,
bottom: lowerLimit != null ? spacing : 0,
),
child: VList(
baselineReferenceWidgetIndex: upperLimit != null ? 1 : 0,
children: [
if (upperLimit != null)
VListElement(
hShift: 0.5 * italic,
child: MinDimension(
minDepth: options.fontMetrics.bigOpSpacing3.cssEm
.toLpUnder(options),
bottomPadding: options.fontMetrics.bigOpSpacing1.cssEm
.toLpUnder(options),
child: childBuildResults[1]!.widget,
),
),
operatorWidget,
if (lowerLimit != null)
VListElement(
hShift: -0.5 * italic,
child: MinDimension(
minHeight: options.fontMetrics.bigOpSpacing4.cssEm
.toLpUnder(options),
topPadding: options.fontMetrics.bigOpSpacing2.cssEm
.toLpUnder(options),
child: childBuildResults[0]!.widget,
),
),
],
),
);
}
}
final widget = Line(
children: [
LineElement(
child: operatorWidget,
trailingMargin:
getSpacingSize(AtomType.op, naryand.leftType, options.style)
.toLpUnder(options),
),
LineElement(
child: childBuildResults[2]!.widget,
trailingMargin: 0.0,
),
],
);
return BuildResult(
widget: widget,
options: options,
italic: childBuildResults[2]!.italic,
);
}