com.vectorprint.report.itext.style.stylers.AbstractFieldStyler.java Source code

Java tutorial

Introduction

Here is the source code for com.vectorprint.report.itext.style.stylers.AbstractFieldStyler.java

Source

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.vectorprint.report.itext.style.stylers;

/*
 * #%L
 * VectorPrintReport4.0
 * %%
 * Copyright (C) 2012 - 2013 VectorPrint
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseField;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfFormField;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPCellEvent;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PushbuttonField;
import com.itextpdf.text.pdf.RadioCheckField;
import com.itextpdf.text.pdf.TextField;
import com.vectorprint.VectorPrintException;
import com.vectorprint.VectorPrintRuntimeException;
import com.vectorprint.configuration.parameters.StringArrayParameter;
import com.vectorprint.configuration.parameters.StringParameter;
import com.vectorprint.configuration.parameters.URLParameter;
import static com.vectorprint.report.ReportConstants.DEBUG;
import com.vectorprint.report.itext.ElementProducer;
import com.vectorprint.report.itext.debug.DebugHelper;
import com.vectorprint.report.itext.debug.DebuggablePdfPCell;
import com.vectorprint.report.itext.style.BaseStyler;
import com.vectorprint.report.itext.style.ElementProducing;
import com.vectorprint.report.itext.style.FormFieldStyler;
import com.vectorprint.report.itext.style.StyleHelper;
import com.vectorprint.report.itext.style.StylerFactory;
import com.vectorprint.report.itext.style.parameters.FieldTypeParameter;
import com.vectorprint.report.itext.style.parameters.FloatParameter;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Base class for drawing form fields on the canvas of a cell.
 *
 * @author Eduard Drenth at VectorPrint.nl
 */
