matchWidget method
Matches the widget provided as element
and returns the corresponding pw.Widget
.
The context
is only null when called from exportFunc.
Implementation
Future<List<pw.Widget>> matchWidget(
Element element, BuildContext? context) async {
final Widget widget = element.widget;
switch (widget.runtimeType) {
case const (MergeSemantics): //anchor: end of widget tree
return [];
case const (Container):
final List children = await _visit(element, context);
return [
await (widget as Container)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (Center):
final List children = await _visit(element, context);
return [
(widget as Center)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (SizedBox):
final List children = await _visit(element, context);
return [
(widget as SizedBox)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (FittedBox):
final List children = await _visit(element, context);
return [
(widget as FittedBox)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (LimitedBox):
final List children = await _visit(element, context);
return [
(widget as LimitedBox)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (ConstrainedBox):
final List children = await _visit(element, context);
return [
(widget as ConstrainedBox)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (ClipRect):
final List children = await _visit(element, context);
return [
(widget as ClipRect)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (ClipRRect):
final List children = await _visit(element, context);
return [
(widget as ClipRRect)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (ClipOval):
final List children = await _visit(element, context);
return [
(widget as ClipOval)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (Transform):
final List children = await _visit(element, context);
return [
(widget as Transform)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (Opacity):
final List children = await _visit(element, context);
return [
(widget as Opacity)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (Padding):
final List children = await _visit(element, context);
return [
(widget as Padding)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (Align):
final List children = await _visit(element, context);
return [
(widget as Align)
.toPdfWidget(children.isNotEmpty ? children.first : null)
];
case const (Positioned):
final List children = await _visit(element, context);
return [
(widget as Positioned).toPdfWidget(
children.isNotEmpty ? children.first : pw.Container(),
)
];
case const (Expanded):
final List children = await _visit(element, context);
return [
(widget as Expanded).toPdfWidget(
children.isNotEmpty ? children.first : pw.Container(),
)
];
case const (Flexible):
final List children = await _visit(element, context);
return [
(widget as Flexible).toPdfWidget(
children.isNotEmpty ? children.first : pw.Container(),
)
];
case const (Placeholder):
return [(widget as Placeholder).toPdfWidget()];
case const (Text):
return [await (widget as Text).toPdfWidget(this)];
case const (TextField):
TextField? contextWidget;
if (context != null) {
TextFormField? textFormField;
if (widget.key == null) {
textFormField =
element.findAncestorWidgetOfExactType<TextFormField>();
if (textFormField?.key == null) {
throw Exception('TextField must have a key to be exported');
}
}
if (textFormField == null) {
Element? contextElement =
findElement(context, (TextField e) => e.key == widget.key);
contextWidget = contextElement!.widget as TextField;
} else {
Element? contextElement = findElement(
context, (TextFormField e) => e.key == textFormField!.key);
contextElement =
findFirstDescendantElement<TextField>(contextElement!);
contextWidget = contextElement!.widget as TextField;
}
}
return [await (widget as TextField).toPdfWidget(this, contextWidget)];
case const (Divider):
return [(widget as Divider).toPdfWidget()];
case const (Image):
return [await (widget as Image).toPdfWidget()];
case const (Checkbox):
Checkbox? contextWidget;
if (context != null) {
if (widget.key == null) {
throw Exception('Checkbox must have a key to be exported');
}
Element? contextElement =
findElement(context, (Checkbox e) => e.key == widget.key);
contextWidget = contextElement!.widget as Checkbox;
}
return [
await (widget as Checkbox)
.toPdfWidget(delegate.options.checkboxOptions, contextWidget)
];
case const (TextButton):
case const (ElevatedButton):
case const (OutlinedButton):
case const (FilledButton):
return [
(widget as ButtonStyleButton)
.toPdfWidget((await _visit(element, context)).first)
];
case const (Column):
return [(widget as Column).toPdfWidget(await _visit(element, context))];
case const (Row):
return [(widget as Row).toPdfWidget(await _visit(element, context))];
case const (Stack):
return [(widget as Stack).toPdfWidget(await _visit(element, context))];
case const (ListView):
Element? contextElement = findElement(context!, (e) => e is SliverList);
return [
(widget as ListView)
.toPdfWidget(await _visit(contextElement!, context))
];
case const (GridView):
final constraints = BoxConstraints(
maxWidth: element.renderObject!.paintBounds.right,
maxHeight: element.renderObject!.paintBounds.bottom,
);
return [
(widget as GridView)
.toPdfWidget(await _visit(element, context), constraints)
];
case const (Wrap):
return [(widget as Wrap).toPdfWidget(await _visit(element, context))];
case const (Table):
return [
await (widget as Table).toPdfWidget(await _visit(element, context))
];
case const (CaptureWrapper):
if (widget.key == null) {
throw Exception('Capture must have a key to be exported');
}
Element? contextElement =
findElement(context!, (CaptureWrapper e) => e.key == widget.key);
assert(contextElement != null);
RenderRepaintBoundary? boundary;
RenderObject? renderObject = contextElement!.renderObject;
if (renderObject is RenderRepaintBoundary) {
boundary = renderObject;
} else {
renderObject?.visitChildren((child) {
if (child is RenderRepaintBoundary) {
boundary = child;
}
});
}
assert(boundary != null);
final ui.Image uiImage = await boundary!.toImage(pixelRatio: 2.0);
final pngBytes =
await uiImage.toByteData(format: ui.ImageByteFormat.png);
debugPrint(
'Captured image for ${widget.key}, with size: ${uiImage.width}x${uiImage.height}');
return [
await Image.memory(
pngBytes!.buffer.asUint8List(),
width: uiImage.width / 2.0,
height: uiImage.height / 2.0,
).toPdfWidget(),
];
default:
return await _visit(element, context);
}
}