Showing
2 changed files
with
128 additions
and
30 deletions
@@ -3,6 +3,7 @@ | @@ -3,6 +3,7 @@ | ||
3 | * Add Document properties | 3 | * Add Document properties |
4 | * Add Page.orientation to force landscape or portrait | 4 | * Add Page.orientation to force landscape or portrait |
5 | * Improve MultiPage Widget | 5 | * Improve MultiPage Widget |
6 | +* Convert GridView to a SpanningWidget | ||
6 | 7 | ||
7 | # 1.3.3 | 8 | # 1.3.3 |
8 | * Fix a bug with the RichText Widget | 9 | * Fix a bug with the RichText Widget |
@@ -16,7 +16,19 @@ | @@ -16,7 +16,19 @@ | ||
16 | 16 | ||
17 | part of widget; | 17 | part of widget; |
18 | 18 | ||
19 | -class GridView extends MultiChildWidget { | 19 | +class _GridViewContext extends WidgetContext { |
20 | + int firstChild = 0; | ||
21 | + int lastChild = 0; | ||
22 | + | ||
23 | + double childCrossAxis; | ||
24 | + double childMainAxis; | ||
25 | + | ||
26 | + @override | ||
27 | + String toString() => | ||
28 | + 'GridViewContext first:$firstChild last:$lastChild size:${childCrossAxis}x$childMainAxis'; | ||
29 | +} | ||
30 | + | ||
31 | +class GridView extends MultiChildWidget implements SpanningWidget { | ||
20 | GridView( | 32 | GridView( |
21 | {this.direction = Axis.vertical, | 33 | {this.direction = Axis.vertical, |
22 | this.padding = EdgeInsets.zero, | 34 | this.padding = EdgeInsets.zero, |
@@ -35,15 +47,22 @@ class GridView extends MultiChildWidget { | @@ -35,15 +47,22 @@ class GridView extends MultiChildWidget { | ||
35 | final double crossAxisSpacing; | 47 | final double crossAxisSpacing; |
36 | final double childAspectRatio; | 48 | final double childAspectRatio; |
37 | 49 | ||
38 | - double _childCrossAxis; | ||
39 | - double _childMainAxis; | ||
40 | - double _totalMain; | ||
41 | - double _totalCross; | 50 | + final _GridViewContext _context = _GridViewContext(); |
51 | + | ||
42 | int _mainAxisCount; | 52 | int _mainAxisCount; |
43 | 53 | ||
44 | @override | 54 | @override |
45 | void layout(Context context, BoxConstraints constraints, | 55 | void layout(Context context, BoxConstraints constraints, |
46 | {bool parentUsesSize = false}) { | 56 | {bool parentUsesSize = false}) { |
57 | + assert(() { | ||
58 | + if (constraints.maxHeight.isInfinite && childAspectRatio.isInfinite) { | ||
59 | + print( | ||
60 | + 'Unable to calculate the GridView dimensions. Please set one the height constraints or childAspectRatio.'); | ||
61 | + return false; | ||
62 | + } | ||
63 | + return true; | ||
64 | + }()); | ||
65 | + | ||
47 | double mainAxisExtent; | 66 | double mainAxisExtent; |
48 | double crossAxisExtent; | 67 | double crossAxisExtent; |
49 | switch (direction) { | 68 | switch (direction) { |
@@ -57,16 +76,38 @@ class GridView extends MultiChildWidget { | @@ -57,16 +76,38 @@ class GridView extends MultiChildWidget { | ||
57 | break; | 76 | break; |
58 | } | 77 | } |
59 | 78 | ||
60 | - _mainAxisCount = (children.length / crossAxisCount).ceil(); | ||
61 | - _childCrossAxis = crossAxisExtent / crossAxisCount - | 79 | + if (constraints.maxHeight.isInfinite || _mainAxisCount == null) { |
80 | + _mainAxisCount = | ||
81 | + ((children.length - _context.firstChild) / crossAxisCount).ceil(); | ||
82 | + | ||
83 | + _context.childCrossAxis = crossAxisExtent / crossAxisCount - | ||
62 | (crossAxisSpacing * (crossAxisCount - 1) / crossAxisCount); | 84 | (crossAxisSpacing * (crossAxisCount - 1) / crossAxisCount); |
63 | - _childMainAxis = math.min( | ||
64 | - _childCrossAxis * childAspectRatio, | 85 | + |
86 | + _context.childMainAxis = math.min( | ||
87 | + _context.childCrossAxis * childAspectRatio, | ||
65 | mainAxisExtent / _mainAxisCount - | 88 | mainAxisExtent / _mainAxisCount - |
66 | (mainAxisSpacing * (_mainAxisCount - 1) / _mainAxisCount)); | 89 | (mainAxisSpacing * (_mainAxisCount - 1) / _mainAxisCount)); |
67 | - _totalMain = | ||
68 | - (_childMainAxis + mainAxisSpacing) * _mainAxisCount - mainAxisSpacing; | ||
69 | - _totalCross = (_childCrossAxis + crossAxisSpacing) * crossAxisCount - | 90 | + |
91 | + if (_context.childCrossAxis.isInfinite) { | ||
92 | + throw Exception( | ||
93 | + 'Unable to calculate child height as the height constraint is infinite.'); | ||
94 | + } | ||
95 | + } else { | ||
96 | + _mainAxisCount = ((mainAxisExtent + mainAxisSpacing) / | ||
97 | + (mainAxisSpacing + _context.childMainAxis)) | ||
98 | + .floor(); | ||
99 | + | ||
100 | + if (_mainAxisCount < 0) { | ||
101 | + // Not enough space to put one line, try to ask for more space. | ||
102 | + _mainAxisCount = 0; | ||
103 | + } | ||
104 | + } | ||
105 | + | ||
106 | + final double totalMain = | ||
107 | + (_context.childMainAxis + mainAxisSpacing) * _mainAxisCount - | ||
108 | + mainAxisSpacing; | ||
109 | + final double totalCross = | ||
110 | + (_context.childCrossAxis + crossAxisSpacing) * crossAxisCount - | ||
70 | crossAxisSpacing; | 111 | crossAxisSpacing; |
71 | 112 | ||
72 | final double startX = padding.left; | 113 | final double startX = padding.left; |
@@ -77,30 +118,35 @@ class GridView extends MultiChildWidget { | @@ -77,30 +118,35 @@ class GridView extends MultiChildWidget { | ||
77 | switch (direction) { | 118 | switch (direction) { |
78 | case Axis.vertical: | 119 | case Axis.vertical: |
79 | innerConstraints = BoxConstraints.tightFor( | 120 | innerConstraints = BoxConstraints.tightFor( |
80 | - width: _childCrossAxis, height: _childMainAxis); | 121 | + width: _context.childCrossAxis, height: _context.childMainAxis); |
81 | crossAxis = startX; | 122 | crossAxis = startX; |
82 | mainAxis = startY; | 123 | mainAxis = startY; |
83 | break; | 124 | break; |
84 | case Axis.horizontal: | 125 | case Axis.horizontal: |
85 | innerConstraints = BoxConstraints.tightFor( | 126 | innerConstraints = BoxConstraints.tightFor( |
86 | - width: _childMainAxis, height: _childCrossAxis); | 127 | + width: _context.childMainAxis, height: _context.childCrossAxis); |
87 | mainAxis = startX; | 128 | mainAxis = startX; |
88 | crossAxis = startY; | 129 | crossAxis = startY; |
89 | break; | 130 | break; |
90 | } | 131 | } |
91 | 132 | ||
92 | int c = 0; | 133 | int c = 0; |
93 | - for (Widget child in children) { | 134 | + _context.lastChild = _context.firstChild; |
135 | + | ||
136 | + for (Widget child in children.sublist( | ||
137 | + _context.firstChild, | ||
138 | + math.min(children.length, | ||
139 | + _context.firstChild + crossAxisCount * _mainAxisCount))) { | ||
94 | child.layout(context, innerConstraints); | 140 | child.layout(context, innerConstraints); |
95 | 141 | ||
96 | switch (direction) { | 142 | switch (direction) { |
97 | case Axis.vertical: | 143 | case Axis.vertical: |
98 | child.box = PdfRect.fromPoints( | 144 | child.box = PdfRect.fromPoints( |
99 | PdfPoint( | 145 | PdfPoint( |
100 | - (_childCrossAxis - child.box.width) / 2.0 + crossAxis, | ||
101 | - _totalMain + | 146 | + (_context.childCrossAxis - child.box.width) / 2.0 + crossAxis, |
147 | + totalMain + | ||
102 | padding.bottom - | 148 | padding.bottom - |
103 | - (_childMainAxis - child.box.height) / 2.0 - | 149 | + (_context.childMainAxis - child.box.height) / 2.0 - |
104 | mainAxis - | 150 | mainAxis - |
105 | child.box.height), | 151 | child.box.height), |
106 | child.box.size); | 152 | child.box.size); |
@@ -108,10 +154,10 @@ class GridView extends MultiChildWidget { | @@ -108,10 +154,10 @@ class GridView extends MultiChildWidget { | ||
108 | case Axis.horizontal: | 154 | case Axis.horizontal: |
109 | child.box = PdfRect.fromPoints( | 155 | child.box = PdfRect.fromPoints( |
110 | PdfPoint( | 156 | PdfPoint( |
111 | - (_childMainAxis - child.box.width) / 2.0 + mainAxis, | ||
112 | - _totalCross + | 157 | + (_context.childMainAxis - child.box.width) / 2.0 + mainAxis, |
158 | + totalCross + | ||
113 | padding.bottom - | 159 | padding.bottom - |
114 | - (_childCrossAxis - child.box.height) / 2.0 - | 160 | + (_context.childCrossAxis - child.box.height) / 2.0 - |
115 | crossAxis - | 161 | crossAxis - |
116 | child.box.height), | 162 | child.box.height), |
117 | child.box.size); | 163 | child.box.size); |
@@ -119,24 +165,38 @@ class GridView extends MultiChildWidget { | @@ -119,24 +165,38 @@ class GridView extends MultiChildWidget { | ||
119 | } | 165 | } |
120 | 166 | ||
121 | if (++c >= crossAxisCount) { | 167 | if (++c >= crossAxisCount) { |
122 | - mainAxis += _childMainAxis + mainAxisSpacing; | 168 | + mainAxis += _context.childMainAxis + mainAxisSpacing; |
169 | + switch (direction) { | ||
170 | + case Axis.vertical: | ||
123 | crossAxis = startX; | 171 | crossAxis = startX; |
172 | + break; | ||
173 | + case Axis.horizontal: | ||
174 | + crossAxis = startY; | ||
175 | + break; | ||
176 | + } | ||
124 | c = 0; | 177 | c = 0; |
178 | + | ||
179 | + if (mainAxis > mainAxisExtent) { | ||
180 | + _context.lastChild++; | ||
181 | + | ||
182 | + break; | ||
183 | + } | ||
125 | } else { | 184 | } else { |
126 | - crossAxis += _childCrossAxis + crossAxisSpacing; | 185 | + crossAxis += _context.childCrossAxis + crossAxisSpacing; |
127 | } | 186 | } |
187 | + _context.lastChild++; | ||
128 | } | 188 | } |
129 | 189 | ||
130 | switch (direction) { | 190 | switch (direction) { |
131 | case Axis.vertical: | 191 | case Axis.vertical: |
132 | box = constraints.constrainRect( | 192 | box = constraints.constrainRect( |
133 | - width: _totalCross + padding.horizontal, | ||
134 | - height: _totalMain + padding.vertical); | 193 | + width: totalCross + padding.horizontal, |
194 | + height: totalMain + padding.vertical); | ||
135 | break; | 195 | break; |
136 | case Axis.horizontal: | 196 | case Axis.horizontal: |
137 | box = constraints.constrainRect( | 197 | box = constraints.constrainRect( |
138 | - width: _totalMain + padding.horizontal, | ||
139 | - height: _totalCross + padding.vertical); | 198 | + width: totalMain + padding.horizontal, |
199 | + height: totalCross + padding.vertical); | ||
140 | break; | 200 | break; |
141 | } | 201 | } |
142 | } | 202 | } |
@@ -164,7 +224,7 @@ class GridView extends MultiChildWidget { | @@ -164,7 +224,7 @@ class GridView extends MultiChildWidget { | ||
164 | ..drawRect( | 224 | ..drawRect( |
165 | box.left + | 225 | box.left + |
166 | padding.left + | 226 | padding.left + |
167 | - (_childCrossAxis + crossAxisSpacing) * c - | 227 | + (_context.childCrossAxis + crossAxisSpacing) * c - |
168 | crossAxisSpacing, | 228 | crossAxisSpacing, |
169 | box.bottom + padding.bottom, | 229 | box.bottom + padding.bottom, |
170 | math.max(crossAxisSpacing, 1), | 230 | math.max(crossAxisSpacing, 1), |
@@ -172,6 +232,16 @@ class GridView extends MultiChildWidget { | @@ -172,6 +232,16 @@ class GridView extends MultiChildWidget { | ||
172 | ..fillPath(); | 232 | ..fillPath(); |
173 | break; | 233 | break; |
174 | case Axis.horizontal: | 234 | case Axis.horizontal: |
235 | + context.canvas | ||
236 | + ..drawRect( | ||
237 | + box.left + padding.left, | ||
238 | + box.bottom + | ||
239 | + padding.bottom + | ||
240 | + (_context.childCrossAxis + crossAxisSpacing) * c - | ||
241 | + crossAxisSpacing, | ||
242 | + box.width - padding.horizontal, | ||
243 | + math.max(crossAxisSpacing, 1)) | ||
244 | + ..fillPath(); | ||
175 | break; | 245 | break; |
176 | } | 246 | } |
177 | } | 247 | } |
@@ -184,13 +254,23 @@ class GridView extends MultiChildWidget { | @@ -184,13 +254,23 @@ class GridView extends MultiChildWidget { | ||
184 | box.left + padding.left, | 254 | box.left + padding.left, |
185 | box.bottom + | 255 | box.bottom + |
186 | padding.bottom + | 256 | padding.bottom + |
187 | - (_childMainAxis + mainAxisSpacing) * c - | 257 | + (_context.childMainAxis + mainAxisSpacing) * c - |
188 | mainAxisSpacing, | 258 | mainAxisSpacing, |
189 | box.width - padding.horizontal, | 259 | box.width - padding.horizontal, |
190 | math.max(mainAxisSpacing, 1)) | 260 | math.max(mainAxisSpacing, 1)) |
191 | ..fillPath(); | 261 | ..fillPath(); |
192 | break; | 262 | break; |
193 | case Axis.horizontal: | 263 | case Axis.horizontal: |
264 | + context.canvas | ||
265 | + ..drawRect( | ||
266 | + box.left + | ||
267 | + padding.left + | ||
268 | + (_context.childMainAxis + mainAxisSpacing) * c - | ||
269 | + mainAxisSpacing, | ||
270 | + box.bottom + padding.bottom, | ||
271 | + math.max(mainAxisSpacing, 1), | ||
272 | + box.height - padding.vertical) | ||
273 | + ..fillPath(); | ||
194 | break; | 274 | break; |
195 | } | 275 | } |
196 | } | 276 | } |
@@ -205,9 +285,26 @@ class GridView extends MultiChildWidget { | @@ -205,9 +285,26 @@ class GridView extends MultiChildWidget { | ||
205 | context.canvas | 285 | context.canvas |
206 | ..saveContext() | 286 | ..saveContext() |
207 | ..setTransform(mat); | 287 | ..setTransform(mat); |
208 | - for (Widget child in children) { | 288 | + |
289 | + for (Widget child | ||
290 | + in children.sublist(_context.firstChild, _context.lastChild)) { | ||
209 | child.paint(context); | 291 | child.paint(context); |
210 | } | 292 | } |
211 | context.canvas.restoreContext(); | 293 | context.canvas.restoreContext(); |
212 | } | 294 | } |
295 | + | ||
296 | + @override | ||
297 | + bool get canSpan => true; | ||
298 | + | ||
299 | + @override | ||
300 | + void restoreContext(WidgetContext context) { | ||
301 | + if (context is _GridViewContext) { | ||
302 | + _context.firstChild = context.lastChild; | ||
303 | + } | ||
304 | + } | ||
305 | + | ||
306 | + @override | ||
307 | + WidgetContext saveContext() { | ||
308 | + return _context; | ||
309 | + } | ||
213 | } | 310 | } |
-
Please register or login to post a comment