All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.pdfbox.pdmodel.interactive.form.PDChoice Maven / Gradle / Ivy

Go to download

The Apache PDFBox library is an open source Java tool for working with PDF documents.

There is a newer version: 3.0.2
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.pdfbox.pdmodel.interactive.form;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSBase;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.cos.COSString;
import org.apache.pdfbox.pdmodel.common.COSArrayList;
import org.apache.pdfbox.pdmodel.interactive.form.FieldUtils.KeyValue;

/**
 * A choice field contains several text items, one or more of which shall be selected as the field
 * value.
 * 
 * @author sug
 * @author John Hewson
 */
public abstract class PDChoice extends PDVariableText
{
    static final int FLAG_COMBO = 1 << 17;
    
    private static final int FLAG_SORT = 1 << 19;
    private static final int FLAG_MULTI_SELECT = 1 << 21;
    private static final int FLAG_DO_NOT_SPELL_CHECK = 1 << 22;
    private static final int FLAG_COMMIT_ON_SEL_CHANGE = 1 << 26;
    
    /**
     * @see PDField#PDField(PDAcroForm)
     *
     * @param acroForm The acroform.
     */
    public PDChoice(PDAcroForm acroForm)
    {
        super(acroForm);
        getCOSObject().setItem(COSName.FT, COSName.CH);
    }

    /**
     * Constructor.
     * 
     * @param acroForm The form that this field is part of.
     * @param field the PDF object to represent as a field.
     * @param parent the parent node of the node
     */
    PDChoice(PDAcroForm acroForm, COSDictionary field, PDNonTerminalField parent)
    {
        super(acroForm, field, parent);
    }
    
