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