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,809 @@
1
+ # ----------------------------------------------------------------------------
2
+ # combobox.tcl
3
+ # This file is part of Unifix BWidget Toolkit
4
+ # $Id: combobox.tcl,v 1.34 2006/09/28 15:46:06 dev_null42a Exp $
5
+ # ----------------------------------------------------------------------------
6
+ # Index of commands:
7
+ # - ComboBox::create
8
+ # - ComboBox::configure
9
+ # - ComboBox::cget
10
+ # - ComboBox::setvalue
11
+ # - ComboBox::getvalue
12
+ # - ComboBox::clearvalue
13
+ # - ComboBox::_create_popup
14
+ # - ComboBox::_mapliste
15
+ # - ComboBox::_unmapliste
16
+ # - ComboBox::_select
17
+ # - ComboBox::_modify_value
18
+ # ----------------------------------------------------------------------------
19
+
20
+ # ComboBox uses the 8.3 -listvariable listbox option
21
+ package require Tk 8.3
22
+
23
+ namespace eval ComboBox {
24
+ Widget::define ComboBox combobox ArrowButton Entry ListBox
25
+
26
+ Widget::tkinclude ComboBox frame :cmd \
27
+ include {-relief -borderwidth -bd -background} \
28
+ initialize {-relief sunken -borderwidth 2} \
29
+
30
+ Widget::bwinclude ComboBox Entry .e \
31
+ remove {-relief -bd -borderwidth -bg} \
32
+ rename {-background -entrybg}
33
+
34
+ Widget::declare ComboBox {
35
+ {-height TkResource 0 0 listbox}
36
+ {-values String "" 0}
37
+ {-images String "" 0}
38
+ {-indents String "" 0}
39
+ {-modifycmd String "" 0}
40
+ {-postcommand String "" 0}
41
+ {-expand Enum none 0 {none tab}}
42
+ {-autocomplete Boolean 0 0}
43
+ {-autopost Boolean 0 0}
44
+ {-bwlistbox Boolean 0 0}
45
+ {-listboxwidth Int 0 0}
46
+ {-hottrack Boolean 0 0}
47
+ }
48
+
49
+ Widget::addmap ComboBox ArrowButton .a {
50
+ -background {} -foreground {} -disabledforeground {} -state {}
51
+ }
52
+
53
+ Widget::syncoptions ComboBox Entry .e {-text {}}
54
+
55
+ ::bind BwComboBox <FocusIn> [list after idle {BWidget::refocus %W %W.e}]
56
+ ::bind BwComboBox <Destroy> [list Widget::destroy %W]
57
+
58
+ ::bind ListBoxHotTrack <Motion> {
59
+ %W selection clear 0 end
60
+ %W activate @%x,%y
61
+ %W selection set @%x,%y
62
+ }
63
+ }
64
+
65
+
66
+ # ComboBox::create --
67
+ #
68
+ # Create a combobox widget with the given options.
69
+ #
70
+ # Arguments:
71
+ # path name of the new widget.
72
+ # args optional arguments to the widget.
73
+ #
74
+ # Results:
75
+ # path name of the new widget.
76
+
77
+ proc ComboBox::create { path args } {
78
+ array set maps [list ComboBox {} :cmd {} .e {} .a {}]
79
+ array set maps [Widget::parseArgs ComboBox $args]
80
+
81
+ eval [list frame $path] $maps(:cmd) \
82
+ [list -highlightthickness 0 -takefocus 0 -class ComboBox]
83
+ Widget::initFromODB ComboBox $path $maps(ComboBox)
84
+
85
+ bindtags $path [list $path BwComboBox [winfo toplevel $path] all]
86
+
87
+ set entry [eval [list Entry::create $path.e] $maps(.e) \
88
+ [list -relief flat -borderwidth 0 -takefocus 1]]
89
+
90
+ ::bind $path.e <FocusOut> [list $path _focus_out]
91
+ ::bind $path <<TraverseIn>> [list $path _traverse_in]
92
+
93
+ if {[Widget::cget $path -autocomplete]} {
94
+ ::bind $path.e <KeyRelease> [list $path _auto_complete %K]
95
+ }
96
+
97
+ if {[Widget::cget $path -autopost]} {
98
+ ::bind $path.e <KeyRelease> +[list $path _auto_post %K]
99
+ } else {
100
+ ::bind $entry <Key-Up> [list ComboBox::_unmapliste $path]
101
+ ::bind $entry <Key-Down> [list ComboBox::_mapliste $path]
102
+ }
103
+
104
+ if {[string equal $::tcl_platform(platform) "unix"]} {
105
+ set ipadx 0
106
+ set width 11
107
+ } else {
108
+ set ipadx 2
109
+ set width 15
110
+ }
111
+ set height [winfo reqheight $entry]
112
+ set arrow [eval [list ArrowButton::create $path.a] $maps(.a) \
113
+ [list -width $width -height $height \
114
+ -highlightthickness 0 -borderwidth 1 -takefocus 0 \
115
+ -dir bottom -type button -ipadx $ipadx \
116
+ -command [list ComboBox::_mapliste $path] \
117
+ ]]
118
+
119
+ pack $arrow -side right -fill y
120
+ pack $entry -side left -fill both -expand yes
121
+
122
+ set editable [Widget::cget $path -editable]
123
+ Entry::configure $path.e -editable $editable
124
+ if {$editable} {
125
+ ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
126
+ } else {
127
+ ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
128
+ if { ![string equal [Widget::cget $path -state] "disabled"] } {
129
+ Entry::configure $path.e -takefocus 1
130
+ }
131
+ }
132
+
133
+ ::bind $path <ButtonPress-1> [list ComboBox::_unmapliste $path]
134
+ ::bind $entry <Control-Up> [list ComboBox::_modify_value $path previous]
135
+ ::bind $entry <Control-Down> [list ComboBox::_modify_value $path next]
136
+ ::bind $entry <Control-Prior> [list ComboBox::_modify_value $path first]
137
+ ::bind $entry <Control-Next> [list ComboBox::_modify_value $path last]
138
+
139
+ if {$editable} {
140
+ set expand [Widget::cget $path -expand]
141
+ if {[string equal "tab" $expand]} {
142
+ # Expand entry value on Tab (from -values)
143
+ ::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
144
+ } elseif {[string equal "auto" $expand]} {
145
+ # Expand entry value anytime (from -values)
146
+ #::bind $entry <Key> "[list ComboBox::_expand $path]; break"
147
+ }
148
+ }
149
+
150
+ ## If we have images, we have to use a BWidget ListBox.
151
+ set bw [Widget::cget $path -bwlistbox]
152
+ if {[llength [Widget::cget $path -images]]} {
153
+ Widget::configure $path [list -bwlistbox 1]
154
+ } else {
155
+ Widget::configure $path [list -bwlistbox $bw]
156
+ }
157
+
158
+ return [Widget::create ComboBox $path]
159
+ }
160
+
161
+
162
+ # ComboBox::configure --
163
+ #
164
+ # Configure subcommand for ComboBox widgets. Works like regular
165
+ # widget configure command.
166
+ #
167
+ # Arguments:
168
+ # path Name of the ComboBox widget.
169
+ # args Additional optional arguments:
170
+ # ?-option?
171
+ # ?-option value ...?
172
+ #
173
+ # Results:
174
+ # Depends on arguments. If no arguments are given, returns a complete
175
+ # list of configuration information. If one argument is given, returns
176
+ # the configuration information for that option. If more than one
177
+ # argument is given, returns nothing.
178
+
179
+ proc ComboBox::configure { path args } {
180
+ set res [Widget::configure $path $args]
181
+ set entry $path.e
182
+
183
+
184
+ set list [list -images -values -bwlistbox -hottrack]
185
+ foreach {ci cv cb ch} [eval [linsert $list 0 Widget::hasChangedX $path]] { break }
186
+
187
+ if { $ci } {
188
+ set images [Widget::cget $path -images]
189
+ if {[llength $images]} {
190
+ Widget::configure $path [list -bwlistbox 1]
191
+ } else {
192
+ Widget::configure $path [list -bwlistbox 0]
193
+ }
194
+ }
195
+
196
+ set bw [Widget::cget $path -bwlistbox]
197
+
198
+ ## If the images, bwlistbox, hottrack or values have changed,
199
+ ## destroy the shell so that it will re-create itself the next
200
+ ## time around.
201
+ if { $ci || $cb || $ch || ($bw && $cv) } {
202
+ destroy $path.shell
203
+ }
204
+
205
+ set chgedit [Widget::hasChangedX $path -editable]
206
+ if {$chgedit} {
207
+ if {[Widget::cget $path -editable]} {
208
+ ::bind $entry <ButtonPress-1> [list ComboBox::_unmapliste $path]
209
+ Entry::configure $entry -editable true
210
+ } else {
211
+ ::bind $entry <ButtonPress-1> [list ArrowButton::invoke $path.a]
212
+ Entry::configure $entry -editable false
213
+
214
+ # Make sure that non-editable comboboxes can still be tabbed to.
215
+
216
+ if { ![string equal [Widget::cget $path -state] "disabled"] } {
217
+ Entry::configure $entry -takefocus 1
218
+ }
219
+ }
220
+ }
221
+
222
+ if {$chgedit || [Widget::hasChangedX $path -expand]} {
223
+ # Unset what we may have created.
224
+ ::bind $entry <Tab> {}
225
+ if {[Widget::cget $path -editable]} {
226
+ set expand [Widget::cget $path -expand]
227
+ if {[string equal "tab" $expand]} {
228
+ # Expand entry value on Tab (from -values)
229
+ ::bind $entry <Tab> "[list ComboBox::_expand $path]; break"
230
+ } elseif {[string equal "auto" $expand]} {
231
+ # Expand entry value anytime (from -values)
232
+ #::bind $entry <Key> "[list ComboBox::_expand $path]; break"
233
+ }
234
+ }
235
+ }
236
+
237
+ # if the dropdown listbox is shown, simply force the actual entry
238
+ # colors into it. If it is not shown, the next time the dropdown
239
+ # is shown it'll get the actual colors anyway
240
+ if {[winfo exists $path.shell.listb]} {
241
+ $path.shell.listb configure \
242
+ -bg [Widget::cget $path -entrybg] \
243
+ -fg [Widget::cget $path -foreground] \
244
+ -selectbackground [Widget::cget $path -selectbackground] \
245
+ -selectforeground [Widget::cget $path -selectforeground]
246
+ }
247
+
248
+ return $res
249
+ }
250
+
251
+
252
+ # ----------------------------------------------------------------------------
253
+ # Command ComboBox::cget
254
+ # ----------------------------------------------------------------------------
255
+ proc ComboBox::cget { path option } {
256
+ return [Widget::cget $path $option]
257
+ }
258
+
259
+
260
+ # ----------------------------------------------------------------------------
261
+ # Command ComboBox::setvalue
262
+ # ----------------------------------------------------------------------------
263
+ proc ComboBox::setvalue { path index } {
264
+ set values [Widget::getMegawidgetOption $path -values]
265
+ set value [Entry::cget $path.e -text]
266
+ switch -- $index {
267
+ next {
268
+ if { [set idx [lsearch -exact $values $value]] != -1 } {
269
+ incr idx
270
+ } else {
271
+ set idx [lsearch -exact $values "$value*"]
272
+ }
273
+ }
274
+ previous {
275
+ if { [set idx [lsearch -exact $values $value]] != -1 } {
276
+ incr idx -1
277
+ } else {
278
+ set idx [lsearch -exact $values "$value*"]
279
+ }
280
+ }
281
+ first {
282
+ set idx 0
283
+ }
284
+ last {
285
+ set idx [expr {[llength $values]-1}]
286
+ }
287
+ default {
288
+ if { [string index $index 0] == "@" } {
289
+ set idx [string range $index 1 end]
290
+ if { ![string is integer -strict $idx] } {
291
+ return -code error "bad index \"$index\""
292
+ }
293
+ } else {
294
+ return -code error "bad index \"$index\""
295
+ }
296
+ }
297
+ }
298
+ if { $idx >= 0 && $idx < [llength $values] } {
299
+ set newval [lindex $values $idx]
300
+ Entry::configure $path.e -text $newval
301
+ return 1
302
+ }
303
+ return 0
304
+ }
305
+
306
+
307
+ proc ComboBox::icursor { path idx } {
308
+ return [$path.e icursor $idx]
309
+ }
310
+
311
+
312
+ proc ComboBox::get { path } {
313
+ return [$path.e get]
314
+ }
315
+
316
+
317
+ # ----------------------------------------------------------------------------
318
+ # Command ComboBox::getvalue
319
+ # ----------------------------------------------------------------------------
320
+ proc ComboBox::getvalue { path } {
321
+ set values [Widget::getMegawidgetOption $path -values]
322
+ set value [Entry::cget $path.e -text]
323
+
324
+ return [lsearch -exact $values $value]
325
+ }
326
+
327
+
328
+ proc ComboBox::getlistbox { path } {
329
+ _create_popup $path
330
+ return $path.shell.listb
331
+ }
332
+
333
+
334
+ # ----------------------------------------------------------------------------
335
+ # Command ComboBox::post
336
+ # ----------------------------------------------------------------------------
337
+ proc ComboBox::post { path } {
338
+ _mapliste $path
339
+ return
340
+ }
341
+
342
+
343
+ proc ComboBox::unpost { path } {
344
+ _unmapliste $path
345
+ return
346
+ }
347
+
348
+
349
+ # ----------------------------------------------------------------------------
350
+ # Command ComboBox::bind
351
+ # ----------------------------------------------------------------------------
352
+ proc ComboBox::bind { path args } {
353
+ return [eval [list ::bind $path.e] $args]
354
+ }
355
+
356
+
357
+ proc ComboBox::insert { path idx args } {
358
+ upvar #0 [Widget::varForOption $path -values] values
359
+
360
+ if {[Widget::cget $path -bwlistbox]} {
361
+ set l [$path getlistbox]
362
+ set i [eval [linsert $args 0 $l insert $idx #auto]]
363
+ set text [$l itemcget $i -text]
364
+ if {$idx == "end"} {
365
+ lappend values $text
366
+ } else {
367
+ set values [linsert $values $idx $text]
368
+ }
369
+ } else {
370
+ set values [eval [list linsert $values $idx] $args]
371
+ }
372
+ }
373
+
374
+ # ----------------------------------------------------------------------------
375
+ # Command ComboBox::clearvalue
376
+ # ----------------------------------------------------------------------------
377
+ proc ComboBox::clearvalue { path } {
378
+ Entry::configure $path.e -text ""
379
+ }
380
+
381
+ # ----------------------------------------------------------------------------
382
+ # Command ComboBox::_create_popup
383
+ # ----------------------------------------------------------------------------
384
+ proc ComboBox::_create_popup { path } {
385
+ set shell $path.shell
386
+
387
+ if {[winfo exists $shell]} { return }
388
+
389
+ set lval [Widget::cget $path -values]
390
+ set h [Widget::cget $path -height]
391
+ set bw [Widget::cget $path -bwlistbox]
392
+
393
+ if { $h <= 0 } {
394
+ set len [llength $lval]
395
+ if { $len < 3 } {
396
+ set h 3
397
+ } elseif { $len > 10 } {
398
+ set h 10
399
+ } else {
400
+ set h $len
401
+ }
402
+ }
403
+
404
+ if { $::tcl_platform(platform) == "unix" } {
405
+ set sbwidth 11
406
+ } else {
407
+ set sbwidth 15
408
+ }
409
+
410
+ toplevel $shell -relief solid -bd 1
411
+ wm withdraw $shell
412
+ update idle
413
+ wm overrideredirect $shell 1
414
+ wm transient $shell [winfo toplevel $path]
415
+ catch { wm attributes $shell -topmost 1 }
416
+
417
+ set sw [ScrolledWindow $shell.sw -managed 0 -size $sbwidth -ipad 0]
418
+
419
+ if {$bw} {
420
+ set listb [ListBox $shell.listb \
421
+ -relief flat -borderwidth 0 -highlightthickness 0 \
422
+ -selectmode single -selectfill 1 -autofocus 0 -height $h \
423
+ -font [Widget::cget $path -font] \
424
+ -bg [Widget::cget $path -entrybg] \
425
+ -fg [Widget::cget $path -foreground] \
426
+ -selectbackground [Widget::cget $path -selectbackground] \
427
+ -selectforeground [Widget::cget $path -selectforeground]]
428
+
429
+ set values [Widget::cget $path -values]
430
+ set images [Widget::cget $path -images]
431
+ foreach value $values image $images {
432
+ $listb insert end #auto -text $value -image $image
433
+ }
434
+ $listb bindText <1> [list ComboBox::_select $path]
435
+ $listb bindImage <1> [list ComboBox::_select $path]
436
+ if {[Widget::cget $path -hottrack]} {
437
+ $listb bindText <Enter> [list $listb selection set]
438
+ $listb bindImage <Enter> [list $listb selection set]
439
+ }
440
+ } else {
441
+ set listb [listbox $shell.listb \
442
+ -relief flat -borderwidth 0 -highlightthickness 0 \
443
+ -exportselection false \
444
+ -font [Widget::cget $path -font] \
445
+ -height $h \
446
+ -bg [Widget::cget $path -entrybg] \
447
+ -fg [Widget::cget $path -foreground] \
448
+ -selectbackground [Widget::cget $path -selectbackground] \
449
+ -selectforeground [Widget::cget $path -selectforeground] \
450
+ -listvariable [Widget::varForOption $path -values]]
451
+ ::bind $listb <ButtonRelease-1> [list ComboBox::_select $path @%x,%y]
452
+
453
+ if {[Widget::cget $path -hottrack]} {
454
+ bindtags $listb [concat [bindtags $listb] ListBoxHotTrack]
455
+ }
456
+ }
457
+ pack $sw -fill both -expand yes
458
+ $sw setwidget $listb
459
+
460
+ ::bind $listb <Return> "ComboBox::_select [list $path] \[%W curselection\]"
461
+ ::bind $listb <Escape> [list ComboBox::_unmapliste $path]
462
+ ::bind $listb <FocusOut> [list ComboBox::_focus_out $path]
463
+ }
464
+
465
+
466
+ proc ComboBox::_recreate_popup { path } {
467
+ variable background
468
+ variable foreground
469
+
470
+ set shell $path.shell
471
+ set lval [Widget::cget $path -values]
472
+ set h [Widget::cget $path -height]
473
+ set bw [Widget::cget $path -bwlistbox]
474
+
475
+ if { $h <= 0 } {
476
+ set len [llength $lval]
477
+ if { $len < 3 } {
478
+ set h 3
479
+ } elseif { $len > 10 } {
480
+ set h 10
481
+ } else {
482
+ set h $len
483
+ }
484
+ }
485
+
486
+ if { $::tcl_platform(platform) == "unix" } {
487
+ set sbwidth 11
488
+ } else {
489
+ set sbwidth 15
490
+ }
491
+
492
+ _create_popup $path
493
+
494
+ if {![Widget::cget $path -editable]} {
495
+ if {[info exists background]} {
496
+ $path.e configure -bg $background
497
+ $path.e configure -fg $foreground
498
+ unset background
499
+ unset foreground
500
+ }
501
+ }
502
+
503
+ set listb $shell.listb
504
+ destroy $shell.sw
505
+ set sw [ScrolledWindow $shell.sw -managed 0 -size $sbwidth -ipad 0]
506
+ $listb configure \
507
+ -height $h \
508
+ -font [Widget::cget $path -font] \
509
+ -bg [Widget::cget $path -entrybg] \
510
+ -fg [Widget::cget $path -foreground] \
511
+ -selectbackground [Widget::cget $path -selectbackground] \
512
+ -selectforeground [Widget::cget $path -selectforeground]
513
+ pack $sw -fill both -expand yes
514
+ $sw setwidget $listb
515
+ raise $listb
516
+ }
517
+
518
+
519
+ # ----------------------------------------------------------------------------
520
+ # Command ComboBox::_mapliste
521
+ # ----------------------------------------------------------------------------
522
+ proc ComboBox::_mapliste { path } {
523
+ set listb $path.shell.listb
524
+ if {[winfo exists $path.shell] &&
525
+ [string equal [wm state $path.shell] "normal"]} {
526
+ _unmapliste $path
527
+ return
528
+ }
529
+
530
+ if { [Widget::cget $path -state] == "disabled" } {
531
+ return
532
+ }
533
+ if {[llength [set cmd [Widget::getMegawidgetOption $path -postcommand]]]} {
534
+ uplevel \#0 $cmd
535
+ }
536
+ if { ![llength [Widget::getMegawidgetOption $path -values]] } {
537
+ return
538
+ }
539
+
540
+ _recreate_popup $path
541
+
542
+ ArrowButton::configure $path.a -relief sunken
543
+ update
544
+
545
+ set bw [Widget::cget $path -bwlistbox]
546
+
547
+ $listb selection clear 0 end
548
+ set values [Widget::getMegawidgetOption $path -values]
549
+ set curval [Entry::cget $path.e -text]
550
+ if { [set idx [lsearch -exact $values $curval]] != -1 ||
551
+ [set idx [lsearch -exact $values "$curval*"]] != -1 } {
552
+ if {$bw} {
553
+ set idx [$listb items $idx]
554
+ } else {
555
+ $listb activate $idx
556
+ }
557
+ $listb selection set $idx
558
+ $listb see $idx
559
+ } else {
560
+ set idx 0
561
+ if {$bw} {
562
+ set idx [$listb items 0]
563
+ } else {
564
+ $listb activate $idx
565
+ }
566
+ $listb selection set $idx
567
+ $listb see $idx
568
+ }
569
+
570
+ set width [Widget::cget $path -listboxwidth]
571
+ if {!$width} { set width [winfo width $path] }
572
+ BWidget::place $path.shell $width 0 below $path
573
+ wm deiconify $path.shell
574
+ raise $path.shell
575
+ BWidget::focus set $listb
576
+ BWidget::grab global $path
577
+ }
578
+
579
+
580
+ # ----------------------------------------------------------------------------
581
+ # Command ComboBox::_unmapliste
582
+ # ----------------------------------------------------------------------------
583
+ proc ComboBox::_unmapliste { path {refocus 1} } {
584
+ if {[winfo exists $path.shell] && \
585
+ [string equal [wm state $path.shell] "normal"]} {
586
+ BWidget::grab release $path
587
+ BWidget::focus release $path.shell.listb $refocus
588
+ # Update now because otherwise [focus -force...] makes the app hang!
589
+ if {$refocus} {
590
+ update
591
+ focus -force $path.e
592
+ }
593
+ wm withdraw $path.shell
594
+ ArrowButton::configure $path.a -relief raised
595
+ }
596
+ }
597
+
598
+
599
+ # ----------------------------------------------------------------------------
600
+ # Command ComboBox::_select
601
+ # ----------------------------------------------------------------------------
602
+ proc ComboBox::_select { path index } {
603
+ set index [$path.shell.listb index $index]
604
+ _unmapliste $path
605
+ if { $index != -1 } {
606
+ if { [setvalue $path @$index] } {
607
+ set cmd [Widget::getMegawidgetOption $path -modifycmd]
608
+ if {[llength $cmd]} {
609
+ uplevel \#0 $cmd
610
+ }
611
+ }
612
+ }
613
+ $path.e selection clear
614
+ $path.e selection range 0 end
615
+ }
616
+
617
+
618
+ # ----------------------------------------------------------------------------
619
+ # Command ComboBox::_modify_value
620
+ # ----------------------------------------------------------------------------
621
+ proc ComboBox::_modify_value { path direction } {
622
+ if {[setvalue $path $direction]
623
+ && [llength [set cmd [Widget::getMegawidgetOption $path -modifycmd]]]} {
624
+ uplevel \#0 $cmd
625
+ }
626
+ }
627
+
628
+ # ----------------------------------------------------------------------------
629
+ # Command ComboBox::_expand
630
+ # ----------------------------------------------------------------------------
631
+ proc ComboBox::_expand {path} {
632
+ set values [Widget::getMegawidgetOption $path -values]
633
+ if {![llength $values]} {
634
+ bell
635
+ return 0
636
+ }
637
+
638
+ set found {}
639
+ set curval [Entry::cget $path.e -text]
640
+ set curlen [$path.e index insert]
641
+ if {$curlen < [string length $curval]} {
642
+ # we are somewhere in the middle of a string.
643
+ # if the full value matches some string in the listbox,
644
+ # reorder values to start matching after that string.
645
+ set idx [lsearch -exact $values $curval]
646
+ if {$idx >= 0} {
647
+ set values [concat [lrange $values [expr {$idx+1}] end] \
648
+ [lrange $values 0 $idx]]
649
+ }
650
+ }
651
+ if {$curlen == 0} {
652
+ set found $values
653
+ } else {
654
+ foreach val $values {
655
+ if {[string equal -length $curlen $curval $val]} {
656
+ lappend found $val
657
+ }
658
+ }
659
+ }
660
+ if {[llength $found]} {
661
+ Entry::configure $path.e -text [lindex $found 0]
662
+ if {[llength $found] > 1} {
663
+ set best [_best_match $found [string range $curval 0 $curlen]]
664
+ set blen [string length $best]
665
+ $path.e icursor $blen
666
+ $path.e selection range $blen end
667
+ }
668
+ } else {
669
+ bell
670
+ }
671
+ return [llength $found]
672
+ }
673
+
674
+ # best_match --
675
+ # finds the best unique match in a list of names
676
+ # The extra $e in this argument allows us to limit the innermost loop a
677
+ # little further.
678
+ # Arguments:
679
+ # l list to find best unique match in
680
+ # e currently best known unique match
681
+ # Returns:
682
+ # longest unique match in the list
683
+ #
684
+ proc ComboBox::_best_match {l {e {}}} {
685
+ set ec [lindex $l 0]
686
+ if {[llength $l]>1} {
687
+ set e [string length $e]; incr e -1
688
+ set ei [string length $ec]; incr ei -1
689
+ foreach l $l {
690
+ while {$ei>=$e && [string first $ec $l]} {
691
+ set ec [string range $ec 0 [incr ei -1]]
692
+ }
693
+ }
694
+ }
695
+ return $ec
696
+ }
697
+ # possibly faster
698
+ #proc match {string1 string2} {
699
+ # set i 1
700
+ # while {[string equal -length $i $string1 $string2]} { incr i }
701
+ # return [string range $string1 0 [expr {$i-2}]]
702
+ #}
703
+ #proc matchlist {list} {
704
+ # set list [lsort $list]
705
+ # return [match [lindex $list 0] [lindex $list end]]
706
+ #}
707
+
708
+
709
+ # ----------------------------------------------------------------------------
710
+ # Command ComboBox::_traverse_in
711
+ # Called when widget receives keyboard focus due to keyboard traversal.
712
+ # ----------------------------------------------------------------------------
713
+ proc ComboBox::_traverse_in { path } {
714
+ if {[$path.e selection present] != 1} {
715
+ # Autohighlight the selection, but not if one existed
716
+ $path.e selection range 0 end
717
+ }
718
+ }
719
+
720
+
721
+ # ----------------------------------------------------------------------------
722
+ # Command ComboBox::_focus_out
723
+ # ----------------------------------------------------------------------------
724
+ proc ComboBox::_focus_out { path } {
725
+ if {[string first $path [focus]] != 0} {
726
+ # we lost focus to some other app or window, so remove the listbox
727
+ return [_unmapliste $path 0]
728
+ }
729
+ }
730
+
731
+ proc ComboBox::_auto_complete { path key } {
732
+ ## Any key string with more than one character and is not entirely
733
+ ## lower-case is considered a function key and is thus ignored.
734
+ if {[string length $key] > 1 && [string tolower $key] != $key} { return }
735
+
736
+ set text [string map [list {[} {\[} {]} {\]}] [$path.e get]]
737
+ if {[string equal $text ""]} { return }
738
+ set values [Widget::cget $path -values]
739
+ set x [lsearch $values $text*]
740
+ if {$x < 0} { return }
741
+
742
+ set idx [$path.e index insert]
743
+ $path.e configure -text [lindex $values $x]
744
+ $path.e icursor $idx
745
+ $path.e select range insert end
746
+ }
747
+
748
+ proc ComboBox::_auto_post { path key } {
749
+ if {[string equal $key "Escape"] || [string equal $key "Return"]} {
750
+ _unmapliste $path
751
+ return
752
+ }
753
+ if {[catch {$path.shell.listb curselection} x] || $x == ""} {
754
+ if {[string equal $key "Up"]} {
755
+ _unmapliste $path
756
+ return
757
+ }
758
+ set x -1
759
+ }
760
+ if {([string length $key] > 1 && [string tolower $key] != $key) && \
761
+ [string equal $key "Backspace"] != 0 && \
762
+ [string equal $key "Up"] != 0 && \
763
+ [string equal $key "Down"] != 0} {
764
+ return
765
+ }
766
+
767
+ # post the listbox
768
+ _create_popup $path
769
+ set width [Widget::cget $path -listboxwidth]
770
+ if {!$width} { set width [winfo width $path] }
771
+ BWidget::place $path.shell $width 0 below $path
772
+ wm deiconify $path.shell
773
+ BWidget::grab release $path
774
+ BWidget::focus release $path.shell.listb 1
775
+ focus -force $path.e
776
+
777
+ set values [Widget::cget $path -values]
778
+ switch -- $key {
779
+ Up {
780
+ if {[incr x -1] < 0} {
781
+ set x 0
782
+ } else {
783
+ Entry::configure $path.e -text [lindex $values $x]
784
+ }
785
+ }
786
+ Down {
787
+ if {[incr x] >= [llength $values]} {
788
+ set x [expr {[llength $values] - 1}]
789
+ } else {
790
+ Entry::configure $path.e -text [lindex $values $x]
791
+ }
792
+ }
793
+ default {
794
+ # auto-select within the listbox the item closest to the entry's value
795
+ set text [string map [list {[} {\[} {]} {\]}] [$path.e get]]
796
+ if {[string equal $text ""]} {
797
+ set x 0
798
+ } else {
799
+ set x [lsearch $values $text*]
800
+ }
801
+ }
802
+ }
803
+
804
+ if {$x >= 0} {
805
+ $path.shell.listb selection clear 0 end
806
+ $path.shell.listb selection set $x
807
+ $path.shell.listb see $x
808
+ }
809
+ }