| #! /usr/bin/env python | 
 |  | 
 | # A Python function that generates dialog boxes with a text message, | 
 | # optional bitmap, and any number of buttons. | 
 | # Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270. | 
 |  | 
 | from Tkinter import * | 
 |  | 
 | mainWidget = None | 
 |  | 
 | def dialog(master, title, text, bitmap, default, *args): | 
 |  | 
 |     # 1. Create the top-level window and divide it into top | 
 |     # and bottom parts. | 
 |  | 
 |     w = Toplevel(master, {'class': 'Dialog'}) | 
 |     w.title(title) | 
 |     w.iconname('Dialog') | 
 |  | 
 |     top = Frame(w, {'relief': 'raised', 'bd': 1, | 
 |                     Pack: {'side': 'top', 'fill': 'both'}}) | 
 |     bot = Frame(w, {'relief': 'raised', 'bd': 1, | 
 |                     Pack: {'side': 'bottom', 'fill': 'both'}}) | 
 |  | 
 |     # 2. Fill the top part with the bitmap and message. | 
 |  | 
 |     msg = Message(top, | 
 |                   {'width': '3i', | 
 |                    'text': text, | 
 |                    'font': '-Adobe-Times-Medium-R-Normal-*-180-*', | 
 |                    Pack: {'side': 'right', 'expand': 1, | 
 |                           'fill': 'both', | 
 |                           'padx': '3m', 'pady': '3m'}}) | 
 |     if bitmap: | 
 |         bm = Label(top, {'bitmap': bitmap, | 
 |                          Pack: {'side': 'left', | 
 |                                 'padx': '3m', 'pady': '3m'}}) | 
 |  | 
 |     # 3. Create a row of buttons at the bottom of the dialog. | 
 |  | 
 |     buttons = [] | 
 |     i = 0 | 
 |     for but in args: | 
 |         b = Button(bot, {'text': but, | 
 |                          'command': ('set', 'button', i)}) | 
 |         buttons.append(b) | 
 |         if i == default: | 
 |             bd = Frame(bot, {'relief': 'sunken', 'bd': 1, | 
 |                              Pack: {'side': 'left', 'expand': 1, | 
 |                                     'padx': '3m', 'pady': '2m'}}) | 
 |             b.lift() | 
 |             b.pack ({'in': bd, 'side': 'left', | 
 |                      'padx': '2m', 'pady': '2m', | 
 |                      'ipadx': '2m', 'ipady': '1m'}) | 
 |         else: | 
 |             b.pack ({'side': 'left', 'expand': 1, | 
 |                      'padx': '3m', 'pady': '3m', | 
 |                      'ipady': '2m', 'ipady': '1m'}) | 
 |         i = i+1 | 
 |  | 
 |     # 4. Set up a binding for <Return>, if there's a default, | 
 |     # set a grab, and claim the focus too. | 
 |  | 
 |     if default >= 0: | 
 |         w.bind('<Return>', | 
 |                lambda e, b=buttons[default], i=default: | 
 |                (b.flash(), | 
 |                 b.setvar('button', i))) | 
 |  | 
 |     oldFocus = w.tk.call('focus') # XXX | 
 |     w.grab_set() | 
 |     w.focus() | 
 |  | 
 |     # 5. Wait for the user to respond, then restore the focus | 
 |     # and return the index of the selected button. | 
 |  | 
 |     w.waitvar('button') | 
 |     w.destroy() | 
 |     w.tk.call('focus', oldFocus) # XXX | 
 |     return w.getint(w.getvar('button')) | 
 |  | 
 | def strdialog(master, title, text, bitmap, default, *args): | 
 |  | 
 |     # 1. Create the top-level window and divide it into top | 
 |     # and bottom parts. | 
 |  | 
 |     w = Toplevel(master, {'class': 'Dialog'}) | 
 |     w.title(title) | 
 |     w.iconname('Dialog') | 
 |  | 
 |     top = Frame(w, {'relief': 'raised', 'bd': 1, | 
 |                     Pack: {'side': 'top', 'fill': 'both'}}) | 
 |     if args: | 
 |         bot = Frame(w, {'relief': 'raised', 'bd': 1, | 
 |                     Pack: {'side': 'bottom', 'fill': 'both'}}) | 
 |  | 
 |     # 2. Fill the top part with the bitmap, message and input field. | 
 |  | 
 |     if bitmap: | 
 |         bm = Label(top, {'bitmap': bitmap, | 
 |                          Pack: {'side': 'left', | 
 |                                 'padx': '3m', 'pady': '3m'}}) | 
 |  | 
 |     msg = Message(top, | 
 |                   {'width': '3i', | 
 |                    'text': text, | 
 |                    'font': '-Adobe-Times-Medium-R-Normal-*-180-*', | 
 |                    Pack: {'side': 'left',  | 
 |                           'fill': 'both', | 
 |                           'padx': '3m', 'pady': '3m'}}) | 
 |  | 
 |     field = Entry(top, | 
 |                   {'relief':'sunken', | 
 |                    Pack:{'side':'left', | 
 |                          'fill':'x', | 
 |                          'expand':1, | 
 |                          'padx':'3m', 'pady':'3m'}}) | 
 |     # 3. Create a row of buttons at the bottom of the dialog. | 
 |  | 
 |     buttons = [] | 
 |     i = 0 | 
 |     for but in args: | 
 |         b = Button(bot, {'text': but, | 
 |                          'command': ('set', 'button', i)}) | 
 |         buttons.append(b) | 
 |         if i == default: | 
 |             bd = Frame(bot, {'relief': 'sunken', 'bd': 1, | 
 |                              Pack: {'side': 'left', 'expand': 1, | 
 |                                     'padx': '3m', 'pady': '2m'}}) | 
 |             b.lift() | 
 |             b.pack ({'in': bd, 'side': 'left', | 
 |                      'padx': '2m', 'pady': '2m', | 
 |                      'ipadx': '2m', 'ipady': '1m'}) | 
 |         else: | 
 |             b.pack ({'side': 'left', 'expand': 1, | 
 |                      'padx': '3m', 'pady': '3m', | 
 |                      'ipady': '2m', 'ipady': '1m'}) | 
 |         i = i+1 | 
 |  | 
 |     # 4. Set up a binding for <Return>, if there's a default, | 
 |     # set a grab, and claim the focus too. | 
 |  | 
 |     if not args: | 
 |         w.bind('<Return>', lambda arg, top=top: top.setvar('button', 0)) | 
 |         field.bind('<Return>', lambda arg, top=top: top.setvar('button', 0)) | 
 |     elif default >= 0: | 
 |         w.bind('<Return>', | 
 |                lambda e, b=buttons[default], i=default: | 
 |                (b.flash(), | 
 |                 b.setvar('button', i))) | 
 |         field.bind('<Return>', | 
 |                lambda e, b=buttons[default], i=default: | 
 |                (b.flash(), | 
 |                 b.setvar('button', i))) | 
 |  | 
 |     oldFocus = w.tk.call('focus') # XXX | 
 |     w.grab_set() | 
 |     field.focus() | 
 |  | 
 |     # 5. Wait for the user to respond, then restore the focus | 
 |     # and return the index of the selected button. | 
 |  | 
 |     w.waitvar('button') | 
 |     v = field.get() | 
 |     w.destroy() | 
 |     w.tk.call('focus', oldFocus) # XXX | 
 |     if args: | 
 |         return v, w.getint(w.getvar('button')) | 
 |     else: | 
 |         return v | 
 |  | 
 | def message(str): | 
 |     i = dialog(mainWidget, 'Message', str, '', 0, 'OK') | 
 |  | 
 | def askyn(str): | 
 |     i = dialog(mainWidget, 'Question', str, '', 0, 'No', 'Yes') | 
 |     return i | 
 |  | 
 | def askync(str): | 
 |     i = dialog(mainWidget, 'Question', str, '', 0, 'Cancel', 'No', 'Yes') | 
 |     return i-1 | 
 |  | 
 | def askstr(str): | 
 |     i = strdialog(mainWidget, 'Question', str, '', 0) | 
 |     return i | 
 |  | 
 | def askfile(str):       # XXXX For now... | 
 |     i = strdialog(mainWidget, 'Question', str, '', 0) | 
 |     return i | 
 |      | 
 | # The rest is the test program. | 
 |  | 
 | def _go(): | 
 |     i = dialog(mainWidget, | 
 |                'Not Responding', | 
 |                "The file server isn't responding right now; " | 
 |                "I'll keep trying.", | 
 |                '', | 
 |                -1, | 
 |                'OK') | 
 |     print 'pressed button', i | 
 |     i = dialog(mainWidget, | 
 |                'File Modified', | 
 |                'File "tcl.h" has been modified since ' | 
 |                'the last time it was saved. ' | 
 |                'Do you want to save it before exiting the application?', | 
 |                'warning', | 
 |                0, | 
 |                'Save File', | 
 |                'Discard Changes', | 
 |                'Return To Editor') | 
 |     print 'pressed button', i | 
 |     print message('Test of message') | 
 |     print askyn('Test of yes/no') | 
 |     print askync('Test of yes/no/cancel') | 
 |     print askstr('Type a string:') | 
 |     print strdialog(mainWidget, 'Question', 'Another string:', '', | 
 |                   0, 'Save', 'Save as text') | 
 |  | 
 | def _test(): | 
 |     import sys | 
 |     global mainWidget | 
 |     mainWidget = Frame() | 
 |     Pack.config(mainWidget) | 
 |     start = Button(mainWidget, | 
 |                    {'text': 'Press Here To Start', 'command': _go}) | 
 |     start.pack() | 
 |     endit = Button(mainWidget, | 
 |                    {'text': 'Exit', | 
 |                     'command': 'exit', | 
 |                     Pack: {'fill' : 'both'}}) | 
 |     mainWidget.mainloop() | 
 |  | 
 | if __name__ == '__main__': | 
 |     _test() |