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(feature = "pdfium_future", feature = "pdfium_7350"))]
307 fn set_is_read_only(&mut self, is_read_only: bool) -> Result<(), PdfiumError>;
309
310 fn is_required(&self) -> bool;
316
317 #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
318 fn set_is_required(&mut self, is_required: bool) -> Result<(), PdfiumError>;
324
325 fn is_exported_on_submit(&self) -> bool;
331
332 #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
333 fn set_is_exported_on_submit(&mut self, is_exported: bool) -> Result<(), PdfiumError>;
339}
340
341impl<'a, T> PdfFormFieldCommon for T
344where
345 T: PdfFormFieldPrivate<'a>,
346{
347 #[inline]
348 fn name(&self) -> Option<String> {
349 self.name_impl()
350 }
351
352 #[inline]
353 fn appearance_stream(&self) -> Option<String> {
354 self.appearance_stream_impl()
355 }
356
357 #[inline]
358 fn appearance_mode_value(&self, appearance_mode: PdfAppearanceMode) -> Option<String> {
359 self.appearance_mode_value_impl(appearance_mode)
360 }
361
362 #[inline]
363 fn is_read_only(&self) -> bool {
364 self.get_flags_impl().contains(PdfFormFieldFlags::ReadOnly)
365 }
366
367 #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
368 #[inline]
369 fn set_is_read_only(&mut self, is_read_only: bool) -> Result<(), PdfiumError> {
370 self.update_one_flag_impl(PdfFormFieldFlags::ReadOnly, is_read_only)
371 }
372
373 #[inline]
374 fn is_required(&self) -> bool {
375 self.get_flags_impl().contains(PdfFormFieldFlags::Required)
376 }
377
378 #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
379 #[inline]
380 fn set_is_required(&mut self, is_required: bool) -> Result<(), PdfiumError> {
381 self.update_one_flag_impl(PdfFormFieldFlags::Required, is_required)
382 }
383
384 #[inline]
385 fn is_exported_on_submit(&self) -> bool {
386 !self.get_flags_impl().contains(PdfFormFieldFlags::NoExport)
387 }
388
389 #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
390 #[inline]
391 fn set_is_exported_on_submit(&mut self, is_exported: bool) -> Result<(), PdfiumError> {
392 self.update_one_flag_impl(PdfFormFieldFlags::NoExport, !is_exported)
393 }
394}
395
396impl<'a> PdfFormFieldPrivate<'a> for PdfFormField<'a> {
397 #[inline]
398 fn form_handle(&self) -> FPDF_FORMHANDLE {
399 self.unwrap_as_trait().form_handle()
400 }
401
402 #[inline]
403 fn annotation_handle(&self) -> FPDF_ANNOTATION {
404 self.unwrap_as_trait().annotation_handle()
405 }
406}
407
408impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfFormField<'a> {}
409
410#[cfg(feature = "thread_safe")]
411unsafe impl<'a> Send for PdfFormField<'a> {}
412
413#[cfg(feature = "thread_safe")]
414unsafe impl<'a> Sync for PdfFormField<'a> {}
415
416impl<'a> From<PdfFormPushButtonField<'a>> for PdfFormField<'a> {
417 #[inline]
418 fn from(field: PdfFormPushButtonField<'a>) -> Self {
419 Self::PushButton(field)
420 }
421}
422
423impl<'a> From<PdfFormCheckboxField<'a>> for PdfFormField<'a> {
424 #[inline]
425 fn from(field: PdfFormCheckboxField<'a>) -> Self {
426 Self::Checkbox(field)
427 }
428}
429
430impl<'a> From<PdfFormRadioButtonField<'a>> for PdfFormField<'a> {
431 #[inline]
432 fn from(field: PdfFormRadioButtonField<'a>) -> Self {
433 Self::RadioButton(field)
434 }
435}
436
437impl<'a> From<PdfFormComboBoxField<'a>> for PdfFormField<'a> {
438 #[inline]
439 fn from(field: PdfFormComboBoxField<'a>) -> Self {
440 Self::ComboBox(field)
441 }
442}
443
444impl<'a> From<PdfFormListBoxField<'a>> for PdfFormField<'a> {
445 #[inline]
446 fn from(field: PdfFormListBoxField<'a>) -> Self {
447 Self::ListBox(field)
448 }
449}
450
451impl<'a> From<PdfFormTextField<'a>> for PdfFormField<'a> {
452 #[inline]
453 fn from(field: PdfFormTextField<'a>) -> Self {
454 Self::Text(field)
455 }
456}
457
458impl<'a> From<PdfFormSignatureField<'a>> for PdfFormField<'a> {
459 #[inline]
460 fn from(field: PdfFormSignatureField<'a>) -> Self {
461 Self::Signature(field)
462 }
463}
464
465impl<'a> From<PdfFormUnknownField<'a>> for PdfFormField<'a> {
466 #[inline]
467 fn from(field: PdfFormUnknownField<'a>) -> Self {
468 Self::Unknown(field)
469 }
470}