FormDataSubmit.cs
// 
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
// 
using System.Drawing;
using System.IO;
using System.Linq;
using System.Xml;
using System.Text;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Pdf.AcroForms;
using GrapeCity.Documents.Pdf.Actions;
using GrapeCity.Documents.Pdf.Annotations;
using GrapeCity.Documents.Text;

namespace DsPdfWeb.Demos
{
    // このサンプルは、サーバーに送信できる AcroForm PDF を作成します。
    // 次に、サーバーは(DsPdf v3 の新機能である)
    // GcPdfDocument.ImportFormDataFromCollection() メソッドを使用
    // して送信されたデータを同様の構造のPDFフォームを含むPDFにインポートし、
    // ユーザーが入力したデータで満たされたフォームをクライアントに送り返します。
    // 
    // 生成されたフォームフィールドのある PDF は、クライアントブラウザのデフォルトの
    // PDF ビューワに表示されることに注意してください。
    // 
    // このサンプルは現在廃止されている FormSubmitXml サンプルに似て
    // いますが、サーバー側は、クライアントフォームからデータが送信される方法に
    // 非常に類似したデータ構造を受け入れる新しい ImportFormDataFromCollection()
    // メソッドを使用するため、 そのデータを操作するためのコードは必要ありません。
    // FormSubmit サンプルも参照してください。
    public class FormDataSubmit
    {
        public int CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var page = doc.NewPage();

            var rc = Common.Util.AddNote(
                "フォームのフィールドに入力し、「送信」をクリックしてサーバーに送り返します。" +
                "サンプルサーバーは GcPdfDocument.ImportFormDataFromCollection()" +
                "メソッドを使用して、送信されたデータを別の互換性のあるPDFフォームにインポートし、" +
                "入力されたフォームをブラウザに送り返します。" +
                "記入されたフォームはブラウザのデフォルトのPDFビューワで開かれ、「送信」および" +
                "「リセット」ボタンがないことに注意してください。",
                page);

            var g = page.Graphics;
            var tf = new TextFormat() { Font = StandardFonts.Times, FontSize = 14 };
            var ip = new PointF(72, rc.Bottom + 36);
            float fldOffset = 72 * 2 + 46;
            float fldHeight = tf.FontSize * 1.2f;
            float dY = 32;

            // テキストフィールド。
            g.DrawString("First name:", tf, ip);
            var fldFirstName = new TextField() { Name = "FirstName", Value = "John" };
            fldFirstName.Widget.Page = page;
            fldFirstName.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
            fldFirstName.Widget.DefaultAppearance.Font = tf.Font;
            fldFirstName.Widget.DefaultAppearance.FontSize = tf.FontSize;
            doc.AcroForm.Fields.Add(fldFirstName);
            ip.Y += dY;

            // テキストフィールド。
            g.DrawString("Last name:", tf, ip);
            var fldLastName = new TextField() { Name = "LastName", Value = "Smith" };
            fldLastName.Widget.Page = page;
            fldLastName.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
            fldLastName.Widget.DefaultAppearance.Font = tf.Font;
            fldLastName.Widget.DefaultAppearance.FontSize = tf.FontSize;
            doc.AcroForm.Fields.Add(fldLastName);
            ip.Y += dY;

            // チェックボックス。
            g.DrawString("Subscribe to Mailing List:", tf, ip);
            var fldCheckbox = new CheckBoxField() { Name = "Subscribe", Checked = true };
            fldCheckbox.Widget.Page = page;
            fldCheckbox.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, fldHeight, fldHeight);
            doc.AcroForm.Fields.Add(fldCheckbox);
            ip.Y += dY;

            // 複数行テキストボックス。
            g.DrawString("Additional information:", tf, ip);
            var fldAdditionalInfo = new TextField() { Name = "AdditionalInfo", Multiline = true };
            fldAdditionalInfo.Widget.Page = page;
            fldAdditionalInfo.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight * 2);
            fldAdditionalInfo.Widget.DefaultAppearance.Font = tf.Font;
            fldAdditionalInfo.Widget.DefaultAppearance.FontSize = tf.FontSize;
            doc.AcroForm.Fields.Add(fldAdditionalInfo);
            ip.Y += dY * 2;

            // フォーム送信ボタン。
            var btnSubmit = new PushButtonField();
            btnSubmit.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72, fldHeight);
            btnSubmit.Widget.ButtonAppearance.Caption = "Submit";
            btnSubmit.Widget.Highlighting = HighlightingMode.Invert;
            btnSubmit.Widget.Page = page;

            // 送信先 URL。
            btnSubmit.Widget.Activate = new ActionSubmitForm("/Samples/HandleFormDataSubmit");
            doc.AcroForm.Fields.Add(btnSubmit);

            // フォームリセットボタン。
            var btnReset = new PushButtonField();
            btnReset.Widget.Rect = new RectangleF(ip.X + fldOffset + 72 * 1.5f, ip.Y, 72, fldHeight);
            btnReset.Widget.ButtonAppearance.Caption = "Reset";
            btnReset.Widget.Highlighting = HighlightingMode.Invert;
            btnReset.Widget.Page = page;
            btnReset.Widget.Activate = new ActionResetForm();
            doc.AcroForm.Fields.Add(btnReset);
            ip.Y += dY;

            // PDF ドキュメントを保存します。
            doc.Save(stream);
            return doc.Pages.Count;
        }

        // 
        // メモ:以下のコードは、このサンプルで準備されたフォームが送信されるときに Web サンプルブラウザ
        // コントローラーによって使用され、CreatePDF() メソッドによって直接呼び出されることはありません。
        // 

        // 
        // GcPdfDocument を作成し、AcroForm PDF をロードして、
        // GcPdfDocument.ImportFormDataFromCollection() メソッドを使用してデータを入力します。
        // 
        // このメソッドは、このサンプルで準備されたフォームがユーザーによって送信されると、
        // サンプルコントローラーによって呼び出されます。コントローラーメソッドは、受け取った
        // IFormCollection を配列またはキー値のペアに変換します。キーはフィールド名であり、
        // 値は文字列値のリストです。このメソッドを呼び出して、互換性のある ImportFormXML.pdf
        // PDF フォームに値をインポートします。そのフォームはクライアントに送り返されます。
        // 
        // このメソッドを呼び出すコントローラーコードは次のようになります:
        // 
        // public IActionResult HandleFormDataSubmit(IFormCollection fields)
        // {
        //   var values = fields.ToList();
        //   var fieldValues = values.Select(kvp_ => new KeyValuePair<string, IList<string>>(kvp_.Key, kvp_.Value.ToArray())).ToArray();
        //   var ms = Samples.FormDataSubmit.ImportFormData(fieldValues);
        //   var result = new FileStreamResult(ms, "application/pdf");
        //   return result;
        // }
        //     
        public static Stream ImportFormData(KeyValuePair<string, IList<string>>[] fieldValues)
        {
            var pdf = new GcPdfDocument();
            using var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "ImportFormFromCollection.pdf"));
                // 互換性のある空のフォームをロードします。
                pdf.Load(fs);
                // 送信されたデータをインポートします。
                pdf.ImportFormDataFromCollection(fieldValues);
                // PDF ドキュメントを保存します。
                var outMs = new MemoryStream();
                pdf.Save(outMs);
                outMs.Seek(0, SeekOrigin.Begin);
                return outMs;
        }
    }
}