use crate::appearance_mode::PdfAppearanceMode;
use crate::bindgen::{
FPDF_ANNOTATION, FPDF_FORMFIELD_CHECKBOX, FPDF_FORMFIELD_COMBOBOX, FPDF_FORMFIELD_LISTBOX,
FPDF_FORMFIELD_PUSHBUTTON, FPDF_FORMFIELD_RADIOBUTTON, FPDF_FORMFIELD_SIGNATURE,
FPDF_FORMFIELD_TEXTFIELD, FPDF_FORMFIELD_UNKNOWN, FPDF_FORMHANDLE,
};
use crate::bindings::PdfiumLibraryBindings;
use crate::error::PdfiumError;
use crate::form_field_button::PdfFormPushButtonField;
use crate::form_field_checkbox::PdfFormCheckboxField;
use crate::form_field_combo::PdfFormComboBoxField;
use crate::form_field_list::PdfFormListBoxField;
use crate::form_field_private::internal::PdfFormFieldPrivate;
use crate::form_field_radio::PdfFormRadioButtonField;
use crate::form_field_signature::PdfFormSignatureField;
use crate::form_field_text::PdfFormTextField;
use crate::form_field_unknown::PdfFormUnknownField;
use std::os::raw::c_int;
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub enum PdfFormFieldType {
Unknown = FPDF_FORMFIELD_UNKNOWN as isize,
PushButton = FPDF_FORMFIELD_PUSHBUTTON as isize,
Checkbox = FPDF_FORMFIELD_CHECKBOX as isize,
RadioButton = FPDF_FORMFIELD_RADIOBUTTON as isize,
ComboBox = FPDF_FORMFIELD_COMBOBOX as isize,
ListBox = FPDF_FORMFIELD_LISTBOX as isize,
Text = FPDF_FORMFIELD_TEXTFIELD as isize,
Signature = FPDF_FORMFIELD_SIGNATURE as isize,
}
impl PdfFormFieldType {
#[inline]
#[allow(dead_code)]
pub(crate) fn from_pdfium(value: c_int) -> Result<PdfFormFieldType, PdfiumError> {
match value as u32 {
FPDF_FORMFIELD_UNKNOWN => Ok(PdfFormFieldType::Unknown),
FPDF_FORMFIELD_PUSHBUTTON => Ok(PdfFormFieldType::PushButton),
FPDF_FORMFIELD_CHECKBOX => Ok(PdfFormFieldType::Checkbox),
FPDF_FORMFIELD_RADIOBUTTON => Ok(PdfFormFieldType::RadioButton),
FPDF_FORMFIELD_COMBOBOX => Ok(PdfFormFieldType::ComboBox),
FPDF_FORMFIELD_LISTBOX => Ok(PdfFormFieldType::ListBox),
FPDF_FORMFIELD_TEXTFIELD => Ok(PdfFormFieldType::Text),
FPDF_FORMFIELD_SIGNATURE => Ok(PdfFormFieldType::Signature),
_ => Err(PdfiumError::UnknownFormFieldType),
}
}
#[inline]
#[allow(dead_code)]
pub(crate) fn as_pdfium(&self) -> u32 {
match self {
PdfFormFieldType::Unknown => FPDF_FORMFIELD_UNKNOWN,
PdfFormFieldType::PushButton => FPDF_FORMFIELD_PUSHBUTTON,
PdfFormFieldType::Checkbox => FPDF_FORMFIELD_CHECKBOX,
PdfFormFieldType::RadioButton => FPDF_FORMFIELD_RADIOBUTTON,
PdfFormFieldType::ComboBox => FPDF_FORMFIELD_COMBOBOX,
PdfFormFieldType::ListBox => FPDF_FORMFIELD_LISTBOX,
PdfFormFieldType::Text => FPDF_FORMFIELD_TEXTFIELD,
PdfFormFieldType::Signature => FPDF_FORMFIELD_SIGNATURE,
}
}
}
pub enum PdfFormField<'a> {
PushButton(PdfFormPushButtonField<'a>),
Checkbox(PdfFormCheckboxField<'a>),
RadioButton(PdfFormRadioButtonField<'a>),
ComboBox(PdfFormComboBoxField<'a>),
ListBox(PdfFormListBoxField<'a>),
Signature(PdfFormSignatureField<'a>),
Text(PdfFormTextField<'a>),
Unknown(PdfFormUnknownField<'a>),
}
impl<'a> PdfFormField<'a> {
pub(crate) fn from_pdfium(
form_handle: FPDF_FORMHANDLE,
annotation_handle: FPDF_ANNOTATION,
bindings: &'a dyn PdfiumLibraryBindings,
) -> Option<Self> {
let result = bindings.FPDFAnnot_GetFormFieldType(form_handle, annotation_handle);
if result == -1 {
return None;
}
let form_field_type =
PdfFormFieldType::from_pdfium(result).unwrap_or(PdfFormFieldType::Unknown);
Some(match form_field_type {
PdfFormFieldType::PushButton => PdfFormField::PushButton(
PdfFormPushButtonField::from_pdfium(form_handle, annotation_handle, bindings),
),
PdfFormFieldType::Checkbox => PdfFormField::Checkbox(
PdfFormCheckboxField::from_pdfium(form_handle, annotation_handle, bindings),
),
PdfFormFieldType::RadioButton => PdfFormField::RadioButton(
PdfFormRadioButtonField::from_pdfium(form_handle, annotation_handle, bindings),
),
PdfFormFieldType::ComboBox => PdfFormField::ComboBox(
PdfFormComboBoxField::from_pdfium(form_handle, annotation_handle, bindings),
),
PdfFormFieldType::ListBox => PdfFormField::ListBox(PdfFormListBoxField::from_pdfium(
form_handle,
annotation_handle,
bindings,
)),
PdfFormFieldType::Text => PdfFormField::Text(PdfFormTextField::from_pdfium(
form_handle,
annotation_handle,
bindings,
)),
PdfFormFieldType::Signature => PdfFormField::Signature(
PdfFormSignatureField::from_pdfium(form_handle, annotation_handle, bindings),
),
_ => PdfFormField::Unknown(PdfFormUnknownField::from_pdfium(
form_handle,
annotation_handle,
bindings,
)),
})
}
#[inline]
pub(crate) fn unwrap_as_trait(&self) -> &dyn PdfFormFieldPrivate<'a> {
match self {
PdfFormField::PushButton(field) => field,
PdfFormField::Checkbox(field) => field,
PdfFormField::RadioButton(field) => field,
PdfFormField::ComboBox(field) => field,
PdfFormField::ListBox(field) => field,
PdfFormField::Signature(field) => field,
PdfFormField::Text(field) => field,
PdfFormField::Unknown(field) => field,
}
}
#[inline]
pub fn field_type(&self) -> PdfFormFieldType {
match self {
PdfFormField::PushButton(_) => PdfFormFieldType::PushButton,
PdfFormField::Checkbox(_) => PdfFormFieldType::Checkbox,
PdfFormField::RadioButton(_) => PdfFormFieldType::RadioButton,
PdfFormField::ComboBox(_) => PdfFormFieldType::ComboBox,
PdfFormField::ListBox(_) => PdfFormFieldType::ListBox,
PdfFormField::Signature(_) => PdfFormFieldType::Signature,
PdfFormField::Text(_) => PdfFormFieldType::Text,
PdfFormField::Unknown(_) => PdfFormFieldType::Unknown,
}
}
#[inline]
pub fn as_push_button_field(&self) -> Option<&PdfFormPushButtonField> {
match self {
PdfFormField::PushButton(field) => Some(field),
_ => None,
}
}
#[inline]
pub fn as_checkbox_field(&self) -> Option<&PdfFormCheckboxField> {
match self {
PdfFormField::Checkbox(field) => Some(field),
_ => None,
}
}
#[inline]
pub fn as_radio_button_field(&self) -> Option<&PdfFormRadioButtonField> {
match self {
PdfFormField::RadioButton(field) => Some(field),
_ => None,
}
}
#[inline]
pub fn as_combo_box_field(&self) -> Option<&PdfFormComboBoxField> {
match self {
PdfFormField::ComboBox(field) => Some(field),
_ => None,
}
}
#[inline]
pub fn as_list_box_field(&self) -> Option<&PdfFormListBoxField> {
match self {
PdfFormField::ListBox(field) => Some(field),
_ => None,
}
}
#[inline]
pub fn as_signature_field(&self) -> Option<&PdfFormSignatureField> {
match self {
PdfFormField::Signature(field) => Some(field),
_ => None,
}
}
#[inline]
pub fn as_text_field(&self) -> Option<&PdfFormTextField> {
match self {
PdfFormField::Text(field) => Some(field),
_ => None,
}
}
#[inline]
pub fn as_unknown_field(&self) -> Option<&PdfFormUnknownField> {
match self {
PdfFormField::Unknown(field) => Some(field),
_ => None,
}
}
}
pub trait PdfFormFieldCommon {
fn name(&self) -> Option<String>;
fn appearance_stream(&self) -> Option<String>;
fn appearance_mode_value(&self, appearance_mode: PdfAppearanceMode) -> Option<String>;
}
impl<'a, T> PdfFormFieldCommon for T
where
T: PdfFormFieldPrivate<'a>,
{
#[inline]
fn name(&self) -> Option<String> {
self.name_impl()
}
#[inline]
fn appearance_stream(&self) -> Option<String> {
self.appearance_stream_impl()
}
#[inline]
fn appearance_mode_value(&self, appearance_mode: PdfAppearanceMode) -> Option<String> {
self.appearance_mode_value_impl(appearance_mode)
}
}
impl<'a> PdfFormFieldPrivate<'a> for PdfFormField<'a> {
#[inline]
fn form_handle(&self) -> &FPDF_FORMHANDLE {
self.unwrap_as_trait().form_handle()
}
#[inline]
fn annotation_handle(&self) -> &FPDF_ANNOTATION {
self.unwrap_as_trait().annotation_handle()
}
#[inline]
fn bindings(&self) -> &dyn PdfiumLibraryBindings {
self.unwrap_as_trait().bindings()
}
}
impl<'a> From<PdfFormPushButtonField<'a>> for PdfFormField<'a> {
#[inline]
fn from(field: PdfFormPushButtonField<'a>) -> Self {
Self::PushButton(field)
}
}
impl<'a> From<PdfFormCheckboxField<'a>> for PdfFormField<'a> {
#[inline]
fn from(field: PdfFormCheckboxField<'a>) -> Self {
Self::Checkbox(field)
}
}
impl<'a> From<PdfFormRadioButtonField<'a>> for PdfFormField<'a> {
#[inline]
fn from(field: PdfFormRadioButtonField<'a>) -> Self {
Self::RadioButton(field)
}
}
impl<'a> From<PdfFormComboBoxField<'a>> for PdfFormField<'a> {
#[inline]
fn from(field: PdfFormComboBoxField<'a>) -> Self {
Self::ComboBox(field)
}
}
impl<'a> From<PdfFormListBoxField<'a>> for PdfFormField<'a> {
#[inline]
fn from(field: PdfFormListBoxField<'a>) -> Self {
Self::ListBox(field)
}
}
impl<'a> From<PdfFormTextField<'a>> for PdfFormField<'a> {
#[inline]
fn from(field: PdfFormTextField<'a>) -> Self {
Self::Text(field)
}
}
impl<'a> From<PdfFormSignatureField<'a>> for PdfFormField<'a> {
#[inline]
fn from(field: PdfFormSignatureField<'a>) -> Self {
Self::Signature(field)
}
}
impl<'a> From<PdfFormUnknownField<'a>> for PdfFormField<'a> {
#[inline]
fn from(field: PdfFormUnknownField<'a>) -> Self {
Self::Unknown(field)
}
}