########################################
# The contents of this file are subject to the MLX PUBLIC LICENSE version
# 1.0 (the "License"); you may not use this file except in
# compliance with the License.
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
# the License for the specific language governing rights and limitations
# under the License.
# 
# The Original Source Code is "compClust", released 2003 September 03.
# 
# The Original Source Code was developed by the California Institute of
# Technology (Caltech).  Portions created by Caltech are Copyright (C)
# 2002-2003 California Institute of Technology. All Rights Reserved.
########################################

from Tkinter import *
import Pmw
import sys, string

from GUI_menubar import MenuBarViewer
#from MyMenuBar import *
#import ProgressBar
#from compClust.visualize.IPlot import DatasetPlot
#from compClust.visualize.IPlot import DatasetRowPlotView
#from compClust.mlx          import views
#from treeview_wrappers import TreeViewer
#from treeview import *

class AppShell(Pmw.MegaWidget):
  appversion = '1.0'
  appname    = 'Generic Application Frame'
  copyright  = 'copyright 2002 Caltech. All Rights Reserved'
  contactname= 'myname'
  contactphone='123-456-7890'
  contactemail='myname@yahoo.com'

  frameWidth = 1000
  frameHeight= 500
  padx       = 5
  pady       = 5
  usecommandarea = 0
  balloonhelp = 1

  busyCursor = 'watch'

  def __init__(self, **kw):
    optiondefs = (
      ('padx', 1,                 Pmw.INITOPT),
      ('pady', 1,                 Pmw.INITOPT),
      ('framewidth', 1,           Pmw.INITOPT),
      ('frameheight', 1,          Pmw.INITOPT),
      ('usecommandarea', self.usecommandarea, Pmw.INITOPT))
    self.defineoptions(kw, optiondefs)

    # intitialize Tk and Pmw and set the widnow's title and geometry
    self.root = Tk()
    self.initializeTk(self.root)
    Pmw.initialise(self.root)
    self.root.title(self.appname)
    self.root.geometry('%dx%d' % (self.frameWidth, self.frameHeight))

    # initialize constants required for adding plots to canvas (SDamle)
    numRows = 0
    numCols = 0
    self.plots = {}
    self.__focus = None
    self.__next = (0,0)
    self.__numRows = numRows
    self.__numCols = numCols

    # Initialize the base class
    Pmw.MegaWidget.__init__(self, parent=self.root)

    # Initialize the application (does nothing yet!)
    self.appInit()

    # Create the interface (does most initialization steps)
    self.__createInterface()

    # Create a table to hold the cursors for
    # widgets which get changed when we go busy
    self.preBusyCursors  = None

    # Pack the container and set focus
    # to ourselves
    self._hull.pack(side=TOP, fill=BOTH, expand=YES)
    self.focus_set()
    # Initialize our options
    self.initialiseoptions(AppShell)

  def appInit(self):
    # Called before interface is created (should be overridden).
    pass

  def __initializeTk_colors_common(self, root):
    root.option_add('*background', 'grey')
    root.option_add('*foreground', 'black')
    root.option_add('*EntryField.Entry.background', 'white')
    root.option_add('*MessageBar.Entry.background', 'gray85')
    root.option_add('*Listbox*background', 'white')
    root.option_add('*Listbox*selectedBackground', 'dark slate blue')
    root.option_add('*Listbox*selectForeground', 'white')

  def initializeTk(self, root):
    # Initialize platform-specific options (just for unix for now)
    self.__initializeTk_unix(root)

  def __initializeTk_unix(self, root):
    self.__initializeTk_colors_common(root)
      
  def busyStart(self, newcursor=None):
    if not newcursor:
      #newcursor = self.busyCursor LLLLLLLLLL
      newcursor = self.busyCursor()
    newPreBusyCursors = {}

    for component in self.busyWidgets:
      newPreBusyCursors[component] = component['cursor']
      component.configure(cursor=newcursor)
      component.update_idletasks()
    self.preBusyCursors = (newPreBusyCursors, self.preBusyCursors)

  def busyEnd(self):
    if not self.preBusyCursors:
      return
    oldPreBusyCursors = self.preBusyCursors[0]
    self.preBusyCursors = self.preBusyCursors[1]
    for component in self.busyWidgets:
      try:
        component.configure(cursor=oldPreBusyCursors[component])
      except KeyError:
        pass
      component.update_idletasks()

  def __createAboutBox(self):
    Pmw.aboutversion(self.appversion)
    Pmw.aboutcopyright(self.copyright)
    Pmw.aboutcontact(
      'For more information, contact:\n %s\n Phone: %s\n Email: %s' % \
      (self.contactname, self.contactphone,
       self.contactemail))
    self.about = Pmw.AboutDialog(self._hull,
                                 applicationname=self.appname)
    self.about.withdraw()
    return None

  def showAbout(self):
    # Create the dialog to display about and contact information.
    self.about.show()
    self.about.focus_set()

  def toggleBalloon(self):
    if self.toggleBalloonVar.get():
      self.__balloon.configure(state='both')
    else:
      self.__balloon.configure(state = 'status')

  def __createMenuBar(self):
    self.menuBar = MenuBarViewer(self._hull, self)
    
    self.menuBar.pack(fill=X)
    self.menuBar.addmenu('Help', 'About %s' % self.appname, side='right')
    self.menuBar.addmenu('File', 'File commands and Quit')

    self.menuBar.addmenuitem('Help', 'command',
                             'Get information on application',
                             label = 'About...', command=self.showAbout)
    self.toggleBalloonVar = IntVar()
    self.toggleBalloonVar.set(1)
    self.menuBar.addmenuitem('Help', 'checkbutton', 'Toggle balloon help',
                             label = 'Balloon help',
                             variable = self.toggleBalloonVar,
                             command = self.toggleBalloon)
    self.menuBar.addmenuitem('File', 'command', 'Quit this application',
                             label='Quit',
                             command = self.quit)



  def __createBalloon(self):
    # Create the balloon help manager from the frame
    # Create the manager for the balloon help
    self.__balloon = self.createcomponent('balloon', (), None,
                                        Pmw.Balloon, (self._hull,))

  def balloon(self):
    return self.__balloon

  def __createDataArea(self):
    """
    creates a data area where data entry widgets are placed
    """
    

    #
    # create a Paned Widget and panes
    #

    self.panes = Pmw.PanedWidget(self._hull, hull_relief='raised',
                                 orient='horizontal')

    # left panes
    self.panes.add('left',  size = 350)
    self.leftPanes = Pmw.PanedWidget(self.panes.pane('left'),
                                     orient='vertical')
    self.leftPanes.add('top', size = 150)
    self.leftPanes.add('bottom', size = 400)
    self.leftPanes.pack(expand=1, fill='both')
    self.panes.pack(expand=1, fill='both')

    # middle panes
    self.panes.add('middle', size = 400)

    # right panes
    self.panes.add('right', size = 350)
    
  def __createManager(self):
  #  #
  #  # once I get this working, I'll want to change this call to instantiate
  #  #  a viewer class object.  It should work to display information about a
  #  #  view and allow the user to change this info as needed
  #  #
  #  
  #  self.dataManager = self.createcomponent('dataManager',
  #                                          (), None,
  #                                          Frame, (self._hull,),
  #                                          relief = GROOVE,
  #                                          bd=1)
  #  self.dataManager.pack(side=TOP, fill=X, expand=YES,
  #                        padx=self['padx'], pady=self['pady'])
    pass

  def __createCommandArea(self):
    # Create a command area for application-wide buttons.
    self.__commandFrame = self.createcomponent('commandframe', (), None,
                                               Frame,
                                               (self._hull,),
                                               relief=SUNKEN,
                                               bd=1)
    self.__buttonBox = self.createcomponent('buttonbox', (), None,
                                            Pmw.ButtonBox,
                                            (self.__commandFrame,),
                                            padx=0, pady=0)
    self.__buttonBox.pack(side=TOP, expand=NO, fill=X)
    if self['usecommandarea']:
      self.__commandFrame.pack(side=TOP,
                              expand=1,
                              fill=X,
                              padx=self['padx'],
                              pady=self['pady'])

  def __createMessageBar(self):
    # Create the message bar area for help and status messages.
    frame = self.createcomponent('bottomtray', (), None,
                                 Frame, (self._hull,), relief=SUNKEN)
    self.__messageBar = self.createcomponent('messagebar',
                                             (), None,
                                             Pmw.MessageBar,
                                             (frame, ),
                                             #entry_width=40,
                                             entry_relief=SUNKEN,
                                             entry_bd=1,
                                             labelpos=None)
    self.__messageBar.pack(side=LEFT, expand=YES, fill=X)

    #self.__progressBar = ProgressBar.ProgressBar(frame,
    #                                             fillColor='slateblue',
    #                                             doLabel=1,
    #                                             width=150)
    #self.__progressBar.frame.pack(side=LEFT, expand=NO, fill=None)

    #self.updateProgress(0)
    frame.pack(side=TOP, expand=NO, fill=X)
    
    self.__balloon.configure(statuscommand= \
                             self.__messageBar.helpmessage)

  def messageBar(self):
    return self.__messageBar

  def updateProgress(self, newValue=0, newLimit=0):
    self.__progressBar.updateProgress(newValue, newLimit)

  def bind(self, child, balloonHelpMsg, statusHelpMsg=None):
    # Bind a help message and/or status message to a widget.
    self.__balloon.bind(child, balloonHelpMsg, statusHelpMsg)

  def interior(self):
    # Retrieve the interior site where widgets should go.
    return self.panes.pane('middle')

  def buttonBox(self):
    # Retrieve the button box.
    return self.__buttonBox

  def buttonAdd(self, buttonName, helpMessage=None,
                statusMessage=None, **kw):
    # Add a button to the button box.
    newBtn = self.__buttonBox.add(buttonName)
    newBtn.configure(kw)
    if helpMessage:
      self.bind(newBtn, helpMessage, statusMessage)
    return newBtn

  def __createInterface(self):
    self.__createBalloon()
    self.__createMenuBar()
    self.__createDataArea()
    self.__createManager()
    self.__createCommandArea()
    self.__createMessageBar()
    self.__createAboutBox()
    #
    # Create the parts of the interface
    # which can be modified by subclasses.
    #
    self.busyWidgets = ( self.root, )
    self.createMenuBar()
    self.createManager()
    self.createDataArea()
    self.createInterface()

  def createMenuBar(self):
    """
    will be overwritten by subclasses
    """
    pass

  def createManager(self):
    pass

  def createDataArea(self):
    # Override this method to create the interface for the app
    pass

  def createInterface(self):
    # Override this method to create the interface for the app
    pass

  def main(self):
    self.pack()
    self.mainloop()

  def run(self):
    self.main()

