1#! /usr/bin/env python
2
3#
4# "$Id: tree.py 495 2013-03-30 09:39:45Z andreasheld $"
5#
6# Tree widget test program for pyFLTK the Python bindings
7# for the Fast Light Tool Kit (FLTK).
8#
9# FLTK copyright 1998-1999 by Bill Spitzak and others.
10# pyFLTK copyright 2003 by Andreas Held and others.
11#
12# This library is free software you can redistribute it and/or
13# modify it under the terms of the GNU Library General Public
14# License as published by the Free Software Foundation either
15# version 2 of the License, or (at your option) any later version.
16#
17# This library is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20# Library General Public License for more details.
21#
22# You should have received a copy of the GNU Library General Public
23# License along with this library if not, write to the Free Software
24# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25# USA.
26#
27# Please report all bugs and problems to "pyfltk-user@lists.sourceforge.net".
28#
29
30
31"""
32Tree test program.
33"""
34
35import traceback, sys
36if sys.version > '3':
37    long = int
38
39from fltk import *
40
41G_cb_counter = 0
42but = None
43grp = None
44
45def reason_as_name(reason):
46    if reason == FL_TREE_REASON_NONE:
47        return "none"
48    elif reason == FL_TREE_REASON_SELECTED:
49        return "selected"
50    elif reason == FL_TREE_REASON_DESELECTED:
51        return "deselected"
52    elif reason == FL_TREE_REASON_OPENED:
53        return "opened"
54    elif reason == FL_TREE_REASON_CLOSED:
55        return "closed"
56    else:
57        return "???"
58
59def Button_CB(w):
60    print("'%s' button pushed\n"%w.label())
61
62def RebuildTree(tree):
63    global but, grp
64    # REBUILD THE TREE TO MAKE CURRENT "DEFAULT" PREFS TAKE EFFECT
65    tree.clear()
66    tree.add("Aaa")
67    tree.add("Bbb")
68    tree.add("Ccc")
69    tree.add("Ddd")
70    tree.add("Bbb/child-01")
71    tree.add("Bbb/child-01/111")
72    tree.add("Bbb/child-01/222")
73    tree.add("Bbb/child-01/333")
74    tree.add("Bbb/child-02")
75    tree.add("Bbb/child-03")
76    tree.add("Bbb/child-04")
77
78    # Assign an FLTK widget to one of the items
79    i = tree.find_item("Bbb/child-03")
80    if i != None:
81        if but == None: # only do this once at program startup
82            tree.begin()
83            but = Fl_Button(1,1,140,1,"ccc button") # we control w() only
84            but.labelsize(10)
85            but.callback(Button_CB)
86        i.widget(but)
87        tree.end()
88
89
90    # Assign an FLTK group to one of the items with widgets
91    i = tree.find_item("Bbb/child-04")
92    if i != None:
93        if grp == None: # only do this once at program startup
94            tree.begin()
95            grp = Fl_Group(100,100,140,18) # build group.. tree handles position
96            grp.color(FL_WHITE);
97            grp.begin()
98            abut = Fl_Button(grp.x()+0 ,grp.y()+2,65,15,"D1")
99            abut.labelsize(10)
100            abut.callback(Button_CB)
101            bbut = Fl_Button(grp.x()+75,grp.y()+2,65,15,"D2")
102            bbut.labelsize(10)
103            bbut.callback(Button_CB)
104            grp.end()
105            grp.resizable(grp)
106            tree.end()
107
108        i.widget(grp);
109
110    # Add an 'Ascending' node, and create it sorted
111    tree.sortorder(FL_TREE_SORT_NONE)
112    tree.add("Ascending").close()
113    tree.sortorder(FL_TREE_SORT_ASCENDING)
114    tree.add("Ascending/Zzz")
115    tree.add("Ascending/Xxx")
116    tree.add("Ascending/Aaa")
117    tree.add("Ascending/Bbb")
118    tree.add("Ascending/Yyy")
119    tree.add("Ascending/Ccc")
120
121    # Add a 'Descending' node, and create it sorted
122    tree.sortorder(FL_TREE_SORT_NONE)
123    tree.add("Descending").close()
124    tree.sortorder(FL_TREE_SORT_DESCENDING)
125    tree.add("Descending/Zzz")
126    tree.add("Descending/Xxx")
127    tree.add("Descending/Aaa")
128    tree.add("Descending/Bbb")
129    tree.add("Descending/Yyy")
130    tree.add("Descending/Ccc")
131
132    # Add 500 items in numerical order
133    tree.sortorder(FL_TREE_SORT_NONE);
134    for t in range(500):
135        s = "500 Items/item %04d"%t
136        tree.add(s)
137
138    tree.close("500 Items")	# close the 500 items by default
139
140    tree.redraw()
141
142
143
144
145
146def cb_tree(tree, data):
147    global G_cb_counter
148    # Increment callback counter whenever tree callback is invoked
149    G_cb_counter = G_cb_counter+1
150
151    item = tree.callback_item()
152    if item:
153        print("TREE CALLBACK: label='%s' userdata=%ld reason=%s\n"%(
154          item.label(),
155          data,
156	  reason_as_name(tree.callback_reason())))
157    else:
158        print("TREE CALLBACK: reason=%s item=(no item -- probably multiple items were changed at once)\n"%(
159          reason_as_name(tree.callback_reason())))
160
161
162def cb_margintop_slider(margintop_slider, tree):
163    val = int(margintop_slider.value())
164    tree.margintop(val)
165    tree.redraw()
166
167def cb_marginleft_slider(marginleft_slider, tree):
168    val = int(marginleft_slider.value())
169    tree.marginleft(val)
170    tree.redraw()
171
172def cb_openchild_marginbottom_slider(openchild_marginbottom_slider, tree):
173    val = int(openchild_marginbottom_slider.value())
174    tree.openchild_marginbottom(val)
175    tree.redraw()
176
177def cb_labelsize_slider(labelsize_slider, tree):
178    size = int(labelsize_slider.value())
179    count = 0
180
181    item = tree.first()
182    while item != None:
183        if item.is_selected():
184            item.labelsize(size)
185            count = count+1
186        item = tree.next(item)
187
188    if count == 0:
189        item = tree.first()
190        while item != None:
191            item.labelsize(size)
192            item = tree.next(item)
193
194    tree.redraw()
195
196def cb_connectorwidth_slider(connectorwidth_slider, tree):
197    val = int(connectorwidth_slider.value())
198    tree.connectorwidth(val)
199    #tree.redraw()
200
201L_folderpixmap = None
202L_documentpixmap = None
203
204def cb_usericon_radio(usericon_radio, tree):
205    global L_folderpixmap, L_documentpixmap
206    L_folder_xpm = [
207    "11 11 3 1",
208    ".  c None",
209    "x  c #d8d833",
210    "@  c #808011",
211    "...........",
212    ".....@@@@..",
213    "....@xxxx@.",
214    "@@@@@xxxx@@",
215    "@xxxxxxxxx@",
216    "@xxxxxxxxx@",
217    "@xxxxxxxxx@",
218    "@xxxxxxxxx@",
219    "@xxxxxxxxx@",
220    "@xxxxxxxxx@",
221    "@@@@@@@@@@@"]
222    L_folderpixmap = Fl_Pixmap(L_folder_xpm)
223
224    L_document_xpm = [
225    "11 11 3 1",
226    ".  c None",
227    "x  c #d8d8f8",
228    "@  c #202060",
229    ".@@@@@@@@@.",
230    ".@xxxxxxx@.",
231    ".@xxxxxxx@.",
232    ".@xxxxxxx@.",
233    ".@xxxxxxx@.",
234    ".@xxxxxxx@.",
235    ".@xxxxxxx@.",
236    ".@xxxxxxx@.",
237    ".@xxxxxxx@.",
238    ".@xxxxxxx@.",
239    ".@@@@@@@@@."]
240    L_documentpixmap = Fl_Pixmap(L_document_xpm)
241
242    i = None
243
244    if usericon_radio.value() != 0.0:
245        tree.usericon(L_folderpixmap)
246        i = tree.find_item("Bbb/bgb/111")
247        if i != None:
248            i.usericon(L_documentpixmap)
249        i = tree.find_item("Bbb/bgb/222")
250        if i != None:
251            i.usericon(L_documentpixmap)
252        i = tree.find_item("Bbb/bgb/333")
253        if i != None:
254            i.usericon(L_documentpixmap)
255    else:
256        tree.usericon(None)
257        i = tree.find_item("Bbb/bgb/111")
258        if i != None:
259            i.usericon(0)
260        i = tree.find_item("Bbb/bgb/222")
261        if i != None:
262            i.usericon(0)
263        i = tree.find_item("Bbb/bgb/333")
264        if i != None:
265            i.usericon(0)
266
267def cb_showroot_radio(showroot_radio, datatree):
268    onoff = int(showroot_radio.value())
269    tree.showroot(onoff)
270
271
272def cb_visiblefocus_checkbox(visiblefocus_checkbox, tree):
273    onoff = int(visiblefocus_checkbox.value())
274    tree.visible_focus(onoff)
275
276L_openpixmap = None
277L_closepixmap = None
278
279def cb_collapseicons_chooser(collapseicons_chooser, tree):
280    global L_openpixmap, L_closepixmap
281    L_open_xpm = [
282    "11 11 2 1",
283    ".  c None",
284    "@  c #000000",
285    "...@.......",
286    "...@@......",
287    "...@@@.....",
288    "...@@@@....",
289    "...@@@@@...",
290    "...@@@@@@..",
291    "...@@@@@...",
292    "...@@@@....",
293    "...@@@.....",
294    "...@@......",
295    "...@......."]
296
297    L_openpixmap = Fl_Pixmap(L_open_xpm)
298
299    L_close_xpm = [
300    "11 11 2 1",
301    ".  c None",
302    "@  c #000000",
303    "...........",
304    "...........",
305    "...........",
306    "...........",
307    "...........",
308    "@@@@@@@@@@@",
309    ".@@@@@@@@@.",
310    "..@@@@@@@..",
311    "...@@@@@...",
312    "....@@@....",
313    ".....@....."]
314    L_closepixmap = Fl_Pixmap (L_close_xpm)
315
316    if collapseicons_chooser.value() == 0:
317        tree.showcollapse(1)
318        tree.openicon(None)
319        tree.closeicon(None)
320    elif collapseicons_chooser.value() == 1:
321        tree.showcollapse(1)
322        tree.openicon(L_openpixmap)
323        tree.closeicon(L_closepixmap)
324    elif collapseicons_chooser.value() == 2:
325        tree.showcollapse(0)
326
327menu_collapseicons_chooser = (("Normal", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
328 ("Custom", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
329 ("Off", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
330 (None,))
331
332def cb_connectorstyle_chooser(connectorstyle_chooser, tree):
333    # CHANGE COLLAPSESTYLE
334    if connectorstyle_chooser.value() == 0:
335        tree.connectorstyle(FL_TREE_CONNECTOR_NONE)
336    elif connectorstyle_chooser.value() == 1:
337        tree.connectorstyle(FL_TREE_CONNECTOR_DOTTED)
338    elif connectorstyle_chooser.value() == 2:
339        tree.connectorstyle(FL_TREE_CONNECTOR_SOLID)
340
341menu_connectorstyle_chooser = (("None", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
342 ("Dotted", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
343 ("Solid", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
344 (None,))
345
346
347def cb_labelcolor_chooser(labelcolor_chooser, tree):
348    # Set color..
349    c = 0x00000000
350    if labelcolor_chooser.value() == 0:
351        c = 0x00000000 # black
352    elif labelcolor_chooser.value() == 1:
353        c = 0xd0000000 # red
354    elif labelcolor_chooser.value() == 2:
355        c = 0x00a00000 # green
356    elif labelcolor_chooser.value() == 3:
357        c = 0x0000a000 # blue
358    else:
359        c = 0x00000000 # black
360
361    # DO SELECTED ITEMS
362    count = 0
363    item = tree.first()
364    while item != None:
365        if item.is_selected():
366            item.labelcolor(c)
367            count = count + 1
368        item = tree.next(item)
369    # NO ITEMS SELECTED? DO ALL
370    if count == 0:
371        item = tree.first()
372        while item != None:
373            item.labelcolor(c)
374            item = tree.next(item)
375    tree.redraw()
376
377menu_labelcolor_chooser = (
378 ("Black", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
379 ("Red", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
380 ("Green", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
381 ("Blue", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
382 (None,))
383
384def cb_selectmode_chooser(selectmode_chooser, tree):
385    # Set selection mode
386    if selectmode_chooser.value() == 0:
387        tree.selectmode(FL_TREE_SELECT_NONE)
388    elif selectmode_chooser.value() == 1:
389        tree.selectmode(FL_TREE_SELECT_SINGLE)
390    elif selectmode_chooser.value() == 2:
391        tree.selectmode(FL_TREE_SELECT_MULTI)
392    else:
393        tree.selectmode(FL_TREE_SELECT_SINGLE)
394
395menu_selectmode_chooser = (
396 ("None", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
397 ("Single", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
398 ("Multi", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
399 (None,))
400
401def cb_whenmode_chooser(whenmode_chooser, tree):
402    # Set when mode
403    if  whenmode_chooser.value() == 0:
404        tree.when(FL_WHEN_RELEASE)
405    elif  whenmode_chooser.value() == 1:
406        tree.when(FL_WHEN_CHANGED)
407    elif  whenmode_chooser.value() == 2:
408        tree.when(FL_WHEN_NEVER)
409    else:
410        tree.when(FL_WHEN_RELEASE)
411
412menu_whenmode_chooser = (
413 ("Changed", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
414 ("Released", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
415 ("Never", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 11, 0),
416 (None,))
417
418
419def cb_Show(show_btn, tree):
420    item = tree.next_selected_item()
421    print(item)
422    tree.show_item(item)
423
424def cb_Top(top_btn, tree):
425    item = tree.next_selected_item()
426    print(item)
427    tree.show_item_top(item)
428
429
430def cb_Mid(mid_btn, tree):
431    item = tree.next_selected_item()
432    tree.show_item_middle(item)
433
434
435def cb_Bot(bot_btn, tree):
436    item = tree.next_selected_item()
437    tree.show_item_bottom(item)
438
439def cb_selectall_button(selectall_button, tree):
440    tree.select_all(None)
441    tree.redraw()
442
443
444def cb_deselectall_button(deselectall_button, tree):
445    tree.deselect_all(None)
446    tree.redraw()
447
448def cb_bbbselect_toggle(bbbselect_toggle, tree):
449    # Toggle select of just the Bbb item (not children)
450    bbb = tree.find_item("/Bbb")
451    if bbb == None:
452        fl_alert("FAIL: Couldn't find item '/Bbb'???")
453        return
454
455    onoff = bbbselect_toggle.value()
456    if onoff != 0:
457        tree.select(bbb)	# select /Bbb
458    else:
459        tree.deselect(bbb)	# deselect /Bbb
460
461def cb_bbbselect2_toggle(bbbselect2_toggle, tree):
462    # Toggle select of just the Bbb item and its immediate children
463    bbb = tree.find_item("/Bbb")
464    if bbb == None:
465        fl_alert("FAIL: Couldn't find item '/Bbb'???")
466        return
467
468    onoff = bbbselect2_toggle.value()
469    if onoff != 0:
470        tree.select_all(bbb)	# select /Bbb
471    else:
472        tree.deselect_all(bbb)	# deselect /Bbb
473
474def cb_bbbchild02select_toggle(bbbchild02select_toggle, tree):
475    # Toggle select of just the /Bbb/child-02 item
476    onoff = bbbchild02select_toggle.value()
477    if onoff != 0:
478        tree.select("/Bbb/child-02")
479    else:
480        tree.deselect("/Bbb/child-02")
481
482def cb_rootselect_toggle(rootselect_toggle, tree):
483    # Toggle select of ROOT item and its children
484    item = tree.find_item("/ROOT")
485    if item == None:
486        fl_alert("FAIL: Couldn't find item '/ROOT'???")
487        return
488
489    onoff = rootselect_toggle.value()
490    if onoff != 0:
491        tree.select(item)	# select /ROOT and its children
492    else:
493        tree.deselect(item)	# deselect /ROOT and its children
494
495def cb_rootselect2_toggle(rootselect2_toggle, tree):
496    # Toggle select of ROOT item and its children
497    item = tree.find_item("/ROOT")
498    if item == None:
499        fl_alert("FAIL: Couldn't find item '/ROOT'???")
500        return
501
502    onoff = rootselect_toggle.value()
503    if onoff != 0:
504        tree.select_all(item)	# select /ROOT and its children
505    else:
506        tree.deselect_all(item)	# deselect /ROOT and its children
507
508
509def cb_deactivate_toggle(deactivate_toggle, tree):
510    onoff = deactivate_toggle.value()
511    if onoff != 0:
512        onoff = 1
513
514    count = 0
515    item=tree.first()
516    while item != None:
517        if item.is_selected():
518            item.activate(onoff)
519            count = count+1
520        item = tree.next(item)
521
522    if count == 0:
523        item=tree.first()
524        while item != None:
525            item.activate(onoff)
526            item = tree.next(item)
527    tree.redraw()
528
529def cb_bold_toggle(bold_toggle, tree):
530    face = FL_HELVETICA
531    if bold_toggle.value() != 0:
532        face = FL_HELVETICA_BOLD
533
534    # DO SELECTED ITEMS
535    count = 0
536    item=tree.first()
537    while item != None:
538        if item.is_selected():
539            item.labelfont(face)
540            count = count+1
541        item = tree.next(item)
542
543    # NO ITEMS SELECTED? DO ALL
544    if count == 0:
545        item=tree.first()
546        while item != None:
547            item.labelfont(face)
548            item = tree.next(item)
549
550    tree.redraw()
551
552
553def cb_loaddb_button(loaddb_button, tree):
554    filename = fl_file_chooser("Select a Preferences style Database", "Preferences(*.prefs)", long(0))
555    if len(filename) > 0:
556        tree.clear()
557        prefs = Fl_Preferences(filename, long(0), long(0))
558        tree.load(prefs)
559        tree.redraw()
560
561def cb_insertabove_button(insertabove_button, tree):
562    item=tree.first()
563    while item != None:
564        if item.is_selected():
565            tree.insert_above(item, "AaaAaa")
566            tree.insert_above(item, "BbbBbb")
567            tree.insert_above(item, "CccCcc")
568        item = item.next()
569    tree.redraw()
570
571def cb_rebuildtree_button(rebuildtree_button, tree):
572    RebuildTree(tree)
573
574def cb_showpathname_button(showpathname_button, tree):
575    item = tree.first_selected_item()
576    if item == None:
577        fl_message("No item was selected")
578        return
579
580    pathname = ""
581    ret_val =  tree.item_pathname(pathname, len(pathname), item)
582    if ret_val == 0:
583        msg = item.label()
584        if msg == None or msg == "":
585            msg = "???"
586        fl_message("Pathname for '%s' is: \"%s\"", msg, pathname)
587    elif ret_val == -1:
588        fl_message("item_pathname() returned -1 (NOT FOUND)")
589    elif ret_val == -2:
590        fl_message("item_pathname() returned -2 (STRING TOO LONG)")
591
592def cb_showselected_button(showselected_button, tree):
593    print("--- SELECTED ITEMS")
594    item = tree.first_selected_item()
595    while item != None:
596        msg = item.label()
597        if msg == None or msg == "":
598            msg = "???"
599        print("\t%s\n"%msg)
600        item = tree.next_selected_item(item)
601
602def cb_clearselected_button(clearselected_button, tree):
603    item=tree.first()
604    while item != None:
605        if item.is_selected():
606            if tree.remove(item) == -1:
607                break
608            item = tree.first()
609        else:
610            item = item.next()
611    tree.redraw()
612
613def cb_clearall_button(clearall_button, tree):
614    tree.clear()
615    tree.redraw()
616
617
618def cb_testcallbackflag_button(testcallbackflag_button, tree):
619    global G_cb_counter
620    root = tree.root()
621    print("--- Checking docallback off\n")
622
623    # "OFF" TEST
624
625    # open/close: Make sure these methods don't trigger cb
626    G_cb_counter = 0
627    tree.close(root, 0)
628    if G_cb_counter != 0:
629        fl_alert("FAILED 'OFF' TEST\n close(item) triggered cb!")
630    G_cb_counter = 0
631    tree.open(root, 0)
632    if G_cb_counter != 0:
633        fl_alert("FAILED 'OFF' TEST\n open(item) triggered cb!")
634    G_cb_counter = 0
635    tree.open_toggle(root, 0)
636    if G_cb_counter != 0:
637        fl_alert("FAILED 'OFF' TEST\n open_toggle(item) triggered cb!")
638    G_cb_counter = 0
639    tree.open("ROOT", 0)
640    if G_cb_counter != 0:
641        fl_alert("FAILED 'OFF' TEST\n open(path) triggered cb!")
642    G_cb_counter = 0
643    tree.close("ROOT", 0)
644    if G_cb_counter != 0:
645        fl_alert("FAILED 'OFF' TEST\n close(path) triggered cb!")
646    tree.open(root,0)	# leave root open
647
648    # select/deselect: Make sure these methods don't trigger cb
649    G_cb_counter = 0
650    tree.select(root, 0)
651    if G_cb_counter != 0:
652        fl_alert("FAILED 'OFF' TEST\n select(item) triggered cb!")
653    G_cb_counter = 0
654    tree.deselect(root, 0)
655    if G_cb_counter != 0:
656        fl_alert("FAILED 'OFF' TEST\n deselect(item) triggered cb!")
657    G_cb_counter = 0
658    tree.select_toggle(root, 0);
659    if G_cb_counter != 0:
660        fl_alert("FAILED 'OFF' TEST\n select_toggle(item) triggered cb!")
661    G_cb_counter = 0
662    tree.deselect("ROOT", 0)
663    if G_cb_counter != 0:
664        fl_alert("FAILED 'OFF' TEST\n deselect(path) triggered cb!")
665    G_cb_counter = 0
666    tree.select("ROOT", 0);
667    if G_cb_counter != 0:
668        fl_alert("FAILED 'OFF' TEST\n select(path) triggered cb!")
669    tree.deselect("ROOT") # leave deselected
670
671    # "ON" TEST
672
673    # open/close: Make sure these methods don't trigger cb
674    G_cb_counter = 0
675    tree.close(root, 1)
676    if G_cb_counter == 0:
677        fl_alert("FAILED 'ON' TEST\n close(item) cb wasn't triggered!")
678    G_cb_counter = 0
679    tree.open(root, 1)
680    if G_cb_counter == 0:
681        fl_alert("FAILED 'ON' TEST\n open(item) cb wasn't triggered!")
682    G_cb_counter = 0
683    tree.open_toggle(root, 1);
684    if G_cb_counter == 0:
685        fl_alert("FAILED 'ON' TEST\n open_toggle(item) cb wasn't triggered!")
686    G_cb_counter = 0
687    tree.open(root, 1)
688    if G_cb_counter == 0:
689        fl_alert("FAILED 'ON' TEST\n open(item)[2] cb wasn't triggered!")
690    G_cb_counter = 0
691    tree.close(root, 1)
692    if G_cb_counter == 0:
693        fl_alert("FAILED 'ON' TEST\n close(item)[2] cb wasn't triggered!")
694    G_cb_counter = 0
695    tree.open("ROOT", 1);
696    if G_cb_counter == 0:
697        fl_alert("FAILED 'ON' TEST\n open(path) cb wasn't triggered!")
698    G_cb_counter = 0
699    tree.close("ROOT", 1)
700    if G_cb_counter == 0:
701        fl_alert("FAILED 'ON' TEST\n close(path) cb wasn't triggered!")
702    tree.open(root,0)	# leave root open
703
704    # select/deselect: Make sure these methods don't trigger cb
705    G_cb_counter = 0
706    tree.select(root, 1)
707    if G_cb_counter == 0:
708        fl_alert("FAILED 'ON' TEST\n select(item) cb wasn't triggered!")
709    G_cb_counter = 0
710    tree.deselect(root, 1)
711    if G_cb_counter == 0:
712        fl_alert("FAILED 'ON' TEST\n deselect(item) cb wasn't triggered!")
713    G_cb_counter = 0
714    tree.select_toggle(root, 1)
715    if G_cb_counter == 0:
716        fl_alert("FAILED 'ON' TEST\n select_toggle(item) cb wasn't triggered!")
717    G_cb_counter = 0
718    tree.deselect("ROOT", 1)
719    if G_cb_counter == 0:
720        fl_alert("FAILED 'ON' TEST\n deselect(path) cb wasn't triggered!")
721    G_cb_counter = 0
722    tree.select("ROOT", 1)
723    if G_cb_counter == 0:
724        fl_alert("FAILED 'ON' TEST\n select(path) cb wasn't triggered!")
725    tree.deselect("ROOT")  # leave deselected
726
727    # "default" TEST (should be same as 'on'
728
729    # open/close: Make sure these methods don't trigger cb
730    G_cb_counter = 0
731    tree.close(root)
732    if G_cb_counter == 0:
733        fl_alert("FAILED 'DEFAULT' TEST: close(item) cb wasn't triggered!")
734    G_cb_counter = 0
735    tree.open(root)
736    if G_cb_counter == 0:
737        fl_alert("FAILED 'DEFAULT' TEST: open(item) cb wasn't triggered!")
738    G_cb_counter = 0
739    tree.open_toggle(root)
740    if G_cb_counter == 0:
741        fl_alert("FAILED 'DEFAULT' TEST: open_toggle(item) cb wasn't triggered!")
742    G_cb_counter = 0
743    tree.open("ROOT")
744    if G_cb_counter == 0:
745        fl_alert("FAILED 'DEFAULT' TEST: open(path) cb wasn't triggered!")
746    G_cb_counter = 0
747    tree.close("ROOT")
748    if G_cb_counter == 0:
749        fl_alert("FAILED 'DEFAULT' TEST: close(path) cb wasn't triggered!")
750    tree.open(root,0)	# leave root open
751
752    # select/deselect: Make sure these methods don't trigger cb
753    G_cb_counter = 0
754    tree.select(root)
755    if G_cb_counter == 0:
756        fl_alert("FAILED 'DEFAULT' TEST\n select(item) cb wasn't triggered!")
757    G_cb_counter = 0
758    tree.deselect(root)
759    if G_cb_counter == 0:
760        fl_alert("FAILED 'DEFAULT' TEST\n deselect(item) cb wasn't triggered!")
761    G_cb_counter = 0
762    tree.select_toggle(root)
763    if G_cb_counter == 0:
764        fl_alert("FAILED 'DEFAULT' TEST\n select_toggle(item) cb wasn't triggered!")
765    G_cb_counter = 0
766    tree.deselect("ROOT")
767    if G_cb_counter == 0:
768        fl_alert("FAILED 'DEFAULT' TEST\n deselect(path) cb wasn't triggered!")
769    G_cb_counter = 0
770    tree.select("ROOT")
771    if G_cb_counter == 0:
772        fl_alert("FAILED 'DEFAULT' TEST\n select(path) cb wasn't triggered!")
773    tree.deselect("ROOT") # leave deselected
774
775    fl_alert("TEST COMPLETED\n If you didn't see any error dialogs, test PASSED.")
776
777if __name__ == '__main__':
778    window = Fl_Double_Window(580, 695, "tree")
779
780    # tree
781    tree = Fl_Tree(15, 15, 550, 390)
782    tree.box(FL_DOWN_BOX)
783    tree.color(55)
784    tree.selection_color(FL_BACKGROUND_COLOR)
785    tree.labeltype(FL_NORMAL_LABEL)
786    tree.labelfont(0)
787    tree.labelsize(14)
788    tree.labelcolor(FL_FOREGROUND_COLOR)
789    tree.callback(cb_tree, 1234)
790    tree.align(FL_ALIGN_TOP)
791    tree.when(FL_WHEN_RELEASE)
792    tree.end()
793
794    # margintop_slider
795    margintop_slider = Fl_Value_Slider(190, 414, 240, 16, "margintop()")
796    margintop_slider.tooltip("Changes the top margin for the tree widget")
797    margintop_slider.type(1)
798    margintop_slider.labelsize(12)
799    margintop_slider.step(0.01)
800    margintop_slider.textsize(12)
801    margintop_slider.callback(cb_margintop_slider, tree)
802    margintop_slider.align(FL_ALIGN_LEFT)
803    margintop_slider.value(tree.margintop())
804    margintop_slider.range(0.0, 100.0)
805    margintop_slider.step(1.0)
806    margintop_slider.color(46)
807    margintop_slider.selection_color(FL_RED)
808
809    # marginleft_slider
810    marginleft_slider = Fl_Value_Slider(190, 434, 240, 16, "marginleft()")
811    marginleft_slider.tooltip("Changes the left margin for the tree widget")
812    marginleft_slider.type(1)
813    marginleft_slider.labelsize(12)
814    marginleft_slider.step(0.01)
815    marginleft_slider.textsize(12)
816    marginleft_slider.callback(cb_marginleft_slider, tree)
817    marginleft_slider.align(FL_ALIGN_LEFT)
818    marginleft_slider.value(tree.marginleft())
819    marginleft_slider.range(0.0, 100.0)
820    marginleft_slider.step(1.0)
821    marginleft_slider.color(46)
822    marginleft_slider.selection_color(FL_RED)
823
824    # openchild_marginbottom_slider
825    openchild_marginbottom_slider = Fl_Value_Slider(190, 454, 240, 16, "openchild_marginbottom()")
826    openchild_marginbottom_slider.tooltip("Changes the vertical space below an open child tree")
827    openchild_marginbottom_slider.type(1)
828    openchild_marginbottom_slider.labelsize(12)
829    openchild_marginbottom_slider.step(0.01)
830    openchild_marginbottom_slider.textsize(12)
831    openchild_marginbottom_slider.callback(cb_openchild_marginbottom_slider, tree)
832    openchild_marginbottom_slider.align(FL_ALIGN_LEFT)
833    openchild_marginbottom_slider.value(tree.openchild_marginbottom())
834    openchild_marginbottom_slider.range(0.0, 100.0)
835    openchild_marginbottom_slider.step(1.0)
836    openchild_marginbottom_slider.color(46)
837    openchild_marginbottom_slider.selection_color(FL_RED)
838
839    # labelsize_slider
840    labelsize_slider = Fl_Value_Slider(190, 474, 240, 16, "Text size")
841    labelsize_slider.tooltip("Changes the font size of the selected items\nIf none selected, all are changed")
842    labelsize_slider.type(1)
843    labelsize_slider.labelsize(12)
844    labelsize_slider.step(0.01)
845    labelsize_slider.textsize(12)
846    labelsize_slider.callback(cb_labelsize_slider, tree)
847    labelsize_slider.align(FL_ALIGN_LEFT)
848    labelsize_slider.value(tree.labelsize())
849    labelsize_slider.range(5.0, 200.0)
850    labelsize_slider.step(1.0)
851    labelsize_slider.color(46)
852    labelsize_slider.selection_color(FL_RED)
853
854    # connectorwidth_slider
855    connectorwidth_slider = Fl_Value_Slider(190, 494, 240, 16, "Connector width")
856    connectorwidth_slider.tooltip("Tests Fl_Tree::connectorwidth()")
857    connectorwidth_slider.type(1)
858    connectorwidth_slider.labelsize(12)
859    connectorwidth_slider.step(0.01)
860    connectorwidth_slider.textsize(12)
861    connectorwidth_slider.callback(cb_connectorwidth_slider, tree)
862    connectorwidth_slider.align(FL_ALIGN_LEFT)
863    connectorwidth_slider.value(tree.connectorwidth())
864    connectorwidth_slider.range(1.0, 100.0)
865    connectorwidth_slider.step(1.0)
866    connectorwidth_slider.color(46)
867    connectorwidth_slider.selection_color(FL_RED)
868
869    # usericon_radio
870    usericon_radio =  Fl_Check_Button(90, 525, 130, 16, "Enable user icons?")
871    usericon_radio.tooltip("Tests Fl_Tree_Item::usericon()")
872    usericon_radio.down_box(FL_DOWN_BOX)
873    usericon_radio.labelsize(11)
874    usericon_radio.callback(cb_usericon_radio, tree)
875
876    # showroot_radio
877    showroot_radio = Fl_Check_Button(90, 542, 130, 16, "Show root?")
878    showroot_radio.tooltip("Tests Fl_Tree_Item::usericon()")
879    showroot_radio.down_box(FL_DOWN_BOX)
880    showroot_radio.labelsize(11)
881    showroot_radio.callback(cb_showroot_radio, tree)
882    onoff = tree.showroot()
883    showroot_radio.value(onoff)
884
885    # visiblefocus_checkbox
886    visiblefocus_checkbox = Fl_Check_Button(90, 559, 130, 16, "Visible focus?")
887    visiblefocus_checkbox.tooltip("Toggles the tree\'s visible_focus()\nThis toggles the visible \'focus box\'")
888    visiblefocus_checkbox.down_box(FL_DOWN_BOX)
889    visiblefocus_checkbox.labelsize(11)
890    visiblefocus_checkbox.callback(cb_visiblefocus_checkbox, tree)
891    onoff = tree.visible_focus()
892    visiblefocus_checkbox.value(onoff)
893
894    # collapseicons_chooser
895    collapseicons_chooser = Fl_Choice(115, 589, 110, 16, "Collapse icons")
896    collapseicons_chooser.tooltip("Tests Fl_Tree::openicon() and Fl_Tree::closeicon()")
897    collapseicons_chooser.down_box(FL_BORDER_BOX)
898    collapseicons_chooser.labelsize(11)
899    collapseicons_chooser.textsize(11)
900    collapseicons_chooser.callback(cb_collapseicons_chooser, tree)
901    collapseicons_chooser.menu(menu_collapseicons_chooser)
902
903    # connectorstyle_chooser
904    connectorstyle_chooser = Fl_Choice(115, 609, 110, 16, "Line style")
905    connectorstyle_chooser.tooltip("Tests connectorstyle() bit flags")
906    connectorstyle_chooser.down_box(FL_BORDER_BOX)
907    connectorstyle_chooser.labelsize(11)
908    connectorstyle_chooser.textsize(11)
909    connectorstyle_chooser.callback(cb_connectorstyle_chooser, tree)
910    connectorstyle_chooser.menu(menu_connectorstyle_chooser)
911    if tree.connectorstyle() == FL_TREE_CONNECTOR_NONE:
912        connectorstyle_chooser.value(0)
913    elif  tree.connectorstyle() == FL_TREE_CONNECTOR_DOTTED:
914        connectorstyle_chooser.value(1)
915    elif  tree.connectorstyle() == FL_TREE_CONNECTOR_SOLID:
916        connectorstyle_chooser.value(2)
917
918    # labelcolor_chooser
919    labelcolor_chooser = Fl_Choice(115, 629, 110, 16, "Item Text Color")
920    labelcolor_chooser.tooltip("Changes the label color for the selected items\nIf no items selected, all are\changed")
921    labelcolor_chooser.down_box(FL_BORDER_BOX)
922    labelcolor_chooser.labelsize(11)
923    labelcolor_chooser.textsize(11)
924    labelcolor_chooser.callback(cb_labelcolor_chooser, tree)
925    labelcolor_chooser.menu(menu_labelcolor_chooser)
926
927    # selectmode_chooser
928    selectmode_chooser = Fl_Choice(115, 649, 110, 16, "Selection Mode")
929    selectmode_chooser.tooltip("Sets how Fl_Tree handles mouse selection of tree items")
930    selectmode_chooser.down_box(FL_BORDER_BOX)
931    selectmode_chooser.labelsize(11)
932    selectmode_chooser.textsize(11)
933    selectmode_chooser.callback(cb_selectmode_chooser, tree)
934    selectmode_chooser.menu(menu_selectmode_chooser)
935    selectmode_chooser.value(1)
936    cb_selectmode_chooser(selectmode_chooser, tree)
937
938    # whenmode_chooser
939    whenmode_chooser = Fl_Choice(115, 669, 110, 16, "When")
940    whenmode_chooser.tooltip("Sets when() the tree\'s callback is invoked")
941    whenmode_chooser.down_box(FL_BORDER_BOX)
942    whenmode_chooser.labelsize(11)
943    whenmode_chooser.textsize(11)
944    whenmode_chooser.callback(cb_whenmode_chooser, tree)
945    whenmode_chooser.menu(menu_whenmode_chooser)
946    whenmode_chooser.value(1)
947    cb_whenmode_chooser(whenmode_chooser, tree)
948
949    # showitem_box
950    showitem_box = Fl_Box(480, 425, 70, 82, "show_item()\n")
951    showitem_box.box(FL_GTK_DOWN_BOX)
952    showitem_box.color(FL_DARK1)
953    showitem_box.labelsize(11)
954    showitem_box.align(FL_ALIGN_TOP)
955
956    show_btn = Fl_Button(495, 434, 40, 17, "Show")
957    show_btn.tooltip("Tests show_item() with no position specified.\nMakes the selected item visibl\e IF it is off-screen.\nNo change made if it is not off-screen.")
958    show_btn.labelsize(11)
959    show_btn.callback(cb_Show, tree)
960
961    top_btn = Fl_Button(495, 451, 40, 16, "Top")
962    top_btn.tooltip("Test show_item_top().\nScrolls selected item to the top of the display\n(only\ works if scrollbar showing)\nTo use:\n1) open \'500 items\'\n2) select item 0\010\n3) Hit Top/Mid/Bot")
963    top_btn.labelsize(11)
964    top_btn.callback(cb_Top, tree)
965
966    mid_btn = Fl_Button(495, 467, 40, 16, "Mid")
967    mid_btn.tooltip("Tests show_item_middle().\nScrolls the selected item to the middle of the dis\play\nTo use:\n  1) open \'500 items\'\n  2) select \'item 0010\'\n  3) Hit To\p/Mid/Bot")
968    mid_btn.labelsize(11)
969    mid_btn.callback(cb_Mid, tree)
970
971    bot_btn = Fl_Button(495, 483, 40, 16, "Bot")
972    bot_btn.tooltip("Tests show_item_bottom().\nScrolls the selected item to the bottom of the dis\play\nTo use:\n  1) open \'500 items\'\n  2) select \'item 0010\'\n  3) Hit To\p/Mid/Bot")
973    bot_btn.labelsize(11)
974    bot_btn.callback(cb_Bot, tree)
975
976    docallback_box = Fl_Box(245, 527, 320, 77, "Selection State Changes")
977    docallback_box.box(FL_GTK_DOWN_BOX)
978    docallback_box.color(FL_DARK1)
979    docallback_box.labelsize(12)
980    docallback_box.align(FL_ALIGN_TOP)
981
982    selectall_button = Fl_Button(260, 539, 75, 16, "Select All")
983    selectall_button.tooltip("Selects all items in the tree")
984    selectall_button.labelsize(9)
985    selectall_button.callback(cb_selectall_button, tree)
986
987    deselectall_button = Fl_Button(260, 559, 75, 16, "Deselect All")
988    deselectall_button.tooltip("Deselects all items in the tree")
989    deselectall_button.labelsize(9)
990    deselectall_button.callback(cb_deselectall_button, tree)
991
992    bbbselect_toggle = Fl_Light_Button(350, 540, 95, 15, " Select Bbb")
993    bbbselect_toggle.tooltip("Toggle selection of just the /Bbb item\n(Not children)")
994    bbbselect_toggle.selection_color(1)
995    bbbselect_toggle.labelsize(9)
996    bbbselect_toggle.callback(cb_bbbselect_toggle, tree)
997
998    bbbselect2_toggle = Fl_Light_Button(350, 560, 95, 15, " Select Bbb+")
999    bbbselect2_toggle.tooltip("Toggle selection of the /Bbb item and its children")
1000    bbbselect2_toggle.selection_color(1)
1001    bbbselect2_toggle.labelsize(9)
1002    bbbselect2_toggle.callback(cb_bbbselect2_toggle, tree)
1003
1004    bbbchild02select_toggle = Fl_Light_Button(350, 579, 95, 16, " Toggle child-02")
1005    bbbchild02select_toggle.tooltip("Toggle the single item /Bbb/child-02")
1006    bbbchild02select_toggle.selection_color(1)
1007    bbbchild02select_toggle.labelsize(9)
1008    bbbchild02select_toggle.callback(cb_bbbchild02select_toggle, tree)
1009
1010    rootselect_toggle = Fl_Light_Button(460, 540, 90, 15, "Select ROOT")
1011    rootselect_toggle.tooltip("Toggle selection of the ROOT item")
1012    rootselect_toggle.selection_color(1)
1013    rootselect_toggle.labelsize(9)
1014    rootselect_toggle.callback(cb_rootselect_toggle, tree)
1015
1016    rootselect2_toggle = Fl_Light_Button(460, 560, 90, 15, "Select ROOT+")
1017    rootselect2_toggle.tooltip("Toggle selection of the ROOT item and all children")
1018    rootselect2_toggle.selection_color(1)
1019    rootselect2_toggle.labelsize(9)
1020    rootselect2_toggle.callback(cb_rootselect2_toggle, tree)
1021
1022    deactivate_toggle = Fl_Light_Button(280, 634, 90, 16, " Deactivate")
1023    deactivate_toggle.tooltip("Toggle the deactivation state of the selected items.\nIf none are selected, a\ll are set.")
1024    deactivate_toggle.selection_color(1)
1025    deactivate_toggle.labelsize(9)
1026    deactivate_toggle.callback(cb_deactivate_toggle, tree)
1027
1028    bold_toggle = Fl_Light_Button(280, 654, 90, 16, " Bold Font")
1029    bold_toggle.tooltip("Toggles bold font for selected items\nIf nothing selected, all are changed")
1030    bold_toggle.selection_color(1)
1031    bold_toggle.labelsize(9)
1032    bold_toggle.callback(cb_bold_toggle, tree)
1033
1034    loaddb_button = Fl_Button(380, 614, 90, 16, "Load Database...")
1035    loaddb_button.tooltip("Load the contents of an Fl_Preferences database into the tree view")
1036    loaddb_button.labelsize(9)
1037    loaddb_button.callback(cb_loaddb_button, tree)
1038
1039    insertabove_button = Fl_Button(380, 634, 90, 16, "Insert Above")
1040    insertabove_button.tooltip("Inserts three items above the selected items")
1041    insertabove_button.labelsize(9)
1042    insertabove_button.callback(cb_insertabove_button, tree)
1043
1044    rebuildtree_button = Fl_Button(380, 654, 90, 16, "Rebuild Tree")
1045    rebuildtree_button.tooltip("Rebuilds the tree with defaults")
1046    rebuildtree_button.labelsize(9)
1047    rebuildtree_button.callback(cb_rebuildtree_button, tree)
1048
1049    showpathname_button = Fl_Button(380, 674, 90, 16, "Show Pathname")
1050    showpathname_button.tooltip("Show the pathname for the selected item. Tests the Fl_Tree::item_pathname() m\ethod.")
1051    showpathname_button.labelsize(8)
1052    showpathname_button.callback(cb_showpathname_button, tree)
1053
1054    showselected_button = Fl_Button(475, 614, 90, 16, "Show Selected")
1055    showselected_button.tooltip("Clears the selected items")
1056    showselected_button.labelsize(9)
1057    showselected_button.callback(cb_showselected_button, tree)
1058
1059    clearselected_button = Fl_Button(475, 634, 90, 16, "Remove Selected")
1060    clearselected_button.tooltip("Removes the selected items")
1061    clearselected_button.labelsize(9)
1062    clearselected_button.callback(cb_clearselected_button, tree)
1063
1064    clearall_button = Fl_Button(475, 654, 90, 16, "Clear All")
1065    clearall_button.tooltip("Clears all items\nTests Fl_Tree::clear()")
1066    clearall_button.labelsize(9)
1067    clearall_button.callback(cb_clearall_button, tree)
1068
1069    testcallbackflag_button = Fl_Button(475, 674, 90, 16, "Test Callback Flag")
1070    testcallbackflag_button.tooltip("Test the \'docallback\' argument can disable callbacks.")
1071    testcallbackflag_button.labelsize(8)
1072    testcallbackflag_button.callback(cb_testcallbackflag_button, tree)
1073    window.end()
1074
1075    tree.root_label("ROOT")
1076    RebuildTree(tree)
1077
1078    window.resizable(window)
1079    window.size_range(window.w(), window.h(), 0, 0)
1080
1081    if tree.when() == FL_WHEN_CHANGED:
1082        whenmode_chooser.value(0)
1083    elif tree.when() == FL_WHEN_RELEASE:
1084        whenmode_chooser.value(1)
1085    elif tree.when() == FL_WHEN_NEVER:
1086        whenmode_chooser.value(2)
1087
1088    window.show(sys.argv)
1089
1090    Fl.run()
1091