Fix three PyChecker-detected gotchas.
[python/dscho.git] / Mac / Lib / EasyDialogs.py
bloba4862041f9b5e50d876b01c6ea133083c4b69031
1 """Easy to use dialogs.
3 Message(msg) -- display a message and an OK button.
4 AskString(prompt, default) -- ask for a string, display OK and Cancel buttons.
5 AskPassword(prompt, default) -- like AskString(), but shows text as bullets.
6 AskYesNoCancel(question, default) -- display a question and Yes, No and Cancel buttons.
7 bar = Progress(label, maxvalue) -- Display a progress bar
8 bar.set(value) -- Set value
9 bar.inc( *amount ) -- increment value by amount (default=1)
10 bar.label( *newlabel ) -- get or set text label.
12 More documentation in each function.
13 This module uses DLOG resources 260 and on.
14 Based upon STDWIN dialogs with the same names and functions.
15 """
17 from Dlg import GetNewDialog, SetDialogItemText, GetDialogItemText, ModalDialog
18 import Qd
19 import QuickDraw
20 import Dialogs
21 import Windows
22 import Dlg,Win,Evt,Events # sdm7g
23 import Ctl
24 import Controls
25 import Menu
26 import MacOS
27 import string
28 from ControlAccessor import * # Also import Controls constants
29 import macfs
31 def cr2lf(text):
32 if '\r' in text:
33 text = string.join(string.split(text, '\r'), '\n')
34 return text
36 def lf2cr(text):
37 if '\n' in text:
38 text = string.join(string.split(text, '\n'), '\r')
39 if len(text) > 253:
40 text = text[:253] + '\311'
41 return text
43 def Message(msg, id=260, ok=None):
44 """Display a MESSAGE string.
46 Return when the user clicks the OK button or presses Return.
48 The MESSAGE string can be at most 255 characters long.
49 """
51 d = GetNewDialog(id, -1)
52 if not d:
53 print "Can't get DLOG resource with id =", id
54 return
55 h = d.GetDialogItemAsControl(2)
56 SetDialogItemText(h, lf2cr(msg))
57 if ok != None:
58 h = d.GetDialogItemAsControl(1)
59 h.SetControlTitle(ok)
60 d.SetDialogDefaultItem(1)
61 d.AutoSizeDialog()
62 d.GetDialogWindow().ShowWindow()
63 while 1:
64 n = ModalDialog(None)
65 if n == 1:
66 return
69 def AskString(prompt, default = "", id=261, ok=None, cancel=None):
70 """Display a PROMPT string and a text entry field with a DEFAULT string.
72 Return the contents of the text entry field when the user clicks the
73 OK button or presses Return.
74 Return None when the user clicks the Cancel button.
76 If omitted, DEFAULT is empty.
78 The PROMPT and DEFAULT strings, as well as the return value,
79 can be at most 255 characters long.
80 """
82 d = GetNewDialog(id, -1)
83 if not d:
84 print "Can't get DLOG resource with id =", id
85 return
86 h = d.GetDialogItemAsControl(3)
87 SetDialogItemText(h, lf2cr(prompt))
88 h = d.GetDialogItemAsControl(4)
89 SetDialogItemText(h, lf2cr(default))
90 d.SelectDialogItemText(4, 0, 999)
91 # d.SetDialogItem(4, 0, 255)
92 if ok != None:
93 h = d.GetDialogItemAsControl(1)
94 h.SetControlTitle(ok)
95 if cancel != None:
96 h = d.GetDialogItemAsControl(2)
97 h.SetControlTitle(cancel)
98 d.SetDialogDefaultItem(1)
99 d.SetDialogCancelItem(2)
100 d.AutoSizeDialog()
101 d.GetDialogWindow().ShowWindow()
102 while 1:
103 n = ModalDialog(None)
104 if n == 1:
105 h = d.GetDialogItemAsControl(4)
106 return cr2lf(GetDialogItemText(h))
107 if n == 2: return None
109 def AskPassword(prompt, default='', id=264, ok=None, cancel=None):
110 """Display a PROMPT string and a text entry field with a DEFAULT string.
111 The string is displayed as bullets only.
113 Return the contents of the text entry field when the user clicks the
114 OK button or presses Return.
115 Return None when the user clicks the Cancel button.
117 If omitted, DEFAULT is empty.
119 The PROMPT and DEFAULT strings, as well as the return value,
120 can be at most 255 characters long.
122 d = GetNewDialog(id, -1)
123 if not d:
124 print "Can't get DLOG resource with id =", id
125 return
126 h = d.GetDialogItemAsControl(3)
127 SetDialogItemText(h, lf2cr(prompt))
128 pwd = d.GetDialogItemAsControl(4)
129 bullets = '\245'*len(default)
130 ## SetControlData(pwd, kControlEditTextPart, kControlEditTextTextTag, bullets)
131 SetControlData(pwd, kControlEditTextPart, kControlEditTextPasswordTag, default)
132 d.SelectDialogItemText(4, 0, 999)
133 Ctl.SetKeyboardFocus(d.GetDialogWindow(), pwd, kControlEditTextPart)
134 if ok != None:
135 h = d.GetDialogItemAsControl(1)
136 h.SetControlTitle(ok)
137 if cancel != None:
138 h = d.GetDialogItemAsControl(2)
139 h.SetControlTitle(cancel)
140 d.SetDialogDefaultItem(Dialogs.ok)
141 d.SetDialogCancelItem(Dialogs.cancel)
142 d.AutoSizeDialog()
143 d.GetDialogWindow().ShowWindow()
144 while 1:
145 n = ModalDialog(None)
146 if n == 1:
147 h = d.GetDialogItemAsControl(4)
148 return cr2lf(GetControlData(pwd, kControlEditTextPart, kControlEditTextPasswordTag))
149 if n == 2: return None
151 def AskYesNoCancel(question, default = 0, yes=None, no=None, cancel=None, id=262):
152 """Display a QUESTION string which can be answered with Yes or No.
154 Return 1 when the user clicks the Yes button.
155 Return 0 when the user clicks the No button.
156 Return -1 when the user clicks the Cancel button.
158 When the user presses Return, the DEFAULT value is returned.
159 If omitted, this is 0 (No).
161 The QUESTION strign ca be at most 255 characters.
164 d = GetNewDialog(id, -1)
165 if not d:
166 print "Can't get DLOG resource with id =", id
167 return
168 # Button assignments:
169 # 1 = default (invisible)
170 # 2 = Yes
171 # 3 = No
172 # 4 = Cancel
173 # The question string is item 5
174 h = d.GetDialogItemAsControl(5)
175 SetDialogItemText(h, lf2cr(question))
176 if yes != None:
177 if yes == '':
178 d.HideDialogItem(2)
179 else:
180 h = d.GetDialogItemAsControl(2)
181 h.SetControlTitle(yes)
182 if no != None:
183 if no == '':
184 d.HideDialogItem(3)
185 else:
186 h = d.GetDialogItemAsControl(3)
187 h.SetControlTitle(no)
188 if cancel != None:
189 if cancel == '':
190 d.HideDialogItem(4)
191 else:
192 h = d.GetDialogItemAsControl(4)
193 h.SetControlTitle(cancel)
194 d.SetDialogCancelItem(4)
195 if default == 1:
196 d.SetDialogDefaultItem(2)
197 elif default == 0:
198 d.SetDialogDefaultItem(3)
199 elif default == -1:
200 d.SetDialogDefaultItem(4)
201 d.AutoSizeDialog()
202 d.GetDialogWindow().ShowWindow()
203 while 1:
204 n = ModalDialog(None)
205 if n == 1: return default
206 if n == 2: return 1
207 if n == 3: return 0
208 if n == 4: return -1
213 screenbounds = Qd.qd.screenBits.bounds
214 screenbounds = screenbounds[0]+4, screenbounds[1]+4, \
215 screenbounds[2]-4, screenbounds[3]-4
218 class ProgressBar:
219 def __init__(self, title="Working...", maxval=100, label="", id=263):
220 self.w = None
221 self.d = None
222 self.maxval = maxval
223 self.curval = -1
224 self.d = GetNewDialog(id, -1)
225 self.w = self.d.GetDialogWindow()
226 self.label(label)
227 self._update(0)
228 self.d.AutoSizeDialog()
229 self.title(title)
230 self.w.ShowWindow()
231 self.d.DrawDialog()
233 def __del__( self ):
234 if self.w:
235 self.w.BringToFront()
236 self.w.HideWindow()
237 del self.w
238 del self.d
240 def title(self, newstr=""):
241 """title(text) - Set title of progress window"""
242 self.w.BringToFront()
243 self.w.SetWTitle(newstr)
245 def label( self, *newstr ):
246 """label(text) - Set text in progress box"""
247 self.w.BringToFront()
248 if newstr:
249 self._label = lf2cr(newstr[0])
250 text_h = self.d.GetDialogItemAsControl(2)
251 SetDialogItemText(text_h, self._label)
253 def _update(self, value):
254 maxval = self.maxval
255 if maxval == 0:
256 # XXXX Quick fix. Should probably display an unknown duration
257 value = 0
258 maxval = 1
259 if maxval > 32767:
260 value = int(value/(maxval/32767.0))
261 maxval = 32767
262 progbar = self.d.GetDialogItemAsControl(3)
263 progbar.SetControlMaximum(maxval)
264 progbar.SetControlValue(value)
265 # Test for cancel button
267 ready, ev = Evt.WaitNextEvent( Events.mDownMask, 1 )
268 if ready :
269 what,msg,when,where,mod = ev
270 part = Win.FindWindow(where)[0]
271 if Dlg.IsDialogEvent(ev):
272 ds = Dlg.DialogSelect(ev)
273 if ds[0] and ds[1] == self.d and ds[-1] == 1:
274 self.w.HideWindow()
275 self.w = None
276 self.d = None
277 raise KeyboardInterrupt, ev
278 else:
279 if part == 4: # inDrag
280 self.d.DragWindow(where, screenbounds)
281 else:
282 MacOS.HandleEvent(ev)
285 def set(self, value, max=None):
286 """set(value) - Set progress bar position"""
287 if max != None:
288 self.maxval = max
289 if value < 0: value = 0
290 if value > self.maxval: value = self.maxval
291 self.curval = value
292 self._update(value)
294 def inc(self, n=1):
295 """inc(amt) - Increment progress bar position"""
296 self.set(self.curval + n)
298 ARGV_ID=265
299 ARGV_ITEM_OK=1
300 ARGV_ITEM_CANCEL=2
301 ARGV_OPTION_GROUP=3
302 ARGV_OPTION_EXPLAIN=4
303 ARGV_OPTION_VALUE=5
304 ARGV_OPTION_ADD=6
305 ARGV_COMMAND_GROUP=7
306 ARGV_COMMAND_EXPLAIN=8
307 ARGV_COMMAND_ADD=9
308 ARGV_ADD_OLDFILE=10
309 ARGV_ADD_NEWFILE=11
310 ARGV_ADD_FOLDER=12
311 ARGV_CMDLINE_GROUP=13
312 ARGV_CMDLINE_DATA=14
314 ##def _myModalDialog(d):
315 ## while 1:
316 ## ready, ev = Evt.WaitNextEvent(0xffff, -1)
317 ## print 'DBG: WNE', ready, ev
318 ## if ready :
319 ## what,msg,when,where,mod = ev
320 ## part, window = Win.FindWindow(where)
321 ## if Dlg.IsDialogEvent(ev):
322 ## didit, dlgdone, itemdone = Dlg.DialogSelect(ev)
323 ## print 'DBG: DialogSelect', didit, dlgdone, itemdone, d
324 ## if didit and dlgdone == d:
325 ## return itemdone
326 ## elif window == d.GetDialogWindow():
327 ## d.GetDialogWindow().SelectWindow()
328 ## if part == 4: # inDrag
329 ## d.DragWindow(where, screenbounds)
330 ## else:
331 ## MacOS.HandleEvent(ev)
332 ## else:
333 ## MacOS.HandleEvent(ev)
335 def _setmenu(control, items):
336 mhandle = control.GetControlData_Handle(Controls.kControlMenuPart,
337 Controls.kControlPopupButtonMenuHandleTag)
338 menu = Menu.as_Menu(mhandle)
339 for item in items:
340 if type(item) == type(()):
341 label = item[0]
342 else:
343 label = item
344 if label[-1] == '=' or label[-1] == ':':
345 label = label[:-1]
346 menu.AppendMenu(label)
347 ## mhandle, mid = menu.getpopupinfo()
348 ## control.SetControlData_Handle(Controls.kControlMenuPart,
349 ## Controls.kControlPopupButtonMenuHandleTag, mhandle)
350 control.SetControlMinimum(1)
351 control.SetControlMaximum(len(items)+1)
353 def _selectoption(d, optionlist, idx):
354 if idx < 0 or idx >= len(optionlist):
355 MacOS.SysBeep()
356 return
357 option = optionlist[idx]
358 if type(option) == type(()) and \
359 len(option) > 1:
360 help = option[-1]
361 else:
362 help = ''
363 h = d.GetDialogItemAsControl(ARGV_OPTION_EXPLAIN)
364 Dlg.SetDialogItemText(h, help)
365 hasvalue = 0
366 if type(option) == type(()):
367 label = option[0]
368 else:
369 label = option
370 if label[-1] == '=' or label[-1] == ':':
371 hasvalue = 1
372 h = d.GetDialogItemAsControl(ARGV_OPTION_VALUE)
373 Dlg.SetDialogItemText(h, '')
374 if hasvalue:
375 d.ShowDialogItem(ARGV_OPTION_VALUE)
376 d.SelectDialogItemText(ARGV_OPTION_VALUE, 0, 0)
377 else:
378 d.HideDialogItem(ARGV_OPTION_VALUE)
381 def GetArgv(optionlist=None, commandlist=None, addoldfile=1, addnewfile=1, addfolder=1, id=ARGV_ID):
382 d = GetNewDialog(id, -1)
383 if not d:
384 print "Can't get DLOG resource with id =", id
385 return
386 # h = d.GetDialogItemAsControl(3)
387 # SetDialogItemText(h, lf2cr(prompt))
388 # h = d.GetDialogItemAsControl(4)
389 # SetDialogItemText(h, lf2cr(default))
390 # d.SelectDialogItemText(4, 0, 999)
391 # d.SetDialogItem(4, 0, 255)
392 if optionlist:
393 _setmenu(d.GetDialogItemAsControl(ARGV_OPTION_GROUP), optionlist)
394 _selectoption(d, optionlist, 0)
395 else:
396 d.GetDialogItemAsControl(ARGV_OPTION_GROUP).DeactivateControl()
397 if commandlist:
398 _setmenu(d.GetDialogItemAsControl(ARGV_COMMAND_GROUP), commandlist)
399 if type(commandlist[0]) == type(()) and len(commandlist[0]) > 1:
400 help = commandlist[0][-1]
401 h = d.GetDialogItemAsControl(ARGV_COMMAND_EXPLAIN)
402 Dlg.SetDialogItemText(h, help)
403 else:
404 d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).DeactivateControl()
405 if not addoldfile:
406 d.GetDialogItemAsControl(ARGV_ADD_OLDFILE).DeactivateControl()
407 if not addnewfile:
408 d.GetDialogItemAsControl(ARGV_ADD_NEWFILE).DeactivateControl()
409 if not addfolder:
410 d.GetDialogItemAsControl(ARGV_ADD_FOLDER).DeactivateControl()
411 d.SetDialogDefaultItem(ARGV_ITEM_OK)
412 d.SetDialogCancelItem(ARGV_ITEM_CANCEL)
413 d.GetDialogWindow().ShowWindow()
414 d.DrawDialog()
415 appsw = MacOS.SchedParams(1, 0)
416 try:
417 while 1:
418 stringstoadd = []
419 n = ModalDialog(None)
420 if n == ARGV_ITEM_OK:
421 break
422 elif n == ARGV_ITEM_CANCEL:
423 raise SystemExit
424 elif n == ARGV_OPTION_GROUP:
425 idx = d.GetDialogItemAsControl(ARGV_OPTION_GROUP).GetControlValue()-1
426 _selectoption(d, optionlist, idx)
427 elif n == ARGV_OPTION_VALUE:
428 pass
429 elif n == ARGV_OPTION_ADD:
430 idx = d.GetDialogItemAsControl(ARGV_OPTION_GROUP).GetControlValue()-1
431 if 0 <= idx < len(optionlist):
432 option = optionlist[idx]
433 if type(option) == type(()):
434 option = option[0]
435 if option[-1] == '=' or option[-1] == ':':
436 option = option[:-1]
437 h = d.GetDialogItemAsControl(ARGV_OPTION_VALUE)
438 value = Dlg.GetDialogItemText(h)
439 else:
440 value = ''
441 if len(option) == 1:
442 stringtoadd = '-' + option
443 else:
444 stringtoadd = '--' + option
445 stringstoadd = [stringtoadd]
446 if value:
447 stringstoadd.append(value)
448 else:
449 MacOS.SysBeep()
450 elif n == ARGV_COMMAND_GROUP:
451 idx = d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).GetControlValue()-1
452 if 0 <= idx < len(commandlist) and type(commandlist[idx]) == type(()) and \
453 len(commandlist[idx]) > 1:
454 help = commandlist[idx][-1]
455 h = d.GetDialogItemAsControl(ARGV_COMMAND_EXPLAIN)
456 Dlg.SetDialogItemText(h, help)
457 elif n == ARGV_COMMAND_ADD:
458 idx = d.GetDialogItemAsControl(ARGV_COMMAND_GROUP).GetControlValue()-1
459 if 0 <= idx < len(commandlist):
460 command = commandlist[idx]
461 if type(command) == type(()):
462 command = command[0]
463 stringstoadd = [command]
464 else:
465 MacOS.SysBeep()
466 elif n == ARGV_ADD_OLDFILE:
467 fss, ok = macfs.StandardGetFile()
468 if ok:
469 stringstoadd = [fss.as_pathname()]
470 elif n == ARGV_ADD_NEWFILE:
471 fss, ok = macfs.StandardPutFile('')
472 if ok:
473 stringstoadd = [fss.as_pathname()]
474 elif n == ARGV_ADD_FOLDER:
475 fss, ok = macfs.GetDirectory()
476 if ok:
477 stringstoadd = [fss.as_pathname()]
478 elif n == ARGV_CMDLINE_DATA:
479 pass # Nothing to do
480 else:
481 raise RuntimeError, "Unknown dialog item %d"%n
483 for stringtoadd in stringstoadd:
484 if '"' in stringtoadd or "'" in stringtoadd or " " in stringtoadd:
485 stringtoadd = `stringtoadd`
486 h = d.GetDialogItemAsControl(ARGV_CMDLINE_DATA)
487 oldstr = GetDialogItemText(h)
488 if oldstr and oldstr[-1] != ' ':
489 oldstr = oldstr + ' '
490 oldstr = oldstr + stringtoadd
491 if oldstr[-1] != ' ':
492 oldstr = oldstr + ' '
493 SetDialogItemText(h, oldstr)
494 d.SelectDialogItemText(ARGV_CMDLINE_DATA, 0x7fff, 0x7fff)
495 h = d.GetDialogItemAsControl(ARGV_CMDLINE_DATA)
496 oldstr = GetDialogItemText(h)
497 tmplist = string.split(oldstr)
498 newlist = []
499 while tmplist:
500 item = tmplist[0]
501 del tmplist[0]
502 if item[0] == '"':
503 while item[-1] != '"':
504 if not tmplist:
505 raise RuntimeError, "Unterminated quoted argument"
506 item = item + ' ' + tmplist[0]
507 del tmplist[0]
508 item = item[1:-1]
509 if item[0] == "'":
510 while item[-1] != "'":
511 if not tmplist:
512 raise RuntimeError, "Unterminated quoted argument"
513 item = item + ' ' + tmplist[0]
514 del tmplist[0]
515 item = item[1:-1]
516 newlist.append(item)
517 return newlist
518 finally:
519 apply(MacOS.SchedParams, appsw)
520 del d
522 def test():
523 import time, sys
525 Message("Testing EasyDialogs.")
526 optionlist = (('v', 'Verbose'), ('verbose', 'Verbose as long option'),
527 ('flags=', 'Valued option'), ('f:', 'Short valued option'))
528 commandlist = (('start', 'Start something'), ('stop', 'Stop something'))
529 argv = GetArgv(optionlist=optionlist, commandlist=commandlist, addoldfile=0)
530 for i in range(len(argv)):
531 print 'arg[%d] = %s'%(i, `argv[i]`)
532 print 'Type return to continue - ',
533 sys.stdin.readline()
534 ok = AskYesNoCancel("Do you want to proceed?")
535 ok = AskYesNoCancel("Do you want to identify?", yes="Identify", no="No")
536 if ok > 0:
537 s = AskString("Enter your first name", "Joe")
538 s2 = AskPassword("Okay %s, tell us your nickname"%s, s, cancel="None")
539 if not s2:
540 Message("%s has no secret nickname"%s)
541 else:
542 Message("Hello everybody!!\nThe secret nickname of %s is %s!!!"%(s, s2))
543 text = ( "Working Hard...", "Hardly Working..." ,
544 "So far, so good!", "Keep on truckin'" )
545 bar = ProgressBar("Progress, progress...", 100)
546 try:
547 appsw = MacOS.SchedParams(1, 0)
548 for i in range(100):
549 bar.set(i)
550 time.sleep(0.1)
551 if i % 10 == 0:
552 bar.label(text[(i/10) % 4])
553 bar.label("Done.")
554 time.sleep(0.3) # give'em a chance to see the done.
555 finally:
556 del bar
557 apply(MacOS.SchedParams, appsw)
559 if __name__ == '__main__':
560 try:
561 test()
562 except KeyboardInterrupt:
563 Message("Operation Canceled.")