David PHAM-VAN

Improve Table Of Content

@@ -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();
  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 +}
No preview for this file type