gummworld2.popup_menu (version $Id: popup_menu.py 407 2013-08-12 15:11:30Z stabbingfinger@gmail.com $)
index
c:\cygwin64\home\bw\dev\python\dist\gummworld2\gamelib\gummworld2\popup_menu.py

popup_menu.py - A low-fuss, infinitely nested popup menu with simple blocking
behavior, and more advanced non-blocking behavior.
 
Classes:
    
    PopupMenu -> A blocking menu.
    
    NonBlockingPopupMenu -> A non-blocking menu.
    
    Menu -> The graphics and geometry for a menu panel. Note: You'll typically
        want to use PopupMenu or NonBlockingPopupMenu instead.
    
    MenuItem -> The graphics and geometry for a menu item. Note: You'll
        typically want to use PopupMenu or NonBlockingPopupMenu instead.
 
    SubmenuLabel -> A helper class for strong-typing of submenu labels. Note:
        You'll typically want to use PopupMenu or NonBlockingPopupMenu instead.
 
Module data (can be changed after importing the module):
    
    font -> pygame.font.Font object used to render menus.
    bg_color -> pygame.Color object used for the menu panel background.
    hi_color -> pygame.Color object used for the highlighted item background.
    text_color -> pygame.Color object used for the text.
    glint_color -> pygame.Color object used for bright beveled edge.
    shadow_color -> pygame.Color object used for dark beveled edge.
    margin -> int used for menu and item padding.
 
Example blocking menu:
    
    menu_data = ['Main', 'Item 0', ['Submenu', 'Item 0'], 'Quit']
    while 1:
        # game stuff...
        for e in pygame.event.get():
            if e.type == MOUSEBUTTONUP and e.button == 3:
                PopupMenu(menu_data)
            elif e.type == USEREVENT and e.code == 'MENU':
                print 'menu event: %s.%d: %s' % (e.name,e.item_id,e.text)
                if (e.name,e.text) == ('Main','Quit'):
                    quit()
            else:
                # handle all game events normally
                pass
 
Example non-blocking menu:
    
    menu_data = ['Main', 'Item 0', ['Submenu', 'Item 0'], 'Quit']
    menu = NonBlockingPopupMenu(menu_data)
    while 1:
        # update game
        # clear screen
        # draw game
        menu.draw()
        # update/flip screen
        for e in menu.handle_events(pygame.event.get()):
            if e.type == MOUSEBUTTONUP and e.button == 3:
                menu.show()
            elif e.type == USEREVENT and e.code == 'MENU':
                if e.name is None:
                    menu.hide()
                elif (e.name,e.text) == ('Main','Quit'):
                    quit()
            else:
                # handle all game events normally
                pass

 
Modules
       
gummworld2.data
pygame

 
Classes
       
__builtin__.object
Menu
MenuItem
PopupMenu
NonBlockingPopupMenu
__builtin__.str(__builtin__.basestring)
SubmenuLabel

 
class Menu(__builtin__.object)
    popup_menu.Menu
Menu(pos, name, items) : return menu
 
pos -> (x,y); topleft coordinates of the menu.
name -> str; the name of the menu.
items -> list; a list containing strings for menu items labels.
 
This class is not intended to be used directly. Use PopupMenu or
NonBlockingPopupMenu instead, unless designing your own subclass.
 
  Methods defined here:
__init__(self, pos, name, items)
check_collision(self, mouse_pos)
draw(self)

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class MenuItem(__builtin__.object)
    popup_menu.MenuItem
MenuItem(text, item_id) : return menu_item
 
text -> str; the display text.
item_id -> int; the numeric ID; also the item_id attribute returned in the
    pygame event.
 
This class is not intended to be used directly. Use PopupMenu or
NonBlockingPopupMenu instead, unless designing your own subclass.
 
  Methods defined here:
__init__(self, text, item_id)

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class NonBlockingPopupMenu(PopupMenu)
    popup_menu.NonBlockingPopupMenu
NonBlockingPopupMenu(data, pos=None, show=False) : return menu
 
