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

namespace DsImagingWeb.Demos
{
    // This demo shows how to draw a table with slanted column headers,
    // so that long headers can be squeezed into narrow columns' headers.
    // The demo uses the GcGraphics.DrawSlantedText() method to draw the headers.
    // See also the DrawRotatedText_0 and DrawSlantedText_0 demos.
    public class SlantedTableHeaders
    {
        public GcBitmap GenerateImage(Size pixelSize, float dpi, bool opaque, string[] _ = null)
        {
            var bmp = new GcBitmap(pixelSize.Width, pixelSize.Height, opaque, dpi, dpi);
            using var g = bmp.CreateGraphics(Color.White);

            // This is just to better position the table in the resulting image:
            g.Transform = Matrix3x2.CreateScale(2) * Matrix3x2.CreateTranslation(g.Resolution, g.Resolution);

            var x = new float[] { 10, 70, 120, 170, 220, 270, 320, 370 };
            var y = new float[] { 10, 70, 90, 110, 130 };
            int lastX = x.Length - 1;
            int lastY = y.Length - 1;

            int angle = -50;
            float dx = (y[0] - y[1]) / (float)Math.Tan(Math.PI * angle / 180);

            using (var path = g.CreatePath())
            {
                path.BeginFigure(new PointF(x[1] + dx, y[0]));
                path.AddLine(new PointF(x[lastX] + dx, y[0]));
                path.AddLine(new PointF(x[lastX], y[1]));
                path.AddLine(new PointF(x[1], y[1]));
                path.EndFigure(FigureEnd.Closed);
                g.FillPath(path, Color.Bisque);
            }
            DrawLine(g, x[1] + dx, y[0], x[lastX] + dx, y[0]);
            for (int i = 1; i <= lastX; i++)
                DrawLine(g, x[i], y[1], x[i] + dx, y[0]);

            var arrH = new string[] { "January", "February", "March", "April", "May", "June" };
            for (int i = 1; i < lastX; i++)
                DrawSlantedText(g, angle, x[i], y[0], x[i + 1], y[1], arrH[i - 1]);

            for (int i = 1; i <= lastY; i++)
                DrawLine(g, x[0], y[i], x[lastX], y[i]);
            for (int i = 0; i <= lastX; i++)
                DrawLine(g, x[i], y[1], x[i], y[lastY]);

            var arr1 = new string[] { "Store 1", "83424", "13558", "2348", "6429", "7565", "2833" };
            var arr2 = new string[] { "Store 2", "53423", "3573", "32321", "16474", "97553", "8364" };
            var arr3 = new string[] { "Store 3", "3421", "83553", "2343", "6428", "77557", "8347" };

            bool bold = true;
            for (int i = 0; i < lastX; i++)
            {
                DrawText(g, y[1], x[i], x[i + 1], arr1[i], bold);
                DrawText(g, y[2], x[i], x[i + 1], arr2[i], bold);
                DrawText(g, y[3], x[i], x[i + 1], arr3[i], bold);
                bold = false;
            }
            return bmp;
        }

        static void DrawLine(GcGraphics g, float x1, float y1, float x2, float y2)
        {
            g.DrawLine(new PointF(x1, y1), new PointF(x2, y2), new GCDRAW::Pen(Color.Gray, 1));
        }

        static void DrawSlantedText(GcGraphics g, int angle, float x1, float y1, float x2, float y2, string s)
        {
            var tl = g.CreateTextLayout();
            tl.TextAlignment = TextAlignment.Center;
            tl.Append(s, new TextFormat
            {
                FontName = "Segoe UI",
                FontSize = 10,
                FontBold = true
            });
            var rc = new RectangleF(x1, y1, x2 - x1, y2 - y1);
            g.DrawSlantedText(tl, angle, false, rc, SlantedTextAlignment.CenterInsideOutside);
        }

        static void DrawText(GcGraphics g, float y1, float x1, float x2, string s, bool bold = false)
        {
            var tl = g.CreateTextLayout();
            tl.TextAlignment = bold ? TextAlignment.Leading : TextAlignment.Trailing;
            tl.MaxWidth = x2 - x1 - 6;
            tl.Append(s, new TextFormat
            {
                FontName = "Segoe UI",
                FontSize = 10,
                FontBold = bold
            });
            g.DrawTextLayout(tl, new PointF(x1 + 3, y1));
        }
    }
}