Flow content
FlowView is the read-only rich-content surface for document previews,
transcripts, reports, and other application-defined content. It is not a
Markdown parser or a document model. Clients build a FlowDocument value from
their own semantic model and give it to the view.
Each FlowBlock contains FlowText, FlowLineBreak, and FlowImage atoms.
Text wraps by grapheme width at the view's current width; styled runs and links
remain intact. Tab and Shift+Tab cycle links, Enter activates the current
link, and mouse clicks activate the linked run. Arrow, page, home, end, and
wheel input scroll ordinary display rows.
widgets::FlowDocument document{
.blocks = {{.content = {
widgets::FlowText{"Build ", Attr::Bold, std::nullopt},
widgets::FlowText{"details", Attr{}, std::string("build://42")},
widgets::FlowLineBreak{},
widgets::FlowText{"The image below remains useful without graphics.", Attr{}, std::nullopt},
}}}
};
widgets::FlowView preview;
preview.set_document(std::move(document));
preview.on_link_activate = [](const std::string& target) { /* client action */ };
Updating one block
When an application-owned semantic record changes, replace only its existing
flow block instead of rebuilding the document value. A successful replacement
keeps the block order and ordinary scroll position, then rebuilds derived
layout and link navigation. Replacing the final block after the current layout
has been realized reflows only that block; other replacements reflow the
document because the changed height or links can affect following content.
Replacing an out-of-range index returns false and leaves the document
unchanged.
const bool replaced = preview.replace_block(1, widgets::FlowBlock{{
widgets::FlowText{"Updated details", Attr::Bold, std::nullopt},
}});
Inline raster atoms
FlowImage reserves its explicit cell extent in the document flow. The image
is emitted through Painter::draw_image, just like ImageView and Canvas:
it is clipped and occluded by the normal scene compositor, has a bounded cell
fallback, and appears as no raster pixels when graphics are unavailable.
auto chart = std::make_shared<Image>(PixelSize{640, 240});
// The application draws chart pixels into chart.
document.blocks.push_back({{widgets::FlowImage{chart, Size{48, 12}, "[chart]"}}});
preview.set_document(std::move(document));
An image occupies complete flow rows rather than allowing text to wrap around its sides. That makes resize, scrolling, fallback, and raster clipping deterministic on every terminal size. Scrolling moves the image's anchor by the rows scrolled, so its top may lie above the first row shown; the clip keeps the rows in view and the columns left of the scrollbar, and the picture itself is never cut into a new image (D-081, Graphics). Its fallback text sits on the image's first row and scrolls away with it. Applications choose their own image generation, refresh, loading placeholder, and semantic layout policy.