Showing
8 changed files
with
141 additions
and
11 deletions
| @@ -8,6 +8,7 @@ | @@ -8,6 +8,7 @@ | ||
| 8 | - Typo: rename "litteral" with "literal" | 8 | - Typo: rename "litteral" with "literal" |
| 9 | - Fix tabs and other spaces placeholder | 9 | - Fix tabs and other spaces placeholder |
| 10 | - Prevent modifying the document once saved | 10 | - Prevent modifying the document once saved |
| 11 | +- Improve Table Of Content | ||
| 11 | 12 | ||
| 12 | ## 3.7.4 | 13 | ## 3.7.4 |
| 13 | 14 |
| @@ -58,7 +58,7 @@ class PdfOutline extends PdfObjectDict { | @@ -58,7 +58,7 @@ class PdfOutline extends PdfObjectDict { | ||
| 58 | this.color, | 58 | this.color, |
| 59 | this.destMode = PdfOutlineMode.fitPage, | 59 | this.destMode = PdfOutlineMode.fitPage, |
| 60 | this.style = PdfOutlineStyle.normal, | 60 | this.style = PdfOutlineStyle.normal, |
| 61 | - String? page, | 61 | + PdfPage? page, |
| 62 | }) : assert(anchor == null || (dest == null && rect == null)), | 62 | }) : assert(anchor == null || (dest == null && rect == null)), |
| 63 | _page = page, | 63 | _page = page, |
| 64 | super(pdfDocument); | 64 | super(pdfDocument); |
| @@ -76,12 +76,20 @@ class PdfOutline extends PdfObjectDict { | @@ -76,12 +76,20 @@ class PdfOutline extends PdfObjectDict { | ||
| 76 | PdfPage? dest; | 76 | PdfPage? dest; |
| 77 | 77 | ||
| 78 | /// Page number | 78 | /// Page number |
| 79 | - String? get page => | ||
| 80 | - _page ?? | ||
| 81 | - (dest != null | ||
| 82 | - ? (pdfDocument.pdfPageList.pages.indexOf(dest!) + 1).toString() | ||
| 83 | - : null); | ||
| 84 | - final String? _page; | 79 | + String? get page { |
| 80 | + final int? num; | ||
| 81 | + if (_page != null) { | ||
| 82 | + num = pdfDocument.pdfPageList.pages.indexOf(_page!); | ||
| 83 | + } else if (dest != null) { | ||
| 84 | + num = pdfDocument.pdfPageList.pages.indexOf(dest!); | ||
| 85 | + } else { | ||
| 86 | + num = null; | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + return num == null ? null : (num + 1).toString(); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + final PdfPage? _page; | ||
| 85 | 93 | ||
| 86 | /// The region on the destination page | 94 | /// The region on the destination page |
| 87 | final PdfRect? rect; | 95 | final PdfRect? rect; |
| @@ -59,8 +59,8 @@ class Anchor extends SingleChildWidget { | @@ -59,8 +59,8 @@ class Anchor extends SingleChildWidget { | ||
| 59 | 59 | ||
| 60 | if (description != null) { | 60 | if (description != null) { |
| 61 | final rb = mat.transform3(Vector3(box!.right, box!.top, 0)); | 61 | final rb = mat.transform3(Vector3(box!.right, box!.top, 0)); |
| 62 | - final ibox = PdfRect.fromLTRB(lt.x, lt.y, rb.x, rb.y); | ||
| 63 | - PdfAnnot(context.page, PdfAnnotText(rect: ibox, content: description!)); | 62 | + final iBox = PdfRect.fromLTRB(lt.x, lt.y, rb.x, rb.y); |
| 63 | + PdfAnnot(context.page, PdfAnnotText(rect: iBox, content: description!)); | ||
| 64 | } | 64 | } |
| 65 | } | 65 | } |
| 66 | } | 66 | } |
| @@ -622,7 +622,7 @@ class Outline extends Anchor { | @@ -622,7 +622,7 @@ class Outline extends Anchor { | ||
| 622 | anchor: name, | 622 | anchor: name, |
| 623 | color: color, | 623 | color: color, |
| 624 | style: style, | 624 | style: style, |
| 625 | - page: context.pageLabel, | 625 | + page: context.page, |
| 626 | )..effectiveLevel = level; | 626 | )..effectiveLevel = level; |
| 627 | 627 | ||
| 628 | final root = context.document.outline; | 628 | final root = context.document.outline; |
| @@ -151,7 +151,7 @@ class TableOfContent extends StatelessWidget { | @@ -151,7 +151,7 @@ class TableOfContent extends StatelessWidget { | ||
| 151 | thickness: 0.2, | 151 | thickness: 0.2, |
| 152 | )), | 152 | )), |
| 153 | SizedBox(width: 8), | 153 | SizedBox(width: 8), |
| 154 | - Text('${c.page}'), | 154 | + DelayedWidget(build: (_) => Text('${c.page}')), |
| 155 | ], | 155 | ], |
| 156 | ), | 156 | ), |
| 157 | ), | 157 | ), |
| @@ -380,3 +380,37 @@ class InheritedWidget extends SingleChildWidget { | @@ -380,3 +380,37 @@ class InheritedWidget extends SingleChildWidget { | ||
| 380 | paintChild(_context!); | 380 | paintChild(_context!); |
| 381 | } | 381 | } |
| 382 | } | 382 | } |
| 383 | + | ||
| 384 | +class DelayedWidget extends SingleChildWidget { | ||
| 385 | + DelayedWidget({required this.build}) : super(); | ||
| 386 | + | ||
| 387 | + final BuildCallback build; | ||
| 388 | + | ||
| 389 | + @override | ||
| 390 | + Widget? get child => _child; | ||
| 391 | + | ||
| 392 | + Widget? _child; | ||
| 393 | + | ||
| 394 | + @override | ||
| 395 | + void layout(Context context, BoxConstraints constraints, | ||
| 396 | + {bool parentUsesSize = false}) { | ||
| 397 | + _child = build(context); | ||
| 398 | + super.layout(context, constraints); | ||
| 399 | + } | ||
| 400 | + | ||
| 401 | + void delayedPaint(Context context) { | ||
| 402 | + _child = build(context); | ||
| 403 | + child!.layout( | ||
| 404 | + context, | ||
| 405 | + BoxConstraints.tight(box!.size), | ||
| 406 | + parentUsesSize: false, | ||
| 407 | + ); | ||
| 408 | + paintChild(context); | ||
| 409 | + } | ||
| 410 | + | ||
| 411 | + @override | ||
| 412 | + void paint(Context context) { | ||
| 413 | + delayedPaint(context); | ||
| 414 | + super.paint(context); | ||
| 415 | + } | ||
| 416 | +} |
| @@ -48,6 +48,7 @@ import 'widget_table_test.dart' as widget_table; | @@ -48,6 +48,7 @@ import 'widget_table_test.dart' as widget_table; | ||
| 48 | import 'widget_test.dart' as widget; | 48 | import 'widget_test.dart' as widget; |
| 49 | import 'widget_text_test.dart' as widget_text; | 49 | import 'widget_text_test.dart' as widget_text; |
| 50 | import 'widget_theme_test.dart' as widget_theme; | 50 | import 'widget_theme_test.dart' as widget_theme; |
| 51 | +import 'widget_toc_test.dart' as widget_toc; | ||
| 51 | import 'widget_watermark_test.dart' as widget_watermark; | 52 | import 'widget_watermark_test.dart' as widget_watermark; |
| 52 | import 'widget_wrap_test.dart' as widget_wrap; | 53 | import 'widget_wrap_test.dart' as widget_wrap; |
| 53 | 54 | ||
| @@ -83,6 +84,7 @@ void main() { | @@ -83,6 +84,7 @@ void main() { | ||
| 83 | widget_table.main(); | 84 | widget_table.main(); |
| 84 | widget_text.main(); | 85 | widget_text.main(); |
| 85 | widget_theme.main(); | 86 | widget_theme.main(); |
| 87 | + widget_toc.main(); | ||
| 86 | widget_watermark.main(); | 88 | widget_watermark.main(); |
| 87 | widget_wrap.main(); | 89 | widget_wrap.main(); |
| 88 | widget.main(); | 90 | widget.main(); |
pdf/test/widget_toc_test.dart
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | +import 'dart:io'; | ||
| 18 | +import 'dart:math'; | ||
| 19 | + | ||
| 20 | +import 'package:pdf/widgets.dart'; | ||
| 21 | +import 'package:test/test.dart'; | ||
| 22 | + | ||
| 23 | +late Document pdf; | ||
| 24 | + | ||
| 25 | +void main() { | ||
| 26 | + setUpAll(() { | ||
| 27 | + Document.debug = true; | ||
| 28 | + pdf = Document(); | ||
| 29 | + }); | ||
| 30 | + | ||
| 31 | + test('Pdf Widgets TableOfContent', () { | ||
| 32 | + pdf.addPage( | ||
| 33 | + Page( | ||
| 34 | + build: (context) => | ||
| 35 | + Center(child: Text('Document', style: Theme.of(context).header0)), | ||
| 36 | + ), | ||
| 37 | + ); | ||
| 38 | + | ||
| 39 | + pdf.addPage( | ||
| 40 | + MultiPage( | ||
| 41 | + footer: (c) => Padding( | ||
| 42 | + padding: const EdgeInsets.only(top: 20), | ||
| 43 | + child: Align( | ||
| 44 | + alignment: Alignment.centerRight, child: Text(c.pageLabel))), | ||
| 45 | + build: (context) => [ | ||
| 46 | + ...Iterable<Widget>.generate(40, (index) { | ||
| 47 | + final level = (sin(index / 5) * 6).abs().toInt(); | ||
| 48 | + return Column( | ||
| 49 | + children: [ | ||
| 50 | + Header( | ||
| 51 | + child: Text('Hello $index level $level'), | ||
| 52 | + text: 'Hello $index', | ||
| 53 | + level: level, | ||
| 54 | + ), | ||
| 55 | + Lorem(length: 60), | ||
| 56 | + ], | ||
| 57 | + ); | ||
| 58 | + }), | ||
| 59 | + ], | ||
| 60 | + ), | ||
| 61 | + ); | ||
| 62 | + | ||
| 63 | + pdf.addPage( | ||
| 64 | + MultiPage( | ||
| 65 | + footer: (c) => Padding( | ||
| 66 | + padding: const EdgeInsets.only(top: 20), | ||
| 67 | + child: Align( | ||
| 68 | + alignment: Alignment.centerRight, child: Text(c.pageLabel))), | ||
| 69 | + build: (context) => [ | ||
| 70 | + Center( | ||
| 71 | + child: | ||
| 72 | + Text('Table of content', style: Theme.of(context).header0)), | ||
| 73 | + SizedBox(height: 20), | ||
| 74 | + TableOfContent(), | ||
| 75 | + ], | ||
| 76 | + ), | ||
| 77 | + index: 1, | ||
| 78 | + ); | ||
| 79 | + }); | ||
| 80 | + | ||
| 81 | + tearDownAll(() async { | ||
| 82 | + final file = File('widgets-toc.pdf'); | ||
| 83 | + await file.writeAsBytes(await pdf.save()); | ||
| 84 | + }); | ||
| 85 | +} |
test/golden/widgets-toc.pdf
0 → 100644
No preview for this file type
-
Please register or login to post a comment