sextile.viewdata.composition

Placing things at positions on a frame, and planning the attributes at once.

A Composition collects text, mosaic pictures and coloured panels with where each goes – a column, or an Align to be placed without counting – and draw places them and works out the spacing attributes for the whole row in one pass. Unlike a RowWriter, which writes left to right and cannot say whether a row fits until it is half drawn, it takes the whole row first: so it can answer fits before drawing anything, and enter a colour once for runs at either end of a row rather than twice.

Rows are independent – each begins in alpha, white, contiguous graphics – so a frame composition is a row composition done for each row, and nothing here concerns the frame as a whole. It settles where things go; the colour they come out in is viewdata.attributes, which it drives once a row’s runs and panels are placed.

class sextile.viewdata.composition.Align(*values)[source]

Bases: Enum

Where to put something along an axis, without counting cells.

START and END are spelled for the axis: the left or right edge where the axis is a row’s columns, the top or bottom where it is the frame’s rows. Naming them for the axis rather than LEFT/RIGHT lets one enum place a thing across a row and down a frame, without LEFT having to mean “top”.

Passed instead of a coordinate because placing at the middle depends on what the row’s attributes cost in cells, which the composition works out; a caller computing the coordinate would have to find that cost first.

class sextile.viewdata.composition.Composition(runs=<factory>, panels=<factory>)[source]

Bases: object

Things to place on a frame, and where.

Parameters:
panel(row, where=Align.CENTRE, *, colour, width=None, around=None, padding=0, rows=1)[source]

Add a coloured rectangle rows deep, returned so things can go in it.

Parameters:
  • row (int | Align) – The top row, an int or an Align to place it down the frame.

  • where (int | Align) – Where it sits across the frame.

  • colour (Colour) – Its background colour.

  • width (int | None) – Its width in cells. Give this or around, not both.

  • around (Sequence[int] | None) – Rows whose ink to fit it to instead, so a stripe is drawn behind something without either being told where the other is.

  • padding (int) – Cells of colour either side of what it goes around.

  • rows (int) – How many rows deep it is.

Return type:

Panel

Returns:

The panel, so a run drawn within it takes its background without saying anything. Fitted to the ink, not the run: a run may begin with a blank half-cell.

Raises:

DoesNotFit – If both or neither of width and around is given, or a row falls off the frame.

text(row, where, words, colour=Colour.WHITE, *, within=None, style=None)[source]

Add text at a position, returning self so calls chain.

Parameters:
  • row (int) – The row to place it on.

  • where (int | Align) – Where it sits across the row, a column or an Align.

  • words (str) – The text.

  • colour (Colour) – Its colour, the common case; style overrides it.

  • within (Panel | None) – A panel it is drawn on, whose background it takes.

  • style (Style | None) – The full style, in place of colour.

Return type:

Composition

Returns:

Self. Double height places the same text on the row below too, which is how the SAA5050 draws the bottom halves.

blocks(row, where, patterns, colour=Colour.WHITE, *, within=None, separated=False, style=None)[source]

Add a run of mosaic blocks, a picture one row tall, returning self.

Parameters:
  • row (int) – The row to place it on.

  • where (int | Align) – Where it sits across the row.

  • patterns (Sequence[int]) – The six-bit block patterns, one per cell.

  • colour (Colour) – The colour to draw them in.

  • within (Panel | None) – A panel it is drawn on.

  • separated (bool) – Whether the blocks are drawn separated, not contiguous.

  • style (Style | None) – The full style, in place of colour and separated.

Return type:

Composition

Returns:

Self.

picture(row, where, rows, colour=Colour.WHITE, *, within=None, separated=False, style=None)[source]

Add several rows of mosaic blocks that belong together, returning self.

Parameters:
  • row (int | Align) – The top row, an int or an Align to place it down the frame.

  • where (int | Align) – Where it sits across the frame.

  • rows (Sequence[Sequence[int]]) – The block patterns, a row of them per frame row.

  • colour (Colour) – The colour to draw them in.

  • within (Panel | None) – A panel it is drawn on.

  • separated (bool) – Whether the blocks are drawn separated, not contiguous.

  • style (Style | None) – The full style, in place of colour and separated.

Returns:

centred a row at a time, some rows would take the half-cell shift and others not.

Return type:

Composition

problems()[source]

Everything wrong with this composition, or nothing if it will draw.

Return type:

list[str]

draw(canvas)[source]

Draw it, or raise DoesNotFit having drawn nothing.

Parameters:

canvas (Canvas)

Return type:

None

exception sextile.viewdata.composition.DoesNotFit[source]

Bases: ValueError

A composition that cannot be drawn, and why.

class sextile.viewdata.composition.Panel(column, width, colour, rows=())[source]

Bases: object

A coloured rectangle, cell-aligned, with things drawn on top of it.

column is its first coloured cell, which is the one carrying NEW_BACKGROUND: the hardware sets a background at the attribute cell rather than after it, so that cell is already the colour it asks for. The cell before it is not – it is where the colour is chosen, and a colour attribute cannot colour itself – so a panel always costs one black cell to its left, and content inside it starts at least one cell in from the left-hand edge.

Parameters:
property end: int

One past the last coloured cell.

class sextile.viewdata.composition.Style(colour=Colour.WHITE, background=Colour.BLACK, separated=False, flashing=False, double_height=False, hold_graphics=False, concealed=False)[source]

Bases: object

How a run is to be displayed: every attribute the SAA5050 has.

Not every combination is reachable from every other in one cell, which is why this is a value handed to a compositor rather than a sequence of attributes written by hand. A background is the worst of them: the hardware has no “set background” attribute, only “make the current foreground the background”, so white on blue costs three cells – choose blue, make it the background, choose white again.

Parameters:
sextile.viewdata.composition.Where = int | sextile.viewdata.composition.Align

A coordinate along an axis – a column across a row, or a row down the frame – or an Align asking to be placed without one being counted.