David PHAM-VAN

Improve Multi-Page layout

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"