1use crate::error::Result;
4use crate::forms::{
5 CheckBox, ComboBox, FieldOptions, FormField, ListBox, PushButton, RadioButton, TextField,
6 Widget,
7};
8use crate::objects::{Dictionary, Object, ObjectReference};
9use std::collections::HashMap;
10
11#[derive(Debug, Clone)]
13pub struct AcroForm {
14 pub fields: Vec<ObjectReference>,
16 pub need_appearances: bool,
18 pub sig_flags: Option<i32>,
20 pub co: Option<Vec<ObjectReference>>,
22 pub dr: Option<Dictionary>,
24 pub da: Option<String>,
26 pub q: Option<i32>,
28}
29
30impl AcroForm {
31 pub fn new() -> Self {
33 Self {
34 fields: Vec::new(),
35 need_appearances: true,
36 sig_flags: None,
37 co: None,
38 dr: None,
39 da: Some("/Helv 12 Tf 0 g".to_string()), q: None,
41 }
42 }
43
44 pub fn add_field(&mut self, field_ref: ObjectReference) {
46 self.fields.push(field_ref);
47 }
48
49 pub fn to_dict(&self) -> Dictionary {
51 let mut dict = Dictionary::new();
52
53 let fields: Vec<Object> = self.fields.iter().map(|r| Object::Reference(*r)).collect();
55 dict.set("Fields", Object::Array(fields));
56
57 dict.set("NeedAppearances", Object::Boolean(self.need_appearances));
59
60 if let Some(sig_flags) = self.sig_flags {
62 dict.set("SigFlags", Object::Integer(sig_flags as i64));
63 }
64
65 if let Some(ref co) = self.co {
67 let co_refs: Vec<Object> = co.iter().map(|r| Object::Reference(*r)).collect();
68 dict.set("CO", Object::Array(co_refs));
69 }
70
71 if let Some(ref dr) = self.dr {
73 dict.set("DR", Object::Dictionary(dr.clone()));
74 }
75
76 if let Some(ref da) = self.da {
78 dict.set("DA", Object::String(da.clone()));
79 }
80
81 if let Some(q) = self.q {
83 dict.set("Q", Object::Integer(q as i64));
84 }
85
86 dict
87 }
88}
89
90impl Default for AcroForm {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96#[derive(Debug, Clone)]
98pub struct FormData {
99 pub values: HashMap<String, String>,
101}
102
103impl FormData {
104 pub fn new() -> Self {
106 Self {
107 values: HashMap::new(),
108 }
109 }
110
111 pub fn set_value(&mut self, name: impl Into<String>, value: impl Into<String>) {
113 self.values.insert(name.into(), value.into());
114 }
115
116 pub fn get_value(&self, name: &str) -> Option<&str> {
118 self.values.get(name).map(|s| s.as_str())
119 }
120}
121
122impl Default for FormData {
123 fn default() -> Self {
124 Self::new()
125 }
126}
127
128#[derive(Debug)]
130pub struct FormManager {
131 fields: HashMap<String, FormField>,
133 acro_form: AcroForm,
135 next_field_id: u32,
137}
138
139impl FormManager {
140 pub fn new() -> Self {
142 Self {
143 fields: HashMap::new(),
144 acro_form: AcroForm::new(),
145 next_field_id: 1,
146 }
147 }
148
149 pub fn add_text_field(
151 &mut self,
152 field: TextField,
153 widget: Widget,
154 options: Option<FieldOptions>,
155 ) -> Result<ObjectReference> {
156 let mut field_dict = field.to_dict();
157
158 if let Some(opts) = options {
160 if opts.flags.to_flags() != 0 {
161 field_dict.set("Ff", Object::Integer(opts.flags.to_flags() as i64));
162 }
163 if let Some(da) = opts.default_appearance {
164 field_dict.set("DA", Object::String(da));
165 }
166 if let Some(q) = opts.quadding {
167 field_dict.set("Q", Object::Integer(q as i64));
168 }
169 }
170
171 let field_name = field.name.clone();
172 let mut form_field = FormField::new(field_dict);
173 form_field.add_widget(widget);
174
175 self.fields.insert(field_name, form_field);
176
177 let obj_ref = ObjectReference::new(self.next_field_id, 0);
179 self.next_field_id += 1;
180 self.acro_form.add_field(obj_ref);
181
182 Ok(obj_ref)
183 }
184
185 pub fn add_checkbox(
187 &mut self,
188 checkbox: CheckBox,
189 widget: Widget,
190 options: Option<FieldOptions>,
191 ) -> Result<ObjectReference> {
192 let mut field_dict = checkbox.to_dict();
193
194 if let Some(opts) = options {
196 if opts.flags.to_flags() != 0 {
197 field_dict.set("Ff", Object::Integer(opts.flags.to_flags() as i64));
198 }
199 }
200
201 let field_name = checkbox.name.clone();
202 let mut form_field = FormField::new(field_dict);
203 form_field.add_widget(widget);
204
205 self.fields.insert(field_name, form_field);
206
207 let obj_ref = ObjectReference::new(self.next_field_id, 0);
209 self.next_field_id += 1;
210 self.acro_form.add_field(obj_ref);
211
212 Ok(obj_ref)
213 }
214
215 pub fn add_push_button(
217 &mut self,
218 button: PushButton,
219 widget: Widget,
220 options: Option<FieldOptions>,
221 ) -> Result<ObjectReference> {
222 let mut field_dict = button.to_dict();
223
224 if let Some(opts) = options {
226 if opts.flags.to_flags() != 0 {
227 field_dict.set("Ff", Object::Integer(opts.flags.to_flags() as i64));
228 }
229 }
230
231 let field_name = button.name.clone();
232 let mut form_field = FormField::new(field_dict);
233 form_field.add_widget(widget);
234
235 self.fields.insert(field_name, form_field);
236
237 let obj_ref = ObjectReference::new(self.next_field_id, 0);
239 self.next_field_id += 1;
240 self.acro_form.add_field(obj_ref);
241
242 Ok(obj_ref)
243 }
244
245 pub fn add_radio_buttons(
247 &mut self,
248 radio: RadioButton,
249 widgets: Vec<Widget>,
250 options: Option<FieldOptions>,
251 ) -> Result<ObjectReference> {
252 let mut field_dict = radio.to_dict();
253
254 if let Some(opts) = options {
256 if opts.flags.to_flags() != 0 {
257 field_dict.set("Ff", Object::Integer(opts.flags.to_flags() as i64));
258 }
259 }
260
261 let field_name = radio.name.clone();
262 let mut form_field = FormField::new(field_dict);
263
264 for widget in widgets {
266 form_field.add_widget(widget);
267 }
268
269 self.fields.insert(field_name, form_field);
270
271 let obj_ref = ObjectReference::new(self.next_field_id, 0);
273 self.next_field_id += 1;
274 self.acro_form.add_field(obj_ref);
275
276 Ok(obj_ref)
277 }
278
279 pub fn add_list_box(
281 &mut self,
282 listbox: ListBox,
283 widget: Widget,
284 options: Option<FieldOptions>,
285 ) -> Result<ObjectReference> {
286 let mut field_dict = listbox.to_dict();
287
288 if let Some(opts) = options {
290 if opts.flags.to_flags() != 0 {
291 field_dict.set("Ff", Object::Integer(opts.flags.to_flags() as i64));
292 }
293 }
294
295 let field_name = listbox.name.clone();
296 let mut form_field = FormField::new(field_dict);
297 form_field.add_widget(widget);
298
299 self.fields.insert(field_name, form_field);
300
301 let obj_ref = ObjectReference::new(self.next_field_id, 0);
303 self.next_field_id += 1;
304 self.acro_form.add_field(obj_ref);
305
306 Ok(obj_ref)
307 }
308
309 pub fn add_combo_box(
311 &mut self,
312 combo: ComboBox,
313 widget: Widget,
314 options: Option<FieldOptions>,
315 ) -> Result<ObjectReference> {
316 let mut field_dict = combo.to_dict();
317
318 if let Some(opts) = options {
320 if opts.flags.to_flags() != 0 {
321 field_dict.set("Ff", Object::Integer(opts.flags.to_flags() as i64));
322 }
323 }
324
325 let field_name = combo.name.clone();
326 let mut form_field = FormField::new(field_dict);
327 form_field.add_widget(widget);
328
329 self.fields.insert(field_name, form_field);
330
331 let obj_ref = ObjectReference::new(self.next_field_id, 0);
333 self.next_field_id += 1;
334 self.acro_form.add_field(obj_ref);
335
336 Ok(obj_ref)
337 }
338
339 pub fn get_acro_form(&self) -> &AcroForm {
341 &self.acro_form
342 }
343
344 pub fn fields(&self) -> &HashMap<String, FormField> {
346 &self.fields
347 }
348
349 pub fn get_field(&self, name: &str) -> Option<&FormField> {
351 self.fields.get(name)
352 }
353
354 pub fn set_default_appearance(&mut self, da: impl Into<String>) {
356 self.acro_form.da = Some(da.into());
357 }
358
359 pub fn set_default_resources(&mut self, resources: Dictionary) {
361 self.acro_form.dr = Some(resources);
362 }
363}
364
365impl Default for FormManager {
366 fn default() -> Self {
367 Self::new()
368 }
369}
370
371#[cfg(test)]
372mod tests {
373 use super::*;
374 use crate::forms::FieldFlags;
375 use crate::geometry::{Point, Rectangle};
376
377 #[test]
378 fn test_acro_form() {
379 let mut acro_form = AcroForm::new();
380 acro_form.add_field(ObjectReference::new(1, 0));
381 acro_form.add_field(ObjectReference::new(2, 0));
382
383 let dict = acro_form.to_dict();
384 assert!(dict.get("Fields").is_some());
385 assert_eq!(dict.get("NeedAppearances"), Some(&Object::Boolean(true)));
386 assert!(dict.get("DA").is_some());
387 }
388
389 #[test]
390 fn test_form_data() {
391 let mut form_data = FormData::new();
392 form_data.set_value("name", "John Doe");
393 form_data.set_value("email", "john@example.com");
394
395 assert_eq!(form_data.get_value("name"), Some("John Doe"));
396 assert_eq!(form_data.get_value("email"), Some("john@example.com"));
397 assert_eq!(form_data.get_value("phone"), None);
398 }
399
400 #[test]
401 fn test_form_manager_text_field() {
402 let mut manager = FormManager::new();
403
404 let field = TextField::new("username").with_default_value("guest");
405 let widget = Widget::new(Rectangle::new(
406 Point::new(100.0, 100.0),
407 Point::new(300.0, 120.0),
408 ));
409
410 let obj_ref = manager.add_text_field(field, widget, None).unwrap();
411 assert_eq!(obj_ref.number(), 1);
412 assert!(manager.get_field("username").is_some());
413 }
414
415 #[test]
416 fn test_form_manager_checkbox() {
417 let mut manager = FormManager::new();
418
419 let checkbox = CheckBox::new("agree").checked();
420 let widget = Widget::new(Rectangle::new(
421 Point::new(100.0, 100.0),
422 Point::new(115.0, 115.0),
423 ));
424
425 let obj_ref = manager.add_checkbox(checkbox, widget, None).unwrap();
426 assert_eq!(obj_ref.number(), 1);
427 assert!(manager.get_field("agree").is_some());
428 }
429
430 #[test]
431 fn test_form_manager_multiple_fields() {
432 let mut manager = FormManager::new();
433
434 let text_field = TextField::new("name");
436 let text_widget = Widget::new(Rectangle::new(
437 Point::new(100.0, 200.0),
438 Point::new(300.0, 220.0),
439 ));
440 manager
441 .add_text_field(text_field, text_widget, None)
442 .unwrap();
443
444 let checkbox = CheckBox::new("subscribe");
446 let check_widget = Widget::new(Rectangle::new(
447 Point::new(100.0, 150.0),
448 Point::new(115.0, 165.0),
449 ));
450 manager.add_checkbox(checkbox, check_widget, None).unwrap();
451
452 assert_eq!(manager.fields().len(), 2);
453 assert!(manager.get_field("name").is_some());
454 assert!(manager.get_field("subscribe").is_some());
455 }
456
457 #[test]
458 fn test_acro_form_comprehensive() {
459 let mut acro_form = AcroForm::new();
460
461 assert_eq!(acro_form.fields.len(), 0);
463 assert!(acro_form.need_appearances);
464 assert!(acro_form.sig_flags.is_none());
465 assert!(acro_form.co.is_none());
466 assert!(acro_form.dr.is_none());
467 assert!(acro_form.da.is_some());
468 assert!(acro_form.q.is_none());
469
470 for i in 1..=5 {
472 acro_form.add_field(ObjectReference::new(i, 0));
473 }
474 assert_eq!(acro_form.fields.len(), 5);
475
476 acro_form.sig_flags = Some(3);
478 acro_form.co = Some(vec![ObjectReference::new(1, 0), ObjectReference::new(2, 0)]);
479 acro_form.q = Some(2); let mut dr = Dictionary::new();
482 dr.set("Font", Object::String("Helvetica".to_string()));
483 acro_form.dr = Some(dr);
484
485 let dict = acro_form.to_dict();
487
488 if let Some(Object::Array(fields)) = dict.get("Fields") {
490 assert_eq!(fields.len(), 5);
491 for (i, field) in fields.iter().enumerate() {
492 assert_eq!(
493 *field,
494 Object::Reference(ObjectReference::new((i + 1) as u32, 0))
495 );
496 }
497 } else {
498 panic!("Expected Fields array");
499 }
500
501 assert_eq!(dict.get("NeedAppearances"), Some(&Object::Boolean(true)));
503 assert_eq!(dict.get("SigFlags"), Some(&Object::Integer(3)));
504 assert_eq!(dict.get("Q"), Some(&Object::Integer(2)));
505 assert!(dict.get("CO").is_some());
506 assert!(dict.get("DR").is_some());
507 assert!(dict.get("DA").is_some());
508 }
509
510 #[test]
511 fn test_acro_form_default() {
512 let acro_form = AcroForm::default();
513 let default_form = AcroForm::new();
514
515 assert_eq!(acro_form.fields.len(), default_form.fields.len());
516 assert_eq!(acro_form.need_appearances, default_form.need_appearances);
517 assert_eq!(acro_form.sig_flags, default_form.sig_flags);
518 assert_eq!(acro_form.da, default_form.da);
519 }
520
521 #[test]
522 fn test_acro_form_debug_clone() {
523 let mut acro_form = AcroForm::new();
524 acro_form.add_field(ObjectReference::new(1, 0));
525 acro_form.sig_flags = Some(1);
526
527 let debug_str = format!("{:?}", acro_form);
528 assert!(debug_str.contains("AcroForm"));
529
530 let cloned = acro_form.clone();
531 assert_eq!(acro_form.fields, cloned.fields);
532 assert_eq!(acro_form.sig_flags, cloned.sig_flags);
533 assert_eq!(acro_form.need_appearances, cloned.need_appearances);
534 }
535
536 #[test]
537 fn test_form_data_comprehensive() {
538 let mut form_data = FormData::new();
539
540 assert_eq!(form_data.values.len(), 0);
542 assert_eq!(form_data.get_value("any"), None);
543
544 form_data.set_value("string_literal", "test");
546 form_data.set_value(String::from("string_owned"), "test2");
547 form_data.set_value("number", "42");
548 form_data.set_value("empty", "");
549 form_data.set_value("unicode", "café ñoño 你好");
550
551 assert_eq!(form_data.values.len(), 5);
552 assert_eq!(form_data.get_value("string_literal"), Some("test"));
553 assert_eq!(form_data.get_value("string_owned"), Some("test2"));
554 assert_eq!(form_data.get_value("number"), Some("42"));
555 assert_eq!(form_data.get_value("empty"), Some(""));
556 assert_eq!(form_data.get_value("unicode"), Some("café ñoño 你好"));
557
558 form_data.set_value("string_literal", "overwritten");
560 assert_eq!(form_data.get_value("string_literal"), Some("overwritten"));
561 assert_eq!(form_data.values.len(), 5); form_data.set_value("Test", "uppercase");
565 form_data.set_value("test", "lowercase");
566 assert_eq!(form_data.get_value("Test"), Some("uppercase"));
567 assert_eq!(form_data.get_value("test"), Some("lowercase"));
568 assert_eq!(form_data.values.len(), 7);
569 }
570
571 #[test]
572 fn test_form_data_edge_cases() {
573 let mut form_data = FormData::new();
574
575 form_data.set_value("", "empty_name");
577 assert_eq!(form_data.get_value(""), Some("empty_name"));
578
579 let long_name = "a".repeat(1000);
581 let long_value = "b".repeat(2000);
582 form_data.set_value(&long_name, &long_value);
583 assert_eq!(form_data.get_value(&long_name), Some(long_value.as_str()));
584
585 form_data.set_value("field/with/slashes", "value1");
587 form_data.set_value("field with spaces", "value2");
588 form_data.set_value("field.with.dots", "value3");
589 form_data.set_value("field-with-dashes", "value4");
590 form_data.set_value("field_with_underscores", "value5");
591
592 assert_eq!(form_data.get_value("field/with/slashes"), Some("value1"));
593 assert_eq!(form_data.get_value("field with spaces"), Some("value2"));
594 assert_eq!(form_data.get_value("field.with.dots"), Some("value3"));
595 assert_eq!(form_data.get_value("field-with-dashes"), Some("value4"));
596 assert_eq!(
597 form_data.get_value("field_with_underscores"),
598 Some("value5")
599 );
600 }
601
602 #[test]
603 fn test_form_data_default_debug_clone() {
604 let form_data = FormData::default();
605 assert_eq!(form_data.values.len(), 0);
606
607 let default_form = FormData::new();
608 assert_eq!(form_data.values.len(), default_form.values.len());
609
610 let debug_str = format!("{:?}", form_data);
611 assert!(debug_str.contains("FormData"));
612
613 let cloned = form_data.clone();
614 assert_eq!(form_data.values.len(), cloned.values.len());
615 }
616
617 #[test]
618 fn test_form_manager_comprehensive() {
619 let mut manager = FormManager::new();
620
621 assert_eq!(manager.field_count(), 0);
623 assert_eq!(manager.fields().len(), 0);
624 assert!(manager.get_field("nonexistent").is_none());
625
626 let acroform = manager.get_acro_form();
627 assert_eq!(acroform.fields.len(), 0);
628 assert!(acroform.need_appearances);
629
630 let field1 = TextField::new("field1");
632 let widget1 = Widget::new(Rectangle::new(
633 Point::new(0.0, 0.0),
634 Point::new(100.0, 20.0),
635 ));
636 let ref1 = manager.add_text_field(field1, widget1, None).unwrap();
637 assert_eq!(ref1.number(), 1);
638
639 let field2 = TextField::new("field2");
640 let widget2 = Widget::new(Rectangle::new(
641 Point::new(0.0, 30.0),
642 Point::new(100.0, 50.0),
643 ));
644 let ref2 = manager.add_text_field(field2, widget2, None).unwrap();
645 assert_eq!(ref2.number(), 2);
646
647 let field3 = TextField::new("field3");
648 let widget3 = Widget::new(Rectangle::new(
649 Point::new(0.0, 60.0),
650 Point::new(100.0, 80.0),
651 ));
652 let ref3 = manager.add_text_field(field3, widget3, None).unwrap();
653 assert_eq!(ref3.number(), 3);
654
655 assert_eq!(manager.field_count(), 3);
656 assert_eq!(manager.get_acro_form().fields.len(), 3);
657 }
658
659 #[test]
660 fn test_form_manager_push_button() {
661 let mut manager = FormManager::new();
662
663 let button = PushButton::new("submit").with_caption("Submit");
664 let widget = Widget::new(Rectangle::new(
665 Point::new(200.0, 100.0),
666 Point::new(280.0, 130.0),
667 ));
668
669 let obj_ref = manager.add_push_button(button, widget, None).unwrap();
670 assert_eq!(obj_ref.number(), 1);
671 assert!(manager.get_field("submit").is_some());
672
673 let form_field = manager.get_field("submit").unwrap();
674 let dict = &form_field.field_dict;
675 assert_eq!(dict.get("T"), Some(&Object::String("submit".to_string())));
676 assert_eq!(dict.get("FT"), Some(&Object::Name("Btn".to_string())));
677 }
678
679 #[test]
680 fn test_form_manager_radio_buttons() {
681 let mut manager = FormManager::new();
682
683 let radio = RadioButton::new("gender")
684 .add_option("M", "Male")
685 .add_option("F", "Female")
686 .with_selected(0);
687
688 let widgets = vec![
689 Widget::new(Rectangle::new(
690 Point::new(100.0, 100.0),
691 Point::new(115.0, 115.0),
692 )),
693 Widget::new(Rectangle::new(
694 Point::new(150.0, 100.0),
695 Point::new(165.0, 115.0),
696 )),
697 ];
698
699 let obj_ref = manager.add_radio_buttons(radio, widgets, None).unwrap();
700 assert_eq!(obj_ref.number(), 1);
701 assert!(manager.get_field("gender").is_some());
702
703 let form_field = manager.get_field("gender").unwrap();
704 assert_eq!(form_field.widgets.len(), 2);
705
706 let dict = &form_field.field_dict;
707 assert_eq!(dict.get("T"), Some(&Object::String("gender".to_string())));
708 assert_eq!(dict.get("V"), Some(&Object::Name("M".to_string())));
709 }
710
711 #[test]
712 fn test_form_manager_list_box() {
713 let mut manager = FormManager::new();
714
715 let listbox = ListBox::new("languages")
716 .add_option("en", "English")
717 .add_option("es", "Spanish")
718 .add_option("fr", "French")
719 .multi_select()
720 .with_selected(vec![0, 2]);
721
722 let widget = Widget::new(Rectangle::new(
723 Point::new(100.0, 100.0),
724 Point::new(200.0, 150.0),
725 ));
726
727 let obj_ref = manager.add_list_box(listbox, widget, None).unwrap();
728 assert_eq!(obj_ref.number(), 1);
729 assert!(manager.get_field("languages").is_some());
730
731 let form_field = manager.get_field("languages").unwrap();
732 let dict = &form_field.field_dict;
733 assert_eq!(
734 dict.get("T"),
735 Some(&Object::String("languages".to_string()))
736 );
737 assert_eq!(dict.get("FT"), Some(&Object::Name("Ch".to_string())));
738 }
739
740 #[test]
741 fn test_form_manager_combo_box() {
742 let mut manager = FormManager::new();
743
744 let combo = ComboBox::new("country")
745 .add_option("US", "United States")
746 .add_option("CA", "Canada")
747 .editable()
748 .with_value("US");
749
750 let widget = Widget::new(Rectangle::new(
751 Point::new(100.0, 100.0),
752 Point::new(300.0, 120.0),
753 ));
754
755 let obj_ref = manager.add_combo_box(combo, widget, None).unwrap();
756 assert_eq!(obj_ref.number(), 1);
757 assert!(manager.get_field("country").is_some());
758
759 let form_field = manager.get_field("country").unwrap();
760 let dict = &form_field.field_dict;
761 assert_eq!(dict.get("T"), Some(&Object::String("country".to_string())));
762 assert_eq!(dict.get("V"), Some(&Object::String("US".to_string())));
763 }
764
765 #[test]
766 fn test_form_manager_with_field_options() {
767 let mut manager = FormManager::new();
768
769 let options = FieldOptions {
770 flags: FieldFlags {
771 read_only: true,
772 required: true,
773 no_export: false,
774 },
775 default_appearance: Some("/Times-Roman 12 Tf 0 g".to_string()),
776 quadding: Some(1), };
778
779 let field = TextField::new("readonly_field").with_value("Read Only");
780 let widget = Widget::new(Rectangle::new(
781 Point::new(50.0, 50.0),
782 Point::new(250.0, 70.0),
783 ));
784
785 manager
786 .add_text_field(field, widget, Some(options))
787 .unwrap();
788
789 let form_field = manager.get_field("readonly_field").unwrap();
790 let dict = &form_field.field_dict;
791
792 if let Some(Object::Integer(flags)) = dict.get("Ff") {
794 assert_ne!(*flags & (1 << 0), 0); assert_ne!(*flags & (1 << 1), 0); assert_eq!(*flags & (1 << 2), 0); } else {
798 panic!("Expected Ff field");
799 }
800
801 assert_eq!(
803 dict.get("DA"),
804 Some(&Object::String("/Times-Roman 12 Tf 0 g".to_string()))
805 );
806 assert_eq!(dict.get("Q"), Some(&Object::Integer(1)));
807 }
808
809 #[test]
810 fn test_form_manager_appearance_resources() {
811 let mut manager = FormManager::new();
812
813 manager.set_default_appearance("/Courier 10 Tf 0.5 g");
815 let acroform = manager.get_acro_form();
816 assert_eq!(acroform.da, Some("/Courier 10 Tf 0.5 g".to_string()));
817
818 let mut resources = Dictionary::new();
820 let mut font_dict = Dictionary::new();
821 font_dict.set("F1", Object::String("Helvetica".to_string()));
822 font_dict.set("F2", Object::String("Times-Roman".to_string()));
823 resources.set("Font", Object::Dictionary(font_dict));
824
825 let mut color_dict = Dictionary::new();
826 color_dict.set(
827 "Red",
828 Object::Array(vec![
829 Object::Real(1.0),
830 Object::Real(0.0),
831 Object::Real(0.0),
832 ]),
833 );
834 resources.set("ColorSpace", Object::Dictionary(color_dict));
835
836 manager.set_default_resources(resources);
837
838 let acroform = manager.get_acro_form();
839 assert!(acroform.dr.is_some());
840
841 let dict = acroform.to_dict();
842 assert_eq!(
843 dict.get("DA"),
844 Some(&Object::String("/Courier 10 Tf 0.5 g".to_string()))
845 );
846
847 if let Some(Object::Dictionary(dr_dict)) = dict.get("DR") {
848 assert!(dr_dict.get("Font").is_some());
849 assert!(dr_dict.get("ColorSpace").is_some());
850 } else {
851 panic!("Expected DR dictionary");
852 }
853 }
854
855 #[test]
856 fn test_form_manager_mixed_field_types() {
857 let mut manager = FormManager::new();
858
859 let text_field = TextField::new("name").with_value("John");
861 let text_widget = Widget::new(Rectangle::new(
862 Point::new(10.0, 100.0),
863 Point::new(210.0, 120.0),
864 ));
865 manager
866 .add_text_field(text_field, text_widget, None)
867 .unwrap();
868
869 let checkbox = CheckBox::new("agree").checked();
870 let check_widget = Widget::new(Rectangle::new(
871 Point::new(10.0, 80.0),
872 Point::new(25.0, 95.0),
873 ));
874 manager.add_checkbox(checkbox, check_widget, None).unwrap();
875
876 let button = PushButton::new("submit");
877 let button_widget = Widget::new(Rectangle::new(
878 Point::new(10.0, 50.0),
879 Point::new(80.0, 75.0),
880 ));
881 manager
882 .add_push_button(button, button_widget, None)
883 .unwrap();
884
885 let radio = RadioButton::new("choice").add_option("A", "Option A");
886 let radio_widgets = vec![Widget::new(Rectangle::new(
887 Point::new(10.0, 30.0),
888 Point::new(25.0, 45.0),
889 ))];
890 manager
891 .add_radio_buttons(radio, radio_widgets, None)
892 .unwrap();
893
894 let listbox = ListBox::new("items").add_option("1", "Item 1");
895 let list_widget = Widget::new(Rectangle::new(
896 Point::new(10.0, 10.0),
897 Point::new(110.0, 25.0),
898 ));
899 manager.add_list_box(listbox, list_widget, None).unwrap();
900
901 let combo = ComboBox::new("selection").add_option("opt", "Option");
902 let combo_widget = Widget::new(Rectangle::new(
903 Point::new(120.0, 10.0),
904 Point::new(220.0, 25.0),
905 ));
906 manager.add_combo_box(combo, combo_widget, None).unwrap();
907
908 assert_eq!(manager.field_count(), 6);
910 assert!(manager.get_field("name").is_some());
911 assert!(manager.get_field("agree").is_some());
912 assert!(manager.get_field("submit").is_some());
913 assert!(manager.get_field("choice").is_some());
914 assert!(manager.get_field("items").is_some());
915 assert!(manager.get_field("selection").is_some());
916
917 let acroform = manager.get_acro_form();
919 assert_eq!(acroform.fields.len(), 6);
920
921 for (i, field_ref) in acroform.fields.iter().enumerate() {
923 assert_eq!(field_ref.number(), (i + 1) as u32);
924 assert_eq!(field_ref.generation(), 0);
925 }
926 }
927
928 #[test]
929 fn test_form_manager_debug_default() {
930 let manager = FormManager::new();
931 let debug_str = format!("{:?}", manager);
932 assert!(debug_str.contains("FormManager"));
933
934 let default_manager = FormManager::default();
935 assert_eq!(manager.field_count(), default_manager.field_count());
936 }
937
938 #[test]
939 fn test_form_manager_error_scenarios() {
940 let mut manager = FormManager::new();
941
942 let empty_field = TextField::new("");
944 let widget = Widget::new(Rectangle::new(
945 Point::new(0.0, 0.0),
946 Point::new(100.0, 20.0),
947 ));
948 let result = manager.add_text_field(empty_field, widget, None);
949 assert!(result.is_ok());
950 assert!(manager.get_field("").is_some());
951
952 let field1 = TextField::new("duplicate");
954 let widget1 = Widget::new(Rectangle::new(
955 Point::new(0.0, 0.0),
956 Point::new(100.0, 20.0),
957 ));
958 manager.add_text_field(field1, widget1, None).unwrap();
959
960 let field2 = TextField::new("duplicate");
961 let widget2 = Widget::new(Rectangle::new(
962 Point::new(0.0, 30.0),
963 Point::new(100.0, 50.0),
964 ));
965 manager.add_text_field(field2, widget2, None).unwrap();
966
967 assert_eq!(manager.field_count(), 2); assert!(manager.get_field("duplicate").is_some());
970 }
971
972 #[test]
973 fn test_acro_form_calculation_order() {
974 let mut acro_form = AcroForm::new();
975
976 let calc_order = vec![
978 ObjectReference::new(3, 0),
979 ObjectReference::new(1, 0),
980 ObjectReference::new(2, 0),
981 ];
982 acro_form.co = Some(calc_order.clone());
983
984 let dict = acro_form.to_dict();
985
986 if let Some(Object::Array(co_array)) = dict.get("CO") {
987 assert_eq!(co_array.len(), 3);
988 assert_eq!(co_array[0], Object::Reference(ObjectReference::new(3, 0)));
989 assert_eq!(co_array[1], Object::Reference(ObjectReference::new(1, 0)));
990 assert_eq!(co_array[2], Object::Reference(ObjectReference::new(2, 0)));
991 } else {
992 panic!("Expected CO array");
993 }
994 }
995
996 #[test]
997 fn test_acro_form_without_optional_fields() {
998 let acro_form = AcroForm::new();
999 let dict = acro_form.to_dict();
1000
1001 assert!(dict.get("SigFlags").is_none());
1003 assert!(dict.get("CO").is_none());
1004 assert!(dict.get("DR").is_none());
1005 assert!(dict.get("Q").is_none());
1006
1007 assert!(dict.get("Fields").is_some());
1009 assert!(dict.get("NeedAppearances").is_some());
1010 assert!(dict.get("DA").is_some());
1011 }
1012}
1013
1014impl FormManager {
1015 pub fn field_count(&self) -> usize {
1017 self.fields.len()
1018 }
1019}