Showing
5 changed files
with
120 additions
and
0 deletions
@@ -9,6 +9,7 @@ | @@ -9,6 +9,7 @@ | ||
9 | - Update Image dependency | 9 | - Update Image dependency |
10 | - Fix lints | 10 | - Fix lints |
11 | - Add options to customise border in Dataset widget [838] | 11 | - Add options to customise border in Dataset widget [838] |
12 | +- Add Choice Field [Carsten Fregin] | ||
12 | 13 | ||
13 | ## 3.8.4 | 14 | ## 3.8.4 |
14 | 15 |
@@ -31,6 +31,73 @@ import 'object.dart'; | @@ -31,6 +31,73 @@ import 'object.dart'; | ||
31 | import 'object_dict.dart'; | 31 | import 'object_dict.dart'; |
32 | import 'page.dart'; | 32 | import 'page.dart'; |
33 | 33 | ||
34 | +class PdfChoiceField extends PdfAnnotWidget { | ||
35 | + PdfChoiceField({ | ||
36 | + required PdfRect rect, | ||
37 | + required this.textColor, | ||
38 | + required this.font, | ||
39 | + required this.fontSize, | ||
40 | + required this.items, | ||
41 | + String? fieldName, | ||
42 | + this.value, | ||
43 | + this.defaultValue, | ||
44 | + }) : super( | ||
45 | + rect: rect, | ||
46 | + fieldType: '/Ch', | ||
47 | + fieldName: fieldName, | ||
48 | + ); | ||
49 | + | ||
50 | + final List<String> items; | ||
51 | + final PdfColor textColor; | ||
52 | + final String? value; | ||
53 | + final String? defaultValue; | ||
54 | + final Set<PdfFieldFlags>? fieldFlags = { | ||
55 | + PdfFieldFlags.combo, | ||
56 | + }; | ||
57 | + final PdfFont font; | ||
58 | + | ||
59 | + final double fontSize; | ||
60 | + @override | ||
61 | + void build(PdfPage page, PdfObject object, PdfDict params) { | ||
62 | + super.build(page, object, params); | ||
63 | + // What is /F? | ||
64 | + //params['/F'] = const PdfNum(4); | ||
65 | + params['/Ff'] = PdfNum(fieldFlagsValue); | ||
66 | + params['/Opt'] = | ||
67 | + PdfArray<PdfString>(items.map((e) => PdfString.fromString(e)).toList()); | ||
68 | + | ||
69 | + if (defaultValue != null) { | ||
70 | + params['/DV'] = PdfString.fromString(defaultValue!); | ||
71 | + } | ||
72 | + | ||
73 | + if (value != null) { | ||
74 | + params['/V'] = PdfString.fromString(value!); | ||
75 | + } else { | ||
76 | + params['/V'] = const PdfNull(); | ||
77 | + } | ||
78 | + | ||
79 | + final buf = PdfStream(); | ||
80 | + final g = PdfGraphics(page, buf); | ||
81 | + g.setFillColor(textColor); | ||
82 | + g.setFont(font, fontSize); | ||
83 | + | ||
84 | + params['/DA'] = PdfSecString.fromStream(object, buf); | ||
85 | + | ||
86 | + // What is /TU? Tooltip? | ||
87 | + //params['/TU'] = PdfString.fromString('Select from list'); | ||
88 | + } | ||
89 | + | ||
90 | + int get fieldFlagsValue { | ||
91 | + if (fieldFlags == null || fieldFlags!.isEmpty) { | ||
92 | + return 0; | ||
93 | + } | ||
94 | + | ||
95 | + return fieldFlags! | ||
96 | + .map<int>((PdfFieldFlags e) => 1 << e.index) | ||
97 | + .reduce((int a, int b) => a | b); | ||
98 | + } | ||
99 | +} | ||
100 | + | ||
34 | class PdfAnnot extends PdfObjectDict { | 101 | class PdfAnnot extends PdfObjectDict { |
35 | PdfAnnot(this.pdfPage, this.annot) | 102 | PdfAnnot(this.pdfPage, this.annot) |
36 | : super(pdfPage.pdfDocument, type: '/Annot') { | 103 | : super(pdfPage.pdfDocument, type: '/Annot') { |
@@ -31,6 +31,46 @@ import 'text_style.dart'; | @@ -31,6 +31,46 @@ import 'text_style.dart'; | ||
31 | import 'theme.dart'; | 31 | import 'theme.dart'; |
32 | import 'widget.dart'; | 32 | import 'widget.dart'; |
33 | 33 | ||
34 | +class ChoiceField extends StatelessWidget { | ||
35 | + ChoiceField({ | ||
36 | + this.width = 120, | ||
37 | + this.height = 13, | ||
38 | + this.textStyle, | ||
39 | + required this.name, | ||
40 | + required this.items, | ||
41 | + this.value, | ||
42 | + }); | ||
43 | + final String name; | ||
44 | + final TextStyle? textStyle; | ||
45 | + final double width; | ||
46 | + final double height; | ||
47 | + final List<String> items; | ||
48 | + final String? value; | ||
49 | + | ||
50 | + @override | ||
51 | + void paint(Context context) { | ||
52 | + super.paint(context); | ||
53 | + final _textStyle = Theme.of(context).defaultTextStyle.merge(textStyle); | ||
54 | + final pdfRect = context.localToGlobal(box!); | ||
55 | + | ||
56 | + final bf = PdfChoiceField( | ||
57 | + textColor: _textStyle.color!, | ||
58 | + fieldName: name, | ||
59 | + value: value, | ||
60 | + font: _textStyle.font!.getFont(context), | ||
61 | + fontSize: _textStyle.fontSize!, | ||
62 | + items: items, | ||
63 | + rect: pdfRect, | ||
64 | + ); | ||
65 | + PdfAnnot(context.page, bf); | ||
66 | + } | ||
67 | + | ||
68 | + @override | ||
69 | + Widget build(Context context) { | ||
70 | + return SizedBox(width: width, height: height); | ||
71 | + } | ||
72 | +} | ||
73 | + | ||
34 | class Checkbox extends SingleChildWidget { | 74 | class Checkbox extends SingleChildWidget { |
35 | Checkbox({ | 75 | Checkbox({ |
36 | required this.value, | 76 | required this.value, |
@@ -98,6 +98,17 @@ void main() { | @@ -98,6 +98,17 @@ void main() { | ||
98 | Decorated(child: TextField(name: 'Address')), | 98 | Decorated(child: TextField(name: 'Address')), |
99 | // | 99 | // |
100 | SizedBox(width: double.infinity, height: 10), | 100 | SizedBox(width: double.infinity, height: 10), |
101 | + Label(label: 'ChoiceField:', width: 100), | ||
102 | + Decorated( | ||
103 | + child: ChoiceField(name: 'Test Choice', items: [ | ||
104 | + 'One', | ||
105 | + 'Two', | ||
106 | + 'Blue', | ||
107 | + 'Yellow', | ||
108 | + 'Test äöüß', | ||
109 | + ])), | ||
110 | + // | ||
111 | + SizedBox(width: double.infinity, height: 10), | ||
101 | // | 112 | // |
102 | Label(label: 'Postcode:', width: 100), | 113 | Label(label: 'Postcode:', width: 100), |
103 | Decorated( | 114 | Decorated( |
@@ -114,6 +125,7 @@ void main() { | @@ -114,6 +125,7 @@ void main() { | ||
114 | name: 'Country', | 125 | name: 'Country', |
115 | color: PdfColors.blue, | 126 | color: PdfColors.blue, |
116 | )), | 127 | )), |
128 | + | ||
117 | // | 129 | // |
118 | SizedBox(width: double.infinity, height: 10), | 130 | SizedBox(width: double.infinity, height: 10), |
119 | // | 131 | // |
No preview for this file type
-
Please register or login to post a comment