pdfium_render/pdf/document/page/
field.rs1pub mod button;
5pub mod checkbox;
6pub mod combo;
7pub mod list;
8pub mod option;
9pub mod options;
10pub(crate) mod private; pub mod radio;
12pub mod signature;
13pub mod text;
14pub mod unknown;
15
16use crate::bindgen::{
17 FPDF_ANNOTATION, FPDF_FORMFIELD_CHECKBOX, FPDF_FORMFIELD_COMBOBOX, FPDF_FORMFIELD_LISTBOX,
18 FPDF_FORMFIELD_PUSHBUTTON, FPDF_FORMFIELD_RADIOBUTTON, FPDF_FORMFIELD_SIGNATURE,
19 FPDF_FORMFIELD_TEXTFIELD, FPDF_FORMFIELD_UNKNOWN, FPDF_FORMHANDLE,
20};
21use crate::bindings::PdfiumLibraryBindings;
22use crate::error::PdfiumError;
23use crate::pdf::appearance_mode::PdfAppearanceMode;
24use crate::pdf::document::page::field::button::PdfFormPushButtonField;
25use crate::pdf::document::page::field::checkbox::PdfFormCheckboxField;
26use crate::pdf::document::page::field::combo::PdfFormComboBoxField;
27use crate::pdf::document::page::field::list::PdfFormListBoxField;
28use crate::pdf::document::page::field::private::internal::{
29 PdfFormFieldFlags, PdfFormFieldPrivate,
30};
31use crate::pdf::document::page::field::radio::PdfFormRadioButtonField;
32use crate::pdf::document::page::field::signature::PdfFormSignatureField;
33use crate::pdf::document::page::field::text::PdfFormTextField;
34use crate::pdf::document::page::field::unknown::PdfFormUnknownField;
35use crate::pdfium::PdfiumLibraryBindingsAccessor;
36use std::os::raw::c_int;
37
38#[cfg(doc)]
39use crate::pdf::document::form::PdfForm;
40
41#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
43pub enum PdfFormFieldType {
44 Unknown = FPDF_FORMFIELD_UNKNOWN as isize,
47 PushButton = FPDF_FORMFIELD_PUSHBUTTON as isize,
48 Checkbox = FPDF_FORMFIELD_CHECKBOX as isize,
49 RadioButton = FPDF_FORMFIELD_RADIOBUTTON as isize,
50 ComboBox = FPDF_FORMFIELD_COMBOBOX as isize,
51 ListBox = FPDF_FORMFIELD_LISTBOX as isize,
52 Text = FPDF_FORMFIELD_TEXTFIELD as isize,
53 Signature = FPDF_FORMFIELD_SIGNATURE as isize,
54}
55
56impl PdfFormFieldType {
57 #[inline]
58 #[allow(dead_code)]
59 pub(crate) fn from_pdfium(value: c_int) -> Result<PdfFormFieldType, PdfiumError> {
60 match value as u32 {
61 FPDF_FORMFIELD_UNKNOWN => Ok(PdfFormFieldType::Unknown),
62 FPDF_FORMFIELD_PUSHBUTTON => Ok(PdfFormFieldType::PushButton),
63 FPDF_FORMFIELD_CHECKBOX => Ok(PdfFormFieldType::Checkbox),
64 FPDF_FORMFIELD_RADIOBUTTON => Ok(PdfFormFieldType::RadioButton),
65 FPDF_FORMFIELD_COMBOBOX => Ok(PdfFormFieldType::ComboBox),
66 FPDF_FORMFIELD_LISTBOX => Ok(PdfFormFieldType::ListBox),
67 FPDF_FORMFIELD_TEXTFIELD => Ok(PdfFormFieldType::Text),
68 FPDF_FORMFIELD_SIGNATURE => Ok(PdfFormFieldType::Signature),
69 _ => Err(PdfiumError::UnknownFormFieldType),
70 }
71 }
72
73 #[inline]
74 #[allow(dead_code)]
75 pub(crate) fn as_pdfium(&self) -> u32 {
77 match self {
78 PdfFormFieldType::Unknown => FPDF_FORMFIELD_UNKNOWN,
79 PdfFormFieldType::PushButton => FPDF_FORMFIELD_PUSHBUTTON,
80 PdfFormFieldType::Checkbox => FPDF_FORMFIELD_CHECKBOX,
81 PdfFormFieldType::RadioButton => FPDF_FORMFIELD_RADIOBUTTON,
82 PdfFormFieldType::ComboBox => FPDF_FORMFIELD_COMBOBOX,
83 PdfFormFieldType::ListBox => FPDF_FORMFIELD_LISTBOX,
84 PdfFormFieldType::Text => FPDF_FORMFIELD_TEXTFIELD,
85 PdfFormFieldType::Signature => FPDF_FORMFIELD_SIGNATURE,
86 }
87 }
88}
89
90pub enum PdfFormField<'a> {
92 PushButton(PdfFormPushButtonField<'a>),
93 Checkbox(PdfFormCheckboxField<'a>),
94 RadioButton(PdfFormRadioButtonField<'a>),
95 ComboBox(PdfFormComboBoxField<'a>),
96 ListBox(PdfFormListBoxField<'a>),
97 Signature(PdfFormSignatureField<'a>),
98 Text(PdfFormTextField<'a>),
99 Unknown(PdfFormUnknownField<'a>),
100}
101
102impl<'a> PdfFormField<'a> {
103 pub(crate) fn from_pdfium(
104 form_handle: FPDF_FORMHANDLE,
105 annotation_handle: FPDF_ANNOTATION,
106 bindings: &'a dyn PdfiumLibraryBindings,
107 ) -> Option<Self> {
108 let result = unsafe { bindings.FPDFAnnot_GetFormFieldType(form_handle, annotation_handle) };
109
110 if result == -1 {
111 return None;
112 }
113
114 let form_field_type =
115 PdfFormFieldType::from_pdfium(result).unwrap_or(PdfFormFieldType::Unknown);
116
117 Some(match form_field_type {
118 PdfFormFieldType::PushButton => PdfFormField::PushButton(
119 PdfFormPushButtonField::from_pdfium(form_handle, annotation_handle),
120 ),
121 PdfFormFieldType::Checkbox => PdfFormField::Checkbox(
122 PdfFormCheckboxField::from_pdfium(form_handle, annotation_handle),
123 ),
124 PdfFormFieldType::RadioButton => PdfFormField::RadioButton(
125 PdfFormRadioButtonField::from_pdfium(form_handle, annotation_handle),
126 ),
127 PdfFormFieldType::ComboBox => PdfFormField::ComboBox(
128 PdfFormComboBoxField::from_pdfium(form_handle, annotation_handle),
129 ),
130 PdfFormFieldType::ListBox => PdfFormField::ListBox(PdfFormListBoxField::from_pdfium(
131 form_handle,
132 annotation_handle,
133 )),
134 PdfFormFieldType::Text => PdfFormField::Text(PdfFormTextField::from_pdfium(
135 form_handle,
136 annotation_handle,
137 )),
138 PdfFormFieldType::Signature => PdfFormField::Signature(
139 PdfFormSignatureField::from_pdfium(form_handle, annotation_handle),
140 ),
141 _ => PdfFormField::Unknown(PdfFormUnknownField::from_pdfium(
142 form_handle,
143 annotation_handle,
144 )),
145 })
146 }
147
148 #[inline]
149 pub(crate) fn unwrap_as_trait(&self) -> &dyn PdfFormFieldPrivate<'a> {
150 match self {
151 PdfFormField::PushButton(field) => field,
152 PdfFormField::Checkbox(field) => field,
153 PdfFormField::RadioButton(field) => field,
154 PdfFormField::ComboBox(field) => field,
155 PdfFormField::ListBox(field) => field,
156 PdfFormField::Signature(field) => field,
157 PdfFormField::Text(field) => field,
158 PdfFormField::Unknown(field) => field,
159 }
160 }
161
162 #[inline]
164 pub fn field_type(&self) -> PdfFormFieldType {
165 match self {
166 PdfFormField::PushButton(_) => PdfFormFieldType::PushButton,
167 PdfFormField::Checkbox(_) => PdfFormFieldType::Checkbox,
168 PdfFormField::RadioButton(_) => PdfFormFieldType::RadioButton,
169 PdfFormField::ComboBox(_) => PdfFormFieldType::ComboBox,
170 PdfFormField::ListBox(_) => PdfFormFieldType::ListBox,
171 PdfFormField::Signature(_) => PdfFormFieldType::Signature,
172 PdfFormField::Text(_) => PdfFormFieldType::Text,
173 PdfFormField::Unknown(_) => PdfFormFieldType::Unknown,
174 }
175 }
176
177 #[inline]
180 pub fn as_push_button_field(&self) -> Option<&PdfFormPushButtonField<'_>> {
181 match self {
182 PdfFormField::PushButton(field) => Some(field),
183 _ => None,
184 }
185 }
186
187 #[inline]
190 pub fn as_checkbox_field(&self) -> Option<&PdfFormCheckboxField<'_>> {
191 match self {
192 PdfFormField::Checkbox(field) => Some(field),
193 _ => None,
194 }
195 }
196
197 #[inline]
200 pub fn as_checkbox_field_mut(&mut self) -> Option<&mut PdfFormCheckboxField<'a>> {
201 match self {
202 PdfFormField::Checkbox(field) => Some(field),
203 _ => None,
204 }
205 }
206
207 #[inline]
210 pub fn as_radio_button_field(&self) -> Option<&PdfFormRadioButtonField<'_>> {
211 match self {
212 PdfFormField::RadioButton(field) => Some(field),
213 _ => None,
214 }
215 }
216
217 #[inline]
220 pub fn as_radio_button_field_mut(&mut self) -> Option<&mut PdfFormRadioButtonField<'a>> {
221 match self {
222 PdfFormField::RadioButton(field) => Some(field),
223 _ => None,
224 }
225 }
226
227 #[inline]
230 pub fn as_combo_box_field(&self) -> Option<&PdfFormComboBoxField<'_>> {
231 match self {
232 PdfFormField::ComboBox(field) => Some(field),
233 _ => None,
234 }
235 }
236
237 #[inline]
240 pub fn as_list_box_field(&self) -> Option<&PdfFormListBoxField<'_>> {
241 match self {
242 PdfFormField::ListBox(field) => Some(field),
243 _ => None,
244 }
245 }
246
247 #[inline]
250 pub fn as_signature_field(&self) -> Option<&PdfFormSignatureField<'_>> {
251 match self {
252 PdfFormField::Signature(field) => Some(field),
253 _ => None,
254 }
255 }
256
257 #[inline]
260 pub fn as_text_field(&self) -> Option<&PdfFormTextField<'_>> {
261 match self {
262 PdfFormField::Text(field) => Some(field),
263 _ => None,
264 }
265 }
266
267 pub fn as_text_field_mut(&mut self) -> Option<&mut PdfFormTextField<'a>> {
270 match self {
271 PdfFormField::Text(field) => Some(field),
272 _ => None,
273 }
274 }
275
276 #[inline]
279 pub fn as_unknown_field(&self) -> Option<&PdfFormUnknownField<'_>> {
280 match self {
281 PdfFormField::Unknown(field) => Some(field),
282 _ => None,
283 }
284 }
285}
286
287pub trait PdfFormFieldCommon {
289 fn name(&self) -> Option<String>;
291
292 fn appearance_stream(&self) -> Option<String>;
294
295 fn appearance_mode_value(&self, appearance_mode: PdfAppearanceMode) -> Option<String>;
298
299 fn is_read_only(&self) -> bool;
305
306 #[cfg(any(
307 feature = "pdfium_future",
308 feature = "pdfium_7881",
309 feature = "pdfium_7763",
310 feature = "pdfium_7543",
311 feature = "pdfium_7350"
312 ))]
313 fn set_is_read_only(&mut self, is_read_only: bool) -> Result<(), PdfiumError>;
315
316 fn is_required(&self) -> bool;
322
323 #[cfg(any(
324 feature = "pdfium_future",
325 feature = "pdfium_7881",
326 feature = "pdfium_7763",
327 feature = "pdfium_7543",
328 feature = "pdfium_7350"
329 ))]
330 fn set_is_required(&mut self, is_required: bool) -> Result<(), PdfiumError>;
336
337 fn is_exported_on_submit(&self) -> bool;
343
344 #[cfg(any(
345 feature = "pdfium_future",
346 feature = "pdfium_7881",
347 feature = "pdfium_7763",
348 feature = "pdfium_7543",
349 feature = "pdfium_7350"
350 ))]
351 fn set_is_exported_on_submit(&mut self, is_exported: bool) -> Result<(), PdfiumError>;
357}
358
359impl<'a, T> PdfFormFieldCommon for T
362where
363 T: PdfFormFieldPrivate<'a>,
364{
365 #[inline]
366 fn name(&self) -> Option<String> {
367 self.name_impl()
368 }
369
370 #[inline]
371 fn appearance_stream(&self) -> Option<String> {
372 self.appearance_stream_impl()
373 }
374
375 #[inline]
376 fn appearance_mode_value(&self, appearance_mode: PdfAppearanceMode) -> Option<String> {
377 self.appearance_mode_value_impl(appearance_mode)
378 }
379
380 #[inline]
381 fn is_read_only(&self) -> bool {
382 self.get_flags_impl().contains(PdfFormFieldFlags::ReadOnly)
383 }
384
385 #[cfg(any(
386 feature = "pdfium_future",
387 feature = "pdfium_7881",
388 feature = "pdfium_7763",
389 feature = "pdfium_7543",
390 feature = "pdfium_7350"
391 ))]
392 #[inline]
393 fn set_is_read_only(&mut self, is_read_only: bool) -> Result<(), PdfiumError> {
394 self.update_one_flag_impl(PdfFormFieldFlags::ReadOnly, is_read_only)
395 }
396
397 #[inline]
398 fn is_required(&self) -> bool {
399 self.get_flags_impl().contains(PdfFormFieldFlags::Required)
400 }
401
402 #[cfg(any(
403 feature = "pdfium_future",
404 feature = "pdfium_7881",
405 feature = "pdfium_7763",
406 feature = "pdfium_7543",
407 feature = "pdfium_7350"
408 ))]
409 #[inline]
410 fn set_is_required(&mut self, is_required: bool) -> Result<(), PdfiumError> {
411 self.update_one_flag_impl(PdfFormFieldFlags::Required, is_required)
412 }
413
414 #[inline]
415 fn is_exported_on_submit(&self) -> bool {
416 !self.get_flags_impl().contains(PdfFormFieldFlags::NoExport)
417 }
418
419 #[cfg(any(
420 feature = "pdfium_future",
421 feature = "pdfium_7881",
422 feature = "pdfium_7763",
423 feature = "pdfium_7543",
424 feature = "pdfium_7350"
425 ))]
426 #[inline]
427 fn set_is_exported_on_submit(&mut self, is_exported: bool) -> Result<(), PdfiumError> {
428 self.update_one_flag_impl(PdfFormFieldFlags::NoExport, !is_exported)
429 }
430}
431
432impl<'a> PdfFormFieldPrivate<'a> for PdfFormField<'a> {
433 #[inline]
434 fn form_handle(&self) -> FPDF_FORMHANDLE {
435 self.unwrap_as_trait().form_handle()
436 }
437
438 #[inline]
439 fn annotation_handle(&self) -> FPDF_ANNOTATION {
440 self.unwrap_as_trait().annotation_handle()
441 }
442}
443
444impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfFormField<'a> {}
445
446#[cfg(feature = "thread_safe")]
447unsafe impl<'a> Send for PdfFormField<'a> {}
448
449#[cfg(feature = "thread_safe")]
450unsafe impl<'a> Sync for PdfFormField<'a> {}
451
452impl<'a> From<PdfFormPushButtonField<'a>> for PdfFormField<'a> {
453 #[inline]
454 fn from(field: PdfFormPushButtonField<'a>) -> Self {
455 Self::PushButton(field)
456 }
457}
458
459impl<'a> From<PdfFormCheckboxField<'a>> for PdfFormField<'a> {
460 #[inline]
461 fn from(field: PdfFormCheckboxField<'a>) -> Self {
462 Self::Checkbox(field)
463 }
464}
465
466impl<'a> From<PdfFormRadioButtonField<'a>> for PdfFormField<'a> {
467 #[inline]
468 fn from(field: PdfFormRadioButtonField<'a>) -> Self {
469 Self::RadioButton(field)
470 }
471}
472
473impl<'a> From<PdfFormComboBoxField<'a>> for PdfFormField<'a> {
474 #[inline]
475 fn from(field: PdfFormComboBoxField<'a>) -> Self {
476 Self::ComboBox(field)
477 }
478}
479
480impl<'a> From<PdfFormListBoxField<'a>> for PdfFormField<'a> {
481 #[inline]
482 fn from(field: PdfFormListBoxField<'a>) -> Self {
483 Self::ListBox(field)
484 }
485}
486
487impl<'a> From<PdfFormTextField<'a>> for PdfFormField<'a> {
488 #[inline]
489 fn from(field: PdfFormTextField<'a>) -> Self {
490 Self::Text(field)
491 }
492}
493
494impl<'a> From<PdfFormSignatureField<'a>> for PdfFormField<'a> {
495 #[inline]
496 fn from(field: PdfFormSignatureField<'a>) -> Self {
497 Self::Signature(field)
498 }
499}
500
501impl<'a> From<PdfFormUnknownField<'a>> for PdfFormField<'a> {
502 #[inline]
503 fn from(field: PdfFormUnknownField<'a>) -> Self {
504 Self::Unknown(field)
505 }
506}