Showing
8 changed files
with
55 additions
and
36 deletions
1 | # Changelog | 1 | # Changelog |
2 | 2 | ||
3 | +## 3.8.4 | ||
4 | + | ||
5 | +- Improve Multi-Page layout | ||
6 | + | ||
3 | ## 3.8.3 | 7 | ## 3.8.3 |
4 | 8 | ||
5 | - Fix Arabic TextAlign.justify issues Set default text align based on text direction [Milad akarie] | 9 | - Fix Arabic TextAlign.justify issues Set default text align based on text direction [Milad akarie] |
@@ -35,17 +35,13 @@ class _GridViewContext extends WidgetContext { | @@ -35,17 +35,13 @@ class _GridViewContext extends WidgetContext { | ||
35 | void apply(_GridViewContext other) { | 35 | void apply(_GridViewContext other) { |
36 | firstChild = other.firstChild; | 36 | firstChild = other.firstChild; |
37 | lastChild = other.lastChild; | 37 | lastChild = other.lastChild; |
38 | - childCrossAxis = other.childCrossAxis; | ||
39 | - childMainAxis = other.childMainAxis; | 38 | + childCrossAxis = other.childCrossAxis ?? childCrossAxis; |
39 | + childMainAxis = other.childMainAxis ?? childMainAxis; | ||
40 | } | 40 | } |
41 | 41 | ||
42 | @override | 42 | @override |
43 | WidgetContext clone() { | 43 | WidgetContext clone() { |
44 | - return _GridViewContext() | ||
45 | - ..firstChild = firstChild | ||
46 | - ..lastChild = lastChild | ||
47 | - ..childCrossAxis = childCrossAxis | ||
48 | - ..childMainAxis = childMainAxis; | 44 | + return _GridViewContext()..apply(this); |
49 | } | 45 | } |
50 | 46 | ||
51 | @override | 47 | @override |
@@ -32,8 +32,11 @@ import 'theme.dart'; | @@ -32,8 +32,11 @@ import 'theme.dart'; | ||
32 | import 'widget.dart'; | 32 | import 'widget.dart'; |
33 | 33 | ||
34 | abstract class WidgetContext { | 34 | abstract class WidgetContext { |
35 | + /// Called after layout to save the state | ||
35 | WidgetContext clone(); | 36 | WidgetContext clone(); |
36 | 37 | ||
38 | + /// Called before relayout to restore the saved state and | ||
39 | + /// restart the layout in the same conditions | ||
37 | void apply(covariant WidgetContext other); | 40 | void apply(covariant WidgetContext other); |
38 | } | 41 | } |
39 | 42 | ||
@@ -46,9 +49,20 @@ mixin SpanningWidget on Widget { | @@ -46,9 +49,20 @@ mixin SpanningWidget on Widget { | ||
46 | @protected | 49 | @protected |
47 | WidgetContext saveContext(); | 50 | WidgetContext saveContext(); |
48 | 51 | ||
49 | - /// Apply the context for next layout | 52 | + /// Apply the context for next page layout. |
53 | + /// Called before layout to prepare for next page | ||
50 | @protected | 54 | @protected |
51 | void restoreContext(covariant WidgetContext context); | 55 | void restoreContext(covariant WidgetContext context); |
56 | + | ||
57 | + /// Called after layout to save the state | ||
58 | + @protected | ||
59 | + WidgetContext cloneContext() => saveContext().clone(); | ||
60 | + | ||
61 | + /// Called before relayout to restore the saved state and | ||
62 | + /// restart the layout in the same conditions | ||
63 | + @protected | ||
64 | + void applyContext(covariant WidgetContext context) => | ||
65 | + saveContext().apply(context); | ||
52 | } | 66 | } |
53 | 67 | ||
54 | class NewPage extends Widget { | 68 | class NewPage extends Widget { |
@@ -88,7 +102,7 @@ class _MultiPageInstance { | @@ -88,7 +102,7 @@ class _MultiPageInstance { | ||
88 | final List<_MultiPageWidget> widgets = <_MultiPageWidget>[]; | 102 | final List<_MultiPageWidget> widgets = <_MultiPageWidget>[]; |
89 | } | 103 | } |
90 | 104 | ||
91 | -/// Create a mult-page section, with automatic overflow from one page to another | 105 | +/// Create a multi-page section, with automatic overflow from one page to another |
92 | /// | 106 | /// |
93 | /// ```dart | 107 | /// ```dart |
94 | /// final pdf = Document(); | 108 | /// final pdf = Document(); |
@@ -101,7 +115,7 @@ class _MultiPageInstance { | @@ -101,7 +115,7 @@ class _MultiPageInstance { | ||
101 | /// ``` | 115 | /// ``` |
102 | /// | 116 | /// |
103 | /// An inner widget tree cannot be bigger than a page: A [Widget] cannot be drawn | 117 | /// An inner widget tree cannot be bigger than a page: A [Widget] cannot be drawn |
104 | -/// partially on one page and the remaining on another page: It's insecable. | 118 | +/// partially on one page and the remaining on another page: It's unbreakable. |
105 | /// | 119 | /// |
106 | /// A small set of [Widget] can automatically span over multiple pages, and can | 120 | /// A small set of [Widget] can automatically span over multiple pages, and can |
107 | /// be used as a direct child of the build method: [Flex], [Partition], [Table], [Wrap], | 121 | /// be used as a direct child of the build method: [Flex], [Partition], [Table], [Wrap], |
@@ -288,9 +302,13 @@ class MultiPage extends Page { | @@ -288,9 +302,13 @@ class MultiPage extends Page { | ||
288 | } | 302 | } |
289 | 303 | ||
290 | // If we are processing a multi-page widget, we restore its context | 304 | // If we are processing a multi-page widget, we restore its context |
291 | - if (widgetContext != null && child is SpanningWidget) { | ||
292 | - child.restoreContext(widgetContext); | ||
293 | - widgetContext = null; | 305 | + WidgetContext? savedContext; |
306 | + if (child is SpanningWidget && child.canSpan) { | ||
307 | + if (widgetContext != null) { | ||
308 | + child.restoreContext(widgetContext); | ||
309 | + widgetContext = null; | ||
310 | + } | ||
311 | + savedContext = child.cloneContext(); | ||
294 | } | 312 | } |
295 | 313 | ||
296 | child.layout(context, constraints, parentUsesSize: false); | 314 | child.layout(context, constraints, parentUsesSize: false); |
@@ -307,7 +325,7 @@ class MultiPage extends Page { | @@ -307,7 +325,7 @@ class MultiPage extends Page { | ||
307 | continue; | 325 | continue; |
308 | } | 326 | } |
309 | 327 | ||
310 | - // Else we crash if the widget is too big and cannot be splitted | 328 | + // Else we crash if the widget is too big and cannot be separated |
311 | if (!canSpan) { | 329 | if (!canSpan) { |
312 | throw Exception( | 330 | throw Exception( |
313 | 'Widget won\'t fit into the page as its height (${child.box!.height}) ' | 331 | 'Widget won\'t fit into the page as its height (${child.box!.height}) ' |
@@ -317,14 +335,19 @@ class MultiPage extends Page { | @@ -317,14 +335,19 @@ class MultiPage extends Page { | ||
317 | 335 | ||
318 | final span = child as SpanningWidget; | 336 | final span = child as SpanningWidget; |
319 | 337 | ||
338 | + if (savedContext != null) { | ||
339 | + // Restore saved context | ||
340 | + span.applyContext(savedContext); | ||
341 | + } | ||
342 | + | ||
320 | final localConstraints = | 343 | final localConstraints = |
321 | constraints.copyWith(maxHeight: offsetStart - offsetEnd); | 344 | constraints.copyWith(maxHeight: offsetStart - offsetEnd); |
322 | - child.layout(context, localConstraints, parentUsesSize: false); | ||
323 | - assert(child.box != null); | 345 | + span.layout(context, localConstraints, parentUsesSize: false); |
346 | + assert(span.box != null); | ||
324 | widgetContext = span.saveContext(); | 347 | widgetContext = span.saveContext(); |
325 | _pages.last.widgets.add( | 348 | _pages.last.widgets.add( |
326 | _MultiPageWidget( | 349 | _MultiPageWidget( |
327 | - child: child, | 350 | + child: span, |
328 | constraints: localConstraints, | 351 | constraints: localConstraints, |
329 | widgetContext: widgetContext.clone(), | 352 | widgetContext: widgetContext.clone(), |
330 | ), | 353 | ), |
@@ -345,9 +368,8 @@ class MultiPage extends Page { | @@ -345,9 +368,8 @@ class MultiPage extends Page { | ||
345 | _MultiPageWidget( | 368 | _MultiPageWidget( |
346 | child: child, | 369 | child: child, |
347 | constraints: constraints, | 370 | constraints: constraints, |
348 | - widgetContext: child is SpanningWidget && canSpan | ||
349 | - ? child.saveContext().clone() | ||
350 | - : null, | 371 | + widgetContext: |
372 | + child is SpanningWidget && canSpan ? child.cloneContext() : null, | ||
351 | ), | 373 | ), |
352 | ); | 374 | ); |
353 | 375 | ||
@@ -394,8 +416,7 @@ class MultiPage extends Page { | @@ -394,8 +416,7 @@ class MultiPage extends Page { | ||
394 | lastFlexChild = child; | 416 | lastFlexChild = child; |
395 | } else { | 417 | } else { |
396 | if (child is SpanningWidget && child.canSpan) { | 418 | if (child is SpanningWidget && child.canSpan) { |
397 | - final context = child.saveContext(); | ||
398 | - context.apply(widget.widgetContext!); | 419 | + child.applyContext(widget.widgetContext!); |
399 | } | 420 | } |
400 | 421 | ||
401 | child.layout(page.context, widget.constraints, parentUsesSize: false); | 422 | child.layout(page.context, widget.constraints, parentUsesSize: false); |
@@ -522,6 +543,10 @@ class MultiPage extends Page { | @@ -522,6 +543,10 @@ class MultiPage extends Page { | ||
522 | x = 0; | 543 | x = 0; |
523 | break; | 544 | break; |
524 | } | 545 | } |
546 | + final child = widget.child; | ||
547 | + if (child is SpanningWidget && child.canSpan) { | ||
548 | + child.applyContext(widget.widgetContext!); | ||
549 | + } | ||
525 | _paintChild(page.context, widget.child, _margin.left + x, pos, | 550 | _paintChild(page.context, widget.child, _margin.left + x, pos, |
526 | pageFormat.height); | 551 | pageFormat.height); |
527 | pos -= betweenSpace; | 552 | pos -= betweenSpace; |
@@ -84,11 +84,9 @@ class _PartitionsContext extends WidgetContext { | @@ -84,11 +84,9 @@ class _PartitionsContext extends WidgetContext { | ||
84 | final List<WidgetContext?> partitionContext; | 84 | final List<WidgetContext?> partitionContext; |
85 | 85 | ||
86 | @override | 86 | @override |
87 | - void apply(WidgetContext other) { | ||
88 | - if (other is _PartitionsContext) { | ||
89 | - for (var index = 0; index < partitionContext.length; index++) { | ||
90 | - partitionContext[index]?.apply(other.partitionContext[index]!); | ||
91 | - } | 87 | + void apply(_PartitionsContext other) { |
88 | + for (var index = 0; index < partitionContext.length; index++) { | ||
89 | + partitionContext[index]?.apply(other.partitionContext[index]!); | ||
92 | } | 90 | } |
93 | } | 91 | } |
94 | 92 | ||
@@ -220,7 +218,7 @@ class Partitions extends Widget with SpanningWidget { | @@ -220,7 +218,7 @@ class Partitions extends Widget with SpanningWidget { | ||
220 | } | 218 | } |
221 | 219 | ||
222 | @override | 220 | @override |
223 | - void restoreContext(WidgetContext context) { | 221 | + void restoreContext(_PartitionsContext context) { |
224 | _context.apply(context); | 222 | _context.apply(context); |
225 | var index = 0; | 223 | var index = 0; |
226 | for (final child in children) { | 224 | for (final child in children) { |
@@ -148,9 +148,7 @@ class _TableContext extends WidgetContext { | @@ -148,9 +148,7 @@ class _TableContext extends WidgetContext { | ||
148 | 148 | ||
149 | @override | 149 | @override |
150 | WidgetContext clone() { | 150 | WidgetContext clone() { |
151 | - return _TableContext() | ||
152 | - ..firstLine = firstLine | ||
153 | - ..lastLine = lastLine; | 151 | + return _TableContext()..apply(this); |
154 | } | 152 | } |
155 | 153 | ||
156 | @override | 154 | @override |
@@ -1294,7 +1294,7 @@ class RichText extends Widget with SpanningWidget { | @@ -1294,7 +1294,7 @@ class RichText extends Widget with SpanningWidget { | ||
1294 | bool get canSpan => overflow == TextOverflow.span; | 1294 | bool get canSpan => overflow == TextOverflow.span; |
1295 | 1295 | ||
1296 | @override | 1296 | @override |
1297 | - bool get hasMoreWidgets => overflow == TextOverflow.span; | 1297 | + bool get hasMoreWidgets => canSpan; |
1298 | 1298 | ||
1299 | @override | 1299 | @override |
1300 | void restoreContext(_RichTextContext context) { | 1300 | void restoreContext(_RichTextContext context) { |
@@ -57,9 +57,7 @@ class _WrapContext extends WidgetContext { | @@ -57,9 +57,7 @@ class _WrapContext extends WidgetContext { | ||
57 | 57 | ||
58 | @override | 58 | @override |
59 | WidgetContext clone() { | 59 | WidgetContext clone() { |
60 | - return _WrapContext() | ||
61 | - ..firstChild = firstChild | ||
62 | - ..lastChild = lastChild; | 60 | + return _WrapContext()..apply(this); |
63 | } | 61 | } |
64 | 62 | ||
65 | @override | 63 | @override |
@@ -3,7 +3,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl | @@ -3,7 +3,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl | ||
3 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf | 3 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf |
4 | repository: https://github.com/DavBfr/dart_pdf | 4 | repository: https://github.com/DavBfr/dart_pdf |
5 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues | 5 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues |
6 | -version: 3.8.3 | 6 | +version: 3.8.4 |
7 | 7 | ||
8 | environment: | 8 | environment: |
9 | sdk: ">=2.12.0 <3.0.0" | 9 | sdk: ">=2.12.0 <3.0.0" |
-
Please register or login to post a comment