arcadia 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. data/README +126 -123
  2. data/arcadia.rb +770 -756
  3. data/base/a-contracts.rb +130 -93
  4. data/base/a-ext.rb +280 -280
  5. data/base/a-libs.rb +5 -11
  6. data/base/a-utils.rb +235 -44
  7. data/conf/arcadia.conf +20 -16
  8. data/conf/arcadia.init.rb +0 -0
  9. data/conf/arcadia.res.rb +74 -0
  10. data/ext/ae-complete-code/ae-complete-code.conf +0 -0
  11. data/ext/ae-complete-code/ae-complete-code.rb +80 -79
  12. data/ext/ae-debug/ae-debug.conf +0 -0
  13. data/ext/ae-debug/ae-debug.rb +2 -6
  14. data/ext/ae-debug/debug1.57.rb +0 -0
  15. data/ext/ae-doc-code/ae-doc-code.conf +15 -0
  16. data/ext/ae-doc-code/ae-doc-code.rb +289 -0
  17. data/ext/ae-editor/ae-editor.conf +17 -8
  18. data/ext/ae-editor/ae-editor.rb +738 -396
  19. data/ext/ae-event-log/ae-event-log.conf +0 -0
  20. data/ext/ae-event-log/ae-event-log.rb +0 -0
  21. data/ext/ae-file-history/ae-file-history.conf +2 -2
  22. data/ext/ae-file-history/ae-file-history.rb +286 -290
  23. data/ext/ae-inspector/ae-inspector.conf +0 -0
  24. data/ext/ae-inspector/ae-inspector.rb +0 -0
  25. data/ext/ae-output-event/ae-output-event.conf +2 -2
  26. data/ext/ae-output/ae-output.conf +2 -2
  27. data/ext/ae-output/ae-output.rb +173 -178
  28. data/ext/ae-palette/ae-palette.conf +0 -0
  29. data/ext/ae-palette/ae-palette.rb +0 -0
  30. data/ext/ae-shell/ae-shell.conf +0 -0
  31. data/ext/ae-shell/ae-shell.rb +54 -54
  32. data/lib/tk/al-tk.rb +3076 -3082
  33. data/lib/tk/al-tk.res.rb +0 -0
  34. data/lib/tk/al-tkarcadia.rb +0 -0
  35. data/lib/tk/al-tkcustom.rb +0 -0
  36. data/lib/tkext/al-bwidget.rb +0 -0
  37. data/lib/tkext/al-iwidgets.rb +0 -0
  38. data/lib/tkext/al-tile.rb +0 -0
  39. data/lib/tkext/al-tktable.rb +0 -0
  40. data/tcl/BWidget-1.8.0/BWman/ArrowButton.html +276 -0
  41. data/tcl/BWidget-1.8.0/BWman/BWidget.html +228 -0
  42. data/tcl/BWidget-1.8.0/BWman/Button.html +273 -0
  43. data/tcl/BWidget-1.8.0/BWman/ButtonBox.html +264 -0
  44. data/tcl/BWidget-1.8.0/BWman/ComboBox.html +402 -0
  45. data/tcl/BWidget-1.8.0/BWman/Dialog.html +314 -0
  46. data/tcl/BWidget-1.8.0/BWman/DragSite.html +139 -0
  47. data/tcl/BWidget-1.8.0/BWman/DropSite.html +254 -0
  48. data/tcl/BWidget-1.8.0/BWman/DynamicHelp.html +248 -0
  49. data/tcl/BWidget-1.8.0/BWman/Entry.html +341 -0
  50. data/tcl/BWidget-1.8.0/BWman/Label.html +331 -0
  51. data/tcl/BWidget-1.8.0/BWman/LabelEntry.html +194 -0
  52. data/tcl/BWidget-1.8.0/BWman/LabelFrame.html +144 -0
  53. data/tcl/BWidget-1.8.0/BWman/ListBox.html +678 -0
  54. data/tcl/BWidget-1.8.0/BWman/MainFrame.html +283 -0
  55. data/tcl/BWidget-1.8.0/BWman/MessageDlg.html +218 -0
  56. data/tcl/BWidget-1.8.0/BWman/NoteBook.html +374 -0
  57. data/tcl/BWidget-1.8.0/BWman/PagesManager.html +180 -0
  58. data/tcl/BWidget-1.8.0/BWman/PanedWindow.html +142 -0
  59. data/tcl/BWidget-1.8.0/BWman/PanelFrame.html +153 -0
  60. data/tcl/BWidget-1.8.0/BWman/PasswdDlg.html +214 -0
  61. data/tcl/BWidget-1.8.0/BWman/ProgressBar.html +152 -0
  62. data/tcl/BWidget-1.8.0/BWman/ProgressDlg.html +145 -0
  63. data/tcl/BWidget-1.8.0/BWman/ScrollView.html +130 -0
  64. data/tcl/BWidget-1.8.0/BWman/ScrollableFrame.html +191 -0
  65. data/tcl/BWidget-1.8.0/BWman/ScrolledWindow.html +116 -0
  66. data/tcl/BWidget-1.8.0/BWman/SelectColor.html +164 -0
  67. data/tcl/BWidget-1.8.0/BWman/SelectFont.html +152 -0
  68. data/tcl/BWidget-1.8.0/BWman/Separator.html +77 -0
  69. data/tcl/BWidget-1.8.0/BWman/SpinBox.html +250 -0
  70. data/tcl/BWidget-1.8.0/BWman/StatusBar.html +147 -0
  71. data/tcl/BWidget-1.8.0/BWman/TitleFrame.html +107 -0
  72. data/tcl/BWidget-1.8.0/BWman/Tree.html +947 -0
  73. data/tcl/BWidget-1.8.0/BWman/Widget.html +502 -0
  74. data/tcl/BWidget-1.8.0/BWman/contents.html +84 -0
  75. data/tcl/BWidget-1.8.0/BWman/index.html +7 -0
  76. data/tcl/BWidget-1.8.0/BWman/navtree.html +41 -0
  77. data/tcl/BWidget-1.8.0/BWman/options.htm +458 -0
  78. data/tcl/BWidget-1.8.0/CHANGES.txt +266 -0
  79. data/tcl/BWidget-1.8.0/ChangeLog +1641 -0
  80. data/tcl/BWidget-1.8.0/LICENSE.txt +41 -0
  81. data/tcl/BWidget-1.8.0/README.txt +127 -0
  82. data/tcl/BWidget-1.8.0/arrow.tcl +551 -0
  83. data/tcl/BWidget-1.8.0/bitmap.tcl +94 -0
  84. data/tcl/BWidget-1.8.0/button.tcl +324 -0
  85. data/tcl/BWidget-1.8.0/buttonbox.tcl +403 -0
  86. data/tcl/BWidget-1.8.0/color.tcl +493 -0
  87. data/tcl/BWidget-1.8.0/combobox.tcl +809 -0
  88. data/tcl/BWidget-1.8.0/demo/basic.tcl +199 -0
  89. data/tcl/BWidget-1.8.0/demo/bwidget.xbm +46 -0
  90. data/tcl/BWidget-1.8.0/demo/demo.tcl +212 -0
  91. data/tcl/BWidget-1.8.0/demo/dnd.tcl +42 -0
  92. data/tcl/BWidget-1.8.0/demo/manager.tcl +141 -0
  93. data/tcl/BWidget-1.8.0/demo/select.tcl +59 -0
  94. data/tcl/BWidget-1.8.0/demo/tmpldlg.tcl +214 -0
  95. data/tcl/BWidget-1.8.0/demo/tree.tcl +260 -0
  96. data/tcl/BWidget-1.8.0/demo/x1.xbm +2258 -0
  97. data/tcl/BWidget-1.8.0/dialog.tcl +345 -0
  98. data/tcl/BWidget-1.8.0/dragsite.tcl +197 -0
  99. data/tcl/BWidget-1.8.0/dropsite.tcl +455 -0
  100. data/tcl/BWidget-1.8.0/dynhelp.tcl +625 -0
  101. data/tcl/BWidget-1.8.0/entry.tcl +469 -0
  102. data/tcl/BWidget-1.8.0/font.tcl +566 -0
  103. data/tcl/BWidget-1.8.0/images/bold.gif +0 -0
  104. data/tcl/BWidget-1.8.0/images/copy.gif +0 -0
  105. data/tcl/BWidget-1.8.0/images/cut.gif +0 -0
  106. data/tcl/BWidget-1.8.0/images/dragfile.gif +0 -0
  107. data/tcl/BWidget-1.8.0/images/dragicon.gif +0 -0
  108. data/tcl/BWidget-1.8.0/images/error.gif +0 -0
  109. data/tcl/BWidget-1.8.0/images/file.gif +0 -0
  110. data/tcl/BWidget-1.8.0/images/folder.gif +0 -0
  111. data/tcl/BWidget-1.8.0/images/hourglass.gif +0 -0
  112. data/tcl/BWidget-1.8.0/images/info.gif +0 -0
  113. data/tcl/BWidget-1.8.0/images/italic.gif +0 -0
  114. data/tcl/BWidget-1.8.0/images/minus.xbm +5 -0
  115. data/tcl/BWidget-1.8.0/images/new.gif +0 -0
  116. data/tcl/BWidget-1.8.0/images/opcopy.xbm +5 -0
  117. data/tcl/BWidget-1.8.0/images/open.gif +0 -0
  118. data/tcl/BWidget-1.8.0/images/openfold.gif +0 -0
  119. data/tcl/BWidget-1.8.0/images/oplink.xbm +5 -0
  120. data/tcl/BWidget-1.8.0/images/opmove.xbm +5 -0
  121. data/tcl/BWidget-1.8.0/images/overstrike.gif +0 -0
  122. data/tcl/BWidget-1.8.0/images/palette.gif +0 -0
  123. data/tcl/BWidget-1.8.0/images/passwd.gif +0 -0
  124. data/tcl/BWidget-1.8.0/images/paste.gif +0 -0
  125. data/tcl/BWidget-1.8.0/images/plus.xbm +5 -0
  126. data/tcl/BWidget-1.8.0/images/print.gif +0 -0
  127. data/tcl/BWidget-1.8.0/images/question.gif +0 -0
  128. data/tcl/BWidget-1.8.0/images/redo.gif +0 -0
  129. data/tcl/BWidget-1.8.0/images/save.gif +0 -0
  130. data/tcl/BWidget-1.8.0/images/target.xbm +9 -0
  131. data/tcl/BWidget-1.8.0/images/underline.gif +0 -0
  132. data/tcl/BWidget-1.8.0/images/undo.gif +0 -0
  133. data/tcl/BWidget-1.8.0/images/warning.gif +0 -0
  134. data/tcl/BWidget-1.8.0/init.tcl +40 -0
  135. data/tcl/BWidget-1.8.0/label.tcl +271 -0
  136. data/tcl/BWidget-1.8.0/labelentry.tcl +100 -0
  137. data/tcl/BWidget-1.8.0/labelframe.tcl +160 -0
  138. data/tcl/BWidget-1.8.0/lang/da.rc +52 -0
  139. data/tcl/BWidget-1.8.0/lang/de.rc +52 -0
  140. data/tcl/BWidget-1.8.0/lang/en.rc +52 -0
  141. data/tcl/BWidget-1.8.0/lang/es.rc +53 -0
  142. data/tcl/BWidget-1.8.0/lang/fr.rc +52 -0
  143. data/tcl/BWidget-1.8.0/listbox.tcl +1638 -0
  144. data/tcl/BWidget-1.8.0/mainframe.tcl +711 -0
  145. data/tcl/BWidget-1.8.0/messagedlg.tcl +128 -0
  146. data/tcl/BWidget-1.8.0/notebook.tcl +1164 -0
  147. data/tcl/BWidget-1.8.0/pagesmgr.tcl +294 -0
  148. data/tcl/BWidget-1.8.0/panedw.tcl +381 -0
  149. data/tcl/BWidget-1.8.0/panelframe.tcl +246 -0
  150. data/tcl/BWidget-1.8.0/passwddlg.tcl +178 -0
  151. data/tcl/BWidget-1.8.0/pkgIndex.tcl +47 -0
  152. data/tcl/BWidget-1.8.0/progressbar.tcl +208 -0
  153. data/tcl/BWidget-1.8.0/progressdlg.tcl +87 -0
  154. data/tcl/BWidget-1.8.0/scrollframe.tcl +226 -0
  155. data/tcl/BWidget-1.8.0/scrollview.tcl +254 -0
  156. data/tcl/BWidget-1.8.0/scrollw.tcl +280 -0
  157. data/tcl/BWidget-1.8.0/separator.tcl +75 -0
  158. data/tcl/BWidget-1.8.0/spinbox.tcl +331 -0
  159. data/tcl/BWidget-1.8.0/statusbar.tcl +422 -0
  160. data/tcl/BWidget-1.8.0/tests/entry.test +173 -0
  161. data/tcl/BWidget-1.8.0/titleframe.tcl +170 -0
  162. data/tcl/BWidget-1.8.0/tree.tcl +2228 -0
  163. data/tcl/BWidget-1.8.0/utils.tcl +645 -0
  164. data/tcl/BWidget-1.8.0/widget.tcl +1576 -0
  165. data/tcl/BWidget-1.8.0/wizard.tcl +1028 -0
  166. data/tcl/BWidget-1.8.0/xpm2image.tcl +115 -0
  167. metadata +141 -5