data -> list; the list of strings and nested lists.
pos -> tuple; the xy screen coordinate for the topleft of the main menu; if
    None, the mouse position is used.
show -> boolean; make the menu visible in the constructor.
 
visible is a read-write property that sets and gets the boolean value
representing the state. The show() and hide() methods are equivalent
alternatives to using the property.
 
Note that the constructor does not copy the data argument. Changes to the
contents will result in changes to the menus once show() is called or
visible is set to True. In addition, data can be entirely replaced by
setting menu.init_data.
 
High-level steps for a non-blocking menu:
 
1.  Fashion a nested list of strings for the NonBlockingPopupMenu constructor.
2.  Store the menu object in a variable.
3.  Construct the NonBlockingPopupMenu object.
4.  Detect the condition that triggers the menu to post, and call menu.show()
    (or set menu.visible=True).
5.  Call menu.draw() to draw the menu. If it is visible, it will be drawn.
6.  Pass pygame events to menu.handle_events() and process the unhandled events
    that are returned as you would pygame's events. If the menu is not visible
    the method will immediately return the list passed in, unchanged.
7.  Upon menu exit, one or two USEREVENTs are posted via pygame. Retrieve them
    and recognize they are menu events (i.e., event.code=='MENU').
    a.  A menu-exit event signals the menu has detected an exit condition, which
        may or many not be accompanied by a menu selection. Recognize this by
        event.name==None or event.menu_id==-1. Upon receiving this event the
        main loop should call menu.hide() (or set menu.visible=False).
    b.  A menu-selection event signals the main loop that a menu item was
        selected. Recognize this by event.name=='your menu title'. event.menu_id
        holds the selected item number, and event.text holds the item label.
8.  Destroying the menu is optional.
9.  Assigning to menu.init_data, or changing its contents or that of the
    original list variable, will result in a modified menu the next time
    menu.show() is called (or menu.visible is set to True).
 
 
Method resolution order:
NonBlockingPopupMenu
PopupMenu
__builtin__.object

Methods defined here:
__init__(self, data, pos=None, show=False)
draw(self)
preemptively return if the menu is not visible; else, call the
superclass's method.
handle_events(self, events)
preemptively return if the menu is not visible; else, call the
superclass's method.
hide(self)
destroy the menu geometry and grpahics, and hides the menu
show(self)
generate the menu geometry and graphics, and makes the menu visible

Data descriptors defined here:
visible

Data descriptors inherited from PopupMenu:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class PopupMenu(__builtin__.object)
    popup_menu.PopupMenu
PopupMenu(data, block=True) : return menu
 
data -> list; the list of strings and nested lists.
pos -> tuple; the xy screen coordinate for the topleft of the main menu; if
    None, the mouse position is used.
block -> boolean; when True popup_menu will run its own event loop, blocking
    your main loop until it exits; when False popup_menu.get_events() will
    intercept events it cares about and return unhandled events to the
    caller.
 
Note: For a non-blocking menu, use the NonBlockingPopupMenu instead. This
class supports non-blocking, but it is more cumbersome to use than the
NonBlockingPopupMenu class.
 
The first string in the data list is taken as the menu title. The remaining
strings are menu items. A nested list becomes a submenu. Submenu lists must
also contain strings for menu title and menu items. Submenus can be
theoretically infinitely nested.
 
The menu runs a mini event loop. This will block the caller until it exits.
Upon exiting, the screen is restored to its prior state.
 
Left-clicking outside the topmost menu will quit the entire menu. Right-
clicking anywhere will close the topmost submenu; if only the main menu
remains the menu will exit. Left-clicking a menu item in the topmost menu
will post a USEREVENT for the caller to process.
 
The USEREVENT will have attributes: code='MENU', name=popup_menu.name,
item_id=menu_item.item_id, text=menu_item.text. name is first element in a
menu data list. item_id corresponds to the Nth element in a menu data list,
incremented from 0; submenu items count as one menu_id even though they are
never posted in an event. text is the string value of the Nth element in the
menu data list. Thus, combinations of name and menu_id or name and text can
be used to uniquely identify menu selections.
 
