ViewerPdfInputTypes.cs
// 
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// Copyright (c) GrapeCity inc. All rights reserved.
// 
using System.IO;
using System.Drawing;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Pdf.AcroForms;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf.Spec;

namespace GcPdfWeb.Samples
{

    // このサンプルでは、PDF ビューワのフォームフィーラーを使用して、GcPdfやGcExcelにて
    // 作成されたPDFフォーム(カスタム入力フィールドを含む)を読み込む方法を示しています。

    // このセクションのサンプルでは、クライアント上のPDF ビューワが、サーバー上で
    // 動作するGcPdfに接続している場合に、PDF ビューワで使用できるPDFファイルの編集機能
    // (注釈やフォームフィールドの追加や編集、ページの回転など)を主に紹介しています。
    // 
    // ビューワの編集機能を有効にするためには、supportApiプロパティに、ビューワにて
    // 使用が想定される編集機能をサポートするAPIのすべてまたは一部を実装したサーバのURLを
    // 設定する必要があります。このGcPdfデモサイトでは、それらのAPIを提供しており、
    // このサンプルでPDF ビューワを開いた際に編集のデモを行うことができます。
    // このサンプルをダウンロードすると、サンプルPDFを生成する.NET Coreコンソール
    // アプリプロジェクトに加えて、必要なAPIを提供するASP.NET Coreプロジェクトも
    // ダウンロードしたzipに含まれています(ダウンロードしたzipのGcPdfViewerWeb
    // フォルダ内にあります)。具体的には、APIを実装し、特別なコントローラを介して
    // そのAPIを提供するプロジェクトが含まれています。実際にこのGcPdfのデモサイトで
    // 使用されているものと同じコントローラで、どのASP.NET Coreサイトでも
    // ビューワの編集機能を有効にすることができます。
    // 
    // 詳細については、サンプルからダウンロードしたzipにある以下のファイルをご参照ください。
    // - GcPdfViewerWeb\SupportApiDemo: ASP.NET Coreのサンプルwebサイトです。
    // - GcPdfViewerWeb\SupportApiDemo.sln: サンプルwebサイトを実行するためのソリューションです。
    // - GcPdfViewerWeb\SupportApi: 実装済みのSupportAPIです(どのサイトでもご使用いただけます)。
    // - GcPdfViewerWeb\SupportApi\Controllers\GcPdfViewerController.cs: SupportAPIのコントローラです。
    // 
    // このセクションのサンプルは、現時点ではC#でしかご利用いただけませんのでご注意ください。
    // 
    public class ViewerPdfInputTypes
    {
        public void CreatePDF(Stream stream)
        {
            CreateFormFieldsPDF(stream);
        }

