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

namespace GcPdfWeb.Samples.Basics
{
    // このサンプルは、GcPdf で異なるスタイルの番号付きリストを描画する方法を示します。
    // NumberedList も参照してください。
    public class NumberedList2
    {
        // サンプルで使用されているページレイアウト定数をカプセル化します。
        private struct Layout
        {
            // ページ外周の余白。
            public static float Margin => 72;
            // 項目番号を基準にしたリストオフセット。
            public static float ListOffset => 24;
            // リストレベルインデント。
            public static float ListIndent => 30;
        };

        // シンプルなツリータイプを定義します。
        private class Node
        {
            public Node(string text)
            {
                Text = text;
            }
            public string Text { get; }
            public List<Node> Children = new List<Node>();
        }

        // ノードのリストを番号付きリストとして描画します。
        private PointF RenderNodes(ref Page page, PointF pt, List<Node> nodes, int level)
        {
            TextLayout tlBullet = new TextLayout(72);
            tlBullet.DefaultFormat.FontName = "Yu Gothic";
            tlBullet.MarginLeft = Layout.ListIndent * level;

            TextLayout tlText = new TextLayout(72);
            tlText.DefaultFormat.FontName = "Yu Gothic";
            tlText.MarginLeft = Layout.ListOffset + Layout.ListIndent * level;

            for (int i = 0; i < nodes.Count; ++i)
            {
                var g = page.Graphics;
                // 項目テキストを準備します。
                tlText.Clear();
                tlText.Append(nodes[i].Text);
                tlText.PerformLayout(true);
                if (pt.Y + tlText.ContentHeight > page.Size.Height - Layout.Margin)
                {
                    page = page.Doc.NewPage();
                    g = page.Graphics;
                    pt.Y = Layout.Margin;
                }
                // 項目番号を準備します。
                tlBullet.Clear();
                tlBullet.Append(ItemIdxToString(i, level, tlBullet));
                tlBullet.PerformLayout(true);
                // 項目を描画します。
                g.DrawTextLayout(tlBullet, pt);
                g.DrawTextLayout(tlText, pt);
                // 挿入位置を拡張します。
                pt.Y += tlText.ContentHeight;
                // 子ノードを描画します。
                if (nodes[i].Children.Count > 0)
                    pt = RenderNodes(ref page, pt, nodes[i].Children, level + 1);
            }
            return pt;
        }

        // アラビア語 -> ラテン文字 -> ローマ数字のループで、
        // 項目インデックスを項目番号表現に変換します。
        // ローマ数字は右揃え、その他は左揃えです。
        private string ItemIdxToString(int itemIdx, int level, TextLayout tl)
        {
            switch (level % 3)
            {
                case 0:
                    tl.MarginLeft = Layout.ListIndent * level;
                    tl.MaxWidth = null;
                    tl.TextAlignment = TextAlignment.Leading;
                    return $"{itemIdx + 1}.";
                case 1:
                    tl.MarginLeft = Layout.ListIndent * level;
                    tl.MaxWidth = null;
                    tl.TextAlignment = TextAlignment.Leading;
                    return $"{(char)('a' + itemIdx)}.";
                case 2:
                    tl.MarginLeft = 0;
                    var font = tl.DefaultFormat.Font;
                    tl.MaxWidth = Layout.ListIndent * level + tl.DefaultFormat.FontSize;
                    tl.TextAlignment = TextAlignment.Trailing;
                    return $"{IntToRoman(itemIdx + 1)}.";
                default:
                    throw new Exception("Unexpected.");
            }
        }

        // http://dotnet-snippets.com/snippet/roman-numerals/667 より
        private string IntToRoman(int number)
        {
            StringBuilder result = new StringBuilder();
            int[] digitsValues = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 };
            string[] romanDigits = { "I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M" };
            while (number > 0)
            {
                for (int i = digitsValues.Count() - 1; i >= 0; i--)
                    if (number / digitsValues[i] >= 1)
                    {
                        number -= digitsValues[i];
                        result.Append(romanDigits[i].ToLower());
                        break;
                    }
            }
            return result.ToString();
        }