Example menu data and resulting event data:
    
    ['Main',            # main menu title
     'Item 0',          # name='Main', menu_id=0, text='Item 0'
        ['Submenu',     # submenu title
         'Item 0',      # name='Submenu', menu_id=0, text='Item 0'
         'Item 1',      # name='Submenu', menu_id=0, text='Item 1'
        ],
     'Item 2',          # name='Main', menu_id=2, text='Item 2'
    ]
 
High-level steps for a blocking menu:
 
1.  Fashion a nested list of strings for the PopupMenu constructor.
2.  Upon creation, the menu runs its own loop.
3.  Upon exit, control is returned to the caller.
4.  Handle the resulting USEREVENT event in the caller where
    event.name=='your menu title', event.item_id holds the selected item
    number, and event.text holds the item label.
 
High-level steps for a non-blocking menu:
 
Note: This usage exists to support the NonBlockingPopupMenu class and
custom non-blocking implementations; for typical use NonBlockingPopupMenu
is recommended.
 
1.  Fashion a nested list of strings for the PopupMenu constructor.
2.  Store the menu object in a variable.
3.  Devise a means for the main loop to choose whether to draw the menu and pass
    it events.
4.  Call menu.draw() to draw the menu.
5.  Pass pygame events to menu.handle_events() and process the unhandled events
    that are returned as you would pygame's events.
6.  Upon menu exit, one or two USEREVENTs are posted via pygame. Retrieve
    them and recognize they are menu events (event.code=='MENU').
    a.  The menu-exit event signals the main loop it has exited, with or
        without a menu selection. Recognize this by event.name==None. Upon
        receiving this event the main loop should stop using the menu's
        draw() and get_events() (until the next time it wants to post the
        menu to the user).
    b.  The menu-selection event signals the main loop that a menu item was
        selected. Recognize this by event.name=='your menu title'.
        event.menu_id holds the selected item number, and event.text holds
        the item label.
7.  Destroying the menu is not necessary. But creating and destroying it may
    be a convenient means to manage the menu state (i.e. to post it or not).
 
  Methods defined here:
__init__(self, data, pos=None, block=True)
draw(self)
handle_events(self, events, block=False)

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
class SubmenuLabel(__builtin__.str)
    popup_menu.SubmenuLabel
SubmenuLabel(s) : return label
 
s -> str; the label text
 
This is a helper class for strong-typing of submenu labels.
 
This class is not intended to be used directly. See PopupMenu or
NonBlockingPopupMenu.
 
 
Method resolution order:
SubmenuLabel
__builtin__.str
__builtin__.basestring
__builtin__.object

Static methods defined here:
__new__(cls, s)

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)

Methods inherited from __builtin__.str:
__add__(...)
x.__add__(y) <==> x+y
__contains__(...)
x.__contains__(y) <==> y in x
__eq__(...)
x.__eq__(y) <==> x==y
__format__(...)
S.__format__(format_spec) -> string
 
Return a formatted version of S as described by format_spec.
__ge__(...)
x.__ge__(y) <==> x>=y
__getattribute__(...)
x.__getattribute__('name') <==> x.name
__getitem__(...)
x.__getitem__(y) <==> x[y]
__getnewargs__(...)
__getslice__(...)
x.__getslice__(i, j) <==> x[i:j]
 
Use of negative indices is not supported.
__gt__(...)
x.__gt__(y) <==> x>y
__hash__(...)
x.__hash__() <==> hash(x)
__le__(...)
x.__le__(y) <==> x<=y
__len__(...)
x.__len__() <==> len(x)
__lt__(...)
x.__lt__(y) <==> x<y
__mod__(...)
x.__mod__(y) <==> x%y
__mul__(...)
x.__mul__(n) <==> x*n
__ne__(...)
x.__ne__(y) <==> x!=y
__repr__(...)
x.__repr__() <==> repr(x)
__rmod__(...)
x.__rmod__(y) <==> y%x
__rmul__(...)
x.__rmul__(n) <==> n*x
__sizeof__(...)
S.__sizeof__() -> size of S in memory, in bytes
__str__(...)
x.__str__() <==> str(x)
capitalize(...)
S.capitalize() -> string
 
