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