namespace AIStudio.Tools.PowerPoint;
///
/// One placeholder of a slide layout which the content of a slide goes into.
///
/// What the slot is for.
/// The number of the slot among the slots of the same role, starting at 1, in reading order.
/// Where the slot sits, inherited from the slide master when the layout does not say.
/// The placeholder type as the file spells it, e.g., "body" or "pic"; "obj" when the file states none.
/// The placeholder index, which links a placeholder of a slide to the one of its layout.
/// How much text fits; missing for pictures.
internal sealed record TemplateSlot(PlaceholderRole Role, int Ordinal, SlotBounds Bounds, string PlaceholderType, uint? PlaceholderIndex, TextCapacity? Capacity)
{
///
/// The slot as the layout offers it, which a slot a slide moved or copied is measured against;
/// null for a slot of the layout itself.
///
public TemplateSlot? LayoutSlot { get; init; }
///
/// The slot where a slide moved or resized its placeholder.
///
///
/// The capacity grows and shrinks with the size, since the slide keeps the font. Insets stay as
/// they are on a smaller slot, so the estimate runs a little high there; the check of the
/// model's answer accepts a line more anyway. The capacity is always scaled from the slot of the
/// layout, so that a slot moved twice, e.g., resized by its slide and then grown into room the
/// slide frees, is not rounded down twice.
///
/// Where the slide puts the placeholder.
public TemplateSlot MovedTo(SlotBounds bounds)
{
var layoutSlot = this.LayoutSlot ?? this;
return this with
{
Bounds = bounds,
Capacity = layoutSlot.Capacity is { } capacity
? new TextCapacity(
Math.Max(1, (int)(capacity.Lines * (double)bounds.Height / Math.Max(1, layoutSlot.Bounds.Height))),
Math.Max(1, (int)(capacity.CharactersPerLine * (double)bounds.Width / Math.Max(1, layoutSlot.Bounds.Width))))
: null,
LayoutSlot = layoutSlot,
};
}
}