arcadia 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. data/README +126 -123
  2. data/arcadia.rb +770 -756
  3. data/base/a-contracts.rb +130 -93
  4. data/base/a-ext.rb +280 -280
  5. data/base/a-libs.rb +5 -11
  6. data/base/a-utils.rb +235 -44
  7. data/conf/arcadia.conf +20 -16
  8. data/conf/arcadia.init.rb +0 -0
  9. data/conf/arcadia.res.rb +74 -0
  10. data/ext/ae-complete-code/ae-complete-code.conf +0 -0
  11. data/ext/ae-complete-code/ae-complete-code.rb +80 -79
  12. data/ext/ae-debug/ae-debug.conf +0 -0
  13. data/ext/ae-debug/ae-debug.rb +2 -6
  14. data/ext/ae-debug/debug1.57.rb +0 -0
  15. data/ext/ae-doc-code/ae-doc-code.conf +15 -0
  16. data/ext/ae-doc-code/ae-doc-code.rb +289 -0
  17. data/ext/ae-editor/ae-editor.conf +17 -8
  18. data/ext/ae-editor/ae-editor.rb +738 -396
  19. data/ext/ae-event-log/ae-event-log.conf +0 -0
  20. data/ext/ae-event-log/ae-event-log.rb +0 -0
  21. data/ext/ae-file-history/ae-file-history.conf +2 -2
  22. data/ext/ae-file-history/ae-file-history.rb +286 -290
  23. data/ext/ae-inspector/ae-inspector.conf +0 -0
  24. data/ext/ae-inspector/ae-inspector.rb +0 -0
  25. data/ext/ae-output-event/ae-output-event.conf +2 -2
  26. data/ext/ae-output/ae-output.conf +2 -2
  27. data/ext/ae-output/ae-output.rb +173 -178
  28. data/ext/ae-palette/ae-palette.conf +0 -0
  29. data/ext/ae-palette/ae-palette.rb +0 -0
  30. data/ext/ae-shell/ae-shell.conf +0 -0
  31. data/ext/ae-shell/ae-shell.rb +54 -54
  32. data/lib/tk/al-tk.rb +3076 -3082
  33. data/lib/tk/al-tk.res.rb +0 -0
  34. data/lib/tk/al-tkarcadia.rb +0 -0
  35. data/lib/tk/al-tkcustom.rb +0 -0
  36. data/lib/tkext/al-bwidget.rb +0 -0
  37. data/lib/tkext/al-iwidgets.rb +0 -0
  38. data/lib/tkext/al-tile.rb +0 -0
  39. data/lib/tkext/al-tktable.rb +0 -0
  40. data/tcl/BWidget-1.8.0/BWman/ArrowButton.html +276 -0
  41. data/tcl/BWidget-1.8.0/BWman/BWidget.html +228 -0
  42. data/tcl/BWidget-1.8.0/BWman/Button.html +273 -0
  43. data/tcl/BWidget-1.8.0/BWman/ButtonBox.html +264 -0
  44. data/tcl/BWidget-1.8.0/BWman/ComboBox.html +402 -0
  45. data/tcl/BWidget-1.8.0/BWman/Dialog.html +314 -0
  46. data/tcl/BWidget-1.8.0/BWman/DragSite.html +139 -0
  47. data/tcl/BWidget-1.8.0/BWman/DropSite.html +254 -0
  48. data/tcl/BWidget-1.8.0/BWman/DynamicHelp.html +248 -0
  49. data/tcl/BWidget-1.8.0/BWman/Entry.html +341 -0
  50. data/tcl/BWidget-1.8.0/BWman/Label.html +331 -0
  51. data/tcl/BWidget-1.8.0/BWman/LabelEntry.html +194 -0
  52. data/tcl/BWidget-1.8.0/BWman/LabelFrame.html +144 -0
  53. data/tcl/BWidget-1.8.0/BWman/ListBox.html +678 -0
  54. data/tcl/BWidget-1.8.0/BWman/MainFrame.html +283 -0
  55. data/tcl/BWidget-1.8.0/BWman/MessageDlg.html +218 -0
  56. data/tcl/BWidget-1.8.0/BWman/NoteBook.html +374 -0
  57. data/tcl/BWidget-1.8.0/BWman/PagesManager.html +180 -0
  58. data/tcl/BWidget-1.8.0/BWman/PanedWindow.html +142 -0
  59. data/tcl/BWidget-1.8.0/BWman/PanelFrame.html +153 -0
  60. data/tcl/BWidget-1.8.0/BWman/PasswdDlg.html +214 -0
  61. data/tcl/BWidget-1.8.0/BWman/ProgressBar.html +152 -0
  62. data/tcl/BWidget-1.8.0/BWman/ProgressDlg.html +145 -0
  63. data/tcl/BWidget-1.8.0/BWman/ScrollView.html +130 -0
  64. data/tcl/BWidget-1.8.0/BWman/ScrollableFrame.html +191 -0
  65. data/tcl/BWidget-1.8.0/BWman/ScrolledWindow.html +116 -0
  66. data/tcl/BWidget-1.8.0/BWman/SelectColor.html +164 -0
  67. data/tcl/BWidget-1.8.0/BWman/SelectFont.html +152 -0
  68. data/tcl/BWidget-1.8.0/BWman/Separator.html +77 -0
  69. data/tcl/BWidget-1.8.0/BWman/SpinBox.html +250 -0
  70. data/tcl/BWidget-1.8.0/BWman/StatusBar.html +147 -0
  71. data/tcl/BWidget-1.8.0/BWman/TitleFrame.html +107 -0
  72. data/tcl/BWidget-1.8.0/BWman/Tree.html +947 -0
  73. data/tcl/BWidget-1.8.0/BWman/Widget.html +502 -0
  74. data/tcl/BWidget-1.8.0/BWman/contents.html +84 -0
  75. data/tcl/BWidget-1.8.0/BWman/index.html +7 -0
  76. data/tcl/BWidget-1.8.0/BWman/navtree.html +41 -0
  77. data/tcl/BWidget-1.8.0/BWman/options.htm +458 -0
  78. data/tcl/BWidget-1.8.0/CHANGES.txt +266 -0
  79. data/tcl/BWidget-1.8.0/ChangeLog +1641 -0
  80. data/tcl/BWidget-1.8.0/LICENSE.txt +41 -0
  81. data/tcl/BWidget-1.8.0/README.txt +127 -0
  82. data/tcl/BWidget-1.8.0/arrow.tcl +551 -0
  83. data/tcl/BWidget-1.8.0/bitmap.tcl +94 -0
  84. data/tcl/BWidget-1.8.0/button.tcl +324 -0
  85. data/tcl/BWidget-1.8.0/buttonbox.tcl +403 -0
  86. data/tcl/BWidget-1.8.0/color.tcl +493 -0
  87. data/tcl/BWidget-1.8.0/combobox.tcl +809 -0
  88. data/tcl/BWidget-1.8.0/demo/basic.tcl +199 -0
  89. data/tcl/BWidget-1.8.0/demo/bwidget.xbm +46 -0
  90. data/tcl/BWidget-1.8.0/demo/demo.tcl +212 -0
  91. data/tcl/BWidget-1.8.0/demo/dnd.tcl +42 -0
  92. data/tcl/BWidget-1.8.0/demo/manager.tcl +141 -0
  93. data/tcl/BWidget-1.8.0/demo/select.tcl +59 -0
  94. data/tcl/BWidget-1.8.0/demo/tmpldlg.tcl +214 -0
  95. data/tcl/BWidget-1.8.0/demo/tree.tcl +260 -0
  96. data/tcl/BWidget-1.8.0/demo/x1.xbm +2258 -0
  97. data/tcl/BWidget-1.8.0/dialog.tcl +345 -0
  98. data/tcl/BWidget-1.8.0/dragsite.tcl +197 -0
  99. data/tcl/BWidget-1.8.0/dropsite.tcl +455 -0
  100. data/tcl/BWidget-1.8.0/dynhelp.tcl +625 -0
  101. data/tcl/BWidget-1.8.0/entry.tcl +469 -0
  102. data/tcl/BWidget-1.8.0/font.tcl +566 -0
  103. data/tcl/BWidget-1.8.0/images/bold.gif +0 -0
  104. data/tcl/BWidget-1.8.0/images/copy.gif +0 -0
  105. data/tcl/BWidget-1.8.0/images/cut.gif +0 -0
  106. data/tcl/BWidget-1.8.0/images/dragfile.gif +0 -0
  107. data/tcl/BWidget-1.8.0/images/dragicon.gif +0 -0
  108. data/tcl/BWidget-1.8.0/images/error.gif +0 -0
  109. data/tcl/BWidget-1.8.0/images/file.gif +0 -0
  110. data/tcl/BWidget-1.8.0/images/folder.gif +0 -0
  111. data/tcl/BWidget-1.8.0/images/hourglass.gif +0 -0
  112. data/tcl/BWidget-1.8.0/images/info.gif +0 -0
  113. data/tcl/BWidget-1.8.0/images/italic.gif +0 -0
  114. data/tcl/BWidget-1.8.0/images/minus.xbm +5 -0
  115. data/tcl/BWidget-1.8.0/images/new.gif +0 -0
  116. data/tcl/BWidget-1.8.0/images/opcopy.xbm +5 -0
  117. data/tcl/BWidget-1.8.0/images/open.gif +0 -0
  118. data/tcl/BWidget-1.8.0/images/openfold.gif +0 -0
  119. data/tcl/BWidget-1.8.0/images/oplink.xbm +5 -0
  120. data/tcl/BWidget-1.8.0/images/opmove.xbm +5 -0
  121. data/tcl/BWidget-1.8.0/images/overstrike.gif +0 -0
  122. data/tcl/BWidget-1.8.0/images/palette.gif +0 -0
  123. data/tcl/BWidget-1.8.0/images/passwd.gif +0 -0
  124. data/tcl/BWidget-1.8.0/images/paste.gif +0 -0
  125. data/tcl/BWidget-1.8.0/images/plus.xbm +5 -0
  126. data/tcl/BWidget-1.8.0/images/print.gif +0 -0
  127. data/tcl/BWidget-1.8.0/images/question.gif +0 -0
  128. data/tcl/BWidget-1.8.0/images/redo.gif +0 -0
  129. data/tcl/BWidget-1.8.0/images/save.gif +0 -0
  130. data/tcl/BWidget-1.8.0/images/target.xbm +9 -0
  131. data/tcl/BWidget-1.8.0/images/underline.gif +0 -0
  132. data/tcl/BWidget-1.8.0/images/undo.gif +0 -0
  133. data/tcl/BWidget-1.8.0/images/warning.gif +0 -0
  134. data/tcl/BWidget-1.8.0/init.tcl +40 -0
  135. data/tcl/BWidget-1.8.0/label.tcl +271 -0
  136. data/tcl/BWidget-1.8.0/labelentry.tcl +100 -0
  137. data/tcl/BWidget-1.8.0/labelframe.tcl +160 -0
  138. data/tcl/BWidget-1.8.0/lang/da.rc +52 -0
  139. data/tcl/BWidget-1.8.0/lang/de.rc +52 -0
  140. data/tcl/BWidget-1.8.0/lang/en.rc +52 -0
  141. data/tcl/BWidget-1.8.0/lang/es.rc +53 -0
  142. data/tcl/BWidget-1.8.0/lang/fr.rc +52 -0
  143. data/tcl/BWidget-1.8.0/listbox.tcl +1638 -0
  144. data/tcl/BWidget-1.8.0/mainframe.tcl +711 -0
  145. data/tcl/BWidget-1.8.0/messagedlg.tcl +128 -0
  146. data/tcl/BWidget-1.8.0/notebook.tcl +1164 -0
  147. data/tcl/BWidget-1.8.0/pagesmgr.tcl +294 -0
  148. data/tcl/BWidget-1.8.0/panedw.tcl +381 -0
  149. data/tcl/BWidget-1.8.0/panelframe.tcl +246 -0
  150. data/tcl/BWidget-1.8.0/passwddlg.tcl +178 -0
  151. data/tcl/BWidget-1.8.0/pkgIndex.tcl +47 -0
  152. data/tcl/BWidget-1.8.0/progressbar.tcl +208 -0
  153. data/tcl/BWidget-1.8.0/progressdlg.tcl +87 -0
  154. data/tcl/BWidget-1.8.0/scrollframe.tcl +226 -0
  155. data/tcl/BWidget-1.8.0/scrollview.tcl +254 -0
  156. data/tcl/BWidget-1.8.0/scrollw.tcl +280 -0
  157. data/tcl/BWidget-1.8.0/separator.tcl +75 -0
  158. data/tcl/BWidget-1.8.0/spinbox.tcl +331 -0
  159. data/tcl/BWidget-1.8.0/statusbar.tcl +422 -0
  160. data/tcl/BWidget-1.8.0/tests/entry.test +173 -0
  161. data/tcl/BWidget-1.8.0/titleframe.tcl +170 -0
  162. data/tcl/BWidget-1.8.0/tree.tcl +2228 -0
  163. data/tcl/BWidget-1.8.0/utils.tcl +645 -0
  164. data/tcl/BWidget-1.8.0/widget.tcl +1576 -0
  165. data/tcl/BWidget-1.8.0/wizard.tcl +1028 -0
  166. data/tcl/BWidget-1.8.0/xpm2image.tcl +115 -0
  167. metadata +141 -5
@@ -0,0 +1,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
+ }