RedNegativesTable.cs
//
// This code is part of Document Solutions for PDF demos.
// Copyright (c) MESCIUS inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Numerics;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Drawing;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Imaging;
using GrapeCity.Documents.Layout;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;

namespace DsPdfWeb.Demos
{
    // This example shows how to draw a simple table containing
    // some numeric data, with negative values displayed in red,
    // and with differently shaded odd and even rows,
    // using the GrapeCity.Documents.Drawing.TableRenderer and related classes.
    public class RedNegativesTable
    {
        public int CreatePDF(Stream stream)
        {
            var doc = new GcPdfDocument();
            var p = doc.NewPage();
            p.Size = new SizeF(p.Size.Height, p.Size.Width);
            var g = p.Graphics;

            DrawTable(g, g.CanvasSize.Width, g.CanvasSize.Height);

            // Save the PDF:
            doc.Save(stream);
            return doc.Pages.Count;
        }

        class ItemLine
        {
            public ItemLine(string text, double sales, double marginNumber, double marginPercent, int totalCustomers)
            {
                Text = text;
                Sales = sales;
                MarginNumber = marginNumber;
                MarginPercent = marginPercent;
                TotalCustomers = totalCustomers;
            }
            public string Text { get; }
            public double Sales { get; }
            public double MarginNumber { get; }
            public double MarginPercent { get; }
            public int TotalCustomers { get; }
        }

        static void DrawTable(GcGraphics g, float pageWidth, float pageHeight)
        {
            var items = new ItemLine[]
            {
                new ItemLine("Washers & Dryers", 1580, 196.82, 12.46, 247),
                new ItemLine("Projectors & Screens", 973, 211.26, 21.72, 382),
                new ItemLine("Refrigerators", 953, -350.57, -36.77, 331),
                new ItemLine("Laptops", 668, 181.17, 27.11, 301),
                new ItemLine("Coffee Machines", 476, -11.15, -2.34, 251),
                new ItemLine("Lamps", 471, 340.31, 72.28, 548),
                new ItemLine("Water Heaters", 443, 94.59, 21.34, 152),
                new ItemLine("Monitors", 424, -0.77, -0.18, 327),
                new ItemLine("Microwaves", 319, 14.30, 4.48, 375),
                new ItemLine("Desktops", 266, 23.22, 8.72, 184),
                new ItemLine("Air Conditioners", 253, 137.82, 54.54, 216),
                new ItemLine("Printers & Scanners", 219, 0.59, 0.27, 379),
                new ItemLine("Computers Accessories", 128, -18.23, -14.27, 654),
                new ItemLine("Fans", 83, -38.64, -46.35, 287)
            };

            var host = new LayoutHost();
            var view = host.CreateView(pageWidth, pageHeight);

            var rt = view.CreateRect();
            rt.AnchorTopLeft(null, 72, 72);

            var ta = new TableRenderer(g,
                rt, FixedTableSides.TopLeft,
                rowCount: items.Length + 1,
                columnCount: 5,
                gridLineColor: Color.Transparent,
                gridLineWidth: 0);

            var columns = ta.ColumnRects;
            columns[0].SetWidth(200);
            columns[1].SetWidth(120);
            columns[2].SetWidth(120);
            columns[3].SetWidth(120);
            columns[4].SetWidth(120);

            var fmt = new TextFormat
            {
                Font = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "consola.ttf")),
                ForeColor = Color.FromArgb(38, 38, 38),
                FontSize = 14,
                FontSizeInGraphicUnits = true,
            };
            var fmtSmall = new TextFormat(fmt)
            {
                FontSize = 11
            };

            var csCaption = new CellStyle
            {
                TextAlignment = TextAlignment.Trailing,
                ParagraphAlignment = ParagraphAlignment.Center,
                TextFormat = fmt,
                PaddingBottom = 10,
                PaddingRight = 4
            };
            ta.AddCell(new CellStyle(csCaption)
            {
                CustomDraw = (g, tc) =>
                {
                    float y = tc.Height * 0.5f;
                    float x = 10;
                    var pen = new GCDRAW.Pen(Color.DimGray, 1);
                    g.DrawLine(new PointF(x, y - 7), new PointF(x, y + 7), pen);
                    g.DrawLine(new PointF(x - 3, y + 3), new PointF(x, y + 7), pen);
                    g.DrawLine(new PointF(x + 3, y + 3), new PointF(x, y + 7), pen);
                },
                CreateTextLayout = (g, cs, data) =>
                {
                    var tl = g.CreateTextLayout();
                    tl.AppendLine("Sales", fmt);
                    tl.Append("in Thousands", fmtSmall);
                    return tl;
                }
            }, 0, 1, null);
            ta.AddCell(new CellStyle(csCaption)
            {
                CreateTextLayout = (g, cs, data) =>
                {
                    var tl = g.CreateTextLayout();
                    tl.AppendLine("Margin", fmt);
                    tl.Append("in Thousands", fmtSmall);
                    return tl;
                }
            }, 0, 2, null);
            ta.AddCell(csCaption, 0, 3, "Margin %");
            ta.AddCell(csCaption, 0, 4, "Total\nCustomers");

            var csName = new CellStyle
            {
                TextFormat = fmt,
                PaddingTopBottom = 5,
                PaddingLeft = 4
            };
            var csNum = new CellStyle
            {
                TextFormat = fmt,
                TextAlignment = TextAlignment.Trailing,
                PaddingTopBottom = 5,
                PaddingRight = 4
            };
            var csNumNegative = new CellStyle(csNum)
            {
                TextFormat = new TextFormat(fmt)
                {
                    ForeColor = Color.Red
                }
            };
            var csBand = new CellStyle
            {
                FillColor = Color.FromArgb(244, 241, 250),
                Background = true
            };

            var ci = new System.Globalization.CultureInfo("en-US");

            for (int i = 0; i < items.Length; i++)
            {
                var item = items[i];
                int rowIndex = i + 1;

                if ((i & 1) != 0)
                {
                    ta.AddCell(csBand, rowIndex, 0, 1, 5);
                }
                ta.AddCell(csName, rowIndex, 0, item.Text);
                ta.AddCell(csNum, rowIndex, 1, item.Sales.ToString("c0", ci));
                var v = item.MarginNumber;
                ta.AddCell(v >= 0.0 ? csNum : csNumNegative, rowIndex, 2, v.ToString("n2"));
                v = item.MarginPercent;
                ta.AddCell(v >= 0.0 ? csNum : csNumNegative, rowIndex, 3, v.ToString("n2"));
                ta.AddCell(csNum, rowIndex, 4, item.TotalCustomers.ToString("n0"));
            }

            ta.SetVerticalGridLineWidth(1, 2);
            ta.SetHorizontalGridLineWidth(1, 2);

            var pen = new GCDRAW.Pen(Color.FromArgb(159, 146, 213), 2)
            {
                DashStyle = DashStyle.Solid,
                LineCap = PenLineCap.Round
            };
            ta.AddCell(new CellStyle
            {
                Background = true,
                Borders = FrameBorders.LeftBorder | FrameBorders.TopBorder,
                Pen = pen,
                LinePaddingLeft = -2,
                LinePaddingTop = -2,
            }, 1, 1, items.Length, 4);

            ta.Render();
        }
    }
}