#! /usr/bin/env python

import imp
import os
import regex
import string
import sys
import types
import Tkinter
import DemoVersion
import FontText

# Find where the other scripts are, so they can be listed.
#if __name__ == '__main__':
#    script_name = sys.argv[0]
#else:
#    script_name = imp.find_module('DemoVersion')[1]

#script_name = os.path.normpath(script_name)
#script_name = DemoVersion.expandLinks(script_name)
#script_dir = os.path.dirname(script_name)
#script_dir = DemoVersion.expandLinks(script_dir)
script_dir = '/usr/doc/python-pmw/examples'
 
# Add the '../../..' directory to the path.
#package_dir = os.path.dirname(script_dir)
#package_dir = DemoVersion.expandLinks(package_dir)
#package_dir = os.path.dirname(package_dir)
#package_dir = DemoVersion.expandLinks(package_dir)
#package_dir = os.path.dirname(package_dir)
#package_dir = DemoVersion.expandLinks(package_dir)
#sys.path[:0] = [package_dir]

# Import Pmw after modifying sys.path (it may not be in the default path).
import Pmw
DemoVersion.setPmwVersion()

class Demo(Pmw.MegaWidget):

    def __init__(self, parent=None, **kw):

	# Define the megawidget options.
	optiondefs = ()
	self.defineoptions(kw, optiondefs)

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

	# Create the contents.
	top = self.interior()

	panes = Pmw.PanedWidget(top, orient = 'horizontal')
	panes.pack(fill = 'both', expand = 1)

	panes.add('widgetlist')
	self._widgetlist = Pmw.ScrolledListBox(panes.pane('widgetlist'),
		selectioncommand = Pmw.busycallback(self.startDemo),
		label_text = 'Select a widget:',
		labelpos = 'nw',
		vscrollmode = 'dynamic',
		hscrollmode = 'none',
		listbox_exportselection = 0)
	self._widgetlist.pack(fill = 'both', expand = 1, padx = 8)

	panes.add('info')
	self._status = Tkinter.Label(panes.pane('info'))
	self._status.pack(padx = 8, anchor = 'w')

	self._example = Tkinter.Frame(panes.pane('info'),
		borderwidth = 2,
		relief = 'sunken',
	        background = 'white')
	self._example.pack(fill = 'both', expand = 1, padx = 8)

	self.buttonBox = Pmw.ButtonBox(top)
	self.buttonBox.pack(fill = 'x')

	# Add the buttons and make them all the same width.
	self._traceText = 'Trace tk calls'
	self._stopTraceText = 'Stop trace'
	self.buttonBox.add('Trace', text = self._traceText,
	        command = self.trace)
	self.buttonBox.add('Code', text = 'Show code', command = self.showCode)
	self.buttonBox.add('Exit', text = 'Exit', command = sys.exit)
	self.buttonBox.alignbuttons()

	# Create the window to display the python code.
	self.codeWindow = Pmw.TextDialog(parent,
	    title = 'Python source',
	    buttons = ('Dismiss',),
	    text_pyclass = FontText.Text,
	    scrolledtext_labelpos = 'n',
	    label_text = 'Source')
	self.codeWindow.withdraw()
	self.codeWindow.insert('end', '')

	self.demoName = None
	self._loadDemos()

	# Check keywords and initialise options.
	self.initialiseoptions(Demo)

    def startDemo(self):
	# Import the selected module and create and instance of the module's
	# Demo class.

	sels = self._widgetlist.getcurselection()
	if len(sels) == 0:
	    print 'No demonstrations to display'
	    return
	demoName = sels[0]

	# Ignore if this if it is a sub title.
	if demoName[0] != ' ':
	    self._widgetlist.bell()
	    return

	# Strip the leading two spaces.
	demoName = demoName[2:]

	# Ignore if this demo is already being shown.
	if self.demoName == demoName:
	    return

	self.demoName = demoName

	self.showStatus('Loading ' + demoName)
	# Busy cursor
	self.update_idletasks()

	for window in self._example.winfo_children():
	    window.destroy()

	frame = Tkinter.Frame(self._example)
	frame.pack(expand = 1)
	try:
	    exec 'import ' + demoName
	    widget = eval(demoName + '.Demo(frame)')
	except:
	    for window in frame.winfo_children():
		window.destroy()
	    exc_type = sys.exc_type
	    if type(exc_type) == types.ClassType:
		# Handle python 1.5 class exceptions.
		exc_type = exc_type.__name__
	    text = 'Error loading ' + demoName + ': ' + \
	            exc_type + '\n' + str(sys.exc_value)
	    err = Tkinter.Label(frame, background = 'white',
	            wraplength = '4i', text = text)
	    err.pack(expand = 1)
	self.showStatus('')

	if self.codeWindow.state() == 'normal':
	    self.insertCode()

    def showStatus(self, text):
	self._status.configure(text = text)

    def showCode(self):
	if self.codeWindow.state() != 'normal':
	    if self.demoName is None:
		print 'No demonstration selected'
		return
	    self.insertCode()

	self.codeWindow.show()

    def insertCode(self):
	self.codeWindow.clear()
	fileName = os.path.join(script_dir, self.demoName + '.py')
	self.codeWindow.importfile(fileName)
	self.codeWindow.configure(label_text = self.demoName + ' source')

    def trace(self):
	text = self.buttonBox.component('Trace').cget('text')
	if text == self._traceText:
	    self.buttonBox.configure(Trace_text = self._stopTraceText)
	    Pmw.tracetk(root, 1)
	    self.showStatus('Trace will appear on standard output')
	else:
	    self.buttonBox.configure(Trace_text = self._traceText)
	    Pmw.tracetk(root, 0)
	    self.showStatus('Tk call tracing stopped')

    def _loadDemos(self):
	files = os.listdir(script_dir)
	files.sort()
	megawidgets = []
	others = []
	for file in files:
	    if regex.search('.py$', file) >= 0 and \
		    file not in ['All.py', 'FontText.py', 'DemoVersion.py']:
		demoName = file[:-3]
		index = string.find(demoName, '_')
		if index < 0:
		    testattr = demoName
		else:
		    testattr = demoName[:index]
		if hasattr(Pmw, testattr):
		    megawidgets.append(demoName)
		else:
		    others.append(demoName)

	self._widgetlist.insert('end', 'Megawidget demos:')
	for name in megawidgets:
	    self._widgetlist.insert('end', '  ' + name)
	self._widgetlist.insert('end', 'Other demos:')
	for name in others:
	    self._widgetlist.insert('end', '  ' + name)
	self._widgetlist.select_set(1)

class StdOut:
    def __init__(self, displayCommand):
        self.displayCommand = displayCommand
	self.text = '\n'

    def write(self, text):
	if self.text[-1] == '\n':
	    self.text = text
	else:
	    self.text = self.text + text
	if self.text[-1] == '\n':
	    text = self.text[:-1]
	else:
	    text = self.text
	self.displayCommand(text)

root = Tkinter.Tk(className = 'Demo')
Pmw.initialise(root, fontScheme = 'pmw1', useTkOptionDb = 1)

Pmw.version()
root.title('Pmw ' + Pmw.version() + ' megawidget demonstration')
root.geometry('700x500')

demo = Demo(root)
demo.pack(fill = 'both', expand = 1)

# Redirect standard output from demos to status line.
sys.stdout = StdOut(demo.showStatus)

# Start the first demo.
demo.startDemo()

root.mainloop()
