David PHAM-VAN

Update Web example

@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 2
3 ## 1.3.24 3 ## 1.3.24
4 4
  5 +- Update Web example
5 - Add more color functions 6 - Add more color functions
6 - Fix Pdf format 7 - Fix Pdf format
7 - Fix warning in tests 8 - Fix warning in tests
@@ -8,6 +8,7 @@ environment: @@ -8,6 +8,7 @@ environment:
8 8
9 dependencies: 9 dependencies:
10 pdf: 10 pdf:
  11 + intl:
11 12
12 dependency_overrides: 13 dependency_overrides:
13 pdf: 14 pdf:
  1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +import 'package:intl/intl.dart';
  18 +import 'package:pdf/pdf.dart';
  19 +import 'package:pdf/widgets.dart';
  20 +
  21 +class Calendar extends StatelessWidget {
  22 + Calendar({
  23 + this.date,
  24 + this.month,
  25 + this.year,
  26 + });
  27 +
  28 + final DateTime date;
  29 +
  30 + final int month;
  31 +
  32 + final int year;
  33 +
  34 + Widget title(
  35 + Context context,
  36 + DateTime date,
  37 + ) {
  38 + return Container(
  39 + width: double.infinity,
  40 + child: Text(
  41 + DateFormat.yMMMM().format(date),
  42 + style: const TextStyle(
  43 + color: PdfColors.deepPurple,
  44 + fontSize: 40,
  45 + ),
  46 + ),
  47 + );
  48 + }
  49 +
  50 + Widget header(
  51 + Context context,
  52 + DateTime date,
  53 + ) {
  54 + return Container(
  55 + color: PdfColors.blue200,
  56 + padding: const EdgeInsets.all(8.0),
  57 + child: Text(
  58 + DateFormat.EEEE().format(date),
  59 + style: const TextStyle(
  60 + fontSize: 15,
  61 + ),
  62 + ),
  63 + );
  64 + }
  65 +
  66 + Widget day(
  67 + Context context,
  68 + DateTime date,
  69 + bool currentMonth,
  70 + bool currentDay,
  71 + ) {
  72 + String text = '${date.day}';
  73 + TextStyle style = const TextStyle();
  74 + PdfColor color = PdfColors.grey300;
  75 +
  76 + if (currentDay) {
  77 + style = TextStyle(color: PdfColors.red);
  78 + color = PdfColors.lightBlue50;
  79 + }
  80 +
  81 + if (!currentMonth) {
  82 + style = TextStyle(color: PdfColors.grey);
  83 + color = PdfColors.grey100;
  84 + }
  85 +
  86 + if (date.day == 1) {
  87 + text += ' ' + DateFormat.MMM().format(date);
  88 + }
  89 +
  90 + return Container(
  91 + padding: const EdgeInsets.all(4),
  92 + color: color,
  93 + child: Text(
  94 + text,
  95 + textAlign: TextAlign.right,
  96 + style: style,
  97 + ),
  98 + );
  99 + }
  100 +
  101 + @override
  102 + Widget build(Context context) {
  103 + final DateTime _date = date ?? DateTime.now();
  104 + final int _year = year ?? _date.year;
  105 + final int _month = month ?? _date.month;
  106 +
  107 + final DateTime start = DateTime(_year, _month, 1, 12);
  108 + final DateTime end = DateTime(_year, _month + 1, 1, 12).subtract(
  109 + const Duration(days: 1),
  110 + );
  111 +
  112 + final int startId = start.weekday - 1;
  113 + final int endId = end.difference(start).inDays + startId + 1;
  114 +
  115 + final Row head = Row(
  116 + mainAxisSize: MainAxisSize.max,
  117 + children: List<Widget>.generate(7, (int index) {
  118 + final DateTime d = start.add(Duration(days: index - startId));
  119 + return Expanded(
  120 + child: Container(
  121 + foregroundDecoration: BoxDecoration(
  122 + border: BoxBorder(
  123 + color: PdfColors.black,
  124 + top: true,
  125 + left: true,
  126 + right: index % 7 == 6,
  127 + bottom: true,
  128 + ),
  129 + ),
  130 + child: header(context, d),
  131 + ),
  132 + );
  133 + }),
  134 + );
  135 +
  136 + final GridView body = GridView(
  137 + crossAxisCount: 7,
  138 + children: List<Widget>.generate(42, (int index) {
  139 + final DateTime d = start.add(Duration(days: index - startId));
  140 + final bool currentMonth = index >= startId && index < endId;
  141 + final bool currentDay = d.year == _date.year &&
  142 + d.month == _date.month &&
  143 + d.day == _date.day;
  144 + return Container(
  145 + foregroundDecoration: BoxDecoration(
  146 + border: BoxBorder(
  147 + color: PdfColors.black,
  148 + left: true,
  149 + right: index % 7 == 6,
  150 + bottom: true,
  151 + ),
  152 + ),
  153 + child: day(context, d, currentMonth, currentDay),
  154 + );
  155 + }),
  156 + );
  157 +
  158 + return Container(
  159 + padding: const EdgeInsets.all(20),
  160 + child: Column(
  161 + mainAxisAlignment: MainAxisAlignment.start,
  162 + mainAxisSize: MainAxisSize.min,
  163 + children: <Widget>[
  164 + title(context, DateTime(_year, _month)),
  165 + head,
  166 + Flexible(flex: 1, child: body),
  167 + ],
  168 + ),
  169 + );
  170 + }
  171 +}
