Class: HexaPDF::Type::AcroForm::ChoiceField

Inherits:
VariableTextField show all
Defined in:
lib/hexapdf/type/acro_form/choice_field.rb

Overview

AcroForm choice fields contain multiple text items of which one (or, if so flagged, more) may be selected.

They are divided into scrollable list boxes and combo boxes. To create a list or combo box, use the appropriate convenience methods on the main Form instance (HexaPDF::Document#acro_form). By using those methods, everything needed is automatically set up.

Type Specific Field Flags

See the class description for Field for the general field flags.

:combo

If set, the field represents a combo box.

:edit

If set, the combo box includes an editable text box for entering arbitrary values. Therefore the ‘combo’ flag also needs to be set.

:sort

The option items have to be sorted alphabetically. This flag is intended for PDF writers, not readers which should display the items in the order they appear.

:multi_select

If set, more than one item may be selected.

:do_not_spell_check

The text should not be spell-checked.

:commit_on_sel_change

If set, a new value should be commited as soon as a selection is made.

See: PDF2.0 s12.7.5.4

Constant Summary collapse

FLAGS_BIT_MAPPING =

Updated list of field flags.

superclass::FLAGS_BIT_MAPPING.merge(
  {
    combo: 17,
    edit: 18,
    sort: 19,
    multi_select: 21,
    do_not_spell_check: 22,
    commit_on_sel_change: 26,
  }
).freeze

Constants inherited from VariableTextField

VariableTextField::INHERITABLE_FIELDS, VariableTextField::UNSET_ARG

Constants inherited from Field

Field::INHERITABLE_FIELDS

Constants included from DictionaryFields

DictionaryFields::Boolean, DictionaryFields::PDFByteString, DictionaryFields::PDFDate

Instance Attribute Summary

Attributes inherited from Object

#data, #document, #must_be_indirect

Instance Method Summary collapse

Methods inherited from VariableTextField

create_appearance_string, parse_appearance_string, #parse_default_appearance_string, #set_default_appearance_string, #text_alignment

Methods inherited from Field

#[], #alternate_field_name, #alternate_field_name=, #create_widget, #delete_widget, #each_widget, #embedded_widget?, #field_name, #field_type, #flags, #form_field, #full_field_name, inherited_value, #must_be_indirect?, #terminal_field?, wrap

Methods included from Utils::BitField

#bit_field

Methods inherited from Dictionary

#[], #[]=, define_field, define_type, #delete, #each, each_field, #empty?, field, #key?, #to_hash, type, #type

Methods inherited from Object

#<=>, #==, #cache, #cached?, #clear_cache, deep_copy, #deep_copy, #document?, #eql?, field, #gen, #gen=, #hash, #indirect?, #initialize, #inspect, make_direct, #must_be_indirect?, #null?, #oid, #oid=, #type, #validate, #value, #value=

Constructor Details

This class inherits a constructor from HexaPDF::Object

Instance Method Details

#combo_box?Boolean

Returns true if this choice field represents a combo box.

Returns:



116
117
118
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 116

def combo_box?
  flagged?(:combo)
end

#concrete_field_typeObject

Returns the concrete choice field type, either :list_box, :combo_box or :editable_combo_box.



216
217
218
219
220
221
222
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 216

def concrete_field_type
  if combo_box?
    flagged?(:edit) ? :editable_combo_box : :combo_box
  else
    :list_box
  end
end

#create_appearances(force: false) ⇒ Object

Creates appropriate appearances for all widgets if they don’t already exist.

For information on how this is done see AppearanceGenerator.

Note that no new appearances are created if the dictionary fields involved in the creation of the appearance stream have not been changed between invocations.

By setting force to true the creation of the appearances can be forced.



232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 232

def create_appearances(force: false)
  current_appearance_state = [self[:V], self[:I], self[:Opt], self[:TI]]

  appearance_generator_class = document.config.constantize('acro_form.appearance_generator')
  each_widget do |widget|
    next if !force && widget.cached?(:appearance_state) &&
      widget.cache(:appearance_state) == current_appearance_state

    widget.cache(:appearance_state, current_appearance_state, update: true)
    if combo_box?
      appearance_generator_class.new(widget).create_combo_box_appearances
    else
      appearance_generator_class.new(widget).create_list_box_appearances
    end
  end
end

#default_field_valueObject

Returns the default field value.

See: #field_value



152
153
154
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 152

def default_field_value
  process_value(self[:DV])
end

#default_field_value=(value) ⇒ Object

Sets the default field value.

See: #field_value=



159
160
161
162
163
164
165
166
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 159

def default_field_value=(value)
  items = option_items
  self[:DV] = if [value].flatten.all? {|v| items.include?(v) }
                value
              else
                @document.config['acro_form.on_invalid_value'].call(self, value)
              end
end

#export_valuesObject

Returns the export values of the option items.

If you need the display strings (as in most cases), use the #option_items method.



180
181
182
183
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 180

def export_values
  prepare_option_items
  key?(:Opt) ? process_value(self[:Opt].map {|i| i.kind_of?(Array) ? i[0] : i }) : []
end

#field_valueObject

Returns the field value which represents the currently selected item(s).

If no item is selected, nil is returned. If multiple values are selected, the return value is an array of strings, otherwise it is just a string.



124
125
126
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 124

def field_value
  process_value(self[:V])
end

#field_value=(value) ⇒ Object

Sets the field value to the given string or array of strings.

The dictionary field /I is also modified to correctly represent the selected item(s).



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 131

def field_value=(value)
  items = option_items
  array_value = [value].flatten
  all_included = array_value.all? {|v| items.include?(v) }
  self[:V] = if combo_box? && value.kind_of?(String) &&
                 (flagged?(:edit) || all_included)
               delete(:I)
               value
             elsif list_box? && all_included &&
                 (value.kind_of?(String) || flagged?(:multi_select))
               self[:I] = array_value.map {|val| items.index(val) }.sort!
               array_value.length == 1 ? value : array_value
             else
               @document.config['acro_form.on_invalid_value'].call(self, value)
             end
  update_widgets
end

#initialize_as_combo_boxObject

Initializes the button field to be a combo box.

This method should only be called directly after creating a new choice field because it doesn’t completely reset the object.



105
106
107
108
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 105

def initialize_as_combo_box
  self[:V] = nil
  flag(:combo)
end

#initialize_as_list_boxObject

Initializes the choice field to be a list box.

This method should only be called directly after creating a new choice field because it doesn’t completely reset the object.



96
97
98
99
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 96

def initialize_as_list_box
  self[:V] = nil
  unflag(:combo)
end

#list_box?Boolean

Returns true if this choice field represents a list box.

Returns:



111
112
113
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 111

def list_box?
  !combo_box?
end

#list_box_top_indexObject

Returns the index of the first visible option item of a list box.



201
202
203
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 201

def list_box_top_index
  self[:TI]
end

#list_box_top_index=(index) ⇒ Object

Makes the option item referred to via the given index the first visible option item of a list box.



207
208
209
210
211
212
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 207

def list_box_top_index=(index)
  if index < 0 || !key?(:Opt) || index >= self[:Opt].length
    raise ArgumentError, "Index out of range for the set option items"
  end
  self[:TI] = index
end

#option_itemsObject

Returns the array with the available option items.

Note that this only returns the option items themselves! For getting the export values, the #export_values method has to be used.



172
173
174
175
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 172

def option_items
  prepare_option_items
  key?(:Opt) ? process_value(self[:Opt].map {|i| i.kind_of?(Array) ? i[1] : i }) : []
end

#option_items=(value) ⇒ Object

Sets the array with the available option items to the given value.

Each entry in the array may either be a string representing the text to be displayed. Or an array of two strings where the first describes the export value (to be used when exporting form field data from the document) and the second is the display value.

See: #option_items, #export_values



192
193
194
195
196
197
198
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 192

def option_items=(value)
  self[:Opt] = if flagged?(:sort)
                 value.sort_by {|i| process_value(i.kind_of?(Array) ? i[1] : i) }
               else
                 value
               end
end

#update_widgetsObject

Updates the widgets so that they reflect the current field value.



250
251
252
# File 'lib/hexapdf/type/acro_form/choice_field.rb', line 250

def update_widgets
  create_appearances
end