    /**
     * This will get the option values "Opt".
     * 
     * 

* For a choice field the options array can either be an array * of text strings or an array of a two-element arrays.
* The method always only returns either the text strings or, * in case of two-element arrays, an array of the first element of * the two-element arrays *

*

* Use {@link #getOptionsExportValues()} and {@link #getOptionsDisplayValues()} * to get the entries of two-element arrays. *

* * @return List containing the export values. */ public List getOptions() { COSBase values = getCOSObject().getDictionaryObject(COSName.OPT); return FieldUtils.getPairableItems(values, 0); } /** * This will set the display values - the 'Opt' key. * *

* The Opt array specifies the list of options in the choice field either * as an array of text strings representing the display value * or as an array of a two-element array where the * first element is the export value and the second the display value. *

*

* To set both the export and the display value use {@link #setOptions(List, List)} *

* * @param displayValues List containing all possible options. */ public void setOptions(List displayValues) { if (displayValues != null && !displayValues.isEmpty()) { if (isSort()) { Collections.sort(displayValues); } getCOSObject().setItem(COSName.OPT, COSArrayList.convertStringListToCOSStringCOSArray(displayValues)); } else { getCOSObject().removeItem(COSName.OPT); } } /** * This will set the display and export values - the 'Opt' key. * *

* This will set both, the export value and the display value * of the choice field. If either one of the parameters is null or an * empty list is supplied the options will * be removed. *

*

* An {@link IllegalArgumentException} will be thrown if the * number of items in the list differ. *

* * @see #setOptions(List) * @param exportValues List containing all possible export values. * @param displayValues List containing all possible display values. */ public void setOptions(List exportValues, List displayValues) { if (exportValues != null && displayValues != null && !exportValues.isEmpty() && !displayValues.isEmpty()) { if (exportValues.size() != displayValues.size()) { throw new IllegalArgumentException( "The number of entries for exportValue and displayValue shall be the same."); } else { List keyValuePairs = FieldUtils.toKeyValueList(exportValues, displayValues); if (isSort()) { FieldUtils.sortByValue(keyValuePairs); } COSArray options = new COSArray(); for (int i = 0; i * For options with an array of text strings the display value and export value * are the same.
* For options with an array of two-element arrays the display value is the * second entry in the two-element array. *

* * @return List containing all the display values. */ public List getOptionsDisplayValues() { COSBase values = getCOSObject().getDictionaryObject(COSName.OPT); return FieldUtils.getPairableItems(values, 1); } /** * This will get the export values from the options. * *

* For options with an array of text strings the display value and export value * are the same.
* For options with an array of two-element arrays the export value is the * first entry in the two-element array. *

* * @return List containing all export values. */ public List getOptionsExportValues() { return getOptions(); } /** * This will get the indices of the selected options - the 'I' key. *

* This is only needed if a choice field allows multiple selections and * two different items have the same export value or more than one values * is selected. *

*

The indices are zero-based

* * @return List containing the indices of all selected options. */ public List getSelectedOptionsIndex() { COSBase value = getCOSObject().getDictionaryObject(COSName.I); if (value != null) { return COSArrayList.convertIntegerCOSArrayToList((COSArray) value); } return Collections.emptyList(); } /** * This will set the indices of the selected options - the 'I' key. *

* This method is preferred over {@link #setValue(List)} for choice fields which *

    *
  • do support multiple selections
  • *
  • have export values with the same value
  • *
*

* Setting the index will set the value too. * * @param values List containing the indices of all selected options. */ public void setSelectedOptionsIndex(List values) { if (values != null && !values.isEmpty()) { if (!isMultiSelect()) { throw new IllegalArgumentException( "Setting the indices is not allowed for choice fields not allowing multiple selections."); } getCOSObject().setItem(COSName.I, COSArrayList.converterToCOSArray(values)); } else { getCOSObject().removeItem(COSName.I); } } /** * Determines if Sort is set. * *

* If set, the field’s option items shall be sorted alphabetically. * The sorting has to be done when writing the PDF. PDF Readers are supposed to * display the options in the order in which they occur in the Opt array. *

* * @return true if the options are sorted. */ public boolean isSort() { return getCOSObject().getFlag(COSName.FF, FLAG_SORT); } /** * Set the Sort bit. * * @see #isSort() * @param sort The value for Sort. */ public void setSort(boolean sort) { getCOSObject().setFlag(COSName.FF, FLAG_SORT, sort); } /** * Determines if MultiSelect is set. * * @return true if multi select is allowed. */ public boolean isMultiSelect() { return getCOSObject().getFlag(COSName.FF, FLAG_MULTI_SELECT); } /** * Set the MultiSelect bit. * * @param multiSelect The value for MultiSelect. */ public void setMultiSelect(boolean multiSelect) { getCOSObject().setFlag(COSName.FF, FLAG_MULTI_SELECT, multiSelect); } /** * Determines if DoNotSpellCheck is set. * * @return true if spell checker is disabled. */ public boolean isDoNotSpellCheck() { return getCOSObject().getFlag(COSName.FF, FLAG_DO_NOT_SPELL_CHECK); } /** * Set the DoNotSpellCheck bit. * * @param doNotSpellCheck The value for DoNotSpellCheck. */ public void setDoNotSpellCheck(boolean doNotSpellCheck) { getCOSObject().setFlag(COSName.FF, FLAG_DO_NOT_SPELL_CHECK, doNotSpellCheck); } /** * Determines if CommitOnSelChange is set. * * @return true if value shall be committed as soon as a selection is made. */ public boolean isCommitOnSelChange() { return getCOSObject().getFlag(COSName.FF, FLAG_COMMIT_ON_SEL_CHANGE); } /** * Set the CommitOnSelChange bit. * * @param commitOnSelChange The value for CommitOnSelChange. */ public void setCommitOnSelChange(boolean commitOnSelChange) { getCOSObject().setFlag(COSName.FF, FLAG_COMMIT_ON_SEL_CHANGE, commitOnSelChange); } /** * Determines if Combo is set. * * @return true if value the choice is a combo box.. */ public boolean isCombo() { return getCOSObject().getFlag(COSName.FF, FLAG_COMBO); } /** * Set the Combo bit. * * @param combo The value for Combo. */ public void setCombo(boolean combo) { getCOSObject().setFlag(COSName.FF, FLAG_COMBO, combo); } /** * Sets the selected value of this field. * * @param value The name of the selected item. * @throws IOException if the value could not be set */ @Override public void setValue(String value) throws IOException { getCOSObject().setString(COSName.V, value); // remove I key for single valued choice field setSelectedOptionsIndex(null); applyChange(); } /** * Sets the default value of this field. * * @param value The name of the selected item. * @throws IOException if the value could not be set */ public void setDefaultValue(String value) throws IOException { getCOSObject().setString(COSName.DV, value); } /** * Sets the entry "V" to the given values. Requires {@link #isMultiSelect()} to be true. * * @param values the list of values * @throws IOException if the appearance couldn't be generated. */ public void setValue(List values) throws IOException { if (values != null && !values.isEmpty()) { if (!isMultiSelect()) { throw new IllegalArgumentException("The list box does not allow multiple selections."); } if (!getOptions().containsAll(values)) { throw new IllegalArgumentException("The values are not contained in the selectable options."); } getCOSObject().setItem(COSName.V, COSArrayList.convertStringListToCOSStringCOSArray(values)); updateSelectedOptionsIndex(values); } else { getCOSObject().removeItem(COSName.V); getCOSObject().removeItem(COSName.I); } applyChange(); } /** * Returns the selected values, or an empty List. This list always contains a single item * unless {@link #isMultiSelect()} is true. * * @return A non-null string. */ public List getValue() { return getValueFor(COSName.V); } /** * Returns the default values, or an empty List. This list always contains a single item * unless {@link #isMultiSelect()} is true. * * @return A non-null string. */ public List getDefaultValue() { return getValueFor(COSName.DV); } /** * Returns the selected values, or an empty List, for the given key. */ private List getValueFor(COSName name) { COSBase value = getCOSObject().getDictionaryObject(name); if (value instanceof COSString) { List array = new ArrayList(); array.add(((COSString) value).getString()); return array; } else if (value instanceof COSArray) { return COSArrayList.convertCOSStringCOSArrayToList((COSArray)value); } return Collections.emptyList(); } @Override public String getValueAsString() { return Arrays.toString(getValue().toArray()); } /** * Update the 'I' key based on values set. */ private void updateSelectedOptionsIndex(List values) { List options = getOptions(); List indices = new ArrayList(); for (String value : values) { indices.add(options.indexOf(value)); } // Indices have to be "... array of integers, sorted in ascending order ..." Collections.sort(indices); setSelectedOptionsIndex(indices); } @Override abstract void constructAppearances() throws IOException; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy