1from Tkinter import *
2
3class 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
51registry = WindowList()
52
53add_windows_to_menu = registry.add_windows_to_menu
54register_callback = registry.register_callback
55unregister_callback = registry.unregister_callback
56
57
58class 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