#!/usr/bin/python # # Urwid tour. It slices, it dices.. # Copyright (C) 2004-2007 Ian Ward # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Urwid web site: http://excess.org/urwid/ """ Urwid tour. Shows many of the standard widget types and features. """ import urwid import urwid.raw_display import urwid.web_display # use appropriate Screen class if urwid.web_display.is_web_request(): Screen = urwid.web_display.Screen else: Screen = urwid.raw_display.Screen blank = urwid.Divider() HEADER = urwid.AttrWrap( urwid.Text("Welcome to the urwid tour! " "UP / DOWN / PAGE UP / PAGE DOWN scroll. F8 exits."), 'header') B_PRESS_FRAME = None # this is set in TourDisplay.__init__ def B_PRESS( button ): B_PRESS_FRAME.footer = urwid.AttrWrap( urwid.Text( ["Pressed: ",button.get_label()]), 'header') RADIO_LIST = [] CONTENT = [ blank, urwid.Padding( urwid.Text( [('important',"Text"), " widgets are the most common in " "any urwid program. This Text widget was created without " "setting the wrap or align mode, so it defaults to left " "alignment with wrapping on space characters. ", ('important',"Change the window width"), " to see how the widgets on this page react. " "This Text widget is wrapped with a ", ('important',"Padding"), " widget to keep it indented on the left and right."] ), ('fixed left',2),('fixed right',2),20), blank, urwid.Text( "This Text widget is right aligned. Wrapped words stay " "to the right as well. ", align='right' ), blank, urwid.Text( "This one is center aligned.", align='center' ), blank, urwid.Text( "Text widgets may be clipped instead of wrapped.\n" "Extra text is discarded instead of wrapped to the next line. " "65-> 70-> 75-> 80-> 85-> 90-> 95-> 100>\n" "Newlines embedded in the string are still respected.", wrap='clip' ), blank, urwid.Text( "This is a right aligned and clipped Text widget.\n" "<100 <-95 <-90 <-85 <-80 <-75 <-70 <-65 " "Text will be cut off at the left of this widget.", align='right', wrap='clip'), blank, urwid.Text( "Center aligned and clipped widgets will have text cut " "off both sides.", align='center', wrap='clip'), blank, urwid.Text( "The 'any' wrap mode will wrap on any character. This " "mode will not collapse space characters at the end of the line but " "it still honors embedded newline characters.\nLike this one.", wrap='any'), blank, urwid.Padding( urwid.Text("Padding widgets have many options. This " "is a standard Text widget wrapped with a Padding widget " "with the alignment set to relative 20% and with its width " "fixed at 40."), ('relative', 20), 40), blank, urwid.AttrWrap(urwid.Divider("=", 1), 'bright'), urwid.Padding( urwid.Text( ["The ",('important',"Divider"), " widget repeats the same character across the whole line. " "It can also add blank lines above and below."]), ('fixed left',2),('fixed right',2),20), urwid.AttrWrap(urwid.Divider("-", 0, 1), 'bright'), blank, urwid.Padding( urwid.Text( ["The ",('important',"Edit"), " widget is a simple text editing widget. It supports cursor " "movement and tries to maintain the current column when focus " "moves to another edit widget. It wraps and aligns the same " "way as Text widgets." ] ), ('fixed left',2),('fixed right',2),20), blank, urwid.AttrWrap( urwid.Edit( ('editcp',"This is a caption. Edit here: " ), "editable stuff" ), 'editbx', 'editfc' ), blank, urwid.AttrWrap( urwid.Edit( ('editcp',"This one supports newlines: "), "line one starts them all\n" "== line 2 == with some more text to edit.. words.. whee..\n" "LINE III, the line to end lines one and two, unless you change " "something.", multiline=True ), 'editbx', 'editfc' ), blank, urwid.AttrWrap( urwid.Edit( ('editcp',"This one is clipped, try " "editing past the edge: "), "add some text here -> -> -> ....", wrap='clip' ), 'editbx', 'editfc' ), blank, urwid.Text( "Different Alignments:" ), urwid.AttrWrap( urwid.Edit( "", "left aligned (default)", align='left' ), 'editbx', 'editfc' ), urwid.AttrWrap( urwid.Edit( "", "center aligned", align='center' ), 'editbx', 'editfc' ), urwid.AttrWrap( urwid.Edit( "", "right aligned", align='right' ), 'editbx', 'editfc' ), blank, urwid.AttrWrap( urwid.IntEdit( ('editcp',[('important',"IntEdit"), " allows only numbers: "]), 123 ), 'editbx', 'editfc' ), blank, urwid.Padding( urwid.AttrWrap( urwid.Edit( ('editcp',"Edit widget within a Padding widget "),""), 'editbx','editfc' ), ('fixed left',10),50 ), blank, blank, urwid.AttrWrap( urwid.Columns( [ urwid.Divider("."), urwid.Divider(","), urwid.Divider("."), ]), 'bright' ), blank, urwid.Columns( [ urwid.Padding( urwid.Text( [('important',"Columns"), " are used to share horizontal screen space. " "This one splits the space into two parts with " "three characters between each column. The " "contents of each column is a single widget."] ), ('fixed left',2),('fixed right',0),20), urwid.Pile( [ urwid.Divider("~"), urwid.Text( ["When you need to put more than one " "widget into a column you can use a ",('important', "Pile")," to combine two or more widgets."] ), urwid.Divider("_") ] ) ], 3 ), blank, blank, urwid.Columns( [ urwid.Text( "Columns may be placed inside other columns."), urwid.Columns( [ urwid.Text( "Col 2.1" ), urwid.Text( "Col 2.2" ), urwid.Text( "Col 2.3" ), ], 1 ), ], 2 ), blank, urwid.Padding( urwid.Text( "Columns may also have uneven relative " "weights or fixed widths. Use a minimum width so that " "columns don't become too small."), ('fixed left',2),('fixed right',2),20), blank, urwid.Columns( [ urwid.AttrWrap(urwid.Text("Weight 1"),'reverse'), ('weight', 2, urwid.Text("Weight 2")), ('weight', 3, urwid.AttrWrap(urwid.Text("Weight 3"),'reverse')), ('weight', 4, urwid.Text("Weight 4")), ('weight', 5, urwid.AttrWrap(urwid.Text("Weight 5"),'reverse')), ('weight', 6, urwid.Text("Weight 6")), ], 0, min_width=8 ), blank, urwid.Columns( [ ('weight', 2, urwid.AttrWrap(urwid.Text("Weight 2"),'reverse')), ('fixed', 9, urwid.Text("")), ('weight', 3, urwid.AttrWrap(urwid.Text("Weight 3"),'reverse')), ('fixed', 14, urwid.Text("<--Fixed 14-->")), ], 0, min_width=8 ), blank, urwid.Columns( [ urwid.AttrWrap( urwid.Edit( ('editcp',"Edit widget within Columns"), "here's\nsome\ninfo", multiline=True), 'editbx','editfc'), urwid.Pile([ urwid.AttrWrap( urwid.Edit( ('editcp',"and within Pile "),"more"), 'editbx','editfc'), blank, urwid.AttrWrap( urwid.Edit( ('editcp',"another "),"still more"), 'editbx','editfc'), ]), ], 1 ), blank, urwid.AttrWrap( urwid.Columns( [ urwid.Divider("'"), urwid.Divider('"'), urwid.Divider("~"), urwid.Divider('"'), urwid.Divider("'"), ]), 'bright' ), blank, blank, urwid.Padding(urwid.Text( ["A ",('important',"GridFlow")," widget " "may be used to display a list of flow widgets with equal " "widths. Widgets that don't fit on the first line will " "flow to the next. This is useful for small widgets that " "you want to keep together such as ",('important',"Button"), ", ",('important',"CheckBox"), " and ", ('important',"RadioButton"), " widgets." ]), ('fixed left',2),('fixed right',2),20), blank, urwid.Padding( urwid.GridFlow( [ urwid.AttrWrap(urwid.Button("Yes",B_PRESS),'buttn','buttnf'), urwid.AttrWrap(urwid.Button("No",B_PRESS),'buttn','buttnf'), urwid.AttrWrap(urwid.Button("Perhaps",B_PRESS), 'buttn','buttnf'), urwid.AttrWrap(urwid.Button("Certainly",B_PRESS), 'buttn','buttnf'), urwid.AttrWrap(urwid.Button("Partially",B_PRESS), 'buttn','buttnf'), urwid.AttrWrap(urwid.Button("Tuesdays Only",B_PRESS), 'buttn','buttnf'), urwid.AttrWrap(urwid.Button("Help",B_PRESS), 'buttn','buttnf'), ], 13,3,1, 'left'), ('fixed left',4),('fixed right',3)), blank, urwid.Padding( urwid.GridFlow( [ urwid.AttrWrap(urwid.CheckBox("Wax"),'buttn','buttnf'), urwid.AttrWrap(urwid.CheckBox("Wash"),'buttn','buttnf'), urwid.AttrWrap(urwid.CheckBox("Buff"),'buttn','buttnf'), urwid.AttrWrap(urwid.CheckBox("Clear Coat"),'buttn','buttnf'), urwid.AttrWrap(urwid.CheckBox("Dry"),'buttn','buttnf'), urwid.AttrWrap(urwid.CheckBox("Racing Stripe"), 'buttn','buttnf'), ], 10,3,1, 'left') , ('fixed left',4),('fixed right',3)), blank, urwid.Padding( urwid.GridFlow( [ urwid.AttrWrap(urwid.RadioButton(RADIO_LIST, "Morning"), 'buttn','buttnf'), urwid.AttrWrap(urwid.RadioButton(RADIO_LIST, "Afternoon"), 'buttn','buttnf'), urwid.AttrWrap(urwid.RadioButton(RADIO_LIST, "Evening"), 'buttn','buttnf'), urwid.AttrWrap(urwid.RadioButton(RADIO_LIST, "Weekend"), 'buttn','buttnf'), ], 13,3,1, 'left') , ('fixed left',4),('fixed right',3)), blank, blank, urwid.Padding(urwid.Text( ["All these widgets have been diplayed " "with the help of a ", ('important',"ListBox"), " widget. " "ListBox widgets handle scrolling and changing focus. A ", ('important',"Frame"), " widget is used to keep the " "instructions at the top of the screen."]), ('fixed left',2),('fixed right',2),20), blank, blank, ] class TourDisplay: palette = [ ('body','black','light gray', 'standout'), ('reverse','light gray','black'), ('header','white','dark red', 'bold'), ('important','dark blue','light gray',('standout','underline')), ('editfc','white', 'dark blue', 'bold'), ('editbx','light gray', 'dark blue'), ('editcp','black','light gray', 'standout'), ('bright','dark gray','light gray', ('bold','standout')), ('buttn','black','dark cyan'), ('buttnf','white','dark blue','bold'), ] def __init__(self): walker = urwid.SimpleListWalker( CONTENT ) self.listbox = urwid.ListBox( walker ) view = urwid.AttrWrap(self.listbox, 'body') self.view = urwid.Frame( view, header=HEADER ) global B_PRESS_FRAME B_PRESS_FRAME = self.view def main(self): self.ui = Screen() self.ui.register_palette( self.palette ) self.ui.run_wrapper( self.run ) def run(self): self.ui.set_mouse_tracking() size = self.ui.get_cols_rows() while 1: canvas = self.view.render( size, focus=1 ) self.ui.draw_screen( size, canvas ) keys = None while not keys: keys = self.ui.get_input() for k in keys: if urwid.is_mouse_event(k): event, button, col, row = k self.view.mouse_event( size, event, button, col, row, focus=True ) elif k == 'window resize': size = self.ui.get_cols_rows() elif k == 'f8': return else: self.view.keypress( size, k ) def main(): urwid.web_display.set_preferences("Urwid Tour") # try to handle short web requests quickly if urwid.web_display.handle_short_request(): return TourDisplay().main() if '__main__'==__name__ or urwid.web_display.is_web_request(): main()