1pub 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_8125",
309 feature = "pdfium_7881",
310 feature = "pdfium_7763",
311 feature = "pdfium_7543",
312 feature = "pdfium_7350"
313 ))]
314 fn set_is_read_only(&mut self, is_read_only: bool) -> Result<(), PdfiumError>;
316
317 fn is_required(&self) -> bool;
323
324 #[cfg(any(
325 feature = "pdfium_future",
326 feature = "pdfium_8125",
327 feature = "pdfium_7881",
328 feature = "pdfium_7763",
329 feature = "pdfium_7543",
330 feature = "pdfium_7350"
331 ))]
332 fn set_is_required(&mut self, is_required: bool) -> Result<(), PdfiumError>;
338
339 fn is_exported_on_submit(&self) -> bool;
345
346 #[cfg(any(
347 feature = "pdfium_future",
348 feature = "pdfium_8125",
349 feature = "pdfium_7881",
350 feature = "pdfium_7763",
351 feature = "pdfium_7543",
352 feature = "pdfium_7350"
353 ))]
354 fn set_is_exported_on_submit(&mut self, is_exported: bool) -> Result<(), PdfiumError>;
360}
361
362impl<'a, T> PdfFormFieldCommon for T
365where
366 T: PdfFormFieldPrivate<'a>,
367{
368 #[inline]
369 fn name(&self) -> Option<String> {
370 self.name_impl()
371 }
372
373 #[inline]
374 fn appearance_stream(&self) -> Option<String> {
375 self.appearance_stream_impl()
376 }
377
378 #[inline]
379 fn appearance_mode_value(&self, appearance_mode: PdfAppearanceMode) -> Option<String> {
380 self.appearance_mode_value_impl(appearance_mode)
381 }
382
383 #[inline]
384 fn is_read_only(&self) -> bool {
385 self.get_flags_impl().contains(PdfFormFieldFlags::ReadOnly)
386 }
387
388 #[cfg(any(
389 feature = "pdfium_future",
390 feature = "pdfium_8125",
391 feature = "pdfium_7881",
392 feature = "pdfium_7763",
393 feature = "pdfium_7543",
394 feature = "pdfium_7350"
395 ))]
396 #[inline]
397 fn set_is_read_only(&mut self, is_read_only: bool) -> Result<(), PdfiumError> {
398 self.update_one_flag_impl(PdfFormFieldFlags::ReadOnly, is_read_only)
399 }
400
401 #[inline]
402 fn is_required(&self) -> bool {
403 self.get_flags_impl().contains(PdfFormFieldFlags::Required)
404 }
405
406 #[cfg(any(
407 feature = "pdfium_future",
408 feature = "pdfium_8125",
409 feature = "pdfium_7881",
410 feature = "pdfium_7763",
411 feature = "pdfium_7543",
412 feature = "pdfium_7350"
413 ))]
414 #[inline]
415 fn set_is_required(&mut self, is_required: bool) -> Result<(), PdfiumError> {
416 self.update_one_flag_impl(PdfFormFieldFlags::Required, is_required)
417 }
418
419 #[inline]
420 fn is_exported_on_submit(&self) -> bool {
421 !self.get_flags_impl().contains(PdfFormFieldFlags::NoExport)
422 }
423
424 #[cfg(any(
425 feature = "pdfium_future",
426 feature = "pdfium_8125",
427 feature = "pdfium_7881",
428 feature = "pdfium_7763",
429 feature = "pdfium_7543",
430 feature = "pdfium_7350"
431 ))]
432 #[inline]
433 fn set_is_exported_on_submit(&mut self, is_exported: bool) -> Result<(), PdfiumError> {
434 self.update_one_flag_impl(PdfFormFieldFlags::NoExport, !is_exported)
435 }
436}
437
438impl<'a> PdfFormFieldPrivate<'a> for PdfFormField<'a> {
439 #[inline]
440 fn form_handle(&self) -> FPDF_FORMHANDLE {
441 self.unwrap_as_trait().form_handle()
442 }
443
444 #[inline]
445 fn annotation_handle(&self) -> FPDF_ANNOTATION {
446 self.unwrap_as_trait().annotation_handle()
447 }
448}
449
450impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfFormField<'a> {}
451
452#[cfg(feature = "thread_safe")]
453unsafe impl<'a> Send for PdfFormField<'a> {}
454
455#[cfg(feature = "thread_safe")]
456unsafe impl<'a> Sync for PdfFormField<'a> {}
457
458impl<'a> From<PdfFormPushButtonField<'a>> for PdfFormField<'a> {
459 #[inline]
460 fn from(field: PdfFormPushButtonField<'a>) -> Self {
461 Self::PushButton(field)
462 }
463}
464
465impl<'a> From<PdfFormCheckboxField<'a>> for PdfFormField<'a> {
466 #[inline]
467 fn from(field: PdfFormCheckboxField<'a>) -> Self {
468 Self::Checkbox(field)
469 }
470}
471
472impl<'a> From<PdfFormRadioButtonField<'a>> for PdfFormField<'a> {
473 #[inline]
474 fn from(field: PdfFormRadioButtonField<'a>) -> Self {
475 Self::RadioButton(field)
476 }
477}
478
479impl<'a> From<PdfFormComboBoxField<'a>> for PdfFormField<'a> {
480 #[inline]
481 fn from(field: PdfFormComboBoxField<'a>) -> Self {
482 Self::ComboBox(field)
483 }
484}
485
486impl<'a> From<PdfFormListBoxField<'a>> for PdfFormField<'a> {
487 #[inline]
488 fn from(field: PdfFormListBoxField<'a>) -> Self {
489 Self::ListBox(field)
490 }
491}
492
493impl<'a> From<PdfFormTextField<'a>> for PdfFormField<'a> {
494 #[inline]
495 fn from(field: PdfFormTextField<'a>) -> Self {
496 Self::Text(field)
497 }
498}
499
500impl<'a> From<PdfFormSignatureField<'a>> for PdfFormField<'a> {
501 #[inline]
502 fn from(field: PdfFormSignatureField<'a>) -> Self {
503 Self::Signature(field)
504 }
505}
506
507impl<'a> From<PdfFormUnknownField<'a>> for PdfFormField<'a> {
508 #[inline]
509 fn from(field: PdfFormUnknownField<'a>) -> Self {
510 Self::Unknown(field)
511 }
512}