TimelineStoryLayout.h header

#include <ew/app/TimelineStoryLayout.h>

Namespace ew::app

StoryLane struct

struct ew::app::StoryLane

One category lane fed to the layout: the side it sits on and its events, in the caller's order.

Members

StorySide ew::app::StoryLane::side =

Which side of the central axis this lane sits on.

std::vector<LayoutEvent> ew::app::StoryLane::events

This lane's events, in the caller's order.

bool ew::app::StoryLane::axisBars = true

Whether this lane's DURATION events (endX > startX) get a dated span bar hugging the axis (R2.4) – the visible geometry a resize grabs. Lifespan lanes switch this off: a lifespan is R5.1's own span-bar treatment inside its lane, not an axis bar.

StoryLaneBox struct

struct ew::app::StoryLaneBox

The outlined box drawn for a lane – the region its pills live inside (never a bare line). Its height is however many pill rows the lane needs (events are stacked, never collapsed), so a busy lane grows and a quiet one stays thin.

Members

QRect ew::app::StoryLaneBox::box

The bordered area, spanning the plot width.

StorySide ew::app::StoryLaneBox::side =

Which side of the central axis the lane box sits on.

int ew::app::StoryLaneBox::rows = 0

How many pill rows it holds (>= 1 when it has events).

StoryLayout struct

struct ew::app::StoryLayout

The whole story-view geometry: the axis y, every lane's box, every event's pill + leader.

Members

int ew::app::StoryLayout::axisY = 0

The y coordinate of the central horizontal axis.

std::vector<StoryLaneBox> ew::app::StoryLayout::laneBoxes

Parallel to the input lanes.

std::vector<StoryPill> ew::app::StoryLayout::pills

Flattened across all lanes, in input order.

StoryLayoutParams struct

struct ew::app::StoryLayoutParams

The pixels the story layout works within.

Members

QRect ew::app::StoryLayoutParams::plot

The drawable area (the plot column, minus the left label gutter).

int ew::app::StoryLayoutParams::pillHeight = 18

Height of one pill (one stack row).

int ew::app::StoryLayoutParams::pillGap = 3

Vertical gap between two stacked pills in a lane.

int ew::app::StoryLayoutParams::laneGap = 8

Gap between two adjacent lane boxes on the same side.

int ew::app::StoryLayoutParams::axisGap = 12

Gap between the axis line and the nearest lane box, each side.

int ew::app::StoryLayoutParams::minPillWidth = 40

Narrowest a pill may be, so a short date-title still reads.

int ew::app::StoryLayoutParams::barHeight = 6

Height of one duration span bar hugging the axis (R2.4).

int ew::app::StoryLayoutParams::barGap = 2

Gap between two stacked span-bar rows (and two bars in one row).

StoryPill struct

struct ew::app::StoryPill

One event, laid out as a pill with a leader to the central axis. The pill is stacked OUTWARD from the axis (row 0 nearest it) so it never overlaps a neighbour – there is no clustering; a dense run uses vertical space (docs/TIMELINE_REDESIGN.md R2.3). The leader is the vertical line that ties the pill to its date on the axis (R2.2): both ends share the event's x.

Members

ew::core::ContentId ew::app::StoryPill::id

The event this pill represents.

QRect ew::app::StoryPill::pill

The date-title card, inside its lane box.

QPoint ew::app::StoryPill::leaderPill

The pill end of the leader (its axis-facing edge, at the event's x).

QPoint ew::app::StoryPill::leaderAxis

The axis end of the leader (the event's x, on the central axis).

int ew::app::StoryPill::row = 0

Its stack row within the lane (0 = nearest the axis).

QRect ew::app::StoryPill::spanBar

A duration event's dated bar hugging the axis on the lane's side (R2.4): startX..endX wide, so the span reads against the axis dates and its edges are the visible resize handles. Null for an instant (endX == startX) and for a lane with StoryLane::axisBars off. Bars on one side stack outward in thin rows so overlapping spans stay individually readable.

Enumerations

enum class StoryLaneKind { Event, Lifespan, Series }

What kind of content a lane holds, which drives its default side: event lanes read as the primary narrative ABOVE the axis; the derived lanes (lifespans, quantitative series) sit BELOW.

enum class StorySide { Above, Below }

The "Story view" layout (docs/TIMELINE_REDESIGN.md): ONE central horizontal axis with category lanes as outlined boxes above and below it, every event a pill joined to its exact point on the axis by a leader line. This is the geometry engine – pure, pixel-space, and unit-tested – so the panel that draws it holds no layout maths (per the redesign's Definition of Done). It reuses LayoutEvent (id / startX / endX / labelWidth, already time->pixel mapped by the caller). Which side of the central axis a lane sits on. Above lanes stack UPWARD from the axis, below lanes stack DOWNWARD, so the axis stays the shared anchor both read against.

Functions

std::vector< StorySide > ew::app::defaultStorySides(const std::vector< StoryLaneKind > &kinds)

The default side (above/below the axis) for each lane, by kind: event lanes above, lifespan and series lanes below. When a project has only event lanes (nothing would sit below), the latter half move below so the axis stays roughly central rather than pinned to the bottom. A user's explicit per-lane choice (persisted with the view settings) overrides this default at the caller.

StoryLayout ew::app::storyLayout(const std::vector< StoryLane > &lanes, const StoryLayoutParams &params)

Computes the story-view geometry (pure). The central axis is anchored at the plot's vertical CENTRE and stays there however tall a lane grows (so a busy lane can never shove the axis off screen – the flaw the redesign fixes); above lanes stack upward from it and below lanes downward, a lane taller than its half simply overflowing the plot edge for the caller to clip or scroll. Each lane box is sized to its stacked pill rows; every pill is stacked outward from the axis (greedy by startX, so two events that overlap in x take different rows and none is ever collapsed); and every pill gets a vertical leader from its axis-facing edge to the event's x on the axis. Lanes with no events still get a thin box.