David PHAM-VAN

Add Page.orientation to force landscape or portrait

# 1.3.4
* Add available dimensions for PdfPageFormat
* Add Document properties
* Add Page.orientation to force landscape or portrait
# 1.3.3
* Fix a bug with the RichText Widget
... ...
... ... @@ -16,15 +16,6 @@
part of widget;
abstract class BasePage {
BasePage({@required this.pageFormat}) : assert(pageFormat != null);
final PdfPageFormat pageFormat;
@protected
void generate(Document document);
}
class Document {
Document(
{PdfPageMode pageMode = PdfPageMode.none,
... ... @@ -52,7 +43,7 @@ class Document {
final Theme theme;
void addPage(BasePage page) {
void addPage(Page page) {
page.generate(this);
}
... ... @@ -62,44 +53,83 @@ class Document {
typedef BuildCallback = Widget Function(Context context);
typedef BuildListCallback = List<Widget> Function(Context context);
class Page extends BasePage {
Page(
{PdfPageFormat pageFormat = PdfPageFormat.standard,
enum PageOrientation { natural, landscape, portrait }
class Page {
const Page(
{this.pageFormat = PdfPageFormat.standard,
BuildCallback build,
this.theme,
this.orientation = PageOrientation.natural,
EdgeInsets margin})
: margin = margin ??
EdgeInsets.fromLTRB(pageFormat.marginLeft, pageFormat.marginTop,
pageFormat.marginRight, pageFormat.marginBottom),
_build = build,
super(pageFormat: pageFormat);
: assert(pageFormat != null),
_margin = margin,
_build = build;
final PdfPageFormat pageFormat;
final PageOrientation orientation;
final EdgeInsets margin;
final EdgeInsets _margin;
final BuildCallback _build;
final Theme theme;
bool get mustRotate =>
(orientation == PageOrientation.landscape &&
pageFormat.height > pageFormat.width) ||
(orientation == PageOrientation.portrait &&
pageFormat.width > pageFormat.height);
EdgeInsets get margin {
if (_margin != null) {
if (mustRotate) {
return EdgeInsets.fromLTRB(
_margin.bottom, _margin.left, _margin.top, _margin.right);
} else {
return _margin;
}
}
if (mustRotate) {
return EdgeInsets.fromLTRB(pageFormat.marginBottom, pageFormat.marginLeft,
pageFormat.marginTop, pageFormat.marginRight);
} else {
return EdgeInsets.fromLTRB(pageFormat.marginLeft, pageFormat.marginTop,
pageFormat.marginRight, pageFormat.marginBottom);
}
}
@protected
void debugPaint(Context context) {
final EdgeInsets _margin = margin;
context.canvas
..setFillColor(PdfColor.lightGreen)
..moveTo(0, 0)
..lineTo(pageFormat.width, 0)
..lineTo(pageFormat.width, pageFormat.height)
..lineTo(0, pageFormat.height)
..moveTo(margin.left, margin.bottom)
..lineTo(margin.left, pageFormat.height - margin.top)
..lineTo(pageFormat.width - margin.right, pageFormat.height - margin.top)
..lineTo(pageFormat.width - margin.right, margin.bottom)
..moveTo(_margin.left, _margin.bottom)
..lineTo(_margin.left, pageFormat.height - _margin.top)
..lineTo(
pageFormat.width - _margin.right, pageFormat.height - _margin.top)
..lineTo(pageFormat.width - _margin.right, _margin.bottom)
..fillPath();
}
@override
@protected
void generate(Document document) {
final PdfPage pdfPage = PdfPage(document.document, pageFormat: pageFormat);
final PdfGraphics canvas = pdfPage.getGraphics();
final BoxConstraints constraints = BoxConstraints(
maxWidth: pageFormat.width, maxHeight: pageFormat.height);
final EdgeInsets _margin = margin;
final BoxConstraints constraints = mustRotate
? BoxConstraints(
maxWidth: pageFormat.height - _margin.vertical,
maxHeight: pageFormat.width - _margin.horizontal)
: BoxConstraints(
maxWidth: pageFormat.width - _margin.horizontal,
maxHeight: pageFormat.height - _margin.vertical);
final Theme calculatedTheme = theme ?? document.theme ?? Theme.base();
final Map<Type, Inherited> inherited = <Type, Inherited>{};
... ... @@ -120,19 +150,11 @@ class Page extends BasePage {
void layout(Widget child, Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
if (child != null) {
final BoxConstraints childConstraints = BoxConstraints(
minWidth: constraints.minWidth,
minHeight: constraints.minHeight,
maxWidth: constraints.hasBoundedWidth
? constraints.maxWidth - margin.horizontal
: margin.horizontal,
maxHeight: constraints.hasBoundedHeight
? constraints.maxHeight - margin.vertical
: margin.vertical);
child.layout(context, childConstraints, parentUsesSize: parentUsesSize);
final EdgeInsets _margin = margin;
child.layout(context, constraints, parentUsesSize: parentUsesSize);
child.box = PdfRect(
margin.left,
pageFormat.height - child.box.height - margin.top,
_margin.left,
pageFormat.height - child.box.height - _margin.top,
child.box.width,
child.box.height);
}
... ... @@ -147,23 +169,44 @@ class Page extends BasePage {
return true;
}());
if (child != null) {
if (child == null) {
return;
}
if (mustRotate) {
final EdgeInsets _margin = margin;
final Matrix4 mat = Matrix4.identity();
mat
..rotateZ(-math.pi / 2)
..translate(-pageFormat.height - _margin.left + _margin.top,
child.box.height - child.box.width + _margin.left - _margin.bottom);
context.canvas
..saveContext()
..setTransform(mat);
child.paint(context);
context.canvas.restoreContext();
} else {
child.paint(context);
}
}
}
class MultiPage extends Page {
MultiPage(
const MultiPage(
{PdfPageFormat pageFormat = PdfPageFormat.a4,
BuildListCallback build,
this.crossAxisAlignment = CrossAxisAlignment.start,
this.header,
this.footer,
Theme theme,
PageOrientation orientation = PageOrientation.natural,
EdgeInsets margin})
: _buildList = build,
super(pageFormat: pageFormat, margin: margin, theme: theme);
super(
pageFormat: pageFormat,
margin: margin,
theme: theme,
orientation: orientation);
final BuildListCallback _buildList;
... ... @@ -173,16 +216,40 @@ class MultiPage extends Page {
final BuildCallback footer;
void paintChild(
Context context, Widget child, double x, double y, double pageHeight) {
if (mustRotate) {
final EdgeInsets _margin = margin;
context.canvas
..saveContext()
..setTransform(Matrix4.identity()
..rotateZ(-math.pi / 2)
..translate(x - pageHeight + _margin.top - _margin.left,
y + _margin.left - _margin.bottom));
child.paint(context);
context.canvas.restoreContext();
} else {
child.box = PdfRect(x, y, child.box.width, child.box.height);
child.paint(context);
}
}
@override
void generate(Document document) {
if (_buildList == null) {
return;
}
final EdgeInsets _margin = margin;
final bool _mustRotate = mustRotate;
final double pageHeight =
_mustRotate ? pageFormat.width : pageFormat.height;
final double pageHeightMargin =
_mustRotate ? _margin.horizontal : _margin.vertical;
final BoxConstraints constraints = BoxConstraints(
maxWidth: pageFormat.width, maxHeight: pageFormat.height);
final BoxConstraints childConstraints =
BoxConstraints(maxWidth: constraints.maxWidth - margin.horizontal);
maxWidth: _mustRotate
? (pageFormat.height - _margin.vertical)
: (pageFormat.width - _margin.horizontal));
final Theme calculatedTheme = theme ?? document.theme ?? Theme.base();
final Map<Type, Inherited> inherited = <Type, Inherited>{};
inherited[calculatedTheme.runtimeType] = calculatedTheme;
... ... @@ -209,19 +276,16 @@ class MultiPage extends Page {
}
return true;
}());
offsetStart = pageFormat.height - margin.top;
offsetEnd = margin.bottom;
offsetStart = pageHeight -
(_mustRotate ? pageHeightMargin - margin.bottom : _margin.top);
offsetEnd =
_mustRotate ? pageHeightMargin - _margin.left : _margin.bottom;
if (header != null) {
final Widget headerWidget = header(context);
if (headerWidget != null) {
headerWidget.layout(context, childConstraints,
parentUsesSize: false);
headerWidget.box = PdfRect(
margin.left,
offsetStart - headerWidget.box.height,
headerWidget.box.width,
headerWidget.box.height);
headerWidget.paint(context);
headerWidget.layout(context, constraints, parentUsesSize: false);
paintChild(context, headerWidget, _margin.left,
offsetStart - headerWidget.box.height, pageFormat.height);
offsetStart -= headerWidget.box.height;
}
}
... ... @@ -229,11 +293,9 @@ class MultiPage extends Page {
if (footer != null) {
final Widget footerWidget = footer(context);
if (footerWidget != null) {
footerWidget.layout(context, childConstraints,
parentUsesSize: false);
footerWidget.box = PdfRect(margin.left, margin.bottom,
footerWidget.box.width, footerWidget.box.height);
footerWidget.paint(context);
footerWidget.layout(context, constraints, parentUsesSize: false);
paintChild(context, footerWidget, _margin.left, _margin.bottom,
pageFormat.height);
offsetEnd += footerWidget.box.height;
}
}
... ... @@ -244,10 +306,11 @@ class MultiPage extends Page {
widgetContext = null;
}
child.layout(context, childConstraints, parentUsesSize: false);
child.layout(context, constraints, parentUsesSize: false);
if (offsetStart - child.box.height < offsetEnd) {
if (child.box.height <= pageFormat.height - margin.vertical) {
if (child.box.height <= pageHeight - pageHeightMargin &&
!(child is SpanningWidget)) {
context = null;
continue;
}
... ... @@ -255,18 +318,17 @@ class MultiPage extends Page {
if (!(child is SpanningWidget)) {
throw Exception(
'Widget won\'t fit into the page as its height (${child.box.height}) '
'exceed a page height (${pageFormat.height - margin.vertical}). '
'exceed a page height (${pageHeight - pageHeightMargin}). '
'You probably need a SpanningWidget or use a single page layout');
}
final SpanningWidget span = child;
child.layout(context,
childConstraints.copyWith(maxHeight: offsetStart - offsetEnd),
child.layout(
context, constraints.copyWith(maxHeight: offsetStart - offsetEnd),
parentUsesSize: false);
child.box = PdfRect(margin.left, offsetStart - child.box.height,
child.box.width, child.box.height);
child.paint(context);
paintChild(context, child, _margin.left, offsetStart - child.box.height,
pageFormat.height);
if (span.canSpan) {
widgetContext = span.saveContext();
... ... @@ -278,9 +340,8 @@ class MultiPage extends Page {
continue;
}
child.box = PdfRect(margin.left, offsetStart - child.box.height,
child.box.width, child.box.height);
child.paint(context);
paintChild(context, child, _margin.left, offsetStart - child.box.height,
pageFormat.height);
offsetStart -= child.box.height;
index++;
}
... ...
... ... @@ -266,6 +266,9 @@ class EdgeInsets {
bottom + other.bottom,
);
}
@override
String toString() => 'EdgeInsets $left, $top, $right, $bottom';
}
class Alignment {
... ...