000
There's no reason to get political about your

Alignment

HORIZONTAL

left(bool offon)

The layout starts out with left-alignment as default (in left-to-right streams), but it may prove useful to interject left-aligned content within a differently aligned block. Anything between left(true) and left(false) will be left-aligned with respect to the nearest block-element parent.

center(bool offon)

Anything between left(true) and left(false) will be centered with respect to the nearest block-element parent.

right(bool offon)

Anything between right(true) and right(false) will be right-aligned with respect to the nearest block-element parent.

outline(bool offon)

Anything between outline(true) and outline(false) will be outlined with respect to the nearest block-element parent.

Horizontal alignment sections are flow-elements.

Example:
#include <iostream>
#include "enframe.h"
layoutstream os(std::cout);
int main() {
   os << center()
         << "I'm a little teapot, short and stout\n"
         << "Here is my handle, here is my spout\n"
         << "When I get all steamed up, hear me shout\n"
         << "Tip me over and pour me out!"
      << center(false)
      << right()
         << "George H. Sanders \n"
         << "and Clarence Z. Kelley,\n"
         << 1939 << '.'
      << std::flush;
   return 0;
}
Output:
  I'm a little teapot, short and stout                   
  Here is my handle, here is my spout                    
When I get all steamed up, hear me shout                 
      Tip me over and pour me out!     George H. Sanders 
                                  and Clarence Z. Kelley,
                                                    1939.
>
001

VERTICAL

top

In a context where vertical alignment makes sense, streaming ‘top’ will make that element align with the other topmost elements of that context.

middle

In a context where vertical alignment makes sense, streaming ‘middle’ will make that element’s vertical middle align with the global vertical middle of that context.

bottom

In a context where vertical alignment makes sense, streaming ‘bottom’ will make that element’s bottom align with the bottommost elements of that context.

Vertical alignment currently only affects columns.

Example:
os << columns_section
   <<    top
   <<       "top"
   << column_break
   <<       "middle"
   <<    middle
   << column_break
   <<    bottom
   <<       "bottom"
   << column_break
   <<       "(1\n"
   <<       "(2\n"
   <<       "(3"
   << end_columns_section
   << std::flush;
