summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorIan Ward <ian@excess.org>2012-09-22 20:31:01 -0400
committerIan Ward <ian@excess.org>2012-09-22 20:31:01 -0400
commitdaefdead5fad770775aa584fc61ea55ef3e8ac89 (patch)
tree9af532ce1c5c32542f2fa20a311055c40984975f /docs
parent9e73e7756f277a5edd6954043729d03fb47c8ca2 (diff)
downloadurwid-daefdead5fad770775aa584fc61ea55ef3e8ac89.tar.gz
docs: move some sections from tutorial to widget manual page
--HG-- branch : feature-sphinx rename : docs/tutorial/wanat.py => docs/manual/wanat.py rename : docs/tutorial/wanat_multi.py => docs/manual/wanat_multi.py rename : docs/tutorial/wanat_new.py => docs/manual/wanat_new.py rename : docs/tutorial/wcur1.py => docs/manual/wcur1.py rename : docs/tutorial/wcur2.py => docs/manual/wcur2.py rename : docs/tutorial/wmod.py => docs/manual/wmod.py rename : docs/tutorial/wsel.py => docs/manual/wsel.py
Diffstat (limited to 'docs')
-rw-r--r--docs/manual/wanat.py (renamed from docs/tutorial/wanat.py)0
-rw-r--r--docs/manual/wanat_multi.py (renamed from docs/tutorial/wanat_multi.py)0
-rw-r--r--docs/manual/wanat_new.py (renamed from docs/tutorial/wanat_new.py)0
-rw-r--r--docs/manual/wcur1.py (renamed from docs/tutorial/wcur1.py)0
-rw-r--r--docs/manual/wcur2.py (renamed from docs/tutorial/wcur2.py)0
-rw-r--r--docs/manual/widgets.rst415
-rw-r--r--docs/manual/wmod.py (renamed from docs/tutorial/wmod.py)0
-rw-r--r--docs/manual/wsel.py (renamed from docs/tutorial/wsel.py)0
-rw-r--r--docs/tutorial/index.rst385
9 files changed, 381 insertions, 419 deletions
diff --git a/docs/tutorial/wanat.py b/docs/manual/wanat.py
index 723eb90..723eb90 100644
--- a/docs/tutorial/wanat.py
+++ b/docs/manual/wanat.py
diff --git a/docs/tutorial/wanat_multi.py b/docs/manual/wanat_multi.py
index b6d6943..b6d6943 100644
--- a/docs/tutorial/wanat_multi.py
+++ b/docs/manual/wanat_multi.py
diff --git a/docs/tutorial/wanat_new.py b/docs/manual/wanat_new.py
index 5a597b9..5a597b9 100644
--- a/docs/tutorial/wanat_new.py
+++ b/docs/manual/wanat_new.py
diff --git a/docs/tutorial/wcur1.py b/docs/manual/wcur1.py
index 6bf97f7..6bf97f7 100644
--- a/docs/tutorial/wcur1.py
+++ b/docs/manual/wcur1.py
diff --git a/docs/tutorial/wcur2.py b/docs/manual/wcur2.py
index 1225419..1225419 100644
--- a/docs/tutorial/wcur2.py
+++ b/docs/manual/wcur2.py
diff --git a/docs/manual/widgets.rst b/docs/manual/widgets.rst
index 0bea599..f464af4 100644
--- a/docs/manual/widgets.rst
+++ b/docs/manual/widgets.rst
@@ -229,49 +229,65 @@ an unbounded number of positions, so care should be used with this interface and
:class:`ListBox`.
-Customizing Widgets
-===================
+Pile Widgets
+------------
-Widgets in Urwid are easiest to create by extending other widgets. If you are
-making a new type of widget that can use other widgets to display its content,
-like a new type of button or control, then you should start by extending
-:class:`WidgetWrap` and passing the display widget to its constructor.
+:class:`Pile` widgets are used to combine multiple widgets by
+stacking them vertically. A Pile can manage selectable widgets by keeping track
+of which widget is in focus and it can handle moving the focus between widgets
+when the user presses the *UP* and *DOWN* keys. A Pile will also work well when
+used within a :class:`ListBox`.
-The :class:`Widget` interface is described in detail in the
-:class:`Widget base class reference <Widget>` and is useful if you're looking to modify
-the behavior of an existing widget,
-build a new widget class from scratch or just want a better understanding of
-the library.
+A Pile is selectable only if its focus widget is selectable. If you create a
+Pile containing one Text widget and one Edit widget the Pile will choose the
+Edit widget as its default focus widget.
-One Urwid design choice that stands out is that widgets typically have no
-size. Widgets don't store their size on screen, and instead are
-passed that information when they need it.
-This choice has some advantages:
+Columns Widgets
+---------------
-* widgets may be reused in different locations
-* reused widgets only need to be rendered once per size displayed
-* widgets don't need to know their parents
-* less data to store and update
-* no worrying about widgets that haven't received their size yet
-* same widgets could be displayed at different sizes to different users
- simultaneously
+:class:`Columns` widgets may be used to arrange either flow
+widgets or box widgets horizontally into columns. Columns widgets will manage
+selectable widgets by keeping track of which column is in focus and it can
+handle moving the focus between columns when the user presses the *LEFT* and
+*RIGHT* keys. Columns widgets also work well when used within a
+:class:`ListBox`.
-It also has disadvantages:
+Columns widgets are selectable only if the column in focus is selectable. If a
+focus column is not specified the first selectable widget will be chosen as the
+focus column.
-* difficult to determine a widget's size on screen
-* more parameters to parse
-* duplicated size calculations across methods
-For determining a widget's size on screen it is possible to look up the size(s)
-it was rendered at in the :class:`CanvasCache`. There are plans
-to address some of the duplicated size handling code in the container widgets
-in a future Urwid release.
+GridFlow Widgets
+----------------
-The same holds true for a widget's focus state, so that too is passed in to
-functions that need it.
+The :class:`GridFlow` widget is a flow widget designed for use
+with :class:`Button`, :class:`CheckBox` and
+:class:`RadioButton` widgets. It renders all the widgets it
+contains the same width and it arranges them from left to right and top to
+bottom.
+
+The GridFlow widget uses Pile, Columns, Padding and Divider widgets to build a
+display widget that will handle the keyboard input and rendering. When the
+GridFlow widget is resized it regenerates the display widget to accommodate the
+new space.
+
+
+Overlay Widgets
+---------------
+
+The :class:`Overlay` widget is a box widget that contains two
+other box widgets. The bottom widget is rendered the full size of the Overlay
+widget and the top widget is placed on top, obscuring an area of the bottom
+widget. This widget can be used to create effects such as overlapping "windows"
+or pop-up menus.
+
+The Overlay widget always treats the top widget as the one in focus. All
+keyboard input will be passed to the top widget.
+
+If you want to use a flow flow widget for the top widget, first wrap the flow
+widget with a :class:`Filler` widget.
-.. seealso:: :ref:`creating-custom-widgets`
.. _listbox-contents:
@@ -284,6 +300,153 @@ Its contents are displayed stacked vertically, and the
One of the flow widgets displayed in the :class:`ListBox` is its
focus widget.
+ListBox Focus and Scrolling
+---------------------------
+
+The :class:`ListBox` is a box widget that contains flow widgets.
+Its contents are displayed stacked vertically, and the
+:class:`ListBox` allows the user to scroll through its content.
+One of the flow widgets displayed in the :class:`ListBox` is the
+focus widget. The :class:`ListBox` passes key presses to the
+focus widget to allow the user to interact with it. If the focus widget does
+not handle a keypress then the :class:`ListBox` may handle the
+keypress by scrolling and/or selecting another widget to become the focus
+widget.
+
+The :class:`ListBox` tries to do the most sensible thing when
+scrolling and changing focus. When the widgets displayed are all
+:class:`Text` widgets or other unselectable widgets then the
+:class:`ListBox` will behave like a web browser does when the
+user presses *UP*, *DOWN*, *PAGE UP* and *PAGE DOWN*: new text is immediately
+scrolled in from the top or bottom. The :class:`ListBox` chooses
+one of the visible widgets as its focus widget when scrolling. When scrolling
+up the :class:`ListBox` chooses the topmost widget as the focus,
+and when scrolling down the :class:`ListBox` chooses the
+bottommost widget as the focus.
+
+The :class:`ListBox` remembers the location of the widget in
+focus as either an "offset" or an "inset". An offset is the number of rows
+between the top of the :class:`ListBox` and the beginning of the
+focus widget. An offset of zero corresponds to a widget with its top aligned
+with the top of the :class:`ListBox`. An inset is the fraction
+of rows of the focus widget that are "above" the top of the
+:class:`ListBox` and not visible. The
+:class:`ListBox` uses this method of remembering the focus
+widget location so that when the :class:`ListBox` is resized the
+text displayed will stay roughly aligned with the top of the
+:class:`ListBox`.
+
+When there are selectable widgets in the :class:`ListBox` the
+focus will move between the selectable widgets, skipping the unselectable
+widgets. The :class:`ListBox` will try to scroll all the rows of
+a selectable widget into view so that the user can see the new focus widget in
+its entirety. This behavior can be used to bring more than a single widget into
+view by using composite widgets to combine a selectable widget with other
+widgets that should be displayed at the same time.
+
+
+Dynamic ListBox with ListWalker
+-------------------------------
+
+While the :class:`ListBox` stores the location of its focus
+widget, it does not directly store the actual focus widget or other contents of
+the :class:`ListBox`. The storage of a
+:class:`ListBox`'s content is delegated to a "List Walker"
+object. If a list of widgets is passed to the :class:`ListBox`
+constructor then it creates a :class:`SimpleListWalker` object
+to manage the list.
+
+When the :class:`ListBox` is `rendering a canvas`_ or `handling
+input`_ it will:
+
+.. _rendering a canvas: :meth:`ListBox.render`
+.. _handling input: :meth:`ListBox.keypress`
+
+1. Call the :meth:`get_focus` method of its list walker object. This method
+ will return the focus widget and a position object.
+2. Optionally call the :meth:`get_prev` method of its List Walker object one or
+ more times, initially passing the focus position and then passing the new
+ position returned on each successive call. This method will return the
+ widget and position object "above" the position passed.
+3. Optionally call the :meth:`get_next` method of its List Walker object one or
+ more times, similarly, to collect widgets and position objects "below" the
+ focus position.
+4. Optionally call the :meth:`set_focus` method passing one of the position
+ objects returned in the previous steps.
+
+This is the only way the :class:`ListBox` accesses its contents,
+and it will not store copies of any of the widgets or position objects beyond
+the current rendering or input handling operation.
+
+The :class:`SimpleListWalker` stores a list of widgets, and uses
+integer indexes into this list as its position objects. It stores the focus
+position as an integer, so if you insert a widget into the list above the focus
+position then you need to remember to increment the focus position in the
+:class:`SimpleListWalker` object or the contents of the
+:class:`ListBox` will shift.
+
+A custom List Walker object may be passed to the
+:class:`ListBox` constructor instead of a plain list of widgets.
+List Walker objects must implement the :ref:`list-walker-interface`.
+
+The fib.py_ example program demonstrates a custom list walker that doesn't
+store any widgets. It uses a tuple of two successive Fibonacci numbers as its
+position objects and it generates Text widgets to display the numbers on the
+fly. The result is a :class:`ListBox` that can scroll through an
+unending list of widgets.
+
+The edit.py_ example program demonstrates a custom list walker that loads lines
+from a text file only as the user scrolls them into view. This allows even
+huge files to be opened almost instantly.
+
+The browse.py_ example program demonstrates a custom list walker that uses a
+tuple of strings as position objects, one for the parent directory and one for
+the file selected. The widgets are cached in a separate class that is accessed
+using a dictionary indexed by parent directory names. This allows the
+directories to be read only as required. The custom list walker also allows
+directories to be hidden from view when they are "collapsed".
+
+.. _fib.py: http://excess.org/urwid/browser/examples/fib.py
+.. _edit.py: http://excess.org/urwid/browser/examples/edit.py
+.. _browse.py: http://excess.org/urwid/browser/examples/browse.py
+
+
+Setting the Focus
+-----------------
+
+The easiest way to change the current :class:`ListBox` focus is
+to call the :meth:`ListBox.set_focus` method. This method doesn't
+require that you know the :class:`ListBox`'s current dimensions
+``(maxcol, maxrow)``. It will wait until the next call to either keypress or
+render to complete setting the offset and inset values using the dimensions
+passed to that method.
+
+The position object passed to :meth:`set_focus` must be compatible with the
+List Walker object that the :class:`ListBox` is using. For
+:class:`SimpleListWalker` the position is the integer index of
+the widget within the list.
+
+The *coming_from* parameter should be set if you know that the old position is
+"above" or "below" the previous position. When the
+:class:`ListBox` completes setting the offset and inset values
+it tries to find the old widget among the visible widgets. If the old widget is
+still visible, if will try to avoid causing the :class:`ListBox`
+contents to scroll up or down from its previous position. If the widget is not
+visible, then the :class:`ListBox` will:
+
+* Display the new focus at the bottom of the :class:`ListBox` if
+ *coming_from* is "above".
+* Display the new focus at the top of the :class:`ListBox` if
+ *coming_from* is "below".
+* Display the new focus in the middle of the :class:`ListBox` if
+ coming_from is ``None``.
+
+If you know exactly where you want to display the new focus widget within the
+:class:`ListBox` you may call
+:meth:`ListBox.set_focus_valign`. This method lets you specify
+the *top*, *bottom*, *middle*, a relative position or the exact number of rows
+from the top or bottom of the :class:`ListBox`.
+
List Walkers
------------
@@ -423,7 +586,191 @@ This behavior can be used to bring more than a single widget into view by using
a :class:`Pile` or other container widget to combine a
selectable widget with other widgets that should be visible at the same time.
-.. seealso:: :ref:`Tutorial chapters covering ListBox usage <zen-listbox>`
+
+Customizing Widgets
+===================
+
+Widgets in Urwid are easiest to create by extending other widgets. If you are
+making a new type of widget that can use other widgets to display its content,
+like a new type of button or control, then you should start by extending
+:class:`WidgetWrap` and passing the display widget to its constructor.
+
+The :class:`Widget` interface is described in detail in the
+:class:`Widget base class reference <Widget>` and is useful if you're looking to modify
+the behavior of an existing widget,
+build a new widget class from scratch or just want a better understanding of
+the library.
+
+One Urwid design choice that stands out is that widgets typically have no
+size. Widgets don't store their size on screen, and instead are
+passed that information when they need it.
+
+This choice has some advantages:
+
+* widgets may be reused in different locations
+* reused widgets only need to be rendered once per size displayed
+* widgets don't need to know their parents
+* less data to store and update
+* no worrying about widgets that haven't received their size yet
+* same widgets could be displayed at different sizes to different users
+ simultaneously
+
+It also has disadvantages:
+
+* difficult to determine a widget's size on screen
+* more parameters to parse
+* duplicated size calculations across methods
+
+For determining a widget's size on screen it is possible to look up the size(s)
+it was rendered at in the :class:`CanvasCache`. There are plans
+to address some of the duplicated size handling code in the container widgets
+in a future Urwid release.
+
+The same holds true for a widget's focus state, so that too is passed in to
+functions that need it.
+
+
+Modifying Existing Widgets
+--------------------------
+
+The easiest way to create a custom widget is to modify an existing widget.
+This can be done by either subclassing the original widget or by wrapping it.
+Subclassing is appropriate when you need to interact at a very low level with
+the original widget, such as if you are creating a custom edit widget with
+different behavior than the usual Edit widgets. If you are creating a custom
+widget that doesn't need tight coupling with the original widget, such as a
+widget that displays customer address information, then wrapping is more
+appropriate.
+
+The :class:`WidgetWrap` class simplifies wrapping existing
+widgets. You can create a custom widget simply by creating a subclass of
+WidgetWrap and passing a widget into WidgetWrap's constructor.
+
+
+This is an example of a custom widget that uses WidgetWrap:
+
+.. literalinclude:: wmod.py
+ :linenos:
+
+The above code creates a group of RadioButtons and provides a method to
+query the state of the buttons.
+
+
+Anatomy of a Widget
+-------------------
+
+Any object that follows the `Widget interface definition`_ may be used as a
+widget. Box widgets must implement selectable_ and render_ methods, and flow
+widgets must implement selectable, render and rows_ methods.
+
+.. _Widget interface definition: :class:`Widget`
+.. _selectable: :meth:`Widget.selectable`
+.. _render: :meth:`Widget.render`
+.. _rows: :meth:`Widget.rows`
+
+.. literalinclude:: wanat.py
+ :linenos:
+
+The above code implements two widget classes. Pudding is a flow widget and
+BoxPudding is a box widget. Pudding will render as much "Pudding" as will fit
+in a single row, and BoxPudding will render as much "Pudding" as will fit into
+the entire area given.
+
+Note that the rows and render methods' focus parameter must have a default
+value of False. Also note that for flow widgets the number of rows returned by
+the rows method must match the number of rows rendered by the render method.
+
+In most cases it is easier to let other widgets handle the rendering and row
+calculations for you:
+
+.. literalinclude:: wanat_new.py
+ :linenos:
+
+The NewPudding class behaves the same way as the Pudding class above, but in
+NewPudding you can change the way the widget appears by modifying only the
+display_widget method, whereas in the Pudding class you may have to modify both
+the render and rows methods.
+
+To improve the efficiency of your Urwid application you should be careful of
+how long your rows methods take to execute. The rows methods may be called many
+times as part of input handling and rendering operations. If you are using a
+display widget that is time consuming to create you should consider caching it
+to reduce its impact on performance.
+
+It is possible to create a widget that will behave as either a flow widget or
+box widget depending on what is required:
+
+.. literalinclude:: wanat_multi.py
+ :linenos:
+
+MultiPudding will work in place of either Pudding or BoxPudding above. The
+number of elements in the size tuple determines whether the containing widget
+is expecting a flow widget or a box widget.
+
+
+Creating a Selectable Widget
+----------------------------
+
+Selectable widgets such as Edit and Button widgets allow the user to interact
+with the application. A widget is selectable if its selectable method returns
+True. Selectable widgets must implement the keypress_ method to handle keyboard
+input.
+
+.. _keypress: :meth:`Widget.keypress`
+
+.. literalinclude:: wsel.py
+
+The SelectablePudding widget will display its contents in uppercase when it is
+in focus, and it allows the user to "eat" the pudding by pressing each of the
+letters *P*, *U*, *D*, *D*, *I*, *N* and *G* on the keyboard. When the user has
+"eaten" all the pudding the widget will reset to its initial state.
+
+Note that keys that are unhandled in the keypress method are returned so that
+another widget may be able to handle them. This is a good convention to follow
+unless you have a very good reason not to. In this case the *UP* and *DOWN*
+keys are returned so that if this widget is in a
+:class:`ListBox` the :class:`ListBox` will behave
+as the user expects and change the focus or scroll the
+:class:`ListBox`.
+
+Widget Displaying the Cursor
+----------------------------
+
+Widgets that display the cursor must implement the get_cursor_coords_ method.
+Similar to the rows method for flow widgets, this method lets other widgets
+make layout decisions without rendering the entire widget. The
+:class:`ListBox` widget in particular uses get_cursor_coords to
+make sure that the cursor is visible within its focus widget.
+
+.. _get_cursor_coords: :meth:`Widget.get_cursor_coords`
+
+.. literalinclude:: wcur1.py
+ :linenos:
+
+CursorPudding will let the user move the cursor through the widget by pressing
+*LEFT* and *RIGHT*. The cursor must only be added to the canvas when the widget
+is in focus. The get_cursor_coords method must always return the same cursor
+coordinates that render does.
+
+A widget displaying a cursor may choose to implement get_pref_col. This method
+returns the preferred column for the cursor, and is called when the focus is
+moving up or down off this widget.
+
+.. _get_pref_col: :meth:`Widget.get_pref_col`
+
+Another optional method is move_cursor_to_coords_. This method allows other
+widgets to try to position the cursor within this widget. The
+:class:`ListBox` widget uses :meth:`move_cursor_to_coords` when
+changing focus and when the user pressed *PAGE UP* or *PAGE DOWN*. This method
+must return ``True`` on success and ``False`` on failure. If the cursor may be
+placed at any position within the row specified (not only at the exact column
+specified) then this method must move the cursor to that position and return
+``True``.
+
+.. _move_cursor_to_coords: :meth:`Widget.move_cursor_to_coords`
+
+.. literalinclude:: wcur2.py
+ :linenos:
Widget Metaclass
diff --git a/docs/tutorial/wmod.py b/docs/manual/wmod.py
index a066a49..a066a49 100644
--- a/docs/tutorial/wmod.py
+++ b/docs/manual/wmod.py
diff --git a/docs/tutorial/wsel.py b/docs/manual/wsel.py
index 15683d8..15683d8 100644
--- a/docs/tutorial/wsel.py
+++ b/docs/manual/wsel.py
diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst
index 24de181..1e2ef2b 100644
--- a/docs/tutorial/index.rst
+++ b/docs/tutorial/index.rst
@@ -331,390 +331,5 @@ default decorations
.. image:: menu43.png
.. image:: menu44.png
-.. _zen-listbox:
-
-Zen of ListBox
-==============
-
-ListBox Focus and Scrolling
----------------------------
-
-The :class:`ListBox` is a box widget that contains flow widgets.
-Its contents are displayed stacked vertically, and the
-:class:`ListBox` allows the user to scroll through its content.
-One of the flow widgets displayed in the :class:`ListBox` is the
-focus widget. The :class:`ListBox` passes key presses to the
-focus widget to allow the user to interact with it. If the focus widget does
-not handle a keypress then the :class:`ListBox` may handle the
-keypress by scrolling and/or selecting another widget to become the focus
-widget.
-
-The :class:`ListBox` tries to do the most sensible thing when
-scrolling and changing focus. When the widgets displayed are all
-:class:`Text` widgets or other unselectable widgets then the
-:class:`ListBox` will behave like a web browser does when the
-user presses *UP*, *DOWN*, *PAGE UP* and *PAGE DOWN*: new text is immediately
-scrolled in from the top or bottom. The :class:`ListBox` chooses
-one of the visible widgets as its focus widget when scrolling. When scrolling
-up the :class:`ListBox` chooses the topmost widget as the focus,
-and when scrolling down the :class:`ListBox` chooses the
-bottommost widget as the focus.
-
-When all the widgets displayed are not selectable the user would typically have
-no way to tell which widget is in focus, but if we wrap the widgets with
-:class:`AttrWrap` we can see what is happening while the
-focus changes:
-
-.. literalinclude:: lbscr.py
- :linenos:
-
-.. image:: lbscr1.png
-.. image:: lbscr2.png
-.. image:: lbscr3.png
-.. image:: lbscr4.png
-.. image:: lbscr5.png
-.. image:: lbscr6.png
-
-The :class:`ListBox` remembers the location of the widget in
-focus as either an "offset" or an "inset". An offset is the number of rows
-between the top of the :class:`ListBox` and the beginning of the
-focus widget. An offset of zero corresponds to a widget with its top aligned
-with the top of the :class:`ListBox`. An inset is the fraction
-of rows of the focus widget that are "above" the top of the
-:class:`ListBox` and not visible. The
-:class:`ListBox` uses this method of remembering the focus
-widget location so that when the :class:`ListBox` is resized the
-text displayed will stay roughly aligned with the top of the
-:class:`ListBox`.
-
-.. image:: lbscr7.png
-.. image:: lbscr8.png
-.. image:: lbscr9.png
-
-When there are selectable widgets in the :class:`ListBox` the
-focus will move between the selectable widgets, skipping the unselectable
-widgets. The :class:`ListBox` will try to scroll all the rows of
-a selectable widget into view so that the user can see the new focus widget in
-its entirety. This behavior can be used to bring more than a single widget into
-view by using composite widgets to combine a selectable widget with other
-widgets that should be displayed at the same time.
-
-
-Dynamic ListBox with ListWalker
--------------------------------
-
-While the :class:`ListBox` stores the location of its focus
-widget, it does not directly store the actual focus widget or other contents of
-the :class:`ListBox`. The storage of a
-:class:`ListBox`'s content is delegated to a "List Walker"
-object. If a list of widgets is passed to the :class:`ListBox`
-constructor then it creates a :class:`SimpleListWalker` object
-to manage the list.
-
-When the :class:`ListBox` is `rendering a canvas`_ or `handling
-input`_ it will:
-
-.. _rendering a canvas: :meth:`ListBox.render`
-.. _handling input: :meth:`ListBox.keypress`
-
-1. Call the :meth:`get_focus` method of its list walker object. This method
- will return the focus widget and a position object.
-2. Optionally call the :meth:`get_prev` method of its List Walker object one or
- more times, initially passing the focus position and then passing the new
- position returned on each successive call. This method will return the
- widget and position object "above" the position passed.
-3. Optionally call the :meth:`get_next` method of its List Walker object one or
- more times, similarly, to collect widgets and position objects "below" the
- focus position.
-4. Optionally call the :meth:`set_focus` method passing one of the position
- objects returned in the previous steps.
-
-This is the only way the :class:`ListBox` accesses its contents,
-and it will not store copies of any of the widgets or position objects beyond
-the current rendering or input handling operation.
-
-The :class:`SimpleListWalker` stores a list of widgets, and uses
-integer indexes into this list as its position objects. It stores the focus
-position as an integer, so if you insert a widget into the list above the focus
-position then you need to remember to increment the focus position in the
-:class:`SimpleListWalker` object or the contents of the
-:class:`ListBox` will shift.
-
-A custom List Walker object may be passed to the
-:class:`ListBox` constructor instead of a plain list of widgets.
-List Walker objects must implement the :ref:`list-walker-interface`.
-
-The fib.py_ example program demonstrates a custom list walker that doesn't
-store any widgets. It uses a tuple of two successive Fibonacci numbers as its
-position objects and it generates Text widgets to display the numbers on the
-fly. The result is a :class:`ListBox` that can scroll through an
-unending list of widgets.
-
-The edit.py_ example program demonstrates a custom list walker that loads lines
-from a text file only as the user scrolls them into view. This allows even
-huge files to be opened almost instantly.
-
-The browse.py_ example program demonstrates a custom list walker that uses a
-tuple of strings as position objects, one for the parent directory and one for
-the file selected. The widgets are cached in a separate class that is accessed
-using a dictionary indexed by parent directory names. This allows the
-directories to be read only as required. The custom list walker also allows
-directories to be hidden from view when they are "collapsed".
-
-.. _fib.py: http://excess.org/urwid/browser/examples/fib.py
-.. _edit.py: http://excess.org/urwid/browser/examples/edit.py
-.. _browse.py: http://excess.org/urwid/browser/examples/browse.py
-
-
-Setting the Focus
------------------
-
-The easiest way to change the current :class:`ListBox` focus is
-to call the :meth:`ListBox.set_focus` method. This method doesn't
-require that you know the :class:`ListBox`'s current dimensions
-``(maxcol, maxrow)``. It will wait until the next call to either keypress or
-render to complete setting the offset and inset values using the dimensions
-passed to that method.
-
-The position object passed to :meth:`set_focus` must be compatible with the
-List Walker object that the :class:`ListBox` is using. For
-:class:`SimpleListWalker` the position is the integer index of
-the widget within the list.
-
-The *coming_from* parameter should be set if you know that the old position is
-"above" or "below" the previous position. When the
-:class:`ListBox` completes setting the offset and inset values
-it tries to find the old widget among the visible widgets. If the old widget is
-still visible, if will try to avoid causing the :class:`ListBox`
-contents to scroll up or down from its previous position. If the widget is not
-visible, then the :class:`ListBox` will:
-
-* Display the new focus at the bottom of the :class:`ListBox` if
- *coming_from* is "above".
-* Display the new focus at the top of the :class:`ListBox` if
- *coming_from* is "below".
-* Display the new focus in the middle of the :class:`ListBox` if
- coming_from is ``None``.
-
-If you know exactly where you want to display the new focus widget within the
-:class:`ListBox` you may call
-:meth:`ListBox.set_focus_valign`. This method lets you specify
-the *top*, *bottom*, *middle*, a relative position or the exact number of rows
-from the top or bottom of the :class:`ListBox`.
-
-
-Combining Widgets
-=================
-
-
-Piling Widgets
---------------
-
-:class:`Pile` widgets are used to combine multiple widgets by
-stacking them vertically. A Pile can manage selectable widgets by keeping track
-of which widget is in focus and it can handle moving the focus between widgets
-when the user presses the *UP* and *DOWN* keys. A Pile will also work well when
-used within a :class:`ListBox`.
-
-A Pile is selectable only if its focus widget is selectable. If you create a
-Pile containing one Text widget and one Edit widget the Pile will choose the
-Edit widget as its default focus widget. To change the pile's focus widget you
-can call :meth:`Pile.set_focus`.
-
-
-Dividing into Columns
----------------------
-
-:class:`Columns` widgets may be used to arrange either flow
-widgets or box widgets horizontally into columns. Columns widgets will manage
-selectable widgets by keeping track of which column is in focus and it can
-handle moving the focus between columns when the user presses the *LEFT* and
-*RIGHT* keys. Columns widgets also work well when used within a
-:class:`ListBox`.
-
-Columns widgets are selectable only if the column in focus is selectable. If a
-focus column is not specified the first selectable widget will be chosen as the
-focus column. The :meth:`Columns.set_focus` method may be used
-to select the focus column.
-
-
-``GridFlow`` Arrangment
------------------------
-
-The :class:`GridFlow` widget is a flow widget designed for use
-with :class:`Button`, :class:`CheckBox` and
-:class:`RadioButton` widgets. It renders all the widgets it
-contains the same width and it arranges them from left to right and top to
-bottom.
-
-The GridFlow widget uses Pile, Columns, Padding and Divider widgets to build a
-display widget that will handle the keyboard input and rendering. When the
-GridFlow widget is resized it regenerates the display widget to accommodate the
-new space.
-
-
-``Overlay`` widgets
--------------------
-
-The :class:`Overlay` widget is a box widget that contains two
-other box widgets. The bottom widget is rendered the full size of the Overlay
-widget and the top widget is placed on top, obscuring an area of the bottom
-widget. This widget can be used to create effects such as overlapping "windows"
-or pop-up menus.
-
-The Overlay widget always treats the top widget as the one in focus. All
-keyboard input will be passed to the top widget.
-
-If you want to use a flow flow widget for the top widget, first wrap the flow
-widget with a :class:`Filler` widget.
-
-
-
-.. _creating-custom-widgets:
-
-Creating Custom Widgets
-=======================
-
-
-Modifying Existing Widgets
---------------------------
-
-The easiest way to create a custom widget is to modify an existing widget.
-This can be done by either subclassing the original widget or by wrapping it.
-Subclassing is appropriate when you need to interact at a very low level with
-the original widget, such as if you are creating a custom edit widget with
-different behavior than the usual Edit widgets. If you are creating a custom
-widget that doesn't need tight coupling with the original widget, such as a
-widget that displays customer address information, then wrapping is more
-appropriate.
-
-The :class:`WidgetWrap` class simplifies wrapping existing
-widgets. You can create a custom widget simply by creating a subclass of
-WidgetWrap and passing a widget into WidgetWrap's constructor.
-
-This is an example of a custom widget that uses WidgetWrap:
-
-.. literalinclude:: wmod.py
- :linenos:
-
-The above code creates a group of RadioButtons and provides a method to
-query the state of the buttons.
-
-Wrapped widgets may also override the standard widget methods. These methods
-are described in following sections.
-
-Anatomy of a Widget
--------------------
-
-Any object that follows the `Widget interface definition`_ may be used as a
-widget. Box widgets must implement selectable_ and render_ methods, and flow
-widgets must implement selectable, render and rows_ methods.
-
-.. _Widget interface definition: :class:`Widget`
-.. _selectable: :meth:`Widget.selectable`
-.. _render: :meth:`Widget.render`
-.. _rows: :meth:`Widget.rows`
-
-.. literalinclude:: wanat.py
- :linenos:
-The above code implements two widget classes. Pudding is a flow widget and
-BoxPudding is a box widget. Pudding will render as much "Pudding" as will fit
-in a single row, and BoxPudding will render as much "Pudding" as will fit into
-the entire area given.
-Note that the rows and render methods' focus parameter must have a default
-value of False. Also note that for flow widgets the number of rows returned by
-the rows method must match the number of rows rendered by the render method.
-
-In most cases it is easier to let other widgets handle the rendering and row
-calculations for you:
-
-.. literalinclude:: wanat_new.py
- :linenos:
-
-The NewPudding class behaves the same way as the Pudding class above, but in
-NewPudding you can change the way the widget appears by modifying only the
-display_widget method, whereas in the Pudding class you may have to modify both
-the render and rows methods.
-
-To improve the efficiency of your Urwid application you should be careful of
-how long your rows methods take to execute. The rows methods may be called many
-times as part of input handling and rendering operations. If you are using a
-display widget that is time consuming to create you should consider caching it
-to reduce its impact on performance.
-
-It is possible to create a widget that will behave as either a flow widget or
-box widget depending on what is required:
-
-.. literalinclude:: wanat_multi.py
- :linenos:
-
-MultiPudding will work in place of either Pudding or BoxPudding above. The
-number of elements in the size tuple determines whether the containing widget
-is expecting a flow widget or a box widget.
-
-
-Creating a Selectable Widget
-----------------------------
-
-Selectable widgets such as Edit and Button widgets allow the user to interact
-with the application. A widget is selectable if its selectable method returns
-True. Selectable widgets must implement the keypress_ method to handle keyboard
-input.
-
-.. _keypress: :meth:`Widget.keypress`
-
-.. literalinclude:: wsel.py
-
-The SelectablePudding widget will display its contents in uppercase when it is
-in focus, and it allows the user to "eat" the pudding by pressing each of the
-letters *P*, *U*, *D*, *D*, *I*, *N* and *G* on the keyboard. When the user has
-"eaten" all the pudding the widget will reset to its initial state.
-
-Note that keys that are unhandled in the keypress method are returned so that
-another widget may be able to handle them. This is a good convention to follow
-unless you have a very good reason not to. In this case the *UP* and *DOWN*
-keys are returned so that if this widget is in a
-:class:`ListBox` the :class:`ListBox` will behave
-as the user expects and change the focus or scroll the
-:class:`ListBox`.
-
-Widget Displaying the Cursor
-----------------------------
-
-Widgets that display the cursor must implement the get_cursor_coords_ method.
-Similar to the rows method for flow widgets, this method lets other widgets
-make layout decisions without rendering the entire widget. The
-:class:`ListBox` widget in particular uses get_cursor_coords to
-make sure that the cursor is visible within its focus widget.
-
-.. _get_cursor_coords: :meth:`Widget.get_cursor_coords`
-
-.. literalinclude:: wcur1.py
- :linenos:
-
-CursorPudding will let the user move the cursor through the widget by pressing
-*LEFT* and *RIGHT*. The cursor must only be added to the canvas when the widget
-is in focus. The get_cursor_coords method must always return the same cursor
-coordinates that render does.
-
-A widget displaying a cursor may choose to implement get_pref_col. This method
-returns the preferred column for the cursor, and is called when the focus is
-moving up or down off this widget.
-
-.. _get_pref_col: :meth:`Widget.get_pref_col`
-
-Another optional method is move_cursor_to_coords_. This method allows other
-widgets to try to position the cursor within this widget. The
-:class:`ListBox` widget uses :meth:`move_cursor_to_coords` when
-changing focus and when the user pressed *PAGE UP* or *PAGE DOWN*. This method
-must return ``True`` on success and ``False`` on failure. If the cursor may be
-placed at any position within the row specified (not only at the exact column
-specified) then this method must move the cursor to that position and return
-``True``.
-
-.. _move_cursor_to_coords: :meth:`Widget.move_cursor_to_coords`
-
-.. literalinclude:: wcur2.py
- :linenos: