xref: /freebsd/contrib/dialog/samples/dialog.py (revision 4c8945a06b01a5c8122cdeb402af36bb46a06acc)
1*4c8945a0SNathan Whitehorn# $Id: dialog.py,v 1.3 2004/09/21 00:52:15 tom Exp $
2*4c8945a0SNathan Whitehorn# Module: dialog.py
3*4c8945a0SNathan Whitehorn# Copyright (c) 2000 Robb Shecter <robb@acm.org>
4*4c8945a0SNathan Whitehorn# All rights reserved.
5*4c8945a0SNathan Whitehorn# This source is covered by the GNU GPL.
6*4c8945a0SNathan Whitehorn#
7*4c8945a0SNathan Whitehorn# This module is a Python wrapper around the Linux "dialog" utility
8*4c8945a0SNathan Whitehorn# by Savio Lam and Stuart Herbert.  My goals were to make dialog as
9*4c8945a0SNathan Whitehorn# easy to use from Python as possible.  The demo code at the end of
10*4c8945a0SNathan Whitehorn# the module is a good example of how to use it.  To run the demo,
11*4c8945a0SNathan Whitehorn# execute:
12*4c8945a0SNathan Whitehorn#
13*4c8945a0SNathan Whitehorn#                       python dialog.py
14*4c8945a0SNathan Whitehorn#
15*4c8945a0SNathan Whitehorn# This module has one class in it, "Dialog".  An application typically
16*4c8945a0SNathan Whitehorn# creates an instance of it, and possibly sets the background title option.
17*4c8945a0SNathan Whitehorn# Then, methods can be called on it for interacting with the user.
18*4c8945a0SNathan Whitehorn#
19*4c8945a0SNathan Whitehorn# I wrote this because I want to use my 486-33 laptop as my main
20*4c8945a0SNathan Whitehorn# development computer (!), and I wanted a way to nicely interact with the
21*4c8945a0SNathan Whitehorn# user in console mode.  There are apparently other modules out there
22*4c8945a0SNathan Whitehorn# with similar functionality, but they require the Python curses library.
23*4c8945a0SNathan Whitehorn# Writing this module from scratch was easier than figuring out how to
24*4c8945a0SNathan Whitehorn# recompile Python with curses enabled. :)
25*4c8945a0SNathan Whitehorn#
26*4c8945a0SNathan Whitehorn# One interesting feature is that the menu and selection windows allow
27*4c8945a0SNathan Whitehorn# *any* objects to be displayed and selected, not just strings.
28*4c8945a0SNathan Whitehorn#
29*4c8945a0SNathan Whitehorn# TO DO:
30*4c8945a0SNathan Whitehorn#   Add code so that the input buffer is flushed before a dialog box is
31*4c8945a0SNathan Whitehorn#     shown.  This would make the UI more predictable for users.  This
32*4c8945a0SNathan Whitehorn#     feature could be turned on and off through an instance method.
33*4c8945a0SNathan Whitehorn#   Drop using temporary files when interacting with 'dialog'
34*4c8945a0SNathan Whitehorn#     (it's possible -- I've already tried :-).
35*4c8945a0SNathan Whitehorn#   Try detecting the terminal window size in order to make reasonable
36*4c8945a0SNathan Whitehorn#     height and width defaults.  Hmmm - should also then check for
37*4c8945a0SNathan Whitehorn#     terminal resizing...
38*4c8945a0SNathan Whitehorn#   Put into a package name to make more reusable - reduce the possibility
39*4c8945a0SNathan Whitehorn#     of name collisions.
40*4c8945a0SNathan Whitehorn#
41*4c8945a0SNathan Whitehorn# NOTES:
42*4c8945a0SNathan Whitehorn#         there is a bug in (at least) Linux-Mandrake 7.0 Russian Edition
43*4c8945a0SNathan Whitehorn#         running on AMD K6-2 3D that causes core dump when 'dialog'
44*4c8945a0SNathan Whitehorn#         is running with --gauge option;
45*4c8945a0SNathan Whitehorn#         in this case you'll have to recompile 'dialog' program.
46*4c8945a0SNathan Whitehorn#
47*4c8945a0SNathan Whitehorn# Modifications:
48*4c8945a0SNathan Whitehorn# Jul 2000, Sultanbek Tezadov (http://sultan.da.ru)
49*4c8945a0SNathan Whitehorn#    Added:
50*4c8945a0SNathan Whitehorn#       - 'gauge' widget *)
51*4c8945a0SNathan Whitehorn#       - 'title' option to some widgets
52*4c8945a0SNathan Whitehorn#       - 'checked' option to checklist dialog; clicking "Cancel" is now
53*4c8945a0SNathan Whitehorn#           recognizable
54*4c8945a0SNathan Whitehorn#       - 'selected' option to radiolist dialog; clicking "Cancel" is now
55*4c8945a0SNathan Whitehorn#           recognizable
56*4c8945a0SNathan Whitehorn#       - some other cosmetic changes and improvements
57*4c8945a0SNathan Whitehorn#
58*4c8945a0SNathan Whitehorn
59*4c8945a0SNathan Whitehornimport os
60*4c8945a0SNathan Whitehornfrom tempfile import mktemp
61*4c8945a0SNathan Whitehornfrom string import split
62*4c8945a0SNathan Whitehornfrom time import sleep
63*4c8945a0SNathan Whitehorn
64*4c8945a0SNathan Whitehorn#
65*4c8945a0SNathan Whitehorn# Path of the dialog executable
66*4c8945a0SNathan Whitehorn#
67*4c8945a0SNathan WhitehornDIALOG = os.getenv("DIALOG");
68*4c8945a0SNathan Whitehornif DIALOG is None:
69*4c8945a0SNathan Whitehorn	DIALOG="../dialog";
70*4c8945a0SNathan Whitehorn
71*4c8945a0SNathan Whitehornclass Dialog:
72*4c8945a0SNathan Whitehorn    def __init__(self):
73*4c8945a0SNathan Whitehorn	self.__bgTitle = ''               # Default is no background title
74*4c8945a0SNathan Whitehorn
75*4c8945a0SNathan Whitehorn
76*4c8945a0SNathan Whitehorn    def setBackgroundTitle(self, text):
77*4c8945a0SNathan Whitehorn	self.__bgTitle = '--backtitle "%s"' % text
78*4c8945a0SNathan Whitehorn
79*4c8945a0SNathan Whitehorn
80*4c8945a0SNathan Whitehorn    def __perform(self, cmd):
81*4c8945a0SNathan Whitehorn	"""Do the actual work of invoking dialog and getting the output."""
82*4c8945a0SNathan Whitehorn	fName = mktemp()
83*4c8945a0SNathan Whitehorn	rv = os.system('%s %s %s 2> %s' % (DIALOG, self.__bgTitle, cmd, fName))
84*4c8945a0SNathan Whitehorn	f = open(fName)
85*4c8945a0SNathan Whitehorn	output = f.readlines()
86*4c8945a0SNathan Whitehorn	f.close()
87*4c8945a0SNathan Whitehorn	os.unlink(fName)
88*4c8945a0SNathan Whitehorn	return (rv, output)
89*4c8945a0SNathan Whitehorn
90*4c8945a0SNathan Whitehorn
91*4c8945a0SNathan Whitehorn    def __perform_no_options(self, cmd):
92*4c8945a0SNathan Whitehorn	"""Call dialog w/out passing any more options. Needed by --clear."""
93*4c8945a0SNathan Whitehorn	return os.system(DIALOG + ' ' + cmd)
94*4c8945a0SNathan Whitehorn
95*4c8945a0SNathan Whitehorn
96*4c8945a0SNathan Whitehorn    def __handleTitle(self, title):
97*4c8945a0SNathan Whitehorn	if len(title) == 0:
98*4c8945a0SNathan Whitehorn	    return ''
99*4c8945a0SNathan Whitehorn	else:
100*4c8945a0SNathan Whitehorn	    return '--title "%s" ' % title
101*4c8945a0SNathan Whitehorn
102*4c8945a0SNathan Whitehorn
103*4c8945a0SNathan Whitehorn    def yesno(self, text, height=10, width=30, title=''):
104*4c8945a0SNathan Whitehorn	"""
105*4c8945a0SNathan Whitehorn	Put a Yes/No question to the user.
106*4c8945a0SNathan Whitehorn	Uses the dialog --yesno option.
107*4c8945a0SNathan Whitehorn	Returns a 1 or a 0.
108*4c8945a0SNathan Whitehorn	"""
109*4c8945a0SNathan Whitehorn	(code, output) = self.__perform(self.__handleTitle(title) +\
110*4c8945a0SNathan Whitehorn	    '--yesno "%s" %d %d' % (text, height, width))
111*4c8945a0SNathan Whitehorn	return code == 0
112*4c8945a0SNathan Whitehorn
113*4c8945a0SNathan Whitehorn
114*4c8945a0SNathan Whitehorn    def msgbox(self, text, height=10, width=30, title=''):
115*4c8945a0SNathan Whitehorn	"""
116*4c8945a0SNathan Whitehorn	Pop up a message to the user which has to be clicked
117*4c8945a0SNathan Whitehorn	away with "ok".
118*4c8945a0SNathan Whitehorn	"""
119*4c8945a0SNathan Whitehorn	self.__perform(self.__handleTitle(title) +\
120*4c8945a0SNathan Whitehorn	    '--msgbox "%s" %d %d' % (text, height, width))
121*4c8945a0SNathan Whitehorn
122*4c8945a0SNathan Whitehorn
123*4c8945a0SNathan Whitehorn    def infobox(self, text, height=10, width=30):
124*4c8945a0SNathan Whitehorn	"""Make a message to the user, and return immediately."""
125*4c8945a0SNathan Whitehorn	self.__perform('--infobox "%s" %d %d' % (text, height, width))
126*4c8945a0SNathan Whitehorn
127*4c8945a0SNathan Whitehorn
128*4c8945a0SNathan Whitehorn    def inputbox(self, text, height=10, width=30, init='', title=''):
129*4c8945a0SNathan Whitehorn	"""
130*4c8945a0SNathan Whitehorn	Request a line of input from the user.
131*4c8945a0SNathan Whitehorn	Returns the user's input or None if cancel was chosen.
132*4c8945a0SNathan Whitehorn	"""
133*4c8945a0SNathan Whitehorn	(c, o) = self.__perform(self.__handleTitle(title) +\
134*4c8945a0SNathan Whitehorn	    '--inputbox "%s" %d %d "%s"' % (text, height, width, init))
135*4c8945a0SNathan Whitehorn	try:
136*4c8945a0SNathan Whitehorn	    return o[0]
137*4c8945a0SNathan Whitehorn	except IndexError:
138*4c8945a0SNathan Whitehorn	    if c == 0:  # empty string entered
139*4c8945a0SNathan Whitehorn		return ''
140*4c8945a0SNathan Whitehorn	    else:  # canceled
141*4c8945a0SNathan Whitehorn		return None
142*4c8945a0SNathan Whitehorn
143*4c8945a0SNathan Whitehorn
144*4c8945a0SNathan Whitehorn    def textbox(self, filename, height=20, width=60, title=None):
145*4c8945a0SNathan Whitehorn	"""Display a file in a scrolling text box."""
146*4c8945a0SNathan Whitehorn	if title is None:
147*4c8945a0SNathan Whitehorn	    title = filename
148*4c8945a0SNathan Whitehorn	self.__perform(self.__handleTitle(title) +\
149*4c8945a0SNathan Whitehorn	    ' --textbox "%s" %d %d' % (filename, height, width))
150*4c8945a0SNathan Whitehorn
151*4c8945a0SNathan Whitehorn
152*4c8945a0SNathan Whitehorn    def menu(self, text, height=15, width=54, list=[]):
153*4c8945a0SNathan Whitehorn	"""
154*4c8945a0SNathan Whitehorn	Display a menu of options to the user.  This method simplifies the
155*4c8945a0SNathan Whitehorn	--menu option of dialog, which allows for complex arguments.  This
156*4c8945a0SNathan Whitehorn	method receives a simple list of objects, and each one is assigned
157*4c8945a0SNathan Whitehorn	a choice number.
158*4c8945a0SNathan Whitehorn	The selected object is returned, or None if the dialog was canceled.
159*4c8945a0SNathan Whitehorn	"""
160*4c8945a0SNathan Whitehorn	menuheight = height - 8
161*4c8945a0SNathan Whitehorn	pairs = map(lambda i, item: (i + 1, item), range(len(list)), list)
162*4c8945a0SNathan Whitehorn	choices = reduce(lambda res, pair: res + '%d "%s" ' % pair, pairs, '')
163*4c8945a0SNathan Whitehorn	(code, output) = self.__perform('--menu "%s" %d %d %d %s' %\
164*4c8945a0SNathan Whitehorn	    (text, height, width, menuheight, choices))
165*4c8945a0SNathan Whitehorn	try:
166*4c8945a0SNathan Whitehorn	    return list[int(output[0]) - 1]
167*4c8945a0SNathan Whitehorn	except IndexError:
168*4c8945a0SNathan Whitehorn	    return None
169*4c8945a0SNathan Whitehorn
170*4c8945a0SNathan Whitehorn
171*4c8945a0SNathan Whitehorn    def checklist(self, text, height=15, width=54, list=[], checked=None):
172*4c8945a0SNathan Whitehorn	"""
173*4c8945a0SNathan Whitehorn	Returns a list of the selected objects.
174*4c8945a0SNathan Whitehorn	Returns an empty list if nothing was selected.
175*4c8945a0SNathan Whitehorn	Returns None if the window was canceled.
176*4c8945a0SNathan Whitehorn	checked -- a list of boolean (0/1) values; len(checked) must equal
177*4c8945a0SNathan Whitehorn	    len(list).
178*4c8945a0SNathan Whitehorn	"""
179*4c8945a0SNathan Whitehorn	if checked is None:
180*4c8945a0SNathan Whitehorn	    checked = [0]*len(list)
181*4c8945a0SNathan Whitehorn	menuheight = height - 8
182*4c8945a0SNathan Whitehorn	triples = map(
183*4c8945a0SNathan Whitehorn	    lambda i, item, onoff, fs=('off', 'on'): (i + 1, item, fs[onoff]),
184*4c8945a0SNathan Whitehorn	    range(len(list)), list, checked)
185*4c8945a0SNathan Whitehorn	choices = reduce(lambda res, triple: res + '%d "%s" %s ' % triple,
186*4c8945a0SNathan Whitehorn	    triples, '')
187*4c8945a0SNathan Whitehorn	(c, o) = self.__perform('--checklist "%s" %d %d %d %s' %\
188*4c8945a0SNathan Whitehorn	    (text, height, width, menuheight, choices))
189*4c8945a0SNathan Whitehorn	try:
190*4c8945a0SNathan Whitehorn	    output = o[0]
191*4c8945a0SNathan Whitehorn	    indexList  = map(lambda x: int(x[1:-1]), split(output))
192*4c8945a0SNathan Whitehorn	    objectList = filter(lambda item, list=list, indexList=indexList:
193*4c8945a0SNathan Whitehorn		    list.index(item) + 1 in indexList,
194*4c8945a0SNathan Whitehorn		list)
195*4c8945a0SNathan Whitehorn	    return objectList
196*4c8945a0SNathan Whitehorn	except IndexError:
197*4c8945a0SNathan Whitehorn	    if c == 0:                        # Nothing was selected
198*4c8945a0SNathan Whitehorn		return []
199*4c8945a0SNathan Whitehorn	    return None  # Was canceled
200*4c8945a0SNathan Whitehorn
201*4c8945a0SNathan Whitehorn
202*4c8945a0SNathan Whitehorn    def radiolist(self, text, height=15, width=54, list=[], selected=0):
203*4c8945a0SNathan Whitehorn	"""
204*4c8945a0SNathan Whitehorn	Return the selected object.
205*4c8945a0SNathan Whitehorn	Returns empty string if no choice was selected.
206*4c8945a0SNathan Whitehorn	Returns None if window was canceled.
207*4c8945a0SNathan Whitehorn	selected -- the selected item (must be between 1 and len(list)
208*4c8945a0SNathan Whitehorn	    or 0, meaning no selection).
209*4c8945a0SNathan Whitehorn	"""
210*4c8945a0SNathan Whitehorn	menuheight = height - 8
211*4c8945a0SNathan Whitehorn	triples = map(lambda i, item: (i + 1, item, 'off'),
212*4c8945a0SNathan Whitehorn	    range(len(list)), list)
213*4c8945a0SNathan Whitehorn	if selected:
214*4c8945a0SNathan Whitehorn	    i, item, tmp = triples[selected - 1]
215*4c8945a0SNathan Whitehorn	    triples[selected - 1] = (i, item, 'on')
216*4c8945a0SNathan Whitehorn	choices = reduce(lambda res, triple: res + '%d "%s" %s ' % triple,
217*4c8945a0SNathan Whitehorn	    triples, '')
218*4c8945a0SNathan Whitehorn	(c, o) = self.__perform('--radiolist "%s" %d %d %d %s' %\
219*4c8945a0SNathan Whitehorn	    (text, height, width, menuheight, choices))
220*4c8945a0SNathan Whitehorn	try:
221*4c8945a0SNathan Whitehorn	    return list[int(o[0]) - 1]
222*4c8945a0SNathan Whitehorn	except IndexError:
223*4c8945a0SNathan Whitehorn	    if c == 0:
224*4c8945a0SNathan Whitehorn		return ''
225*4c8945a0SNathan Whitehorn	    return None
226*4c8945a0SNathan Whitehorn
227*4c8945a0SNathan Whitehorn
228*4c8945a0SNathan Whitehorn    def clear(self):
229*4c8945a0SNathan Whitehorn	"""
230*4c8945a0SNathan Whitehorn	Clear the screen. Equivalent to the dialog --clear option.
231*4c8945a0SNathan Whitehorn	"""
232*4c8945a0SNathan Whitehorn	self.__perform_no_options('--clear')
233*4c8945a0SNathan Whitehorn
234*4c8945a0SNathan Whitehorn
235*4c8945a0SNathan Whitehorn    def scrollbox(self, text, height=20, width=60, title=''):
236*4c8945a0SNathan Whitehorn	"""
237*4c8945a0SNathan Whitehorn	This is a bonus method.  The dialog package only has a function to
238*4c8945a0SNathan Whitehorn	display a file in a scrolling text field.  This method allows any
239*4c8945a0SNathan Whitehorn	string to be displayed by first saving it in a temp file, and calling
240*4c8945a0SNathan Whitehorn	--textbox.
241*4c8945a0SNathan Whitehorn	"""
242*4c8945a0SNathan Whitehorn	fName = mktemp()
243*4c8945a0SNathan Whitehorn	f = open(fName, 'w')
244*4c8945a0SNathan Whitehorn	f.write(text)
245*4c8945a0SNathan Whitehorn	f.close()
246*4c8945a0SNathan Whitehorn	self.__perform(self.__handleTitle(title) +\
247*4c8945a0SNathan Whitehorn	    '--textbox "%s" %d %d' % (fName, height, width))
248*4c8945a0SNathan Whitehorn	os.unlink(fName)
249*4c8945a0SNathan Whitehorn
250*4c8945a0SNathan Whitehorn
251*4c8945a0SNathan Whitehorn    def gauge_start(self, perc=0, text='', height=8, width=54, title=''):
252*4c8945a0SNathan Whitehorn	"""
253*4c8945a0SNathan Whitehorn	Display gauge output window.
254*4c8945a0SNathan Whitehorn	Gauge normal usage (assuming that there is an instace of 'Dialog'
255*4c8945a0SNathan Whitehorn	class named 'd'):
256*4c8945a0SNathan Whitehorn	    d.gauge_start()
257*4c8945a0SNathan Whitehorn	    # do something
258*4c8945a0SNathan Whitehorn	    d.gauge_iterate(10)  # passed throgh 10%
259*4c8945a0SNathan Whitehorn	    # ...
260*4c8945a0SNathan Whitehorn	    d.gauge_iterate(100, 'any text here')  # work is done
261*4c8945a0SNathan Whitehorn	    d.stop_gauge()  # clean-up actions
262*4c8945a0SNathan Whitehorn	"""
263*4c8945a0SNathan Whitehorn	cmd = self.__handleTitle(title) +\
264*4c8945a0SNathan Whitehorn	    '--gauge "%s" %d %d %d' % (text, height, width, perc)
265*4c8945a0SNathan Whitehorn	cmd = '%s %s %s 2> /dev/null' % (DIALOG, self.__bgTitle, cmd)
266*4c8945a0SNathan Whitehorn	self.pipe = os.popen(cmd, 'w')
267*4c8945a0SNathan Whitehorn    #/gauge_start()
268*4c8945a0SNathan Whitehorn
269*4c8945a0SNathan Whitehorn
270*4c8945a0SNathan Whitehorn    def gauge_iterate(self, perc, text=''):
271*4c8945a0SNathan Whitehorn	"""
272*4c8945a0SNathan Whitehorn	Update percentage point value.
273*4c8945a0SNathan Whitehorn
274*4c8945a0SNathan Whitehorn	See gauge_start() function above for the usage.
275*4c8945a0SNathan Whitehorn	"""
276*4c8945a0SNathan Whitehorn	if text:
277*4c8945a0SNathan Whitehorn	    text = 'XXX\n%d\n%s\nXXX\n' % (perc, text)
278*4c8945a0SNathan Whitehorn	else:
279*4c8945a0SNathan Whitehorn	    text = '%d\n' % perc
280*4c8945a0SNathan Whitehorn	self.pipe.write(text)
281*4c8945a0SNathan Whitehorn	self.pipe.flush()
282*4c8945a0SNathan Whitehorn    #/gauge_iterate()
283*4c8945a0SNathan Whitehorn
284*4c8945a0SNathan Whitehorn
285*4c8945a0SNathan Whitehorn    def gauge_stop(self):
286*4c8945a0SNathan Whitehorn	"""
287*4c8945a0SNathan Whitehorn	Finish previously started gauge.
288*4c8945a0SNathan Whitehorn
289*4c8945a0SNathan Whitehorn	See gauge_start() function above for the usage.
290*4c8945a0SNathan Whitehorn	"""
291*4c8945a0SNathan Whitehorn	self.pipe.close()
292*4c8945a0SNathan Whitehorn    #/gauge_stop()
293*4c8945a0SNathan Whitehorn
294*4c8945a0SNathan Whitehorn
295*4c8945a0SNathan Whitehorn
296*4c8945a0SNathan Whitehorn#
297*4c8945a0SNathan Whitehorn# DEMO APPLICATION
298*4c8945a0SNathan Whitehorn#
299*4c8945a0SNathan Whitehornif __name__ == '__main__':
300*4c8945a0SNathan Whitehorn    """
301*4c8945a0SNathan Whitehorn    This demo tests all the features of the class.
302*4c8945a0SNathan Whitehorn    """
303*4c8945a0SNathan Whitehorn    d = Dialog()
304*4c8945a0SNathan Whitehorn    d.setBackgroundTitle('dialog.py demo')
305*4c8945a0SNathan Whitehorn
306*4c8945a0SNathan Whitehorn    d.infobox(
307*4c8945a0SNathan Whitehorn	"One moment... Just wasting some time here to test the infobox...")
308*4c8945a0SNathan Whitehorn    sleep(3)
309*4c8945a0SNathan Whitehorn
310*4c8945a0SNathan Whitehorn    if d.yesno("Do you like this demo?"):
311*4c8945a0SNathan Whitehorn	d.msgbox("Excellent!  Here's the source code:")
312*4c8945a0SNathan Whitehorn    else:
313*4c8945a0SNathan Whitehorn	d.msgbox("Send your complaints to /dev/null")
314*4c8945a0SNathan Whitehorn
315*4c8945a0SNathan Whitehorn    d.textbox("dialog.py")
316*4c8945a0SNathan Whitehorn
317*4c8945a0SNathan Whitehorn    name = d.inputbox("What's your name?", init="Snow White")
318*4c8945a0SNathan Whitehorn    fday = d.menu("What's your favorite day of the week?",
319*4c8945a0SNathan Whitehorn	list=["Monday", "Tuesday", "Wednesday", "Thursday",
320*4c8945a0SNathan Whitehorn	    "Friday (The best day of all)", "Saturday", "Sunday"])
321*4c8945a0SNathan Whitehorn    food = d.checklist("What sandwich toppings do you like?",
322*4c8945a0SNathan Whitehorn	list=["Catsup", "Mustard", "Pesto", "Mayonaise", "Horse radish",
323*4c8945a0SNathan Whitehorn	    "Sun-dried tomatoes"], checked=[0,0,0,1,1,1])
324*4c8945a0SNathan Whitehorn    sand = d.radiolist("What's your favorite kind of sandwich?",
325*4c8945a0SNathan Whitehorn	list=["Hamburger", "Hotdog", "Burrito", "Doener", "Falafel",
326*4c8945a0SNathan Whitehorn	    "Bagel", "Big Mac", "Whopper", "Quarter Pounder",
327*4c8945a0SNathan Whitehorn	    "Peanut Butter and Jelly", "Grilled cheese"], selected=4)
328*4c8945a0SNathan Whitehorn
329*4c8945a0SNathan Whitehorn    # Prepare the message for the final window
330*4c8945a0SNathan Whitehorn    bigMessage = "Here are some vital statistics about you:\n\nName: " + name +\
331*4c8945a0SNathan Whitehorn        "\nFavorite day of the week: " + fday +\
332*4c8945a0SNathan Whitehorn	"\nFavorite sandwich toppings:\n"
333*4c8945a0SNathan Whitehorn    for topping in food:
334*4c8945a0SNathan Whitehorn	bigMessage = bigMessage + "    " + topping + "\n"
335*4c8945a0SNathan Whitehorn    bigMessage = bigMessage + "Favorite sandwich: " + str(sand)
336*4c8945a0SNathan Whitehorn
337*4c8945a0SNathan Whitehorn    d.scrollbox(bigMessage)
338*4c8945a0SNathan Whitehorn
339*4c8945a0SNathan Whitehorn    #<>#  Gauge Demo
340*4c8945a0SNathan Whitehorn    d.gauge_start(0, 'percentage: 0', title='Gauge Demo')
341*4c8945a0SNathan Whitehorn    for i in range(1, 101):
342*4c8945a0SNathan Whitehorn	if i < 50:
343*4c8945a0SNathan Whitehorn	    msg = 'percentage: %d' % i
344*4c8945a0SNathan Whitehorn	elif i == 50:
345*4c8945a0SNathan Whitehorn	    msg = 'Over 50%'
346*4c8945a0SNathan Whitehorn	else:
347*4c8945a0SNathan Whitehorn	    msg = ''
348*4c8945a0SNathan Whitehorn	d.gauge_iterate(i, msg)
349*4c8945a0SNathan Whitehorn	sleep(0.1)
350*4c8945a0SNathan Whitehorn    d.gauge_stop()
351*4c8945a0SNathan Whitehorn    #<>#
352*4c8945a0SNathan Whitehorn
353*4c8945a0SNathan Whitehorn    d.clear()
354