        private Dictionary<string, KeyValuePair<string, object>[]> GetSampleGcPropTextFields()
        {
            return new Dictionary<string, KeyValuePair<string, object>[]>() {
                {
                    "日付", new KeyValuePair<string, object>[]{
                    new KeyValuePair<string, object>("type", "date"),
                    new KeyValuePair<string, object>("placeholder", "日付を入力してください")}
                },
                {
                    "日付(読み取り専用)", new KeyValuePair<string, object>[]{
                        new KeyValuePair<string, object>("type", "date"),
                        new KeyValuePair<string, object>("defaultvalue", "2018-01-01"),
                        new KeyValuePair<string, object>("readonly", true)
                    }
                },
                {
                    "時間", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "time") }
                },
                {
                    "時間(デフォルト値あり)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "time"),
                    new KeyValuePair<string, object>("defaultvalue", "18:00") }
                },
                {
                    "電話番号", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "tel"),
                    new KeyValuePair<string, object>("validateoninput", true) }
                },
                {
                    "電話番号(パターン指定)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "tel"),
                    new KeyValuePair<string, object>("pattern", @"^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$"),
                    new KeyValuePair<string, object>("validateoninput", true),
                    new KeyValuePair<string, object>("validationmessage", "有効な形式:" +
                        "(123) 456-7890" +
                        "(123)456-7890" +
                        "123-456-7890" +
                        "123.456.7890" +
                        "1234567890" +
                        "+31636363634" +
                        "075-63546725") }
                },
                {
                    "電子メール", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "email"),
                    new KeyValuePair<string, object>("autocomplete", "email"),
                    new KeyValuePair<string, object>("validateoninput", true) }
                },
                {
                    "電子メール(複数)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "email"),
                    new KeyValuePair<string, object>("autocomplete", "email"),
                    new KeyValuePair<string, object>("validateoninput", true),
                    new KeyValuePair<string, object>("multiple", true) }
                },
                {
                    "電子メール(パターン指定)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "email"),
                    new KeyValuePair<string, object>("pattern", @"\S+@example\.com"),
                    new KeyValuePair<string, object>("autocomplete", "email"),
                    new KeyValuePair<string, object>("placeholder", "有効なドメイン @example.com."),
                    new KeyValuePair<string, object>("validationmessage", "test@example.com."),
                    new KeyValuePair<string, object>("validateoninput", true),
                    new KeyValuePair<string, object>("multiple", true) }
                },
                {
                    "URL", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "url"),
                    new KeyValuePair<string, object>("autocomplete", "url"),
                    new KeyValuePair<string, object>("validateoninput", true) }
                },
                {
                    "パスワード", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "password"),
                    new KeyValuePair<string, object>("autocomplete", "new-password"),
                    new KeyValuePair<string, object>("validateoninput", true)  }
                },
                {
                    "パスワード(最小文字数指定)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "password"),
                    new KeyValuePair<string, object>("placeholder", "最小文字数=8"),
                    new KeyValuePair<string, object>("minlength", 8),
                    new KeyValuePair<string, object>("validateoninput", true),
                    new KeyValuePair<string, object>("autocomplete", "new-password")} },
                {
                    "パスワード(最大文字数指定)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "password"),
                    new KeyValuePair<string, object>("placeholder", "最大文字数=4"),
                    new KeyValuePair<string, object>("maxlength", 4),
                    new KeyValuePair<string, object>("validateoninput", true),
                    new KeyValuePair<string, object>("autocomplete", "off")} },
                {
                    "パスワード(パターン指定)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "password"),
                    new KeyValuePair<string, object>("placeholder", "4~8文字"),
                    new KeyValuePair<string, object>("pattern", @"^(?=.*\d).{4,8}$"),
                    new KeyValuePair<string, object>("validateoninput", true),
                    new KeyValuePair<string, object>("validationmessage",  "パスワードは4~8文字で入力してください"),
                    new KeyValuePair<string, object>("autocomplete", "off")}
                },
                {
                    "パスワード(PIN)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "password"),
                    new KeyValuePair<string, object>("title", "PINを入力してください"),
                    new KeyValuePair<string, object>("placeholder", "PIN"),
                    new KeyValuePair<string, object>("pattern", @"^[0-9]{3,3}$"),
                    new KeyValuePair<string, object>("maxlength", 3),
                    new KeyValuePair<string, object>("validateoninput", true),
                    new KeyValuePair<string, object>("validationmessage", "PINは3桁の数字で入力してください"),
                    new KeyValuePair<string, object>("autocomplete", "one-time-code")}
                },
                {
                    "テキスト(オートフォーカス)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "text"),
                    new KeyValuePair<string, object>("autofocus", "true") }
                },
                {
                    "テキスト(必須)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "text"),
                    new KeyValuePair<string, object>("required", true),
                    new KeyValuePair<string, object>("validateoninput", true) }
                },
                {
                    "テキスト(スペルチェックあり)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "text"),
                    new KeyValuePair<string, object>("defaultvalue", "mistaake"),
                    new KeyValuePair<string, object>("spellcheck", "true")}
                },
                {
                    "テキスト(スペルチェックなし)", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "text"),
                    new KeyValuePair<string, object>("defaultvalue", "mistaake"),
                    new KeyValuePair<string, object>("spellcheck", "false")}
                },
                {
                    "月", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "month") }
                },
                {
                    "週", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "week") }
                },
                {
                    "最小/最大の数", new KeyValuePair<string, object>[] {
                    new KeyValuePair<string, object>("type", "number") ,
                    new KeyValuePair<string, object>("placeholder", "数字"),
                    new KeyValuePair<string, object>("required", true),
                    new KeyValuePair<string, object>("title", "1から100までの数字を入力してください"),
                    new KeyValuePair<string, object>("min", 1),
                    new KeyValuePair<string, object>("max", 100),
                    new KeyValuePair<string, object>("validateoninput", true),
                    new KeyValuePair<string, object>("validationmessage", "入力できる数字は1から100までです") }
                },
                {
                    "検索", new KeyValuePair<string, object>[] { new KeyValuePair<string, object>("type", "search") }
                },
                {
                    "範囲", new KeyValuePair<string, object>[] { new KeyValuePair<string, object>("type", "range"),
                        new KeyValuePair<string, object>("title", "1から100までの数字を選択してください"),
                        new KeyValuePair<string, object>("defaultvalue", 50),
                        new KeyValuePair<string, object>("min", 1),
                        new KeyValuePair<string, object>("max", 100)}
                },
                {
                "色", new KeyValuePair<string, object>[] { new KeyValuePair<string, object>("type", "color"),
                    new KeyValuePair<string, object>("title", "色を選択してください"),
                    new KeyValuePair<string, object>("defaultvalue", 50),
                    new KeyValuePair<string, object>("min", 1),
                    new KeyValuePair<string, object>("max", 100)}
                }
            };
        }

        public void CreateFormFieldsPDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var page = doc.NewPage();
            var g = page.Graphics;
            TextFormat tf = new TextFormat();
            tf.Font = Common.Util.getFont();
            tf.FontSize = 14;

            PointF ip = new PointF(72, 72);
            float fldOffset = 72f * 3f;
            float fldHeight = tf.FontSize * 1.6f;
            float dY = 28;

            // サンプルフィールドを追加
            int orderindex = 1;
            var sampleGcPropTextFields = GetSampleGcPropTextFields();
            foreach (var data in sampleGcPropTextFields)
            {
                string fieldName = data.Key;

                g.DrawString($"{fieldName}:", tf, ip);

                TextField field = new TextField();
                // GcPropsディクショナリに追加
                KeyValuePair<string, object>[] gcProps = data.Value;
                foreach(var gcProp in gcProps)
                {
                    field.GcProps[gcProp.Key] = gcProp.Value is string ? new PdfString((string)gcProp.Value) : gcProp.Value;
                }
                field.GcProps["orderindex"] = orderindex;
                field.Name = fieldName;
                field.Widget.Page = page;
                field.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
                field.Widget.TextFormat.Font = tf.Font;
                field.Widget.TextFormat.FontSize = tf.FontSize;
                doc.AcroForm.Fields.Add(field);
                ip.Y += dY;
                orderindex++;
            }

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

        // SupportApiDemoにてPDF ビューワの初期化に使用されます。
        public static GcPdfViewerSupportApiDemo.Models.PdfViewerOptions PdfViewerOptions
        {
            get => new GcPdfViewerSupportApiDemo.Models.PdfViewerOptions(
                GcPdfViewerSupportApiDemo.Models.PdfViewerOptions.Options.SupportApi ,
                viewerTools: new string[] { "open", "save", "form-filler", "$navigation", "$split", "text-selection", "pan", "$zoom", "print", "rotate", "hide-annotations", "doc-properties", "about" });
        }

        public const string JS_CODE = @"
function createPdfViewer(selector, baseOptions) {
    var options = baseOptions || {};    
    options.formFiller = { title: 'カスタム入力フィールドに記入'}
    var viewer = new GcPdfViewer(selector, options);    
    viewer.addDefaultPanels();
    // ツールバーのボタンを設定
    viewer.toolbarLayout.viewer = { 
        default: ['open', 'save', 'form-filler', '$navigation', '$split', 'text-selection', 'pan', '$zoom', 'print', 'rotate', 'hide-annotations', 'doc-properties', 'about'], 
        mobile: ['open', 'save', 'form-filler', '$navigation', '$split', 'text-selection', 'pan', '$zoom', 'print', 'rotate', 'hide-annotations', 'doc-properties', 'about'], 
        fullscreen: ['$fullscreen', 'open', 'save', 'form-filler', '$navigation', '$split', 'text-selection', 'pan', '$zoom', 'print', 'rotate', 'hide-annotations', 'doc-properties', 'about']
    };
    viewer.applyToolbarLayout();
    viewer.applyOptions();
    return viewer;
}
";
    }
}