Skip to main content

pdfium_render/pdf/document/page/field/
combo.rs

1//! Defines the [PdfFormComboBoxField] struct, exposing functionality related to a single
2//! form field of type [PdfFormFieldType::ComboBox].
3
4use std::marker::PhantomData;
5
6use crate::bindgen::{FPDF_ANNOTATION, FPDF_FORMHANDLE};
7use crate::pdf::document::page::field::options::PdfFormFieldOptions;
8use crate::pdf::document::page::field::private::internal::{
9    PdfFormFieldFlags, PdfFormFieldPrivate,
10};
11
12#[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
13use crate::error::PdfiumError;
14use crate::pdfium::PdfiumLibraryBindingsAccessor;
15
16#[cfg(doc)]
17use {
18    crate::pdf::document::form::PdfForm,
19    crate::pdf::document::page::annotation::PdfPageAnnotationType,
20    crate::pdf::document::page::field::{PdfFormField, PdfFormFieldType},
21};
22
23/// A single [PdfFormField] of type [PdfFormFieldType::ComboBox]. The form field object defines
24/// an interactive drop-down list widget that allows the user to either select a value
25/// from a list of options or type a value into a text field.
26///
27/// Form fields in Pdfium are wrapped inside page annotations of type [PdfPageAnnotationType::Widget]
28/// or [PdfPageAnnotationType::XfaWidget]. User-specified values can be retrieved directly from
29/// each form field object by unwrapping the form field from the annotation, or in bulk from the
30/// [PdfForm::field_values()] function.
31pub struct PdfFormComboBoxField<'a> {
32    form_handle: FPDF_FORMHANDLE,
33    annotation_handle: FPDF_ANNOTATION,
34    options: PdfFormFieldOptions<'a>,
35    lifetime: PhantomData<&'a FPDF_ANNOTATION>,
36}
37
38impl<'a> PdfFormComboBoxField<'a> {
39    #[inline]
40    pub(crate) fn from_pdfium(
41        form_handle: FPDF_FORMHANDLE,
42        annotation_handle: FPDF_ANNOTATION,
43    ) -> Self {
44        PdfFormComboBoxField {
45            form_handle,
46            annotation_handle,
47            options: PdfFormFieldOptions::from_pdfium(form_handle, annotation_handle),
48            lifetime: PhantomData,
49        }
50    }
51
52    /// Returns the collection of selectable options in this [PdfFormComboBoxField].
53    pub fn options(&self) -> &PdfFormFieldOptions<'_> {
54        &self.options
55    }
56
57    /// Returns the displayed label for the currently selected option in this [PdfFormComboBoxField] object, if any.
58    #[inline]
59    pub fn value(&self) -> Option<String> {
60        self.options()
61            .iter()
62            .find(|option| option.is_set())
63            .and_then(|option| option.label().cloned())
64    }
65
66    /// Returns `true` if this [PdfFormComboBoxField] also includes an editable text box.
67    /// If `false`, this combo box field only includes a drop-down list.
68    #[inline]
69    pub fn has_editable_text_box(&self) -> bool {
70        self.get_flags_impl()
71            .contains(PdfFormFieldFlags::ChoiceEdit)
72    }
73
74    #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
75    /// Controls whether or not this [PdfFormComboBoxField] includes an editable text box
76    /// in addition to a drop-down list.
77    #[inline]
78    pub fn set_has_editable_text_box(
79        &mut self,
80        has_editable_text_box: bool,
81    ) -> Result<(), PdfiumError> {
82        self.update_one_flag_impl(PdfFormFieldFlags::ChoiceEdit, has_editable_text_box)
83    }
84
85    /// Returns `true` if the option items of this [PdfFormComboBoxField] should be sorted
86    /// alphabetically.
87    ///
88    /// This flag is intended for use by form authoring tools, not by PDF viewer applications.
89    #[inline]
90    pub fn is_sorted(&self) -> bool {
91        self.get_flags_impl()
92            .contains(PdfFormFieldFlags::ChoiceSort)
93    }
94
95    #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
96    /// Controls whether or not the option items of this [PdfFormComboBoxField] should be
97    /// sorted alphabetically.
98    ///
99    /// This flag is intended for use by form authoring tools, not by PDF viewer applications.
100    #[inline]
101    pub fn set_is_sorted(&mut self, is_sorted: bool) -> Result<(), PdfiumError> {
102        self.update_one_flag_impl(PdfFormFieldFlags::ChoiceSort, is_sorted)
103    }
104
105    /// Returns `true` if more than one of the option items in this [PdfFormComboBoxField]
106    /// may be selected simultaneously. If `false`, only one item at a time may be selected.
107    ///
108    /// This flag was added in PDF version 1.4.
109    pub fn is_multiselect(&self) -> bool {
110        self.get_flags_impl()
111            .contains(PdfFormFieldFlags::ChoiceMultiSelect)
112    }
113
114    #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
115    /// Controls whether more than one of the option items in this [PdfFormComboBoxField]
116    /// may be selected simultaneously.
117    ///
118    /// This flag was added in PDF version 1.4.
119    pub fn set_is_multiselect(&mut self, is_multiselect: bool) -> Result<(), PdfiumError> {
120        self.update_one_flag_impl(PdfFormFieldFlags::ChoiceMultiSelect, is_multiselect)
121    }
122
123    /// Returns `true` if text entered into the editable text box included in this
124    /// [PdfFormComboBoxField] should be spell checked.
125    ///
126    /// This flag is meaningful only if the [PdfFormComboBoxField::has_editable_text_box()]
127    /// flag is also `true`.
128    ///
129    /// This flag was added in PDF version 1.4.
130    pub fn is_spell_checked(&self) -> bool {
131        !self
132            .get_flags_impl()
133            .contains(PdfFormFieldFlags::TextDoNotSpellCheck)
134    }
135
136    #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
137    /// Controls whether or not text entered into the editable text box included in this
138    /// [PdfFormComboBoxField] should be spell checked.
139    ///
140    /// This flag was added in PDF version 1.4.
141    pub fn set_is_spell_checked(&mut self, is_spell_checked: bool) -> Result<(), PdfiumError> {
142        self.update_one_flag_impl(PdfFormFieldFlags::TextDoNotSpellCheck, !is_spell_checked)
143    }
144
145    /// Returns `true` if any new value is committed to this [PdfFormComboBoxField]
146    /// as soon as a selection is made with the pointing device. This option enables
147    /// applications to perform an action once a selection is made, without requiring
148    /// the user to exit the field. If `false`, any new value is not committed until the
149    /// user exits the field.
150    ///
151    /// This flag was added in PDF version 1.5.
152    pub fn is_commit_on_selection_change(&self) -> bool {
153        self.get_flags_impl()
154            .contains(PdfFormFieldFlags::ChoiceCommitOnSelectionChange)
155    }
156
157    #[cfg(any(feature = "pdfium_future", feature = "pdfium_7350"))]
158    /// Controls whether or not any new value is committed to this [PdfFormComboBoxField]
159    /// as soon as a selection is made with the pointing device.
160    ///
161    /// This flag was added in PDF version 1.5.
162    pub fn set_is_commit_on_selection_change(
163        &mut self,
164        is_commit_on_selection_change: bool,
165    ) -> Result<(), PdfiumError> {
166        self.update_one_flag_impl(
167            PdfFormFieldFlags::ChoiceCommitOnSelectionChange,
168            is_commit_on_selection_change,
169        )
170    }
171}
172
173impl<'a> PdfFormFieldPrivate<'a> for PdfFormComboBoxField<'a> {
174    #[inline]
175    fn form_handle(&self) -> FPDF_FORMHANDLE {
176        self.form_handle
177    }
178
179    #[inline]
180    fn annotation_handle(&self) -> FPDF_ANNOTATION {
181        self.annotation_handle
182    }
183}
184
185impl<'a> PdfiumLibraryBindingsAccessor<'a> for PdfFormComboBoxField<'a> {}
186
187#[cfg(feature = "thread_safe")]
188unsafe impl<'a> Send for PdfFormComboBoxField<'a> {}
189
190#[cfg(feature = "thread_safe")]
191unsafe impl<'a> Sync for PdfFormComboBoxField<'a> {}