summaryrefslogtreecommitdiff
path: root/docs/tutorial
diff options
context:
space:
mode:
authorIan Ward <ian@excess.org>2012-10-08 18:17:17 -0400
committerIan Ward <ian@excess.org>2012-10-08 18:17:17 -0400
commit6da4472da8188af9eefd95d919846ea83a7bd9e9 (patch)
tree626b370c77157ce314f2eb45e0ce525c4215a57a /docs/tutorial
parentb04e1ba21279ce38d46f9166e0aead6f7de07c7a (diff)
downloadurwid-6da4472da8188af9eefd95d919846ea83a7bd9e9.tar.gz
tutorial: menu1, menu2 discussion
--HG-- branch : feature-sphinx
Diffstat (limited to 'docs/tutorial')
-rw-r--r--docs/tutorial/index.rst60
-rw-r--r--docs/tutorial/menu1.py4
-rw-r--r--docs/tutorial/menu2.py2
-rw-r--r--docs/tutorial/menu21.pngbin1257 -> 1166 bytes
-rw-r--r--docs/tutorial/menu22.pngbin1266 -> 1222 bytes
5 files changed, 61 insertions, 5 deletions
diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst
index 4fe4f3b..4133b30 100644
--- a/docs/tutorial/index.rst
+++ b/docs/tutorial/index.rst
@@ -265,7 +265,7 @@ it in a subclass.
the default options using :meth:`Pile.options`.
* To add another question after the current one we treat our
:class:`SimpleFocusListWalker` stored as :attr:`ListBox.body` like a normal
- list of widgets and call ``insert()``, then update the focus position to the widget we just
+ list of widgets by calling *insert*, then update the focus position to the widget we just
created.
.. image:: lbcont1.png
@@ -283,6 +283,20 @@ This program lets you choose an option then repeats what you chose.
.. literalinclude:: menu1.py
:linenos:
+* *menu* builds a :class:`ListBox` with a *title* and a sequence of :class:`Button`
+ widgets. Each button has its ``'click'`` signal attached to *item_chosen*,
+ with item name is passed as data.
+ The buttons are decorated with an :class:`AttrMap` that applies
+ a display attribute when a button is in focus.
+* *item_chosen* replaces the menu displayed with text indicating the users'
+ choice. It then installs *exit_program* as the *unhandled_input* method of the
+ :class:`MainLoop`.
+* *exit_program* causes the program to exit on any keystroke.
+* The menu is created and decorated with an :class:`Overlay` using a
+ :class:`SolidFill` as the background. The :class:`Overlay` is given a
+ miniumum width and height but is allowed to expand to 60% of the available
+ space if the user's terminal window is large enough.
+
.. image:: menu11.png
.. image:: menu12.png
.. image:: menu13.png
@@ -291,11 +305,53 @@ Cascading Menu
--------------
A nested menu effect can be created by having some buttons open new menus. This program
-lets you choose an option from a nested menu then repeats what you chose.
+lets you choose an option from a nested menu then repeats what you chose. You may also
+return to previous menus by pressing *ESC*.
.. literalinclude:: menu2.py
:linenos:
+* *menu_button* returns an :class:`AttrMap`-decorated :class:`Button`
+ and attaches a *callback* to the the its ``'click'`` signal. This function is
+ used for both sub-menus and final selection buttons.
+* *sub_menu* creates a menu button and a closure that will open the the
+ menu when that button is clicked. Notice that
+ :ref:`text markup <text-markup>` is used to add ``'...'`` to the end of
+ the *caption* passed to *menu_button*.
+* *menu* builds a :class:`ListBox` with a *title* and a sequence of widgets.
+* *item_chosen* displays the users' choice similar to the previous example.
+* *menu_top* is the top level menu with all of its child menus and
+ options built using the functions above.
+
+This example introduces :class:`WidgetPlaceholder`. :class:`WidgetPlaceholder` is a
+:ref:`decoration widget <decoration-widgets>` that does nothing to the widget it
+decorates. It is useful if you need a simple way to replace a widget that doesn't
+involve knowing its position in a :ref:`container <container-widgets>`, or in this
+case as a base class for a widget that will be replacing its own contents regularly.
+
+* *CascadingBoxes* is a new widget that extends :class:`WidgetPlaceholder`.
+ It provides an *open_box* method that displays a box widget *box* "on top of"
+ all the previous content with an :class:`Overlay` and a :class:`LineBox`.
+ The position of each successive box is shifted right and down from the
+ previous one.
+* *CascadingBoxes.keypress* intercepts *ESC* keys to cause the current box
+ to be removed and the previous one to be shown. This allows the user to
+ return to a previous menu level.
+
+In this example there is a subtle effect that prevents pressing *ESC* to return
+to a menu once an item is chosen. *item_chosen* displays a
+widget that is not selectable, and the default for
+:ref:`decoration widgets <decoration-widgets>` including :class:`WidgetPlaceholder`
+is to reflect the selectable state of the widget contained. :class:`MainLoop`
+will not call :meth:`Widget.keypress`
+on non-selectable widgets, so *ESC* will not reach our *CascadingBoxes.keypress*
+method once an item is chosen.
+
+If you did want to allow backing out after a selection was made you could make
+*CascadingBoxes* selectable by defining a :meth:`Widget.selectable` method.
+You would also need to handle exiting the program in a cleaner way than
+by overwriting :meth:`MainLoop.unhandled_input` as *item_chosen* does above.
+
.. image:: menu21.png
.. image:: menu22.png
.. image:: menu23.png
diff --git a/docs/tutorial/menu1.py b/docs/tutorial/menu1.py
index 8925cf4..3b2c3c4 100644
--- a/docs/tutorial/menu1.py
+++ b/docs/tutorial/menu1.py
@@ -10,7 +10,7 @@ def menu(title, choices):
body.append(urwid.AttrMap(button, None, focus_map='reversed'))
return urwid.ListBox(urwid.SimpleFocusListWalker(body))
-def item_chosen(self, choice):
+def item_chosen(button, choice):
response = urwid.Text(u'You chose %s' % choice)
main.original_widget = urwid.Filler(response)
# exit on the next input from user
@@ -20,7 +20,7 @@ def exit_program(key):
raise urwid.ExitMainLoop()
main = urwid.Padding(menu(u'Pythons', choices), left=2, right=2)
-top = urwid.Overlay(main, urwid.SolidFill(u'\u2592'),
+top = urwid.Overlay(main, urwid.SolidFill(u'\N{MEDIUM SHADE}'),
align='center', width=('relative', 60),
valign='middle', height=('relative', 60),
min_width=20, min_height=9)
diff --git a/docs/tutorial/menu2.py b/docs/tutorial/menu2.py
index 5ee7134..bc72ca6 100644
--- a/docs/tutorial/menu2.py
+++ b/docs/tutorial/menu2.py
@@ -9,7 +9,7 @@ def sub_menu(caption, choices):
contents = menu(caption, choices)
def open_menu(button):
return top.open_box(contents)
- return menu_button(u'MENU: %s' % caption, open_menu)
+ return menu_button([caption, u'...'], open_menu)
def menu(title, choices):
body = [urwid.Text(title), urwid.Divider()]
diff --git a/docs/tutorial/menu21.png b/docs/tutorial/menu21.png
index e6e19c1..9e8ea5b 100644
--- a/docs/tutorial/menu21.png
+++ b/docs/tutorial/menu21.png
Binary files differ
diff --git a/docs/tutorial/menu22.png b/docs/tutorial/menu22.png
index 92b79ef..5df7578 100644
--- a/docs/tutorial/menu22.png
+++ b/docs/tutorial/menu22.png
Binary files differ