Passthrough SpanningWidget on SingleChildWidget and StatelessWidget
Showing
11 changed files
with
84 additions
and
45 deletions
@@ -26,8 +26,8 @@ Future<Uint8List> generateDocument( | @@ -26,8 +26,8 @@ Future<Uint8List> generateDocument( | ||
26 | final doc = pw.Document(pageMode: PdfPageMode.outlines); | 26 | final doc = pw.Document(pageMode: PdfPageMode.outlines); |
27 | 27 | ||
28 | doc.addPage(pw.MultiPage( | 28 | doc.addPage(pw.MultiPage( |
29 | - pageFormat: | ||
30 | - PdfPageFormat.letter.copyWith(marginBottom: 1.5 * PdfPageFormat.cm), | 29 | + pageFormat: format.copyWith(marginBottom: 1.5 * PdfPageFormat.cm), |
30 | + orientation: pw.PageOrientation.portrait, | ||
31 | crossAxisAlignment: pw.CrossAxisAlignment.start, | 31 | crossAxisAlignment: pw.CrossAxisAlignment.start, |
32 | header: (pw.Context context) { | 32 | header: (pw.Context context) { |
33 | if (context.pageNumber == 1) { | 33 | if (context.pageNumber == 1) { |
@@ -10,6 +10,7 @@ | @@ -10,6 +10,7 @@ | ||
10 | - ImageProvider.resolve returns non-null object | 10 | - ImageProvider.resolve returns non-null object |
11 | - Fix textScalingFactor with lineSpacing | 11 | - Fix textScalingFactor with lineSpacing |
12 | - Implement SpanningWidget on RichText | 12 | - Implement SpanningWidget on RichText |
13 | +- Passthrough SpanningWidget on SingleChildWidget and StatelessWidget | ||
13 | 14 | ||
14 | ## 3.2.0 | 15 | ## 3.2.0 |
15 | 16 |
@@ -133,12 +133,13 @@ class Header extends StatelessWidget { | @@ -133,12 +133,13 @@ class Header extends StatelessWidget { | ||
133 | } | 133 | } |
134 | 134 | ||
135 | class Paragraph extends StatelessWidget { | 135 | class Paragraph extends StatelessWidget { |
136 | - Paragraph( | ||
137 | - {this.text, | ||
138 | - this.textAlign = TextAlign.justify, | ||
139 | - this.style, | ||
140 | - this.margin = const EdgeInsets.only(bottom: 5.0 * PdfPageFormat.mm), | ||
141 | - this.padding}); | 136 | + Paragraph({ |
137 | + this.text, | ||
138 | + this.textAlign = TextAlign.justify, | ||
139 | + this.style, | ||
140 | + this.margin = const EdgeInsets.only(bottom: 5.0 * PdfPageFormat.mm), | ||
141 | + this.padding, | ||
142 | + }); | ||
142 | 143 | ||
143 | final String? text; | 144 | final String? text; |
144 | 145 | ||
@@ -159,6 +160,7 @@ class Paragraph extends StatelessWidget { | @@ -159,6 +160,7 @@ class Paragraph extends StatelessWidget { | ||
159 | text!, | 160 | text!, |
160 | textAlign: textAlign, | 161 | textAlign: textAlign, |
161 | style: style ?? Theme.of(context).paragraphStyle, | 162 | style: style ?? Theme.of(context).paragraphStyle, |
163 | + overflow: TextOverflow.span, | ||
162 | ), | 164 | ), |
163 | ); | 165 | ); |
164 | } | 166 | } |
@@ -81,7 +81,7 @@ class _FlexContext extends WidgetContext { | @@ -81,7 +81,7 @@ class _FlexContext extends WidgetContext { | ||
81 | String toString() => '$runtimeType first:$firstChild last:$lastChild'; | 81 | String toString() => '$runtimeType first:$firstChild last:$lastChild'; |
82 | } | 82 | } |
83 | 83 | ||
84 | -class Flex extends MultiChildWidget implements SpanningWidget { | 84 | +class Flex extends MultiChildWidget with SpanningWidget { |
85 | Flex({ | 85 | Flex({ |
86 | required this.direction, | 86 | required this.direction, |
87 | this.mainAxisAlignment = MainAxisAlignment.start, | 87 | this.mainAxisAlignment = MainAxisAlignment.start, |
@@ -53,7 +53,7 @@ class _GridViewContext extends WidgetContext { | @@ -53,7 +53,7 @@ class _GridViewContext extends WidgetContext { | ||
53 | '$runtimeType first:$firstChild last:$lastChild size:${childCrossAxis}x$childMainAxis'; | 53 | '$runtimeType first:$firstChild last:$lastChild size:${childCrossAxis}x$childMainAxis'; |
54 | } | 54 | } |
55 | 55 | ||
56 | -class GridView extends MultiChildWidget implements SpanningWidget { | 56 | +class GridView extends MultiChildWidget with SpanningWidget { |
57 | GridView( | 57 | GridView( |
58 | {this.direction = Axis.vertical, | 58 | {this.direction = Axis.vertical, |
59 | this.padding = EdgeInsets.zero, | 59 | this.padding = EdgeInsets.zero, |
@@ -37,7 +37,7 @@ abstract class WidgetContext { | @@ -37,7 +37,7 @@ abstract class WidgetContext { | ||
37 | void apply(covariant WidgetContext other); | 37 | void apply(covariant WidgetContext other); |
38 | } | 38 | } |
39 | 39 | ||
40 | -abstract class SpanningWidget extends Widget { | 40 | +mixin SpanningWidget on Widget { |
41 | bool get canSpan; | 41 | bool get canSpan; |
42 | 42 | ||
43 | bool get hasMoreWidgets; | 43 | bool get hasMoreWidgets; |
@@ -46,7 +46,7 @@ abstract class SpanningWidget extends Widget { | @@ -46,7 +46,7 @@ abstract class SpanningWidget extends Widget { | ||
46 | @protected | 46 | @protected |
47 | WidgetContext saveContext(); | 47 | WidgetContext saveContext(); |
48 | 48 | ||
49 | - /// Aplpy the context for next layout | 49 | + /// Apply the context for next layout |
50 | @protected | 50 | @protected |
51 | void restoreContext(covariant WidgetContext context); | 51 | void restoreContext(covariant WidgetContext context); |
52 | } | 52 | } |
@@ -230,10 +230,6 @@ class MultiPage extends Page { | @@ -230,10 +230,6 @@ class MultiPage extends Page { | ||
230 | 230 | ||
231 | while (_index < children.length) { | 231 | while (_index < children.length) { |
232 | final child = children[_index]; | 232 | final child = children[_index]; |
233 | - var canSpan = false; | ||
234 | - if (child is SpanningWidget) { | ||
235 | - canSpan = child.canSpan; | ||
236 | - } | ||
237 | 233 | ||
238 | assert(() { | 234 | assert(() { |
239 | // Detect too big widgets | 235 | // Detect too big widgets |
@@ -292,7 +288,7 @@ class MultiPage extends Page { | @@ -292,7 +288,7 @@ class MultiPage extends Page { | ||
292 | } | 288 | } |
293 | 289 | ||
294 | // If we are processing a multi-page widget, we restore its context | 290 | // If we are processing a multi-page widget, we restore its context |
295 | - if (widgetContext != null && canSpan && child is SpanningWidget) { | 291 | + if (widgetContext != null && child is SpanningWidget) { |
296 | child.restoreContext(widgetContext); | 292 | child.restoreContext(widgetContext); |
297 | widgetContext = null; | 293 | widgetContext = null; |
298 | } | 294 | } |
@@ -300,6 +296,8 @@ class MultiPage extends Page { | @@ -300,6 +296,8 @@ class MultiPage extends Page { | ||
300 | child.layout(context, constraints, parentUsesSize: false); | 296 | child.layout(context, constraints, parentUsesSize: false); |
301 | assert(child.box != null); | 297 | assert(child.box != null); |
302 | 298 | ||
299 | + final canSpan = child is SpanningWidget && child.canSpan; | ||
300 | + | ||
303 | // What to do if the widget is too big for the page? | 301 | // What to do if the widget is too big for the page? |
304 | if (offsetStart! - child.box!.height < offsetEnd) { | 302 | if (offsetStart! - child.box!.height < offsetEnd) { |
305 | // If it is not a multi-page widget and its height | 303 | // If it is not a multi-page widget and its height |
@@ -475,7 +473,8 @@ class MultiPage extends Page { | @@ -475,7 +473,8 @@ class MultiPage extends Page { | ||
475 | final flex = child is Flexible ? child.flex : 0; | 473 | final flex = child is Flexible ? child.flex : 0; |
476 | final fit = child is Flexible ? child.fit : FlexFit.loose; | 474 | final fit = child is Flexible ? child.fit : FlexFit.loose; |
477 | if (flex > 0) { | 475 | if (flex > 0) { |
478 | - assert(child is! SpanningWidget); | 476 | + assert(child is! SpanningWidget || child.canSpan == false, |
477 | + 'Cannot have a spanning widget flexible'); | ||
479 | final maxChildExtent = child == lastFlexChild | 478 | final maxChildExtent = child == lastFlexChild |
480 | ? (freeSpace - allocatedFlexSpace) | 479 | ? (freeSpace - allocatedFlexSpace) |
481 | : spacePerFlex * flex; | 480 | : spacePerFlex * flex; |
@@ -24,7 +24,7 @@ import 'geometry.dart'; | @@ -24,7 +24,7 @@ import 'geometry.dart'; | ||
24 | import 'multi_page.dart'; | 24 | import 'multi_page.dart'; |
25 | import 'widget.dart'; | 25 | import 'widget.dart'; |
26 | 26 | ||
27 | -class Partition implements SpanningWidget { | 27 | +class Partition extends Widget with SpanningWidget { |
28 | Partition({ | 28 | Partition({ |
29 | required this.child, | 29 | required this.child, |
30 | this.width, | 30 | this.width, |
@@ -59,6 +59,7 @@ class Partition implements SpanningWidget { | @@ -59,6 +59,7 @@ class Partition implements SpanningWidget { | ||
59 | 59 | ||
60 | @override | 60 | @override |
61 | void paint(Context context) { | 61 | void paint(Context context) { |
62 | + super.paint(context); | ||
62 | child.paint(context); | 63 | child.paint(context); |
63 | } | 64 | } |
64 | 65 | ||
@@ -102,7 +103,7 @@ class _PartitionsContext extends WidgetContext { | @@ -102,7 +103,7 @@ class _PartitionsContext extends WidgetContext { | ||
102 | } | 103 | } |
103 | } | 104 | } |
104 | 105 | ||
105 | -class Partitions extends Widget implements SpanningWidget { | 106 | +class Partitions extends Widget with SpanningWidget { |
106 | Partitions({ | 107 | Partitions({ |
107 | required this.children, | 108 | required this.children, |
108 | this.mainAxisSize = MainAxisSize.max, | 109 | this.mainAxisSize = MainAxisSize.max, |
@@ -236,7 +236,7 @@ typedef OnCellDecoration = BoxDecoration Function( | @@ -236,7 +236,7 @@ typedef OnCellDecoration = BoxDecoration Function( | ||
236 | int index, dynamic data, int rowNum); | 236 | int index, dynamic data, int rowNum); |
237 | 237 | ||
238 | /// A widget that uses the table layout algorithm for its children. | 238 | /// A widget that uses the table layout algorithm for its children. |
239 | -class Table extends Widget implements SpanningWidget { | 239 | +class Table extends Widget with SpanningWidget { |
240 | Table({ | 240 | Table({ |
241 | this.children = const <TableRow>[], | 241 | this.children = const <TableRow>[], |
242 | this.border, | 242 | this.border, |
@@ -575,7 +575,7 @@ class _RichTextContext extends WidgetContext { | @@ -575,7 +575,7 @@ class _RichTextContext extends WidgetContext { | ||
575 | '$runtimeType Offset: $startOffset -> $endOffset Span: $spanStart -> $spanEnd'; | 575 | '$runtimeType Offset: $startOffset -> $endOffset Span: $spanStart -> $spanEnd'; |
576 | } | 576 | } |
577 | 577 | ||
578 | -class RichText extends Widget implements SpanningWidget { | 578 | +class RichText extends Widget with SpanningWidget { |
579 | RichText({ | 579 | RichText({ |
580 | required this.text, | 580 | required this.text, |
581 | this.textAlign, | 581 | this.textAlign, |
@@ -19,6 +19,7 @@ import 'dart:math' as math; | @@ -19,6 +19,7 @@ import 'dart:math' as math; | ||
19 | 19 | ||
20 | import 'package:meta/meta.dart'; | 20 | import 'package:meta/meta.dart'; |
21 | import 'package:pdf/pdf.dart'; | 21 | import 'package:pdf/pdf.dart'; |
22 | +import 'package:pdf/widgets.dart'; | ||
22 | import 'package:vector_math/vector_math_64.dart'; | 23 | import 'package:vector_math/vector_math_64.dart'; |
23 | 24 | ||
24 | import 'document.dart'; | 25 | import 'document.dart'; |
@@ -210,7 +211,7 @@ abstract class Widget { | @@ -210,7 +211,7 @@ abstract class Widget { | ||
210 | } | 211 | } |
211 | } | 212 | } |
212 | 213 | ||
213 | -abstract class StatelessWidget extends Widget { | 214 | +abstract class StatelessWidget extends Widget with SpanningWidget { |
214 | StatelessWidget() : super(); | 215 | StatelessWidget() : super(); |
215 | 216 | ||
216 | Widget? _child; | 217 | Widget? _child; |
@@ -246,9 +247,33 @@ abstract class StatelessWidget extends Widget { | @@ -246,9 +247,33 @@ abstract class StatelessWidget extends Widget { | ||
246 | 247 | ||
247 | @protected | 248 | @protected |
248 | Widget build(Context context); | 249 | Widget build(Context context); |
250 | + | ||
251 | + @override | ||
252 | + bool get canSpan => | ||
253 | + _child is SpanningWidget && (_child as SpanningWidget).canSpan; | ||
254 | + | ||
255 | + @override | ||
256 | + bool get hasMoreWidgets => | ||
257 | + _child is SpanningWidget && (_child as SpanningWidget).hasMoreWidgets; | ||
258 | + | ||
259 | + @override | ||
260 | + void restoreContext(covariant WidgetContext context) { | ||
261 | + if (_child is SpanningWidget) { | ||
262 | + (_child as SpanningWidget).restoreContext(context); | ||
263 | + } | ||
264 | + } | ||
265 | + | ||
266 | + @override | ||
267 | + WidgetContext saveContext() { | ||
268 | + if (_child is SpanningWidget) { | ||
269 | + return (_child as SpanningWidget).saveContext(); | ||
270 | + } | ||
271 | + | ||
272 | + throw UnimplementedError(); | ||
273 | + } | ||
249 | } | 274 | } |
250 | 275 | ||
251 | -abstract class SingleChildWidget extends Widget { | 276 | +abstract class SingleChildWidget extends Widget with SpanningWidget { |
252 | SingleChildWidget({this.child}) : super(); | 277 | SingleChildWidget({this.child}) : super(); |
253 | 278 | ||
254 | final Widget? child; | 279 | final Widget? child; |
@@ -277,6 +302,30 @@ abstract class SingleChildWidget extends Widget { | @@ -277,6 +302,30 @@ abstract class SingleChildWidget extends Widget { | ||
277 | context.canvas.restoreContext(); | 302 | context.canvas.restoreContext(); |
278 | } | 303 | } |
279 | } | 304 | } |
305 | + | ||
306 | + @override | ||
307 | + bool get canSpan => | ||
308 | + child is SpanningWidget && (child as SpanningWidget).canSpan; | ||
309 | + | ||
310 | + @override | ||
311 | + bool get hasMoreWidgets => | ||
312 | + child is SpanningWidget && (child as SpanningWidget).hasMoreWidgets; | ||
313 | + | ||
314 | + @override | ||
315 | + void restoreContext(covariant WidgetContext context) { | ||
316 | + if (child is SpanningWidget) { | ||
317 | + (child as SpanningWidget).restoreContext(context); | ||
318 | + } | ||
319 | + } | ||
320 | + | ||
321 | + @override | ||
322 | + WidgetContext saveContext() { | ||
323 | + if (child is SpanningWidget) { | ||
324 | + return (child as SpanningWidget).saveContext(); | ||
325 | + } | ||
326 | + | ||
327 | + throw UnimplementedError(); | ||
328 | + } | ||
280 | } | 329 | } |
281 | 330 | ||
282 | abstract class MultiChildWidget extends Widget { | 331 | abstract class MultiChildWidget extends Widget { |
@@ -285,8 +334,8 @@ abstract class MultiChildWidget extends Widget { | @@ -285,8 +334,8 @@ abstract class MultiChildWidget extends Widget { | ||
285 | final List<Widget> children; | 334 | final List<Widget> children; |
286 | } | 335 | } |
287 | 336 | ||
288 | -class InheritedWidget extends Widget { | ||
289 | - InheritedWidget({this.build, this.inherited}); | 337 | +class InheritedWidget extends SingleChildWidget { |
338 | + InheritedWidget({this.build, this.inherited}) : super(); | ||
290 | 339 | ||
291 | final BuildCallback? build; | 340 | final BuildCallback? build; |
292 | 341 | ||
@@ -294,6 +343,9 @@ class InheritedWidget extends Widget { | @@ -294,6 +343,9 @@ class InheritedWidget extends Widget { | ||
294 | 343 | ||
295 | Context? _context; | 344 | Context? _context; |
296 | 345 | ||
346 | + @override | ||
347 | + Widget? get child => _child; | ||
348 | + | ||
297 | Widget? _child; | 349 | Widget? _child; |
298 | 350 | ||
299 | @override | 351 | @override |
@@ -301,29 +353,13 @@ class InheritedWidget extends Widget { | @@ -301,29 +353,13 @@ class InheritedWidget extends Widget { | ||
301 | {bool parentUsesSize = false}) { | 353 | {bool parentUsesSize = false}) { |
302 | _context = inherited != null ? context.inheritFrom(inherited!) : context; | 354 | _context = inherited != null ? context.inheritFrom(inherited!) : context; |
303 | _child = build!(_context!); | 355 | _child = build!(_context!); |
304 | - | ||
305 | - if (_child != null) { | ||
306 | - _child!.layout(_context!, constraints, parentUsesSize: parentUsesSize); | ||
307 | - assert(_child!.box != null); | ||
308 | - box = _child!.box; | ||
309 | - } else { | ||
310 | - box = PdfRect.fromPoints(PdfPoint.zero, constraints.smallest); | ||
311 | - } | 356 | + super.layout(_context!, constraints); |
312 | } | 357 | } |
313 | 358 | ||
314 | @override | 359 | @override |
315 | void paint(Context context) { | 360 | void paint(Context context) { |
316 | assert(_context != null); | 361 | assert(_context != null); |
317 | super.paint(_context!); | 362 | super.paint(_context!); |
318 | - | ||
319 | - if (_child != null) { | ||
320 | - final mat = Matrix4.identity(); | ||
321 | - mat.translate(box!.x, box!.y); | ||
322 | - context.canvas | ||
323 | - ..saveContext() | ||
324 | - ..setTransform(mat); | ||
325 | - _child!.paint(_context!); | ||
326 | - context.canvas.restoreContext(); | ||
327 | - } | 363 | + paintChild(_context!); |
328 | } | 364 | } |
329 | } | 365 | } |
@@ -67,7 +67,7 @@ class _WrapContext extends WidgetContext { | @@ -67,7 +67,7 @@ class _WrapContext extends WidgetContext { | ||
67 | } | 67 | } |
68 | 68 | ||
69 | /// A widget that displays its children in multiple horizontal or vertical runs. | 69 | /// A widget that displays its children in multiple horizontal or vertical runs. |
70 | -class Wrap extends MultiChildWidget implements SpanningWidget { | 70 | +class Wrap extends MultiChildWidget with SpanningWidget { |
71 | /// Creates a wrap layout. | 71 | /// Creates a wrap layout. |
72 | 72 | ||
73 | Wrap({ | 73 | Wrap({ |
-
Please register or login to post a comment