# Based on iwidgets2.2.0/dialog.itk and iwidgets2.2.0/dialogshell.itk code.

# Convention:
#   Each dialog window should have one of these as the rightmost button:
#     Close         Close a window which only displays information.
#     Cancel        Close a window which may be used to change the state of
#                   the application.

import sys
import Tkinter
import Pmw

# A Toplevel with a ButtonBox and child site.

class Dialog(Pmw.MegaToplevel):
    def __init__(self, parent = None, **kw):

	# Define the megawidget options.
	INITOPT = Pmw.INITOPT
	optiondefs = (
	    ('buttonbox_hull_borderwidth',   1,         None),
	    ('buttonbox_hull_relief',        'raised',  None),
	    ('buttonboxpos',                 's',       INITOPT),
	    ('buttons',                      ('OK',),   self._buttons),
	    ('command',                      None,      None),
	    ('dialogchildsite_borderwidth',  1,         None),
	    ('dialogchildsite_relief',       'raised',  None),
	    ('defaultbutton',                None,      self._defaultButton),
	    ('separatorwidth',               0,         INITOPT),
	)
	self.defineoptions(kw, optiondefs)

	# Initialise the base class (after defining the options).
	Pmw.MegaToplevel.__init__(self, parent)

	# Create the components.

	oldInterior = Pmw.MegaToplevel.interior(self)

	# Set up pack options according to the position of the button box.
        pos = self['buttonboxpos']
	if pos not in 'nsew':
	    raise ValueError, \
	        'bad buttonboxpos option "%s":  should be n, s, e, or w' \
		    % pos

	if pos in 'ns':
	    orient = 'horizontal'
	    fill = 'x'
	    if pos == 'n':
	        side = 'top'
	    else:
	        side = 'bottom'
	else:
	    orient = 'vertical'
	    fill = 'y'
	    if pos == 'w':
	        side = 'left'
	    else:
	        side = 'right'

	# Create the button box.
	self._buttonBox = self.createcomponent('buttonbox',
		(), None,
		Pmw.ButtonBox, (oldInterior,), orient = orient)
	self._buttonBox.pack(side = side, fill = fill)

	# Create the separating line.
	width = self['separatorwidth']
	if width > 0:
	    self._separator = self.createcomponent('separator',
		    (), None,
		    Tkinter.Frame, (oldInterior,), relief = 'sunken',
		    height = width, width = width, borderwidth = width / 2)
	    self._separator.pack(side = side, fill = fill)
	
	# Create the child site.
	self.__dialogChildSite = self.createcomponent('dialogchildsite',
		(), None,
		Tkinter.Frame, (oldInterior,))
	self.__dialogChildSite.pack(side=side, fill='both', expand=1)

	self.oldButtons = ()
	self.oldDefault = None

	self.bind('<Return>', self._invokeDefault)
        self.userdeletefunc(self._doCommand)
        self.usermodaldeletefunc(self._doCommand)
	
	# Check keywords and initialise options.
	self.initialiseoptions(Dialog)

    def interior(self):
	return self.__dialogChildSite

    def invoke(self, index = 'default'):
	return self._buttonBox.invoke(index)

    def _invokeDefault(self, event):
	try:
	    self._buttonBox.index('default')
	except ValueError:
	    sys.exc_traceback = None   # Clean up object references
	    return
	self._buttonBox.invoke()

    def _doCommand(self, name = None):
	command = self['command']
	if callable(command):
	    return command(name)
	else:
	    if self.active():
	        self.deactivate(name)
	    else:
	        self.withdraw()

    def _buttons(self):
	buttons = self['buttons']
	if type(buttons) != type(()) and type(buttons) != type([]):
	    raise ValueError, \
	        'bad buttons option "%s": should be a tuple' % str(buttons)
	if self.oldButtons == buttons:
	  return

	self.oldButtons = buttons

	for index in range(self._buttonBox.numbuttons()):
	    self._buttonBox.delete(0)
	for name in buttons:
	    self._buttonBox.add(name,
		command=lambda self=self, name=name: self._doCommand(name))

	if len(buttons) > 0:
	    defaultbutton = self['defaultbutton']
	    if defaultbutton is None:
		self._buttonBox.setdefault(None)
	    else:
		try:
		    self._buttonBox.index(defaultbutton)
		except ValueError:
		    sys.exc_traceback = None   # Clean up object references
		else:
		    self._buttonBox.setdefault(defaultbutton)
	self._buttonBox.alignbuttons()

    def _defaultButton(self):
	defaultbutton = self['defaultbutton']
	if self.oldDefault == defaultbutton:
	  return

	self.oldDefault = defaultbutton

	if len(self['buttons']) > 0:
	    if defaultbutton is None:
		self._buttonBox.setdefault(None)
	    else:
		try:
		    self._buttonBox.index(defaultbutton)
		except ValueError:
		    sys.exc_traceback = None   # Clean up object references
		else:
		    self._buttonBox.setdefault(defaultbutton)