Output:
top│      │      │(1
   │middle│      │(2
   │      │bottom│(3
<
>
002
Will you please excuse me? I will be right back.

Marking the insert position

postpone(std::size_t identifier)

Streaming ‘postpone’ with a std::size_t argument relates that argument to the current input position. Any consequential input after ‘postpone’ will follow sequentially, but later streaming ‘postponed’ with the same argument will insert any consequential input to the original position, effectively between what has come before and after the original streaming position of ‘postpone’. You can choose any number yourself, but it should obviously be unique for the lifetime of the ‘layoutstream’ object.

postponed(std::size_t identifier)

Streaming ‘postponed’ with a std::size_t argument must not happen before streaming ‘postpone’ with the same argument first. See ‘postpone’, above.

Postponed sections are flow-elements.

Example:
#include <iostream>
#include "enframe.h"
layoutstream os(std::cout);
int main() {
   os << "Name: \"" << postpone(123) << "\".\n";
   // Do other things here...
   // And then:
   os << postponed(123) << "John Doe";
   os << std::flush;
   return 0;
}
Output:
Name: "John Doe".
<
>
003
Not quite tables, but nonetheless

Columns and rows

columns_section

Signals the start of columnised text. You just add as many ‘column_break’s as you want there to be columns, minus one.

column_break

Signals the end of the current column.

end_columns_section

Signals the end of all columns that make up this columns_section.

rows_section

Signals the start of text made up in separated rows. You just add as many ‘row_break’s as you want there to be rows, minus one.

row_break

Signals the end of the current row, (and the end of any previous row).

end_rows_section

Signals the end of all rows that make up this rows_section.

Columns and row sections are block-elements, as are cells within.

Example:
os << columns_section
   <<    top
   <<       "top"
   << column_break
   <<       "middle"
   <<    middle
   << column_break
   <<    bottom
   <<       "bottom"
   << column_break
   <<       "(1\n"
   <<       "(2\n"
   <<       "(3"
   << end_columns_section
   << std::flush;
Output:
top│      │      │(1
   │middle│      │(2
   │      │bottom│(3
<
>
004
Four legs, and a top useful for placing your mug on.

Defining a table

begin_table(bool rows_cols)

Starts a table definition at the current insert position. The boolean argument is taken to mean column-majority in the case of true, and row-majority in the false case.

end_table

Ends the last table definition that was started with begin_table.

row_break

Signals that the current row (or cell in a column-major table) is fully defined.

column_break

Signals that the current column (or cell in a row-major table) is fully defined.

bool_break(bool row_col)

The boolean argument selects whether to operate as row_break or column_break.

colspan

The argument specifies the number of cells the current cell will take up, expanding from the current position to the right.

rowspan

The argument specifies the number of cells the current cell will take up, expanding from the current position downward.

bool_span(bool row_col)

The boolean argument selects whether to operate as rowspan or colspan, the second argument behaves as though respectively passed to either aforementioned constructors.

transpose

Turns a column-major table into a row-major one, or the other way around. This effectively also switches colspan and rowspan usages into each other.

The table can be composed in two ways: you either construct columns of rows, or else rows of columns. When constructing columns of rows, you start with column one. When the upperleft cell has been defined, you have to insert a row_break (if there will be more than one row in the table you’re defining). You then define the cell below the upperleft one, and so on until you complete all required rows. Inserting a column_break signals the beginning of the second column. Repeat until all cells are defined. Interchange row_break and column_break in the above if you are defining the table in row-major order instead. Then you move to the right in one successive row at a time. The order can be specified as a boolean argument to begin_table(majority).

When the stream is in a position to accept data for the current cell, then the stream can also relate any received box model modifiers, or colspan or rowspan objects, to the current cell. A cell can only be modified from when it is reached for the first time. When colspan or rowspan have been previously used, then the next time you could presume to have reached the same cell again it will in actuality be skipped and the next cell in definition order will have been reached instead.

Make sure you keep in mind the natural order of the table, or things might segfault on you. Mentally, divide the picture of the table you want to draw into a grid. On this grid, imagine colspan and rowspan repeat the same contents amongst the number of cells they span. If cell contents overlap in this mental picture, then there is something wrong with the definition, and a segfault will occur. Also make sure there are no cells undefined in this mental grid overlay.

Tables are block-elements, as are cells within.

<
>
Example:
os << begin_table(false)
   <<    "1x1"
   <<    column_break
   <<    "1x2"
   <<    column_break
   <<    "1x3"
   <<    rowspan(2)
   << row_break
   <<    "2x1"
   <<    colspan(2)
   << row_break
   <<    "3x1"
   <<    column_break
   <<    "3x2"
   <<    column_break
   <<    "3x3"
   << end_table
   << std::flush;
Output:
╭───╮╭───╮╭───╮
│1x1││1x2││1x3│
╰───╯╰───╯│   │
╭────────╮│   │
│2x1     ││   │
╰────────╯╰───╯
╭───╮╭───╮╭───╮
│3x1││3x2││3x3│
╰───╯╰───╯╰───╯
005
I can not stress this enough, but I can

Underline

underline

Signals that the text starting on the previous line but on the same position be underlined, by inserting the same number of unicode horizontal line drawing characters as there are characters on the previous line before a space character is encountered there. To underline the complete previous line in this manner, see ‘underline_all’.

underline_all

Signals that the text starting on the previous line but on the same position be underlined, by inserting a number of unicode horizontal line drawing characters equal to the number of characters on the previous line. To stop the line at encounter of a space character, use ‘underline’ instead.

This kind of underline adds no elements, but types text in the current element.

Note: When ANSI-code interpretation is available, the underline provided by wash_separately can be more useful.

Example:
os << "This text is underlined\n"
   << underline_all << "\nAnd this text isn't.";

os << std::flush;
Output:
This text is underlined
───────────────────────
And this text isn't.
<
>
006
The ellipsoid model is still in development. For now, please resort to the

Box model

padding(top,right,bottom,left)
padding(topbottom,rightleft)
padding(topbottomrightleft)

Stream a ‘padding’ to define the space between the content of a block element and its border.

border(top,right,bottom,left)
border(topbottom,rightleft)
border(topbottomrightleft)

Stream a ‘border’ to define the width of the border between the padding of a block element and its margin.

margin(top,right,bottom,left)
margin(topbottom,rightleft)
margin(topbottomrightleft)

Stream a ‘margin’ to define the widths of space around the border of a block element.

separator(width)

Only affects colums, rows, or sections thereof. Set number of separators.

Box-border manipulators operate on block-elements only.

Example:
os << begin_table(false) << border(2) 
                   << "1x1" << padding(1)
   << column_break << "1x2" << padding(2) << border(2)
   << column_break << "1x3" << rowspan(2)
   << row_break    << "2x1" << colspan(2)
   << row_break    << "3x1"
   << column_break << "3x2" << border(1,2,2,1)
   << column_break << "3x3" << margin(1)
   << end_table
   << std::flush;
Output:
╭───────────────────────────╮
│╭─────────────────────────╮│
││╭─────╮╭─────────╮╭─────╮││
│││     ││╭───────╮││1x3  │││
│││ 1x1 │││       │││     │││
│││     │││       │││     │││
│││     │││  1x2  │││     │││
│││     │││       │││     │││
│││     │││       │││     │││
│││     ││╰───────╯││     │││
││╰─────╯╰─────────╯│     │││
││╭────────────────╮│     │││
│││2x1             ││     │││
││╰────────────────╯╰─────╯││
││╭─────╮╭────────╮╮       ││
│││3x1  ││3x2     ││ ╭───╮ ││
│││     ││        ││ │3x3│ ││
│││     ││╰───────╯│ ╰───╯ ││
││╰─────╯╰─────────╯       ││
│╰─────────────────────────╯│
╰───────────────────────────╯
<
>
007
Going to war with the

Bulleted list

list

Signals the beginning of a list.

item

Signals the beginning of an item (also the end of any previous item).

end_list

Signals the end of a list.

Lists are block-elements, as are items.

Example:
os << list
   << item << "Potatoes"
   << item << "Tomatoes"
   << item << "Toilet paper"
   << item << "Toilet paper"
   << item << "Toilet paper\n"
           << "Toilet paper"
   << item << "..."
   << std::flush;
Output:
 • Potatoes    
               
 • Tomatoes    
               
 • Toilet paper
               
 • Toilet paper
               
 • Toilet paper
   Toilet paper
                
 • ...
<