1title = 'Blt Graph demonstration'
2
3# Import Pmw from this directory tree.
4import sys
5sys.path[:0] = ['../../..']
6
7import string
8import Tkinter
9import Pmw
10
11# Simple random number generator.
12rand = 12345
13def random():
14    global rand
15    rand = (rand * 125) % 2796203
16    return rand
17
18class GraphDemo(Pmw.MegaToplevel):
19
20    def __init__(self, parent=None, **kw):
21
22	# Define the megawidget options.
23	optiondefs = (
24	    ('size',      10,   Pmw.INITOPT),
25	)
26	self.defineoptions(kw, optiondefs)
27
28	# Initialise the base class (after defining the options).
29	Pmw.MegaToplevel.__init__(self, parent)
30
31	# Create the graph.
32	self.createWidgets()
33
34	# Check keywords and initialise options.
35	self.initialiseoptions()
36
37    def createWidgets(self):
38	# Create vectors for use as x and y data points.
39	self._numElements = 7
40	self._vectorSize = self['size']
41	self._vector_x = Pmw.Blt.Vector()
42	self._vector_y = []
43	for y in range(self._numElements):
44	    self._vector_y.append(Pmw.Blt.Vector())
45	for index in range(self._vectorSize):
46	    self._vector_x.append(index)
47	    for y in range(self._numElements):
48		self._vector_y[y].append(random() % 100)
49
50	interior = self.interior()
51
52        controlFrame = Tkinter.Frame(interior)
53	controlFrame.pack(side = 'bottom', fill = 'x', expand = 0)
54
55        # Create an option menu for the kind of elements to create.
56	elementtype = Pmw.OptionMenu(controlFrame,
57		labelpos = 'nw',
58		label_text = 'Element type',
59		items = ['bars', 'lines', 'mixed', 'none'],
60		command = self._setelementtype,
61		menubutton_width = 8,
62	)
63	elementtype.pack(side = 'left')
64
65        # Create an option menu for the barmode option.
66	barmode = Pmw.OptionMenu(controlFrame,
67		labelpos = 'nw',
68		label_text = 'Bar mode',
69		items = ['normal', 'stacked', 'aligned', 'overlap'],
70		command = self._setbarmode,
71		menubutton_width = 8,
72	)
73	barmode.pack(side = 'left')
74
75        # Create an option menu for the smooth option.
76	self.smooth = Pmw.OptionMenu(controlFrame,
77		labelpos = 'nw',
78		label_text = 'Smooth',
79		items = ['linear', 'step', 'natural', 'quadratic'],
80		command = self._setsmooth,
81		menubutton_width = 9,
82	)
83	self.smooth.pack(side = 'left')
84
85        # Create an option menu to reverse sort the elements.
86	sortelements = Pmw.OptionMenu(controlFrame,
87		labelpos = 'nw',
88		label_text = 'Order',
89		items = ['normal', 'reverse'],
90		command = self._setsortelements,
91		menubutton_width = 8,
92	)
93	sortelements.pack(side = 'left')
94
95        # Create an option menu for the bufferelements option.
96	bufferelements = Pmw.OptionMenu(controlFrame,
97		labelpos = 'nw',
98		label_text = 'Buffering',
99		items = ['buffered', 'unbuffered'],
100		command = self._setbufferelements,
101		menubutton_width = 10,
102	)
103	bufferelements.pack(side = 'left')
104
105	# Create a button to add a point to the vector.
106	addpoint = Tkinter.Button(controlFrame, text = 'Add point',
107		command = Pmw.busycallback(self._addpoint))
108	addpoint.pack(side = 'left', fill = 'x', expand = 0)
109
110	# Create a button to close the window
111	close = Tkinter.Button(controlFrame, text = 'Close',
112		command = Pmw.busycallback(self.destroy))
113	close.pack(side = 'left', fill = 'x', expand = 0)
114
115	# Create the graph and its elements.
116	self._graph = Pmw.Blt.Graph(interior)
117	self._graph.pack(expand = 1, fill = 'both')
118	self._graph.yaxis_configure(command=self.yaxisCommand)
119	elementtype.invoke('mixed')
120	bufferelements.invoke('buffered')
121
122    def yaxisCommand(self, graph, value):
123        try:
124            num = string.atoi(value)
125            return '%d      %3d' % (num * 3, num)
126        except ValueError:
127            num = string.atof(value)
128            return '%g      %3g' % (num * 3, num)
129
130    def _setelementtype(self, type):
131        elements = self._graph.element_names()
132	apply(self._graph.element_delete, elements)
133
134        if type == 'none':
135            return
136
137	colorList = Pmw.Color.spectrum(self._numElements)
138	for elem in range(self._numElements):
139	    if elem == 0:
140	        hue = None
141	    else:
142	        hue = (elem + 1.0) / self._numElements * 6.28318
143	    foreground = colorList[elem]
144	    background = Pmw.Color.changebrightness(self, foreground, 0.8)
145	    if type == 'mixed':
146	        if elem < self._numElements / 2:
147		    bar = 0
148		else:
149		    bar = 1
150	    elif type == 'bars':
151	        bar = 1
152	    else:
153	        bar = 0
154	    if bar:
155		self._graph.bar_create(
156		    'var' + str(elem),
157		    xdata=self._vector_x,
158		    ydata=self._vector_y[elem],
159		    foreground = foreground,
160		    background = background)
161	    else:
162		self._graph.line_create(
163		    'var' + str(elem),
164		    linewidth = 4,
165		    xdata=self._vector_x,
166		    ydata=self._vector_y[elem],
167                    smooth = self.smooth.getcurselection(),
168		    color = foreground)
169
170    def _setbarmode(self, tag):
171        self._graph.configure(barmode = tag)
172
173    def _setsmooth(self, tag):
174	for element in self._graph.element_show():
175            if self._graph.element_type(element) == 'line':
176                self._graph.element_configure(element, smooth = tag)
177
178    def _setbufferelements(self, tag):
179        self._graph.configure(bufferelements = (tag == 'buffered'))
180
181    def _setsortelements(self, tag):
182	element_list = list(self._graph.element_show())
183        if len(element_list) > 1:
184            if (tag == 'normal') == (element_list[-1] != 'var0'):
185                element_list.reverse()
186                self._graph.element_show(element_list)
187
188    def _addpoint(self):
189	self._vector_x.append(self._vectorSize)
190	for y in range(self._numElements):
191	    self._vector_y[y].append(random() % 100)
192	self._vectorSize = self._vectorSize + 1
193
194class Demo:
195    def __init__(self, parent):
196	if not Pmw.Blt.haveblt(parent):
197	    message = 'Sorry\nThe BLT package has not been\n' + \
198		    'installed on this system.\n' + \
199		    'Please install it and try again.'
200	    w = Tkinter.Label(parent, text = message)
201	    w.pack(padx = 8, pady = 8)
202	    return
203
204	message = 'This is a simple demonstration of the\n' + \
205		'BLT graph widget.\n' + \
206		'Select the number of points to display and\n' + \
207		'click on the button to display the graph.'
208	w = Tkinter.Label(parent, text = message)
209	w.pack(padx = 8, pady = 8)
210
211	# Create combobox to select number of points to display.
212	self.combo = Pmw.ComboBox(parent,
213		scrolledlist_items = ('10', '25', '50', '100', '300'),
214		entryfield_value = '10')
215	self.combo.pack(padx = 8, pady = 8)
216
217	# Create button to start blt graph.
218	start = Tkinter.Button(parent,
219		text = 'Show BLT graph',
220	        command = Pmw.busycallback(self.showGraphDemo))
221	start.pack(padx = 8, pady = 8)
222
223	self.parent = parent
224
225    def showGraphDemo(self):
226	size = string.atoi(self.combo.get())
227	demo = GraphDemo(self.parent, size = size)
228        demo.focus()
229
230######################################################################
231
232# Create demo in root window for testing.
233if __name__ == '__main__':
234    root = Tkinter.Tk()
235    Pmw.initialise(root)
236    root.title(title)
237
238    exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy)
239    exitButton.pack(side = 'bottom')
240    widget = Demo(root)
241    root.mainloop()
242