Return a copy of the string S with only its first character
capitalized.
center(...)
S.center(width[, fillchar]) -> string
 
Return S centered in a string of length width. Padding is
done using the specified fill character (default is a space)
count(...)
S.count(sub[, start[, end]]) -> int
 
Return the number of non-overlapping occurrences of substring sub in
string S[start:end].  Optional arguments start and end are interpreted
as in slice notation.
decode(...)
S.decode([encoding[,errors]]) -> object
 
Decodes S using the codec registered for encoding. encoding defaults
to the default encoding. errors may be given to set a different error
handling scheme. Default is 'strict' meaning that encoding errors raise
a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'
as well as any other name registered with codecs.register_error that is
able to handle UnicodeDecodeErrors.
encode(...)
S.encode([encoding[,errors]]) -> object
 
Encodes S using the codec registered for encoding. encoding defaults
to the default encoding. errors may be given to set a different error
handling scheme. Default is 'strict' meaning that encoding errors raise
a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and
'xmlcharrefreplace' as well as any other name registered with
codecs.register_error that is able to handle UnicodeEncodeErrors.
endswith(...)
S.endswith(suffix[, start[, end]]) -> bool
 
Return True if S ends with the specified suffix, False otherwise.
With optional start, test S beginning at that position.
With optional end, stop comparing S at that position.
suffix can also be a tuple of strings to try.
expandtabs(...)
S.expandtabs([tabsize]) -> string
 
Return a copy of S where all tab characters are expanded using spaces.
If tabsize is not given, a tab size of 8 characters is assumed.
find(...)
S.find(sub [,start [,end]]) -> int
 
Return the lowest index in S where substring sub is found,
such that sub is contained within s[start:end].  Optional
arguments start and end are interpreted as in slice notation.
 
Return -1 on failure.
format(...)
S.format(*args, **kwargs) -> string
 
Return a formatted version of S, using substitutions from args and kwargs.
The substitutions are identified by braces ('{' and '}').
index(...)
S.index(sub [,start [,end]]) -> int
 
Like S.find() but raise ValueError when the substring is not found.
isalnum(...)
S.isalnum() -> bool
 
Return True if all characters in S are alphanumeric
and there is at least one character in S, False otherwise.
isalpha(...)
S.isalpha() -> bool
 
Return True if all characters in S are alphabetic
and there is at least one character in S, False otherwise.
isdigit(...)
S.isdigit() -> bool
 
Return True if all characters in S are digits
and there is at least one character in S, False otherwise.
islower(...)
S.islower() -> bool
 
Return True if all cased characters in S are lowercase and there is
at least one cased character in S, False otherwise.
isspace(...)
S.isspace() -> bool
 
Return True if all characters in S are whitespace
and there is at least one character in S, False otherwise.
istitle(...)
S.istitle() -> bool
 
Return True if S is a titlecased string and there is at least one
character in S, i.e. uppercase characters may only follow uncased
characters and lowercase characters only cased ones. Return False
otherwise.
isupper(...)
S.isupper() -> bool
 
Return True if all cased characters in S are uppercase and there is
at least one cased character in S, False otherwise.
join(...)
S.join(iterable) -> string
 
Return a string which is the concatenation of the strings in the
iterable.  The separator between elements is S.
ljust(...)
S.ljust(width[, fillchar]) -> string
 
Return S left-justified in a string of length width. Padding is
done using the specified fill character (default is a space).
lower(...)
S.lower() -> string
 
Return a copy of the string S converted to lowercase.
lstrip(...)
S.lstrip([chars]) -> string or unicode
 
Return a copy of the string S with leading whitespace removed.
If chars is given and not None, remove characters in chars instead.
If chars is unicode, S will be converted to unicode before stripping
partition(...)
S.partition(sep) -> (head, sep, tail)
 