@@ -8,17 +8,87 @@ @@ -8,17 +8,87 @@
8 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 8 <meta name="viewport" content="width=device-width, initial-scale=1.0">
9 <title>Pdf Web Example</title> 9 <title>Pdf Web Example</title>
10 <link rel="stylesheet" href="styles.css"> 10 <link rel="stylesheet" href="styles.css">
11 - <script defer src="main.dart.js"></script> 11 + <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.3.200/pdf.min.js"></script>
  12 + <script src="main.dart.js"></script>
  13 + <script>
  14 + async function displayPdf(pdf) {
  15 + let doc = await pdfjsLib.getDocument(pdf).promise;
  16 + document.getElementById('page_count').innerText = doc.numPages;
  17 + let metadata = await doc.getMetadata();
  18 + let title = metadata.info.Title || 'Untitled';
  19 + document.getElementById('title').innerText = title;
  20 + document.title = title;
  21 +
  22 + let author = metadata.info.Author || '';
  23 + let producer = metadata.info.Producer || '';
  24 + document.getElementById('author').innerText = author + ' | ' + producer;
  25 +
  26 + let currentPage = 1;
  27 +
  28 + document.getElementById('prev').addEventListener('click', () => {
  29 + if (currentPage <= 1) {
  30 + return;
  31 + }
  32 + currentPage--;
  33 + renderPage(doc, currentPage);
  34 + });
  35 +
  36 + document.getElementById('next').addEventListener('click', () => {
  37 + if (currentPage >= doc.numPages) {
  38 + return;
  39 + }
  40 + currentPage++;
  41 + renderPage(doc, currentPage);
  42 + });
  43 +
  44 + renderPage(doc, currentPage);
  45 + }
  46 +
  47 + async function renderPage(doc, pageNum) {
  48 + document.getElementById('page_num').innerText = pageNum;
  49 +
  50 + let page = await doc.getPage(pageNum);
  51 + let viewport = page.getViewport({ scale: 1 });
  52 + let canvas = document.getElementById('container');
  53 + canvas.width = viewport.width;
  54 + canvas.height = viewport.height;
  55 +
  56 + let renderContext = {
  57 + canvasContext: canvas.getContext('2d'),
  58 + viewport: viewport
  59 + };
  60 +
  61 + await page.render(renderContext).promise;
  62 +
  63 + document.getElementById('toolbar-loading').style.display = 'none';
  64 + document.getElementById('toolbar-content').style.display = '';
  65 + document.getElementById('container').style.display = '';
  66 + document.getElementById('author').style.display = '';
  67 + }
  68 +
  69 + function ready() {
  70 + // Dart is fully loaded
  71 + let pdf = buildPdf();
  72 + displayPdf(pdf);
  73 + };
  74 + </script>
12 </head> 75 </head>
13 76
14 <body> 77 <body>
15 - <div>  
16 - <button id="generate">Generate</button> 78 + <div class="toolbar">
  79 + <div id="toolbar-loading">Loading ...</div>
  80 + <div id="toolbar-content" style="display:none;">
  81 + <button id="prev">Previous</button>
  82 + <button id="next">Next</button>
  83 + &nbsp; &nbsp;
  84 + <span>Page: <span id="page_num"></span> / <span id="page_count"></span></span>
  85 + <span id="title"></span>
  86 + </div>
17 </div> 87 </div>
18 88
19 - <div id="container">  
20 - <object id="doc" type="application/pdf"></object>  
21 - </div> 89 +
  90 + <canvas id="container" style="display:none;"></canvas>
  91 + <div id="author" style="display:none;"></div>
