arcadia 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }