Committed by
David PHAM-VAN
Add RTL support to EdgeInsets widget
Add RTL support Page and MultiPage
Showing
7 changed files
with
556 additions
and
195 deletions
| @@ -22,8 +22,7 @@ import 'point.dart'; | @@ -22,8 +22,7 @@ import 'point.dart'; | ||
| 22 | class PdfRect { | 22 | class PdfRect { |
| 23 | const PdfRect(this.x, this.y, this.width, this.height); | 23 | const PdfRect(this.x, this.y, this.width, this.height); |
| 24 | 24 | ||
| 25 | - factory PdfRect.fromLTRB( | ||
| 26 | - double left, double top, double right, double bottom) { | 25 | + factory PdfRect.fromLTRB(double left, double top, double right, double bottom) { |
| 27 | return PdfRect(left, top, right - left, bottom - top); | 26 | return PdfRect(left, top, right - left, bottom - top); |
| 28 | } | 27 | } |
| 29 | 28 | ||
| @@ -36,14 +35,18 @@ class PdfRect { | @@ -36,14 +35,18 @@ class PdfRect { | ||
| 36 | static const PdfRect zero = PdfRect(0, 0, 0, 0); | 35 | static const PdfRect zero = PdfRect(0, 0, 0, 0); |
| 37 | 36 | ||
| 38 | double get left => x; | 37 | double get left => x; |
| 38 | + | ||
| 39 | double get bottom => y; | 39 | double get bottom => y; |
| 40 | + | ||
| 40 | double get right => x + width; | 41 | double get right => x + width; |
| 42 | + | ||
| 41 | double get top => y + height; | 43 | double get top => y + height; |
| 42 | 44 | ||
| 43 | @Deprecated('type => horizontalCenter') | 45 | @Deprecated('type => horizontalCenter') |
| 44 | double get horizondalCenter => horizontalCenter; | 46 | double get horizondalCenter => horizontalCenter; |
| 45 | 47 | ||
| 46 | double get horizontalCenter => x + width / 2; | 48 | double get horizontalCenter => x + width / 2; |
| 49 | + | ||
| 47 | double get verticalCenter => y + height / 2; | 50 | double get verticalCenter => y + height / 2; |
| 48 | 51 | ||
| 49 | @override | 52 | @override |
| @@ -54,19 +57,36 @@ class PdfRect { | @@ -54,19 +57,36 @@ class PdfRect { | ||
| 54 | } | 57 | } |
| 55 | 58 | ||
| 56 | PdfPoint get offset => PdfPoint(x, y); | 59 | PdfPoint get offset => PdfPoint(x, y); |
| 60 | + | ||
| 57 | PdfPoint get size => PdfPoint(width, height); | 61 | PdfPoint get size => PdfPoint(width, height); |
| 58 | 62 | ||
| 59 | PdfPoint get topLeft => PdfPoint(x, y); | 63 | PdfPoint get topLeft => PdfPoint(x, y); |
| 64 | + | ||
| 60 | PdfPoint get topRight => PdfPoint(right, y); | 65 | PdfPoint get topRight => PdfPoint(right, y); |
| 66 | + | ||
| 61 | PdfPoint get bottomLeft => PdfPoint(x, top); | 67 | PdfPoint get bottomLeft => PdfPoint(x, top); |
| 68 | + | ||
| 62 | PdfPoint get bottomRight => PdfPoint(right, top); | 69 | PdfPoint get bottomRight => PdfPoint(right, top); |
| 63 | 70 | ||
| 64 | /// Returns a new rectangle with edges moved outwards by the given delta. | 71 | /// Returns a new rectangle with edges moved outwards by the given delta. |
| 65 | PdfRect inflate(double delta) { | 72 | PdfRect inflate(double delta) { |
| 66 | - return PdfRect.fromLTRB( | ||
| 67 | - left - delta, top - delta, right + delta, bottom + delta); | 73 | + return PdfRect.fromLTRB(left - delta, top - delta, right + delta, bottom + delta); |
| 68 | } | 74 | } |
| 69 | 75 | ||
| 70 | /// Returns a new rectangle with edges moved inwards by the given delta. | 76 | /// Returns a new rectangle with edges moved inwards by the given delta. |
| 71 | PdfRect deflate(double delta) => inflate(-delta); | 77 | PdfRect deflate(double delta) => inflate(-delta); |
| 78 | + | ||
| 79 | + PdfRect copyWith({ | ||
| 80 | + double? x, | ||
| 81 | + double? y, | ||
| 82 | + double? width, | ||
| 83 | + double? height, | ||
| 84 | + }) { | ||
| 85 | + return PdfRect( | ||
| 86 | + x ?? this.x, | ||
| 87 | + y ?? this.y, | ||
| 88 | + width ?? this.width, | ||
| 89 | + height ?? this.height, | ||
| 90 | + ); | ||
| 91 | + } | ||
| 72 | } | 92 | } |
| @@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
| 16 | 16 | ||
| 17 | import 'dart:math' as math; | 17 | import 'dart:math' as math; |
| 18 | 18 | ||
| 19 | +import 'package:pdf/widgets.dart'; | ||
| 19 | import 'package:vector_math/vector_math_64.dart'; | 20 | import 'package:vector_math/vector_math_64.dart'; |
| 20 | 21 | ||
| 21 | import '../../pdf.dart'; | 22 | import '../../pdf.dart'; |
| @@ -80,46 +81,48 @@ class Padding extends SingleChildWidget { | @@ -80,46 +81,48 @@ class Padding extends SingleChildWidget { | ||
| 80 | Widget? child, | 81 | Widget? child, |
| 81 | }) : super(child: child); | 82 | }) : super(child: child); |
| 82 | 83 | ||
| 83 | - final EdgeInsets padding; | 84 | + final EdgeInsetsGeometry padding; |
| 84 | 85 | ||
| 85 | @override | 86 | @override |
| 86 | void layout(Context context, BoxConstraints constraints, | 87 | void layout(Context context, BoxConstraints constraints, |
| 87 | {bool parentUsesSize = false}) { | 88 | {bool parentUsesSize = false}) { |
| 89 | + final effectivePadding = padding.resolve(Directionality.of(context)); | ||
| 88 | if (child != null) { | 90 | if (child != null) { |
| 89 | - final childConstraints = constraints.deflate(padding); | 91 | + final childConstraints = constraints.deflate(effectivePadding); |
| 90 | child!.layout(context, childConstraints, parentUsesSize: parentUsesSize); | 92 | child!.layout(context, childConstraints, parentUsesSize: parentUsesSize); |
| 91 | assert(child!.box != null); | 93 | assert(child!.box != null); |
| 92 | box = constraints.constrainRect( | 94 | box = constraints.constrainRect( |
| 93 | - width: child!.box!.width + padding.horizontal, | ||
| 94 | - height: child!.box!.height + padding.vertical); | 95 | + width: child!.box!.width + effectivePadding.horizontal, |
| 96 | + height: child!.box!.height + effectivePadding.vertical); | ||
| 95 | } else { | 97 | } else { |
| 96 | box = constraints.constrainRect( | 98 | box = constraints.constrainRect( |
| 97 | - width: padding.horizontal, height: padding.vertical); | 99 | + width: effectivePadding.horizontal, height: effectivePadding.vertical); |
| 98 | } | 100 | } |
| 99 | } | 101 | } |
| 100 | 102 | ||
| 101 | @override | 103 | @override |
| 102 | void debugPaint(Context context) { | 104 | void debugPaint(Context context) { |
| 105 | + final effectivePadding = padding.resolve(Directionality.of(context)); | ||
| 103 | context.canvas | 106 | context.canvas |
| 104 | ..setFillColor(PdfColors.lime) | 107 | ..setFillColor(PdfColors.lime) |
| 105 | ..moveTo(box!.x, box!.y) | 108 | ..moveTo(box!.x, box!.y) |
| 106 | ..lineTo(box!.right, box!.y) | 109 | ..lineTo(box!.right, box!.y) |
| 107 | ..lineTo(box!.right, box!.top) | 110 | ..lineTo(box!.right, box!.top) |
| 108 | ..lineTo(box!.x, box!.top) | 111 | ..lineTo(box!.x, box!.top) |
| 109 | - ..moveTo(box!.x + padding.left, box!.y + padding.bottom) | ||
| 110 | - ..lineTo(box!.x + padding.left, box!.top - padding.top) | ||
| 111 | - ..lineTo(box!.right - padding.right, box!.top - padding.top) | ||
| 112 | - ..lineTo(box!.right - padding.right, box!.y + padding.bottom) | 112 | + ..moveTo(box!.x + effectivePadding.left, box!.y + effectivePadding.bottom) |
| 113 | + ..lineTo(box!.x + effectivePadding.left, box!.top - effectivePadding.top) | ||
| 114 | + ..lineTo(box!.right - effectivePadding.right, box!.top - effectivePadding.top) | ||
| 115 | + ..lineTo(box!.right - effectivePadding.right, box!.y + effectivePadding.bottom) | ||
| 113 | ..fillPath(); | 116 | ..fillPath(); |
| 114 | } | 117 | } |
| 115 | 118 | ||
| 116 | @override | 119 | @override |
| 117 | void paint(Context context) { | 120 | void paint(Context context) { |
| 118 | super.paint(context); | 121 | super.paint(context); |
| 119 | - | 122 | + final effectivePadding = padding.resolve(Directionality.of(context)); |
| 120 | if (child != null) { | 123 | if (child != null) { |
| 121 | final mat = Matrix4.identity(); | 124 | final mat = Matrix4.identity(); |
| 122 | - mat.translate(box!.x + padding.left, box!.y + padding.bottom); | 125 | + mat.translate(box!.x + effectivePadding.left, box!.y + effectivePadding.bottom); |
| 123 | context.canvas | 126 | context.canvas |
| 124 | ..saveContext() | 127 | ..saveContext() |
| 125 | ..setTransform(mat); | 128 | ..setTransform(mat); |
| @@ -20,16 +20,13 @@ import 'package:meta/meta.dart'; | @@ -20,16 +20,13 @@ import 'package:meta/meta.dart'; | ||
| 20 | import 'package:vector_math/vector_math_64.dart'; | 20 | import 'package:vector_math/vector_math_64.dart'; |
| 21 | 21 | ||
| 22 | import '../../pdf.dart'; | 22 | import '../../pdf.dart'; |
| 23 | -import 'basic.dart'; | 23 | +import '../../widgets.dart'; |
| 24 | 24 | ||
| 25 | @immutable | 25 | @immutable |
| 26 | class BoxConstraints { | 26 | class BoxConstraints { |
| 27 | /// Creates box constraints with the given constraints. | 27 | /// Creates box constraints with the given constraints. |
| 28 | const BoxConstraints( | 28 | const BoxConstraints( |
| 29 | - {this.minWidth = 0.0, | ||
| 30 | - this.maxWidth = double.infinity, | ||
| 31 | - this.minHeight = 0.0, | ||
| 32 | - this.maxHeight = double.infinity}); | 29 | + {this.minWidth = 0.0, this.maxWidth = double.infinity, this.minHeight = 0.0, this.maxHeight = double.infinity}); |
| 33 | 30 | ||
| 34 | /// Creates box constraints that require the given width or height. | 31 | /// Creates box constraints that require the given width or height. |
| 35 | const BoxConstraints.tightFor({double? width, double? height}) | 32 | const BoxConstraints.tightFor({double? width, double? height}) |
| @@ -104,8 +101,7 @@ class BoxConstraints { | @@ -104,8 +101,7 @@ class BoxConstraints { | ||
| 104 | return result; | 101 | return result; |
| 105 | } | 102 | } |
| 106 | 103 | ||
| 107 | - PdfRect constrainRect( | ||
| 108 | - {double width = double.infinity, double height = double.infinity}) { | 104 | + PdfRect constrainRect({double width = double.infinity, double height = double.infinity}) { |
| 109 | final result = PdfPoint(constrainWidth(width), constrainHeight(height)); | 105 | final result = PdfPoint(constrainWidth(width), constrainHeight(height)); |
| 110 | return PdfRect.fromPoints(PdfPoint.zero, result); | 106 | return PdfRect.fromPoints(PdfPoint.zero, result); |
| 111 | } | 107 | } |
| @@ -162,10 +158,8 @@ class BoxConstraints { | @@ -162,10 +158,8 @@ class BoxConstraints { | ||
| 162 | return BoxConstraints( | 158 | return BoxConstraints( |
| 163 | minWidth: width == null ? minWidth : width.clamp(minWidth, maxWidth), | 159 | minWidth: width == null ? minWidth : width.clamp(minWidth, maxWidth), |
| 164 | maxWidth: width == null ? maxWidth : width.clamp(minWidth, maxWidth), | 160 | maxWidth: width == null ? maxWidth : width.clamp(minWidth, maxWidth), |
| 165 | - minHeight: | ||
| 166 | - height == null ? minHeight : height.clamp(minHeight, maxHeight), | ||
| 167 | - maxHeight: | ||
| 168 | - height == null ? maxHeight : height.clamp(minHeight, maxHeight)); | 161 | + minHeight: height == null ? minHeight : height.clamp(minHeight, maxHeight), |
| 162 | + maxHeight: height == null ? maxHeight : height.clamp(minHeight, maxHeight)); | ||
| 169 | } | 163 | } |
| 170 | 164 | ||
| 171 | /// Returns new box constraints that are smaller by the given edge dimensions. | 165 | /// Returns new box constraints that are smaller by the given edge dimensions. |
| @@ -197,17 +191,11 @@ class BoxConstraints { | @@ -197,17 +191,11 @@ class BoxConstraints { | ||
| 197 | return BoxConstraints( | 191 | return BoxConstraints( |
| 198 | minWidth: minWidth.clamp(constraints.minWidth, constraints.maxWidth), | 192 | minWidth: minWidth.clamp(constraints.minWidth, constraints.maxWidth), |
| 199 | maxWidth: maxWidth.clamp(constraints.minWidth, constraints.maxWidth), | 193 | maxWidth: maxWidth.clamp(constraints.minWidth, constraints.maxWidth), |
| 200 | - minHeight: | ||
| 201 | - minHeight.clamp(constraints.minHeight, constraints.maxHeight), | ||
| 202 | - maxHeight: | ||
| 203 | - maxHeight.clamp(constraints.minHeight, constraints.maxHeight)); | 194 | + minHeight: minHeight.clamp(constraints.minHeight, constraints.maxHeight), |
| 195 | + maxHeight: maxHeight.clamp(constraints.minHeight, constraints.maxHeight)); | ||
| 204 | } | 196 | } |
| 205 | 197 | ||
| 206 | - BoxConstraints copyWith( | ||
| 207 | - {double? minWidth, | ||
| 208 | - double? maxWidth, | ||
| 209 | - double? minHeight, | ||
| 210 | - double? maxHeight}) { | 198 | + BoxConstraints copyWith({double? minWidth, double? maxWidth, double? minHeight, double? maxHeight}) { |
| 211 | return BoxConstraints( | 199 | return BoxConstraints( |
| 212 | minWidth: minWidth ?? this.minWidth, | 200 | minWidth: minWidth ?? this.minWidth, |
| 213 | maxWidth: maxWidth ?? this.maxWidth, | 201 | maxWidth: maxWidth ?? this.maxWidth, |
| @@ -222,7 +210,96 @@ class BoxConstraints { | @@ -222,7 +210,96 @@ class BoxConstraints { | ||
| 222 | } | 210 | } |
| 223 | 211 | ||
| 224 | @immutable | 212 | @immutable |
| 225 | -class EdgeInsets { | 213 | +abstract class EdgeInsetsGeometry { |
| 214 | + /// Abstract const constructor. This constructor enables subclasses to provide | ||
| 215 | + /// const constructors so that they can be used in const expressions. | ||
| 216 | + const EdgeInsetsGeometry(); | ||
| 217 | + | ||
| 218 | + double get _bottom; | ||
| 219 | + | ||
| 220 | + double get _end; | ||
| 221 | + | ||
| 222 | + double get _left; | ||
| 223 | + | ||
| 224 | + double get _right; | ||
| 225 | + | ||
| 226 | + double get _start; | ||
| 227 | + | ||
| 228 | + double get _top; | ||
| 229 | + | ||
| 230 | + /// The total offset in the horizontal direction. | ||
| 231 | + double get horizontal => _left + _right + _start + _end; | ||
| 232 | + | ||
| 233 | + /// The total offset in the vertical direction. | ||
| 234 | + double get vertical => _top + _bottom; | ||
| 235 | + | ||
| 236 | + /// Convert this instance into an [EdgeInsets], which uses literal coordinates | ||
| 237 | + /// (i.e. the `left` coordinate being explicitly a distance from the left, and | ||
| 238 | + /// the `right` coordinate being explicitly a distance from the right). | ||
| 239 | + /// | ||
| 240 | + /// See also: | ||
| 241 | + /// | ||
| 242 | + /// * [EdgeInsets], for which this is a no-op (returns itself). | ||
| 243 | + /// * [EdgeInsetsDirectional], which flips the horizontal direction | ||
| 244 | + /// based on the `direction` argument. | ||
| 245 | + EdgeInsets resolve(TextDirection? direction); | ||
| 246 | + | ||
| 247 | + /// Returns the sum of two [EdgeInsetsGeometry] objects. | ||
| 248 | + /// | ||
| 249 | + /// If you know you are adding two [EdgeInsets] or two [EdgeInsetsDirectional] | ||
| 250 | + /// objects, consider using the `+` operator instead, which always returns an | ||
| 251 | + /// object of the same type as the operands, and is typed accordingly. | ||
| 252 | + /// | ||
| 253 | + /// If [add] is applied to two objects of the same type ([EdgeInsets] or | ||
| 254 | + /// [EdgeInsetsDirectional]), an object of that type will be returned (though | ||
| 255 | + /// this is not reflected in the type system). Otherwise, an object | ||
| 256 | + /// representing a combination of both is returned. That object can be turned | ||
| 257 | + /// into a concrete [EdgeInsets] using [resolve]. | ||
| 258 | + EdgeInsetsGeometry add(EdgeInsetsGeometry other) { | ||
| 259 | + return _MixedEdgeInsets.fromLRSETB( | ||
| 260 | + _left + other._left, | ||
| 261 | + _right + other._right, | ||
| 262 | + _start + other._start, | ||
| 263 | + _end + other._end, | ||
| 264 | + _top + other._top, | ||
| 265 | + _bottom + other._bottom, | ||
| 266 | + ); | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + @override | ||
| 270 | + String toString() { | ||
| 271 | + if (_start == 0.0 && _end == 0.0) { | ||
| 272 | + if (_left == 0.0 && _right == 0.0 && _top == 0.0 && _bottom == 0.0) { | ||
| 273 | + return 'EdgeInsets.zero'; | ||
| 274 | + } | ||
| 275 | + if (_left == _right && _right == _top && _top == _bottom) { | ||
| 276 | + return 'EdgeInsets.all(${_left.toStringAsFixed(1)})'; | ||
| 277 | + } | ||
| 278 | + return 'EdgeInsets(${_left.toStringAsFixed(1)}, ' | ||
| 279 | + '${_top.toStringAsFixed(1)}, ' | ||
| 280 | + '${_right.toStringAsFixed(1)}, ' | ||
| 281 | + '${_bottom.toStringAsFixed(1)})'; | ||
| 282 | + } | ||
| 283 | + if (_left == 0.0 && _right == 0.0) { | ||
| 284 | + return 'EdgeInsetsDirectional(${_start.toStringAsFixed(1)}, ' | ||
| 285 | + '${_top.toStringAsFixed(1)}, ' | ||
| 286 | + '${_end.toStringAsFixed(1)}, ' | ||
| 287 | + '${_bottom.toStringAsFixed(1)})'; | ||
| 288 | + } | ||
| 289 | + return 'EdgeInsets(${_left.toStringAsFixed(1)}, ' | ||
| 290 | + '${_top.toStringAsFixed(1)}, ' | ||
| 291 | + '${_right.toStringAsFixed(1)}, ' | ||
| 292 | + '${_bottom.toStringAsFixed(1)})' | ||
| 293 | + ' + ' | ||
| 294 | + 'EdgeInsetsDirectional(${_start.toStringAsFixed(1)}, ' | ||
| 295 | + '0.0, ' | ||
| 296 | + '${_end.toStringAsFixed(1)}, ' | ||
| 297 | + '0.0)'; | ||
| 298 | + } | ||
| 299 | +} | ||
| 300 | + | ||
| 301 | +@immutable | ||
| 302 | +class EdgeInsets extends EdgeInsetsGeometry { | ||
| 226 | const EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom); | 303 | const EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom); |
| 227 | 304 | ||
| 228 | const EdgeInsets.all(double value) | 305 | const EdgeInsets.all(double value) |
| @@ -231,8 +308,7 @@ class EdgeInsets { | @@ -231,8 +308,7 @@ class EdgeInsets { | ||
| 231 | right = value, | 308 | right = value, |
| 232 | bottom = value; | 309 | bottom = value; |
| 233 | 310 | ||
| 234 | - const EdgeInsets.only( | ||
| 235 | - {this.left = 0.0, this.top = 0.0, this.right = 0.0, this.bottom = 0.0}); | 311 | + const EdgeInsets.only({this.left = 0.0, this.top = 0.0, this.right = 0.0, this.bottom = 0.0}); |
| 236 | 312 | ||
| 237 | const EdgeInsets.symmetric({double vertical = 0.0, double horizontal = 0.0}) | 313 | const EdgeInsets.symmetric({double vertical = 0.0, double horizontal = 0.0}) |
| 238 | : left = horizontal, | 314 | : left = horizontal, |
| @@ -242,19 +318,45 @@ class EdgeInsets { | @@ -242,19 +318,45 @@ class EdgeInsets { | ||
| 242 | 318 | ||
| 243 | static const EdgeInsets zero = EdgeInsets.only(); | 319 | static const EdgeInsets zero = EdgeInsets.only(); |
| 244 | 320 | ||
| 321 | + /// The offset from the left. | ||
| 245 | final double left; | 322 | final double left; |
| 246 | 323 | ||
| 324 | + @override | ||
| 325 | + double get _left => left; | ||
| 326 | + | ||
| 327 | + /// The offset from the top. | ||
| 247 | final double top; | 328 | final double top; |
| 248 | 329 | ||
| 330 | + @override | ||
| 331 | + double get _top => top; | ||
| 332 | + | ||
| 333 | + /// The offset from the right. | ||
| 249 | final double right; | 334 | final double right; |
| 250 | 335 | ||
| 336 | + @override | ||
| 337 | + double get _right => right; | ||
| 338 | + | ||
| 339 | + /// The offset from the bottom. | ||
| 251 | final double bottom; | 340 | final double bottom; |
| 252 | 341 | ||
| 253 | - /// The total offset in the horizontal direction. | ||
| 254 | - double get horizontal => left + right; | 342 | + @override |
| 343 | + double get _bottom => bottom; | ||
| 255 | 344 | ||
| 256 | - /// The total offset in the vertical direction. | ||
| 257 | - double get vertical => top + bottom; | 345 | + @override |
| 346 | + double get _start => 0.0; | ||
| 347 | + | ||
| 348 | + @override | ||
| 349 | + double get _end => 0.0; | ||
| 350 | + | ||
| 351 | + /// Returns the sum of two [EdgeInsets]. | ||
| 352 | + EdgeInsets operator +(EdgeInsets other) { | ||
| 353 | + return EdgeInsets.fromLTRB( | ||
| 354 | + left + other.left, | ||
| 355 | + top + other.top, | ||
| 356 | + right + other.right, | ||
| 357 | + bottom + other.bottom, | ||
| 358 | + ); | ||
| 359 | + } | ||
| 258 | 360 | ||
| 259 | EdgeInsets copyWith({ | 361 | EdgeInsets copyWith({ |
| 260 | double? left, | 362 | double? left, |
| @@ -270,18 +372,198 @@ class EdgeInsets { | @@ -270,18 +372,198 @@ class EdgeInsets { | ||
| 270 | ); | 372 | ); |
| 271 | } | 373 | } |
| 272 | 374 | ||
| 273 | - /// Returns the sum of two [EdgeInsets] objects. | ||
| 274 | - EdgeInsets add(EdgeInsets other) { | ||
| 275 | - return EdgeInsets.fromLTRB( | ||
| 276 | - left + other.left, | 375 | + @override |
| 376 | + EdgeInsetsGeometry add(EdgeInsetsGeometry other) { | ||
| 377 | + if (other is EdgeInsets) { | ||
| 378 | + return this + other; | ||
| 379 | + } | ||
| 380 | + return super.add(other); | ||
| 381 | + } | ||
| 382 | + | ||
| 383 | + @override | ||
| 384 | + EdgeInsets resolve(TextDirection? direction) => this; | ||
| 385 | +} | ||
| 386 | + | ||
| 387 | +class _MixedEdgeInsets extends EdgeInsetsGeometry { | ||
| 388 | + const _MixedEdgeInsets.fromLRSETB(this._left, this._right, this._start, this._end, this._top, this._bottom); | ||
| 389 | + | ||
| 390 | + @override | ||
| 391 | + final double _left; | ||
| 392 | + | ||
| 393 | + @override | ||
| 394 | + final double _right; | ||
| 395 | + | ||
| 396 | + @override | ||
| 397 | + final double _start; | ||
| 398 | + | ||
| 399 | + @override | ||
| 400 | + final double _end; | ||
| 401 | + | ||
| 402 | + @override | ||
| 403 | + final double _top; | ||
| 404 | + | ||
| 405 | + @override | ||
| 406 | + final double _bottom; | ||
| 407 | + | ||
| 408 | + @override | ||
| 409 | + EdgeInsets resolve(TextDirection? direction) { | ||
| 410 | + assert(direction != null); | ||
| 411 | + switch (direction!) { | ||
| 412 | + case TextDirection.rtl: | ||
| 413 | + return EdgeInsets.fromLTRB(_end + _left, _top, _start + _right, _bottom); | ||
| 414 | + case TextDirection.ltr: | ||
| 415 | + return EdgeInsets.fromLTRB(_start + _left, _top, _end + _right, _bottom); | ||
| 416 | + } | ||
| 417 | + } | ||
| 418 | +} | ||
| 419 | + | ||
| 420 | +/// An immutable set of offsets in each of the four cardinal directions, but | ||
| 421 | +/// whose horizontal components are dependent on the writing direction. | ||
| 422 | +/// | ||
| 423 | +/// This can be used to indicate padding from the left in [TextDirection.ltr] | ||
| 424 | +/// text and padding from the right in [TextDirection.rtl] text without having | ||
| 425 | +/// to be aware of the current text direction. | ||
| 426 | +/// | ||
| 427 | +/// See also: | ||
| 428 | +/// | ||
| 429 | +/// * [EdgeInsets], a variant that uses physical labels (left and right instead | ||
| 430 | +/// of start and end). | ||
| 431 | +class EdgeInsetsDirectional extends EdgeInsetsGeometry { | ||
| 432 | + /// Creates insets from offsets from the start, top, end, and bottom. | ||
| 433 | + const EdgeInsetsDirectional.fromSTEB(this.start, this.top, this.end, this.bottom); | ||
| 434 | + | ||
| 435 | + /// Creates insets with only the given values non-zero. | ||
| 436 | + /// | ||
| 437 | + /// {@tool snippet} | ||
| 438 | + /// | ||
| 439 | + /// A margin indent of 40 pixels on the leading side: | ||
| 440 | + /// | ||
| 441 | + /// ```dart | ||
| 442 | + /// const EdgeInsetsDirectional.only(start: 40.0) | ||
| 443 | + /// ``` | ||
| 444 | + /// {@end-tool} | ||
| 445 | + const EdgeInsetsDirectional.only({ | ||
| 446 | + this.start = 0.0, | ||
| 447 | + this.top = 0.0, | ||
| 448 | + this.end = 0.0, | ||
| 449 | + this.bottom = 0.0, | ||
| 450 | + }); | ||
| 451 | + | ||
| 452 | + /// Creates insets with symmetric vertical and horizontal offsets. | ||
| 453 | + /// | ||
| 454 | + /// This is equivalent to [EdgeInsets.symmetric], since the inset is the same | ||
| 455 | + /// with either [TextDirection]. This constructor is just a convenience for | ||
| 456 | + /// type compatibility. | ||
| 457 | + /// | ||
| 458 | + /// {@tool snippet} | ||
| 459 | + /// Eight pixel margin above and below, no horizontal margins: | ||
| 460 | + /// | ||
| 461 | + /// ```dart | ||
| 462 | + /// const EdgeInsetsDirectional.symmetric(vertical: 8.0) | ||
| 463 | + /// ``` | ||
| 464 | + /// {@end-tool} | ||
| 465 | + const EdgeInsetsDirectional.symmetric({ | ||
| 466 | + double horizontal = 0.0, | ||
| 467 | + double vertical = 0.0, | ||
| 468 | + }) : start = horizontal, | ||
| 469 | + end = horizontal, | ||
| 470 | + top = vertical, | ||
| 471 | + bottom = vertical; | ||
| 472 | + | ||
| 473 | + /// Creates insets where all the offsets are `value`. | ||
| 474 | + /// | ||
| 475 | + /// {@tool snippet} | ||
| 476 | + /// | ||
| 477 | + /// Typical eight-pixel margin on all sides: | ||
| 478 | + /// | ||
| 479 | + /// ```dart | ||
| 480 | + /// const EdgeInsetsDirectional.all(8.0) | ||
| 481 | + /// ``` | ||
| 482 | + /// {@end-tool} | ||
| 483 | + const EdgeInsetsDirectional.all(double value) | ||
| 484 | + : start = value, | ||
| 485 | + top = value, | ||
| 486 | + end = value, | ||
| 487 | + bottom = value; | ||
| 488 | + | ||
| 489 | + /// An [EdgeInsetsDirectional] with zero offsets in each direction. | ||
| 490 | + /// | ||
| 491 | + /// Consider using [EdgeInsets.zero] instead, since that object has the same | ||
| 492 | + /// effect, but will be cheaper to [resolve]. | ||
| 493 | + static const EdgeInsetsDirectional zero = EdgeInsetsDirectional.only(); | ||
| 494 | + | ||
| 495 | + /// The offset from the start side, the side from which the user will start | ||
| 496 | + /// reading text. | ||
| 497 | + /// | ||
| 498 | + /// This value is normalized into an [EdgeInsets.left] or [EdgeInsets.right] | ||
| 499 | + /// value by the [resolve] method. | ||
| 500 | + final double start; | ||
| 501 | + | ||
| 502 | + @override | ||
| 503 | + double get _start => start; | ||
| 504 | + | ||
| 505 | + /// The offset from the top. | ||
| 506 | + /// | ||
| 507 | + /// This value is passed through to [EdgeInsets.top] unmodified by the | ||
| 508 | + /// [resolve] method. | ||
| 509 | + final double top; | ||
| 510 | + | ||
| 511 | + @override | ||
| 512 | + double get _top => top; | ||
| 513 | + | ||
| 514 | + /// The offset from the end side, the side on which the user ends reading | ||
| 515 | + /// text. | ||
| 516 | + /// | ||
| 517 | + /// This value is normalized into an [EdgeInsets.left] or [EdgeInsets.right] | ||
| 518 | + /// value by the [resolve] method. | ||
| 519 | + final double end; | ||
| 520 | + | ||
| 521 | + @override | ||
| 522 | + double get _end => end; | ||
| 523 | + | ||
| 524 | + /// The offset from the bottom. | ||
| 525 | + /// | ||
| 526 | + /// This value is passed through to [EdgeInsets.bottom] unmodified by the | ||
| 527 | + /// [resolve] method. | ||
| 528 | + final double bottom; | ||
| 529 | + | ||
| 530 | + @override | ||
| 531 | + double get _bottom => bottom; | ||
| 532 | + | ||
| 533 | + @override | ||
| 534 | + double get _left => 0.0; | ||
| 535 | + | ||
| 536 | + @override | ||
| 537 | + double get _right => 0.0; | ||
| 538 | + | ||
| 539 | + @override | ||
| 540 | + EdgeInsetsGeometry add(EdgeInsetsGeometry other) { | ||
| 541 | + if (other is EdgeInsetsDirectional) { | ||
| 542 | + return this + other; | ||
| 543 | + } | ||
| 544 | + return super.add(other); | ||
| 545 | + } | ||
| 546 | + | ||
| 547 | + /// Returns the sum of two [EdgeInsetsDirectional] objects. | ||
| 548 | + EdgeInsetsDirectional operator +(EdgeInsetsDirectional other) { | ||
| 549 | + return EdgeInsetsDirectional.fromSTEB( | ||
| 550 | + start + other.start, | ||
| 277 | top + other.top, | 551 | top + other.top, |
| 278 | - right + other.right, | 552 | + end + other.end, |
| 279 | bottom + other.bottom, | 553 | bottom + other.bottom, |
| 280 | ); | 554 | ); |
| 281 | } | 555 | } |
| 282 | 556 | ||
| 283 | @override | 557 | @override |
| 284 | - String toString() => 'EdgeInsets $left, $top, $right, $bottom'; | 558 | + EdgeInsets resolve(TextDirection? direction) { |
| 559 | + assert(direction != null); | ||
| 560 | + switch (direction!) { | ||
| 561 | + case TextDirection.rtl: | ||
| 562 | + return EdgeInsets.fromLTRB(end, top, start, bottom); | ||
| 563 | + case TextDirection.ltr: | ||
| 564 | + return EdgeInsets.fromLTRB(start, top, end, bottom); | ||
| 565 | + } | ||
| 566 | + } | ||
| 285 | } | 567 | } |
| 286 | 568 | ||
| 287 | class Alignment { | 569 | class Alignment { |
| @@ -374,10 +656,7 @@ class FittedSizes { | @@ -374,10 +656,7 @@ class FittedSizes { | ||
| 374 | } | 656 | } |
| 375 | 657 | ||
| 376 | FittedSizes applyBoxFit(BoxFit fit, PdfPoint inputSize, PdfPoint outputSize) { | 658 | FittedSizes applyBoxFit(BoxFit fit, PdfPoint inputSize, PdfPoint outputSize) { |
| 377 | - if (inputSize.y <= 0.0 || | ||
| 378 | - inputSize.x <= 0.0 || | ||
| 379 | - outputSize.y <= 0.0 || | ||
| 380 | - outputSize.x <= 0.0) { | 659 | + if (inputSize.y <= 0.0 || inputSize.x <= 0.0 || outputSize.y <= 0.0 || outputSize.x <= 0.0) { |
| 381 | return const FittedSizes(PdfPoint.zero, PdfPoint.zero); | 660 | return const FittedSizes(PdfPoint.zero, PdfPoint.zero); |
| 382 | } | 661 | } |
| 383 | 662 | ||
| @@ -390,38 +669,29 @@ FittedSizes applyBoxFit(BoxFit fit, PdfPoint inputSize, PdfPoint outputSize) { | @@ -390,38 +669,29 @@ FittedSizes applyBoxFit(BoxFit fit, PdfPoint inputSize, PdfPoint outputSize) { | ||
| 390 | case BoxFit.contain: | 669 | case BoxFit.contain: |
| 391 | sourceSize = inputSize; | 670 | sourceSize = inputSize; |
| 392 | if (outputSize.x / outputSize.y > sourceSize.x / sourceSize.y) { | 671 | if (outputSize.x / outputSize.y > sourceSize.x / sourceSize.y) { |
| 393 | - destinationSize = | ||
| 394 | - PdfPoint(sourceSize.x * outputSize.y / sourceSize.y, outputSize.y); | 672 | + destinationSize = PdfPoint(sourceSize.x * outputSize.y / sourceSize.y, outputSize.y); |
| 395 | } else { | 673 | } else { |
| 396 | - destinationSize = | ||
| 397 | - PdfPoint(outputSize.x, sourceSize.y * outputSize.x / sourceSize.x); | 674 | + destinationSize = PdfPoint(outputSize.x, sourceSize.y * outputSize.x / sourceSize.x); |
| 398 | } | 675 | } |
| 399 | break; | 676 | break; |
| 400 | case BoxFit.cover: | 677 | case BoxFit.cover: |
| 401 | if (outputSize.x / outputSize.y > inputSize.x / inputSize.y) { | 678 | if (outputSize.x / outputSize.y > inputSize.x / inputSize.y) { |
| 402 | - sourceSize = | ||
| 403 | - PdfPoint(inputSize.x, inputSize.x * outputSize.y / outputSize.x); | 679 | + sourceSize = PdfPoint(inputSize.x, inputSize.x * outputSize.y / outputSize.x); |
| 404 | } else { | 680 | } else { |
| 405 | - sourceSize = | ||
| 406 | - PdfPoint(inputSize.y * outputSize.x / outputSize.y, inputSize.y); | 681 | + sourceSize = PdfPoint(inputSize.y * outputSize.x / outputSize.y, inputSize.y); |
| 407 | } | 682 | } |
| 408 | destinationSize = outputSize; | 683 | destinationSize = outputSize; |
| 409 | break; | 684 | break; |
| 410 | case BoxFit.fitWidth: | 685 | case BoxFit.fitWidth: |
| 411 | - sourceSize = | ||
| 412 | - PdfPoint(inputSize.x, inputSize.x * outputSize.y / outputSize.x); | ||
| 413 | - destinationSize = | ||
| 414 | - PdfPoint(outputSize.x, sourceSize.y * outputSize.x / sourceSize.x); | 686 | + sourceSize = PdfPoint(inputSize.x, inputSize.x * outputSize.y / outputSize.x); |
| 687 | + destinationSize = PdfPoint(outputSize.x, sourceSize.y * outputSize.x / sourceSize.x); | ||
| 415 | break; | 688 | break; |
| 416 | case BoxFit.fitHeight: | 689 | case BoxFit.fitHeight: |
| 417 | - sourceSize = | ||
| 418 | - PdfPoint(inputSize.y * outputSize.x / outputSize.y, inputSize.y); | ||
| 419 | - destinationSize = | ||
| 420 | - PdfPoint(sourceSize.x * outputSize.y / sourceSize.y, outputSize.y); | 690 | + sourceSize = PdfPoint(inputSize.y * outputSize.x / outputSize.y, inputSize.y); |
| 691 | + destinationSize = PdfPoint(sourceSize.x * outputSize.y / sourceSize.y, outputSize.y); | ||
| 421 | break; | 692 | break; |
| 422 | case BoxFit.none: | 693 | case BoxFit.none: |
| 423 | - sourceSize = PdfPoint(math.min(inputSize.x, outputSize.x), | ||
| 424 | - math.min(inputSize.y, outputSize.y)); | 694 | + sourceSize = PdfPoint(math.min(inputSize.x, outputSize.x), math.min(inputSize.y, outputSize.y)); |
| 425 | destinationSize = sourceSize; | 695 | destinationSize = sourceSize; |
| 426 | break; | 696 | break; |
| 427 | case BoxFit.scaleDown: | 697 | case BoxFit.scaleDown: |
| @@ -61,14 +61,12 @@ mixin SpanningWidget on Widget { | @@ -61,14 +61,12 @@ mixin SpanningWidget on Widget { | ||
| 61 | /// Called before relayout to restore the saved state and | 61 | /// Called before relayout to restore the saved state and |
| 62 | /// restart the layout in the same conditions | 62 | /// restart the layout in the same conditions |
| 63 | @protected | 63 | @protected |
| 64 | - void applyContext(covariant WidgetContext context) => | ||
| 65 | - saveContext().apply(context); | 64 | + void applyContext(covariant WidgetContext context) => saveContext().apply(context); |
| 66 | } | 65 | } |
| 67 | 66 | ||
| 68 | class NewPage extends Widget { | 67 | class NewPage extends Widget { |
| 69 | @override | 68 | @override |
| 70 | - void layout(Context context, BoxConstraints constraints, | ||
| 71 | - {bool parentUsesSize = false}) { | 69 | + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) { |
| 72 | box = PdfRect.zero; | 70 | box = PdfRect.zero; |
| 73 | } | 71 | } |
| 74 | } | 72 | } |
| @@ -151,7 +149,7 @@ class MultiPage extends Page { | @@ -151,7 +149,7 @@ class MultiPage extends Page { | ||
| 151 | ThemeData? theme, | 149 | ThemeData? theme, |
| 152 | this.maxPages = 20, | 150 | this.maxPages = 20, |
| 153 | PageOrientation? orientation, | 151 | PageOrientation? orientation, |
| 154 | - EdgeInsets? margin, | 152 | + EdgeInsetsGeometry? margin, |
| 155 | TextDirection? textDirection, | 153 | TextDirection? textDirection, |
| 156 | }) : _buildList = build, | 154 | }) : _buildList = build, |
| 157 | assert(maxPages > 0), | 155 | assert(maxPages > 0), |
| @@ -185,10 +183,9 @@ class MultiPage extends Page { | @@ -185,10 +183,9 @@ class MultiPage extends Page { | ||
| 185 | /// This is not checked with a Release build. | 183 | /// This is not checked with a Release build. |
| 186 | final int maxPages; | 184 | final int maxPages; |
| 187 | 185 | ||
| 188 | - void _paintChild( | ||
| 189 | - Context context, Widget child, double x, double y, double pageHeight) { | 186 | + void _paintChild(Context context, Widget child, double x, double y, double pageHeight) { |
| 190 | if (mustRotate) { | 187 | if (mustRotate) { |
| 191 | - final _margin = margin!; | 188 | + final _margin = resolvedMargin!; |
| 192 | context.canvas | 189 | context.canvas |
| 193 | ..saveContext() | 190 | ..saveContext() |
| 194 | ..setTransform(Matrix4.identity() | 191 | ..setTransform(Matrix4.identity() |
| @@ -198,10 +195,21 @@ class MultiPage extends Page { | @@ -198,10 +195,21 @@ class MultiPage extends Page { | ||
| 198 | y + _margin.left - _margin.bottom, | 195 | y + _margin.left - _margin.bottom, |
| 199 | )); | 196 | )); |
| 200 | 197 | ||
| 198 | + final availableWidth = pageHeight - resolvedMargin!.vertical; | ||
| 199 | + if (pageTheme.textDirection == TextDirection.rtl) { | ||
| 200 | + child.box = child.box!.copyWith( | ||
| 201 | + x: (availableWidth - child.box!.width) + child.box!.x, | ||
| 202 | + ); | ||
| 203 | + } | ||
| 201 | child.paint(context); | 204 | child.paint(context); |
| 202 | context.canvas.restoreContext(); | 205 | context.canvas.restoreContext(); |
| 203 | } else { | 206 | } else { |
| 204 | - child.box = PdfRect(x, y, child.box!.width, child.box!.height); | 207 | + var childXPos = x; |
| 208 | + if (pageTheme.textDirection == TextDirection.rtl) { | ||
| 209 | + final availableWidth = pageFormat.width - resolvedMargin!.horizontal; | ||
| 210 | + childXPos = (availableWidth - child.box!.width) + x; | ||
| 211 | + } | ||
| 212 | + child.box = child.box!.copyWith(x: childXPos, y: y); | ||
| 205 | child.paint(context); | 213 | child.paint(context); |
| 206 | } | 214 | } |
| 207 | } | 215 | } |
| @@ -211,33 +219,26 @@ class MultiPage extends Page { | @@ -211,33 +219,26 @@ class MultiPage extends Page { | ||
| 211 | assert(pageFormat.width > 0 && pageFormat.width < double.infinity); | 219 | assert(pageFormat.width > 0 && pageFormat.width < double.infinity); |
| 212 | assert(pageFormat.height > 0 && pageFormat.height < double.infinity); | 220 | assert(pageFormat.height > 0 && pageFormat.height < double.infinity); |
| 213 | 221 | ||
| 214 | - final _margin = margin; | 222 | + final _margin = resolvedMargin!; |
| 215 | final _mustRotate = mustRotate; | 223 | final _mustRotate = mustRotate; |
| 216 | final pageHeight = _mustRotate ? pageFormat.width : pageFormat.height; | 224 | final pageHeight = _mustRotate ? pageFormat.width : pageFormat.height; |
| 217 | - final pageHeightMargin = | ||
| 218 | - _mustRotate ? _margin!.horizontal : _margin!.vertical; | 225 | + final pageHeightMargin = _mustRotate ? _margin.horizontal : _margin.vertical; |
| 219 | final constraints = BoxConstraints( | 226 | final constraints = BoxConstraints( |
| 220 | - maxWidth: _mustRotate | ||
| 221 | - ? (pageFormat.height - _margin.vertical) | ||
| 222 | - : (pageFormat.width - _margin.horizontal)); | 227 | + maxWidth: _mustRotate ? (pageFormat.height - _margin.vertical) : (pageFormat.width - _margin.horizontal)); |
| 223 | final fullConstraints = mustRotate | 228 | final fullConstraints = mustRotate |
| 224 | ? BoxConstraints( | 229 | ? BoxConstraints( |
| 225 | - maxWidth: pageFormat.height - _margin.vertical, | ||
| 226 | - maxHeight: pageFormat.width - _margin.horizontal) | 230 | + maxWidth: pageFormat.height - _margin.vertical, maxHeight: pageFormat.width - _margin.horizontal) |
| 227 | : BoxConstraints( | 231 | : BoxConstraints( |
| 228 | - maxWidth: pageFormat.width - _margin.horizontal, | ||
| 229 | - maxHeight: pageFormat.height - _margin.vertical); | 232 | + maxWidth: pageFormat.width - _margin.horizontal, maxHeight: pageFormat.height - _margin.vertical); |
| 230 | final calculatedTheme = theme ?? document.theme ?? ThemeData.base(); | 233 | final calculatedTheme = theme ?? document.theme ?? ThemeData.base(); |
| 231 | Context? context; | 234 | Context? context; |
| 232 | late double offsetEnd; | 235 | late double offsetEnd; |
| 233 | double? offsetStart; | 236 | double? offsetStart; |
| 234 | var _index = 0; | 237 | var _index = 0; |
| 235 | var sameCount = 0; | 238 | var sameCount = 0; |
| 236 | - final baseContext = | ||
| 237 | - Context(document: document.document).inheritFromAll(<Inherited>[ | 239 | + final baseContext = Context(document: document.document).inheritFromAll(<Inherited>[ |
| 238 | calculatedTheme, | 240 | calculatedTheme, |
| 239 | - if (pageTheme.textDirection != null) | ||
| 240 | - InheritedDirectionality(pageTheme.textDirection), | 241 | + if (pageTheme.textDirection != null) InheritedDirectionality(pageTheme.textDirection), |
| 241 | ]); | 242 | ]); |
| 242 | final children = _buildList(baseContext); | 243 | final children = _buildList(baseContext); |
| 243 | WidgetContext? widgetContext; | 244 | WidgetContext? widgetContext; |
| @@ -272,10 +273,8 @@ class MultiPage extends Page { | @@ -272,10 +273,8 @@ class MultiPage extends Page { | ||
| 272 | return true; | 273 | return true; |
| 273 | }()); | 274 | }()); |
| 274 | 275 | ||
| 275 | - offsetStart = pageHeight - | ||
| 276 | - (_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top); | ||
| 277 | - offsetEnd = | ||
| 278 | - _mustRotate ? pageHeightMargin - _margin.left : _margin.bottom; | 276 | + offsetStart = pageHeight - (_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top); |
| 277 | + offsetEnd = _mustRotate ? pageHeightMargin - _margin.left : _margin.bottom; | ||
| 279 | 278 | ||
| 280 | _pages.add(_MultiPageInstance( | 279 | _pages.add(_MultiPageInstance( |
| 281 | context: context, | 280 | context: context, |
| @@ -327,8 +326,7 @@ class MultiPage extends Page { | @@ -327,8 +326,7 @@ class MultiPage extends Page { | ||
| 327 | 326 | ||
| 328 | // Else we crash if the widget is too big and cannot be separated | 327 | // Else we crash if the widget is too big and cannot be separated |
| 329 | if (!canSpan) { | 328 | if (!canSpan) { |
| 330 | - throw Exception( | ||
| 331 | - 'Widget won\'t fit into the page as its height (${child.box!.height}) ' | 329 | + throw Exception('Widget won\'t fit into the page as its height (${child.box!.height}) ' |
| 332 | 'exceed a page height (${pageHeight - pageHeightMargin}). ' | 330 | 'exceed a page height (${pageHeight - pageHeightMargin}). ' |
| 333 | 'You probably need a SpanningWidget or use a single page layout'); | 331 | 'You probably need a SpanningWidget or use a single page layout'); |
| 334 | } | 332 | } |
| @@ -340,8 +338,7 @@ class MultiPage extends Page { | @@ -340,8 +338,7 @@ class MultiPage extends Page { | ||
| 340 | span.applyContext(savedContext); | 338 | span.applyContext(savedContext); |
| 341 | } | 339 | } |
| 342 | 340 | ||
| 343 | - final localConstraints = | ||
| 344 | - constraints.copyWith(maxHeight: offsetStart - offsetEnd); | 341 | + final localConstraints = constraints.copyWith(maxHeight: offsetStart - offsetEnd); |
| 345 | span.layout(context, localConstraints, parentUsesSize: false); | 342 | span.layout(context, localConstraints, parentUsesSize: false); |
| 346 | assert(span.box != null); | 343 | assert(span.box != null); |
| 347 | widgetContext = span.saveContext(); | 344 | widgetContext = span.saveContext(); |
| @@ -368,8 +365,7 @@ class MultiPage extends Page { | @@ -368,8 +365,7 @@ class MultiPage extends Page { | ||
| 368 | _MultiPageWidget( | 365 | _MultiPageWidget( |
| 369 | child: child, | 366 | child: child, |
| 370 | constraints: constraints, | 367 | constraints: constraints, |
| 371 | - widgetContext: | ||
| 372 | - child is SpanningWidget && canSpan ? child.cloneContext() : null, | 368 | + widgetContext: child is SpanningWidget && canSpan ? child.cloneContext() : null, |
| 373 | ), | 369 | ), |
| 374 | ); | 370 | ); |
| 375 | 371 | ||
| @@ -381,28 +377,24 @@ class MultiPage extends Page { | @@ -381,28 +377,24 @@ class MultiPage extends Page { | ||
| 381 | 377 | ||
| 382 | @override | 378 | @override |
| 383 | void postProcess(Document document) { | 379 | void postProcess(Document document) { |
| 384 | - final _margin = margin; | 380 | + final _margin = resolvedMargin!; |
| 385 | final _mustRotate = mustRotate; | 381 | final _mustRotate = mustRotate; |
| 386 | final pageHeight = _mustRotate ? pageFormat.width : pageFormat.height; | 382 | final pageHeight = _mustRotate ? pageFormat.width : pageFormat.height; |
| 387 | final pageWidth = _mustRotate ? pageFormat.height : pageFormat.width; | 383 | final pageWidth = _mustRotate ? pageFormat.height : pageFormat.width; |
| 388 | - final pageHeightMargin = | ||
| 389 | - _mustRotate ? _margin!.horizontal : _margin!.vertical; | 384 | + final pageHeightMargin = _mustRotate ? _margin.horizontal : _margin.vertical; |
| 390 | final pageWidthMargin = _mustRotate ? _margin.vertical : _margin.horizontal; | 385 | final pageWidthMargin = _mustRotate ? _margin.vertical : _margin.horizontal; |
| 391 | final availableWidth = pageWidth - pageWidthMargin; | 386 | final availableWidth = pageWidth - pageWidthMargin; |
| 392 | 387 | ||
| 393 | for (final page in _pages) { | 388 | for (final page in _pages) { |
| 394 | - var offsetStart = pageHeight - | ||
| 395 | - (_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top); | ||
| 396 | - var offsetEnd = | ||
| 397 | - _mustRotate ? pageHeightMargin - _margin.left : _margin.bottom; | 389 | + var offsetStart = pageHeight - (_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top); |
| 390 | + var offsetEnd = _mustRotate ? pageHeightMargin - _margin.left : _margin.bottom; | ||
| 398 | 391 | ||
| 399 | if (pageTheme.buildBackground != null) { | 392 | if (pageTheme.buildBackground != null) { |
| 400 | final child = pageTheme.buildBackground!(page.context); | 393 | final child = pageTheme.buildBackground!(page.context); |
| 401 | 394 | ||
| 402 | child.layout(page.context, page.fullConstraints, parentUsesSize: false); | 395 | child.layout(page.context, page.fullConstraints, parentUsesSize: false); |
| 403 | assert(child.box != null); | 396 | assert(child.box != null); |
| 404 | - _paintChild(page.context, child, _margin.left, _margin.bottom, | ||
| 405 | - pageFormat.height); | 397 | + _paintChild(page.context, child, _margin.left, _margin.bottom, pageFormat.height); |
| 406 | } | 398 | } |
| 407 | 399 | ||
| 408 | var totalFlex = 0; | 400 | var totalFlex = 0; |
| @@ -428,23 +420,20 @@ class MultiPage extends Page { | @@ -428,23 +420,20 @@ class MultiPage extends Page { | ||
| 428 | if (header != null) { | 420 | if (header != null) { |
| 429 | final headerWidget = header!(page.context); | 421 | final headerWidget = header!(page.context); |
| 430 | 422 | ||
| 431 | - headerWidget.layout(page.context, page.constraints, | ||
| 432 | - parentUsesSize: false); | 423 | + headerWidget.layout(page.context, page.constraints, parentUsesSize: false); |
| 433 | assert(headerWidget.box != null); | 424 | assert(headerWidget.box != null); |
| 434 | offsetStart -= headerWidget.box!.height; | 425 | offsetStart -= headerWidget.box!.height; |
| 435 | - _paintChild(page.context, headerWidget, _margin.left, | ||
| 436 | - page.offsetStart! - headerWidget.box!.height, pageFormat.height); | 426 | + _paintChild( |
| 427 | + page.context, headerWidget, _margin.left, page.offsetStart! - headerWidget.box!.height, pageFormat.height); | ||
| 437 | } | 428 | } |
| 438 | 429 | ||
| 439 | if (footer != null) { | 430 | if (footer != null) { |
| 440 | final footerWidget = footer!(page.context); | 431 | final footerWidget = footer!(page.context); |
| 441 | 432 | ||
| 442 | - footerWidget.layout(page.context, page.constraints, | ||
| 443 | - parentUsesSize: false); | 433 | + footerWidget.layout(page.context, page.constraints, parentUsesSize: false); |
| 444 | assert(footerWidget.box != null); | 434 | assert(footerWidget.box != null); |
| 445 | offsetEnd += footerWidget.box!.height; | 435 | offsetEnd += footerWidget.box!.height; |
| 446 | - _paintChild(page.context, footerWidget, _margin.left, _margin.bottom, | ||
| 447 | - pageFormat.height); | 436 | + _paintChild(page.context, footerWidget, _margin.left, _margin.bottom, pageFormat.height); |
| 448 | } | 437 | } |
| 449 | 438 | ||
| 450 | final freeSpace = math.max(0.0, offsetStart - offsetEnd - allocatedSize); | 439 | final freeSpace = math.max(0.0, offsetStart - offsetEnd - allocatedSize); |
| @@ -473,16 +462,14 @@ class MultiPage extends Page { | @@ -473,16 +462,14 @@ class MultiPage extends Page { | ||
| 473 | break; | 462 | break; |
| 474 | case MainAxisAlignment.spaceBetween: | 463 | case MainAxisAlignment.spaceBetween: |
| 475 | leadingSpace = 0.0; | 464 | leadingSpace = 0.0; |
| 476 | - betweenSpace = | ||
| 477 | - totalChildren > 1 ? freeSpace / (totalChildren - 1) : 0.0; | 465 | + betweenSpace = totalChildren > 1 ? freeSpace / (totalChildren - 1) : 0.0; |
| 478 | break; | 466 | break; |
| 479 | case MainAxisAlignment.spaceAround: | 467 | case MainAxisAlignment.spaceAround: |
| 480 | betweenSpace = totalChildren > 0 ? freeSpace / totalChildren : 0.0; | 468 | betweenSpace = totalChildren > 0 ? freeSpace / totalChildren : 0.0; |
| 481 | leadingSpace = betweenSpace / 2.0; | 469 | leadingSpace = betweenSpace / 2.0; |
| 482 | break; | 470 | break; |
| 483 | case MainAxisAlignment.spaceEvenly: | 471 | case MainAxisAlignment.spaceEvenly: |
| 484 | - betweenSpace = | ||
| 485 | - totalChildren > 0 ? freeSpace / (totalChildren + 1) : 0.0; | 472 | + betweenSpace = totalChildren > 0 ? freeSpace / (totalChildren + 1) : 0.0; |
| 486 | leadingSpace = betweenSpace; | 473 | leadingSpace = betweenSpace; |
| 487 | break; | 474 | break; |
| 488 | } | 475 | } |
| @@ -494,11 +481,8 @@ class MultiPage extends Page { | @@ -494,11 +481,8 @@ class MultiPage extends Page { | ||
| 494 | final flex = child is Flexible ? child.flex : 0; | 481 | final flex = child is Flexible ? child.flex : 0; |
| 495 | final fit = child is Flexible ? child.fit : FlexFit.loose; | 482 | final fit = child is Flexible ? child.fit : FlexFit.loose; |
| 496 | if (flex > 0) { | 483 | if (flex > 0) { |
| 497 | - assert(child is! SpanningWidget || child.canSpan == false, | ||
| 498 | - 'Cannot have a spanning widget flexible'); | ||
| 499 | - final maxChildExtent = child == lastFlexChild | ||
| 500 | - ? (freeSpace - allocatedFlexSpace) | ||
| 501 | - : spacePerFlex * flex; | 484 | + assert(child is! SpanningWidget || child.canSpan == false, 'Cannot have a spanning widget flexible'); |
| 485 | + final maxChildExtent = child == lastFlexChild ? (freeSpace - allocatedFlexSpace) : spacePerFlex * flex; | ||
| 502 | late double minChildExtent; | 486 | late double minChildExtent; |
| 503 | switch (fit) { | 487 | switch (fit) { |
| 504 | case FlexFit.tight: | 488 | case FlexFit.tight: |
| @@ -547,8 +531,7 @@ class MultiPage extends Page { | @@ -547,8 +531,7 @@ class MultiPage extends Page { | ||
| 547 | if (child is SpanningWidget && child.canSpan) { | 531 | if (child is SpanningWidget && child.canSpan) { |
| 548 | child.applyContext(widget.widgetContext!); | 532 | child.applyContext(widget.widgetContext!); |
| 549 | } | 533 | } |
| 550 | - _paintChild(page.context, widget.child, _margin.left + x, pos, | ||
| 551 | - pageFormat.height); | 534 | + _paintChild(page.context, widget.child, _margin.left + x, pos, pageFormat.height); |
| 552 | pos -= betweenSpace; | 535 | pos -= betweenSpace; |
| 553 | } | 536 | } |
| 554 | 537 | ||
| @@ -557,8 +540,7 @@ class MultiPage extends Page { | @@ -557,8 +540,7 @@ class MultiPage extends Page { | ||
| 557 | 540 | ||
| 558 | child.layout(page.context, page.fullConstraints, parentUsesSize: false); | 541 | child.layout(page.context, page.fullConstraints, parentUsesSize: false); |
| 559 | assert(child.box != null); | 542 | assert(child.box != null); |
| 560 | - _paintChild(page.context, child, _margin.left, _margin.bottom, | ||
| 561 | - pageFormat.height); | 543 | + _paintChild(page.context, child, _margin.left, _margin.bottom, pageFormat.height); |
| 562 | } | 544 | } |
| 563 | } | 545 | } |
| 564 | } | 546 | } |
| @@ -40,7 +40,7 @@ class Page { | @@ -40,7 +40,7 @@ class Page { | ||
| 40 | required BuildCallback build, | 40 | required BuildCallback build, |
| 41 | ThemeData? theme, | 41 | ThemeData? theme, |
| 42 | PageOrientation? orientation, | 42 | PageOrientation? orientation, |
| 43 | - EdgeInsets? margin, | 43 | + EdgeInsetsGeometry? margin, |
| 44 | bool clip = false, | 44 | bool clip = false, |
| 45 | TextDirection? textDirection, | 45 | TextDirection? textDirection, |
| 46 | }) : assert( | 46 | }) : assert( |
| @@ -77,11 +77,14 @@ class Page { | @@ -77,11 +77,14 @@ class Page { | ||
| 77 | 77 | ||
| 78 | PdfPage? _pdfPage; | 78 | PdfPage? _pdfPage; |
| 79 | 79 | ||
| 80 | - EdgeInsets? get margin => pageTheme.margin; | 80 | + EdgeInsetsGeometry? get margin => pageTheme.margin; |
| 81 | + | ||
| 82 | + EdgeInsets? get resolvedMargin => margin?.resolve(pageTheme.textDirection); | ||
| 81 | 83 | ||
| 82 | @protected | 84 | @protected |
| 83 | void debugPaint(Context context) { | 85 | void debugPaint(Context context) { |
| 84 | - final _margin = margin!; | 86 | + final _margin = resolvedMargin!; |
| 87 | + | ||
| 85 | context.canvas | 88 | context.canvas |
| 86 | ..setFillColor(PdfColors.lightGreen) | 89 | ..setFillColor(PdfColors.lightGreen) |
| 87 | ..moveTo(0, 0) | 90 | ..moveTo(0, 0) |
| @@ -90,8 +93,7 @@ class Page { | @@ -90,8 +93,7 @@ class Page { | ||
| 90 | ..lineTo(0, pageFormat.height) | 93 | ..lineTo(0, pageFormat.height) |
| 91 | ..moveTo(_margin.left, _margin.bottom) | 94 | ..moveTo(_margin.left, _margin.bottom) |
| 92 | ..lineTo(_margin.left, pageFormat.height - _margin.top) | 95 | ..lineTo(_margin.left, pageFormat.height - _margin.top) |
| 93 | - ..lineTo( | ||
| 94 | - pageFormat.width - _margin.right, pageFormat.height - _margin.top) | 96 | + ..lineTo(pageFormat.width - _margin.right, pageFormat.height - _margin.top) |
| 95 | ..lineTo(pageFormat.width - _margin.right, _margin.bottom) | 97 | ..lineTo(pageFormat.width - _margin.right, _margin.bottom) |
| 96 | ..fillPath(); | 98 | ..fillPath(); |
| 97 | } | 99 | } |
| @@ -99,8 +101,7 @@ class Page { | @@ -99,8 +101,7 @@ class Page { | ||
| 99 | void generate(Document document, {bool insert = true, int? index}) { | 101 | void generate(Document document, {bool insert = true, int? index}) { |
| 100 | if (index != null) { | 102 | if (index != null) { |
| 101 | if (insert) { | 103 | if (insert) { |
| 102 | - _pdfPage = | ||
| 103 | - PdfPage(document.document, pageFormat: pageFormat, index: index); | 104 | + _pdfPage = PdfPage(document.document, pageFormat: pageFormat, index: index); |
| 104 | } else { | 105 | } else { |
| 105 | _pdfPage = document.document.page(index); | 106 | _pdfPage = document.document.page(index); |
| 106 | } | 107 | } |
| @@ -112,14 +113,12 @@ class Page { | @@ -112,14 +113,12 @@ class Page { | ||
| 112 | void postProcess(Document document) { | 113 | void postProcess(Document document) { |
| 113 | final canvas = _pdfPage!.getGraphics(); | 114 | final canvas = _pdfPage!.getGraphics(); |
| 114 | canvas.reset(); | 115 | canvas.reset(); |
| 115 | - final _margin = margin; | 116 | + final _margin = resolvedMargin; |
| 116 | var constraints = mustRotate | 117 | var constraints = mustRotate |
| 117 | ? BoxConstraints( | 118 | ? BoxConstraints( |
| 118 | - maxWidth: pageFormat.height - _margin!.vertical, | ||
| 119 | - maxHeight: pageFormat.width - _margin.horizontal) | 119 | + maxWidth: pageFormat.height - _margin!.vertical, maxHeight: pageFormat.width - _margin.horizontal) |
| 120 | : BoxConstraints( | 120 | : BoxConstraints( |
| 121 | - maxWidth: pageFormat.width - _margin!.horizontal, | ||
| 122 | - maxHeight: pageFormat.height - _margin.vertical); | 121 | + maxWidth: pageFormat.width - _margin!.horizontal, maxHeight: pageFormat.height - _margin.vertical); |
| 123 | 122 | ||
| 124 | final calculatedTheme = theme ?? document.theme ?? ThemeData.base(); | 123 | final calculatedTheme = theme ?? document.theme ?? ThemeData.base(); |
| 125 | final context = Context( | 124 | final context = Context( |
| @@ -128,8 +127,7 @@ class Page { | @@ -128,8 +127,7 @@ class Page { | ||
| 128 | canvas: canvas, | 127 | canvas: canvas, |
| 129 | ).inheritFromAll(<Inherited>[ | 128 | ).inheritFromAll(<Inherited>[ |
| 130 | calculatedTheme, | 129 | calculatedTheme, |
| 131 | - if (pageTheme.textDirection != null) | ||
| 132 | - InheritedDirectionality(pageTheme.textDirection), | 130 | + if (pageTheme.textDirection != null) InheritedDirectionality(pageTheme.textDirection), |
| 133 | ]); | 131 | ]); |
| 134 | 132 | ||
| 135 | Widget? background; | 133 | Widget? background; |
| @@ -141,8 +139,7 @@ class Page { | @@ -141,8 +139,7 @@ class Page { | ||
| 141 | final size = layout(content, context, constraints); | 139 | final size = layout(content, context, constraints); |
| 142 | 140 | ||
| 143 | if (_pdfPage!.pageFormat.height == double.infinity) { | 141 | if (_pdfPage!.pageFormat.height == double.infinity) { |
| 144 | - _pdfPage!.pageFormat = | ||
| 145 | - _pdfPage!.pageFormat.copyWith(width: size.x, height: size.y); | 142 | + _pdfPage!.pageFormat = _pdfPage!.pageFormat.copyWith(width: size.x, height: size.y); |
| 146 | constraints = mustRotate | 143 | constraints = mustRotate |
| 147 | ? BoxConstraints( | 144 | ? BoxConstraints( |
| 148 | maxWidth: _pdfPage!.pageFormat.height - _margin.vertical, | 145 | maxWidth: _pdfPage!.pageFormat.height - _margin.vertical, |
| @@ -181,43 +178,49 @@ class Page { | @@ -181,43 +178,49 @@ class Page { | ||
| 181 | } | 178 | } |
| 182 | 179 | ||
| 183 | @protected | 180 | @protected |
| 184 | - PdfPoint layout(Widget child, Context context, BoxConstraints constraints, | ||
| 185 | - {bool parentUsesSize = false}) { | ||
| 186 | - final _margin = margin!; | 181 | + PdfPoint layout(Widget child, Context context, BoxConstraints constraints, {bool parentUsesSize = false}) { |
| 182 | + final _margin = resolvedMargin!; | ||
| 187 | child.layout(context, constraints, parentUsesSize: parentUsesSize); | 183 | child.layout(context, constraints, parentUsesSize: parentUsesSize); |
| 188 | assert(child.box != null); | 184 | assert(child.box != null); |
| 189 | 185 | ||
| 190 | - final width = pageFormat.width == double.infinity | ||
| 191 | - ? child.box!.width + _margin.left + _margin.right | ||
| 192 | - : pageFormat.width; | 186 | + final width = |
| 187 | + pageFormat.width == double.infinity ? child.box!.width + _margin.left + _margin.right : pageFormat.width; | ||
| 193 | 188 | ||
| 194 | - final height = pageFormat.height == double.infinity | ||
| 195 | - ? child.box!.height + _margin.top + _margin.bottom | ||
| 196 | - : pageFormat.height; | 189 | + final height = |
| 190 | + pageFormat.height == double.infinity ? child.box!.height + _margin.top + _margin.bottom : pageFormat.height; | ||
| 197 | 191 | ||
| 198 | - child.box = PdfRect(_margin.left, height - child.box!.height - _margin.top, | ||
| 199 | - child.box!.width, child.box!.height); | 192 | + child.box = PdfRect(_margin.left, height - child.box!.height - _margin.top, child.box!.width, child.box!.height); |
| 200 | 193 | ||
| 201 | return PdfPoint(width, height); | 194 | return PdfPoint(width, height); |
| 202 | } | 195 | } |
| 203 | 196 | ||
| 204 | @protected | 197 | @protected |
| 205 | void paint(Widget child, Context context) { | 198 | void paint(Widget child, Context context) { |
| 206 | - if (pageTheme.clip) { | ||
| 207 | - final _margin = margin!; | ||
| 208 | - context.canvas | ||
| 209 | - ..saveContext() | ||
| 210 | - ..drawRect( | 199 | + final _margin = resolvedMargin!; |
| 200 | + final box = PdfRect( | ||
| 211 | _margin.left, | 201 | _margin.left, |
| 212 | _margin.bottom, | 202 | _margin.bottom, |
| 213 | pageFormat.width - _margin.horizontal, | 203 | pageFormat.width - _margin.horizontal, |
| 214 | pageFormat.height - _margin.vertical, | 204 | pageFormat.height - _margin.vertical, |
| 215 | - ) | 205 | + ); |
| 206 | + if (pageTheme.clip) { | ||
| 207 | + context.canvas | ||
| 208 | + ..saveContext() | ||
| 209 | + ..drawRect(box.x, box.y, box.width, box.height) | ||
| 216 | ..clipPath(); | 210 | ..clipPath(); |
| 217 | } | 211 | } |
| 218 | 212 | ||
| 213 | + if (pageTheme.textDirection == TextDirection.rtl) { | ||
| 214 | + child.box = PdfRect( | ||
| 215 | + ((mustRotate ? box.height : box.width) - child.box!.width) + child.box!.x, | ||
| 216 | + child.box!.y, | ||
| 217 | + child.box!.width, | ||
| 218 | + child.box!.height, | ||
| 219 | + ); | ||
| 220 | + } | ||
| 221 | + | ||
| 219 | if (mustRotate) { | 222 | if (mustRotate) { |
| 220 | - final _margin = margin!; | 223 | + final _margin = resolvedMargin!; |
| 221 | context.canvas | 224 | context.canvas |
| 222 | ..saveContext() | 225 | ..saveContext() |
| 223 | ..setTransform(Matrix4.identity() | 226 | ..setTransform(Matrix4.identity() |
| @@ -30,7 +30,7 @@ class PageTheme { | @@ -30,7 +30,7 @@ class PageTheme { | ||
| 30 | this.buildForeground, | 30 | this.buildForeground, |
| 31 | this.theme, | 31 | this.theme, |
| 32 | PageOrientation? orientation, | 32 | PageOrientation? orientation, |
| 33 | - EdgeInsets? margin, | 33 | + EdgeInsetsGeometry? margin, |
| 34 | this.clip = false, | 34 | this.clip = false, |
| 35 | this.textDirection, | 35 | this.textDirection, |
| 36 | }) : pageFormat = pageFormat ?? PdfPageFormat.standard, | 36 | }) : pageFormat = pageFormat ?? PdfPageFormat.standard, |
| @@ -41,7 +41,7 @@ class PageTheme { | @@ -41,7 +41,7 @@ class PageTheme { | ||
| 41 | 41 | ||
| 42 | final PageOrientation orientation; | 42 | final PageOrientation orientation; |
| 43 | 43 | ||
| 44 | - final EdgeInsets? _margin; | 44 | + final EdgeInsetsGeometry? _margin; |
| 45 | 45 | ||
| 46 | final BuildCallback? buildBackground; | 46 | final BuildCallback? buildBackground; |
| 47 | 47 | ||
| @@ -54,27 +54,30 @@ class PageTheme { | @@ -54,27 +54,30 @@ class PageTheme { | ||
| 54 | final TextDirection? textDirection; | 54 | final TextDirection? textDirection; |
| 55 | 55 | ||
| 56 | bool get mustRotate => | 56 | bool get mustRotate => |
| 57 | - (orientation == PageOrientation.landscape && | ||
| 58 | - pageFormat.height > pageFormat.width) || | ||
| 59 | - (orientation == PageOrientation.portrait && | ||
| 60 | - pageFormat.width > pageFormat.height); | 57 | + (orientation == PageOrientation.landscape && pageFormat.height > pageFormat.width) || |
| 58 | + (orientation == PageOrientation.portrait && pageFormat.width > pageFormat.height); | ||
| 61 | 59 | ||
| 62 | - EdgeInsets? get margin { | 60 | + EdgeInsetsGeometry? get margin { |
| 63 | if (_margin != null) { | 61 | if (_margin != null) { |
| 62 | + final effectiveMargin = _margin!.resolve(textDirection); | ||
| 64 | if (mustRotate) { | 63 | if (mustRotate) { |
| 65 | return EdgeInsets.fromLTRB( | 64 | return EdgeInsets.fromLTRB( |
| 66 | - _margin!.bottom, _margin!.left, _margin!.top, _margin!.right); | 65 | + effectiveMargin.bottom, |
| 66 | + effectiveMargin.left, | ||
| 67 | + effectiveMargin.top, | ||
| 68 | + effectiveMargin.right, | ||
| 69 | + ); | ||
| 67 | } else { | 70 | } else { |
| 68 | return _margin; | 71 | return _margin; |
| 69 | } | 72 | } |
| 70 | } | 73 | } |
| 71 | 74 | ||
| 72 | if (mustRotate) { | 75 | if (mustRotate) { |
| 73 | - return EdgeInsets.fromLTRB(pageFormat.marginBottom, pageFormat.marginLeft, | ||
| 74 | - pageFormat.marginTop, pageFormat.marginRight); | 76 | + return EdgeInsets.fromLTRB( |
| 77 | + pageFormat.marginBottom, pageFormat.marginLeft, pageFormat.marginTop, pageFormat.marginRight); | ||
| 75 | } else { | 78 | } else { |
| 76 | - return EdgeInsets.fromLTRB(pageFormat.marginLeft, pageFormat.marginTop, | ||
| 77 | - pageFormat.marginRight, pageFormat.marginBottom); | 79 | + return EdgeInsets.fromLTRB( |
| 80 | + pageFormat.marginLeft, pageFormat.marginTop, pageFormat.marginRight, pageFormat.marginBottom); | ||
| 78 | } | 81 | } |
| 79 | } | 82 | } |
| 80 | 83 |
| @@ -40,11 +40,7 @@ final _yellowBox = Container( | @@ -40,11 +40,7 @@ final _yellowBox = Container( | ||
| 40 | color: PdfColors.yellow, | 40 | color: PdfColors.yellow, |
| 41 | ); | 41 | ); |
| 42 | 42 | ||
| 43 | -final _greenBox = Container( | ||
| 44 | - width: 50, | ||
| 45 | - height: 50, | ||
| 46 | - color: PdfColors.green, | ||
| 47 | -); | 43 | + |
| 48 | void main() { | 44 | void main() { |
| 49 | setUpAll(() { | 45 | setUpAll(() { |
| 50 | Document.debug = true; | 46 | Document.debug = true; |
| @@ -144,9 +140,8 @@ void main() { | @@ -144,9 +140,8 @@ void main() { | ||
| 144 | width: 150, | 140 | width: 150, |
| 145 | height: 150, | 141 | height: 150, |
| 146 | child: Wrap( | 142 | child: Wrap( |
| 147 | - children: [_blueBox, _redBox,_yellowBox], | ||
| 148 | - ) | ||
| 149 | - ), | 143 | + children: [_blueBox, _redBox, _yellowBox], |
| 144 | + )), | ||
| 150 | ), | 145 | ), |
| 151 | ); | 146 | ); |
| 152 | }); | 147 | }); |
| @@ -160,9 +155,8 @@ void main() { | @@ -160,9 +155,8 @@ void main() { | ||
| 160 | width: 150, | 155 | width: 150, |
| 161 | height: 150, | 156 | height: 150, |
| 162 | child: Wrap( | 157 | child: Wrap( |
| 163 | - children: [_blueBox, _redBox,_yellowBox], | ||
| 164 | - ) | ||
| 165 | - ), | 158 | + children: [_blueBox, _redBox, _yellowBox], |
| 159 | + )), | ||
| 166 | ), | 160 | ), |
| 167 | ); | 161 | ); |
| 168 | }); | 162 | }); |
| @@ -178,9 +172,8 @@ void main() { | @@ -178,9 +172,8 @@ void main() { | ||
| 178 | spacing: 10, | 172 | spacing: 10, |
| 179 | runSpacing: 10, | 173 | runSpacing: 10, |
| 180 | runAlignment: WrapAlignment.center, | 174 | runAlignment: WrapAlignment.center, |
| 181 | - children: [_blueBox, _redBox,_yellowBox], | ||
| 182 | - ) | ||
| 183 | - ), | 175 | + children: [_blueBox, _redBox, _yellowBox], |
| 176 | + )), | ||
| 184 | ), | 177 | ), |
| 185 | ); | 178 | ); |
| 186 | }); | 179 | }); |
| @@ -197,9 +190,96 @@ void main() { | @@ -197,9 +190,96 @@ void main() { | ||
| 197 | spacing: 10, | 190 | spacing: 10, |
| 198 | runSpacing: 10, | 191 | runSpacing: 10, |
| 199 | runAlignment: WrapAlignment.end, | 192 | runAlignment: WrapAlignment.end, |
| 200 | - children: [_blueBox, _redBox,_yellowBox], | ||
| 201 | - ) | 193 | + children: [_blueBox, _redBox, _yellowBox], |
| 194 | + )), | ||
| 195 | + ), | ||
| 196 | + ); | ||
| 197 | + }); | ||
| 198 | + | ||
| 199 | + test('RTL Page Should render child aligned right', () { | ||
| 200 | + pdf.addPage( | ||
| 201 | + Page( | ||
| 202 | + textDirection: TextDirection.rtl, | ||
| 203 | + pageFormat: const PdfPageFormat(150, 150), | ||
| 204 | + build: (Context context) { | ||
| 205 | + return _blueBox; | ||
| 206 | + }, | ||
| 207 | + ), | ||
| 208 | + ); | ||
| 209 | + }); | ||
| 210 | + | ||
| 211 | + test('LTR Page Should render child aligned left', () { | ||
| 212 | + pdf.addPage( | ||
| 213 | + Page( | ||
| 214 | + textDirection: TextDirection.ltr, | ||
| 215 | + pageFormat: const PdfPageFormat(150, 150), | ||
| 216 | + build: (Context context) { | ||
| 217 | + return _blueBox; | ||
| 218 | + }, | ||
| 219 | + ), | ||
| 220 | + ); | ||
| 221 | + }); | ||
| 222 | + | ||
| 223 | + test('RTL Multi Page Should render child aligned right', () { | ||
| 224 | + pdf.addPage( | ||
| 225 | + MultiPage( | ||
| 226 | + textDirection: TextDirection.rtl, | ||
| 227 | + pageFormat: const PdfPageFormat(150, 150), | ||
| 228 | + build: (Context context) { | ||
| 229 | + return [ | ||
| 230 | + ListView(children: [ | ||
| 231 | + for(int i = 0; i < 30; i++) | ||
| 232 | + Text('Hello World') | ||
| 233 | + ]), | ||
| 234 | + ]; | ||
| 235 | + }, | ||
| 236 | + ), | ||
| 237 | + ); | ||
| 238 | + }); | ||
| 239 | + | ||
| 240 | + test('LTR Multi Page Should render child aligned left', () { | ||
| 241 | + pdf.addPage( | ||
| 242 | + MultiPage( | ||
| 243 | + textDirection: TextDirection.ltr, | ||
| 244 | + pageFormat: const PdfPageFormat(150, 150), | ||
| 245 | + build: (Context context) { | ||
| 246 | + return [ | ||
| 247 | + ListView(children: [ | ||
| 248 | + for(int i = 0; i < 30; i++) | ||
| 249 | + Text('Hello World') | ||
| 250 | + ]), | ||
| 251 | + ]; | ||
| 252 | + }, | ||
| 202 | ), | 253 | ), |
| 254 | + ); | ||
| 255 | + }); | ||
| 256 | + | ||
| 257 | + test('Should render a blue box padded from right', () { | ||
| 258 | + pdf.addPage( | ||
| 259 | + Page( | ||
| 260 | + textDirection: TextDirection.rtl, | ||
| 261 | + pageFormat: const PdfPageFormat(150, 150), | ||
| 262 | + build: (Context context) { | ||
| 263 | + return Padding( | ||
| 264 | + padding: const EdgeInsetsDirectional.only(start: 20), | ||
| 265 | + child: _blueBox, | ||
| 266 | + ); | ||
| 267 | + }, | ||
| 268 | + ), | ||
| 269 | + ); | ||
| 270 | + }); | ||
| 271 | + | ||
| 272 | + test('Should render a blue box padded from left', () { | ||
| 273 | + pdf.addPage( | ||
| 274 | + Page( | ||
| 275 | + textDirection: TextDirection.ltr, | ||
| 276 | + pageFormat: const PdfPageFormat(150, 150), | ||
| 277 | + build: (Context context) { | ||
| 278 | + return Padding( | ||
| 279 | + padding: const EdgeInsetsDirectional.only(start: 20), | ||
| 280 | + child: _blueBox, | ||
| 281 | + ); | ||
| 282 | + }, | ||
| 203 | ), | 283 | ), |
| 204 | ); | 284 | ); |
| 205 | }); | 285 | }); |
-
Please register or login to post a comment