1
49
50 package com.lowagie.text.pdf;
51
52 import java.util.HashMap;
53 import java.util.Iterator;
54
55 import com.lowagie.text.ExceptionConverter;
56 import com.lowagie.text.Rectangle;
57
58
61
62 public class PdfAcroForm extends PdfDictionary {
63
64 private PdfWriter writer;
65
66
67
68 private HashMap fieldTemplates = new HashMap();
69
70
71 private PdfArray documentFields = new PdfArray();
72
73
74 private PdfArray calculationOrder = new PdfArray();
75
76
77 private int sigFlags = 0;
78
79
82 public PdfAcroForm(PdfWriter writer) {
83 super();
84 this.writer = writer;
85 }
86
87 public void setNeedAppearances(boolean value) {
88 put(PdfName.NEEDAPPEARANCES, new PdfBoolean(value));
89 }
90
91
95
96 public void addFieldTemplates(HashMap ft) {
97 fieldTemplates.putAll(ft);
98 }
99
100
104
105 public void addDocumentField(PdfIndirectReference ref) {
106 documentFields.add(ref);
107 }
108
109
113
114 public boolean isValid() {
115 if (documentFields.size() == 0) return false;
116 put(PdfName.FIELDS, documentFields);
117 if (sigFlags != 0)
118 put(PdfName.SIGFLAGS, new PdfNumber(sigFlags));
119 if (calculationOrder.size() > 0)
120 put(PdfName.CO, calculationOrder);
121 if (fieldTemplates.isEmpty()) return true;
122 PdfDictionary dic = new PdfDictionary();
123 for (Iterator it = fieldTemplates.keySet().iterator(); it.hasNext();) {
124 PdfTemplate template = (PdfTemplate)it.next();
125 PdfFormField.mergeResources(dic, (PdfDictionary)template.getResources());
126 }
127 put(PdfName.DR, dic);
128 put(PdfName.DA, new PdfString("/Helv 0 Tf 0 g "));
129 PdfDictionary fonts = (PdfDictionary)dic.get(PdfName.FONT);
130 if (fonts != null) {
131 writer.eliminateFontSubset(fonts);
132 }
133 return true;
134 }
135
136
140
141 public void addCalculationOrder(PdfFormField formField) {
142 calculationOrder.add(formField.getIndirectReference());
143 }
144
145
149
150 public void setSigFlags(int f) {
151 sigFlags |= f;
152 }
153
154
158
159 public void addFormField(PdfFormField formField) {
160 writer.addAnnotation(formField);
161 }
162
163
176 public PdfFormField addHtmlPostButton(String name, String caption, String value, String url, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
177 PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT);
178 PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
179 setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
180 drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
181 addFormField(button);
182 return button;
183 }
184
185
197 public PdfFormField addResetButton(String name, String caption, String value, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
198 PdfAction action = PdfAction.createResetForm(null, 0);
199 PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
200 setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, value);
201 drawButton(button, caption, font, fontSize, llx, lly, urx, ury);
202 addFormField(button);
203 return button;
204 }
205
206
217 public PdfFormField addMap(String name, String value, String url, PdfContentByte appearance, float llx, float lly, float urx, float ury) {
218 PdfAction action = PdfAction.createSubmitForm(url, null, PdfAction.SUBMIT_HTML_FORMAT | PdfAction.SUBMIT_COORDINATES);
219 PdfFormField button = new PdfFormField(writer, llx, lly, urx, ury, action);
220 setButtonParams(button, PdfFormField.FF_PUSHBUTTON, name, null);
221 PdfAppearance pa = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
222 pa.add(appearance);
223 button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
224 addFormField(button);
225 return button;
226 }
227
228
234 public void setButtonParams(PdfFormField button, int characteristics, String name, String value) {
235 button.setButton(characteristics);
236 button.setFlags(PdfAnnotation.FLAGS_PRINT);
237 button.setPage();
238 button.setFieldName(name);
239 if (value != null) button.setValueAsString(value);
240 }
241
242
252 public void drawButton(PdfFormField button, String caption, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
253 PdfAppearance pa = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
254 pa.drawButton(0f, 0f, urx - llx, ury - lly, caption, font, fontSize);
255 button.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, pa);
256 }
257
258
263 public PdfFormField addHiddenField(String name, String value) {
264 PdfFormField hidden = PdfFormField.createEmpty(writer);
265 hidden.setFieldName(name);
266 hidden.setValueAsName(value);
267 addFormField(hidden);
268 return hidden;
269 }
270
271
282 public PdfFormField addSingleLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
283 PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PLAINTEXT, 0);
284 setTextFieldParams(field, text, name, llx, lly, urx, ury);
285 drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
286 addFormField(field);
287 return field;
288 }
289
290
301 public PdfFormField addMultiLineTextField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
302 PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.MULTILINE, PdfFormField.PLAINTEXT, 0);
303 setTextFieldParams(field, text, name, llx, lly, urx, ury);
304 drawMultiLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
305 addFormField(field);
306 return field;
307 }
308
309
320 public PdfFormField addSingleLinePasswordField(String name, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
321 PdfFormField field = PdfFormField.createTextField(writer, PdfFormField.SINGLELINE, PdfFormField.PASSWORD, 0);
322 setTextFieldParams(field, text, name, llx, lly, urx, ury);
323 drawSingleLineOfText(field, text, font, fontSize, llx, lly, urx, ury);
324 addFormField(field);
325 return field;
326 }
327
328
337 public void setTextFieldParams(PdfFormField field, String text, String name, float llx, float lly, float urx, float ury) {
338 field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
339 field.setValueAsString(text);
340 field.setDefaultValueAsString(text);
341 field.setFieldName(name);
342 field.setFlags(PdfAnnotation.FLAGS_PRINT);
343 field.setPage();
344 }
345
346
356 public void drawSingleLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
357 PdfAppearance tp = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
358 PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
359 tp2.setFontAndSize(font, fontSize);
360 tp2.resetRGBColorFill();
361 field.setDefaultAppearanceString(tp2);
362 tp.drawTextField(0f, 0f, urx - llx, ury - lly);
363 tp.beginVariableText();
364 tp.saveState();
365 tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
366 tp.clip();
367 tp.newPath();
368 tp.beginText();
369 tp.setFontAndSize(font, fontSize);
370 tp.resetRGBColorFill();
371 tp.setTextMatrix(4, (ury - lly) / 2 - (fontSize * 0.3f));
372 tp.showText(text);
373 tp.endText();
374 tp.restoreState();
375 tp.endVariableText();
376 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
377 }
378
379
389 public void drawMultiLineOfText(PdfFormField field, String text, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
390 PdfAppearance tp = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
391 PdfAppearance tp2 = (PdfAppearance)tp.getDuplicate();
392 tp2.setFontAndSize(font, fontSize);
393 tp2.resetRGBColorFill();
394 field.setDefaultAppearanceString(tp2);
395 tp.drawTextField(0f, 0f, urx - llx, ury - lly);
396 tp.beginVariableText();
397 tp.saveState();
398 tp.rectangle(3f, 3f, urx - llx - 6f, ury - lly - 6f);
399 tp.clip();
400 tp.newPath();
401 tp.beginText();
402 tp.setFontAndSize(font, fontSize);
403 tp.resetRGBColorFill();
404 tp.setTextMatrix(4, 5);
405 java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(text, "\n");
406 float yPos = ury - lly;
407 while (tokenizer.hasMoreTokens()) {
408 yPos -= fontSize * 1.2f;
409 tp.showTextAligned(PdfContentByte.ALIGN_LEFT, tokenizer.nextToken(), 3, yPos, 0);
410 }
411 tp.endText();
412 tp.restoreState();
413 tp.endVariableText();
414 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
415 }
416
417
427 public PdfFormField addCheckBox(String name, String value, boolean status, float llx, float lly, float urx, float ury) {
428 PdfFormField field = PdfFormField.createCheckBox(writer);
429 setCheckBoxParams(field, name, value, status, llx, lly, urx, ury);
430 drawCheckBoxAppearences(field, value, llx, lly, urx, ury);
431 addFormField(field);
432 return field;
433 }
434
435
445 public void setCheckBoxParams(PdfFormField field, String name, String value, boolean status, float llx, float lly, float urx, float ury) {
446 field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
447 field.setFieldName(name);
448 if (status) {
449 field.setValueAsName(value);
450 field.setAppearanceState(value);
451 }
452 else {
453 field.setValueAsName("Off");
454 field.setAppearanceState("Off");
455 }
456 field.setFlags(PdfAnnotation.FLAGS_PRINT);
457 field.setPage();
458 field.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
459 }
460
461
469 public void drawCheckBoxAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
470 BaseFont font = null;
471 try {
472 font = BaseFont.createFont(BaseFont.ZAPFDINGBATS, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
473 }
474 catch(Exception e) {
475 throw new ExceptionConverter(e);
476 }
477 float size = (ury - lly);
478 PdfAppearance tpOn = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
479 PdfAppearance tp2 = (PdfAppearance)tpOn.getDuplicate();
480 tp2.setFontAndSize(font, size);
481 tp2.resetRGBColorFill();
482 field.setDefaultAppearanceString(tp2);
483 tpOn.drawTextField(0f, 0f, urx - llx, ury - lly);
484 tpOn.saveState();
485 tpOn.resetRGBColorFill();
486 tpOn.beginText();
487 tpOn.setFontAndSize(font, size);
488 tpOn.showTextAligned(PdfContentByte.ALIGN_CENTER, "4", (urx - llx) / 2, (ury - lly) / 2 - (size * 0.3f), 0);
489 tpOn.endText();
490 tpOn.restoreState();
491 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
492 PdfAppearance tpOff = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
493 tpOff.drawTextField(0f, 0f, urx - llx, ury - lly);
494 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
495 }
496
497
503 public PdfFormField getRadioGroup(String name, String defaultValue, boolean noToggleToOff) {
504 PdfFormField radio = PdfFormField.createRadioButton(writer, noToggleToOff);
505 radio.setFieldName(name);
506 radio.setValueAsName(defaultValue);
507 return radio;
508 }
509
510
513 public void addRadioGroup(PdfFormField radiogroup) {
514 addFormField(radiogroup);
515 }
516
517
526 public PdfFormField addRadioButton(PdfFormField radiogroup, String value, float llx, float lly, float urx, float ury) {
527 PdfFormField radio = PdfFormField.createEmpty(writer);
528 radio.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_TOGGLE);
529 String name = ((PdfName)radiogroup.get(PdfName.V)).toString().substring(1);
530 if (name.equals(value)) {
531 radio.setAppearanceState(value);
532 }
533 else {
534 radio.setAppearanceState("Off");
535 }
536 drawRadioAppearences(radio, value, llx, lly, urx, ury);
537 radiogroup.addKid(radio);
538 return radio;
539 }
540
541
549 public void drawRadioAppearences(PdfFormField field, String value, float llx, float lly, float urx, float ury) {
550 PdfAppearance tpOn = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
551 tpOn.drawRadioField(0f, 0f, urx - llx, ury - lly, true);
552 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, value, tpOn);
553 PdfAppearance tpOff = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
554 tpOff.drawRadioField(0f, 0f, urx - llx, ury - lly, false);
555 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", tpOff);
556 }
557
558
570 public PdfFormField addSelectList(String name, String[] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
571 PdfFormField choice = PdfFormField.createList(writer, options, 0);
572 setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
573 StringBuffer text = new StringBuffer();
574 for (int i = 0; i < options.length; i++) {
575 text.append(options[i]).append('\n');
576 }
577 drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
578 addFormField(choice);
579 return choice;
580 }
581
582
594 public PdfFormField addSelectList(String name, String[][] options, String defaultValue, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
595 PdfFormField choice = PdfFormField.createList(writer, options, 0);
596 setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
597 StringBuffer text = new StringBuffer();
598 for (int i = 0; i < options.length; i++) {
599 text.append(options[i][1]).append('\n');
600 }
601 drawMultiLineOfText(choice, text.toString(), font, fontSize, llx, lly, urx, ury);
602 addFormField(choice);
603 return choice;
604 }
605
606
619 public PdfFormField addComboBox(String name, String[] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
620 PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
621 setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
622 if (defaultValue == null) {
623 defaultValue = options[0];
624 }
625 drawSingleLineOfText(choice, defaultValue, font, fontSize, llx, lly, urx, ury);
626 addFormField(choice);
627 return choice;
628 }
629
630
643 public PdfFormField addComboBox(String name, String[][] options, String defaultValue, boolean editable, BaseFont font, float fontSize, float llx, float lly, float urx, float ury) {
644 PdfFormField choice = PdfFormField.createCombo(writer, editable, options, 0);
645 setChoiceParams(choice, name, defaultValue, llx, lly, urx, ury);
646 String value = null;
647 for (int i = 0; i < options.length; i++) {
648 if (options[i][0].equals(defaultValue)) {
649 value = options[i][1];
650 break;
651 }
652 }
653 if (value == null) {
654 value = options[0][1];
655 }
656 drawSingleLineOfText(choice, value, font, fontSize, llx, lly, urx, ury);
657 addFormField(choice);
658 return choice;
659 }
660
661
670 public void setChoiceParams(PdfFormField field, String name, String defaultValue, float llx, float lly, float urx, float ury) {
671 field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
672 if (defaultValue != null) {
673 field.setValueAsString(defaultValue);
674 field.setDefaultValueAsString(defaultValue);
675 }
676 field.setFieldName(name);
677 field.setFlags(PdfAnnotation.FLAGS_PRINT);
678 field.setPage();
679 field.setBorderStyle(new PdfBorderDictionary(2, PdfBorderDictionary.STYLE_SOLID));
680 }
681
682
690 public PdfFormField addSignature(String name,
691 float llx, float lly, float urx, float ury) {
692 PdfFormField signature = PdfFormField.createSignature(writer);
693 setSignatureParams(signature, name, llx, lly, urx, ury);
694 drawSignatureAppearences(signature, llx, lly, urx, ury);
695 addFormField(signature);
696 return signature;
697 }
698
699
707 public void setSignatureParams(PdfFormField field, String name,
708 float llx, float lly, float urx, float ury) {
709 field.setWidget(new Rectangle(llx, lly, urx, ury), PdfAnnotation.HIGHLIGHT_INVERT);
710 field.setFieldName(name);
711 field.setFlags(PdfAnnotation.FLAGS_PRINT);
712 field.setPage();
713 field.setMKBorderColor(java.awt.Color.black);
714 field.setMKBackgroundColor(java.awt.Color.white);
715 }
716
717
724 public void drawSignatureAppearences(PdfFormField field,
725 float llx, float lly, float urx, float ury) {
726 PdfAppearance tp = PdfAppearance.createAppearance(writer, urx - llx, ury - lly);
727 tp.setGrayFill(1.0f);
728 tp.rectangle(0, 0, urx - llx, ury - lly);
729 tp.fill();
730 tp.setGrayStroke(0);
731 tp.setLineWidth(1);
732 tp.rectangle(0.5f, 0.5f, urx - llx - 0.5f, ury - lly - 0.5f);
733 tp.closePathStroke();
734 tp.saveState();
735 tp.rectangle(1, 1, urx - llx - 2, ury - lly - 2);
736 tp.clip();
737 tp.newPath();
738 tp.restoreState();
739 field.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, tp);
740 }
741 }