001/*
002 * $Id: FieldPositioningEvents.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf.events;
045
046import java.io.IOException;
047import java.util.HashMap;
048
049import com.itextpdf.text.Document;
050import com.itextpdf.text.DocumentException;
051import com.itextpdf.text.ExceptionConverter;
052import com.itextpdf.text.Rectangle;
053import com.itextpdf.text.error_messages.MessageLocalization;
054import com.itextpdf.text.pdf.PdfContentByte;
055import com.itextpdf.text.pdf.PdfFormField;
056import com.itextpdf.text.pdf.PdfName;
057import com.itextpdf.text.pdf.PdfPCell;
058import com.itextpdf.text.pdf.PdfPCellEvent;
059import com.itextpdf.text.pdf.PdfPageEventHelper;
060import com.itextpdf.text.pdf.PdfRectangle;
061import com.itextpdf.text.pdf.PdfWriter;
062import com.itextpdf.text.pdf.TextField;
063
064/**
065 * Class that can be used to position AcroForm fields.
066 */
067public class FieldPositioningEvents extends PdfPageEventHelper implements PdfPCellEvent {
068
069    /**
070     * Keeps a map with fields that are to be positioned in inGenericTag.
071     */
072    protected HashMap<String, PdfFormField> genericChunkFields = new HashMap<String, PdfFormField>();
073
074    /**
075     * Keeps the form field that is to be positioned in a cellLayout event.
076     */
077    protected PdfFormField cellField = null;
078
079    /**
080     * The PdfWriter to use when a field has to added in a cell event.
081     */
082    protected PdfWriter fieldWriter = null;
083    /**
084     * The PdfFormField that is the parent of the field added in a cell event.
085     */
086    protected PdfFormField parent = null;
087
088    /** Creates a new event. This constructor will be used if you need to position fields with Chunk objects. */
089    public FieldPositioningEvents() {}
090
091    /** Some extra padding that will be taken into account when defining the widget. */
092    public float padding;
093
094    /**
095     * Add a PdfFormField that has to be tied to a generic Chunk.
096     */
097    public void addField(String text, PdfFormField field) {
098        genericChunkFields.put(text, field);
099    }
100
101    /** Creates a new event. This constructor will be used if you need to position fields with a Cell Event. */
102    public FieldPositioningEvents(PdfWriter writer, PdfFormField field) {
103        this.cellField = field;
104        this.fieldWriter = writer;
105    }
106
107    /** Creates a new event. This constructor will be used if you need to position fields with a Cell Event. */
108    public FieldPositioningEvents(PdfFormField parent, PdfFormField field) {
109        this.cellField = field;
110        this.parent = parent;
111    }
112
113    /** Creates a new event. This constructor will be used if you need to position fields with a Cell Event.
114     * @throws DocumentException
115     * @throws IOException*/
116    public FieldPositioningEvents(PdfWriter writer, String text) throws IOException, DocumentException {
117        this.fieldWriter = writer;
118        TextField tf = new TextField(writer, new Rectangle(0, 0), text);
119                tf.setFontSize(14);
120                cellField = tf.getTextField();
121        }
122
123    /** Creates a new event. This constructor will be used if you need to position fields with a Cell Event.
124     * @throws DocumentException
125     * @throws IOException*/
126    public FieldPositioningEvents(PdfWriter writer, PdfFormField parent, String text) throws IOException, DocumentException {
127        this.parent = parent;
128        TextField tf = new TextField(writer, new Rectangle(0, 0), text);
129                tf.setFontSize(14);
130                cellField = tf.getTextField();
131        }
132
133        /**
134         * @param padding The padding to set.
135         */
136        public void setPadding(float padding) {
137                this.padding = padding;
138        }
139
140        /**
141         * @param parent The parent to set.
142         */
143        public void setParent(PdfFormField parent) {
144                this.parent = parent;
145        }
146        /**
147         * @see com.itextpdf.text.pdf.PdfPageEvent#onGenericTag(com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document, com.itextpdf.text.Rectangle, java.lang.String)
148         */
149        @Override
150    public void onGenericTag(PdfWriter writer, Document document,
151                        Rectangle rect, String text) {
152                rect.setBottom(rect.getBottom() - 3);
153                PdfFormField field = genericChunkFields.get(text);
154                if (field == null) {
155                        TextField tf = new TextField(writer, new Rectangle(rect.getLeft(padding), rect.getBottom(padding), rect.getRight(padding), rect.getTop(padding)), text);
156                        tf.setFontSize(14);
157                        try {
158                                field = tf.getTextField();
159                        } catch (Exception e) {
160                                throw new ExceptionConverter(e);
161                        }
162                }
163                else {
164                        field.put(PdfName.RECT,  new PdfRectangle(rect.getLeft(padding), rect.getBottom(padding), rect.getRight(padding), rect.getTop(padding)));
165                }
166                if (parent == null)
167                        writer.addAnnotation(field);
168                else
169                        parent.addKid(field);
170        }
171
172        /**
173         * @see com.itextpdf.text.pdf.PdfPCellEvent#cellLayout(com.itextpdf.text.pdf.PdfPCell, com.itextpdf.text.Rectangle, com.itextpdf.text.pdf.PdfContentByte[])
174         */
175        public void cellLayout(PdfPCell cell, Rectangle rect, PdfContentByte[] canvases) {
176                if (cellField == null || fieldWriter == null && parent == null) throw new IllegalArgumentException(MessageLocalization.getComposedMessage("you.have.used.the.wrong.constructor.for.this.fieldpositioningevents.class"));
177                cellField.put(PdfName.RECT, new PdfRectangle(rect.getLeft(padding), rect.getBottom(padding), rect.getRight(padding), rect.getTop(padding)));
178                if (parent == null)
179                        fieldWriter.addAnnotation(cellField);
180                else
181                        parent.addKid(cellField);
182        }
183}