use oxidize_pdf::forms::{
create_checkbox_widget, create_pushbutton_widget, create_radio_widget, ButtonWidget, CheckBox,
PushButton, RadioButton,
};
use oxidize_pdf::geometry::{Point, Rectangle};
use oxidize_pdf::graphics::Color;
use oxidize_pdf::text::Font;
use oxidize_pdf::{Document, Page, Result};
fn main() -> Result<()> {
println!("Creating button fields demo PDF...");
let mut doc = Document::new();
let mut page = Page::a4();
{
let gc = page.graphics();
gc.set_font(Font::HelveticaBold, 16.0);
gc.draw_text(
"Button Fields Demo - Complete Widget Integration",
50.0,
750.0,
)?;
gc.set_font(Font::HelveticaBold, 14.0);
gc.draw_text("Checkboxes:", 50.0, 700.0)?;
gc.set_font(Font::Helvetica, 12.0);
gc.draw_text("I agree to the terms and conditions", 70.0, 670.0)?;
gc.draw_text("Subscribe to newsletter", 70.0, 640.0)?;
gc.draw_text("Remember me", 70.0, 610.0)?;
gc.rectangle(50.0, 665.0, 15.0, 15.0).stroke();
gc.rectangle(50.0, 635.0, 15.0, 15.0).stroke();
gc.rectangle(50.0, 605.0, 15.0, 15.0).stroke();
gc.set_font(Font::HelveticaBold, 14.0);
gc.draw_text("Radio Buttons:", 50.0, 550.0)?;
gc.set_font(Font::Helvetica, 12.0);
gc.draw_text("Select your preferred contact method:", 50.0, 520.0)?;
gc.draw_text("Email", 70.0, 490.0)?;
gc.draw_text("Phone", 70.0, 460.0)?;
gc.draw_text("Postal Mail", 70.0, 430.0)?;
gc.circle(57.5, 492.5, 7.5).stroke();
gc.circle(57.5, 462.5, 7.5).stroke();
gc.circle(57.5, 432.5, 7.5).stroke();
gc.draw_text("Select size:", 50.0, 380.0)?;
let sizes = ["Small", "Medium", "Large", "Extra Large"];
for (i, size_text) in sizes.iter().enumerate() {
let x = 50.0 + (i as f64 * 100.0);
gc.draw_text(size_text, x + 20.0, 350.0)?;
gc.circle(x + 7.5, 352.5, 7.5).stroke();
}
gc.set_font(Font::HelveticaBold, 14.0);
gc.draw_text("Push Buttons:", 50.0, 300.0)?;
gc.rectangle(50.0, 250.0, 100.0, 30.0).stroke();
gc.rectangle(170.0, 250.0, 80.0, 30.0).stroke();
gc.rectangle(270.0, 250.0, 80.0, 30.0).stroke();
gc.rectangle(50.0, 200.0, 150.0, 30.0).stroke();
gc.set_font(Font::Helvetica, 10.0);
gc.draw_text(
"This PDF demonstrates button fields with complete widget annotations.",
50.0,
150.0,
)?;
gc.draw_text(
"All buttons have proper appearance streams and are ISO 32000-1 compliant.",
50.0,
135.0,
)?;
gc.draw_text(
"The fields are interactive and can be filled in PDF readers that support forms.",
50.0,
120.0,
)?;
gc.set_font(Font::HelveticaBold, 10.0);
gc.draw_text("ISO 32000-1 Compliance Features:", 50.0, 90.0)?;
gc.set_font(Font::Helvetica, 9.0);
gc.draw_text("• Widget annotations (ISO §12.5.6.19)", 70.0, 75.0)?;
gc.draw_text("• Button fields (ISO §12.7.4.2)", 70.0, 63.0)?;
gc.draw_text("• Appearance streams (ISO §12.5.5)", 70.0, 51.0)?;
gc.draw_text(
"• Field flags and characteristics (ISO §12.7.3)",
70.0,
39.0,
)?;
}
let terms_checkbox = CheckBox::new("terms").checked().with_export_value("Agreed");
let terms_widget = ButtonWidget::new(Rectangle::new(
Point::new(50.0, 665.0),
Point::new(65.0, 680.0),
))
.with_border_color(Color::rgb(0.2, 0.2, 0.2))
.with_background_color(Some(Color::rgb(1.0, 1.0, 1.0)));
let terms_annotation = create_checkbox_widget(&terms_checkbox, &terms_widget)?;
page.add_annotation(terms_annotation);
let newsletter_checkbox = CheckBox::new("newsletter").with_export_value("Subscribe");
let newsletter_widget = ButtonWidget::new(Rectangle::new(
Point::new(50.0, 635.0),
Point::new(65.0, 650.0),
))
.with_border_color(Color::rgb(0.2, 0.2, 0.2))
.with_background_color(Some(Color::rgb(1.0, 1.0, 1.0)));
let newsletter_annotation = create_checkbox_widget(&newsletter_checkbox, &newsletter_widget)?;
page.add_annotation(newsletter_annotation);
let remember_checkbox = CheckBox::new("remember").checked().with_export_value("Yes");
let remember_widget = ButtonWidget::new(Rectangle::new(
Point::new(50.0, 605.0),
Point::new(65.0, 620.0),
))
.with_border_color(Color::rgb(0.0, 0.5, 1.0))
.with_background_color(Some(Color::rgb(0.9, 0.95, 1.0)))
.with_text_color(Color::rgb(0.0, 0.3, 0.7));
let remember_annotation = create_checkbox_widget(&remember_checkbox, &remember_widget)?;
page.add_annotation(remember_annotation);
let contact_radio = RadioButton::new("contact")
.add_option("email", "Email")
.add_option("phone", "Phone")
.add_option("mail", "Postal Mail")
.with_selected(0);
let email_widget = ButtonWidget::new(Rectangle::new(
Point::new(50.0, 485.0),
Point::new(65.0, 500.0),
));
let email_annotation = create_radio_widget(&contact_radio, &email_widget, 0)?;
page.add_annotation(email_annotation);
let phone_widget = ButtonWidget::new(Rectangle::new(
Point::new(50.0, 455.0),
Point::new(65.0, 470.0),
));
let phone_annotation = create_radio_widget(&contact_radio, &phone_widget, 1)?;
page.add_annotation(phone_annotation);
let mail_widget = ButtonWidget::new(Rectangle::new(
Point::new(50.0, 425.0),
Point::new(65.0, 440.0),
));
let mail_annotation = create_radio_widget(&contact_radio, &mail_widget, 2)?;
page.add_annotation(mail_annotation);
let size_radio = RadioButton::new("size")
.add_option("S", "Small")
.add_option("M", "Medium")
.add_option("L", "Large")
.add_option("XL", "Extra Large")
.with_selected(1);
let size_colors = [
Color::rgb(0.8, 0.8, 1.0), Color::rgb(0.8, 1.0, 0.8), Color::rgb(1.0, 0.9, 0.8), Color::rgb(1.0, 0.8, 0.8), ];
for (i, bg_color) in size_colors.iter().enumerate() {
let x = 50.0 + (i as f64 * 100.0);
let size_widget = ButtonWidget::new(Rectangle::new(
Point::new(x, 345.0),
Point::new(x + 15.0, 360.0),
))
.with_background_color(Some(*bg_color));
let size_annotation = create_radio_widget(&size_radio, &size_widget, i)?;
page.add_annotation(size_annotation);
}
let submit_button = PushButton::new("submit").with_caption("Submit Form");
let submit_widget = ButtonWidget::new(Rectangle::new(
Point::new(50.0, 250.0),
Point::new(150.0, 280.0),
))
.with_border_width(2.0)
.with_border_color(Color::rgb(0.0, 0.5, 0.0))
.with_background_color(Some(Color::rgb(0.9, 1.0, 0.9)))
.with_text_color(Color::rgb(0.0, 0.4, 0.0))
.with_font_size(14.0);
let submit_annotation = create_pushbutton_widget(&submit_button, &submit_widget)?;
page.add_annotation(submit_annotation);
let reset_button = PushButton::new("reset").with_caption("Reset");
let reset_widget = ButtonWidget::new(Rectangle::new(
Point::new(170.0, 250.0),
Point::new(250.0, 280.0),
))
.with_border_width(2.0)
.with_border_color(Color::rgb(0.7, 0.7, 0.7))
.with_background_color(Some(Color::rgb(0.95, 0.95, 0.95)))
.with_text_color(Color::rgb(0.3, 0.3, 0.3))
.with_font_size(14.0);
let reset_annotation = create_pushbutton_widget(&reset_button, &reset_widget)?;
page.add_annotation(reset_annotation);
let cancel_button = PushButton::new("cancel").with_caption("Cancel");
let cancel_widget = ButtonWidget::new(Rectangle::new(
Point::new(270.0, 250.0),
Point::new(350.0, 280.0),
))
.with_border_width(2.0)
.with_border_color(Color::rgb(0.7, 0.0, 0.0))
.with_background_color(Some(Color::rgb(1.0, 0.9, 0.9)))
.with_text_color(Color::rgb(0.6, 0.0, 0.0))
.with_font_size(14.0);
let cancel_annotation = create_pushbutton_widget(&cancel_button, &cancel_widget)?;
page.add_annotation(cancel_annotation);
let custom_button = PushButton::new("custom").with_caption("Custom Style");
let custom_widget = ButtonWidget::new(Rectangle::new(
Point::new(50.0, 200.0),
Point::new(200.0, 230.0),
))
.with_border_width(3.0)
.with_border_color(Color::rgb(0.5, 0.0, 0.5))
.with_background_color(Some(Color::rgb(0.95, 0.9, 1.0)))
.with_text_color(Color::rgb(0.4, 0.0, 0.4))
.with_font_size(16.0);
let custom_annotation = create_pushbutton_widget(&custom_button, &custom_widget)?;
page.add_annotation(custom_annotation);
doc.add_page(page);
let output_path = "examples/results/button_fields_demo.pdf";
doc.save(output_path)?;
println!("✅ Button fields demo PDF created successfully!");
println!("📄 Output: {}", output_path);
println!("Features demonstrated:");
println!(" - 3 checkboxes with different states and styles");
println!(" - 7 radio buttons in 2 groups with custom colors");
println!(" - 4 push buttons with various styles");
println!(" - Complete widget annotations with appearance streams");
println!(" - ISO 32000-1 compliant implementation");
Ok(())
}