org.xhtmlrenderer.pdf.SelectFormField.java Source code

Java tutorial

Introduction

Here is the source code for org.xhtmlrenderer.pdf.SelectFormField.java

Source

/*
 * {{{ header & license
 * Copyright (c) 2007 Wisconsin Court System
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * }}}
 */
package org.xhtmlrenderer.pdf;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xhtmlrenderer.css.parser.FSColor;
import org.xhtmlrenderer.layout.LayoutContext;
import org.xhtmlrenderer.render.BlockBox;
import org.xhtmlrenderer.render.RenderingContext;
import org.xhtmlrenderer.util.*;

import com.lowagie.text.pdf.PdfAnnotation;
import com.lowagie.text.pdf.PdfAppearance;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfFormField;
import com.lowagie.text.pdf.PdfWriter;

public class SelectFormField extends AbstractFormField {
    private static final String FIELD_TYPE = "Select";

    private static final int EMPTY_SPACE_COUNT = 10;
    private static final int EXTRA_SPACE_COUNT = 4;

    private List _options;

    private int _baseline;

    public SelectFormField(LayoutContext c, BlockBox box, int cssWidth, int cssHeight) {
        _options = readOptions(box.getElement());
        initDimensions(c, box, cssWidth, cssHeight);

        float fontSize = box.getStyle().getFSFont(c).getSize2D();
        // FIXME: findbugs possible loss of precision, cf. int / (float)2
        _baseline = (int) (getHeight() / 2 + (fontSize * 0.3f));
    }

    private int getSelectedIndex() {
        int result = 0;

        List options = _options;

        int offset = 0;
        for (Iterator i = options.iterator(); i.hasNext(); offset++) {
            Option option = (Option) i.next();
            if (option.isSelected()) {
                result = offset;
            }
        }

        return result;
    }

    private String[][] getPDFOptions() {
        List options = _options;
        String[][] result = new String[options.size()][];

        int offset = 0;
        for (Iterator i = options.iterator(); i.hasNext(); offset++) {
            Option option = (Option) i.next();
            result[offset] = new String[] { option.getValue(), option.getLabel() };
        }

        return result;
    }

    private int calcDefaultWidth(LayoutContext c, BlockBox box) {
        List options = _options;

        if (options.size() == 0) {
            return c.getTextRenderer().getWidth(c.getFontContext(), box.getStyle().getFSFont(c),
                    spaces(EMPTY_SPACE_COUNT));
        } else {
            int maxWidth = 0;
            for (Iterator i = options.iterator(); i.hasNext();) {
                Option option = (Option) i.next();

                String result = option.getLabel() + spaces(EXTRA_SPACE_COUNT);

                int width = c.getTextRenderer().getWidth(c.getFontContext(), box.getStyle().getFSFont(c), result);

                if (width > maxWidth) {
                    maxWidth = width;
                }
            }

            return maxWidth;
        }
    }

    private List readOptions(Element e) {
        List result = new ArrayList();

        Node n = e.getFirstChild();
        while (n != null) {
            if (n.getNodeType() == Node.ELEMENT_NODE && n.getNodeName().equalsIgnoreCase("option")) {
                Element optionElem = (Element) n;

                String label = collectText(optionElem);
                Attr valueAttr = optionElem.getAttributeNode("value");
                String value;
                if (valueAttr == null) {
                    value = label;
                } else {
                    value = valueAttr.getValue();
                }

                if (label != null) {
                    Option option = new Option();
                    option.setLabel(label);
                    option.setValue(value);
                    if (isSelected(optionElem)) {
                        option.setSelected(true);
                    }
                    result.add(option);
                }
            }

            n = n.getNextSibling();
        }

        return result;
    }

    private String collectText(Element e) {
        StringBuffer result = new StringBuffer();

        Node n = e.getFirstChild();
        while (n != null) {
            short nodeType = n.getNodeType();
            if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) {
                Text t = (Text) n;
                result.append(t.getData());
            }
            n = n.getNextSibling();
        }

        return result.length() > 0 ? result.toString() : null;
    }

    protected void initDimensions(LayoutContext c, BlockBox box, int cssWidth, int cssHeight) {
        if (cssWidth != -1) {
            setWidth(cssWidth);
        } else {
            setWidth(calcDefaultWidth(c, box));
        }

        if (cssHeight != -1) {
            setHeight(cssHeight);
        } else {
            setHeight((int) (box.getStyle().getLineHeight(c) * getSize(box.getElement())));
        }
    }

    private int getSize(Element elem) {
        int result = 1;
        try {
            String v = elem.getAttribute("size").trim();
            if (v.length() > 0) {
                int i = Integer.parseInt(v);
                if (i > 1) {
                    result = i;
                }

            }
        } catch (NumberFormatException e) {
            // ignore
        }

        return result;
    }

    protected boolean isMultiple(Element e) {
        return !Util.isNullOrEmpty(e.getAttribute("multiple"));
    }

    protected String getFieldType() {
        return FIELD_TYPE;
    }

    public void paint(RenderingContext c, ITextOutputDevice outputDevice, BlockBox box) {
        PdfWriter writer = outputDevice.getWriter();

        String[][] options = getPDFOptions();
        int selectedIndex = getSelectedIndex();

        PdfFormField field;

        /*
         * Comment out for now.  We need to draw an appropriate appearance for
         * this to work correctly.
         */
        /*
        if (isMultiple(box.getElement())) {
        field = PdfFormField.createList(writer, options, selectedIndex);  
        } else {
        field = PdfFormField.createCombo(writer, false, options, selectedIndex);    
        }
        */

        field = PdfFormField.createCombo(writer, false, options, selectedIndex);

        field.setWidget(outputDevice.createLocalTargetArea(c, box), PdfAnnotation.HIGHLIGHT_INVERT);
        field.setFieldName(getFieldName(outputDevice, box.getElement()));
        if (options.length > 0) {
            field.setValueAsString(options[selectedIndex][0]);
        }

        createAppearance(c, outputDevice, box, field);

        if (isReadOnly(box.getElement())) {
            field.setFieldFlags(PdfFormField.FF_READ_ONLY);
        }

        /*
        if (isMultiple(box.getElement())) {
        field.setFieldFlags(PdfFormField.FF_MULTISELECT);
        }
        */

        writer.addAnnotation(field);
    }

    private void createAppearance(RenderingContext c, ITextOutputDevice outputDevice, BlockBox box,
            PdfFormField field) {
        PdfWriter writer = outputDevice.getWriter();
        ITextFSFont font = (ITextFSFont) box.getStyle().getFSFont(c);

        PdfContentByte cb = writer.getDirectContent();

        float width = outputDevice.getDeviceLength(getWidth());
        float height = outputDevice.getDeviceLength(getHeight());
        float fontSize = outputDevice.getDeviceLength(font.getSize2D());

        PdfAppearance tp = cb.createAppearance(width, height);
        tp.setFontAndSize(font.getFontDescription().getFont(), fontSize);

        FSColor color = box.getStyle().getColor();
        setFillColor(tp, color);

        field.setDefaultAppearanceString(tp);
    }

    public int getBaseline() {
        return _baseline;
    }

    public boolean hasBaseline() {
        return true;
    }

    private static final class Option {
        private String _value;
        private String _label;
        private boolean _selected;

        public String getValue() {
            return _value;
        }

        public void setValue(String value) {
            _value = value;
        }

        public String getLabel() {
            return _label;
        }

        public void setLabel(String label) {
            _label = label;
        }

        public boolean isSelected() {
            return _selected;
        }

        public void setSelected(boolean selected) {
            _selected = selected;
        }
    }
}