@@ -0,0 +1,173 @@
1
+ if { [lsearch [package names] tcltest] == -1 } {
2
+ package require tcltest
3
+ namespace import tcltest::*
4
+ }
5
+ lappend auto_path /home/ericm/bwidget
6
+ package require BWidget
7
+
8
+ option add *Entry.borderWidth 2
9
+ option add *Entry.highlightThickness 2
10
+ option add *Entry.font {Helvetica -12}
11
+ option add *Entry.relief sunken
12
+
13
+ Entry .e
14
+ pack .e
15
+ update
16
+ set i 0
17
+ foreach test {
18
+ {-background #ff0000 #ff0000 non-existent \
19
+ {unknown color name "non-existent"}}
20
+ {-bd 4 4 bad Value {bad screen distance "badValue"}}
21
+ {-bg #ff0000 #ff0000 non-existent {unknown color name "non-existent"}}
22
+ {-borderwidth 1.3 1 badValue {bad screen distance "badValue"}}
23
+ {-command foo foo {} {}}
24
+ {-disabledforeground blue blue non-existent \
25
+ {unknown color name "non-existent"}}
26
+ {-editable false false shazbot {expected boolean value but got "shazbot"}}
27
+ {-exportselection yes 1 xyzzy {expected boolean value but got "xyzzy"}}
28
+ {-fg #110022 #110022 bogus {unknown color name "bogus"}}
29
+ {-font {Helvetica 12 italic} {Helvetica 12 italic} {} \
30
+ {font "" doesn't exist}}
31
+ {-foreground #110022 #110022 bogus {unknown color name "bogus"}}
32
+ {-highlightbackground #123456 #123456 ugly {unknown color name "ugly"}}
33
+ {-highlightcolor #123456 #123456 bogus {unknown color name "bogus"}}
34
+ {-highlightthickness 6 6 bogus {bad screen distance "bogus"}}
35
+ {-highlightthickness -2 0 {} {}}
36
+ {-insertbackground #110022 #110022 bogus {unknown color name "bogus"}}
37
+ {-insertborderwidth 1.3 1 2.6x {bad screen distance "2.6x"}}
38
+ {-insertofftime 100 100 3.2 {expected integer but got "3.2"}}
39
+ {-insertontime 100 100 3.2 {expected integer but got "3.2"}}
40
+ {-justify right right bogus \
41
+ {bad justification "bogus": must be left, right, or center}}
42
+ {-relief groove groove 1.5 \
43
+ {bad relief "1.5": must be flat, groove, raised, ridge,\
44
+ solid, or sunken}}
45
+ {-selectbackground #110022 #110022 bogus {unknown color name "bogus"}}
46
+ {-selectborderwidth 1.3 1 badValue {bad screen distance "badValue"}}
47
+ {-selectforeground #654321 #654321 bogus {unknown color name "bogus"}}
48
+ {-show * * {} {}}
49
+ {-state normal normal bogus \
50
+ {bad state "bogus": must be disabled or normal}}
51
+ {-takefocus "any string" "any string" {} {}}
52
+ {-text foobar foobar {} {}}
53
+ {-textvariable i i {} {}}
54
+ {-width 402 402 3p {expected integer but got "3p"}}
55
+ {-xscrollcommand {Some command} {Some command} {} {}}
56
+ } {
57
+ set name [lindex $test 0]
58
+ test entry-1.$i {configuration options} {
59
+ .e configure $name [lindex $test 1]
60
+ list [lindex [.e configure $name] 4] [.e cget $name]
61
+ } [list [lindex $test 2] [lindex $test 2]]
62
+ incr i
63
+ }
64
+ destroy .e
65
+
66
+ test Entry-2.1 {Entry} {
67
+ list [catch {Entry} msg] $msg
68
+ } {1 {no value given for parameter "path" to "Entry"}}
69
+ test Entry-2.2 {Entry} {
70
+ list [catch {Entry gorp} msg] $msg
71
+ } {1 {bad window path name "gorp"}}
72
+ test Entry-2.3 {Entry procedure} {
73
+ Entry .e
74
+ set res [list [winfo exists .e] [winfo class .e] [info commands .e]]
75
+ destroy .e
76
+ set res
77
+ } {1 Entry .e}
78
+ test Entry-2.4 {Entr procedure} {
79
+ list [catch {Entry .e -gorp foo} msg] $msg [winfo exists .e] \
80
+ [info commands .e]
81
+ } {1 {unknown option "-gorp"} 0 {}}
82
+
83
+ test Entry-3.1 {disabled state grays widget} {
84
+ Entry .e -disabledforeground blue -foreground red -state normal
85
+ set res [list [.e cget -foreground] [.e cget -disabledforeground] \
86
+ [.e:cmd cget -foreground]]
87
+ .e configure -state disabled
88
+ lappend res [.e:cmd cget -foreground]
89
+ .e configure -state normal
90
+ lappend res [.e:cmd cget -foreground]
91
+ destroy .e
92
+ set res
93
+ } {red blue red blue red}
94
+ test Entry-3.2 {changing disabledforeground of an enabled entry} {
95
+ Entry .e -disabledforeground blue -foreground red -state normal
96
+ set res [list [.e cget -foreground] [.e cget -disabledforeground] \
97
+ [.e:cmd cget -foreground]]
98
+ .e configure -disabledforeground green
99
+ lappend res [.e:cmd cget -foreground]
100
+ destroy .e
101
+ set res
102
+ } {red blue red red}
103
+ test Entry-3.3 {changing normal foreground of a disabled entry} {
104
+ Entry .e -disabledforeground blue -foreground red -state disabled
105
+ set res [list [.e cget -foreground] [.e cget -disabledforeground] \
106
+ [.e:cmd cget -foreground]]
107
+ .e configure -foreground green
108
+ lappend res [.e:cmd cget -foreground]
109
+ destroy .e
110
+ set res
111
+ } {red blue blue blue}
112
+ test Entry-3.4 {changing disabled foreground of a disabled entry} {
113
+ Entry .e -disabledforeground blue -foreground red -state disabled
114
+ set res [list [.e cget -foreground] [.e cget -disabledforeground] \
115
+ [.e:cmd cget -foreground]]
116
+ .e configure -disabledforeground green
117
+ lappend res [.e:cmd cget -foreground]
118
+ destroy .e
119
+ set res
120
+ } {red blue blue green}
121
+
122
+ test Entry-4.1 {editable flag enables/disables editing} {
123
+ Entry .e -editable true
124
+ set res [expr {[lsearch [bindtags .e] BwDisabledEntry] == -1}]
125
+ .e configure -editable false
126
+ lappend res [expr {[lsearch [bindtags .e] BwDisabledEntry] != -1}]
127
+ destroy .e
128
+ set res
129
+ } {1 1}
130
+ test Entry-4.2 {editable flag does not impact foreground color} {
131
+ Entry .e -editable 1 -foreground red -disabledforeground blue -state normal
132
+ set res [list [.e:cmd cget -foreground]]
133
+ .e configure -editable false
134
+ lappend res [.e:cmd cget -foreground]
135
+ destroy .e
136
+ set res
137
+ } {red red}
138
+ test Entry-4.3 {editable flag changes cursor} {
139
+ Entry .e -editable 1
140
+ set res [list [.e:cmd cget -cursor]]
141
+ .e configure -editable 0
142
+ lappend res [.e:cmd cget -cursor]
143
+ destroy .e
144
+ set res
145
+ } [list xterm left_ptr]
146
+
147
+ test Entry-5.1 {-text flag gets entry text} {
148
+ Entry .e
149
+ .e delete 0 end
150
+ .e insert end foobar
151
+ set res [.e cget -text]
152
+ destroy .e
153
+ set res
154
+ } foobar
155
+ test Entry-5.2 {-text flag sets entry text} {
156
+ Entry .e
157
+ .e delete 0 end
158
+ .e configure -text barbaz
159
+ set res [.e get]
160
+ destroy .e
161
+ set res
162
+ } barbaz
163
+
164
+ test Entry-6.1 {-command works} {
165
+ set ::foo 0
166
+ Entry .e -command {incr ::foo}
167
+ Entry::invoke .e
168
+ destroy .e
169
+ set ::foo
170
+ } 1
171
+
172
+ tcltest::cleanupTests
173
+ exit
@@ -0,0 +1,170 @@
1
+ # ------------------------------------------------------------------------------
2
+ # titleframe.tcl
3
+ # This file is part of Unifix BWidget Toolkit
4
+ # ------------------------------------------------------------------------------
5
+ # Index of commands:
6
+ # - TitleFrame::create
7
+ # - TitleFrame::configure
8
+ # - TitleFrame::cget
9
+ # - TitleFrame::getframe
10
+ # - TitleFrame::_place
11
+ # ------------------------------------------------------------------------------
12
+
13
+ namespace eval TitleFrame {
14
+ Widget::define TitleFrame titleframe
15
+
16
+ Widget::declare TitleFrame {
17
+ {-relief TkResource groove 0 frame}
18
+ {-borderwidth TkResource 2 0 frame}
19
+ {-font TkResource "" 0 label}
20
+ {-foreground TkResource "" 0 label}
21
+ {-state TkResource "" 0 label}
22
+ {-background TkResource "" 0 frame}
23
+ {-text String "" 0}
24
+ {-ipad Int 4 0 "%d >=0"}
25
+ {-side Enum left 0 {left center right}}
26
+ {-baseline Enum center 0 {top center bottom}}
27
+ {-fg Synonym -foreground}
28
+ {-bg Synonym -background}
29
+ {-bd Synonym -borderwidth}
30
+ }
31
+
32
+ Widget::addmap TitleFrame "" :cmd {-background {}}
33
+ Widget::addmap TitleFrame "" .l {
34
+ -background {} -foreground {} -text {} -font {}
35
+ }
36
+ Widget::addmap TitleFrame "" .l {-state {}}
37
+ Widget::addmap TitleFrame "" .p {-background {}}
38
+ Widget::addmap TitleFrame "" .b {
39
+ -background {} -relief {} -borderwidth {}
40
+ }
41
+ Widget::addmap TitleFrame "" .b.p {-background {}}
42
+ Widget::addmap TitleFrame "" .f {-background {}}
43
+ }
44
+
45
+
46
+ # ------------------------------------------------------------------------------
47
+ # Command TitleFrame::create
48
+ # ------------------------------------------------------------------------------
49
+ proc TitleFrame::create { path args } {
50
+ Widget::init TitleFrame $path $args
51
+
52
+ set frame [eval [list frame $path] [Widget::subcget $path :cmd] \
53
+ -class TitleFrame -relief flat -bd 0 -highlightthickness 0]
54
+
55
+ set padtop [eval [list frame $path.p] [Widget::subcget $path :cmd] \
56
+ -relief flat -borderwidth 0]
57
+ set border [eval [list frame $path.b] [Widget::subcget $path .b] -highlightthickness 0]
58
+ set label [eval [list label $path.l] [Widget::subcget $path .l] \
59
+ -highlightthickness 0 \
60
+ -relief flat \
61
+ -bd 0 -padx 2 -pady 0]
62
+ set padbot [eval [list frame $border.p] [Widget::subcget $path .p] \
63
+ -relief flat -bd 0 -highlightthickness 0]
64
+ set frame [eval [list frame $path.f] [Widget::subcget $path .f] \
65
+ -relief flat -bd 0 -highlightthickness 0]
66
+ set height [winfo reqheight $label]
67
+
68
+ switch [Widget::getoption $path -side] {
69
+ left { set relx 0.0; set x 5; set anchor nw }
70
+ center { set relx 0.5; set x 0; set anchor n }
71
+ right { set relx 1.0; set x -5; set anchor ne }
72
+ }
73
+ set bd [Widget::getoption $path -borderwidth]
74
+ switch [Widget::getoption $path -baseline] {
75
+ top {
76
+ set y 0
77
+ set htop $height
78
+ set hbot 1
79
+ }
80
+ center {
81
+ set y 0
82
+ set htop [expr {$height/2}]
83
+ set hbot [expr {$height/2+$height%2+1}]
84
+ }
85
+ bottom {
86
+ set y [expr {$bd+1}]
87
+ set htop 1
88
+ set hbot $height
89
+ }
90
+ }
91
+ $padtop configure -height $htop
92
+ $padbot configure -height $hbot
93
+
94
+ set pad [Widget::getoption $path -ipad]
95
+ pack $padbot -side top -fill x
96
+ pack $frame -in $border -fill both -expand yes -padx $pad -pady $pad
97
+
98
+ pack $padtop -side top -fill x
99
+ pack $border -fill both -expand yes
100
+
101
+ place $label -relx $relx -x $x -anchor $anchor -y $y
102
+
103
+ bind $label <Configure> [list TitleFrame::_place $path]
104
+ bind $path <Destroy> [list Widget::destroy %W]
105
+
106
+ return [Widget::create TitleFrame $path]
107
+ }
108
+
109
+
110
+ # ------------------------------------------------------------------------------
111
+ # Command TitleFrame::configure
112
+ # ------------------------------------------------------------------------------
113
+ proc TitleFrame::configure { path args } {
114
+ set res [Widget::configure $path $args]
115
+
116
+ if { [Widget::hasChanged $path -ipad pad] } {
117
+ pack configure $path.f -padx $pad -pady $pad
118
+ }
119
+ if { [Widget::hasChanged $path -borderwidth val] |
120
+ [Widget::hasChanged $path -font val] |
121
+ [Widget::hasChanged $path -side val] |
122
+ [Widget::hasChanged $path -baseline val] } {
123
+ _place $path
124
+ }
125
+
126
+ return $res
127
+ }
128
+
129
+
130
+ # ------------------------------------------------------------------------------
131
+ # Command TitleFrame::cget
132
+ # ------------------------------------------------------------------------------
133
+ proc TitleFrame::cget { path option } {
134
+ return [Widget::cget $path $option]
135
+ }
136
+
137
+
138
+ # ------------------------------------------------------------------------------
139
+ # Command TitleFrame::getframe
140
+ # ------------------------------------------------------------------------------
141
+ proc TitleFrame::getframe { path } {
142
+ return $path.f
143
+ }
144
+
145
+
146
+ # ------------------------------------------------------------------------------
147
+ # Command TitleFrame::_place
148
+ # ------------------------------------------------------------------------------
149
+ proc TitleFrame::_place { path } {
150
+ set height [winfo height $path.l]
151
+ switch [Widget::getoption $path -side] {
152
+ left { set relx 0.0; set x 10; set anchor nw }
153
+ center { set relx 0.5; set x 0; set anchor n }
154
+ right { set relx 1.0; set x -10; set anchor ne }
155
+ }
156
+ set bd [Widget::getoption $path -borderwidth]
157
+ switch [Widget::getoption $path -baseline] {
158
+ top { set htop $height; set hbot 1; set y 0 }
159
+ center { set htop [expr {$height/2}]; set hbot [expr {$height/2+$height%2+1}]; set y 0 }
160
+ bottom { set htop 1; set hbot $height; set y [expr {$bd+1}] }
161
+ }
162
+ $path.p configure -height $htop
163
+ $path.b.p configure -height $hbot
164
+
165
+ place $path.l -relx $relx -x $x -anchor $anchor -y $y
166
+ }
167
+
168
+
169
+
170
+
@@ -0,0 +1,2228 @@
1
+ # ----------------------------------------------------------------------------
2
+ # tree.tcl
3
+ # This file is part of Unifix BWidget Toolkit
4
+ # $Id: tree.tcl,v 1.54 2006/09/28 15:46:06 dev_null42a Exp $
5
+ # ----------------------------------------------------------------------------
6
+ # Index of commands:
7
+ # - Tree::create
8
+ # - Tree::configure
9
+ # - Tree::cget
10
+ # - Tree::insert
11
+ # - Tree::itemconfigure
12
+ # - Tree::itemcget
13
+ # - Tree::bindArea
14
+ # - Tree::bindText
15
+ # - Tree::bindImage
16
+ # - Tree::delete
17
+ # - Tree::move
18
+ # - Tree::reorder
19
+ # - Tree::selection
20
+ # - Tree::exists
21
+ # - Tree::parent
22
+ # - Tree::index
23
+ # - Tree::nodes
24
+ # - Tree::see
25
+ # - Tree::opentree
26
+ # - Tree::closetree
27
+ # - Tree::edit
28
+ # - Tree::xview
29
+ # - Tree::yview
30
+ # - Tree::_update_edit_size
31
+ # - Tree::_destroy
32
+ # - Tree::_see
33
+ # - Tree::_recexpand
34
+ # - Tree::_subdelete
35
+ # - Tree::_update_scrollregion
36
+ # - Tree::_cross_event
37
+ # - Tree::_draw_node
38
+ # - Tree::_draw_subnodes
39
+ # - Tree::_update_nodes
40
+ # - Tree::_draw_tree
41
+ # - Tree::_redraw_tree
42
+ # - Tree::_redraw_selection
43
+ # - Tree::_redraw_idle
44
+ # - Tree::_drag_cmd
45
+ # - Tree::_drop_cmd
46
+ # - Tree::_over_cmd
47
+ # - Tree::_auto_scroll
48
+ # - Tree::_scroll
49
+ # ----------------------------------------------------------------------------
50
+
51
+ namespace eval Tree {
52
+ Widget::define Tree tree DragSite DropSite DynamicHelp
53
+
54
+ namespace eval Node {
55
+ Widget::declare Tree::Node {
56
+ {-text String "" 0}
57
+ {-font TkResource "" 0 listbox}
58
+ {-image TkResource "" 0 label}
59
+ {-window String "" 0}
60
+ {-fill TkResource black 0 {listbox -foreground}}
61
+ {-data String "" 0}
62
+ {-open Boolean 0 0}
63
+ {-selectable Boolean 1 0}
64
+ {-drawcross Enum auto 0 {auto always never allways}}
65
+ {-padx Int -1 0 "%d >= -1"}
66
+ {-deltax Int -1 0 "%d >= -1"}
67
+ {-anchor String "w" 0 ""}
68
+ }
69
+ }
70
+
71
+ DynamicHelp::include Tree::Node balloon
72
+
73
+ Widget::tkinclude Tree canvas .c \
74
+ remove {
75
+ -insertwidth -insertbackground -insertborderwidth -insertofftime
76
+ -insertontime -selectborderwidth -closeenough -confine -scrollregion
77
+ -xscrollincrement -yscrollincrement -width -height
78
+ } \
79
+ initialize {
80
+ -relief sunken -borderwidth 2 -takefocus 1
81
+ -highlightthickness 1 -width 200
82
+ }
83
+
84
+ Widget::declare Tree {
85
+ {-deltax Int 10 0 "%d >= 0"}
86
+ {-deltay Int 15 0 "%d >= 0"}
87
+ {-padx Int 20 0 "%d >= 0"}
88
+ {-background TkResource "" 0 listbox}
89
+ {-selectbackground TkResource "" 0 listbox}
90
+ {-selectforeground TkResource "" 0 listbox}
91
+ {-selectcommand String "" 0}
92
+ {-width TkResource "" 0 listbox}
93
+ {-height TkResource "" 0 listbox}
94
+ {-selectfill Boolean 0 0}
95
+ {-showlines Boolean 1 0}
96
+ {-linesfill TkResource black 0 {listbox -foreground}}
97
+ {-linestipple TkResource "" 0 {label -bitmap}}
98
+ {-crossfill TkResource black 0 {listbox -foreground}}
99
+ {-redraw Boolean 1 0}
100
+ {-opencmd String "" 0}
101
+ {-closecmd String "" 0}
102
+ {-dropovermode Flag "wpn" 0 "wpn"}
103
+ {-bg Synonym -background}
104
+
105
+ {-crossopenimage String "" 0}
106
+ {-crosscloseimage String "" 0}
107
+ {-crossopenbitmap String "" 0}
108
+ {-crossclosebitmap String "" 0}
109
+ }
110
+
111
+ DragSite::include Tree "TREE_NODE" 1
112
+ DropSite::include Tree {
113
+ TREE_NODE {copy {} move {}}
114
+ }
115
+
116
+ Widget::addmap Tree "" .c {-deltay -yscrollincrement}
117
+
118
+ # Trees on windows have a white (system window) background
119
+ if { $::tcl_platform(platform) == "windows" } {
120
+ option add *Tree.c.background SystemWindow widgetDefault
121
+ option add *TreeNode.fill SystemWindowText widgetDefault
122
+ }
123
+
124
+ bind Tree <FocusIn> [list after idle {BWidget::refocus %W %W.c}]
125
+ bind Tree <Destroy> [list Tree::_destroy %W]
126
+ bind Tree <Configure> [list Tree::_update_scrollregion %W]
127
+
128
+
129
+ bind TreeSentinalStart <Button-1> {
130
+ if { $::Tree::sentinal(%W) } {
131
+ set ::Tree::sentinal(%W) 0
132
+ break
133
+ }
134
+ }
135
+
136
+ bind TreeSentinalEnd <Button-1> {
137
+ set ::Tree::sentinal(%W) 0
138
+ }
139
+
140
+ bind TreeFocus <Button-1> [list focus %W]
141
+
142
+ variable _edit
143
+ }
144
+
145
+
146
+ # ----------------------------------------------------------------------------
147
+ # Command Tree::create
148
+ # ----------------------------------------------------------------------------
149
+ proc Tree::create { path args } {
150
+ variable $path
151
+ upvar 0 $path data
152
+
153
+ Widget::init Tree $path $args
154
+ set ::Tree::sentinal($path.c) 0
155
+
156
+ if {[Widget::cget $path -crossopenbitmap] == ""} {
157
+ set file [file join $::BWIDGET::LIBRARY images "minus.xbm"]
158
+ Widget::configure $path [list -crossopenbitmap @$file]
159
+ }
160
+ if {[Widget::cget $path -crossclosebitmap] == ""} {
161
+ set file [file join $::BWIDGET::LIBRARY images "plus.xbm"]
162
+ Widget::configure $path [list -crossclosebitmap @$file]
163
+ }
164
+
165
+ set data(root) {{}}
166
+ set data(selnodes) {}
167
+ set data(upd,level) 0
168
+ set data(upd,nodes) {}
169
+ set data(upd,afterid) ""
170
+ set data(dnd,scroll) ""
171
+ set data(dnd,afterid) ""
172
+ set data(dnd,selnodes) {}
173
+ set data(dnd,node) ""
174
+
175
+ frame $path -class Tree -bd 0 -highlightthickness 0 -relief flat \
176
+ -takefocus 0
177
+ # For 8.4+ we don't want to inherit the padding
178
+ catch {$path configure -padx 0 -pady 0}
179
+ eval [list canvas $path.c] [Widget::subcget $path .c] -xscrollincrement 8
180
+ bindtags $path.c [list TreeSentinalStart TreeFocus $path.c Canvas \
181
+ [winfo toplevel $path] all TreeSentinalEnd]
182
+ pack $path.c -expand yes -fill both
183
+ $path.c bind cross <ButtonPress-1> [list Tree::_cross_event $path]
184
+
185
+ # Added by ericm@scriptics.com
186
+ # These allow keyboard traversal of the tree
187
+ bind $path.c <KeyPress-Up> [list Tree::_keynav up $path]
188
+ bind $path.c <KeyPress-Down> [list Tree::_keynav down $path]
189
+ bind $path.c <KeyPress-Right> [list Tree::_keynav right $path]
190
+ bind $path.c <KeyPress-Left> [list Tree::_keynav left $path]
191
+ bind $path.c <KeyPress-space> [list +Tree::_keynav space $path]
192
+
193
+ # These allow keyboard control of the scrolling
194
+ bind $path.c <Control-KeyPress-Up> [list $path.c yview scroll -1 units]
195
+ bind $path.c <Control-KeyPress-Down> [list $path.c yview scroll 1 units]
196
+ bind $path.c <Control-KeyPress-Left> [list $path.c xview scroll -1 units]
197
+ bind $path.c <Control-KeyPress-Right> [list $path.c xview scroll 1 units]
198
+ # ericm@scriptics.com
199
+
200
+ BWidget::bindMouseWheel $path.c
201
+
202
+ DragSite::setdrag $path $path.c Tree::_init_drag_cmd \
203
+ [Widget::cget $path -dragendcmd] 1
204
+ DropSite::setdrop $path $path.c Tree::_over_cmd Tree::_drop_cmd 1
205
+
206
+ Widget::create Tree $path
207
+
208
+ set w [Widget::cget $path -width]
209
+ set h [Widget::cget $path -height]
210
+ set dy [Widget::cget $path -deltay]
211
+ $path.c configure -width [expr {$w*8}] -height [expr {$h*$dy}]
212
+
213
+ # ericm
214
+ # Bind <Button-1> to select the clicked node -- no reason not to, right?
215
+
216
+ ## Bind button 1 to select the node via the _mouse_select command.
217
+ ## This command will generate the proper <<TreeSelect>> virtual event
218
+ ## when necessary.
219
+ set selectcmd Tree::_mouse_select
220
+ Tree::bindText $path <Button-1> [list $selectcmd $path set]
221
+ Tree::bindImage $path <Button-1> [list $selectcmd $path set]
222
+ Tree::bindText $path <Control-Button-1> [list $selectcmd $path toggle]
223
+ Tree::bindImage $path <Control-Button-1> [list $selectcmd $path toggle]
224
+
225
+ # Add sentinal bindings for double-clicking on items, to handle the
226
+ # gnarly Tk bug wherein:
227
+ # ButtonClick
228
+ # ButtonClick
229
+ # On a canvas item translates into button click on the item, button click
230
+ # on the canvas, double-button on the item, single button click on the
231
+ # canvas (which can happen if the double-button on the item causes some
232
+ # other event to be handled in between when the button clicks are examined
233
+ # for the canvas)
234
+ $path.c bind TreeItemSentinal <Double-Button-1> \
235
+ [list set ::Tree::sentinal($path.c) 1]
236
+ # ericm
237
+
238
+ return $path
239
+ }
240
+
241
+
242
+ # ----------------------------------------------------------------------------
243
+ # Command Tree::configure
244
+ # ----------------------------------------------------------------------------
245
+ proc Tree::configure { path args } {
246
+ variable $path
247
+ upvar 0 $path data
248
+
249
+ set res [Widget::configure $path $args]
250
+
251
+ set ch1 [expr {[Widget::hasChanged $path -deltax val] |
252
+ [Widget::hasChanged $path -deltay dy] |
253
+ [Widget::hasChanged $path -padx val] |
254
+ [Widget::hasChanged $path -showlines val]}]
255
+
256
+ set ch2 [expr {[Widget::hasChanged $path -selectbackground val] |
257
+ [Widget::hasChanged $path -selectforeground val]}]
258
+
259
+ if { [Widget::hasChanged $path -linesfill fill] |
260
+ [Widget::hasChanged $path -linestipple stipple] } {
261
+ $path.c itemconfigure line -fill $fill -stipple $stipple
262
+ }
263
+
264
+ if { [Widget::hasChanged $path -crossfill fill] } {
265
+ $path.c itemconfigure cross -foreground $fill
266
+ }
267
+
268
+ if {[Widget::hasChanged $path -selectfill fill]} {
269
+ # Make sure that the full-width boxes have either all or none
270
+ # of the standard node bindings
271
+ if {$fill} {
272
+ foreach event [$path.c bind "node"] {
273
+ $path.c bind "box" $event [$path.c bind "node" $event]
274
+ }
275
+ } else {
276
+ foreach event [$path.c bind "node"] {
277
+ $path.c bind "box" $event {}
278
+ }
279
+ }
280
+ }
281
+
282
+ if { $ch1 } {
283
+ _redraw_idle $path 3
284
+ } elseif { $ch2 } {
285
+ _redraw_idle $path 1
286
+ }
287
+
288
+ if { [Widget::hasChanged $path -height h] } {
289
+ $path.c configure -height [expr {$h*$dy}]
290
+ }
291
+ if { [Widget::hasChanged $path -width w] } {
292
+ $path.c configure -width [expr {$w*8}]
293
+ }
294
+
295
+ if { [Widget::hasChanged $path -redraw bool] && $bool } {
296
+ set upd $data(upd,level)
297
+ set data(upd,level) 0
298
+ _redraw_idle $path $upd
299
+ }
300
+
301
+ set force [Widget::hasChanged $path -dragendcmd dragend]
302
+ DragSite::setdrag $path $path.c Tree::_init_drag_cmd $dragend $force
303
+ DropSite::setdrop $path $path.c Tree::_over_cmd Tree::_drop_cmd
304
+
305
+ return $res
306
+ }
307
+
308
+
309
+ # ----------------------------------------------------------------------------
310
+ # Command Tree::cget
311
+ # ----------------------------------------------------------------------------
312
+ proc Tree::cget { path option } {
313
+ return [Widget::cget $path $option]
314
+ }
315
+
316
+
317
+ # ----------------------------------------------------------------------------
318
+ # Command Tree::insert
319
+ # ----------------------------------------------------------------------------
320
+ proc Tree::insert { path index parent node args } {
321
+ variable $path
322
+ upvar 0 $path data
323
+
324
+ set node [_node_name $path $node]
325
+ set node [Widget::nextIndex $path $node]
326
+
327
+ if { [info exists data($node)] } {
328
+ return -code error "node \"$node\" already exists"
329
+ }
330
+ if { ![info exists data($parent)] } {
331
+ return -code error "node \"$parent\" does not exist"
332
+ }
333
+
334
+ Widget::init Tree::Node $path.$node $args
335
+ if {[string equal $index "end"]} {
336
+ lappend data($parent) $node
337
+ } else {
338
+ incr index
339
+ set data($parent) [linsert $data($parent) $index $node]
340
+ }
341
+ set data($node) [list $parent]
342
+
343
+ if { [string equal $parent "root"] } {
344
+ _redraw_idle $path 3
345
+ } elseif { [visible $path $parent] } {
346
+ # parent is visible...
347
+ if { [Widget::getMegawidgetOption $path.$parent -open] } {
348
+ # ...and opened -> redraw whole
349
+ _redraw_idle $path 3
350
+ } else {
351
+ # ...and closed -> redraw cross
352
+ lappend data(upd,nodes) $parent 8
353
+ _redraw_idle $path 2
354
+ }
355
+ }
356
+
357
+ return $node
358
+ }
359
+
360
+
361
+ # ----------------------------------------------------------------------------
362
+ # Command Tree::itemconfigure
363
+ # ----------------------------------------------------------------------------
364
+ proc Tree::itemconfigure { path node args } {
365
+ variable $path
366
+ upvar 0 $path data
367
+
368
+ set node [_node_name $path $node]
369
+ if { [string equal $node "root"] || ![info exists data($node)] } {
370
+ return -code error "node \"$node\" does not exist"
371
+ }
372
+
373
+ set result [Widget::configure $path.$node $args]
374
+
375
+ _set_help $path $node
376
+
377
+ if { [visible $path $node] } {
378
+ set lopt {}
379
+ set flag 0
380
+ foreach opt {-window -image -drawcross -font -text -fill} {
381
+ set flag [expr {$flag << 1}]
382
+ if { [Widget::hasChanged $path.$node $opt val] } {
383
+ set flag [expr {$flag | 1}]
384
+ }
385
+ }
386
+
387
+ if { [Widget::hasChanged $path.$node -open val] } {
388
+ if {[llength $data($node)] > 1} {
389
+ # node have subnodes - full redraw
390
+ _redraw_idle $path 3
391
+ } else {
392
+ # force a redraw of the plus/minus sign
393
+ set flag [expr {$flag | 8}]
394
+ }
395
+ }
396
+
397
+ if {$data(upd,level) < 3 && [Widget::hasChanged $path.$node -padx x]} {
398
+ _redraw_idle $path 3
399
+ }
400
+
401
+ if { $data(upd,level) < 3 && $flag } {
402
+ if { [set idx [lsearch -exact $data(upd,nodes) $node]] == -1 } {
403
+ lappend data(upd,nodes) $node $flag
404
+ } else {
405
+ incr idx
406
+ set flag [expr {[lindex $data(upd,nodes) $idx] | $flag}]
407
+ set data(upd,nodes) [lreplace $data(upd,nodes) $idx $idx $flag]
408
+ }
409
+ _redraw_idle $path 2
410
+ }
411
+ }
412
+ return $result
413
+ }
414
+
415
+
416
+ # ----------------------------------------------------------------------------
417
+ # Command Tree::itemcget
418
+ # ----------------------------------------------------------------------------
419
+ proc Tree::itemcget { path node option } {
420
+ # Instead of upvar'ing $path as data for this test, just directly refer to
421
+ # it, as that is faster.
422
+ set node [_node_name $path $node]
423
+ if { [string equal $node "root"] || \
424
+ ![info exists ::Tree::${path}($node)] } {
425
+ return -code error "node \"$node\" does not exist"
426
+ }
427
+
428
+ return [Widget::cget $path.$node $option]
429
+ }
430
+
431
+ # ----------------------------------------------------------------------------
432
+ # Command Tree::bindArea
433
+ # ----------------------------------------------------------------------------
434
+ proc Tree::bindArea { path event script } {
435
+ bind $path.c $event $script
436
+ }
437
+
438
+ # ----------------------------------------------------------------------------
439
+ # Command Tree::bindText
440
+ # ----------------------------------------------------------------------------
441
+ proc Tree::bindText { path event script } {
442
+ if {[string length $script]} {
443
+ append script " \[Tree::_get_node_name [list $path] current 2\]"
444
+ }
445
+ $path.c bind "node" $event $script
446
+ if {[Widget::getoption $path -selectfill]} {
447
+ $path.c bind "box" $event $script
448
+ } else {
449
+ $path.c bind "box" $event {}
450
+ }
451
+ }
452
+
453
+
454
+ # ----------------------------------------------------------------------------
455
+ # Command Tree::bindImage
456
+ # ----------------------------------------------------------------------------
457
+ proc Tree::bindImage { path event script } {
458
+ if {[string length $script]} {
459
+ append script " \[Tree::_get_node_name [list $path] current 2\]"
460
+ }
461
+ $path.c bind "img" $event $script
462
+ if {[Widget::getoption $path -selectfill]} {
463
+ $path.c bind "box" $event $script
464
+ } else {
465
+ $path.c bind "box" $event {}
466
+ }
467
+ }
468
+
469
+
470
+ # ----------------------------------------------------------------------------
471
+ # Command Tree::delete
472
+ # ----------------------------------------------------------------------------
473
+ proc Tree::delete { path args } {
474
+ variable $path
475
+ upvar 0 $path data
476
+
477
+ set sel 0
478
+ foreach lnodes $args {
479
+ foreach node $lnodes {
480
+ set node [_node_name $path $node]
481
+ if { ![string equal $node "root"] && [info exists data($node)] } {
482
+ set parent [lindex $data($node) 0]
483
+ set idx [lsearch -exact $data($parent) $node]
484
+ set data($parent) [lreplace $data($parent) $idx $idx]
485
+ incr sel [_subdelete $path [list $node]]
486
+ }
487
+ }
488
+ }
489
+ if {$sel} {
490
+ # if selection changed, call the selectcommand
491
+ __call_selectcmd $path
492
+ }
493
+
494
+ _redraw_idle $path 3
495
+ }
496
+
497
+
498
+ # ----------------------------------------------------------------------------
499
+ # Command Tree::move
500
+ # ----------------------------------------------------------------------------
501
+ proc Tree::move { path parent node index } {
502
+ variable $path
503
+ upvar 0 $path data
504
+
505
+ set node [_node_name $path $node]
506
+ if { [string equal $node "root"] || ![info exists data($node)] } {
507
+ return -code error "node \"$node\" does not exist"
508
+ }
509
+ if { ![info exists data($parent)] } {
510
+ return -code error "node \"$parent\" does not exist"
511
+ }
512
+ set p $parent
513
+ while { ![string equal $p "root"] } {
514
+ if { [string equal $p $node] } {
515
+ return -code error "node \"$parent\" is a descendant of \"$node\""
516
+ }
517
+ set p [parent $path $p]
518
+ }
519
+
520
+ set oldp [lindex $data($node) 0]
521
+ set idx [lsearch -exact $data($oldp) $node]
522
+ set data($oldp) [lreplace $data($oldp) $idx $idx]
523
+ set data($node) [concat [list $parent] [lrange $data($node) 1 end]]
524
+ if { [string equal $index "end"] } {
525
+ lappend data($parent) $node
526
+ } else {
527
+ incr index
528
+ set data($parent) [linsert $data($parent) $index $node]
529
+ }
530
+ if { ([string equal $oldp "root"] ||
531
+ ([visible $path $oldp] && [Widget::getoption $path.$oldp -open])) ||
532
+ ([string equal $parent "root"] ||
533
+ ([visible $path $parent] && [Widget::getoption $path.$parent -open])) } {
534
+ _redraw_idle $path 3
535
+ }
536
+ }
537
+
538
+
539
+ # ----------------------------------------------------------------------------
540
+ # Command Tree::reorder
541
+ # ----------------------------------------------------------------------------
542
+ proc Tree::reorder { path node neworder } {
543
+ variable $path
544
+ upvar 0 $path data
545
+
546
+ set node [_node_name $path $node]
547
+ if { ![info exists data($node)] } {
548
+ return -code error "node \"$node\" does not exist"
549
+ }
550
+ set children [lrange $data($node) 1 end]
551
+ if { [llength $children] } {
552
+ set children [BWidget::lreorder $children $neworder]
553
+ set data($node) [linsert $children 0 [lindex $data($node) 0]]
554
+ if { [visible $path $node] && [Widget::getoption $path.$node -open] } {
555
+ _redraw_idle $path 3
556
+ }
557
+ }
558
+ }
559
+
560
+
561
+ # ----------------------------------------------------------------------------
562
+ # Command Tree::selection
563
+ # ----------------------------------------------------------------------------
564
+ proc Tree::selection { path cmd args } {
565
+ variable $path
566
+ upvar 0 $path data
567
+
568
+ switch -- $cmd {
569
+ toggle {
570
+ foreach node $args {
571
+ set node [_node_name $path $node]
572
+ if {![info exists data($node)]} {
573
+ return -code error \
574
+ "$path selection toggle: Cannot toggle unknown node \"$node\"."
575
+ }
576
+ }
577
+ foreach node $args {
578
+ set node [_node_name $path $node]
579
+ if {[$path selection includes $node]} {
580
+ $path selection remove $node
581
+ } else {
582
+ $path selection add $node
583
+ }
584
+ }
585
+ }
586
+ set {
587
+ foreach node $args {
588
+ set node [_node_name $path $node]
589
+ if {![info exists data($node)]} {
590
+ return -code error \
591
+ "$path selection set: Cannot select unknown node \"$node\"."
592
+ }
593
+ }
594
+ set data(selnodes) {}
595
+ foreach node $args {
596
+ set node [_node_name $path $node]
597
+ if { [Widget::getoption $path.$node -selectable] } {
598
+ if { [lsearch -exact $data(selnodes) $node] == -1 } {
599
+ lappend data(selnodes) $node
600
+ }
601
+ }
602
+ }
603
+ __call_selectcmd $path
604
+ }
605
+ add {
606
+ foreach node $args {
607
+ set node [_node_name $path $node]
608
+ if {![info exists data($node)]} {
609
+ return -code error \
610
+ "$path selection add: Cannot select unknown node \"$node\"."
611
+ }
612
+ }
613
+ foreach node $args {
614
+ set node [_node_name $path $node]
615
+ if { [Widget::getoption $path.$node -selectable] } {
616
+ if { [lsearch -exact $data(selnodes) $node] == -1 } {
617
+ lappend data(selnodes) $node
618
+ }
619
+ }
620
+ }
621
+ __call_selectcmd $path
622
+ }
623
+ range {
624
+ # Here's our algorithm:
625
+ # make a list of all nodes, then take the range from node1
626
+ # to node2 and select those nodes
627
+ #
628
+ # This works because of how this widget handles redraws:
629
+ # The tree is always completely redrawn, and always from
630
+ # top to bottom. So the list of visible nodes *is* the
631
+ # list of nodes, and we can use that to decide which nodes
632
+ # to select.
633
+
634
+ if {[llength $args] != 2} {
635
+ return -code error \
636
+ "wrong#args: Expected $path selection range node1 node2"
637
+ }
638
+
639
+ foreach {node1 node2} $args break
640
+
641
+ set node1 [_node_name $path $node1]
642
+ set node2 [_node_name $path $node2]
643
+ if {![info exists data($node1)]} {
644
+ return -code error \
645
+ "$path selection range: Cannot start range at unknown node \"$node1\"."
646
+ }
647
+ if {![info exists data($node2)]} {
648
+ return -code error \
649
+ "$path selection range: Cannot end range at unknown node \"$node2\"."
650
+ }
651
+
652
+ set nodes {}
653
+ foreach nodeItem [$path.c find withtag node] {
654
+ set node [Tree::_get_node_name $path $nodeItem 2]
655
+ if { [Widget::getoption $path.$node -selectable] } {
656
+ lappend nodes $node
657
+ }
658
+ }
659
+ # surles: Set the root string to the first element on the list.
660
+ if {$node1 == "root"} {
661
+ set node1 [lindex $nodes 0]
662
+ }
663
+ if {$node2 == "root"} {
664
+ set node2 [lindex $nodes 0]
665
+ }
666
+
667
+ # Find the first visible ancestor of node1, starting with node1
668
+ while {[set index1 [lsearch -exact $nodes $node1]] == -1} {
669
+ set node1 [lindex $data($node1) 0]
670
+ }
671
+ # Find the first visible ancestor of node2, starting with node2
672
+ while {[set index2 [lsearch -exact $nodes $node2]] == -1} {
673
+ set node2 [lindex $data($node2) 0]
674
+ }
675
+ # If the nodes were given in backwards order, flip the
676
+ # indices now
677
+ if { $index2 < $index1 } {
678
+ incr index1 $index2
679
+ set index2 [expr {$index1 - $index2}]
680
+ set index1 [expr {$index1 - $index2}]
681
+ }
682
+ set data(selnodes) [lrange $nodes $index1 $index2]
683
+ __call_selectcmd $path
684
+ }
685
+ remove {
686
+ foreach node $args {
687
+ set node [_node_name $path $node]
688
+ if { [set idx [lsearch -exact $data(selnodes) $node]] != -1 } {
689
+ set data(selnodes) [lreplace $data(selnodes) $idx $idx]
690
+ }
691
+ }
692
+ __call_selectcmd $path
693
+ }
694
+ clear {
695
+ if {[llength $args] != 0} {
696
+ return -code error \
697
+ "wrong#args: Expected $path selection clear"
698
+ }
699
+ set data(selnodes) {}
700
+ __call_selectcmd $path
701
+ }
702
+ get {
703
+ if {[llength $args] != 0} {
704
+ return -code error \
705
+ "wrong#args: Expected $path selection get"
706
+ }
707
+ return $data(selnodes)
708
+ }
709
+ includes {
710
+ if {[llength $args] != 1} {
711
+ return -code error \
712
+ "wrong#args: Expected $path selection includes node"
713
+ }
714
+ set node [lindex $args 0]
715
+ set node [_node_name $path $node]
716
+ return [expr {[lsearch -exact $data(selnodes) $node] != -1}]
717
+ }
718
+ default {
719
+ return
720
+ }
721
+ }
722
+ _redraw_idle $path 1
723
+ }
724
+
725
+
726
+ proc Tree::getcanvas { path } {
727
+ return $path.c
728
+ }
729
+
730
+
731
+ proc Tree::__call_selectcmd { path } {
732
+ variable $path
733
+ upvar 0 $path data
734
+
735
+ set selectcmd [Widget::getoption $path -selectcommand]
736
+ if {[llength $selectcmd]} {
737
+ lappend selectcmd $path
738
+ lappend selectcmd $data(selnodes)
739
+ uplevel \#0 $selectcmd
740
+ }
741
+ return
742
+ }
743
+
744
+ # ----------------------------------------------------------------------------
745
+ # Command Tree::exists
746
+ # ----------------------------------------------------------------------------
747
+ proc Tree::exists { path node } {
748
+ variable $path
749
+ upvar 0 $path data
750
+
751
+ set node [_node_name $path $node]
752
+ return [info exists data($node)]
753
+ }
754
+
755
+
756
+ # ----------------------------------------------------------------------------
757
+ # Command Tree::visible
758
+ # ----------------------------------------------------------------------------
759
+ proc Tree::visible { path node } {
760
+ set node [_node_name $path $node]
761
+ set idn [$path.c find withtag n:$node]
762
+ return [llength $idn]
763
+ }
764
+
765
+
766
+ # ----------------------------------------------------------------------------
767
+ # Command Tree::parent
768
+ # ----------------------------------------------------------------------------
769
+ proc Tree::parent { path node } {
770
+ variable $path
771
+ upvar 0 $path data
772
+
773
+ set node [_node_name $path $node]
774
+ if { ![info exists data($node)] } {
775
+ return -code error "node \"$node\" does not exist"
776
+ }
777
+ return [lindex $data($node) 0]
778
+ }
779
+
780
+
781
+ # ----------------------------------------------------------------------------
782
+ # Command Tree::index
783
+ # ----------------------------------------------------------------------------
784
+ proc Tree::index { path node } {
785
+ variable $path
786
+ upvar 0 $path data
787
+
788
+ set node [_node_name $path $node]
789
+ if { [string equal $node "root"] || ![info exists data($node)] } {
790
+ return -code error "node \"$node\" does not exist"
791
+ }
792
+ set parent [lindex $data($node) 0]
793
+ return [expr {[lsearch -exact $data($parent) $node] - 1}]
794
+ }
795
+
796
+
797
+ # ----------------------------------------------------------------------------
798
+ # Tree::find
799
+ # Returns the node given a position.
800
+ # findInfo @x,y ?confine?
801
+ # lineNumber
802
+ # ----------------------------------------------------------------------------
803
+ proc Tree::find {path findInfo {confine ""}} {
804
+ if {[regexp -- {^@([0-9]+),([0-9]+)$} $findInfo match x y]} {
805
+ set x [$path.c canvasx $x]
806
+ set y [$path.c canvasy $y]
807
+ } elseif {[regexp -- {^[0-9]+$} $findInfo lineNumber]} {
808
+ set dy [Widget::getoption $path -deltay]
809
+ set y [expr {$dy*($lineNumber+0.5)}]
810
+ set confine ""
811
+ } else {
812
+ return -code error "invalid find spec \"$findInfo\""
813
+ }
814
+
815
+ set found 0
816
+ set region [$path.c bbox all]
817
+ if {[llength $region]} {
818
+ set xi [lindex $region 0]
819
+ set xs [lindex $region 2]
820
+ foreach id [$path.c find overlapping $xi $y $xs $y] {
821
+ set ltags [$path.c gettags $id]
822
+ set item [lindex $ltags 1]
823
+ if { [string equal $item "node"] ||
824
+ [string equal $item "img"] ||
825
+ [string equal $item "win"] } {
826
+ # item is the label or image/window of the node
827
+ set node [Tree::_get_node_name $path $id 2]
828
+ set found 1
829
+ break
830
+ }
831
+ }
832
+ }
833
+
834
+ if {$found} {
835
+ if {![string equal $confine ""]} {
836
+ # test if x stand inside node bbox
837
+ set padx [_get_node_padx $path $node]
838
+ set xi [expr {[lindex [$path.c coords n:$node] 0] - $padx}]
839
+ set xs [lindex [$path.c bbox n:$node] 2]
840
+ if {$x >= $xi && $x <= $xs} {
841
+ return $node
842
+ }
843
+ } else {
844
+ return $node
845
+ }
846
+ }
847
+ return ""
848
+ }
849
+
850
+
851
+ # ----------------------------------------------------------------------------
852
+ # Command Tree::line
853
+ # Returns the line where a node was drawn.
854
+ # ----------------------------------------------------------------------------
855
+ proc Tree::line {path node} {
856
+ set node [_node_name $path $node]
857
+ set item [$path.c find withtag n:$node]
858
+ if {[string length $item]} {
859
+ set dy [Widget::getoption $path -deltay]
860
+ set y [lindex [$path.c coords $item] 1]
861
+ set line [expr {int($y/$dy)}]
862
+ } else {
863
+ set line -1
864
+ }
865
+ return $line
866
+ }
867
+
868
+
869
+ # ----------------------------------------------------------------------------
870
+ # Command Tree::nodes
871
+ # ----------------------------------------------------------------------------
872
+ proc Tree::nodes { path node {first ""} {last ""} } {
873
+ variable $path
874
+ upvar 0 $path data
875
+
876
+ set node [_node_name $path $node]
877
+ if { ![info exists data($node)] } {
878
+ return -code error "node \"$node\" does not exist"
879
+ }
880
+
881
+ if { ![string length $first] } {
882
+ return [lrange $data($node) 1 end]
883
+ }
884
+
885
+ if { ![string length $last] } {
886
+ return [lindex [lrange $data($node) 1 end] $first]
887
+ } else {
888
+ return [lrange [lrange $data($node) 1 end] $first $last]
889
+ }
890
+ }
891
+
892
+
893
+ # Tree::visiblenodes --
894
+ #
895
+ # Retrieve a list of all the nodes in a tree.
896
+ #
897
+ # Arguments:
898
+ # path tree to retrieve nodes for.
899
+ #
900
+ # Results:
901
+ # nodes list of nodes in the tree.
902
+
903
+ proc Tree::visiblenodes { path } {
904
+ variable $path
905
+ upvar 0 $path data
906
+
907
+ # Root is always open (?), so all of its children automatically get added
908
+ # to the result, and to the stack.
909
+ set st [lrange $data(root) 1 end]
910
+ set result $st
911
+
912
+ while {[llength $st]} {
913
+ set node [lindex $st end]
914
+ set st [lreplace $st end end]
915
+ # Danger, danger! Using getMegawidgetOption is fragile, but much
916
+ # much faster than going through cget.
917
+ if { [Widget::getMegawidgetOption $path.$node -open] } {
918
+ set nodes [lrange $data($node) 1 end]
919
+ set result [concat $result $nodes]
920
+ set st [concat $st $nodes]
921
+ }
922
+ }
923
+ return $result
924
+ }
925
+
926
+ # ----------------------------------------------------------------------------
927
+ # Command Tree::see
928
+ # ----------------------------------------------------------------------------
929
+ proc Tree::see { path node } {
930
+ variable $path
931
+ upvar 0 $path data
932
+
933
+ set node [_node_name $path $node]
934
+ if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
935
+ after cancel $data(upd,afterid)
936
+ _redraw_tree $path
937
+ }
938
+ set idn [$path.c find withtag n:$node]
939
+ if { $idn != "" } {
940
+ Tree::_see $path $idn
941
+ }
942
+ }
943
+
944
+
945
+ # ----------------------------------------------------------------------------
946
+ # Command Tree::opentree
947
+ # ----------------------------------------------------------------------------
948
+ # JDC: added option recursive
949
+ proc Tree::opentree { path node {recursive 1} } {
950
+ variable $path
951
+ upvar 0 $path data
952
+
953
+ set node [_node_name $path $node]
954
+ if { [string equal $node "root"] || ![info exists data($node)] } {
955
+ return -code error "node \"$node\" does not exist"
956
+ }
957
+
958
+ _recexpand $path $node 1 $recursive [Widget::getoption $path -opencmd]
959
+ _redraw_idle $path 3
960
+ }
961
+
962
+
963
+ # ----------------------------------------------------------------------------
964
+ # Command Tree::closetree
965
+ # ----------------------------------------------------------------------------
966
+ proc Tree::closetree { path node {recursive 1} } {
967
+ variable $path
968
+ upvar 0 $path data
969
+
970
+ set node [_node_name $path $node]
971
+ if { [string equal $node "root"] || ![info exists data($node)] } {
972
+ return -code error "node \"$node\" does not exist"
973
+ }
974
+
975
+ _recexpand $path $node 0 $recursive [Widget::getoption $path -closecmd]
976
+ _redraw_idle $path 3
977
+ }
978
+
979
+
980
+ proc Tree::toggle { path node } {
981
+ if {[$path itemcget $node -open]} {
982
+ $path closetree $node 0
983
+ } else {
984
+ $path opentree $node 0
985
+ }
986
+ }
987
+
988
+
989
+ # ----------------------------------------------------------------------------
990
+ # Command Tree::edit
991
+ # ----------------------------------------------------------------------------
992
+ proc Tree::edit { path node text {verifycmd ""} {clickres 0} {select 1}} {
993
+ variable _edit
994
+ variable $path
995
+ upvar 0 $path data
996
+
997
+ set node [_node_name $path $node]
998
+ if { [Widget::getoption $path -redraw] && $data(upd,afterid) != "" } {
999
+ after cancel $data(upd,afterid)
1000
+ _redraw_tree $path
1001
+ }
1002
+ set idn [$path.c find withtag n:$node]
1003
+ if { $idn != "" } {
1004
+ Tree::_see $path $idn
1005
+
1006
+ set oldfg [$path.c itemcget $idn -fill]
1007
+ set sbg [Widget::getoption $path -selectbackground]
1008
+ set coords [$path.c coords $idn]
1009
+ set x [lindex $coords 0]
1010
+ set y [lindex $coords 1]
1011
+ set bd [expr {[$path.c cget -borderwidth]+[$path.c cget -highlightthickness]}]
1012
+ set w [expr {[winfo width $path] - 2*$bd}]
1013
+ set wmax [expr {[$path.c canvasx $w]-$x}]
1014
+
1015
+ set _edit(text) $text
1016
+ set _edit(wait) 0
1017
+
1018
+ $path.c itemconfigure $idn -fill [Widget::getoption $path -background]
1019
+ $path.c itemconfigure s:$node -fill {} -outline {}
1020
+
1021
+ set frame [frame $path.edit \
1022
+ -relief flat -borderwidth 0 -highlightthickness 0 \
1023
+ -background [Widget::getoption $path -background]]
1024
+ set ent [entry $frame.edit \
1025
+ -width 0 \
1026
+ -relief solid \
1027
+ -borderwidth 1 \
1028
+ -highlightthickness 0 \
1029
+ -foreground [Widget::getoption $path.$node -fill] \
1030
+ -background [Widget::getoption $path -background] \
1031
+ -selectforeground [Widget::getoption $path -selectforeground] \
1032
+ -selectbackground $sbg \
1033
+ -font [Widget::getoption $path.$node -font] \
1034
+ -textvariable Tree::_edit(text)]
1035
+ pack $ent -ipadx 8 -anchor w
1036
+
1037
+ set idw [$path.c create window $x $y -window $frame -anchor w]
1038
+ trace variable Tree::_edit(text) w \
1039
+ [list Tree::_update_edit_size $path $ent $idw $wmax]
1040
+ tkwait visibility $ent
1041
+ grab $frame
1042
+ BWidget::focus set $ent
1043
+
1044
+ _update_edit_size $path $ent $idw $wmax
1045
+ update
1046
+ if { $select } {
1047
+ $ent selection range 0 end
1048
+ $ent icursor end
1049
+ $ent xview end
1050
+ }
1051
+
1052
+ bindtags $ent [list $ent Entry]
1053
+ bind $ent <Escape> {set Tree::_edit(wait) 0}
1054
+ bind $ent <Return> {set Tree::_edit(wait) 1}
1055
+ if { $clickres == 0 || $clickres == 1 } {
1056
+ bind $frame <Button> [list set Tree::_edit(wait) $clickres]
1057
+ }
1058
+
1059
+ set ok 0
1060
+ while { !$ok } {
1061
+ tkwait variable Tree::_edit(wait)
1062
+ if { !$_edit(wait) || [llength $verifycmd]==0 ||
1063
+ [uplevel \#0 $verifycmd [list $_edit(text)]] } {
1064
+ set ok 1
1065
+ }
1066
+ }
1067
+
1068
+ trace vdelete Tree::_edit(text) w \
1069
+ [list Tree::_update_edit_size $path $ent $idw $wmax]
1070
+ grab release $frame
1071
+ BWidget::focus release $ent
1072
+ destroy $frame
1073
+ $path.c delete $idw
1074
+ $path.c itemconfigure $idn -fill $oldfg
1075
+ $path.c itemconfigure s:$node -fill $sbg -outline $sbg
1076
+
1077
+ if { $_edit(wait) } {
1078
+ return $_edit(text)
1079
+ }
1080
+ }
1081
+ return ""
1082
+ }
1083
+
1084
+
1085
+ # ----------------------------------------------------------------------------
1086
+ # Command Tree::xview
1087
+ # ----------------------------------------------------------------------------
1088
+ proc Tree::xview { path args } {
1089
+ return [eval [linsert $args 0 $path.c xview]]
1090
+ }
1091
+
1092
+
1093
+ # ----------------------------------------------------------------------------
1094
+ # Command Tree::yview
1095
+ # ----------------------------------------------------------------------------
1096
+ proc Tree::yview { path args } {
1097
+ return [eval [linsert $args 0 $path.c yview]]
1098
+ }
1099
+
1100
+
1101
+ # ----------------------------------------------------------------------------
1102
+ # Command Tree::_update_edit_size
1103
+ # ----------------------------------------------------------------------------
1104
+ proc Tree::_update_edit_size { path entry idw wmax args } {
1105
+ set entw [winfo reqwidth $entry]
1106
+ if { $entw+8 >= $wmax } {
1107
+ $path.c itemconfigure $idw -width $wmax
1108
+ } else {
1109
+ $path.c itemconfigure $idw -width 0
1110
+ }
1111
+ }
1112
+
1113
+
1114
+ # ----------------------------------------------------------------------------
1115
+ # Command Tree::_see
1116
+ # ----------------------------------------------------------------------------
1117
+ proc Tree::_see { path idn } {
1118
+ set bbox [$path.c bbox $idn]
1119
+ set scrl [$path.c cget -scrollregion]
1120
+
1121
+ set ymax [lindex $scrl 3]
1122
+ set dy [$path.c cget -yscrollincrement]
1123
+ set yv [$path yview]
1124
+ set yv0 [expr {round([lindex $yv 0]*$ymax/$dy)}]
1125
+ set yv1 [expr {round([lindex $yv 1]*$ymax/$dy)}]
1126
+ set y [expr {int([lindex [$path.c coords $idn] 1]/$dy)}]
1127
+ if { $y < $yv0 } {
1128
+ $path.c yview scroll [expr {$y-$yv0}] units
1129
+ } elseif { $y >= $yv1 } {
1130
+ $path.c yview scroll [expr {$y-$yv1+1}] units
1131
+ }
1132
+
1133
+ set xmax [lindex $scrl 2]
1134
+ set dx [$path.c cget -xscrollincrement]
1135
+ set xv [$path xview]
1136
+ set x0 [expr {int([lindex $bbox 0]/$dx)}]
1137
+ set xv0 [expr {round([lindex $xv 0]*$xmax/$dx)}]
1138
+ set xv1 [expr {round([lindex $xv 1]*$xmax/$dx)}]
1139
+ if { $x0 >= $xv1 || $x0 < $xv0 } {
1140
+ $path.c xview scroll [expr {$x0-$xv0}] units
1141
+ }
1142
+ }
1143
+
1144
+
1145
+ # ----------------------------------------------------------------------------
1146
+ # Command Tree::_recexpand
1147
+ # ----------------------------------------------------------------------------
1148
+ # JDC : added option recursive
1149
+ proc Tree::_recexpand { path node expand recursive cmd } {
1150
+ variable $path
1151
+ upvar 0 $path data
1152
+
1153
+ if { [Widget::getoption $path.$node -open] != $expand } {
1154
+ Widget::setoption $path.$node -open $expand
1155
+ if {[llength $cmd]} {
1156
+ uplevel \#0 $cmd [list $node]
1157
+ }
1158
+ }
1159
+
1160
+ if { $recursive } {
1161
+ foreach subnode [lrange $data($node) 1 end] {
1162
+ _recexpand $path $subnode $expand $recursive $cmd
1163
+ }
1164
+ }
1165
+ }
1166
+
1167
+
1168
+ # ----------------------------------------------------------------------------
1169
+ # Command Tree::_subdelete
1170
+ # ----------------------------------------------------------------------------
1171
+ proc Tree::_subdelete { path lnodes } {
1172
+ variable $path
1173
+ upvar 0 $path data
1174
+
1175
+ set sel $data(selnodes)
1176
+ set selchanged 0
1177
+
1178
+ while { [llength $lnodes] } {
1179
+ set lsubnodes [list]
1180
+ foreach node $lnodes {
1181
+ foreach subnode [lrange $data($node) 1 end] {
1182
+ lappend lsubnodes $subnode
1183
+ }
1184
+ unset data($node)
1185
+ set idx [lsearch -exact $sel $node]
1186
+ if { $idx >= 0 } {
1187
+ set sel [lreplace $sel $idx $idx]
1188
+ incr selchanged
1189
+ }
1190
+ if { [set win [Widget::getoption $path.$node -window]] != "" } {
1191
+ destroy $win
1192
+ }
1193
+ Widget::destroy $path.$node
1194
+ }
1195
+ set lnodes $lsubnodes
1196
+ }
1197
+
1198
+ set data(selnodes) $sel
1199
+ # return number of sel items changes
1200
+ return $selchanged
1201
+ }
1202
+
1203
+
1204
+ # ----------------------------------------------------------------------------
1205
+ # Command Tree::_update_scrollregion
1206
+ # ----------------------------------------------------------------------------
1207
+ proc Tree::_update_scrollregion { path } {
1208
+ set bd [expr {2*([$path.c cget -borderwidth]+[$path.c cget -highlightthickness])}]
1209
+ set w [expr {[winfo width $path] - $bd}]
1210
+ set h [expr {[winfo height $path] - $bd}]
1211
+ set xinc [$path.c cget -xscrollincrement]
1212
+ set yinc [$path.c cget -yscrollincrement]
1213
+ set bbox [$path.c bbox node]
1214
+ if { [llength $bbox] } {
1215
+ set xs [lindex $bbox 2]
1216
+ set ys [lindex $bbox 3]
1217
+
1218
+ if { $w < $xs } {
1219
+ set w [expr {int($xs)}]
1220
+ if { [set r [expr {$w % $xinc}]] } {
1221
+ set w [expr {$w+$xinc-$r}]
1222
+ }
1223
+ }
1224
+ if { $h < $ys } {
1225
+ set h [expr {int($ys)}]
1226
+ if { [set r [expr {$h % $yinc}]] } {
1227
+ set h [expr {$h+$yinc-$r}]
1228
+ }
1229
+ }
1230
+ }
1231
+
1232
+ $path.c configure -scrollregion [list 0 0 $w $h]
1233
+
1234
+ if {[Widget::getoption $path -selectfill]} {
1235
+ _redraw_selection $path
1236
+ }
1237
+ }
1238
+
1239
+
1240
+ # ----------------------------------------------------------------------------
1241
+ # Command Tree::_cross_event
1242
+ # ----------------------------------------------------------------------------
1243
+ proc Tree::_cross_event { path } {
1244
+ variable $path
1245
+ upvar 0 $path data
1246
+
1247
+ set node [Tree::_get_node_name $path current 1]
1248
+ if { [Widget::getoption $path.$node -open] } {
1249
+ Tree::itemconfigure $path $node -open 0
1250
+ if {[llength [set cmd [Widget::getoption $path -closecmd]]]} {
1251
+ uplevel \#0 $cmd [list $node]
1252
+ }
1253
+ } else {
1254
+ Tree::itemconfigure $path $node -open 1
1255
+ if {[llength [set cmd [Widget::getoption $path -opencmd]]]} {
1256
+ uplevel \#0 $cmd [list $node]
1257
+ }
1258
+ }
1259
+ }
1260
+
1261
+
1262
+ proc Tree::_draw_cross { path node open x y } {
1263
+ set idc [$path.c find withtag c:$node]
1264
+
1265
+ if { $open } {
1266
+ set img [Widget::cget $path -crossopenimage]
1267
+ set bmp [Widget::cget $path -crossopenbitmap]
1268
+ } else {
1269
+ set img [Widget::cget $path -crosscloseimage]
1270
+ set bmp [Widget::cget $path -crossclosebitmap]
1271
+ }
1272
+
1273
+ ## If we already have a cross for this node, we just adjust the image.
1274
+ if {$idc != ""} {
1275
+ if {$img == ""} {
1276
+ $path.c itemconfigure $idc -bitmap $bmp
1277
+ } else {
1278
+ $path.c itemconfigure $idc -image $img
1279
+ }
1280
+ return
1281
+ }
1282
+
1283
+ ## Create a new image for the cross. If the user has specified an
1284
+ ## image, it overrides a bitmap.
1285
+ if {$img == ""} {
1286
+ $path.c create bitmap $x $y \
1287
+ -bitmap $bmp \
1288
+ -background [$path.c cget -background] \
1289
+ -foreground [Widget::getoption $path -crossfill] \
1290
+ -tags [list cross c:$node] -anchor c
1291
+ } else {
1292
+ $path.c create image $x $y \
1293
+ -image $img \
1294
+ -tags [list cross c:$node] -anchor c
1295
+ }
1296
+ }
1297
+
1298
+
1299
+ # ----------------------------------------------------------------------------
1300
+ # Command Tree::_draw_node
1301
+ # ----------------------------------------------------------------------------
1302
+ proc Tree::_draw_node { path node x0 y0 deltax deltay padx showlines } {
1303
+ variable $path
1304
+ upvar 0 $path data
1305
+
1306
+ set x1 [expr {$x0+$deltax+5}]
1307
+ set y1 $y0
1308
+ if { $showlines } {
1309
+ $path.c create line $x0 $y0 $x1 $y0 \
1310
+ -fill [Widget::getoption $path -linesfill] \
1311
+ -stipple [Widget::getoption $path -linestipple] \
1312
+ -tags line
1313
+ }
1314
+ $path.c create text [expr {$x1+$padx}] $y0 \
1315
+ -text [Widget::getoption $path.$node -text] \
1316
+ -fill [Widget::getoption $path.$node -fill] \
1317
+ -font [Widget::getoption $path.$node -font] \
1318
+ -anchor w \
1319
+ -tags [Tree::_get_node_tags $path $node [list node n:$node]]
1320
+ set len [expr {[llength $data($node)] > 1}]
1321
+ set dc [Widget::getoption $path.$node -drawcross]
1322
+ set exp [Widget::getoption $path.$node -open]
1323
+
1324
+ if { $len && $exp } {
1325
+ set y1 [_draw_subnodes $path [lrange $data($node) 1 end] \
1326
+ [expr {$x0+$deltax}] $y0 $deltax $deltay $padx $showlines]
1327
+ }
1328
+
1329
+ if {![string equal $dc "never"]
1330
+ && ($len || [string equal $dc "always"] || [string equal $dc "allways"])} {
1331
+ _draw_cross $path $node $exp $x0 $y0
1332
+ }
1333
+
1334
+ if { [set win [Widget::getoption $path.$node -window]] != "" } {
1335
+ set a [Widget::cget $path.$node -anchor]
1336
+ $path.c create window $x1 $y0 -window $win -anchor $a \
1337
+ -tags [Tree::_get_node_tags $path $node [list win i:$node]]
1338
+ } elseif { [set img [Widget::getoption $path.$node -image]] != "" } {
1339
+ set a [Widget::cget $path.$node -anchor]
1340
+ $path.c create image $x1 $y0 -image $img -anchor $a \
1341
+ -tags [Tree::_get_node_tags $path $node [list img i:$node]]
1342
+ }
1343
+ set box [$path.c bbox n:$node i:$node]
1344
+ set id [$path.c create rect 0 [lindex $box 1] \
1345
+ [winfo screenwidth $path] [lindex $box 3] \
1346
+ -tags [Tree::_get_node_tags $path $node [list box b:$node]] \
1347
+ -fill {} -outline {}]
1348
+ $path.c lower $id
1349
+
1350
+ _set_help $path $node
1351
+
1352
+ return $y1
1353
+ }
1354
+
1355
+
1356
+ # ----------------------------------------------------------------------------
1357
+ # Command Tree::_draw_subnodes
1358
+ # ----------------------------------------------------------------------------
1359
+ proc Tree::_draw_subnodes { path nodes x0 y0 deltax deltay padx showlines } {
1360
+ set y1 $y0
1361
+ foreach node $nodes {
1362
+ set padx [_get_node_padx $path $node]
1363
+ set deltax [_get_node_deltax $path $node]
1364
+ set yp $y1
1365
+ set y1 [_draw_node $path $node $x0 [expr {$y1+$deltay}] $deltax $deltay $padx $showlines]
1366
+ }
1367
+ if { $showlines && [llength $nodes] } {
1368
+ if {$y0 < 0} {
1369
+ # Adjust the drawing of the line to the first root node
1370
+ # to start at the vertical point (not go up).
1371
+ incr y0 $deltay
1372
+ }
1373
+ set id [$path.c create line $x0 $y0 $x0 [expr {$yp+$deltay}] \
1374
+ -fill [Widget::getoption $path -linesfill] \
1375
+ -stipple [Widget::getoption $path -linestipple] \
1376
+ -tags line]
1377
+
1378
+ $path.c lower $id
1379
+ }
1380
+ return $y1
1381
+ }
1382
+
1383
+
1384
+ # ----------------------------------------------------------------------------
1385
+ # Command Tree::_update_nodes
1386
+ # ----------------------------------------------------------------------------
1387
+ proc Tree::_update_nodes { path } {
1388
+ variable $path
1389
+ upvar 0 $path data
1390
+
1391
+ foreach {node flag} $data(upd,nodes) {
1392
+ set idn [$path.c find withtag "n:$node"]
1393
+ if { $idn == "" } {
1394
+ continue
1395
+ }
1396
+ set padx [_get_node_padx $path $node]
1397
+ set deltax [_get_node_deltax $path $node]
1398
+ set c [$path.c coords $idn]
1399
+ set x1 [expr {[lindex $c 0]-$padx}]
1400
+ set x0 [expr {$x1-$deltax-5}]
1401
+ set y0 [lindex $c 1]
1402
+ if { $flag & 48 } {
1403
+ # -window or -image modified
1404
+ set win [Widget::getoption $path.$node -window]
1405
+ set img [Widget::getoption $path.$node -image]
1406
+ set anc [Widget::cget $path.$node -anchor]
1407
+ set idi [$path.c find withtag i:$node]
1408
+ set type [lindex [$path.c gettags $idi] 1]
1409
+ if { [string length $win] } {
1410
+ if { [string equal $type "win"] } {
1411
+ $path.c itemconfigure $idi -window $win
1412
+ } else {
1413
+ $path.c delete $idi
1414
+ $path.c create window $x1 $y0 -window $win -anchor $anc \
1415
+ -tags [_get_node_tags $path $node [list win i:$node]]
1416
+ }
1417
+ } elseif { [string length $img] } {
1418
+ if { [string equal $type "img"] } {
1419
+ $path.c itemconfigure $idi -image $img
1420
+ } else {
1421
+ $path.c delete $idi
1422
+ $path.c create image $x1 $y0 -image $img -anchor $anc \
1423
+ -tags [_get_node_tags $path $node [list img i:$node]]
1424
+ }
1425
+ } else {
1426
+ $path.c delete $idi
1427
+ }
1428
+ }
1429
+
1430
+ if { $flag & 8 } {
1431
+ # -drawcross modified
1432
+ set len [expr {[llength $data($node)] > 1}]
1433
+ set dc [Widget::getoption $path.$node -drawcross]
1434
+ set exp [Widget::getoption $path.$node -open]
1435
+
1436
+ if {![string equal $dc "never"]
1437
+ && ($len || [string equal $dc "always"] || [string equal $dc "allways"])} {
1438
+ _draw_cross $path $node $exp $x0 $y0
1439
+ } else {
1440
+ set idc [$path.c find withtag c:$node]
1441
+ $path.c delete $idc
1442
+ }
1443
+ }
1444
+
1445
+ if { $flag & 7 } {
1446
+ # -font, -text or -fill modified
1447
+ $path.c itemconfigure $idn \
1448
+ -text [Widget::getoption $path.$node -text] \
1449
+ -fill [Widget::getoption $path.$node -fill] \
1450
+ -font [Widget::getoption $path.$node -font]
1451
+ }
1452
+ }
1453
+ }
1454
+
1455
+
1456
+ # ----------------------------------------------------------------------------
1457
+ # Command Tree::_draw_tree
1458
+ # ----------------------------------------------------------------------------
1459
+ proc Tree::_draw_tree { path } {
1460
+ variable $path
1461
+ upvar 0 $path data
1462
+
1463
+ $path.c delete all
1464
+ set cursor [$path.c cget -cursor]
1465
+ $path.c configure -cursor watch
1466
+ _draw_subnodes $path [lrange $data(root) 1 end] 8 \
1467
+ [expr {-[Widget::getoption $path -deltay]/2}] \
1468
+ [Widget::getoption $path -deltax] \
1469
+ [Widget::getoption $path -deltay] \
1470
+ [Widget::getoption $path -padx] \
1471
+ [Widget::getoption $path -showlines]
1472
+ $path.c configure -cursor $cursor
1473
+ }
1474
+
1475
+
1476
+ # ----------------------------------------------------------------------------
1477
+ # Command Tree::_redraw_tree
1478
+ # ----------------------------------------------------------------------------
1479
+ proc Tree::_redraw_tree { path } {
1480
+ variable $path
1481
+ upvar 0 $path data
1482
+
1483
+ if { [Widget::getoption $path -redraw] } {
1484
+ if { $data(upd,level) == 2 } {
1485
+ _update_nodes $path
1486
+ } elseif { $data(upd,level) == 3 } {
1487
+ _draw_tree $path
1488
+ }
1489
+ _redraw_selection $path
1490
+ _update_scrollregion $path
1491
+ set data(upd,nodes) {}
1492
+ set data(upd,level) 0
1493
+ set data(upd,afterid) ""
1494
+ }
1495
+ }
1496
+
1497
+
1498
+ # ----------------------------------------------------------------------------
1499
+ # Command Tree::_redraw_selection
1500
+ # ----------------------------------------------------------------------------
1501
+ proc Tree::_redraw_selection { path } {
1502
+ variable $path
1503
+ upvar 0 $path data
1504
+
1505
+ set selbg [Widget::getoption $path -selectbackground]
1506
+ set selfg [Widget::getoption $path -selectforeground]
1507
+ set fill [Widget::getoption $path -selectfill]
1508
+ if {$fill} {
1509
+ set scroll [$path.c cget -scrollregion]
1510
+ if {[llength $scroll]} {
1511
+ set xmax [expr {[lindex $scroll 2]-1}]
1512
+ } else {
1513
+ set xmax [winfo width $path]
1514
+ }
1515
+ }
1516
+ foreach id [$path.c find withtag sel] {
1517
+ set node [Tree::_get_node_name $path $id 1]
1518
+ $path.c itemconfigure "n:$node" -fill [Widget::getoption $path.$node -fill]
1519
+ }
1520
+ $path.c delete sel
1521
+ foreach node $data(selnodes) {
1522
+ set bbox [$path.c bbox "n:$node"]
1523
+ if { [llength $bbox] } {
1524
+ if {$fill} {
1525
+ # get the image to (if any), as it may have different height
1526
+ set bbox [$path.c bbox "n:$node" "i:$node"]
1527
+ set bbox [list 0 [lindex $bbox 1] $xmax [lindex $bbox 3]]
1528
+ }
1529
+ set id [$path.c create rectangle $bbox -tags [list sel s:$node] \
1530
+ -fill $selbg -outline $selbg]
1531
+ $path.c itemconfigure "n:$node" -fill $selfg
1532
+ $path.c lower $id
1533
+ }
1534
+ }
1535
+ }
1536
+
1537
+
1538
+ # ----------------------------------------------------------------------------
1539
+ # Command Tree::_redraw_idle
1540
+ # ----------------------------------------------------------------------------
1541
+ proc Tree::_redraw_idle { path level } {
1542
+ variable $path
1543
+ upvar 0 $path data
1544
+
1545
+ if { [Widget::getoption $path -redraw] && $data(upd,afterid) == "" } {
1546
+ set data(upd,afterid) [after idle [list Tree::_redraw_tree $path]]
1547
+ }
1548
+ if { $level > $data(upd,level) } {
1549
+ set data(upd,level) $level
1550
+ }
1551
+ return ""
1552
+ }
1553
+
1554
+
1555
+ # ----------------------------------------------------------------------------
1556
+ # Command Tree::_init_drag_cmd
1557
+ # ----------------------------------------------------------------------------
1558
+ proc Tree::_init_drag_cmd { path X Y top } {
1559
+ set path [winfo parent $path]
1560
+ set ltags [$path.c gettags current]
1561
+ set item [lindex $ltags 1]
1562
+ if { [string equal $item "node"] ||
1563
+ [string equal $item "img"] ||
1564
+ [string equal $item "win"] } {
1565
+ set node [Tree::_get_node_name $path current 2]
1566
+ if {[llength [set cmd [Widget::getoption $path -draginitcmd]]]} {
1567
+ return [uplevel \#0 $cmd [list $path $node $top]]
1568
+ }
1569
+ if { [set type [Widget::getoption $path -dragtype]] == "" } {
1570
+ set type "TREE_NODE"
1571
+ }
1572
+ if { [set img [Widget::getoption $path.$node -image]] != "" } {
1573
+ pack [label $top.l -image $img -padx 0 -pady 0]
1574
+ }
1575
+ return [list $type {copy move link} $node]
1576
+ }
1577
+ return {}
1578
+ }
1579
+
1580
+
1581
+ # ----------------------------------------------------------------------------
1582
+ # Command Tree::_drop_cmd
1583
+ # ----------------------------------------------------------------------------
1584
+ proc Tree::_drop_cmd { path source X Y op type dnddata } {
1585
+ set path [winfo parent $path]
1586
+ variable $path
1587
+ upvar 0 $path data
1588
+
1589
+ $path.c delete drop
1590
+ if { [string length $data(dnd,afterid)] } {
1591
+ after cancel $data(dnd,afterid)
1592
+ set data(dnd,afterid) ""
1593
+ }
1594
+ set data(dnd,scroll) ""
1595
+ if {[llength $data(dnd,node)]
1596
+ && [llength [set cmd [Widget::getoption $path -dropcmd]]]} {
1597
+ return [uplevel \#0 $cmd \
1598
+ [list $path $source $data(dnd,node) $op $type $dnddata]]
1599
+ }
1600
+ return 0
1601
+ }
1602
+
1603
+
1604
+ # ----------------------------------------------------------------------------
1605
+ # Command Tree::_over_cmd
1606
+ # ----------------------------------------------------------------------------
1607
+ proc Tree::_over_cmd { path source event X Y op type dnddata } {
1608
+ set path [winfo parent $path]
1609
+ variable $path
1610
+ upvar 0 $path data
1611
+
1612
+ if { [string equal $event "leave"] } {
1613
+ # we leave the window tree
1614
+ $path.c delete drop
1615
+ if { [string length $data(dnd,afterid)] } {
1616
+ after cancel $data(dnd,afterid)
1617
+ set data(dnd,afterid) ""
1618
+ }
1619
+ set data(dnd,scroll) ""
1620
+ return 0
1621
+ }
1622
+
1623
+ if { [string equal $event "enter"] } {
1624
+ # we enter the window tree - dnd data initialization
1625
+ set mode [Widget::getoption $path -dropovermode]
1626
+ set data(dnd,mode) 0
1627
+ foreach c {w p n} {
1628
+ set data(dnd,mode) [expr {($data(dnd,mode) << 1) | ([string first $c $mode] != -1)}]
1629
+ }
1630
+ set bbox [$path.c bbox all]
1631
+ if { [llength $bbox] } {
1632
+ set data(dnd,xs) [lindex $bbox 2]
1633
+ set data(dnd,empty) 0
1634
+ } else {
1635
+ set data(dnd,xs) 0
1636
+ set data(dnd,empty) 1
1637
+ }
1638
+ set data(dnd,node) {}
1639
+ }
1640
+
1641
+ set x [expr {$X-[winfo rootx $path]}]
1642
+ set y [expr {$Y-[winfo rooty $path]}]
1643
+ $path.c delete drop
1644
+ set data(dnd,node) {}
1645
+
1646
+ # test for auto-scroll unless mode is widget only
1647
+ if { $data(dnd,mode) != 4 && [_auto_scroll $path $x $y] != "" } {
1648
+ return 2
1649
+ }
1650
+
1651
+ if { $data(dnd,mode) & 4 } {
1652
+ # dropovermode includes widget
1653
+ set target [list widget]
1654
+ set vmode 4
1655
+ } else {
1656
+ set target [list ""]
1657
+ set vmode 0
1658
+ }
1659
+ if { ($data(dnd,mode) & 2) && $data(dnd,empty) } {
1660
+ # dropovermode includes position and tree is empty
1661
+ lappend target [list root 0]
1662
+ set vmode [expr {$vmode | 2}]
1663
+ }
1664
+
1665
+ set xc [$path.c canvasx $x]
1666
+ set xs $data(dnd,xs)
1667
+ if { $xc <= $xs } {
1668
+ set yc [$path.c canvasy $y]
1669
+ set dy [$path.c cget -yscrollincrement]
1670
+ set line [expr {int($yc/$dy)}]
1671
+ set xi 0
1672
+ set yi [expr {$line*$dy}]
1673
+ set ys [expr {$yi+$dy}]
1674
+ set found 0
1675
+ foreach id [$path.c find overlapping $xi $yi $xs $ys] {
1676
+ set ltags [$path.c gettags $id]
1677
+ set item [lindex $ltags 1]
1678
+ if { [string equal $item "node"] ||
1679
+ [string equal $item "img"] ||
1680
+ [string equal $item "win"] } {
1681
+ # item is the label or image/window of the node
1682
+ set node [Tree::_get_node_name $path $id 2]
1683
+ set found 1
1684
+ break
1685
+ }
1686
+ }
1687
+ if {$found} {
1688
+ set padx [_get_node_padx $path $node]
1689
+ set deltax [_get_node_deltax $path $node]
1690
+ set xi [expr {[lindex [$path.c coords n:$node] 0] - $padx - 1}]
1691
+ if { $data(dnd,mode) & 1 } {
1692
+ # dropovermode includes node
1693
+ lappend target $node
1694
+ set vmode [expr {$vmode | 1}]
1695
+ } else {
1696
+ lappend target ""
1697
+ }
1698
+
1699
+ if { $data(dnd,mode) & 2 } {
1700
+ # dropovermode includes position
1701
+ if { $yc >= $yi+$dy/2 } {
1702
+ # position is after $node
1703
+ if { [Widget::getoption $path.$node -open] &&
1704
+ [llength $data($node)] > 1 } {
1705
+ # $node is open and have subnodes
1706
+ # drop position is 0 in children of $node
1707
+ set parent $node
1708
+ set index 0
1709
+ set xli [expr {$xi-5}]
1710
+ } else {
1711
+ # $node is not open and doesn't have subnodes
1712
+ # drop position is after $node in children of parent of $node
1713
+ set parent [lindex $data($node) 0]
1714
+ set index [lsearch -exact $data($parent) $node]
1715
+ set xli [expr {$xi - $deltax - 5}]
1716
+ }
1717
+ set yl $ys
1718
+ } else {
1719
+ # position is before $node
1720
+ # drop position is before $node in children of parent of $node
1721
+ set parent [lindex $data($node) 0]
1722
+ set index [expr {[lsearch -exact $data($parent) $node] - 1}]
1723
+ set xli [expr {$xi - $deltax - 5}]
1724
+ set yl $yi
1725
+ }
1726
+ lappend target [list $parent $index]
1727
+ set vmode [expr {$vmode | 2}]
1728
+ } else {
1729
+ lappend target {}
1730
+ }
1731
+
1732
+ if { ($vmode & 3) == 3 } {
1733
+ # result have both node and position
1734
+ # we compute what is the preferred method
1735
+ if { $yc-$yi <= 3 || $ys-$yc <= 3 } {
1736
+ lappend target "position"
1737
+ } else {
1738
+ lappend target "node"
1739
+ }
1740
+ }
1741
+ }
1742
+ }
1743
+
1744
+ if {$vmode && [llength [set cmd [Widget::getoption $path -dropovercmd]]]} {
1745
+ # user-defined dropover command
1746
+ set res [uplevel \#0 $cmd [list $path $source $target $op $type $dnddata]]
1747
+ set code [lindex $res 0]
1748
+ set newmode 0
1749
+ if { $code & 1 } {
1750
+ # update vmode
1751
+ set mode [lindex $res 1]
1752
+ if { ($vmode & 1) && [string equal $mode "node"] } {
1753
+ set newmode 1
1754
+ } elseif { ($vmode & 2) && [string equal $mode "position"] } {
1755
+ set newmode 2
1756
+ } elseif { ($vmode & 4) && [string equal $mode "widget"] } {
1757
+ set newmode 4
1758
+ }
1759
+ }
1760
+ set vmode $newmode
1761
+ } else {
1762
+ if { ($vmode & 3) == 3 } {
1763
+ # result have both item and position
1764
+ # we choose the preferred method
1765
+ if { [string equal [lindex $target 3] "position"] } {
1766
+ set vmode [expr {$vmode & ~1}]
1767
+ } else {
1768
+ set vmode [expr {$vmode & ~2}]
1769
+ }
1770
+ }
1771
+
1772
+ if { $data(dnd,mode) == 4 || $data(dnd,mode) == 0 } {
1773
+ # dropovermode is widget or empty - recall is not necessary
1774
+ set code 1
1775
+ } else {
1776
+ set code 3
1777
+ }
1778
+ }
1779
+
1780
+ if {!$data(dnd,empty)} {
1781
+ # draw dnd visual following vmode
1782
+ if { $vmode & 1 } {
1783
+ set data(dnd,node) [list "node" [lindex $target 1]]
1784
+ $path.c create rectangle $xi $yi $xs $ys -tags drop
1785
+ } elseif { $vmode & 2 } {
1786
+ set data(dnd,node) [concat "position" [lindex $target 2]]
1787
+ $path.c create line $xli [expr {$yl-$dy/2}] $xli $yl $xs $yl -tags drop
1788
+ } elseif { $vmode & 4 } {
1789
+ set data(dnd,node) [list "widget"]
1790
+ } else {
1791
+ set code [expr {$code & 2}]
1792
+ }
1793
+ }
1794
+
1795
+ if { $code & 1 } {
1796
+ DropSite::setcursor based_arrow_down
1797
+ } else {
1798
+ DropSite::setcursor dot
1799
+ }
1800
+ return $code
1801
+ }
1802
+
1803
+
1804
+ # ----------------------------------------------------------------------------
1805
+ # Command Tree::_auto_scroll
1806
+ # ----------------------------------------------------------------------------
1807
+ proc Tree::_auto_scroll { path x y } {
1808
+ variable $path
1809
+ upvar 0 $path data
1810
+
1811
+ set xmax [winfo width $path]
1812
+ set ymax [winfo height $path]
1813
+ set scroll {}
1814
+ if { $y <= 6 } {
1815
+ if { [lindex [$path.c yview] 0] > 0 } {
1816
+ set scroll [list yview -1]
1817
+ DropSite::setcursor sb_up_arrow
1818
+ }
1819
+ } elseif { $y >= $ymax-6 } {
1820
+ if { [lindex [$path.c yview] 1] < 1 } {
1821
+ set scroll [list yview 1]
1822
+ DropSite::setcursor sb_down_arrow
1823
+ }
1824
+ } elseif { $x <= 6 } {
1825
+ if { [lindex [$path.c xview] 0] > 0 } {
1826
+ set scroll [list xview -1]
1827
+ DropSite::setcursor sb_left_arrow
1828
+ }
1829
+ } elseif { $x >= $xmax-6 } {
1830
+ if { [lindex [$path.c xview] 1] < 1 } {
1831
+ set scroll [list xview 1]
1832
+ DropSite::setcursor sb_right_arrow
1833
+ }
1834
+ }
1835
+
1836
+ if { [string length $data(dnd,afterid)] && ![string equal $data(dnd,scroll) $scroll] } {
1837
+ after cancel $data(dnd,afterid)
1838
+ set data(dnd,afterid) ""
1839
+ }
1840
+
1841
+ set data(dnd,scroll) $scroll
1842
+ if { [string length $scroll] && ![string length $data(dnd,afterid)] } {
1843
+ set data(dnd,afterid) [after 200 [list Tree::_scroll $path $scroll]]
1844
+ }
1845
+ return $data(dnd,afterid)
1846
+ }
1847
+
1848
+
1849
+ # ----------------------------------------------------------------------------
1850
+ # Command Tree::_scroll
1851
+ # ----------------------------------------------------------------------------
1852
+ proc Tree::_scroll { path cmd dir } {
1853
+ variable $path
1854
+ upvar 0 $path data
1855
+
1856
+ if { ($dir == -1 && [lindex [$path.c $cmd] 0] > 0) ||
1857
+ ($dir == 1 && [lindex [$path.c $cmd] 1] < 1) } {
1858
+ $path.c $cmd scroll $dir units
1859
+ set data(dnd,afterid) [after 100 [list Tree::_scroll $path $cmd $dir]]
1860
+ } else {
1861
+ set data(dnd,afterid) ""
1862
+ DropSite::setcursor dot
1863
+ }
1864
+ }
1865
+
1866
+ # Tree::_keynav --
1867
+ #
1868
+ # Handle navigational keypresses on the tree.
1869
+ #
1870
+ # Arguments:
1871
+ # which tag indicating the direction of motion:
1872
+ # up move to the node graphically above current
1873
+ # down move to the node graphically below current
1874
+ # left close current if open, else move to parent
1875
+ # right open current if closed, else move to child
1876
+ # open open current if closed, close current if open
1877
+ # win name of the tree widget
1878
+ #
1879
+ # Results:
1880
+ # None.
1881
+
1882
+ proc Tree::_keynav {which win} {
1883
+ # check for an empty tree
1884
+ if {[$win nodes root] eq ""} {
1885
+ return
1886
+ }
1887
+
1888
+ # Keyboard navigation is riddled with special cases. In order to avoid
1889
+ # the complex logic, we will instead make a list of all the visible,
1890
+ # selectable nodes, then do a simple next or previous operation.
1891
+
1892
+ # One easy way to get all of the visible nodes is to query the canvas
1893
+ # object for all the items with the "node" tag; since the tree is always
1894
+ # completely redrawn, this list will be in vertical order.
1895
+ set nodes {}
1896
+ foreach nodeItem [$win.c find withtag node] {
1897
+ set node [Tree::_get_node_name $win $nodeItem 2]
1898
+ if { [Widget::cget $win.$node -selectable] } {
1899
+ lappend nodes $node
1900
+ }
1901
+ }
1902
+
1903
+ # Keyboard navigation is all relative to the current node
1904
+ # surles: Get the current node for single or multiple selection schemas.
1905
+ set node [_get_current_node $win]
1906
+
1907
+ switch -exact -- $which {
1908
+ "up" {
1909
+ # Up goes to the node that is vertically above the current node
1910
+ # (NOT necessarily the current node's parent)
1911
+ if { [string equal $node ""] } {
1912
+ return
1913
+ }
1914
+ set index [lsearch -exact $nodes $node]
1915
+ incr index -1
1916
+ if { $index >= 0 } {
1917
+ $win selection set [lindex $nodes $index]
1918
+ _set_current_node $win [lindex $nodes $index]
1919
+ $win see [lindex $nodes $index]
1920
+ return
1921
+ }
1922
+ }
1923
+ "down" {
1924
+ # Down goes to the node that is vertically below the current node
1925
+ if { [string equal $node ""] } {
1926
+ $win selection set [lindex $nodes 0]
1927
+ _set_current_node $win [lindex $nodes 0]
1928
+ $win see [lindex $nodes 0]
1929
+ return
1930
+ }
1931
+
1932
+ set index [lsearch -exact $nodes $node]
1933
+ incr index
1934
+ if { $index < [llength $nodes] } {
1935
+ $win selection set [lindex $nodes $index]
1936
+ _set_current_node $win [lindex $nodes $index]
1937
+ $win see [lindex $nodes $index]
1938
+ return
1939
+ }
1940
+ }
1941
+ "right" {
1942
+ # On a right arrow, if the current node is closed, open it.
1943
+ # If the current node is open, go to its first child
1944
+ if { [string equal $node ""] } {
1945
+ return
1946
+ }
1947
+ set open [$win itemcget $node -open]
1948
+ if { $open } {
1949
+ if { [llength [$win nodes $node]] } {
1950
+ set index [lsearch -exact $nodes $node]
1951
+ incr index
1952
+ if { $index < [llength $nodes] } {
1953
+ $win selection set [lindex $nodes $index]
1954
+ _set_current_node $win [lindex $nodes $index]
1955
+ $win see [lindex $nodes $index]
1956
+ return
1957
+ }
1958
+ }
1959
+ } else {
1960
+ $win itemconfigure $node -open 1
1961
+ if {[llength [set cmd [Widget::getoption $win -opencmd]]]} {
1962
+ uplevel \#0 $cmd [list $node]
1963
+ }
1964
+ return
1965
+ }
1966
+ }
1967
+ "left" {
1968
+ # On a left arrow, if the current node is open, close it.
1969
+ # If the current node is closed, go to its parent.
1970
+ if { [string equal $node ""] } {
1971
+ return
1972
+ }
1973
+ set open [$win itemcget $node -open]
1974
+ if { $open } {
1975
+ $win itemconfigure $node -open 0
1976
+ if {[llength [set cmd [Widget::getoption $win -closecmd]]]} {
1977
+ uplevel \#0 $cmd [list $node]
1978
+ }
1979
+ return
1980
+ } else {
1981
+ set parent [$win parent $node]
1982
+ if { [string equal $parent "root"] } {
1983
+ set parent $node
1984
+ } else {
1985
+ while { ![$win itemcget $parent -selectable] } {
1986
+ set parent [$win parent $parent]
1987
+ if { [string equal $parent "root"] } {
1988
+ set parent $node
1989
+ break
1990
+ }
1991
+ }
1992
+ }
1993
+ $win selection set $parent
1994
+ _set_current_node $win $parent
1995
+ $win see $parent
1996
+ return
1997
+ }
1998
+ }
1999
+ "space" {
2000
+ if { [string equal $node ""] } {
2001
+ return
2002
+ }
2003
+ set open [$win itemcget $node -open]
2004
+ if { [llength [$win nodes $node]] } {
2005
+
2006
+ # Toggle the open status of the chosen node.
2007
+
2008
+ $win itemconfigure $node -open [expr {$open?0:1}]
2009
+
2010
+ if {$open} {
2011
+ # Node was open, is now closed. Call the close-cmd
2012
+
2013
+ if {[llength [set cmd [Widget::getoption $win -closecmd]]]} {
2014
+ uplevel \#0 $cmd [list $node]
2015
+ }
2016
+ } else {
2017
+ # Node was closed, is now open. Call the open-cmd
2018
+
2019
+ if {[llength [set cmd [Widget::getoption $win -opencmd]]]} {
2020
+ uplevel \#0 $cmd [list $node]
2021
+ }
2022
+ }
2023
+ }
2024
+ }
2025
+ }
2026
+ return
2027
+ }
2028
+
2029
+ # Tree::_get_current_node --
2030
+ #
2031
+ # Get the current node for either single or multiple
2032
+ # node selection trees. If the tree allows for
2033
+ # multiple selection, return the cursor node. Otherwise,
2034
+ # if there is a selection, return the first node in the
2035
+ # list. If there is no selection, return the root node.
2036
+ #
2037
+ # arguments:
2038
+ # win name of the tree widget
2039
+ #
2040
+ # Results:
2041
+ # The current node.
2042
+
2043
+ proc Tree::_get_current_node {win} {
2044
+ if {[info exists selectTree::selectCursor($win)]} {
2045
+ set result $selectTree::selectCursor($win)
2046
+ } elseif {[llength [set selList [$win selection get]]]} {
2047
+ set result [lindex $selList 0]
2048
+ } else {
2049
+ set result ""
2050
+ }
2051
+ return $result
2052
+ }
2053
+
2054
+ # Tree::_set_current_node --
2055
+ #
2056
+ # Set the current node for either single or multiple
2057
+ # node selection trees.
2058
+ #
2059
+ # arguments:
2060
+ # win Name of the tree widget
2061
+ # node The current node.
2062
+ #
2063
+ # Results:
2064
+ # None.
2065
+
2066
+ proc Tree::_set_current_node {win node} {
2067
+ if {[info exists selectTree::selectCursor($win)]} {
2068
+ set selectTree::selectCursor($win) $node
2069
+ }
2070
+ return
2071
+ }
2072
+
2073
+ # Tree::_get_node_name --
2074
+ #
2075
+ # Given a canvas item, get the name of the tree node represented by that
2076
+ # item.
2077
+ #
2078
+ # Arguments:
2079
+ # path tree to query
2080
+ # item Optional canvas item to examine; if omitted,
2081
+ # defaults to "current"
2082
+ # tagindex Optional tag index, since the n:nodename tag is not
2083
+ # in the same spot for all canvas items. If omitted,
2084
+ # defaults to "end-1", so it works with "current" item.
2085
+ #
2086
+ # Results:
2087
+ # node name of the tree node.
2088
+
2089
+ proc Tree::_get_node_name {path {item current} {tagindex end-1}} {
2090
+ return [string range [lindex [$path.c gettags $item] $tagindex] 2 end]
2091
+ }
2092
+
2093
+ # Tree::_get_node_padx --
2094
+ #
2095
+ # Given a node in the tree, return it's padx value. If the value is
2096
+ # less than 0, default to the padx of the entire tree.
2097
+ #
2098
+ # Arguments:
2099
+ # path Tree to query
2100
+ # node Node in the tree
2101
+ #
2102
+ # Results:
2103
+ # padx The numeric padx value
2104
+ proc Tree::_get_node_padx {path node} {
2105
+ set padx [Widget::getoption $path.$node -padx]
2106
+ if {$padx < 0} { set padx [Widget::getoption $path -padx] }
2107
+ return $padx
2108
+ }
2109
+
2110
+ # Tree::_get_node_deltax --
2111
+ #
2112
+ # Given a node in the tree, return it's deltax value. If the value is
2113
+ # less than 0, default to the deltax of the entire tree.
2114
+ #
2115
+ # Arguments:
2116
+ # path Tree to query
2117
+ # node Node in the tree
2118
+ #
2119
+ # Results:
2120
+ # deltax The numeric deltax value
2121
+ proc Tree::_get_node_deltax {path node} {
2122
+ set deltax [Widget::getoption $path.$node -deltax]
2123
+ if {$deltax < 0} { set deltax [Widget::getoption $path -deltax] }
2124
+ return $deltax
2125
+ }
2126
+
2127
+
2128
+ # Tree::_get_node_tags --
2129
+ #
2130
+ # Given a node in the tree, return a list of tags to apply to its
2131
+ # canvas item.
2132
+ #
2133
+ # Arguments:
2134
+ # path Tree to query
2135
+ # node Node in the tree
2136
+ # tags A list of tags to add to the final list
2137
+ #
2138
+ # Results:
2139
+ # list The list of tags to apply to the canvas item
2140
+ proc Tree::_get_node_tags {path node {tags ""}} {
2141
+ eval [linsert $tags 0 lappend list TreeItemSentinal]
2142
+ if {[Widget::getoption $path.$node -helptext] == ""} { return $list }
2143
+
2144
+ switch -- [Widget::getoption $path.$node -helptype] {
2145
+ balloon {
2146
+ lappend list BwHelpBalloon
2147
+ }
2148
+ variable {
2149
+ lappend list BwHelpVariable
2150
+ }
2151
+ }
2152
+ return $list
2153
+ }
2154
+
2155
+ # Tree::_set_help --
2156
+ #
2157
+ # Register dynamic help for a node in the tree.
2158
+ #
2159
+ # Arguments:
2160
+ # path Tree to query
2161
+ # node Node in the tree
2162
+ # force Optional argument to force a reset of the help
2163
+ #
2164
+ # Results:
2165
+ # none
2166
+ proc Tree::_set_help { path node } {
2167
+ Widget::getVariable $path help
2168
+
2169
+ set item $path.$node
2170
+ set opts [list -helptype -helptext -helpvar]
2171
+ foreach {cty ctx cv} [eval [linsert $opts 0 Widget::hasChangedX $item]] break
2172
+ set text [Widget::getoption $item -helptext]
2173
+
2174
+ ## If we've never set help for this item before, and text is not blank,
2175
+ ## we need to setup help. We also need to reset help if any of the
2176
+ ## options have changed.
2177
+ if { (![info exists help($node)] && $text != "") || $cty || $ctx || $cv } {
2178
+ set help($node) 1
2179
+ set type [Widget::getoption $item -helptype]
2180
+ switch $type {
2181
+ balloon {
2182
+ DynamicHelp::register $path.c balloon n:$node $text
2183
+ DynamicHelp::register $path.c balloon i:$node $text
2184
+ DynamicHelp::register $path.c balloon b:$node $text
2185
+ }
2186
+ variable {
2187
+ set var [Widget::getoption $item -helpvar]
2188
+ DynamicHelp::register $path.c variable n:$node $var $text
2189
+ DynamicHelp::register $path.c variable i:$node $var $text
2190
+ DynamicHelp::register $path.c variable b:$node $var $text
2191
+ }
2192
+ }
2193
+ }
2194
+ }
2195
+
2196
+ proc Tree::_mouse_select { path cmd args } {
2197
+ eval [linsert $args 0 selection $path $cmd]
2198
+ switch -- $cmd {
2199
+ "add" - "clear" - "remove" - "set" - "toggle" {
2200
+ event generate $path <<TreeSelect>>
2201
+ }
2202
+ }
2203
+ }
2204
+
2205
+
2206
+ proc Tree::_node_name { path node } {
2207
+ set map [list & _ | _ ^ _ ! _]
2208
+ return [string map $map $node]
2209
+ }
2210
+
2211
+
2212
+ # ----------------------------------------------------------------------------
2213
+ # Command Tree::_destroy
2214
+ # ----------------------------------------------------------------------------
2215
+ proc Tree::_destroy { path } {
2216
+ variable $path
2217
+ upvar 0 $path data
2218
+
2219
+ if { $data(upd,afterid) != "" } {
2220
+ after cancel $data(upd,afterid)
2221
+ }
2222
+ if { $data(dnd,afterid) != "" } {
2223
+ after cancel $data(dnd,afterid)
2224
+ }
2225
+ _subdelete $path [lrange $data(root) 1 end]
2226
+ Widget::destroy $path
2227
+ unset data
2228
+ }