Showing
7 changed files
with
215 additions
and
36 deletions
@@ -37,6 +37,7 @@ part 'widgets/grid_view.dart'; | @@ -37,6 +37,7 @@ part 'widgets/grid_view.dart'; | ||
37 | part 'widgets/image.dart'; | 37 | part 'widgets/image.dart'; |
38 | part 'widgets/multi_page.dart'; | 38 | part 'widgets/multi_page.dart'; |
39 | part 'widgets/page.dart'; | 39 | part 'widgets/page.dart'; |
40 | +part 'widgets/page_theme.dart'; | ||
40 | part 'widgets/placeholders.dart'; | 41 | part 'widgets/placeholders.dart'; |
41 | part 'widgets/progress.dart'; | 42 | part 'widgets/progress.dart'; |
42 | part 'widgets/stack.dart'; | 43 | part 'widgets/stack.dart'; |
@@ -40,27 +40,31 @@ class _MultiPageInstance { | @@ -40,27 +40,31 @@ class _MultiPageInstance { | ||
40 | const _MultiPageInstance( | 40 | const _MultiPageInstance( |
41 | {@required this.context, | 41 | {@required this.context, |
42 | @required this.constraints, | 42 | @required this.constraints, |
43 | + @required this.fullConstraints, | ||
43 | @required this.offsetStart}); | 44 | @required this.offsetStart}); |
44 | 45 | ||
45 | final Context context; | 46 | final Context context; |
46 | final BoxConstraints constraints; | 47 | final BoxConstraints constraints; |
48 | + final BoxConstraints fullConstraints; | ||
47 | final double offsetStart; | 49 | final double offsetStart; |
48 | } | 50 | } |
49 | 51 | ||
50 | class MultiPage extends Page { | 52 | class MultiPage extends Page { |
51 | MultiPage( | 53 | MultiPage( |
52 | - {PdfPageFormat pageFormat = PdfPageFormat.a4, | 54 | + {PageTheme pageTheme, |
55 | + PdfPageFormat pageFormat, | ||
53 | BuildListCallback build, | 56 | BuildListCallback build, |
54 | this.crossAxisAlignment = CrossAxisAlignment.start, | 57 | this.crossAxisAlignment = CrossAxisAlignment.start, |
55 | this.header, | 58 | this.header, |
56 | this.footer, | 59 | this.footer, |
57 | Theme theme, | 60 | Theme theme, |
58 | this.maxPages = 20, | 61 | this.maxPages = 20, |
59 | - PageOrientation orientation = PageOrientation.natural, | 62 | + PageOrientation orientation, |
60 | EdgeInsets margin}) | 63 | EdgeInsets margin}) |
61 | : _buildList = build, | 64 | : _buildList = build, |
62 | assert(maxPages != null && maxPages > 0), | 65 | assert(maxPages != null && maxPages > 0), |
63 | super( | 66 | super( |
67 | + pageTheme: pageTheme, | ||
64 | pageFormat: pageFormat, | 68 | pageFormat: pageFormat, |
65 | margin: margin, | 69 | margin: margin, |
66 | theme: theme, | 70 | theme: theme, |
@@ -88,6 +92,7 @@ class MultiPage extends Page { | @@ -88,6 +92,7 @@ class MultiPage extends Page { | ||
88 | ..rotateZ(-math.pi / 2) | 92 | ..rotateZ(-math.pi / 2) |
89 | ..translate(x - pageHeight + _margin.top - _margin.left, | 93 | ..translate(x - pageHeight + _margin.top - _margin.left, |
90 | y + _margin.left - _margin.bottom)); | 94 | y + _margin.left - _margin.bottom)); |
95 | + | ||
91 | child.paint(context); | 96 | child.paint(context); |
92 | context.canvas.restoreContext(); | 97 | context.canvas.restoreContext(); |
93 | } else { | 98 | } else { |
@@ -112,6 +117,13 @@ class MultiPage extends Page { | @@ -112,6 +117,13 @@ class MultiPage extends Page { | ||
112 | maxWidth: _mustRotate | 117 | maxWidth: _mustRotate |
113 | ? (pageFormat.height - _margin.vertical) | 118 | ? (pageFormat.height - _margin.vertical) |
114 | : (pageFormat.width - _margin.horizontal)); | 119 | : (pageFormat.width - _margin.horizontal)); |
120 | + final BoxConstraints fullConstraints = mustRotate | ||
121 | + ? BoxConstraints( | ||
122 | + maxWidth: pageFormat.height - _margin.vertical, | ||
123 | + maxHeight: pageFormat.width - _margin.horizontal) | ||
124 | + : BoxConstraints( | ||
125 | + maxWidth: pageFormat.width - _margin.horizontal, | ||
126 | + maxHeight: pageFormat.height - _margin.vertical); | ||
115 | final Theme calculatedTheme = theme ?? document.theme ?? Theme.base(); | 127 | final Theme calculatedTheme = theme ?? document.theme ?? Theme.base(); |
116 | Context context; | 128 | Context context; |
117 | double offsetEnd; | 129 | double offsetEnd; |
@@ -149,6 +161,16 @@ class MultiPage extends Page { | @@ -149,6 +161,16 @@ class MultiPage extends Page { | ||
149 | return true; | 161 | return true; |
150 | }()); | 162 | }()); |
151 | 163 | ||
164 | + if (pageTheme.buildBackground != null) { | ||
165 | + final Widget child = pageTheme.buildBackground(context); | ||
166 | + if (child != null) { | ||
167 | + child.layout(context, fullConstraints, parentUsesSize: false); | ||
168 | + assert(child.box != null); | ||
169 | + _paintChild(context, child, _margin.left, _margin.bottom, | ||
170 | + pageFormat.height); | ||
171 | + } | ||
172 | + } | ||
173 | + | ||
152 | offsetStart = pageHeight - | 174 | offsetStart = pageHeight - |
153 | (_mustRotate ? pageHeightMargin - margin.bottom : _margin.top); | 175 | (_mustRotate ? pageHeightMargin - margin.bottom : _margin.top); |
154 | offsetEnd = | 176 | offsetEnd = |
@@ -157,6 +179,7 @@ class MultiPage extends Page { | @@ -157,6 +179,7 @@ class MultiPage extends Page { | ||
157 | _pages.add(_MultiPageInstance( | 179 | _pages.add(_MultiPageInstance( |
158 | context: context, | 180 | context: context, |
159 | constraints: constraints, | 181 | constraints: constraints, |
182 | + fullConstraints: fullConstraints, | ||
160 | offsetStart: offsetStart, | 183 | offsetStart: offsetStart, |
161 | )); | 184 | )); |
162 | 185 | ||
@@ -262,6 +285,17 @@ class MultiPage extends Page { | @@ -262,6 +285,17 @@ class MultiPage extends Page { | ||
262 | pageFormat.height); | 285 | pageFormat.height); |
263 | } | 286 | } |
264 | } | 287 | } |
288 | + | ||
289 | + if (pageTheme.buildForeground != null) { | ||
290 | + final Widget child = pageTheme.buildForeground(page.context); | ||
291 | + if (child != null) { | ||
292 | + child.layout(page.context, page.fullConstraints, | ||
293 | + parentUsesSize: false); | ||
294 | + assert(child.box != null); | ||
295 | + _paintChild(page.context, child, _margin.left, _margin.bottom, | ||
296 | + pageFormat.height); | ||
297 | + } | ||
298 | + } | ||
265 | } | 299 | } |
266 | } | 300 | } |
267 | } | 301 | } |
@@ -23,51 +23,43 @@ enum PageOrientation { natural, landscape, portrait } | @@ -23,51 +23,43 @@ enum PageOrientation { natural, landscape, portrait } | ||
23 | 23 | ||
24 | class Page { | 24 | class Page { |
25 | Page( | 25 | Page( |
26 | - {this.pageFormat = PdfPageFormat.standard, | 26 | + {PageTheme pageTheme, |
27 | + PdfPageFormat pageFormat, | ||
27 | BuildCallback build, | 28 | BuildCallback build, |
28 | - this.theme, | ||
29 | - this.orientation = PageOrientation.natural, | 29 | + Theme theme, |
30 | + PageOrientation orientation, | ||
30 | EdgeInsets margin}) | 31 | EdgeInsets margin}) |
31 | - : assert(pageFormat != null), | ||
32 | - _margin = margin, | 32 | + : assert( |
33 | + pageTheme == null || | ||
34 | + (pageFormat == null && | ||
35 | + theme == null && | ||
36 | + orientation == null && | ||
37 | + margin == null), | ||
38 | + 'Don\'t set both pageTheme and other settings'), | ||
39 | + pageTheme = pageTheme ?? | ||
40 | + PageTheme( | ||
41 | + pageFormat: pageFormat, | ||
42 | + orientation: orientation, | ||
43 | + margin: margin, | ||
44 | + theme: theme, | ||
45 | + ), | ||
33 | _build = build; | 46 | _build = build; |
34 | 47 | ||
35 | - final PdfPageFormat pageFormat; | 48 | + final PageTheme pageTheme; |
36 | 49 | ||
37 | - final PageOrientation orientation; | 50 | + PdfPageFormat get pageFormat => pageTheme.pageFormat; |
38 | 51 | ||
39 | - final EdgeInsets _margin; | 52 | + PageOrientation get orientation => pageTheme.orientation; |
40 | 53 | ||
41 | final BuildCallback _build; | 54 | final BuildCallback _build; |
42 | 55 | ||
43 | - final Theme theme; | 56 | + Theme get theme => pageTheme.theme; |
44 | 57 | ||
45 | - bool get mustRotate => | ||
46 | - (orientation == PageOrientation.landscape && | ||
47 | - pageFormat.height > pageFormat.width) || | ||
48 | - (orientation == PageOrientation.portrait && | ||
49 | - pageFormat.width > pageFormat.height); | 58 | + bool get mustRotate => pageTheme.mustRotate; |
50 | 59 | ||
51 | PdfPage _pdfPage; | 60 | PdfPage _pdfPage; |
52 | 61 | ||
53 | - EdgeInsets get margin { | ||
54 | - if (_margin != null) { | ||
55 | - if (mustRotate) { | ||
56 | - return EdgeInsets.fromLTRB( | ||
57 | - _margin.bottom, _margin.left, _margin.top, _margin.right); | ||
58 | - } else { | ||
59 | - return _margin; | ||
60 | - } | ||
61 | - } | ||
62 | - | ||
63 | - if (mustRotate) { | ||
64 | - return EdgeInsets.fromLTRB(pageFormat.marginBottom, pageFormat.marginLeft, | ||
65 | - pageFormat.marginTop, pageFormat.marginRight); | ||
66 | - } else { | ||
67 | - return EdgeInsets.fromLTRB(pageFormat.marginLeft, pageFormat.marginTop, | ||
68 | - pageFormat.marginRight, pageFormat.marginBottom); | ||
69 | - } | ||
70 | - } | 62 | + EdgeInsets get margin => pageTheme.margin; |
71 | 63 | ||
72 | @protected | 64 | @protected |
73 | void debugPaint(Context context) { | 65 | void debugPaint(Context context) { |
@@ -109,10 +101,26 @@ class Page { | @@ -109,10 +101,26 @@ class Page { | ||
109 | page: _pdfPage, | 101 | page: _pdfPage, |
110 | canvas: canvas, | 102 | canvas: canvas, |
111 | ).inheritFrom(calculatedTheme); | 103 | ).inheritFrom(calculatedTheme); |
104 | + if (pageTheme.buildBackground != null) { | ||
105 | + final Widget child = pageTheme.buildBackground(context); | ||
106 | + if (child != null) { | ||
107 | + layout(child, context, constraints); | ||
108 | + paint(child, context); | ||
109 | + } | ||
110 | + } | ||
112 | if (_build != null) { | 111 | if (_build != null) { |
113 | final Widget child = _build(context); | 112 | final Widget child = _build(context); |
114 | - layout(child, context, constraints); | ||
115 | - paint(child, context); | 113 | + if (child != null) { |
114 | + layout(child, context, constraints); | ||
115 | + paint(child, context); | ||
116 | + } | ||
117 | + } | ||
118 | + if (pageTheme.buildForeground != null) { | ||
119 | + final Widget child = pageTheme.buildForeground(context); | ||
120 | + if (child != null) { | ||
121 | + layout(child, context, constraints); | ||
122 | + paint(child, context); | ||
123 | + } | ||
116 | } | 124 | } |
117 | } | 125 | } |
118 | 126 |
pdf/lib/widgets/page_theme.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 | +part of widget; | ||
18 | + | ||
19 | +@immutable | ||
20 | +class PageTheme { | ||
21 | + const PageTheme( | ||
22 | + {PdfPageFormat pageFormat, | ||
23 | + this.buildBackground, | ||
24 | + this.buildForeground, | ||
25 | + this.theme, | ||
26 | + PageOrientation orientation, | ||
27 | + EdgeInsets margin}) | ||
28 | + : pageFormat = pageFormat ?? PdfPageFormat.standard, | ||
29 | + orientation = orientation ?? PageOrientation.natural, | ||
30 | + _margin = margin; | ||
31 | + | ||
32 | + final PdfPageFormat pageFormat; | ||
33 | + | ||
34 | + final PageOrientation orientation; | ||
35 | + | ||
36 | + final EdgeInsets _margin; | ||
37 | + | ||
38 | + final BuildCallback buildBackground; | ||
39 | + | ||
40 | + final BuildCallback buildForeground; | ||
41 | + | ||
42 | + final Theme theme; | ||
43 | + | ||
44 | + bool get mustRotate => | ||
45 | + (orientation == PageOrientation.landscape && | ||
46 | + pageFormat.height > pageFormat.width) || | ||
47 | + (orientation == PageOrientation.portrait && | ||
48 | + pageFormat.width > pageFormat.height); | ||
49 | + | ||
50 | + EdgeInsets get margin { | ||
51 | + if (_margin != null) { | ||
52 | + if (mustRotate) { | ||
53 | + return EdgeInsets.fromLTRB( | ||
54 | + _margin.bottom, _margin.left, _margin.top, _margin.right); | ||
55 | + } else { | ||
56 | + return _margin; | ||
57 | + } | ||
58 | + } | ||
59 | + | ||
60 | + if (mustRotate) { | ||
61 | + return EdgeInsets.fromLTRB(pageFormat.marginBottom, pageFormat.marginLeft, | ||
62 | + pageFormat.marginTop, pageFormat.marginRight); | ||
63 | + } else { | ||
64 | + return EdgeInsets.fromLTRB(pageFormat.marginLeft, pageFormat.marginTop, | ||
65 | + pageFormat.marginRight, pageFormat.marginBottom); | ||
66 | + } | ||
67 | + } | ||
68 | +} |
@@ -34,6 +34,7 @@ import 'widget_table_test.dart' as widget_table; | @@ -34,6 +34,7 @@ import 'widget_table_test.dart' as widget_table; | ||
34 | import 'widget_test.dart' as widget; | 34 | import 'widget_test.dart' as widget; |
35 | import 'widget_text_test.dart' as widget_text; | 35 | import 'widget_text_test.dart' as widget_text; |
36 | import 'widget_theme_test.dart' as widget_theme; | 36 | import 'widget_theme_test.dart' as widget_theme; |
37 | +import 'widget_watermark_test.dart' as widget_watermark; | ||
37 | import 'widget_wrap_test.dart' as widget_wrap; | 38 | import 'widget_wrap_test.dart' as widget_wrap; |
38 | 39 | ||
39 | void main() { | 40 | void main() { |
@@ -54,6 +55,7 @@ void main() { | @@ -54,6 +55,7 @@ void main() { | ||
54 | widget_table.main(); | 55 | widget_table.main(); |
55 | widget_text.main(); | 56 | widget_text.main(); |
56 | widget_theme.main(); | 57 | widget_theme.main(); |
58 | + widget_watermark.main(); | ||
57 | widget_wrap.main(); | 59 | widget_wrap.main(); |
58 | widget.main(); | 60 | widget.main(); |
59 | } | 61 | } |
pdf/test/widget_watermark_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 | + | ||
19 | +import 'package:pdf/widgets.dart'; | ||
20 | +import 'package:test/test.dart'; | ||
21 | + | ||
22 | +void main() { | ||
23 | + test('Pdf Widgets Watermark', () { | ||
24 | + Document.debug = true; | ||
25 | + final Document pdf = Document(); | ||
26 | + | ||
27 | + final PageTheme pageTheme = PageTheme( | ||
28 | + buildBackground: (Context context) => Watermark.text('DRAFT'), | ||
29 | + buildForeground: (Context context) => Align( | ||
30 | + alignment: Alignment.bottomLeft, | ||
31 | + child: SizedBox( | ||
32 | + width: 100, | ||
33 | + height: 100, | ||
34 | + child: PdfLogo(), | ||
35 | + ), | ||
36 | + ), | ||
37 | + ); | ||
38 | + | ||
39 | + pdf.addPage( | ||
40 | + Page( | ||
41 | + pageTheme: pageTheme, | ||
42 | + build: (Context context) => Center( | ||
43 | + child: Text( | ||
44 | + 'Hello World', | ||
45 | + ), | ||
46 | + ), | ||
47 | + ), | ||
48 | + ); | ||
49 | + | ||
50 | + pdf.addPage( | ||
51 | + MultiPage( | ||
52 | + pageTheme: pageTheme, | ||
53 | + build: (Context context) => List<Widget>.filled( | ||
54 | + 100, | ||
55 | + Text( | ||
56 | + 'Hello World', | ||
57 | + ), | ||
58 | + ), | ||
59 | + ), | ||
60 | + ); | ||
61 | + | ||
62 | + final File file = File('widgets-watermark.pdf'); | ||
63 | + file.writeAsBytesSync(pdf.save()); | ||
64 | + }); | ||
65 | +} |
-
Please register or login to post a comment