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 = int(value)
125            return '%d      %3d' % (num * 3, num)
126        except ValueError:
127            num = float(value)
128            return '%g      %3g' % (num * 3, num)
129
130    def _setelementtype(self, type):
131        elements = self._graph.element_names()
132        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 = int(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    Pmw.Blt.setBltDisable(root, False)
237    root.title(title)
238
239    exitButton = tkinter.Button(root, text = 'Exit', command = root.destroy)
240    exitButton.pack(side = 'bottom')
241    widget = Demo(root)
242    root.mainloop()
243