Search for the separator sep in S, and return the part before it,
the separator itself, and the part after it.  If the separator is not
found, return S and two empty strings.
replace(...)
S.replace(old, new[, count]) -> string
 
Return a copy of string S with all occurrences of substring
old replaced by new.  If the optional argument count is
given, only the first count occurrences are replaced.
rfind(...)
S.rfind(sub [,start [,end]]) -> int
 
Return the highest index in S where substring sub is found,
such that sub is contained within s[start:end].  Optional
arguments start and end are interpreted as in slice notation.
 
Return -1 on failure.
rindex(...)
S.rindex(sub [,start [,end]]) -> int
 
Like S.rfind() but raise ValueError when the substring is not found.
rjust(...)
S.rjust(width[, fillchar]) -> string
 
Return S right-justified in a string of length width. Padding is
done using the specified fill character (default is a space)
rpartition(...)
S.rpartition(sep) -> (head, sep, tail)
 
Search for the separator sep in S, starting at the end of S, and return
the part before it, the separator itself, and the part after it.  If the
separator is not found, return two empty strings and S.
rsplit(...)
S.rsplit([sep [,maxsplit]]) -> list of strings
 
Return a list of the words in the string S, using sep as the
delimiter string, starting at the end of the string and working
to the front.  If maxsplit is given, at most maxsplit splits are
done. If sep is not specified or is None, any whitespace string
is a separator.
rstrip(...)
S.rstrip([chars]) -> string or unicode
 
Return a copy of the string S with trailing whitespace removed.
If chars is given and not None, remove characters in chars instead.
If chars is unicode, S will be converted to unicode before stripping
split(...)
S.split([sep [,maxsplit]]) -> list of strings
 
Return a list of the words in the string S, using sep as the
delimiter string.  If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are removed
from the result.
splitlines(...)
S.splitlines([keepends]) -> list of strings
 
Return a list of the lines in S, breaking at line boundaries.
Line breaks are not included in the resulting list unless keepends
is given and true.
startswith(...)
S.startswith(prefix[, start[, end]]) -> bool
 
Return True if S starts with the specified prefix, False otherwise.
With optional start, test S beginning at that position.
With optional end, stop comparing S at that position.
prefix can also be a tuple of strings to try.
strip(...)
S.strip([chars]) -> string or unicode
 
Return a copy of the string S with leading and trailing
whitespace removed.
If chars is given and not None, remove characters in chars instead.
If chars is unicode, S will be converted to unicode before stripping
swapcase(...)
S.swapcase() -> string
 
Return a copy of the string S with uppercase characters
converted to lowercase and vice versa.
title(...)
S.title() -> string
 
Return a titlecased version of S, i.e. words start with uppercase
characters, all remaining cased characters have lowercase.
translate(...)
S.translate(table [,deletechars]) -> string
 
Return a copy of the string S, where all characters occurring
in the optional argument deletechars are removed, and the
remaining characters have been mapped through the given
translation table, which must be a string of length 256.
upper(...)
S.upper() -> string
 
Return a copy of the string S converted to uppercase.
zfill(...)
S.zfill(width) -> string
 
Pad a numeric string S with zeros on the left, to fill a field
of the specified width.  The string S is never truncated.

 
Data
        __all__ = ['bg_color', 'hi_color', 'text_color', 'glint_color', 'shadow_color', 'margin', 'PopupMenu', 'NonBlockingPopupMenu', 'SubmenuLabel', 'MenuItem', 'Menu']
__author__ = 'Gummbum, (c) 2011-2014'
__version__ = '$Id: popup_menu.py 407 2013-08-12 15:11:30Z stabbingfinger@gmail.com $'
bg_color = (190, 190, 190, 255)
glint_color = (220, 220, 220, 255)
hi_color = (155, 155, 155, 255)
margin = 2
shadow_color = (105, 105, 105, 255)
text_color = (0, 0, 0, 255)

 
Author
        Gummbum, (c) 2011-2014