16634bf2919d855ccd821e878b8cc00c7209f1cbeGeorg Brandlfrom Tkinter import *
27aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
37aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass WindowList:
47aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
57aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self):
67aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.dict = {}
77aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.callbacks = []
87aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
97aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def add(self, window):
107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        window.after_idle(self.call_callbacks)
117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.dict[str(window)] = window
127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def delete(self, window):
147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            del self.dict[str(window)]
167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except KeyError:
177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # Sometimes, destroy() is called twice
187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.call_callbacks()
207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def add_windows_to_menu(self,  menu):
227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        list = []
237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        for key in self.dict.keys():
247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            window = self.dict[key]
257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                title = window.get_title()
277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except TclError:
287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                continue
297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            list.append((title, window))
307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        list.sort()
317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        for title, window in list:
327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            menu.add_command(label=title, command=window.wakeup)
337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def register_callback(self, callback):
357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.callbacks.append(callback)
367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def unregister_callback(self, callback):
387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
39817a76cfbb3b636d6f084ea859ce61f1cdaece83Steven M. Gava            self.callbacks.remove(callback)
407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except ValueError:
417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def call_callbacks(self):
447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        for callback in self.callbacks:
457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                callback()
477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except:
487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                print "warning: callback failed in WindowList", \
497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                      sys.exc_type, ":", sys.exc_value
507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererregistry = WindowList()
527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schereradd_windows_to_menu = registry.add_windows_to_menu
547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererregister_callback = registry.register_callback
557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererunregister_callback = registry.unregister_callback
567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ListedToplevel(Toplevel):
597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, master, **kw):
617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        Toplevel.__init__(self, master, kw)
627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        registry.add(self)
63183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser        self.focused_widget = self
647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def destroy(self):
667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        registry.delete(self)
677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        Toplevel.destroy(self)
68beb6bd96593401fdb71464baaec255f7c12ce365Kurt B. Kaiser        # If this is Idle's last window then quit the mainloop
69beb6bd96593401fdb71464baaec255f7c12ce365Kurt B. Kaiser        # (Needed for clean exit on Windows 98)
70beb6bd96593401fdb71464baaec255f7c12ce365Kurt B. Kaiser        if not registry.dict:
71beb6bd96593401fdb71464baaec255f7c12ce365Kurt B. Kaiser            self.quit()
727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
73260cb9034c861fa159f26fba8679ac265af47109Kurt B. Kaiser    def update_windowlist_registry(self, window):
74260cb9034c861fa159f26fba8679ac265af47109Kurt B. Kaiser        registry.call_callbacks()
75260cb9034c861fa159f26fba8679ac265af47109Kurt B. Kaiser
767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def get_title(self):
777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Subclass can override
787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.wm_title()
797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def wakeup(self):
817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.wm_state() == "iconic":
83183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser                self.wm_withdraw()
847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.wm_deiconify()
85183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser            self.tkraise()
86183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser            self.focused_widget.focus_set()
877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # This can happen when the window menu was torn off.
897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # Simply ignore it.
907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
91