blob: 00ed5eb981e2291ca26e35849b5f989c8966e9dd [file] [log] [blame]
Guido van Rossumf06ee5f1996-11-27 19:52:01 +00001#! /usr/bin/env python
Guido van Rossumd2112201995-03-02 14:05:29 +00002
3# A Python function that generates dialog boxes with a text message,
4# optional bitmap, and any number of buttons.
5# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270.
6
7from Tkinter import *
8
9mainWidget = None
10
11def dialog(master, title, text, bitmap, default, *args):
12
13 # 1. Create the top-level window and divide it into top
14 # and bottom parts.
15
16 w = Toplevel(master, {'class': 'Dialog'})
17 w.title(title)
18 w.iconname('Dialog')
19
20 top = Frame(w, {'relief': 'raised', 'bd': 1,
Guido van Rossuma16a5091998-04-10 19:15:27 +000021 Pack: {'side': 'top', 'fill': 'both'}})
Guido van Rossumd2112201995-03-02 14:05:29 +000022 bot = Frame(w, {'relief': 'raised', 'bd': 1,
Guido van Rossuma16a5091998-04-10 19:15:27 +000023 Pack: {'side': 'bottom', 'fill': 'both'}})
Guido van Rossumd2112201995-03-02 14:05:29 +000024
25 # 2. Fill the top part with the bitmap and message.
26
27 msg = Message(top,
Guido van Rossuma16a5091998-04-10 19:15:27 +000028 {'width': '3i',
29 'text': text,
30 'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
31 Pack: {'side': 'right', 'expand': 1,
32 'fill': 'both',
33 'padx': '3m', 'pady': '3m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +000034 if bitmap:
Guido van Rossuma16a5091998-04-10 19:15:27 +000035 bm = Label(top, {'bitmap': bitmap,
36 Pack: {'side': 'left',
37 'padx': '3m', 'pady': '3m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +000038
39 # 3. Create a row of buttons at the bottom of the dialog.
40
41 buttons = []
42 i = 0
43 for but in args:
Guido van Rossuma16a5091998-04-10 19:15:27 +000044 b = Button(bot, {'text': but,
45 'command': ('set', 'button', i)})
46 buttons.append(b)
47 if i == default:
48 bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
49 Pack: {'side': 'left', 'expand': 1,
50 'padx': '3m', 'pady': '2m'}})
51 b.lift()
52 b.pack ({'in': bd, 'side': 'left',
53 'padx': '2m', 'pady': '2m',
54 'ipadx': '2m', 'ipady': '1m'})
55 else:
56 b.pack ({'side': 'left', 'expand': 1,
57 'padx': '3m', 'pady': '3m',
58 'ipady': '2m', 'ipady': '1m'})
59 i = i+1
Guido van Rossumd2112201995-03-02 14:05:29 +000060
61 # 4. Set up a binding for <Return>, if there's a default,
62 # set a grab, and claim the focus too.
63
64 if default >= 0:
Guido van Rossuma16a5091998-04-10 19:15:27 +000065 w.bind('<Return>',
66 lambda e, b=buttons[default], i=default:
67 (b.flash(),
68 b.setvar('button', i)))
Guido van Rossumd2112201995-03-02 14:05:29 +000069
70 oldFocus = w.tk.call('focus') # XXX
71 w.grab_set()
72 w.focus()
73
74 # 5. Wait for the user to respond, then restore the focus
75 # and return the index of the selected button.
76
77 w.waitvar('button')
78 w.destroy()
79 w.tk.call('focus', oldFocus) # XXX
80 return w.getint(w.getvar('button'))
81
82def strdialog(master, title, text, bitmap, default, *args):
83
84 # 1. Create the top-level window and divide it into top
85 # and bottom parts.
86
87 w = Toplevel(master, {'class': 'Dialog'})
88 w.title(title)
89 w.iconname('Dialog')
90
91 top = Frame(w, {'relief': 'raised', 'bd': 1,
Guido van Rossuma16a5091998-04-10 19:15:27 +000092 Pack: {'side': 'top', 'fill': 'both'}})
Guido van Rossumd2112201995-03-02 14:05:29 +000093 if args:
Guido van Rossuma16a5091998-04-10 19:15:27 +000094 bot = Frame(w, {'relief': 'raised', 'bd': 1,
95 Pack: {'side': 'bottom', 'fill': 'both'}})
Guido van Rossumd2112201995-03-02 14:05:29 +000096
97 # 2. Fill the top part with the bitmap, message and input field.
98
99 if bitmap:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000100 bm = Label(top, {'bitmap': bitmap,
101 Pack: {'side': 'left',
102 'padx': '3m', 'pady': '3m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000103
104 msg = Message(top,
Guido van Rossuma16a5091998-04-10 19:15:27 +0000105 {'width': '3i',
106 'text': text,
107 'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
108 Pack: {'side': 'left',
109 'fill': 'both',
110 'padx': '3m', 'pady': '3m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000111
112 field = Entry(top,
Guido van Rossuma16a5091998-04-10 19:15:27 +0000113 {'relief':'sunken',
114 Pack:{'side':'left',
115 'fill':'x',
116 'expand':1,
117 'padx':'3m', 'pady':'3m'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000118 # 3. Create a row of buttons at the bottom of the dialog.
119
120 buttons = []
121 i = 0
122 for but in args:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000123 b = Button(bot, {'text': but,
124 'command': ('set', 'button', i)})
125 buttons.append(b)
126 if i == default:
127 bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
128 Pack: {'side': 'left', 'expand': 1,
129 'padx': '3m', 'pady': '2m'}})
130 b.lift()
131 b.pack ({'in': bd, 'side': 'left',
132 'padx': '2m', 'pady': '2m',
133 'ipadx': '2m', 'ipady': '1m'})
134 else:
135 b.pack ({'side': 'left', 'expand': 1,
136 'padx': '3m', 'pady': '3m',
137 'ipady': '2m', 'ipady': '1m'})
138 i = i+1
Guido van Rossumd2112201995-03-02 14:05:29 +0000139
140 # 4. Set up a binding for <Return>, if there's a default,
141 # set a grab, and claim the focus too.
142
143 if not args:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000144 w.bind('<Return>', lambda arg, top=top: top.setvar('button', 0))
145 field.bind('<Return>', lambda arg, top=top: top.setvar('button', 0))
Guido van Rossumd2112201995-03-02 14:05:29 +0000146 elif default >= 0:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000147 w.bind('<Return>',
148 lambda e, b=buttons[default], i=default:
149 (b.flash(),
150 b.setvar('button', i)))
151 field.bind('<Return>',
152 lambda e, b=buttons[default], i=default:
153 (b.flash(),
154 b.setvar('button', i)))
Guido van Rossumd2112201995-03-02 14:05:29 +0000155
156 oldFocus = w.tk.call('focus') # XXX
157 w.grab_set()
158 field.focus()
159
160 # 5. Wait for the user to respond, then restore the focus
161 # and return the index of the selected button.
162
163 w.waitvar('button')
164 v = field.get()
165 w.destroy()
166 w.tk.call('focus', oldFocus) # XXX
167 if args:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000168 return v, w.getint(w.getvar('button'))
Guido van Rossumd2112201995-03-02 14:05:29 +0000169 else:
Guido van Rossuma16a5091998-04-10 19:15:27 +0000170 return v
Guido van Rossumd2112201995-03-02 14:05:29 +0000171
172def message(str):
173 i = dialog(mainWidget, 'Message', str, '', 0, 'OK')
174
175def askyn(str):
176 i = dialog(mainWidget, 'Question', str, '', 0, 'No', 'Yes')
177 return i
178
179def askync(str):
180 i = dialog(mainWidget, 'Question', str, '', 0, 'Cancel', 'No', 'Yes')
181 return i-1
182
183def askstr(str):
184 i = strdialog(mainWidget, 'Question', str, '', 0)
185 return i
186
Guido van Rossuma16a5091998-04-10 19:15:27 +0000187def askfile(str): # XXXX For now...
Guido van Rossumd2112201995-03-02 14:05:29 +0000188 i = strdialog(mainWidget, 'Question', str, '', 0)
189 return i
190
191# The rest is the test program.
192
193def _go():
194 i = dialog(mainWidget,
Guido van Rossuma16a5091998-04-10 19:15:27 +0000195 'Not Responding',
196 "The file server isn't responding right now; "
197 "I'll keep trying.",
198 '',
199 -1,
200 'OK')
Guido van Rossumd2112201995-03-02 14:05:29 +0000201 print 'pressed button', i
202 i = dialog(mainWidget,
Guido van Rossuma16a5091998-04-10 19:15:27 +0000203 'File Modified',
204 'File "tcl.h" has been modified since '
205 'the last time it was saved. '
206 'Do you want to save it before exiting the application?',
207 'warning',
208 0,
209 'Save File',
210 'Discard Changes',
211 'Return To Editor')
Guido van Rossumd2112201995-03-02 14:05:29 +0000212 print 'pressed button', i
213 print message('Test of message')
214 print askyn('Test of yes/no')
215 print askync('Test of yes/no/cancel')
216 print askstr('Type a string:')
217 print strdialog(mainWidget, 'Question', 'Another string:', '',
Guido van Rossuma16a5091998-04-10 19:15:27 +0000218 0, 'Save', 'Save as text')
Guido van Rossumd2112201995-03-02 14:05:29 +0000219
220def _test():
221 import sys
222 global mainWidget
223 mainWidget = Frame()
224 Pack.config(mainWidget)
225 start = Button(mainWidget,
Guido van Rossuma16a5091998-04-10 19:15:27 +0000226 {'text': 'Press Here To Start', 'command': _go})
Guido van Rossumd2112201995-03-02 14:05:29 +0000227 start.pack()
228 endit = Button(mainWidget,
Guido van Rossuma16a5091998-04-10 19:15:27 +0000229 {'text': 'Exit',
230 'command': 'exit',
231 Pack: {'fill' : 'both'}})
Guido van Rossumd2112201995-03-02 14:05:29 +0000232 mainWidget.mainloop()
233
234if __name__ == '__main__':
235 _test()