import os, sys
import Tkinter, Pmw
balloons_on = 'balloon'  # alternates are status, both
balloons_off = 'none'
_dialogs=[]
balloon=None
# Manage just one balloon flag for all dialogs
def balloon_state():
    "Return the state of the global balloon setting."
    if  _balloon_var.get():
        return balloons_on
    else:
        return balloons_off

def toggle_balloon_state ():
    "Set the balloon help flag."
    balloon.configure(state=balloon_state())


# One common root for all dialogs
_root = None
def root ():
    "Return the root"
    global _root, _balloon_var, balloon
    if _root is None:
        _root = Pmw.initialise()
        _root.withdraw()
        balloon = Pmw.Balloon(_root)
        _balloon_var = Tkinter.IntVar(_root)
        iebf = 1
        _balloon_var.set(iebf)
        if iebf:
            balloon.configure(state=balloons_on)
        else:
            balloon.configure(state=balloons_off)
        _root.balloon = balloon
    return _root

def root_exists():
    "Does the root window exist yet?"
    return _root is not None

def set_root (root):
    "Set the root externally."
    global _root
    if root_exists():
        raise RuntimeError, 'set_root called illegally.'
    _root = root

class MyDialog: # should inherit, had some trouble packing though -- pfd
    def __init__ (self, **kw):
        self.am_root = not root_exists()
        kw['parent'] = root()
        if not kw.has_key('command'):
            kw['command'] = self.execute
        self.dialog = Pmw.Dialog(**kw)
        self.title = self.dialog.title
        self.interior = self.dialog.interior
        self.geometry = self.dialog.geometry
        self.component = self.dialog.component
        self.config = self.dialog.config
        self.option_add = self.dialog.option_add
        self.balloon=balloon
        self.transient= self.dialog.transient
        self.withdraw = self.dialog.withdraw
        self.deiconify = self.dialog.deiconify
        self.activate = self.dialog.activate
        self.deactivate = self.dialog.deactivate
        _dialogs.append(self)

    def position_popup (self, popup, transient=1):
        "Position a dialog over this one."
        if transient: 
            popup.transient(self.interior())
        g = self.geometry()
        d = g.split('+')[1:]
        popup.geometry("+%s+%s" % (d[0],d[1]))

    def position_over (self, gui_parent):
        "Position this dialog over the gui_parent"
        g = gui_parent.geometry()
        d = g.split('+')[1:]
        self.geometry("+%s+%s" % (d[0],d[1]))

    def execute (self, name):
        if name is None:
            self.destroy()
            return

    def destroy (self):
        global _root
        for i in range(len(_dialogs)):
            if _dialogs[i] is self:
                del _dialogs[i]
                break
        self.dialog.destroy()
        if self.am_root:
            _root.destroy()
            _root = None

def add_balloon_help (menu, menu_title):
    "Add a balloon help toggle to menu."
    menu.addmenuitem(menu_title, 'checkbutton', 
                        'Toggle balloon help on/off',
                        label = 'Show Balloons',
                        variable = _balloon_var,
                        command = toggle_balloon_state
                       )


syntax highlighted by Code2HTML, v. 0.9.1