1# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
2#
3# $Id$
4#
5# tixwidgets.py --
6#
7#       For Tix, see http://tix.sourceforge.net
8#
9#       This is a demo program of some of the Tix widgets available in Python.
10#       If you have installed Python & Tix properly, you can execute this as
11#
12#               % python tixwidgets.py
13#
14
15import os, os.path, sys, Tix
16from Tkconstants import *
17import traceback, tkMessageBox
18
19TCL_DONT_WAIT           = 1<<1
20TCL_WINDOW_EVENTS       = 1<<2
21TCL_FILE_EVENTS         = 1<<3
22TCL_TIMER_EVENTS        = 1<<4
23TCL_IDLE_EVENTS         = 1<<5
24TCL_ALL_EVENTS          = 0
25
26class Demo:
27    def __init__(self, top):
28        self.root = top
29        self.exit = -1
30
31        self.dir = None                         # script directory
32        self.balloon = None                     # balloon widget
33        self.useBalloons = Tix.StringVar()
34        self.useBalloons.set('0')
35        self.statusbar = None                   # status bar widget
36        self.welmsg = None                      # Msg widget
37        self.welfont = ''                       # font name
38        self.welsize = ''                       # font size
39
40        progname = sys.argv[0]
41        dirname = os.path.dirname(progname)
42        if dirname and dirname != os.curdir:
43            self.dir = dirname
44            index = -1
45            for i in range(len(sys.path)):
46                p = sys.path[i]
47                if p in ("", os.curdir):
48                    index = i
49            if index >= 0:
50                sys.path[index] = dirname
51            else:
52                sys.path.insert(0, dirname)
53        else:
54            self.dir = os.getcwd()
55        sys.path.insert(0, self.dir+'/samples')
56
57    def MkMainMenu(self):
58        top = self.root
59        w = Tix.Frame(top, bd=2, relief=RAISED)
60        file = Tix.Menubutton(w, text='File', underline=0, takefocus=0)
61        help = Tix.Menubutton(w, text='Help', underline=0, takefocus=0)
62        file.pack(side=LEFT)
63        help.pack(side=RIGHT)
64        fm = Tix.Menu(file, tearoff=0)
65        file['menu'] = fm
66        hm = Tix.Menu(help, tearoff=0)
67        help['menu'] = hm
68
69        fm.add_command(label='Exit', underline=1,
70                     command = lambda self=self: self.quitcmd () )
71        hm.add_checkbutton(label='BalloonHelp', underline=0, command=ToggleHelp,
72                           variable=self.useBalloons)
73        # The trace variable option doesn't seem to work, instead I use 'command'
74        #apply(w.tk.call, ('trace', 'variable', self.useBalloons, 'w',
75        #                     ToggleHelp))
76
77        return w
78
79    def MkMainNotebook(self):
80        top = self.root
81        w = Tix.NoteBook(top, ipadx=5, ipady=5, options="""
82        tagPadX 6
83        tagPadY 4
84        borderWidth 2
85        """)
86        # This may be required if there is no *Background option
87        top['bg'] = w['bg']
88
89        w.add('wel', label='Welcome', underline=0,
90              createcmd=lambda w=w, name='wel': MkWelcome(w, name))
91        w.add('cho', label='Choosers', underline=0,
92              createcmd=lambda w=w, name='cho': MkChoosers(w, name))
93        w.add('scr', label='Scrolled Widgets', underline=0,
94              createcmd=lambda w=w, name='scr': MkScroll(w, name))
95        w.add('mgr', label='Manager Widgets', underline=0,
96              createcmd=lambda w=w, name='mgr': MkManager(w, name))
97        w.add('dir', label='Directory List', underline=0,
98              createcmd=lambda w=w, name='dir': MkDirList(w, name))
99        w.add('exp', label='Run Sample Programs', underline=0,
100              createcmd=lambda w=w, name='exp': MkSample(w, name))
101        return w
102
103    def MkMainStatus(self):
104        global demo
105        top = self.root
106
107        w = Tix.Frame(top, relief=Tix.RAISED, bd=1)
108        demo.statusbar = Tix.Label(w, relief=Tix.SUNKEN, bd=1)
109        demo.statusbar.form(padx=3, pady=3, left=0, right='%70')
110        return w
111
112    def build(self):
113        root = self.root
114        z = root.winfo_toplevel()
115        z.wm_title('Tix Widget Demonstration')
116        if z.winfo_screenwidth() <= 800:
117            z.geometry('790x590+10+10')
118        else:
119            z.geometry('890x640+10+10')
120        demo.balloon = Tix.Balloon(root)
121        frame1 = self.MkMainMenu()
122        frame2 = self.MkMainNotebook()
123        frame3 = self.MkMainStatus()
124        frame1.pack(side=TOP, fill=X)
125        frame3.pack(side=BOTTOM, fill=X)
126        frame2.pack(side=TOP, expand=1, fill=BOTH, padx=4, pady=4)
127        demo.balloon['statusbar'] = demo.statusbar
128        z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
129
130        # To show Tcl errors - uncomment this to see the listbox bug.
131        # Tkinter defines a Tcl tkerror procedure that in effect
132        # silences all background Tcl error reporting.
133        # root.tk.eval('if {[info commands tkerror] != ""} {rename tkerror pytkerror}')
134    def quitcmd (self):
135        """Quit our mainloop. It is up to you to call root.destroy() after."""
136        self.exit = 0
137
138    def loop(self):
139        """This is an explict replacement for _tkinter mainloop()
140        It lets you catch keyboard interrupts easier, and avoids
141        the 20 msec. dead sleep() which burns a constant CPU."""
142        while self.exit < 0:
143            # There are 2 whiles here. The outer one lets you continue
144            # after a ^C interrupt.
145            try:
146                # This is the replacement for _tkinter mainloop()
147                # It blocks waiting for the next Tcl event using select.
148                while self.exit < 0:
149                    self.root.tk.dooneevent(TCL_ALL_EVENTS)
150            except SystemExit:
151                # Tkinter uses SystemExit to exit
152                #print 'Exit'
153                self.exit = 1
154                return
155            except KeyboardInterrupt:
156                if tkMessageBox.askquestion ('Interrupt', 'Really Quit?') == 'yes':
157                    # self.tk.eval('exit')
158                    self.exit = 1
159                    return
160                continue
161            except:
162                # Otherwise it's some other error - be nice and say why
163                t, v, tb = sys.exc_info()
164                text = ""
165                for line in traceback.format_exception(t,v,tb):
166                    text += line + '\n'
167                try: tkMessageBox.showerror ('Error', text)
168                except: pass
169                self.exit = 1
170                raise SystemExit, 1
171
172    def destroy (self):
173        self.root.destroy()
174
175def RunMain(root):
176    global demo
177
178    demo = Demo(root)
179
180    demo.build()
181    demo.loop()
182    demo.destroy()
183
184# Tabs
185def MkWelcome(nb, name):
186    w = nb.page(name)
187    bar = MkWelcomeBar(w)
188    text = MkWelcomeText(w)
189    bar.pack(side=TOP, fill=X, padx=2, pady=2)
190    text.pack(side=TOP, fill=BOTH, expand=1)
191
192def MkWelcomeBar(top):
193    global demo
194
195    w = Tix.Frame(top, bd=2, relief=Tix.GROOVE)
196    b1 = Tix.ComboBox(w, command=lambda w=top: MainTextFont(w))
197    b2 = Tix.ComboBox(w, command=lambda w=top: MainTextFont(w))
198    b1.entry['width'] = 15
199    b1.slistbox.listbox['height'] = 3
200    b2.entry['width'] = 4
201    b2.slistbox.listbox['height'] = 3
202
203    demo.welfont = b1
204    demo.welsize = b2
205
206    b1.insert(Tix.END, 'Courier')
207    b1.insert(Tix.END, 'Helvetica')
208    b1.insert(Tix.END, 'Lucida')
209    b1.insert(Tix.END, 'Times Roman')
210
211    b2.insert(Tix.END, '8')
212    b2.insert(Tix.END, '10')
213    b2.insert(Tix.END, '12')
214    b2.insert(Tix.END, '14')
215    b2.insert(Tix.END, '18')
216
217    b1.pick(1)
218    b2.pick(3)
219
220    b1.pack(side=Tix.LEFT, padx=4, pady=4)
221    b2.pack(side=Tix.LEFT, padx=4, pady=4)
222
223    demo.balloon.bind_widget(b1, msg='Choose\na font',
224                             statusmsg='Choose a font for this page')
225    demo.balloon.bind_widget(b2, msg='Point size',
226                             statusmsg='Choose the font size for this page')
227    return w
228
229def MkWelcomeText(top):
230    global demo
231
232    w = Tix.ScrolledWindow(top, scrollbar='auto')
233    win = w.window
234    text = 'Welcome to TIX in Python'
235    title = Tix.Label(win,
236                      bd=0, width=30, anchor=Tix.N, text=text)
237    msg = Tix.Message(win,
238                      bd=0, width=400, anchor=Tix.N,
239                      text='Tix is a set of mega-widgets based on TK. This program \
240demonstrates the widgets in the Tix widget set. You can choose the pages \
241in this window to look at the corresponding widgets. \n\n\
242To quit this program, choose the "File | Exit" command.\n\n\
243For more information, see http://tix.sourceforge.net.')
244    title.pack(expand=1, fill=Tix.BOTH, padx=10, pady=10)
245    msg.pack(expand=1, fill=Tix.BOTH, padx=10, pady=10)
246    demo.welmsg = msg
247    return w
248
249def MainTextFont(w):
250    global demo
251
252    if not demo.welmsg:
253        return
254    font = demo.welfont['value']
255    point = demo.welsize['value']
256    if font == 'Times Roman':
257        font = 'times'
258    fontstr = '%s %s' % (font, point)
259    demo.welmsg['font'] = fontstr
260
261def ToggleHelp():
262    if demo.useBalloons.get() == '1':
263        demo.balloon['state'] = 'both'
264    else:
265        demo.balloon['state'] = 'none'
266
267def MkChoosers(nb, name):
268    w = nb.page(name)
269    options = "label.padX 4"
270
271    til = Tix.LabelFrame(w, label='Chooser Widgets', options=options)
272    cbx = Tix.LabelFrame(w, label='tixComboBox', options=options)
273    ctl = Tix.LabelFrame(w, label='tixControl', options=options)
274    sel = Tix.LabelFrame(w, label='tixSelect', options=options)
275    opt = Tix.LabelFrame(w, label='tixOptionMenu', options=options)
276    fil = Tix.LabelFrame(w, label='tixFileEntry', options=options)
277    fbx = Tix.LabelFrame(w, label='tixFileSelectBox', options=options)
278    tbr = Tix.LabelFrame(w, label='Tool Bar', options=options)
279
280    MkTitle(til.frame)
281    MkCombo(cbx.frame)
282    MkControl(ctl.frame)
283    MkSelect(sel.frame)
284    MkOptMenu(opt.frame)
285    MkFileEnt(fil.frame)
286    MkFileBox(fbx.frame)
287    MkToolBar(tbr.frame)
288
289    # First column: comBox and selector
290    cbx.form(top=0, left=0, right='%33')
291    sel.form(left=0, right='&'+str(cbx), top=cbx)
292    opt.form(left=0, right='&'+str(cbx), top=sel, bottom=-1)
293
294    # Second column: title .. etc
295    til.form(left=cbx, top=0,right='%66')
296    ctl.form(left=cbx, right='&'+str(til), top=til)
297    fil.form(left=cbx, right='&'+str(til), top=ctl)
298    tbr.form(left=cbx, right='&'+str(til), top=fil, bottom=-1)
299
300    #
301    # Third column: file selection
302    fbx.form(right=-1, top=0, left='%66')
303
304def MkCombo(w):
305    options="label.width %d label.anchor %s entry.width %d" % (10, Tix.E, 14)
306
307    static = Tix.ComboBox(w, label='Static', editable=0, options=options)
308    editable = Tix.ComboBox(w, label='Editable', editable=1, options=options)
309    history = Tix.ComboBox(w, label='History', editable=1, history=1,
310                           anchor=Tix.E, options=options)
311    static.insert(Tix.END, 'January')
312    static.insert(Tix.END, 'February')
313    static.insert(Tix.END, 'March')
314    static.insert(Tix.END, 'April')
315    static.insert(Tix.END, 'May')
316    static.insert(Tix.END, 'June')
317    static.insert(Tix.END, 'July')
318    static.insert(Tix.END, 'August')
319    static.insert(Tix.END, 'September')
320    static.insert(Tix.END, 'October')
321    static.insert(Tix.END, 'November')
322    static.insert(Tix.END, 'December')
323
324    editable.insert(Tix.END, 'Angola')
325    editable.insert(Tix.END, 'Bangladesh')
326    editable.insert(Tix.END, 'China')
327    editable.insert(Tix.END, 'Denmark')
328    editable.insert(Tix.END, 'Ecuador')
329
330    history.insert(Tix.END, '/usr/bin/ksh')
331    history.insert(Tix.END, '/usr/local/lib/python')
332    history.insert(Tix.END, '/var/adm')
333
334    static.pack(side=Tix.TOP, padx=5, pady=3)
335    editable.pack(side=Tix.TOP, padx=5, pady=3)
336    history.pack(side=Tix.TOP, padx=5, pady=3)
337
338states = ['Bengal', 'Delhi', 'Karnataka', 'Tamil Nadu']
339
340def spin_cmd(w, inc):
341    idx = states.index(demo_spintxt.get()) + inc
342    if idx < 0:
343        idx = len(states) - 1
344    elif idx >= len(states):
345        idx = 0
346# following doesn't work.
347#    return states[idx]
348    demo_spintxt.set(states[idx])       # this works
349
350def spin_validate(w):
351    global states, demo_spintxt
352
353    try:
354        i = states.index(demo_spintxt.get())
355    except ValueError:
356        return states[0]
357    return states[i]
358    # why this procedure works as opposed to the previous one beats me.
359
360def MkControl(w):
361    global demo_spintxt
362
363    options="label.width %d label.anchor %s entry.width %d" % (10, Tix.E, 13)
364
365    demo_spintxt = Tix.StringVar()
366    demo_spintxt.set(states[0])
367    simple = Tix.Control(w, label='Numbers', options=options)
368    spintxt = Tix.Control(w, label='States', variable=demo_spintxt,
369                          options=options)
370    spintxt['incrcmd'] = lambda w=spintxt: spin_cmd(w, 1)
371    spintxt['decrcmd'] = lambda w=spintxt: spin_cmd(w, -1)
372    spintxt['validatecmd'] = lambda w=spintxt: spin_validate(w)
373
374    simple.pack(side=Tix.TOP, padx=5, pady=3)
375    spintxt.pack(side=Tix.TOP, padx=5, pady=3)
376
377def MkSelect(w):
378    options = "label.anchor %s" % Tix.CENTER
379
380    sel1 = Tix.Select(w, label='Mere Mortals', allowzero=1, radio=1,
381                      orientation=Tix.VERTICAL,
382                      labelside=Tix.TOP,
383                      options=options)
384    sel2 = Tix.Select(w, label='Geeks', allowzero=1, radio=0,
385                      orientation=Tix.VERTICAL,
386                      labelside= Tix.TOP,
387                      options=options)
388
389    sel1.add('eat', text='Eat')
390    sel1.add('work', text='Work')
391    sel1.add('play', text='Play')
392    sel1.add('party', text='Party')
393    sel1.add('sleep', text='Sleep')
394
395    sel2.add('eat', text='Eat')
396    sel2.add('prog1', text='Program')
397    sel2.add('prog2', text='Program')
398    sel2.add('prog3', text='Program')
399    sel2.add('sleep', text='Sleep')
400
401    sel1.pack(side=Tix.LEFT, padx=5, pady=3, fill=Tix.X)
402    sel2.pack(side=Tix.LEFT, padx=5, pady=3, fill=Tix.X)
403
404def MkOptMenu(w):
405    options='menubutton.width 15 label.anchor %s' % Tix.E
406
407    m = Tix.OptionMenu(w, label='File Format : ', options=options)
408    m.add_command('text', label='Plain Text')
409    m.add_command('post', label='PostScript')
410    m.add_command('format', label='Formatted Text')
411    m.add_command('html', label='HTML')
412    m.add_command('sep')
413    m.add_command('tex', label='LaTeX')
414    m.add_command('rtf', label='Rich Text Format')
415
416    m.pack(fill=Tix.X, padx=5, pady=3)
417
418def MkFileEnt(w):
419    msg = Tix.Message(w,
420                      relief=Tix.FLAT, width=240, anchor=Tix.N,
421                      text='Press the "open file" icon button and a TixFileSelectDialog will popup.')
422    ent = Tix.FileEntry(w, label='Select a file : ')
423    msg.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=3, pady=3)
424    ent.pack(side=Tix.TOP, fill=Tix.X, padx=3, pady=3)
425
426def MkFileBox(w):
427    """The FileSelectBox is a Motif-style box with various enhancements.
428    For example, you can adjust the size of the two listboxes
429    and your past selections are recorded.
430    """
431    msg = Tix.Message(w,
432                      relief=Tix.FLAT, width=240, anchor=Tix.N,
433                      text='The Tix FileSelectBox is a Motif-style box with various enhancements. For example, you can adjust the size of the two listboxes and your past selections are recorded.')
434    box = Tix.FileSelectBox(w)
435    msg.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=3, pady=3)
436    box.pack(side=Tix.TOP, fill=Tix.X, padx=3, pady=3)
437
438def MkToolBar(w):
439    """The Select widget is also good for arranging buttons in a tool bar.
440    """
441    global demo
442
443    options='frame.borderWidth 1'
444
445    msg = Tix.Message(w,
446                      relief=Tix.FLAT, width=240, anchor=Tix.N,
447                      text='The Select widget is also good for arranging buttons in a tool bar.')
448    bar = Tix.Frame(w, bd=2, relief=Tix.RAISED)
449    font = Tix.Select(w, allowzero=1, radio=0, label='', options=options)
450    para = Tix.Select(w, allowzero=0, radio=1, label='', options=options)
451
452    font.add('bold', bitmap='@' + demo.dir + '/bitmaps/bold.xbm')
453    font.add('italic', bitmap='@' + demo.dir + '/bitmaps/italic.xbm')
454    font.add('underline', bitmap='@' + demo.dir + '/bitmaps/underline.xbm')
455    font.add('capital', bitmap='@' + demo.dir + '/bitmaps/capital.xbm')
456
457    para.add('left', bitmap='@' + demo.dir + '/bitmaps/leftj.xbm')
458    para.add('right', bitmap='@' + demo.dir + '/bitmaps/rightj.xbm')
459    para.add('center', bitmap='@' + demo.dir + '/bitmaps/centerj.xbm')
460    para.add('justify', bitmap='@' + demo.dir + '/bitmaps/justify.xbm')
461
462    msg.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=3, pady=3)
463    bar.pack(side=Tix.TOP, fill=Tix.X, padx=3, pady=3)
464    font.pack({'in':bar}, side=Tix.LEFT, padx=3, pady=3)
465    para.pack({'in':bar}, side=Tix.LEFT, padx=3, pady=3)
466
467def MkTitle(w):
468    msg = Tix.Message(w,
469                      relief=Tix.FLAT, width=240, anchor=Tix.N,
470                      text='There are many types of "chooser" widgets that allow the user to input different types of information')
471    msg.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=3, pady=3)
472
473def MkScroll(nb, name):
474    w = nb.page(name)
475    options='label.padX 4'
476
477    sls = Tix.LabelFrame(w, label='Tix.ScrolledListBox', options=options)
478    swn = Tix.LabelFrame(w, label='Tix.ScrolledWindow', options=options)
479    stx = Tix.LabelFrame(w, label='Tix.ScrolledText', options=options)
480
481    MkSList(sls.frame)
482    MkSWindow(swn.frame)
483    MkSText(stx.frame)
484
485    sls.form(top=0, left=0, right='%33', bottom=-1)
486    swn.form(top=0, left=sls, right='%66', bottom=-1)
487    stx.form(top=0, left=swn, right=-1, bottom=-1)
488
489
490def MkSList(w):
491    """This TixScrolledListBox is configured so that it uses scrollbars
492    only when it is necessary. Use the handles to resize the listbox and
493    watch the scrollbars automatically appear and disappear.  """
494    top = Tix.Frame(w, width=300, height=330)
495    bot = Tix.Frame(w)
496    msg = Tix.Message(top,
497                      relief=Tix.FLAT, width=200, anchor=Tix.N,
498                      text='This TixScrolledListBox is configured so that it uses scrollbars only when it is necessary. Use the handles to resize the listbox and watch the scrollbars automatically appear and disappear.')
499
500    list = Tix.ScrolledListBox(top, scrollbar='auto')
501    list.place(x=50, y=150, width=120, height=80)
502    list.listbox.insert(Tix.END, 'Alabama')
503    list.listbox.insert(Tix.END, 'California')
504    list.listbox.insert(Tix.END, 'Montana')
505    list.listbox.insert(Tix.END, 'New Jersey')
506    list.listbox.insert(Tix.END, 'New York')
507    list.listbox.insert(Tix.END, 'Pennsylvania')
508    list.listbox.insert(Tix.END, 'Washington')
509
510    rh = Tix.ResizeHandle(top, bg='black',
511                          relief=Tix.RAISED,
512                          handlesize=8, gridded=1, minwidth=50, minheight=30)
513    btn = Tix.Button(bot, text='Reset', command=lambda w=rh, x=list: SList_reset(w,x))
514    top.propagate(0)
515    msg.pack(fill=Tix.X)
516    btn.pack(anchor=Tix.CENTER)
517    top.pack(expand=1, fill=Tix.BOTH)
518    bot.pack(fill=Tix.BOTH)
519    list.bind('<Map>', func=lambda arg=0, rh=rh, list=list:
520              list.tk.call('tixDoWhenIdle', str(rh), 'attachwidget', str(list)))
521
522def SList_reset(rh, list):
523    list.place(x=50, y=150, width=120, height=80)
524    list.update()
525    rh.attach_widget(list)
526
527def MkSWindow(w):
528    """The ScrolledWindow widget allows you to scroll any kind of Tk
529    widget. It is more versatile than a scrolled canvas widget.
530    """
531    global demo
532
533    text = 'The Tix ScrolledWindow widget allows you to scroll any kind of Tk widget. It is more versatile than a scrolled canvas widget.'
534
535    file = os.path.join(demo.dir, 'bitmaps', 'tix.gif')
536    if not os.path.isfile(file):
537        text += ' (Image missing)'
538
539    top = Tix.Frame(w, width=330, height=330)
540    bot = Tix.Frame(w)
541    msg = Tix.Message(top,
542                      relief=Tix.FLAT, width=200, anchor=Tix.N,
543                      text=text)
544
545    win = Tix.ScrolledWindow(top, scrollbar='auto')
546
547    image1 = win.window.image_create('photo', file=file)
548    lbl = Tix.Label(win.window, image=image1)
549    lbl.pack(expand=1, fill=Tix.BOTH)
550
551    win.place(x=30, y=150, width=190, height=120)
552
553    rh = Tix.ResizeHandle(top, bg='black',
554                          relief=Tix.RAISED,
555                          handlesize=8, gridded=1, minwidth=50, minheight=30)
556    btn = Tix.Button(bot, text='Reset', command=lambda w=rh, x=win: SWindow_reset(w,x))
557    top.propagate(0)
558    msg.pack(fill=Tix.X)
559    btn.pack(anchor=Tix.CENTER)
560    top.pack(expand=1, fill=Tix.BOTH)
561    bot.pack(fill=Tix.BOTH)
562
563    win.bind('<Map>', func=lambda arg=0, rh=rh, win=win:
564             win.tk.call('tixDoWhenIdle', str(rh), 'attachwidget', str(win)))
565
566def SWindow_reset(rh, win):
567    win.place(x=30, y=150, width=190, height=120)
568    win.update()
569    rh.attach_widget(win)
570
571def MkSText(w):
572    """The TixScrolledWindow widget allows you to scroll any kind of Tk
573    widget. It is more versatile than a scrolled canvas widget."""
574    top = Tix.Frame(w, width=330, height=330)
575    bot = Tix.Frame(w)
576    msg = Tix.Message(top,
577                      relief=Tix.FLAT, width=200, anchor=Tix.N,
578                      text='The Tix ScrolledWindow widget allows you to scroll any kind of Tk widget. It is more versatile than a scrolled canvas widget.')
579
580    win = Tix.ScrolledText(top, scrollbar='auto')
581    win.text['wrap'] = 'none'
582    win.text.insert(Tix.END, '''When -scrollbar is set to "auto", the
583scrollbars are shown only when needed.
584Additional modifiers can be used to force a
585scrollbar to be shown or hidden. For example,
586"auto -y" means the horizontal scrollbar
587should be shown when needed but the vertical
588scrollbar should always be hidden;
589"auto +x" means the vertical scrollbar
590should be shown when needed but the horizontal
591scrollbar should always be shown, and so on.'''
592)
593    win.place(x=30, y=150, width=190, height=100)
594
595    rh = Tix.ResizeHandle(top, bg='black',
596                          relief=Tix.RAISED,
597                          handlesize=8, gridded=1, minwidth=50, minheight=30)
598    btn = Tix.Button(bot, text='Reset', command=lambda w=rh, x=win: SText_reset(w,x))
599    top.propagate(0)
600    msg.pack(fill=Tix.X)
601    btn.pack(anchor=Tix.CENTER)
602    top.pack(expand=1, fill=Tix.BOTH)
603    bot.pack(fill=Tix.BOTH)
604    win.bind('<Map>', func=lambda arg=0, rh=rh, win=win:
605             win.tk.call('tixDoWhenIdle', str(rh), 'attachwidget', str(win)))
606
607def SText_reset(rh, win):
608    win.place(x=30, y=150, width=190, height=120)
609    win.update()
610    rh.attach_widget(win)
611
612def MkManager(nb, name):
613    w = nb.page(name)
614    options='label.padX 4'
615
616    pane = Tix.LabelFrame(w, label='Tix.PanedWindow', options=options)
617    note = Tix.LabelFrame(w, label='Tix.NoteBook', options=options)
618
619    MkPanedWindow(pane.frame)
620    MkNoteBook(note.frame)
621
622    pane.form(top=0, left=0, right=note, bottom=-1)
623    note.form(top=0, right=-1, bottom=-1)
624
625def MkPanedWindow(w):
626    """The PanedWindow widget allows the user to interactively manipulate
627    the sizes of several panes. The panes can be arranged either vertically
628    or horizontally.
629    """
630    msg = Tix.Message(w,
631                      relief=Tix.FLAT, width=240, anchor=Tix.N,
632                      text='The PanedWindow widget allows the user to interactively manipulate the sizes of several panes. The panes can be arranged either vertically or horizontally.')
633    group = Tix.LabelEntry(w, label='Newsgroup:', options='entry.width 25')
634    group.entry.insert(0,'comp.lang.python')
635    pane = Tix.PanedWindow(w, orientation='vertical')
636
637    p1 = pane.add('list', min=70, size=100)
638    p2 = pane.add('text', min=70)
639    list = Tix.ScrolledListBox(p1)
640    text = Tix.ScrolledText(p2)
641
642    list.listbox.insert(Tix.END, "  12324 Re: Tkinter is good for your health")
643    list.listbox.insert(Tix.END, "+ 12325 Re: Tkinter is good for your health")
644    list.listbox.insert(Tix.END, "+ 12326 Re: Tix is even better for your health (Was: Tkinter is good...)")
645    list.listbox.insert(Tix.END, "  12327 Re: Tix is even better for your health (Was: Tkinter is good...)")
646    list.listbox.insert(Tix.END, "+ 12328 Re: Tix is even better for your health (Was: Tkinter is good...)")
647    list.listbox.insert(Tix.END, "  12329 Re: Tix is even better for your health (Was: Tkinter is good...)")
648    list.listbox.insert(Tix.END, "+ 12330 Re: Tix is even better for your health (Was: Tkinter is good...)")
649
650    text.text['bg'] = list.listbox['bg']
651    text.text['wrap'] = 'none'
652    text.text.insert(Tix.END, """
653Mon, 19 Jun 1995 11:39:52        comp.lang.python              Thread   34 of  220
654Lines 353       A new way to put text and bitmaps together iNo responses
655ioi@blue.seas.upenn.edu                Ioi K. Lam at University of Pennsylvania
656
657Hi,
658
659I have implemented a new image type called "compound". It allows you
660to glue together a bunch of bitmaps, images and text strings together
661to form a bigger image. Then you can use this image with widgets that
662support the -image option. For example, you can display a text string
663together with a bitmap, at the same time, inside a TK button widget.
664""")
665    list.pack(expand=1, fill=Tix.BOTH, padx=4, pady=6)
666    text.pack(expand=1, fill=Tix.BOTH, padx=4, pady=6)
667
668    msg.pack(side=Tix.TOP, padx=3, pady=3, fill=Tix.BOTH)
669    group.pack(side=Tix.TOP, padx=3, pady=3, fill=Tix.BOTH)
670    pane.pack(side=Tix.TOP, padx=3, pady=3, fill=Tix.BOTH, expand=1)
671
672def MkNoteBook(w):
673    msg = Tix.Message(w,
674                      relief=Tix.FLAT, width=240, anchor=Tix.N,
675                      text='The NoteBook widget allows you to layout a complex interface into individual pages.')
676    # prefix = Tix.OptionName(w)
677    # if not prefix: prefix = ''
678    # w.option_add('*' + prefix + '*TixNoteBook*tagPadX', 8)
679    options = "entry.width %d label.width %d label.anchor %s" % (10, 18, Tix.E)
680
681    nb = Tix.NoteBook(w, ipadx=6, ipady=6, options=options)
682    nb.add('hard_disk', label="Hard Disk", underline=0)
683    nb.add('network', label="Network", underline=0)
684
685    # Frame for the buttons that are present on all pages
686    common = Tix.Frame(nb.hard_disk)
687    common.pack(side=Tix.RIGHT, padx=2, pady=2, fill=Tix.Y)
688    CreateCommonButtons(common)
689
690    # Widgets belonging only to this page
691    a = Tix.Control(nb.hard_disk, value=12, label='Access Time: ')
692    w = Tix.Control(nb.hard_disk, value=400, label='Write Throughput: ')
693    r = Tix.Control(nb.hard_disk, value=400, label='Read Throughput: ')
694    c = Tix.Control(nb.hard_disk, value=1021, label='Capacity: ')
695    a.pack(side=Tix.TOP, padx=20, pady=2)
696    w.pack(side=Tix.TOP, padx=20, pady=2)
697    r.pack(side=Tix.TOP, padx=20, pady=2)
698    c.pack(side=Tix.TOP, padx=20, pady=2)
699
700    common = Tix.Frame(nb.network)
701    common.pack(side=Tix.RIGHT, padx=2, pady=2, fill=Tix.Y)
702    CreateCommonButtons(common)
703
704    a = Tix.Control(nb.network, value=12, label='Access Time: ')
705    w = Tix.Control(nb.network, value=400, label='Write Throughput: ')
706    r = Tix.Control(nb.network, value=400, label='Read Throughput: ')
707    c = Tix.Control(nb.network, value=1021, label='Capacity: ')
708    u = Tix.Control(nb.network, value=10, label='Users: ')
709    a.pack(side=Tix.TOP, padx=20, pady=2)
710    w.pack(side=Tix.TOP, padx=20, pady=2)
711    r.pack(side=Tix.TOP, padx=20, pady=2)
712    c.pack(side=Tix.TOP, padx=20, pady=2)
713    u.pack(side=Tix.TOP, padx=20, pady=2)
714
715    msg.pack(side=Tix.TOP, padx=3, pady=3, fill=Tix.BOTH)
716    nb.pack(side=Tix.TOP, padx=5, pady=5, fill=Tix.BOTH, expand=1)
717
718def CreateCommonButtons(f):
719    ok = Tix.Button(f, text='OK', width = 6)
720    cancel = Tix.Button(f, text='Cancel', width = 6)
721    ok.pack(side=Tix.TOP, padx=2, pady=2)
722    cancel.pack(side=Tix.TOP, padx=2, pady=2)
723
724def MkDirList(nb, name):
725    w = nb.page(name)
726    options = "label.padX 4"
727
728    dir = Tix.LabelFrame(w, label='Tix.DirList', options=options)
729    fsbox = Tix.LabelFrame(w, label='Tix.ExFileSelectBox', options=options)
730    MkDirListWidget(dir.frame)
731    MkExFileWidget(fsbox.frame)
732    dir.form(top=0, left=0, right='%40', bottom=-1)
733    fsbox.form(top=0, left='%40', right=-1, bottom=-1)
734
735def MkDirListWidget(w):
736    """The TixDirList widget gives a graphical representation of the file
737    system directory and makes it easy for the user to choose and access
738    directories.
739    """
740    msg = Tix.Message(w,
741                      relief=Tix.FLAT, width=240, anchor=Tix.N,
742                      text='The Tix DirList widget gives a graphical representation of the file system directory and makes it easy for the user to choose and access directories.')
743    dirlist = Tix.DirList(w, options='hlist.padY 1 hlist.width 25 hlist.height 16')
744    msg.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=3, pady=3)
745    dirlist.pack(side=Tix.TOP, padx=3, pady=3)
746
747def MkExFileWidget(w):
748    """The TixExFileSelectBox widget is more user friendly than the Motif
749    style FileSelectBox.  """
750    msg = Tix.Message(w,
751                      relief=Tix.FLAT, width=240, anchor=Tix.N,
752                      text='The Tix ExFileSelectBox widget is more user friendly than the Motif style FileSelectBox.')
753    # There's a bug in the ComboBoxes - the scrolledlistbox is destroyed
754    box = Tix.ExFileSelectBox(w, bd=2, relief=Tix.RAISED)
755    msg.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=3, pady=3)
756    box.pack(side=Tix.TOP, padx=3, pady=3)
757
758###
759### List of all the demos we want to show off
760comments = {'widget' : 'Widget Demos', 'image' : 'Image Demos'}
761samples = {'Balloon'            : 'Balloon',
762           'Button Box'         : 'BtnBox',
763           'Combo Box'          : 'ComboBox',
764           'Compound Image'     : 'CmpImg',
765           'Directory List'     : 'DirList',
766           'Directory Tree'     : 'DirTree',
767           'Control'            : 'Control',
768           'Notebook'           : 'NoteBook',
769           'Option Menu'        : 'OptMenu',
770           'Paned Window'       : 'PanedWin',
771           'Popup Menu'         : 'PopMenu',
772           'ScrolledHList (1)'  : 'SHList1',
773           'ScrolledHList (2)'  : 'SHList2',
774           'Tree (dynamic)'     : 'Tree'
775}
776
777# There are still a lot of demos to be translated:
778##      set root {
779##          {d "File Selectors"         file    }
780##          {d "Hierachical ListBox"    hlist   }
781##          {d "Tabular ListBox"        tlist   {c tixTList}}
782##          {d "Grid Widget"            grid    {c tixGrid}}
783##          {d "Manager Widgets"        manager }
784##          {d "Scrolled Widgets"       scroll  }
785##          {d "Miscellaneous Widgets"  misc    }
786##          {d "Image Types"            image   }
787##      }
788##
789##      set image {
790##          {d "Compound Image"         cmpimg  }
791##          {d "XPM Image"              xpm     {i pixmap}}
792##      }
793##
794##      set cmpimg {
795##done      {f "In Buttons"             CmpImg.tcl      }
796##          {f "In NoteBook"            CmpImg2.tcl     }
797##          {f "Notebook Color Tabs"    CmpImg4.tcl     }
798##          {f "Icons"                  CmpImg3.tcl     }
799##      }
800##
801##      set xpm {
802##          {f "In Button"              Xpm.tcl         {i pixmap}}
803##          {f "In Menu"                Xpm1.tcl        {i pixmap}}
804##      }
805##
806##      set file {
807##added     {f DirList                          DirList.tcl     }
808##added     {f DirTree                          DirTree.tcl     }
809##          {f DirSelectDialog                  DirDlg.tcl      }
810##          {f ExFileSelectDialog               EFileDlg.tcl    }
811##          {f FileSelectDialog                 FileDlg.tcl     }
812##          {f FileEntry                        FileEnt.tcl     }
813##      }
814##
815##      set hlist {
816##          {f HList                    HList1.tcl      }
817##          {f CheckList                ChkList.tcl     {c tixCheckList}}
818##done      {f "ScrolledHList (1)"      SHList.tcl      }
819##done      {f "ScrolledHList (2)"      SHList2.tcl     }
820##done      {f Tree                     Tree.tcl        }
821##done      {f "Tree (Dynamic)"         DynTree.tcl     {v win}}
822##      }
823##
824##      set tlist {
825##          {f "ScrolledTList (1)"      STList1.tcl     {c tixTList}}
826##          {f "ScrolledTList (2)"      STList2.tcl     {c tixTList}}
827##      }
828##      global tcl_platform
829##      #  This demo hangs windows
830##      if {$tcl_platform(platform) != "windows"} {
831##na    lappend tlist     {f "TList File Viewer"        STList3.tcl     {c tixTList}}
832##      }
833##
834##      set grid {
835##na        {f "Simple Grid"            SGrid0.tcl      {c tixGrid}}
836##na        {f "ScrolledGrid"           SGrid1.tcl      {c tixGrid}}
837##na        {f "Editable Grid"          EditGrid.tcl    {c tixGrid}}
838##      }
839##
840##      set scroll {
841##          {f ScrolledListBox          SListBox.tcl    }
842##          {f ScrolledText             SText.tcl       }
843##          {f ScrolledWindow           SWindow.tcl     }
844##na        {f "Canvas Object View"     CObjView.tcl    {c tixCObjView}}
845##      }
846##
847##      set manager {
848##          {f ListNoteBook             ListNBK.tcl     }
849##done      {f NoteBook                 NoteBook.tcl    }
850##done      {f PanedWindow              PanedWin.tcl    }
851##      }
852##
853##      set misc {
854##done      {f Balloon                  Balloon.tcl     }
855##done      {f ButtonBox                BtnBox.tcl      }
856##done      {f ComboBox                 ComboBox.tcl    }
857##done      {f Control                  Control.tcl     }
858##          {f LabelEntry               LabEntry.tcl    }
859##          {f LabelFrame               LabFrame.tcl    }
860##          {f Meter                    Meter.tcl       {c tixMeter}}
861##done      {f OptionMenu               OptMenu.tcl     }
862##done      {f PopupMenu                PopMenu.tcl     }
863##          {f Select                   Select.tcl      }
864##          {f StdButtonBox             StdBBox.tcl     }
865##      }
866##
867
868stypes = {}
869stypes['widget'] = ['Balloon', 'Button Box', 'Combo Box', 'Control',
870                    'Directory List', 'Directory Tree',
871                    'Notebook', 'Option Menu', 'Popup Menu', 'Paned Window',
872                    'ScrolledHList (1)', 'ScrolledHList (2)', 'Tree (dynamic)']
873stypes['image'] = ['Compound Image']
874
875def MkSample(nb, name):
876    w = nb.page(name)
877    options = "label.padX 4"
878
879    pane = Tix.PanedWindow(w, orientation='horizontal')
880    pane.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH)
881    f1 = pane.add('list', expand='1')
882    f2 = pane.add('text', expand='5')
883    f1['relief'] = 'flat'
884    f2['relief'] = 'flat'
885
886    lab = Tix.LabelFrame(f1, label='Select a sample program:')
887    lab.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=5, pady=5)
888    lab1 = Tix.LabelFrame(f2, label='Source:')
889    lab1.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=5, pady=5)
890
891    slb = Tix.Tree(lab.frame, options='hlist.width 20')
892    slb.pack(side=Tix.TOP, expand=1, fill=Tix.BOTH, padx=5)
893
894    stext = Tix.ScrolledText(lab1.frame, name='stext')
895    font = root.tk.eval('tix option get fixed_font')
896    stext.text.config(font=font)
897
898    frame = Tix.Frame(lab1.frame, name='frame')
899
900    run = Tix.Button(frame, text='Run ...', name='run')
901    view = Tix.Button(frame, text='View Source ...', name='view')
902    run.pack(side=Tix.LEFT, expand=0, fill=Tix.NONE)
903    view.pack(side=Tix.LEFT, expand=0, fill=Tix.NONE)
904
905    stext.text['bg'] = slb.hlist['bg']
906    stext.text['state'] = 'disabled'
907    stext.text['wrap'] = 'none'
908    stext.text['width'] = 80
909
910    frame.pack(side=Tix.BOTTOM, expand=0, fill=Tix.X, padx=7)
911    stext.pack(side=Tix.TOP, expand=0, fill=Tix.BOTH, padx=7)
912
913    slb.hlist['separator'] = '.'
914    slb.hlist['width'] = 25
915    slb.hlist['drawbranch'] = 0
916    slb.hlist['indent'] = 10
917    slb.hlist['wideselect'] = 1
918    slb.hlist['command'] = lambda args=0, w=w,slb=slb,stext=stext,run=run,view=view: Sample_Action(w, slb, stext, run, view, 'run')
919    slb.hlist['browsecmd'] = lambda args=0, w=w,slb=slb,stext=stext,run=run,view=view: Sample_Action(w, slb, stext, run, view, 'browse')
920
921    run['command']      = lambda args=0, w=w,slb=slb,stext=stext,run=run,view=view: Sample_Action(w, slb, stext, run, view, 'run')
922    view['command'] = lambda args=0, w=w,slb=slb,stext=stext,run=run,view=view: Sample_Action(w, slb, stext, run, view, 'view')
923
924    for type in ['widget', 'image']:
925        if type != 'widget':
926            x = Tix.Frame(slb.hlist, bd=2, height=2, width=150,
927                          relief=Tix.SUNKEN, bg=slb.hlist['bg'])
928            slb.hlist.add_child(itemtype=Tix.WINDOW, window=x, state='disabled')
929        x = slb.hlist.add_child(itemtype=Tix.TEXT, state='disabled',
930                                text=comments[type])
931        for key in stypes[type]:
932            slb.hlist.add_child(x, itemtype=Tix.TEXT, data=key,
933                                text=key)
934    slb.hlist.selection_clear()
935
936    run['state'] = 'disabled'
937    view['state'] = 'disabled'
938
939def Sample_Action(w, slb, stext, run, view, action):
940    global demo
941
942    hlist = slb.hlist
943    anchor = hlist.info_anchor()
944    if not anchor:
945        run['state'] = 'disabled'
946        view['state'] = 'disabled'
947    elif not hlist.info_parent(anchor):
948        # a comment
949        return
950
951    run['state'] = 'normal'
952    view['state'] = 'normal'
953    key = hlist.info_data(anchor)
954    title = key
955    prog = samples[key]
956
957    if action == 'run':
958        exec('import ' + prog)
959        w = Tix.Toplevel()
960        w.title(title)
961        rtn = eval(prog + '.RunSample')
962        rtn(w)
963    elif action == 'view':
964        w = Tix.Toplevel()
965        w.title('Source view: ' + title)
966        LoadFile(w, demo.dir + '/samples/' + prog + '.py')
967    elif action == 'browse':
968        ReadFile(stext.text, demo.dir + '/samples/' + prog + '.py')
969
970def LoadFile(w, fname):
971    global root
972    b = Tix.Button(w, text='Close', command=w.destroy)
973    t = Tix.ScrolledText(w)
974    #    b.form(left=0, bottom=0, padx=4, pady=4)
975    #    t.form(left=0, bottom=b, right='-0', top=0)
976    t.pack()
977    b.pack()
978
979    font = root.tk.eval('tix option get fixed_font')
980    t.text.config(font=font)
981    t.text['bd'] = 2
982    t.text['wrap'] = 'none'
983
984    ReadFile(t.text, fname)
985
986def ReadFile(w, fname):
987    old_state = w['state']
988    w['state'] = 'normal'
989    w.delete('0.0', Tix.END)
990
991    try:
992        f = open(fname)
993        lines = f.readlines()
994        for s in lines:
995            w.insert(Tix.END, s)
996        f.close()
997    finally:
998#       w.see('1.0')
999        w['state'] = old_state
1000
1001if __name__ == '__main__':
1002    root = Tix.Tk()
1003    RunMain(root)
1004