LongTable.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.Linq;
- using System.Collections.Generic;
- using GrapeCity.Documents.Pdf;
- using GrapeCity.Documents.Text;
- using GrapeCity.Documents.Layout;
- using GrapeCity.Documents.Layout.Composition;
- using GCTEXT = GrapeCity.Documents.Text;
- using GCDRAW = GrapeCity.Documents.Drawing;
-
- namespace DsPdfWeb.Demos
- {
- // This demo creates a table with variable row height and spanning many pages,
- // using classes from the GrapeCity.Documents.Layout.Composition namespace.
- public class LongTable
- {
- string[] _headers;
- TextFormat _thFormat;
- TextFormat _tdFormat;
- float _resolution;
-
- readonly List<LayoutRect> _rows = new();
- readonly List<LayoutRect> _columns = new();
- readonly List<Visual> _cells = new();
- readonly List<TextLayout> _texts = new();
-
- GcPdfGraphics _g;
- View _pageView;
- Layer _textLayer;
- LayoutRect _bounds;
- Surface _sf;
-
- public int CreatePDF(Stream stream)
- {
- var doc = new GcPdfDocument();
-
- var page = doc.NewPage();
- var pageSize = page.Size;
- _g = page.Graphics;
-
- _sf = new Surface();
- _pageView = _sf.CreateView(pageSize.Width, pageSize.Height);
- _textLayer = _pageView.CreateSubLayer();
- _resolution = _g.Resolution;
-
- var marginsVisual = _pageView.CreateVisual((g, v) =>
- {
- g.FillRectangle(v.AsRectF(), Color.FromArgb(0xFF, 0xF8, 0xF8));
- });
- _bounds = marginsVisual.LayoutRect;
- _bounds.AnchorInflate(null, -_resolution);
- _sf.PerformLayout();
-
- var noteBounds = AddNote("We create a table with a large number of variable height rows. " +
- "The table starts at a specified position on the first page, and spans multiple pages.");
-
- var fc = FontCollection.SystemFonts;
- _thFormat = new TextFormat
- {
- Font = fc.FindFamilyName("Trebuchet MS", true) ?? fc.FindFamilyName("Arial", true),
- FontBold = true,
- ForeColor = Color.White
- };
- _tdFormat = new TextFormat
- {
- Font = fc.FindFamilyName("Trebuchet MS") ?? fc.FindFamilyName("Arial")
- };
-
- _headers = new string[] { "#", "Lorem", "Ipsum" };
- CreateColumns();
-
- var headerRowRect = CreateHeaderRow();
- headerRowRect.SetTop(noteBounds, AnchorParam.Bottom, _resolution / 2);
- FillHeaderRow(headerRowRect);
-
- var prevRowRect = headerRowRect;
- var numberOfRows = Common.Util.NewRandom().Next(100, 500);
-
- for (int i = 0; i < numberOfRows; i++)
- {
- var row = CreateRow((i & 1) != 0);
- var rc = row.LayoutRect;
- rc.SetTop(prevRowRect, AnchorParam.Bottom);
- if (!FillRow(i, rc))
- {
- row.Detach();
- CreateTableGrid();
- _sf.Render(_g);
-
- _columns.Clear();
- _rows.Clear();
-
- page = doc.NewPage();
- pageSize = page.Size;
- _g = page.Graphics;
-
- _sf = new Surface();
- _pageView = _sf.CreateView(pageSize.Width, pageSize.Height);
- _textLayer = _pageView.CreateSubLayer();
-
- marginsVisual = _pageView.CreateVisual((g, v) =>
- {
- g.FillRectangle(v.AsRectF(), Color.FromArgb(0xFF, 0xF8, 0xF8));
- });
- _bounds = marginsVisual.LayoutRect;
- _bounds.AnchorInflate(null, -_resolution);
- _sf.PerformLayout();
-
- CreateColumns();
- headerRowRect = CreateHeaderRow();
- headerRowRect.SetTop(_bounds, AnchorParam.Top);
- FillHeaderRow(headerRowRect);
-
- row = CreateRow((i & 1) != 0);
- rc = row.LayoutRect;
- rc.SetTop(headerRowRect, AnchorParam.Bottom);
-
- RestoreRow(rc);
- }
- prevRowRect = rc;
- }
-
- CreateTableGrid();
- _sf.Render(_g);
-
- doc.Save(stream);
- return doc.Pages.Count;
- }
-
- class TableGridInfo
- {
- public TableGridInfo(LayoutRect[] columns, LayoutRect[] rows)
- {
- Columns = columns;
- Rows = rows;
- }
- public readonly LayoutRect[] Columns;
- public readonly LayoutRect[] Rows;
- }
-
- void CreateTableGrid()
- {
- var grid = _pageView.CreateVisual(false);
- grid.Tag = new TableGridInfo(_columns.ToArray(), _rows.ToArray());
- grid.Draw = (g, v) =>
- {
- var pen = new GCDRAW::Pen(Color.FromArgb(0xDD, 0xDD, 0xDD), 1);
- var tgi = (TableGridInfo)v.Tag;
- int lastColumnIndex = tgi.Columns.Length - 1;
- int lastRowIndex = tgi.Rows.Length - 1;
-
- float xMin = tgi.Columns[0].P0X;
- float yMin = tgi.Rows[0].P0Y;
- float xMax = tgi.Columns[lastColumnIndex].P1X;
- float yMax = tgi.Rows[lastRowIndex].P2Y;
-
- g.DrawRectangle(new RectangleF(xMin, yMin, xMax - xMin, yMax - yMin), pen);
- for (int i = 0; i < lastColumnIndex; i++)
- {
- float x = tgi.Columns[i].P1X;
- g.DrawLine(new PointF(x, yMin), new PointF(x, yMax), pen);
- }
- for (int i = 0; i < lastRowIndex; i++)
- {
- float y = tgi.Rows[i].P2Y;
- g.DrawLine(new PointF(xMin, y), new PointF(xMax, y), pen);
- }
- };
- }
-
- void CreateColumns()
- {
- LayoutRect column1 = _pageView.CreateSpace().LayoutRect;
- LayoutRect column2 = _pageView.CreateSpace().LayoutRect;
- LayoutRect column3 = _pageView.CreateSpace().LayoutRect;
-
- column1.AnchorTopBottom(_bounds, 0, 0);
- column2.AnchorTopBottom(_bounds, 0, 0);
- column3.AnchorTopBottom(_bounds, 0, 0);
-
- column1.SetLeft(_bounds, AnchorParam.Left);
- column2.SetLeftAndOpposite(column1, AnchorParam.Right);
- column3.SetLeftAndOpposite(column2, AnchorParam.Right);
- column3.SetRight(_bounds, AnchorParam.Right);
-
- column1.SetStarWidth(1);
- column2.SetStarWidth(3);
- column3.SetStarWidth(3);
-
- _sf.PerformLayout();
-
- _columns.Add(column1);
- _columns.Add(column2);
- _columns.Add(column3);
- }
-
- LayoutRect CreateHeaderRow()
- {
- var rc = _pageView.CreateVisual((g, v) =>
- {
- g.FillRectangle(v.AsRectF(), Color.FromArgb(0x33, 0x77, 0xFF));
- }).LayoutRect;
- rc.AnchorLeftRight(_bounds, 0, 0);
- return rc;
- }
-
- void FillHeaderRow(LayoutRect headerRowRect)
- {
- for (int i = 0; i < _columns.Count; i++)
- {
- var column = _columns[i];
- var tl = new TextLayout(_resolution)
- {
- MaxWidth = column.Width,
- TextAlignment = TextAlignment.Center,
- MarginLeft = 8,
- MarginRight = 8,
- MarginTop = 12
- };
- tl.Append(_headers[i], _thFormat);
- tl.PerformLayout();
-
- var cell = _textLayer.CreateVisual();
- cell.Tag = tl;
- cell.Draw = (g, v) =>
- {
- g.DrawTextLayout((TextLayout)v.Tag, new PointF(0, 0));
- };
- var rc = cell.LayoutRect;
- rc.AnchorLeftRight(column, 0, 0);
- rc.SetTop(headerRowRect, AnchorParam.Top, 0);
- rc.SetHeight(tl.ContentHeight + 12 + 12);
- headerRowRect.AppendMinBottom(rc, AnchorParam.Bottom);
- }
- _rows.Add(headerRowRect);
- _sf.PerformLayout();
- }
-
- Visual CreateRow(bool even)
- {
- var row = _pageView.CreateVisual();
- if (even)
- row.Draw = (g, v) => g.FillRectangle(v.AsRectF(), Color.FromArgb(0xF2, 0xF2, 0xF2));
- else
- row.Draw = (g, v) => g.FillRectangle(v.AsRectF(), Color.White);
- row.LayoutRect.AnchorLeftRight(_bounds, 0, 0);
- return row;
- }
-
- bool FillRow(int index, LayoutRect rowRect)
- {
- _cells.Clear();
- _texts.Clear();
- for (int i = 0; i < _columns.Count; i++)
- {
- var column = _columns[i];
- var tl = new TextLayout(_resolution)
- {
- MaxWidth = column.Width,
- MarginAll = 8
- };
- if (i == 0)
- {
- tl.TextAlignment = TextAlignment.Center;
- tl.Append((index + 1).ToString(), _tdFormat);
- }
- else
- {
- // Add random data:
- tl.Append(Common.Util.LoremIpsum(1, 1, 2, 1, 15), _tdFormat);
- }
- tl.PerformLayout();
- _texts.Add(tl);
-
- var cell = _textLayer.CreateVisual();
- cell.Tag = tl;
- cell.Draw = (g, v) =>
- {
- g.DrawTextLayout((TextLayout)v.Tag, new PointF(0, 0));
- };
- var rc = cell.LayoutRect;
- rc.AnchorLeftRight(column, 0, 0);
- rc.SetTop(rowRect, AnchorParam.Top, 0);
- rc.SetHeight(tl.ContentHeight + 8 + 8);
- rowRect.AppendMinBottom(rc, AnchorParam.Bottom);
- _cells.Add(cell);
- }
- _sf.PerformLayout();
-
- if (rowRect.P2Y > _bounds.P2Y)
- {
- for (int i = 0; i < _cells.Count; i++)
- {
- _cells[i].Detach();
- }
- _cells.Clear();
- return false;
- }
-
- _rows.Add(rowRect);
- return true;
- }
-
- void RestoreRow(LayoutRect rowRect)
- {
- for (int i = 0; i < _columns.Count; i++)
- {
- var tl = _texts[i];
- var cell = _textLayer.CreateVisual();
- cell.Tag = tl;
- cell.Draw = (g, v) =>
- {
- g.DrawTextLayout((TextLayout)v.Tag, new PointF(0, 0));
- };
- var rc = cell.LayoutRect;
- rc.AnchorLeftRight(_columns[i], 0, 0);
- rc.SetTop(rowRect, AnchorParam.Top, 0);
- rc.SetHeight(tl.ContentHeight + 8 + 8);
- rowRect.AppendMinBottom(rc, AnchorParam.Bottom);
- }
- _sf.PerformLayout();
- _rows.Add(rowRect);
- }
-
- LayoutRect AddNote(string text)
- {
- var pad = _resolution / 8f;
- var tl = new TextLayout(_resolution)
- {
- MaxWidth = _bounds.Width,
- MaxHeight = _bounds.Height,
- MarginAll = pad
- };
- tl.Append(text, new TextFormat { Font = StandardFonts.Helvetica });
- tl.PerformLayout();
-
- var noteVisual = _pageView.CreateVisual();
- noteVisual.Tag = tl;
- noteVisual.Draw = (g, v) =>
- {
- var rect = v.AsRectF();
- g.FillRectangle(rect, Color.FromArgb(213, 221, 240));
- g.DrawRectangle(rect, Color.FromArgb(59, 92, 170), 0.5f);
- g.DrawTextLayout((TextLayout)v.Tag, new PointF(0, 0));
- };
-
- var textRect = tl.ContentRectangle;
- textRect.Inflate(pad, pad);
- var rc = noteVisual.LayoutRect;
- rc.AnchorTopLeft(_bounds, 0, 0, textRect.Width, textRect.Height);
- return rc;
- }
- }
- }
-