diff --git a/forms/pdf_form_action.go b/forms/pdf_form_action.go new file mode 100644 index 00000000..a26aa37f --- /dev/null +++ b/forms/pdf_form_action.go @@ -0,0 +1,152 @@ +/* + * Create a new form with a submit and reset button. + * The example shows how to add a submit button and a reset button to a form. + * The submit button could be used to send the form data to a backend server, + * and the reset button would reset the form fields value. + * + * Run as: go run pdf_form_action.go + */ + +package main + +import ( + "log" + "os" + + "github.com/unidoc/unipdf/v3/annotator" + "github.com/unidoc/unipdf/v3/common/license" + "github.com/unidoc/unipdf/v3/contentstream/draw" + "github.com/unidoc/unipdf/v3/core" + "github.com/unidoc/unipdf/v3/creator" + "github.com/unidoc/unipdf/v3/model" +) + +func init() { + // Make sure to load your metered License API key prior to using the library. + // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io + err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`)) + if err != nil { + panic(err) + } +} + +func main() { + textFieldsDef := []struct { + Label string + Name string + Rect []float64 + }{ + {Label: "Full Name", Name: "full_name", Rect: []float64{123.97, 619.02, 343.99, 633.6}}, + {Label: "Address 1", Name: "address_line_1", Rect: []float64{123.97, 596.82, 343.99, 611.4}}, + {Label: "Address 2", Name: "address_line_2", Rect: []float64{123.97, 574.28, 343.99, 588.86}}, + } + + c := creator.New() + page := c.NewPage() + _, pageHeight, err := page.Size() + if err != nil { + log.Fatal(err) + } + + form := model.NewPdfAcroForm() + fields := core.MakeArray() + + // Create text fields and it's label + for _, fdef := range textFieldsDef { + opt := annotator.TextFieldOptions{} + textf, err := annotator.NewTextField(page, fdef.Name, fdef.Rect, opt) + if err != nil { + log.Fatal(err) + } + + *form.Fields = append(*form.Fields, textf.PdfField) + page.AddAnnotation(textf.Annotations[0].PdfAnnotation) + + y := pageHeight - fdef.Rect[1] + + p := c.NewParagraph(fdef.Label) + p.SetPos(fdef.Rect[0]-80, y-10) + err = c.Draw(p) + if err != nil { + log.Fatal(err) + } + + line := c.NewLine(fdef.Rect[0], y, fdef.Rect[2], y) + err = c.Draw(line) + if err != nil { + log.Fatal(err) + } + + fields.Append(textf.ToPdfObject()) + } + + err = addSubmitButton(page, form) + if err != nil { + log.Fatal(err) + } + + err = addResetButton(page, form, fields) + if err != nil { + log.Fatal(err) + } + + c.SetForms(form) + + err = c.WriteToFile("form_with_action_button.pdf") + if err != nil { + log.Fatal(err) + } +} + +// Add Submit button that will submit all fields value. +func addSubmitButton(page *model.PdfPage, form *model.PdfAcroForm) error { + optSubmit := annotator.FormSubmitActionOptions{ + Url: "https://unidoc.io", + Rectangle: draw.Rectangle{ + X: 400.0, + Y: 400.0, + Width: 50.0, + Height: 20.0, + FillColor: model.NewPdfColorDeviceRGB(0.0, 1.0, 0.0), + }, + Label: "Submit", + LabelColor: model.NewPdfColorDeviceRGB(1.0, 0.0, 0.0), + } + + btnSubmitField, err := annotator.NewFormSubmitButtonField(page, optSubmit) + if err != nil { + return err + } + + *form.Fields = append(*form.Fields, btnSubmitField.PdfField) + page.AddAnnotation(btnSubmitField.Annotations[0].PdfAnnotation) + + return nil +} + +// Add Reset button that would reset the specified fields to it's default value. +func addResetButton(page *model.PdfPage, form *model.PdfAcroForm, fields *core.PdfObjectArray) error { + optReset := annotator.FormResetActionOptions{ + Rectangle: draw.Rectangle{ + X: 100.0, + Y: 400.0, + Width: 50.0, + Height: 20.0, + FillColor: model.NewPdfColorDeviceGray(0.5), + }, + Label: "Reset", + LabelColor: model.NewPdfColorDeviceGray(1.0), + Fields: fields, + } + + btnResetField, err := annotator.NewFormResetButtonField(page, optReset) + if err != nil { + return err + } + + // Add widget to existing form. + *form.Fields = append(*form.Fields, btnResetField.PdfField) + page.AddAnnotation(btnResetField.Annotations[0].PdfAnnotation) + + return nil +} diff --git a/forms/pdf_form_add.go b/forms/pdf_form_add.go index 0fa9506d..a38dd4f4 100644 --- a/forms/pdf_form_add.go +++ b/forms/pdf_form_add.go @@ -14,8 +14,6 @@ import ( "github.com/unidoc/unipdf/v3/annotator" "github.com/unidoc/unipdf/v3/common/license" - "github.com/unidoc/unipdf/v3/contentstream" - "github.com/unidoc/unipdf/v3/core" "github.com/unidoc/unipdf/v3/model" ) @@ -163,86 +161,5 @@ func createForm(page *model.PdfPage) *model.PdfAcroForm { page.AddAnnotation(comboboxf.Annotations[0].PdfAnnotation) } - addSubmitButton(page, form) - return form } - -func addSubmitButton(page *model.PdfPage, form *model.PdfAcroForm) error { - submitUrl := "https://url-to-backend" - btnX := 400.0 - btnY := 400.0 - btnW := 50.0 - btnH := 20.0 - - // Construct a new pdf field for the submit button. - field := model.NewPdfField() - btnField := &model.PdfFieldButton{} - field.SetContext(btnField) - btnField.PdfField = field - - btnField.T = core.MakeString("btnSubmit") - btnField.SetType(model.ButtonTypePush) - - btnField.V = core.MakeName("Off") - btnField.TU = core.MakeString("submit") - - // Define an Action that will be executed when the button is clicked. - submitAction := model.NewPdfActionSubmitForm() - submitAction.Flags = core.MakeInteger(5) // This will submit all fields value using HTTP Form format. - submitAction.F = model.NewPdfFilespec() - submitAction.F.F = core.MakeString(submitUrl) - submitAction.F.FS = core.MakeName("URL") - - widgetText := core.MakeDict() - widgetText.Set(*core.MakeName("CA"), core.MakeString("Submit")) - - fontData, err := model.NewStandard14Font("Helvetica") - if err != nil { - return err - } - fontName := core.MakeName("Helv") - - // Construct button. - cc := contentstream.NewContentCreator() - cc.Add_q() - cc.Add_g(0.7) - cc.Add_re(0, 0, btnW, btnH) - cc.Add_f() - cc.Add_Q() - cc.Add_q() - cc.Add_BT() - cc.Add_Tf(*fontName, 10) - cc.Add_g(0) - cc.Add_Td(5, 5) - cc.Add_Tj(*core.MakeString("Submit")) - cc.Add_ET() - cc.Add_Q() - - xform := model.NewXObjectForm() - xform.SetContentStream(cc.Bytes(), core.NewRawEncoder()) - xform.BBox = core.MakeArrayFromFloats([]float64{0, 0, btnW, btnH}) - xform.Resources = model.NewPdfPageResources() - xform.Resources.SetFontByName(*fontName, fontData.ToPdfObject()) - - appearance := core.MakeDict() - appearance.Set("N", xform.ToPdfObject()) - - // Construct a widget annotation. - btnWidget := model.NewPdfAnnotationWidget() - btnWidget.Rect = core.MakeArrayFromFloats([]float64{btnX, btnY, btnX + btnW, btnY + btnH}) - btnWidget.P = page.ToPdfObject() - btnWidget.F = core.MakeInteger(4) - btnWidget.Parent = btnField.ToPdfObject() - btnWidget.A = submitAction.ToPdfObject() - btnWidget.MK = widgetText - btnWidget.AP = appearance - - btnField.Annotations = append(btnField.Annotations, btnWidget) - - // Add widget to existing form. - *form.Fields = append(*form.Fields, btnField.PdfField) - page.AddAnnotation(btnField.Annotations[0].PdfAnnotation) - - return nil -}