        // メインエントリポイントです。
        public void CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var page = doc.NewPage();
            RenderNodes(ref page, new PointF(Layout.Margin, Layout.Margin), _cities.Children, 0);
            // PDF ドキュメントを保存します。
            doc.Save(stream);
        }

        // サンプルツリーデータです。
        private Node _cities = new Node("政令指定都市")
        {
            Children = new List<Node>()
            {
                new Node("北海道・東北")
            {
                Children = new List<Node>()
                {
                    new Node("札幌市")
                    {
                        Children = new List<Node>()
                        {
                            new Node("札幌市中央区"),
                            new Node("札幌市北区"),
                            new Node("札幌市東区"),
                            new Node("札幌市白石区"),
                            new Node("札幌市豊平区"),
                            new Node("札幌市南区"),
                            new Node("札幌市西区"),
                            new Node("札幌市厚別区"),
                            new Node("札幌市手稲区"),
                            new Node("札幌市清田区")
                        },
                    },
                    new Node("仙台市")
                    {
                        Children = new List<Node>()
                        {
                            new Node("仙台市青葉区"),
                            new Node("仙台市宮城野区"),
                            new Node("仙台市若林区"),
                            new Node("仙台市太白区"),
                            new Node("仙台市泉区"),
                        },
                    },
                },
            },
                new Node("関東")
                {
                    Children = new List<Node>()
                    {
                        new Node("さいたま市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("さいたま市西区"),
                            new Node("さいたま市北区"),
                            new Node("さいたま市大宮区"),
                            new Node("さいたま市見沼区"),
                            new Node("さいたま市中央区"),
                            new Node("さいたま市桜区"),
                            new Node("さいたま市浦和区"),
                            new Node("さいたま市南区"),
                            new Node("さいたま市緑区"),
                            new Node("さいたま市岩槻区"),
                            },
                        },
                        new Node("千葉市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("千葉市中央区"),
                            new Node("千葉市花見川区"),
                            new Node("千葉市稲毛区"),
                            new Node("千葉市若葉区"),
                            new Node("千葉市緑区"),
                            new Node("千葉市美浜区"),
                            },
                        },
                        new Node("横浜市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("横浜市鶴見区"),
                            new Node("横浜市神奈川区"),
                            new Node("横浜市西区"),
                            new Node("横浜市中区"),
                            new Node("横浜市南区"),
                            new Node("横浜市保土ケ谷区"),
                            new Node("横浜市磯子区"),
                            new Node("横浜市金沢区"),
                            new Node("横浜市港北区"),
                            new Node("横浜市戸塚区"),
                            new Node("横浜市港南区"),
                            new Node("横浜市旭区"),
                            new Node("横浜市緑区"),
                            new Node("横浜市瀬谷区"),
                            new Node("横浜市栄区"),
                            new Node("横浜市泉区"),
                            new Node("横浜市青葉区"),
                            new Node("横浜市都筑区"),
                            },
                        },
                        new Node("川崎市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("川崎市川崎区"),
                            new Node("川崎市幸区"),
                            new Node("川崎市中原区"),
                            new Node("川崎市高津区"),
                            new Node("川崎市多摩区"),
                            new Node("川崎市宮前区"),
                            new Node("川崎市麻生区"),
                            },
                        },
                        new Node("相模原市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("相模原市緑区"),
                            new Node("相模原市中央区"),
                            new Node("相模原市南区"),
                            },
                        },
                },
            },
                new Node("甲信越")
                {
                Children = new List<Node>()
                            {
                        new Node("新潟市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("新潟市北区"),
                            new Node("新潟市東区"),
                            new Node("新潟市中央区"),
                            new Node("新潟市江南区"),
                            new Node("新潟市秋葉区"),
                            new Node("新潟市南区"),
                            new Node("新潟市西区"),
                            new Node("新潟市西蒲区"),
                            },
                        },
                        new Node("静岡市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("静岡市葵区"),
                            new Node("静岡市駿河区"),
                            new Node("静岡市清水区"),
                            },
                        },
                        new Node("浜松市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("浜松市中区"),
                            new Node("浜松市東区"),
                            new Node("浜松市西区"),
                            new Node("浜松市南区"),
                            new Node("浜松市北区"),
                            new Node("浜松市浜北区"),
                            new Node("浜松市天竜区"),
                            },
                        },
                },
            },
                new Node("中部・近畿")
                {
                    Children = new List<Node>()
                            {
                                new Node("名古屋市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("名古屋市千種区"),
                            new Node("名古屋市東区"),
                            new Node("名古屋市北区"),
                            new Node("名古屋市西区"),
                            new Node("名古屋市中村区"),
                            new Node("名古屋市中区"),
                            new Node("名古屋市昭和区"),
                            new Node("名古屋市瑞穂区"),
                            new Node("名古屋市熱田区"),
                            new Node("名古屋市中川区"),
                            new Node("名古屋市港区"),
                            new Node("名古屋市南区"),
                            new Node("名古屋市守山区"),
                            new Node("名古屋市緑区"),
                            new Node("名古屋市名東区"),
                            new Node("名古屋市天白区"),
                            },
                        },
                        new Node("京都市")
                        {
                            Children = new List<Node>()
                            {
                            new Node("京都市北区"),
                            new Node("京都市上京区"),
                            new Node("京都市左京区"),
                            new Node("京都市中京区"),
                            new Node("京都市東山区"),
                            new Node("京都市下京区"),
                            new Node("京都市南区"),
                            new Node("京都市右京区"),
                            new Node("京都市伏見区"),
                            new Node("京都市山科区"),
                            new Node("京都市西京区"),
                            },
                        },
                        new Node("大阪市")
                        {
                            Children = new List<Node>()
                            {
                                new Node("大阪市都島区"),
                                new Node("大阪市福島区"),
                                new Node("大阪市此花区"),
                                new Node("大阪市西区"),
                                new Node("大阪市港区"),
                                new Node("大阪市大正区"),
                                new Node("大阪市天王寺区"),
                                new Node("大阪市浪速区"),
                                new Node("大阪市西淀川区"),
                                new Node("大阪市東淀川区"),
                                new Node("大阪市東成区"),
                                new Node("大阪市生野区"),
                                new Node("大阪市旭区"),
                                new Node("大阪市城東区"),
                                new Node("大阪市阿倍野区"),
                                new Node("大阪市住吉区"),
                                new Node("大阪市東住吉区"),
                                new Node("大阪市西成区"),
                                new Node("大阪市淀川区"),
                                new Node("大阪市鶴見区"),
                                new Node("大阪市住之江区"),
                                new Node("大阪市平野区"),
                                new Node("大阪市北区"),
                                new Node("大阪市中央区"),
                            },
                        },
                        new Node("堺市")
                        {
                            Children = new List<Node>()
                            {
                                new Node("堺市堺区"),
                                new Node("堺市中区"),
                                new Node("堺市東区"),
                                new Node("堺市西区"),
                                new Node("堺市南区"),
                                new Node("堺市北区"),
                                new Node("堺市美原区"),
                            },
                        },
                        new Node("神戸市")
                        {
                            Children = new List<Node>()
                            {
                                new Node("神戸市東灘区"),
                                new Node("神戸市灘区"),
                                new Node("神戸市兵庫区"),
                                new Node("神戸市長田区"),
                                new Node("神戸市須磨区"),
                                new Node("神戸市垂水区"),
                                new Node("神戸市北区"),
                                new Node("神戸市中央区"),
                                new Node("神戸市西区"),
                            },
                        },
                },
            },
                new Node("中国・四国・九州")
                {
                    Children = new List<Node>()
                        {
                        new Node("岡山市")
                        {
                            Children = new List<Node>()
                            {
                                new Node("岡山市北区"),
                                new Node("岡山市中区"),
                                new Node("岡山市東区"),
                                new Node("岡山市南区"),
                            },
                        },
                        new Node("広島市")
                        {
                            Children = new List<Node>()
                            {
                                new Node("広島市中区"),
                                new Node("広島市東区"),
                                new Node("広島市南区"),
                                new Node("広島市西区"),
                                new Node("広島市安佐南区"),
                                new Node("広島市安佐北区"),
                                new Node("広島市安芸区"),
                                new Node("広島市佐伯区"),
                            },
                        },
                        new Node("北九州市")
                        {
                            Children = new List<Node>()
                            {
                                new Node("北九州市門司区"),
                                new Node("北九州市若松区"),
                                new Node("北九州市戸畑区"),
                                new Node("北九州市小倉北区"),
                                new Node("北九州市小倉南区"),
                                new Node("北九州市八幡東区"),
                                new Node("北九州市八幡西区"),
                            },
                        },
                        new Node("福岡市")
                        {
                            Children = new List<Node>()
                            {
                                new Node("福岡市東区"),
                                new Node("福岡市博多区"),
                                new Node("福岡市中央区"),
                                new Node("福岡市南区"),
                                new Node("福岡市西区"),
                                new Node("福岡市城南区"),
                                new Node("福岡市早良区"),
                            },
                        },
                        new Node("熊本市")
                        {
                            Children = new List<Node>()
                            {
                                new Node("熊本市中央区"),
                                new Node("熊本市東区"),
                                new Node("熊本市西区"),
                                new Node("熊本市南区"),
                                new Node("熊本市北区"),
                            },

                        },
                    },

        }
            },
        };

    }
}