Compose a frame¶
A how-to guide: place runs, panels and lettering at positions with a
Composition, which checks the whole layout fits before it draws a cell.
from sextile import Custom, OnOneFrame, Page, PageLayout, PageRequest, PageRouter, Sextile
from sextile.viewdata.canvas import Canvas
from sextile.viewdata.composition import Align, Composition, Style
from sextile.viewdata.controls import Colour
router = PageRouter()
_BOARD = [
("Aberdeen", "4", "10:15"), ("Bristol", "9", "10:22"), ("Carlisle", "1", "10:40"),
("Dover", "6", "10:51"), ("Edinburgh", "3", "11:05"), ("Falmouth", "7", "11:18"),
("Glasgow", "2", "11:30"),
]
@router.page("1", name="board", title="Departures")
async def board(request: PageRequest) -> Page:
def draw(canvas: Canvas, row: int) -> None:
layout = Composition()
head = layout.panel(row, Align.START, width=39, colour=Colour.BLUE, rows=1)
layout.text(row, Align.CENTRE, "KINGS CROSS", style=Style(colour=Colour.YELLOW), within=head)
for column, heading in ((1, "TO"), (Align.CENTRE, "PLAT"), (Align.END, "TIME")):
layout.text(row + 2, column, heading, style=Style(colour=Colour.CYAN))
for offset, (place, plat, time) in enumerate(_BOARD):
line = row + 4 + offset * 2
layout.text(line, 1, place, style=Style(colour=Colour.WHITE))
layout.text(line, Align.CENTRE, plat, style=Style(colour=Colour.WHITE))
layout.text(line, Align.END, time, style=Style(colour=Colour.GREEN))
foot = layout.panel(row + 18, Align.START, width=39, colour=Colour.MAGENTA, rows=1)
layout.text(row + 18, Align.CENTRE, "Times are provisional", style=Style(colour=Colour.WHITE), within=foot)
layout.draw(canvas)
return PageLayout(parts=[OnOneFrame(Custom(rows=19, draw=draw))]).build(request)
app = Sextile(name="Station", pages=[*router])
DEPARTURES 1a KINGS CROSS TO PLAT TIME Aberdeen 4 10:15 Bristol 9 10:22 Carlisle 1 10:40 Dover 6 10:51 Edinburgh 3 11:05 Falmouth 7 11:18 Glasgow 2 11:30 Times are provisional 0 index
Composition.text(row, column, text, style=) places a run at a position, where a
Canvas row writes only left to right; a column may be a number or an Align
(START, CENTRE, END). Each row’s destination, platform and time are placed
at START, CENTRE and END, so the three columns line up however long the
names are. panel declares a coloured box once — the blue masthead and the
magenta footer — and a run placed within it is aligned in the box rather than on
the frame.
The layout is checked, not searched¶
Composition.draw reports whether the layout is possible — naming the row, the
column and the arithmetic in a DoesNotFit — before a cell is written, and draws
nothing if any row fails, so a bad layout never leaves half a frame on a screen.
A coloured run reserves the cell before it for its colour attribute, which is why
the destinations begin at column 1 and not column 0; two runs in one style cost
one attribute, not two. Why placement is a single left-to-right pass rather than a
search is in the graphics explanation.
Which to reach for¶
Use |
For |
|---|---|
|
text and mosaics that run left to right along one row |
|
runs placed at positions, panels, alignment, and a checked fit |
Draw a row at a time with Draw a custom frame; set lettering on a panel
with Letter on a background. The compositor’s own API is
sextile.viewdata.composition.