22 </body> 92 </body>
23 93
24 </html> 94 </html>
1 -import 'dart:convert'; 1 +/*
  2 + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +import 'dart:async';
2 import 'dart:html'; 18 import 'dart:html';
  19 +import 'dart:js' as js;
  20 +import 'dart:typed_data';
3 21
4 import 'package:pdf/pdf.dart'; 22 import 'package:pdf/pdf.dart';
5 import 'package:pdf/widgets.dart'; 23 import 'package:pdf/widgets.dart';
6 24
7 -void main() {  
8 - final ButtonElement generateButton = querySelector('#generate');  
9 -  
10 - generateButton.onClick.listen((_) async {  
11 - final String data = Uri.encodeComponent(base64.encode(buildPdf())); 25 +import 'calendar.dart';
12 26
13 - final ObjectElement doc = querySelector('#doc');  
14 - doc.data = 'data:application/pdf;base64,$data';  
15 - });  
16 -} 27 +Uint8List buildPdf() {
  28 + final Document pdf = Document(title: 'My Document', author: 'David PHAM-VAN');
17 29
18 -List<int> buildPdf() {  
19 - final Document pdf = Document();  
20 -  
21 - pdf.addPage(Page(build: (Context ctx) {  
22 - return Container(  
23 - width: double.infinity,  
24 - height: double.infinity,  
25 - child: FittedBox(  
26 - child: Text(  
27 - 'Hello!',  
28 - style: TextStyle(color: PdfColors.blueGrey), 30 + pdf.addPage(Page(
  31 + build: (Context ctx) {
  32 + return Container(
  33 + width: double.infinity,
  34 + height: double.infinity,
  35 + child: FittedBox(
  36 + child: Text(
  37 + 'Hello!',
  38 + style: TextStyle(color: PdfColors.blueGrey),
  39 + ),
29 ), 40 ),
30 - ),  
31 - );  
32 - })); 41 + );
  42 + },
  43 + ));
  44 +
  45 + pdf.addPage(Page(
  46 + pageFormat: PdfPageFormat.a4.landscape,
  47 + build: (Context context) => Calendar(),
  48 + ));
33 49
34 - return pdf.save(); 50 + pdf.addPage(Page(
  51 + pageFormat: PdfPageFormat.a4.landscape,
  52 + build: (Context context) => Calendar(
  53 + month: DateTime.now().month + 1,
  54 + ),
  55 + ));
  56 +
  57 + pdf.addPage(Page(
  58 + build: (Context ctx) {
  59 + return Center(child: PdfLogo());
  60 + },
  61 + ));
  62 +
  63 + return Uint8List.fromList(pdf.save());
  64 +}
  65 +
  66 +void main() {
  67 + js.context['buildPdf'] = buildPdf;
  68 + Timer.run(() {
  69 + js.context.callMethod('ready');
  70 + });
35 } 71 }
@@ -10,18 +10,44 @@ body { @@ -10,18 +10,44 @@ body {
10 } 10 }
11 11
12 #container { 12 #container {
13 - left: 10px;  
14 - right: 10px;  
15 - width: auto;  
16 - bottom: 10px;  
17 - top: 49px;  
18 - display: block;  
19 - position: absolute;  
20 - border: 1px dotted red; 13 + border: 1px solid rgb(37, 37, 37);
  14 + box-shadow: 3px 3px 5px rgb(129, 129, 129);
  15 + margin: 20px;
21 } 16 }
22 17
23 -#doc {  
24 - width: 100%;  
25 - height: 100%;  
26 - display: block; 18 +.toolbar {
  19 + background-color: rgb(82, 82, 82);
  20 + padding: 10px;
  21 + color: #fff;
  22 +}
  23 +
  24 +button {
  25 + height: 50px;
  26 + width: 100px;
  27 + background-color: #5cb8ff;
  28 + border: 1px solid #4f90ff;
  29 + display: inline-block;
  30 + cursor: pointer;
  31 + color: #ffffff;
  32 + font-size: 17px;
  33 +}
  34 +
  35 +button:hover {
  36 + background-color: #2688ff;
  37 +}
  38 +
  39 +button:active {
  40 + background-color: #1a64be;
  41 +}
  42 +
  43 +#title {
  44 + margin-left: 2rem;
  45 + font-size: 1.8em;
  46 +}
  47 +
  48 +#author {
  49 + margin-left: 20px;
  50 + margin-bottom: 20px;
  51 + color: rgb(65, 72, 77);
  52 + font-size: 0.7em;
27 } 53 }