Class: HexaPDF::Type::AcroForm::TextField

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

Overview

AcroForm text fields provide a box or space to fill-in data entered from keyboard. The text may be restricted to a single line or can span multiple lines.

A special type of single-line text field is the comb text field. This type of field divides the existing space into /MaxLen equally spaced positions.

Type Specific Field Flags

:multiline

If set, the text field may contain multiple lines.

:password

The field is a password field. This changes the behaviour of the PDF reader application to not echo the input text and to not store it in the PDF file.

:file_select

The text field represents a file selection control where the input text is the path to a file.

:do_not_spell_check

The text should not be spell-checked.

:do_not_scroll

The text field should not scroll (horizontally for single-line fields and vertically for multiline fields) to accomodate more text than fits into the annotation rectangle. This means that no more text can be entered once the field is full.

:comb

The field is divided into /MaxLen equally spaced positions (so /MaxLen needs to be set). This is useful, for example, when entering things like social security numbers which always have the same length.

:rich_text

The field is a rich text field.

See: PDF1.7 s12.7.4.3

Constant Summary collapse

INHERITABLE_FIELDS =

All inheritable dictionary fields for text fields.

(superclass::INHERITABLE_FIELDS + [:MaxLen]).freeze
FLAGS_BIT_MAPPING =

Updated list of field flags.

superclass::FLAGS_BIT_MAPPING.merge(
  {
    multiline: 12,
    password: 13,
    file_select: 20,
    do_not_spell_check: 22,
    do_not_scroll: 23,
    comb: 24,
    rich_text: 25,
  }
).freeze

Constants inherited from VariableTextField

VariableTextField::UNSET_ARG

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, #full_field_name, inherited_value, #must_be_indirect?, #terminal_field?

Methods included from Utils::BitField

#bit_field

Methods inherited from Dictionary

#[], #[]=, define_field, define_type, #delete, #each, each_field, #empty?, field, #key?, #to_h, 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

#comb_text_field?Boolean

Returns true if this field is a comb text field.

Returns:



139
140
141
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 139

def comb_text_field?
  flagged?(:comb) && !(flagged?(:file_select) || flagged?(:multiline) || flagged?(:password))
end

#concrete_field_typeObject

Returns the concrete text field type, either :single_line_text_field, :multiline_text_field, :password_field, :file_select_field, :comb_text_field or :rich_text_field.



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 197

def concrete_field_type
  if flagged?(:multiline)
    :multiline_text_field
  elsif flagged?(:password)
    :password_field
  elsif flagged?(:file_select)
    :file_select_field
  elsif flagged?(:comb)
    :comb_text_field
  elsif flagged?(:rich_text)
    :rich_text_field
  else
    :single_line_text_field
  end
end

#create_appearances(force: false) ⇒ Object

Creates appropriate appearances for all widgets.

For information on how this is done see AppearanceGenerator.

Note that no new appearances are created if the field value hasn’t changed between invocations.

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



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 221

def create_appearances(force: false)
  current_value = field_value
  appearance_generator_class = document.config.constantize('acro_form.appearance_generator')
  each_widget do |widget|
    is_cached = widget.cached?(:last_value)
    unless force
      if is_cached && widget.cache(:last_value) == current_value
        next
      elsif !is_cached && widget.appearance?
        widget.cache(:last_value, current_value, update: true)
        next
      end
    end
    widget.cache(:last_value, current_value, update: true)
    appearance_generator_class.new(widget).create_text_appearances
  end
end

#default_field_valueObject

Returns the default field value.

See: #field_value



183
184
185
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 183

def default_field_value
  self[:DV].kind_of?(String) ? self[:DV] : self[:DV].stream
end

#default_field_value=(str) ⇒ Object

Sets the default field value.

See: #field_value=



190
191
192
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 190

def default_field_value=(str)
  self[:DV] = str
end

#field_valueObject

Returns the field value, i.e. the text contents of the field, or nil if no value is set.

Note that modifying the returned value *might not* modify the text contents in case it is stored as stream! So always use #field_value= to set the field value.



157
158
159
160
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 157

def field_value
  return unless value[:V]
  self[:V].kind_of?(String) ? self[:V] : self[:V].stream
end

#field_value=(str) ⇒ Object

Sets the field value, i.e. the text contents of the field, to the given string.

Note that for single line text fields, all whitespace characters are changed to simple spaces.



166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 166

def field_value=(str)
  if flagged?(:password)
    raise HexaPDF::Error, "Storing a field value for a password field is not allowed"
  elsif comb_text_field? && !key?(:MaxLen)
    raise HexaPDF::Error, "A comb text field need a valid /MaxLen value"
  end
  str = str.gsub(/[[:space:]]/, ' ') if str && concrete_field_type == :single_line_text_field
  if key?(:MaxLen) && str && str.length > self[:MaxLen]
    raise HexaPDF::Error, "Value exceeds maximum allowed length of #{self[:MaxLen]}"
  end
  self[:V] = str
  update_widgets
end

#file_select_field?Boolean

Returns true if this field is a file select field.

Returns:



149
150
151
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 149

def file_select_field?
  flagged?(:file_select) && !(flagged?(:password) || flagged?(:multiline) || flagged?(:comb))
end

#initialize_as_comb_text_fieldObject

Initializes the text field to be a comb text field.

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



109
110
111
112
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 109

def initialize_as_comb_text_field
  flag(:comb)
  unflag(:file_select, :multiline, :password)
end

#initialize_as_file_select_fieldObject

Initializes the text field to be a file select field.

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



128
129
130
131
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 128

def initialize_as_file_select_field
  flag(:file_select)
  unflag(:comb, :multiline, :password)
end

#initialize_as_multiline_text_fieldObject

Initializes the text field to be a multiline text field.

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



100
101
102
103
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 100

def initialize_as_multiline_text_field
  flag(:multiline)
  unflag(:file_select, :comb, :password)
end

#initialize_as_password_fieldObject

Initializes the text field to be a password field.

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



118
119
120
121
122
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 118

def initialize_as_password_field
  delete(:V)
  flag(:password)
  unflag(:comb, :multiline, :file_select)
end

#multiline_text_field?Boolean

Returns true if this field is a multiline text field.

Returns:



134
135
136
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 134

def multiline_text_field?
  flagged?(:multiline) && !(flagged?(:file_select) || flagged?(:comb) || flagged?(:password))
end

#password_field?Boolean

Returns true if this field is a password field.

Returns:



144
145
146
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 144

def password_field?
  flagged?(:password) && !(flagged?(:file_select) || flagged?(:multiline) || flagged?(:comb))
end

#update_widgetsObject

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



240
241
242
# File 'lib/hexapdf/type/acro_form/text_field.rb', line 240

def update_widgets
  create_appearances(force: true)
end