# subiquity design notes
## UI
### basic ground rules:
1. Subiquity is entirely usable by pressing up, down, space (or return) and the
occasional bit of typing.
2. The UI never blocks. If something takes more than about 0.1s, it is done
in the background, possibly with some kind of indication in the UI and the
ability to cancel if appropriate. (We should consider making sure that if
we pop up a progress dialog while something happens -- e.g. applying
keyboard configuration, which the user just has to wait for until going on
to the next screen -- that the dialog appears for at least, say, 0.5s to
avoid flickering the UI).
3. General UX principles that it is worth keeping in mind:
1. Prevent invalid use if that makes sense (e.g. unix usernames can never
contain spaces, so you simply can't enter spaces in that box)
2. When rejecting input, be clear about that to the user and explain what
they need to do differently (e.g. when you do try to put a space in a
unix username, a message appears explaining which characters are valid).
3. Make the common case as easy as possible by doing things like thinking
about which widget should be highlighted when a screen is first shown.
4. Subiquity is functional in an 80x24 terminal. It doesn't matter if it falls
apart in a smaller terminal and obviously you can get more information on a
larger terminal at once, but it needs to work in 80x24.
### urwid specific ranting
subiquity is built using the [urwid](http://urwid.org/) console user interface
library for Python. urwid is mostly fine but has some design decisions that
have meant that we're sort of slowly re-implementing pieces of it.
The main one of these is that in urwid, widgets do not have a size; they
inherit it from their parent widget. While this is unavoidable for the "outer"
widgets (subiquity does not get to decide the size of the console it runs in!)
I don't think it leads to a good appearance for things like stacked columns of
buttons, which we want to fit to label length (and label length depends on
which language it is being used in!). There is a similar tension around having
scroll bars that are only shown when needed (scroll bars should only be shown
when the contained widget "wants" to be taller than the space available for
it).
subiquity has a few generic facilities for handling these:
* The `subiquitycore.ui.containers` module defines a `ListBox` class that
automatically handles scroll bars. It is used everywhere instead of urwid's
`ListBox` class (it does not support lazy construction of widgets like
urwid's does).
* The `subiquitycore.ui.stretchy` module defines classes for creating modal
dialogs out of stacks of widgets that fit to their content (and let you say
which widget to scroll if the content is too tall to fit on the screen).
* The `subiquitycore.ui.width` module defines a `widget_width` function, which
knows how wide a widget "wants" to be (as above, this isn't a concept urwid
comes with).
* The `subiquitycore.ui.table` module defines classes for creating Tables that
act a little like `
` elements in HTML.
Subiquity also has replacements for the standard containers that handle tab
cycling (i.e. tab advances to the next element and wraps around to the
beginning when at the end).
urwid can be extremely frustrating to work with, but usually a good UI can be
implemented after sufficient swearing.
### The typical screen
A subiquity screen consists of:
1. a header
2. a body area, which usually contains
1. an excerpt (which explains what this screen is for)
2. a scrollable content area
3. a stack of buttons, including "done"/"cancel" buttons for moving between
screens
The header has a summary line describing the current screen against an "ubuntu
orange" background.
The body area is where most of the action is. It follows a standard pattern
described above, and the `subiquitycore.ui.utils.screen()` function makes it
very easy to follow that pattern. Many screen have "sub-dialogs" (think:
editing the addresses for a NIC) which can be as large as the whole body area
but are often smaller. The base view class has `show_overlay`/`hide_overlay`
methods for handling these.
### Custom widgets
subiquity defines a few generic widgets that are used in several places.
`Selector` is a bit like an html `