| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using QuestPDF.Drawing;
- using QuestPDF.Infrastructure;
- namespace QuestPDF.Elements
- {
- internal sealed class ColumnItem : Container
- {
- public bool IsRendered { get; set; }
- }
- internal sealed class ColumnItemRenderingCommand
- {
- public ColumnItem ColumnItem { get; set; }
- public SpacePlan Measurement { get; set; }
- public Size Size { get; set; }
- public Position Offset { get; set; }
- }
- internal sealed class Column : Element, ICacheable, IStateResettable
- {
- internal List<ColumnItem> Items { get; } = new();
- internal float Spacing { get; set; }
- public void ResetState()
- {
- Items.ForEach(x => x.IsRendered = false);
- }
-
- internal override IEnumerable<Element?> GetChildren()
- {
- return Items;
- }
-
- internal override void CreateProxy(Func<Element?, Element?> create)
- {
- Items.ForEach(x => x.Child = create(x.Child));
- }
- internal override SpacePlan Measure(Size availableSpace)
- {
- if (!Items.Any())
- return SpacePlan.FullRender(Size.Zero);
-
- var renderingCommands = PlanLayout(availableSpace);
- if (!renderingCommands.Any())
- return SpacePlan.Wrap();
- var width = renderingCommands.Max(x => x.Size.Width);
- var height = renderingCommands.Last().Offset.Y + renderingCommands.Last().Size.Height;
- var size = new Size(width, height);
-
- if (width > availableSpace.Width + Size.Epsilon || height > availableSpace.Height + Size.Epsilon)
- return SpacePlan.Wrap();
-
- var totalRenderedItems = Items.Count(x => x.IsRendered) + renderingCommands.Count(x => x.Measurement.Type == SpacePlanType.FullRender);
- var willBeFullyRendered = totalRenderedItems == Items.Count;
- return willBeFullyRendered
- ? SpacePlan.FullRender(size)
- : SpacePlan.PartialRender(size);
- }
- internal override void Draw(Size availableSpace)
- {
- var renderingCommands = PlanLayout(availableSpace);
- foreach (var command in renderingCommands)
- {
- if (command.Measurement.Type == SpacePlanType.FullRender)
- command.ColumnItem.IsRendered = true;
- var targetSize = new Size(availableSpace.Width, command.Size.Height);
- Canvas.Translate(command.Offset);
- command.ColumnItem.Draw(targetSize);
- Canvas.Translate(command.Offset.Reverse());
- }
-
- if (Items.All(x => x.IsRendered))
- ResetState();
- }
- private ICollection<ColumnItemRenderingCommand> PlanLayout(Size availableSpace)
- {
- var topOffset = 0f;
- var targetWidth = 0f;
- var commands = new List<ColumnItemRenderingCommand>();
- foreach (var item in Items)
- {
- if (item.IsRendered)
- continue;
- var availableHeight = availableSpace.Height - topOffset;
-
- if (availableHeight < -Size.Epsilon)
- break;
- var itemSpace = new Size(availableSpace.Width, availableHeight);
- var measurement = item.Measure(itemSpace);
-
- if (measurement.Type == SpacePlanType.Wrap)
- break;
- commands.Add(new ColumnItemRenderingCommand
- {
- ColumnItem = item,
- Size = measurement,
- Measurement = measurement,
- Offset = new Position(0, topOffset)
- });
-
- if (measurement.Width > targetWidth)
- targetWidth = measurement.Width;
-
- if (measurement.Type == SpacePlanType.PartialRender)
- break;
-
- topOffset += measurement.Height + Spacing;
- }
- foreach (var command in commands)
- command.Size = new Size(targetWidth, command.Size.Height);
- return commands;
- }
- }
- }
|