public abstract class AbstractFieldStyler extends AbstractPositioning<Object>
        implements FormFieldStyler, ElementProducing {

    public static final String FIELDTYPE_PARAM = "fieldtype";
    public static final String NAME_PARAM = "name";
    public static final String VALUES_PARAM = "values";
    private ElementProducer elementProducer;
    private StylerFactory stylerFactory;
    private BaseField bf = null;

    public AbstractFieldStyler() {
        addParameter(new FieldTypeParameter(FIELDTYPE_PARAM, Arrays.asList(FIELDTYPE.values()).toString())
                .setDefault(FIELDTYPE.TEXT), AbstractFieldStyler.class);
        addParameter(new FloatParameter(DocumentSettings.HEIGHT, "the height of the field"),
                AbstractFieldStyler.class);
        addParameter(new FloatParameter(DocumentSettings.WIDTH, "the width of the field"),
                AbstractFieldStyler.class);
        addParameter(new StringArrayParameter(VALUES_PARAM, "the value(s) for the form field"),
                AbstractFieldStyler.class);
        addParameter(new StringParameter(NAME_PARAM, "the name of the form field"), AbstractFieldStyler.class);
        addParameter(new URLParameter(Image.URLPARAM, "the url for posting"), AbstractFieldStyler.class);
        getParameter(USEPADDING, Boolean.class).setDefault(Boolean.TRUE);
    }

    private static final Class<Object>[] classes = new Class[] { PdfPCell.class };
    private static final Set<Class> c = Collections.unmodifiableSet(new HashSet<Class>(Arrays.asList(classes)));

    @Override
    public Set<Class> getSupportedClasses() {
        return c;
    }

    @Override
    public String getHelp() {
        return "determines type of field, dimensions and value(s)." + " " + super.getHelp();
    }

    @Override
    public FIELDTYPE getFieldtype() {
        return getValue(FIELDTYPE_PARAM, FIELDTYPE.class);
    }

    public void setFieldtype(FIELDTYPE fieldtype) {
        setValue(FIELDTYPE_PARAM, fieldtype);
    }

    public String getName() {
        return getValue(NAME_PARAM, String.class);
    }

    public void setName(String name) {
        setValue(NAME_PARAM, name);
    }

    public float getHeight() {
        return getValue(DocumentSettings.HEIGHT, Float.class);
    }

    public void setHeight(float height) {
        setValue(DocumentSettings.HEIGHT, height);
    }

    /**
     * creates the correct BaseField based on the {@link FIELDTYPE} of this styler.
     *
     * @return
     * @throws VectorPrintException
     */
    @Override
    public BaseField create() throws VectorPrintException {
        switch (getFieldtype()) {
        case TEXT:
        case COMBO:
        case LIST:
            return new TextField(getWriter(), null, getName());
        case BUTTON:
            return new PushbuttonField(getWriter(), null, getName());
        case CHECKBOX:
        case RADIO:
            return new RadioCheckField(getWriter(), null, getName(), "Yes");
        }
        throw new VectorPrintException("unable to create BaseField for " + getFieldtype());
    }

    /**
     * calls {@link #create() } and {@link #setFieldValues()  } and registers this
     * FormFieldStyler as a {@link PdfPCellEvent} when element is null or when the {@link DebuggablePdfPCell} does not
     * contain a {@link BaseField} yet. Subclasses should first call this style method and after this call
     * {@link #getFromCell(java.lang.Object)} to get hold of the BaseField and style it. The BaseField is drawn on the
     * {@link PdfPTable#TEXTCANVAS} of the cell.
     *
     * @param <E>
     * @param element
     * @param data
     * @return
     * @throws VectorPrintException
     */
    @Override
    public <E> E style(E element, Object data) throws VectorPrintException {
        if (stylerFactory.getDocumentStyler().getValue(DocumentSettings.PDFA, Boolean.class)) {
            throw new VectorPrintRuntimeException("forms not supported in PDF/X-1a ");
        }
        bf = getFromCell(element);
        if (bf == null) {
            bf = create();
            setFieldValues();
            ((PdfPCell) element).setCellEvent(this);
        }
        return element;
    }

    /**
     * Set the value(s) for the BaseField, based on {@link FIELDTYPE}.
     *
     * @see #VALUES_PARAM
     */
    @Override
    public void setFieldValues() {
        String[] values = getValue(VALUES_PARAM, String[].class);
        switch (getFieldtype()) {
        case TEXT:
            if (values.length > 0) {
                ((TextField) bf).setText(values[0]);
            }
            break;
        case COMBO:
            if (values.length > 0) {
                ((TextField) bf).setChoices(values);
            }
            break;
        case LIST:
            if (values.length > 0) {
                ((TextField) bf).setChoices(values);
            }
            break;
        case BUTTON:
            ((PushbuttonField) bf).setText(values[0]);
            break;
        case CHECKBOX:
            if (values.length > 0) {
                ((RadioCheckField) bf).setOnValue(values[0]);
            }
            break;
        case RADIO:
            if (values.length > 0) {
                ((RadioCheckField) bf).setOnValue(values[0]);
            }
            break;
        }
    }

    /**
     * Create the PdfFormField that will be used to add a form field to the pdf.
     *
     * @return
     * @throws IOException
     * @throws DocumentException
     * @throws VectorPrintException
     */
    @Override
    public PdfFormField makeField() throws IOException, DocumentException, VectorPrintException {

        switch (getFieldtype()) {
        case TEXT:
            return ((TextField) bf).getTextField();
        case COMBO:
            return ((TextField) bf).getComboField();
        case LIST:
            return ((TextField) bf).getListField();
        case BUTTON:
            return ((PushbuttonField) bf).getField();
        case CHECKBOX:
            return ((RadioCheckField) bf).getCheckField();
        case RADIO:
            return ((RadioCheckField) bf).getRadioField();
        }
        throw new VectorPrintException(String.format("cannot create pdfformfield from %s and %s",
                (bf != null) ? bf.getClass() : null, String.valueOf(getFieldtype())));
    }

    @Override
    protected void draw(PdfContentByte canvas, float x, float y, float width, float height, String genericTag)
            throws VectorPrintException {
        Rectangle box = new Rectangle(x, y, x + width, y - height);
        PdfFormField pff = null;
        if (getValue(DocumentSettings.WIDTH, Float.class) > 0) {
            box.setRight(box.getLeft() + getValue(DocumentSettings.WIDTH, Float.class));
        }
        if (getValue(DocumentSettings.HEIGHT, Float.class) > 0) {
            float diff = box.getHeight() - getValue(DocumentSettings.HEIGHT, Float.class);
            box.setBottom(box.getBottom() + diff / 2);
            box.setTop(box.getTop() - diff / 2);
        }
        bf.setBox(box);
        try {
            List<BaseStyler> stylers = stylerFactory.getStylers(getStyleClass());
            List<FormFieldStyler> ffStylers = StyleHelper.getStylers(stylers, FormFieldStyler.class);
            pff = makeField();
            if (FormFieldStyler.FIELDTYPE.BUTTON.equals(getFieldtype())) {
                for (FormFieldStyler f : ffStylers) {
                    if (f.isParameterSet(Image.URLPARAM)) {
                        pff.setAction(PdfAction.createSubmitForm(f.getValue(Image.URLPARAM, URL.class).toString(),
                                null, PdfAction.SUBMIT_HTML_FORMAT));
                        break;
                    }
                }
            }
        } catch (IOException | DocumentException | VectorPrintException ex) {
            throw new VectorPrintRuntimeException(ex);
        }
        getWriter().addAnnotation(pff);
        if (stylerFactory.getSettings().getBooleanProperty(false, DEBUG)) {
            DebugHelper.debugRect(canvas, box, new float[] { 2, 2 }, 0.7f, stylerFactory.getSettings(),
                    elementProducer);
            DebugHelper.styleLink(canvas, getStyleClass(), "", box.getLeft(), box.getTop(),
                    stylerFactory.getSettings(), elementProducer);
        }
    }

    @Override
    public void setElementProducer(ElementProducer elementProducer) {
        this.elementProducer = elementProducer;
    }

    @Override
    public void setStylerFactory(StylerFactory stylerFactory) {
        this.stylerFactory = stylerFactory;
    }

    @Override
    public BaseField getBaseField() {
        return bf;
    }

    protected ElementProducer getElementProducer() {
        return elementProducer;
    }

    protected StylerFactory getStylerFactory() {
        return stylerFactory;
    }

    protected BaseField getBf() {
        return bf;
    }

    @Override
    public BaseField getFromCell(Object element) {
        if (element instanceof DebuggablePdfPCell) {
            return ((DebuggablePdfPCell) element).getBaseField();
        } else {
            return null;
        }
    }

    @Override
    public final EVENTMODE getEventmode() {
        return EVENTMODE.NONE;
    }

}