1 from Tkinter import * 2 3 class WindowList: 4 5 def __init__(self): 6 self.dict = {} 7 self.callbacks = [] 8 9 def add(self, window): 10 window.after_idle(self.call_callbacks) 11 self.dict[str(window)] = window 12 13 def delete(self, window): 14 try: 15 del self.dict[str(window)] 16 except KeyError: 17 # Sometimes, destroy() is called twice 18 pass 19 self.call_callbacks() 20 21 def add_windows_to_menu(self, menu): 22 list = [] 23 for key in self.dict.keys(): 24 window = self.dict[key] 25 try: 26 title = window.get_title() 27 except TclError: 28 continue 29 list.append((title, window)) 30 list.sort() 31 for title, window in list: 32 menu.add_command(label=title, command=window.wakeup) 33 34 def register_callback(self, callback): 35 self.callbacks.append(callback) 36 37 def unregister_callback(self, callback): 38 try: 39 self.callbacks.remove(callback) 40 except ValueError: 41 pass 42 43 def call_callbacks(self): 44 for callback in self.callbacks: 45 try: 46 callback() 47 except: 48 print "warning: callback failed in WindowList", \ 49 sys.exc_type, ":", sys.exc_value 50 51 registry = WindowList() 52 53 add_windows_to_menu = registry.add_windows_to_menu 54 register_callback = registry.register_callback 55 unregister_callback = registry.unregister_callback 56 57 58 class ListedToplevel(Toplevel): 59 60 def __init__(self, master, **kw): 61 Toplevel.__init__(self, master, kw) 62 registry.add(self) 63 self.focused_widget = self 64 65 def destroy(self): 66 registry.delete(self) 67 Toplevel.destroy(self) 68 # If this is Idle's last window then quit the mainloop 69 # (Needed for clean exit on Windows 98) 70 if not registry.dict: 71 self.quit() 72 73 def update_windowlist_registry(self, window): 74 registry.call_callbacks() 75 76 def get_title(self): 77 # Subclass can override 78 return self.wm_title() 79 80 def wakeup(self): 81 try: 82 if self.wm_state() == "iconic": 83 self.wm_withdraw() 84 self.wm_deiconify() 85 self.tkraise() 86 self.focused_widget.focus_set() 87 except TclError: 88 # This can happen when the window menu was torn off. 89 # Simply ignore it. 90 pass 91