""" Demonstration of the Blt Graph widget.
"""

# Import Pmw from the sibling directory.
import sys
sys.path[:0] = ['../../..']

import string
import Tkinter
import Pmw

# Simple random number generator.
rand = 12345
def random():
    global rand
    rand = (rand * 125) % 2796203
    return rand

class GraphDemo(Pmw.MegaToplevel):

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

	# Define the megawidget options.
	optiondefs = (
	    ('size',      10,   Pmw.INITOPT),
	)
	self.defineoptions(kw, optiondefs)

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

	# Create the graph.
	self.createWidgets()

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

    def createWidgets(self):
	# Create vectors for use as x and y data points.
	self._numElements = 7
	self._vectorSize = self['size']
	self._vector_x = Pmw.Blt.Vector()
	self._vector_y = []
	for y in range(self._numElements):
	    self._vector_y.append(Pmw.Blt.Vector())
	for index in range(self._vectorSize):
	    self._vector_x.append(index)
	    for y in range(self._numElements):
		self._vector_y[y].append(random() % 100)

	interior = self.interior()
	# Create a button box and add some buttons
	self._buttons = Pmw.ButtonBox(interior)
	buttonInfo = (
	    ('Stacked', self._stacked),
	    ('Normal', self._normal),
	    ('Reverse', self._reverse),
	    ('Bar', self._bar),
	    ('Line', self._line),
	    ('Bars and lines', self._barsandlines),
	    ('Add point', self._addpoint),
	    ('Clear', self._clear),
	    ('Buffer', self._buffer),
	    ('Close', self.destroy),
	)
	for text, callback in buttonInfo:
	    self._buttons.add(text,
		command = Pmw.busycallback(callback))
	self._buttons.pack(side = 'bottom', fill = 'x', expand = 0)

	# Create the graph and its elements.
	self._graph = Pmw.Blt.Graph(interior)
	self._graph.pack(expand = 1, fill = 'both')
	self._graph.yaxis_configure(command=self.yaxisCommand)
	self._createElements('bar')

    def yaxisCommand(self, graph, value):
	num = string.atoi(value)
	return '%d      %3d' % (num * 3, num)

    def _createElements(self, type):
	self._clear()

	colorList = Pmw.Color.spectrum(self._numElements)
	for elem in range(self._numElements):
	    if elem == 0:
	        hue = None
	    else:
	        hue = (elem + 1.0) / self._numElements * 6.28318
	    foreground = colorList[elem]
	    background = Pmw.Color.changebrightness(self, foreground, 0.8)
	    if type == 'barsandlines':
	        if elem < self._numElements / 2:
		    bar = 1
		else:
		    bar = 0
	    elif type == 'bar':
	        bar = 1
	    else:
	        bar = 0
	    if bar:
		self._graph.element_bar(
		    'var' + str(elem),
		    xdata=self._vector_x,
		    ydata=self._vector_y[elem],
		    foreground = foreground,
		    background = background)
	    else:
		self._graph.element_line(
		    'var' + str(elem),
		    linewidth = 4,
		    xdata=self._vector_x,
		    ydata=self._vector_y[elem],
		    color = foreground)

    def _stacked(self):
        self._graph.configure(barmode = 'stacked')

    def _normal(self):
        self._graph.configure(barmode = 'normal')

    def _reverse(self):
	element_list = list(self._graph.element_show())
	element_list.reverse()
	self._graph.element_show(element_list)

    def _bar(self):
        self._createElements('bar')

    def _line(self):
        self._createElements('line')

    def _barsandlines(self):
        self._createElements('barsandlines')

    def _addpoint(self):
	self._vector_x.append(self._vectorSize)
	for y in range(self._numElements):
	    self._vector_y[y].append(random() % 100)
	self._vectorSize = self._vectorSize + 1

    def _clear(self):
	self._graph.element_delete('*')

    def _buffer(self):
	buffered = string.atoi(self._graph.cget('bufferelements'))
        self._graph.configure(bufferelements = not buffered)

class Demo:
    def __init__(self, parent):
	if not Pmw.Blt.haveblt(parent):
	    message = 'Sorry\nThe BLT package has not been\n' + \
		    'installed on this system.\n' + \
		    'Please install it and try again.'
	    w = Tkinter.Label(parent, text = message)
	    w.pack(padx = 8, pady = 8)
	    return

	message = 'This is a simple demonstration of the\n' + \
		'BLT graph widget.\n' + \
		'Select the number of points to display and\n' + \
		'click on the button to display the graph.'
	w = Tkinter.Label(parent, text = message)
	w.pack(padx = 8, pady = 8)

	# Create combobox to select number of points to display.
	self.combo = Pmw.ComboBox(parent,
		scrolledlist_items = ('10', '25', '50', '100', '300'),
		entryfield_value = '10')
	self.combo.pack(padx = 8, pady = 8)

	# Create button to start blt graph.
	start = Tkinter.Button(parent,
		text = 'Show BLT graph',
	        command = Pmw.busycallback(self.showGraphDemo))
	start.pack(padx = 8, pady = 8)

	self.parent = parent

    def showGraphDemo(self):
	size = string.atoi(self.combo.get())
	GraphDemo(self.parent, size = size)

######################################################################

# Create demo in root window for testing.
if __name__ == '__main__':
    root = Tkinter.Tk()
    Pmw.initialise(root, fontScheme = 'pmw1')
    root.title('Blt graph demonstration')

    exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy)
    exitButton.pack(side = 'bottom')
    widget = Demo(root)
    root.mainloop()
