I have been following the 'Chapter 8: Filling out interactive forms' iText example (code and pdfs at http://itextpdf.com/examples/iia.php?id=154) and have noticed a number of appearance-related issues which also manifest themselves in the example pdfs.
The example features a list of radio buttons (classic dot within a circle) and a list of checkboxes (crossed box with a red background). So far so good. However the pdf generated after programmatically filling in these fields is visually inconsistent. The radio buttons have all reverted to squares and the selected ('Spanish') has a wingdings (?) cross within it rather than a dot. The fields are all still editable. When I select a different radio button, the previously selected radio button reverts to an empty circle. The newly selected field has changed from an empty square to a dotted circle. This can also be observed with the checkboxes.
Is there any way to fill the fields whilst preserving their original appearances?
Thanks!
EDIT - Here's a simplification of the code I use :
public void buildPdf() throws Exception {
Document document = new Document(PageSize.A4);
File file = new File("/test.pdf");
final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
PdfPCell cell = new PdfPCell();
PdfRadioGroupTable group = new PdfRadioGroupTable("ndna", Arrays.asList("Not Available", "Not Applicable"), writer, Locale.ENGLISH, DEFAULT);
cell.addElement(group);
PdfPTable table = new PdfPTable(1);
table.addCell(cell);
cell = new PdfPCell();
cell.setCellEvent(new ActionEvent(writer, "http://localhost:8080/entrypointpdf"));
table.addCell(cell);
document.add(table);
group.addAnnotations();
document.close();
}
Here's the ActionEvent
class ActionEvent implements PdfPCellEvent {
private PdfWriter writer;
private String submissionUrl;
public ActionEvent(PdfWriter writer, String submissionUrl) {
this.writer = writer;
this.submissionUrl = submissionUrl;
}
@Override
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
PushbuttonField submit = new PushbuttonField(writer, position, "submit") {
@Override
public PdfFormField getField() throws IOException, DocumentException {
PdfFormField field = super.getField();
field.setAction(PdfAction.createSubmitForm(submissionUrl, null, 0));
return field;
}
};
submit.setText("CLICK ME");
submit.setTextColor(BaseColor.BLUE);
submit.setFont(DEFAULT.getCalculatedBaseFont(false));
submit.setVisibility(PushbuttonField.VISIBLE);
try {
writer.addAnnotation(submit.getField());
} catch (Exception ignore) {
}
}
}
Here's the PdfRadioGroupTable
public class PdfRadioGroupTable extends PdfPTable {
private PdfWriter writer;
public PdfFormField radioGroup;
public PdfRadioGroupTable(String name, List<String> choices, PdfWriter writer, Locale locale, Font font) {
super(2);
this.writer = writer;
setWidthPercentage(100);
try {
setTotalWidth(new float[] { 14, 400 });
} catch (DocumentException ignore) {
}
radioGroup = PdfFormField.createRadioButton(writer, true);
radioGroup.setFieldName(name);
PdfPCell cell;
for (String choice : choices) {
cell = new PdfPCell();
cell.setBorder(0);
cell.setPaddingBottom(5);
cell.setUseAscender(true);
cell.setUseDescender(true);
cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
cell.setCellEvent(new RadioCellEvent(radioGroup, choice));
addCell(cell);
cell = new PdfPCell();
cell.setBorder(0);
cell.setPaddingBottom(5);
cell.setPaddingLeft(6);
cell.setUseAscender(true);
cell.setUseDescender(true);
cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
cell.addElement(new Phrase(choice), font));
addCell(cell);
}
}
class RadioCellEvent implements PdfPCellEvent {
protected PdfFormField radioGroup;
protected String value;
public RadioCellEvent(PdfFormField radioGroup, String value) {
this.radioGroup = radioGroup;
this.value = value;
}
@Override
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases) {
RadioCheckField radio = new RadioCheckField(writer, position, null, value);
radio.setChecked(false);
radio.setBorderColor(GrayColor.GRAYBLACK);
radio.setBackgroundColor(GrayColor.GRAYWHITE);
radio.setCheckType(RadioCheckField.TYPE_CIRCLE);
try {
PdfFormField field = radio.getRadioField();
writer.addAnnotation(field);
radioGroup.addKid(field);
} catch (Exception exception) {
throw new ExceptionConverter(exception);
}
}
}
}
And here's what happens on the server side when one clicks the button in the pdf (in acrobat) :
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=\"your.pdf\"");
try {
FdfReader fdf = new FdfReader(request.getInputStream());
File pdfFile = new File("/test.pdf");
InputStream is = new FileInputStream(pdfFile);
PdfReader reader = new PdfReader(is);
File resultFile = new File(System.currentTimeMillis() + "_" + pdfFile.getName());
FileOutputStream out = new FileOutputStream(resultFile);
PdfStamper stamper = new PdfStamper(reader, out);
AcroFields fields = stamper.getAcroFields();
fields.setFields(fdf);
// EXTRACT VALUES HERE
stamper.setFormFlattening(true);
stamper.close();
reader.close();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(FilesUtilities.read(resultFile));
OutputStream os = response.getOutputStream();
bos.writeTo(os);
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
So basically I generate a pdf with one radiogroup and a button. The button results in the pdf fields being imported and the idea is to send a 'receipt' back to the user in the form of the previously generated pdf containing the same fields with the user selection/values and import status fields (ok, missing, bad data, etc.) (which I have omitted in the above code as that part works fine). My problem is that the radio fields in the returned pdf don't look remotely like the editable ones in the original pdf (they don't even look like radio buttons anymore).
I tried using
fields.setFieldProperty("ndna", "setfflags", PdfFormField.FF_READ_ONLY, null);
and disabling form flattening by this results in the same alternate appearance in the returned pdf.
Your help would be most appreciated as I've been struggling with this for a while now...
Anthony