David PHAM-VAN

Implement InheritedWidget

@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 4
5 - Implement InlineSpan and WidgetSpan 5 - Implement InlineSpan and WidgetSpan
6 - Fix Theme.withFont factory 6 - Fix Theme.withFont factory
  7 +- Implement InheritedWidget
7 8
8 ## 1.3.17 9 ## 1.3.17
9 10
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 16
17 library widget; 17 library widget;
18 18
  19 +import 'dart:collection';
19 import 'dart:math' as math; 20 import 'dart:math' as math;
20 import 'dart:typed_data'; 21 import 'dart:typed_data';
21 22
@@ -158,13 +158,11 @@ class Page { @@ -158,13 +158,11 @@ class Page {
158 maxHeight: pageFormat.height - _margin.vertical); 158 maxHeight: pageFormat.height - _margin.vertical);
159 159
160 final Theme calculatedTheme = theme ?? document.theme ?? Theme.base(); 160 final Theme calculatedTheme = theme ?? document.theme ?? Theme.base();
161 - final Map<Type, Inherited> inherited = <Type, Inherited>{};  
162 - inherited[calculatedTheme.runtimeType] = calculatedTheme;  
163 final Context context = Context( 161 final Context context = Context(
164 document: document.document, 162 document: document.document,
165 page: _pdfPage, 163 page: _pdfPage,
166 canvas: canvas, 164 canvas: canvas,
167 - inherited: inherited); 165 + ).inheritFrom(calculatedTheme);
168 if (_build != null) { 166 if (_build != null) {
169 final Widget child = _build(context); 167 final Widget child = _build(context);
170 layout(child, context, constraints); 168 layout(child, context, constraints);
@@ -113,15 +113,13 @@ class MultiPage extends Page { @@ -113,15 +113,13 @@ class MultiPage extends Page {
113 ? (pageFormat.height - _margin.vertical) 113 ? (pageFormat.height - _margin.vertical)
114 : (pageFormat.width - _margin.horizontal)); 114 : (pageFormat.width - _margin.horizontal));
115 final Theme calculatedTheme = theme ?? document.theme ?? Theme.base(); 115 final Theme calculatedTheme = theme ?? document.theme ?? Theme.base();
116 - final Map<Type, Inherited> inherited = <Type, Inherited>{};  
117 - inherited[calculatedTheme.runtimeType] = calculatedTheme;  
118 Context context; 116 Context context;
119 double offsetEnd; 117 double offsetEnd;
120 double offsetStart; 118 double offsetStart;
121 int index = 0; 119 int index = 0;
122 int sameCount = 0; 120 int sameCount = 0;
123 final Context baseContext = 121 final Context baseContext =
124 - Context(document: document.document, inherited: inherited); 122 + Context(document: document.document).inheritFrom(calculatedTheme);
125 final List<Widget> children = _buildList(baseContext); 123 final List<Widget> children = _buildList(baseContext);
126 WidgetContext widgetContext; 124 WidgetContext widgetContext;
127 125
@@ -18,7 +18,19 @@ part of widget; @@ -18,7 +18,19 @@ part of widget;
18 18
19 @immutable 19 @immutable
20 class Context { 20 class Context {
21 - const Context({ 21 + factory Context({
  22 + @required PdfDocument document,
  23 + PdfPage page,
  24 + PdfGraphics canvas,
  25 + }) =>
  26 + Context._(
  27 + document: document,
  28 + page: page,
  29 + canvas: canvas,
  30 + inherited: HashMap<Type, Inherited>(),
  31 + );
  32 +
  33 + const Context._({
22 @required this.document, 34 @required this.document,
23 this.page, 35 this.page,
24 this.canvas, 36 this.canvas,
@@ -30,7 +42,7 @@ class Context { @@ -30,7 +42,7 @@ class Context {
30 42
31 final PdfGraphics canvas; 43 final PdfGraphics canvas;
32 44
33 - final Map<Type, Inherited> inherited; 45 + final HashMap<Type, Inherited> inherited;
34 46
35 final PdfDocument document; 47 final PdfDocument document;
36 48
@@ -45,8 +57,8 @@ class Context { @@ -45,8 +57,8 @@ class Context {
45 {PdfPage page, 57 {PdfPage page,
46 PdfGraphics canvas, 58 PdfGraphics canvas,
47 Matrix4 ctm, 59 Matrix4 ctm,
48 - Map<Type, Inherited> inherited}) {  
49 - return Context( 60 + HashMap<Type, Inherited> inherited}) {
  61 + return Context._(
50 document: document, 62 document: document,
51 page: page ?? this.page, 63 page: page ?? this.page,
52 canvas: canvas ?? this.canvas, 64 canvas: canvas ?? this.canvas,
@@ -54,7 +66,8 @@ class Context { @@ -54,7 +66,8 @@ class Context {
54 } 66 }
55 67
56 Context inheritFrom(Inherited object) { 68 Context inheritFrom(Inherited object) {
57 - final Map<Type, Inherited> inherited = this.inherited; 69 + final HashMap<Type, Inherited> inherited =
  70 + HashMap<Type, Inherited>.of(this.inherited);
58 inherited[object.runtimeType] = object; 71 inherited[object.runtimeType] = object;
59 return copyWith(inherited: inherited); 72 return copyWith(inherited: inherited);
60 } 73 }
@@ -172,3 +185,53 @@ abstract class MultiChildWidget extends Widget { @@ -172,3 +185,53 @@ abstract class MultiChildWidget extends Widget {
172 185
173 final List<Widget> children; 186 final List<Widget> children;
174 } 187 }
  188 +
  189 +class InheritedWidget extends Widget {
  190 + InheritedWidget({this.build, this.inherited});
  191 +
  192 + final BuildCallback build;
  193 +
  194 + final Inherited inherited;
  195 +
  196 + Context _context;
  197 +
  198 + Widget _child;
  199 +
  200 + @override
  201 + void layout(Context context, BoxConstraints constraints,
  202 + {bool parentUsesSize = false}) {
  203 + if (_context == null) {
  204 + // final Inherited inherited = build(context);
  205 + if (inherited != null) {
  206 + _context = context.inheritFrom(inherited);
  207 + }
  208 + }
  209 +
  210 + _context ??= context;
  211 + _child ??= build(_context);
  212 +
  213 + if (_child != null) {
  214 + _child.layout(_context, constraints, parentUsesSize: parentUsesSize);
  215 + assert(_child.box != null);
  216 + box = _child.box;
  217 + } else {
  218 + box = PdfRect.fromPoints(PdfPoint.zero, constraints.smallest);
  219 + }
  220 + }
  221 +
  222 + @override
  223 + void paint(Context context) {
  224 + assert(_context != null);
  225 + super.paint(_context);
  226 +
  227 + if (_child != null) {
  228 + final Matrix4 mat = Matrix4.identity();
  229 + mat.translate(box.x, box.y);
  230 + context.canvas
  231 + ..saveContext()
  232 + ..setTransform(mat);
  233 + _child.paint(_context);
  234 + context.canvas.restoreContext();
  235 + }
  236 + }
  237 +}
@@ -70,6 +70,53 @@ void main() { @@ -70,6 +70,53 @@ void main() {
70 )); 70 ));
71 }); 71 });
72 72
  73 + test('Theme Page 1', () {
  74 + final Theme theme = Theme.withFont(base: roboto);
  75 +
  76 + pdf.addPage(Page(
  77 + theme: theme,
  78 + build: (Context context) => Center(
  79 + child: Text('Hello'),
  80 + ),
  81 + ));
  82 + });
  83 +
  84 + test('Theme Page 2', () {
  85 + final Theme theme = Theme.base().copyWith(
  86 + tableHeader: TextStyle(font: openSansBold),
  87 + tableCell: TextStyle(font: roboto),
  88 + );
  89 +
  90 + pdf.addPage(Page(
  91 + theme: theme,
  92 + build: (Context context) => Center(
  93 + child: Table.fromTextArray(context: context, data: [
  94 + ['Header', '123'],
  95 + ['Cell', '456']
  96 + ]),
  97 + ),
  98 + ));
  99 + });
  100 +
  101 + test('Theme Page 3', () {
  102 + pdf.addPage(Page(
  103 + build: (Context context) => Center(
  104 + child: Column(
  105 + mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  106 + children: <Widget>[
  107 + Text('Hello default'),
  108 + InheritedWidget(
  109 + inherited: Theme.withFont(
  110 + base: roboto,
  111 + ),
  112 + build: (Context context) => Text('Hello themed'),
  113 + ),
  114 + ],
  115 + ),
  116 + ),
  117 + ));
  118 + });
  119 +
73 tearDownAll(() { 120 tearDownAll(() {
74 final File file = File('widgets-theme.pdf'); 121 final File file = File('widgets-theme.pdf');
75 file.writeAsBytesSync(pdf.save()); 122 file.writeAsBytesSync(pdf.save());