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,1576 @@
1
+ # ----------------------------------------------------------------------------
2
+ # widget.tcl
3
+ # This file is part of Unifix BWidget Toolkit
4
+ # $Id: widget.tcl,v 1.29 2005/07/28 00:40:42 hobbs Exp $
5
+ # ----------------------------------------------------------------------------
6
+ # Index of commands:
7
+ # - Widget::tkinclude
8
+ # - Widget::bwinclude
9
+ # - Widget::declare
10
+ # - Widget::addmap
11
+ # - Widget::init
12
+ # - Widget::destroy
13
+ # - Widget::setoption
14
+ # - Widget::configure
15
+ # - Widget::cget
16
+ # - Widget::subcget
17
+ # - Widget::hasChanged
18
+ # - Widget::options
19
+ # - Widget::_get_tkwidget_options
20
+ # - Widget::_test_tkresource
21
+ # - Widget::_test_bwresource
22
+ # - Widget::_test_synonym
23
+ # - Widget::_test_string
24
+ # - Widget::_test_flag
25
+ # - Widget::_test_enum
26
+ # - Widget::_test_int
27
+ # - Widget::_test_boolean
28
+ # ----------------------------------------------------------------------------
29
+ # Each megawidget gets a namespace of the same name inside the Widget namespace
30
+ # Each of these has an array opt, which contains information about the
31
+ # megawidget options. It maps megawidget options to a list with this format:
32
+ # {optionType defaultValue isReadonly {additionalOptionalInfo}}
33
+ # Option types and their additional optional info are:
34
+ # TkResource {genericTkWidget genericTkWidgetOptionName}
35
+ # BwResource {nothing}
36
+ # Enum {list of enumeration values}
37
+ # Int {Boundary information}
38
+ # Boolean {nothing}
39
+ # String {nothing}
40
+ # Flag {string of valid flag characters}
41
+ # Synonym {nothing}
42
+ # Color {nothing}
43
+ #
44
+ # Next, each namespace has an array map, which maps class options to their
45
+ # component widget options:
46
+ # map(-foreground) => {.e -foreground .f -foreground}
47
+ #
48
+ # Each has an array ${path}:opt, which contains the value of each megawidget
49
+ # option for a particular instance $path of the megawidget, and an array
50
+ # ${path}:mod, which stores the "changed" status of configuration options.
51
+
52
+ # Steps for creating a bwidget megawidget:
53
+ # 1. parse args to extract subwidget spec
54
+ # 2. Create frame with appropriate class and command line options
55
+ # 3. Get initialization options from optionDB, using frame
56
+ # 4. create subwidgets
57
+
58
+ # Uses newer string operations
59
+ package require Tcl 8.1.1
60
+
61
+ namespace eval Widget {
62
+ variable _optiontype
63
+ variable _class
64
+ variable _tk_widget
65
+
66
+ # This controls whether we try to use themed widgets from Tile
67
+ variable _theme 0
68
+
69
+ variable _aqua [expr {($::tcl_version >= 8.4) &&
70
+ [string equal [tk windowingsystem] "aqua"]}]
71
+
72
+ array set _optiontype {
73
+ TkResource Widget::_test_tkresource
74
+ BwResource Widget::_test_bwresource
75
+ Enum Widget::_test_enum
76
+ Int Widget::_test_int
77
+ Boolean Widget::_test_boolean
78
+ String Widget::_test_string
79
+ Flag Widget::_test_flag
80
+ Synonym Widget::_test_synonym
81
+ Color Widget::_test_color
82
+ Padding Widget::_test_padding
83
+ }
84
+
85
+ proc use {} {}
86
+ }
87
+
88
+
89
+ # ----------------------------------------------------------------------------
90
+ # Command Widget::tkinclude
91
+ # Includes tk widget resources to BWidget widget.
92
+ # class class name of the BWidget
93
+ # tkwidget tk widget to include
94
+ # subpath subpath to configure
95
+ # args additionnal args for included options
96
+ # ----------------------------------------------------------------------------
97
+ proc Widget::tkinclude { class tkwidget subpath args } {
98
+ foreach {cmd lopt} $args {
99
+ # cmd can be
100
+ # include options to include lopt = {opt ...}
101
+ # remove options to remove lopt = {opt ...}
102
+ # rename options to rename lopt = {opt newopt ...}
103
+ # prefix options to prefix lopt = {pref opt opt ..}
104
+ # initialize set default value for options lopt = {opt value ...}
105
+ # readonly set readonly flag for options lopt = {opt flag ...}
106
+ switch -- $cmd {
107
+ remove {
108
+ foreach option $lopt {
109
+ set remove($option) 1
110
+ }
111
+ }
112
+ include {
113
+ foreach option $lopt {
114
+ set include($option) 1
115
+ }
116
+ }
117
+ prefix {
118
+ set prefix [lindex $lopt 0]
119
+ foreach option [lrange $lopt 1 end] {
120
+ set rename($option) "-$prefix[string range $option 1 end]"
121
+ }
122
+ }
123
+ rename -
124
+ readonly -
125
+ initialize {
126
+ array set $cmd $lopt
127
+ }
128
+ default {
129
+ return -code error "invalid argument \"$cmd\""
130
+ }
131
+ }
132
+ }
133
+
134
+ namespace eval $class {}
135
+ upvar 0 ${class}::opt classopt
136
+ upvar 0 ${class}::map classmap
137
+ upvar 0 ${class}::map$subpath submap
138
+ upvar 0 ${class}::optionExports exports
139
+
140
+ set foo [$tkwidget ".ericFoo###"]
141
+ # create resources informations from tk widget resources
142
+ foreach optdesc [_get_tkwidget_options $tkwidget] {
143
+ set option [lindex $optdesc 0]
144
+ if { (![info exists include] || [info exists include($option)]) &&
145
+ ![info exists remove($option)] } {
146
+ if { [llength $optdesc] == 3 } {
147
+ # option is a synonym
148
+ set syn [lindex $optdesc 1]
149
+ if { ![info exists remove($syn)] } {
150
+ # original option is not removed
151
+ if { [info exists rename($syn)] } {
152
+ set classopt($option) [list Synonym $rename($syn)]
153
+ } else {
154
+ set classopt($option) [list Synonym $syn]
155
+ }
156
+ }
157
+ } else {
158
+ if { [info exists rename($option)] } {
159
+ set realopt $option
160
+ set option $rename($option)
161
+ } else {
162
+ set realopt $option
163
+ }
164
+ if { [info exists initialize($option)] } {
165
+ set value $initialize($option)
166
+ } else {
167
+ set value [lindex $optdesc 1]
168
+ }
169
+ if { [info exists readonly($option)] } {
170
+ set ro $readonly($option)
171
+ } else {
172
+ set ro 0
173
+ }
174
+ set classopt($option) \
175
+ [list TkResource $value $ro [list $tkwidget $realopt]]
176
+
177
+ # Add an option database entry for this option
178
+ set optionDbName ".[lindex [_configure_option $option ""] 0]"
179
+ if { ![string equal $subpath ":cmd"] } {
180
+ set optionDbName "$subpath$optionDbName"
181
+ }
182
+ option add *${class}$optionDbName $value widgetDefault
183
+ lappend exports($option) "$optionDbName"
184
+
185
+ # Store the forward and backward mappings for this
186
+ # option <-> realoption pair
187
+ lappend classmap($option) $subpath "" $realopt
188
+ set submap($realopt) $option
189
+ }
190
+ }
191
+ }
192
+ ::destroy $foo
193
+ }
194
+
195
+
196
+ # ----------------------------------------------------------------------------
197
+ # Command Widget::bwinclude
198
+ # Includes BWidget resources to BWidget widget.
199
+ # class class name of the BWidget
200
+ # subclass BWidget class to include
201
+ # subpath subpath to configure
202
+ # args additionnal args for included options
203
+ # ----------------------------------------------------------------------------
204
+ proc Widget::bwinclude { class subclass subpath args } {
205
+ foreach {cmd lopt} $args {
206
+ # cmd can be
207
+ # include options to include lopt = {opt ...}
208
+ # remove options to remove lopt = {opt ...}
209
+ # rename options to rename lopt = {opt newopt ...}
210
+ # prefix options to prefix lopt = {prefix opt opt ...}
211
+ # initialize set default value for options lopt = {opt value ...}
212
+ # readonly set readonly flag for options lopt = {opt flag ...}
213
+ switch -- $cmd {
214
+ remove {
215
+ foreach option $lopt {
216
+ set remove($option) 1
217
+ }
218
+ }
219
+ include {
220
+ foreach option $lopt {
221
+ set include($option) 1
222
+ }
223
+ }
224
+ prefix {
225
+ set prefix [lindex $lopt 0]
226
+ foreach option [lrange $lopt 1 end] {
227
+ set rename($option) "-$prefix[string range $option 1 end]"
228
+ }
229
+ }
230
+ rename -
231
+ readonly -
232
+ initialize {
233
+ array set $cmd $lopt
234
+ }
235
+ default {
236
+ return -code error "invalid argument \"$cmd\""
237
+ }
238
+ }
239
+ }
240
+
241
+ namespace eval $class {}
242
+ upvar 0 ${class}::opt classopt
243
+ upvar 0 ${class}::map classmap
244
+ upvar 0 ${class}::map$subpath submap
245
+ upvar 0 ${class}::optionExports exports
246
+ upvar 0 ${subclass}::opt subclassopt
247
+ upvar 0 ${subclass}::optionExports subexports
248
+
249
+ # create resources informations from BWidget resources
250
+ foreach {option optdesc} [array get subclassopt] {
251
+ set subOption $option
252
+ if { (![info exists include] || [info exists include($option)]) &&
253
+ ![info exists remove($option)] } {
254
+ set type [lindex $optdesc 0]
255
+ if { [string equal $type "Synonym"] } {
256
+ # option is a synonym
257
+ set syn [lindex $optdesc 1]
258
+ if { ![info exists remove($syn)] } {
259
+ if { [info exists rename($syn)] } {
260
+ set classopt($option) [list Synonym $rename($syn)]
261
+ } else {
262
+ set classopt($option) [list Synonym $syn]
263
+ }
264
+ }
265
+ } else {
266
+ if { [info exists rename($option)] } {
267
+ set realopt $option
268
+ set option $rename($option)
269
+ } else {
270
+ set realopt $option
271
+ }
272
+ if { [info exists initialize($option)] } {
273
+ set value $initialize($option)
274
+ } else {
275
+ set value [lindex $optdesc 1]
276
+ }
277
+ if { [info exists readonly($option)] } {
278
+ set ro $readonly($option)
279
+ } else {
280
+ set ro [lindex $optdesc 2]
281
+ }
282
+ set classopt($option) \
283
+ [list $type $value $ro [lindex $optdesc 3]]
284
+
285
+ # Add an option database entry for this option
286
+ foreach optionDbName $subexports($subOption) {
287
+ if { ![string equal $subpath ":cmd"] } {
288
+ set optionDbName "$subpath$optionDbName"
289
+ }
290
+ # Only add the option db entry if we are overriding the
291
+ # normal widget default
292
+ if { [info exists initialize($option)] } {
293
+ option add *${class}$optionDbName $value \
294
+ widgetDefault
295
+ }
296
+ lappend exports($option) "$optionDbName"
297
+ }
298
+
299
+ # Store the forward and backward mappings for this
300
+ # option <-> realoption pair
301
+ lappend classmap($option) $subpath $subclass $realopt
302
+ set submap($realopt) $option
303
+ }
304
+ }
305
+ }
306
+ }
307
+
308
+
309
+ # ----------------------------------------------------------------------------
310
+ # Command Widget::declare
311
+ # Declares new options to BWidget class.
312
+ # ----------------------------------------------------------------------------
313
+ proc Widget::declare { class optlist } {
314
+ variable _optiontype
315
+
316
+ namespace eval $class {}
317
+ upvar 0 ${class}::opt classopt
318
+ upvar 0 ${class}::optionExports exports
319
+ upvar 0 ${class}::optionClass optionClass
320
+
321
+ foreach optdesc $optlist {
322
+ set option [lindex $optdesc 0]
323
+ set optdesc [lrange $optdesc 1 end]
324
+ set type [lindex $optdesc 0]
325
+
326
+ if { ![info exists _optiontype($type)] } {
327
+ # invalid resource type
328
+ return -code error "invalid option type \"$type\""
329
+ }
330
+
331
+ if { [string equal $type "Synonym"] } {
332
+ # test existence of synonym option
333
+ set syn [lindex $optdesc 1]
334
+ if { ![info exists classopt($syn)] } {
335
+ return -code error "unknow option \"$syn\" for Synonym \"$option\""
336
+ }
337
+ set classopt($option) [list Synonym $syn]
338
+ continue
339
+ }
340
+
341
+ # all other resource may have default value, readonly flag and
342
+ # optional arg depending on type
343
+ set value [lindex $optdesc 1]
344
+ set ro [lindex $optdesc 2]
345
+ set arg [lindex $optdesc 3]
346
+
347
+ if { [string equal $type "BwResource"] } {
348
+ # We don't keep BwResource. We simplify to type of sub BWidget
349
+ set subclass [lindex $arg 0]
350
+ set realopt [lindex $arg 1]
351
+ if { ![string length $realopt] } {
352
+ set realopt $option
353
+ }
354
+
355
+ upvar 0 ${subclass}::opt subclassopt
356
+ if { ![info exists subclassopt($realopt)] } {
357
+ return -code error "unknow option \"$realopt\""
358
+ }
359
+ set suboptdesc $subclassopt($realopt)
360
+ if { $value == "" } {
361
+ # We initialize default value
362
+ set value [lindex $suboptdesc 1]
363
+ }
364
+ set type [lindex $suboptdesc 0]
365
+ set ro [lindex $suboptdesc 2]
366
+ set arg [lindex $suboptdesc 3]
367
+ set optionDbName ".[lindex [_configure_option $option ""] 0]"
368
+ option add *${class}${optionDbName} $value widgetDefault
369
+ set exports($option) $optionDbName
370
+ set classopt($option) [list $type $value $ro $arg]
371
+ continue
372
+ }
373
+
374
+ # retreive default value for TkResource
375
+ if { [string equal $type "TkResource"] } {
376
+ set tkwidget [lindex $arg 0]
377
+ set foo [$tkwidget ".ericFoo##"]
378
+ set realopt [lindex $arg 1]
379
+ if { ![string length $realopt] } {
380
+ set realopt $option
381
+ }
382
+ set tkoptions [_get_tkwidget_options $tkwidget]
383
+ if { ![string length $value] } {
384
+ # We initialize default value
385
+ set ind [lsearch $tkoptions [list $realopt *]]
386
+ set value [lindex [lindex $tkoptions $ind] end]
387
+ }
388
+ set optionDbName ".[lindex [_configure_option $option ""] 0]"
389
+ option add *${class}${optionDbName} $value widgetDefault
390
+ set exports($option) $optionDbName
391
+ set classopt($option) [list TkResource $value $ro \
392
+ [list $tkwidget $realopt]]
393
+ set optionClass($option) [lindex [$foo configure $realopt] 1]
394
+ ::destroy $foo
395
+ continue
396
+ }
397
+
398
+ set optionDbName ".[lindex [_configure_option $option ""] 0]"
399
+ option add *${class}${optionDbName} $value widgetDefault
400
+ set exports($option) $optionDbName
401
+ # for any other resource type, we keep original optdesc
402
+ set classopt($option) [list $type $value $ro $arg]
403
+ }
404
+ }
405
+
406
+
407
+ proc Widget::define { class filename args } {
408
+ variable ::BWidget::use
409
+ set use($class) $args
410
+ set use($class,file) $filename
411
+ lappend use(classes) $class
412
+
413
+ if {[set x [lsearch -exact $args "-classonly"]] > -1} {
414
+ set args [lreplace $args $x $x]
415
+ } else {
416
+ interp alias {} ::${class} {} ${class}::create
417
+ proc ::${class}::use {} {}
418
+
419
+ bind $class <Destroy> [list Widget::destroy %W]
420
+ }
421
+
422
+ foreach class $args { ${class}::use }
423
+ }
424
+
425
+
426
+ proc Widget::create { class path {rename 1} } {
427
+ if {$rename} { rename $path ::$path:cmd }
428
+ proc ::$path { cmd args } \
429
+ [subst {return \[eval \[linsert \$args 0 ${class}::\$cmd [list $path]\]\]}]
430
+ return $path
431
+ }
432
+
433
+
434
+ # ----------------------------------------------------------------------------
435
+ # Command Widget::addmap
436
+ # ----------------------------------------------------------------------------
437
+ proc Widget::addmap { class subclass subpath options } {
438
+ upvar 0 ${class}::opt classopt
439
+ upvar 0 ${class}::optionExports exports
440
+ upvar 0 ${class}::optionClass optionClass
441
+ upvar 0 ${class}::map classmap
442
+ upvar 0 ${class}::map$subpath submap
443
+
444
+ foreach {option realopt} $options {
445
+ if { ![string length $realopt] } {
446
+ set realopt $option
447
+ }
448
+ set val [lindex $classopt($option) 1]
449
+ set optDb ".[lindex [_configure_option $realopt ""] 0]"
450
+ if { ![string equal $subpath ":cmd"] } {
451
+ set optDb "$subpath$optDb"
452
+ }
453
+ option add *${class}${optDb} $val widgetDefault
454
+ lappend exports($option) $optDb
455
+ # Store the forward and backward mappings for this
456
+ # option <-> realoption pair
457
+ lappend classmap($option) $subpath $subclass $realopt
458
+ set submap($realopt) $option
459
+ }
460
+ }
461
+
462
+
463
+ # ----------------------------------------------------------------------------
464
+ # Command Widget::syncoptions
465
+ # ----------------------------------------------------------------------------
466
+ proc Widget::syncoptions { class subclass subpath options } {
467
+ upvar 0 ${class}::sync classync
468
+
469
+ foreach {option realopt} $options {
470
+ if { ![string length $realopt] } {
471
+ set realopt $option
472
+ }
473
+ set classync($option) [list $subpath $subclass $realopt]
474
+ }
475
+ }
476
+
477
+
478
+ # ----------------------------------------------------------------------------
479
+ # Command Widget::init
480
+ # ----------------------------------------------------------------------------
481
+ proc Widget::init { class path options } {
482
+ variable _inuse
483
+
484
+ upvar 0 ${class}::opt classopt
485
+ upvar 0 ${class}::$path:opt pathopt
486
+ upvar 0 ${class}::$path:mod pathmod
487
+ upvar 0 ${class}::map classmap
488
+ upvar 0 ${class}::$path:init pathinit
489
+
490
+ if { [info exists pathopt] } {
491
+ unset pathopt
492
+ }
493
+ if { [info exists pathmod] } {
494
+ unset pathmod
495
+ }
496
+ # We prefer to use the actual widget for option db queries, but if it
497
+ # doesn't exist yet, do the next best thing: create a widget of the
498
+ # same class and use that.
499
+ set fpath $path
500
+ set rdbclass [string map [list :: ""] $class]
501
+ if { ![winfo exists $path] } {
502
+ set fpath ".#BWidget.#Class#$class"
503
+ # encapsulation frame to not pollute '.' childspace
504
+ if {![winfo exists ".#BWidget"]} { frame ".#BWidget" }
505
+ if { ![winfo exists $fpath] } {
506
+ frame $fpath -class $rdbclass
507
+ }
508
+ }
509
+ foreach {option optdesc} [array get classopt] {
510
+ set pathmod($option) 0
511
+ if { [info exists classmap($option)] } {
512
+ continue
513
+ }
514
+ set type [lindex $optdesc 0]
515
+ if { [string equal $type "Synonym"] } {
516
+ continue
517
+ }
518
+ if { [string equal $type "TkResource"] } {
519
+ set alt [lindex [lindex $optdesc 3] 1]
520
+ } else {
521
+ set alt ""
522
+ }
523
+ set optdb [lindex [_configure_option $option $alt] 0]
524
+ set def [option get $fpath $optdb $rdbclass]
525
+ if { [string length $def] } {
526
+ set pathopt($option) $def
527
+ } else {
528
+ set pathopt($option) [lindex $optdesc 1]
529
+ }
530
+ }
531
+
532
+ if {![info exists _inuse($class)]} { set _inuse($class) 0 }
533
+ incr _inuse($class)
534
+
535
+ set Widget::_class($path) $class
536
+ foreach {option value} $options {
537
+ if { ![info exists classopt($option)] } {
538
+ unset pathopt
539
+ unset pathmod
540
+ return -code error "unknown option \"$option\""
541
+ }
542
+ set optdesc $classopt($option)
543
+ set type [lindex $optdesc 0]
544
+ if { [string equal $type "Synonym"] } {
545
+ set option [lindex $optdesc 1]
546
+ set optdesc $classopt($option)
547
+ set type [lindex $optdesc 0]
548
+ }
549
+ set pathopt($option) [$Widget::_optiontype($type) $option $value [lindex $optdesc 3]]
550
+ set pathinit($option) $pathopt($option)
551
+ }
552
+ }
553
+
554
+ # Bastien Chevreux (bach@mwgdna.com)
555
+ #
556
+ # copyinit performs basically the same job as init, but it uses a
557
+ # existing template to initialize its values. So, first a perferct copy
558
+ # from the template is made just to be altered by any existing options
559
+ # afterwards.
560
+ # But this still saves time as the first initialization parsing block is
561
+ # skipped.
562
+ # As additional bonus, items that differ in just a few options can be
563
+ # initialized faster by leaving out the options that are equal.
564
+
565
+ # This function is currently used only by ListBox::multipleinsert, but other
566
+ # calls should follow :)
567
+
568
+ # ----------------------------------------------------------------------------
569
+ # Command Widget::copyinit
570
+ # ----------------------------------------------------------------------------
571
+ proc Widget::copyinit { class templatepath path options } {
572
+ upvar 0 ${class}::opt classopt \
573
+ ${class}::$path:opt pathopt \
574
+ ${class}::$path:mod pathmod \
575
+ ${class}::$path:init pathinit \
576
+ ${class}::$templatepath:opt templatepathopt \
577
+ ${class}::$templatepath:mod templatepathmod \
578
+ ${class}::$templatepath:init templatepathinit
579
+
580
+ if { [info exists pathopt] } {
581
+ unset pathopt
582
+ }
583
+ if { [info exists pathmod] } {
584
+ unset pathmod
585
+ }
586
+
587
+ # We use the template widget for option db copying, but it has to exist!
588
+ array set pathmod [array get templatepathmod]
589
+ array set pathopt [array get templatepathopt]
590
+ array set pathinit [array get templatepathinit]
591
+
592
+ set Widget::_class($path) $class
593
+ foreach {option value} $options {
594
+ if { ![info exists classopt($option)] } {
595
+ unset pathopt
596
+ unset pathmod
597
+ return -code error "unknown option \"$option\""
598
+ }
599
+ set optdesc $classopt($option)
600
+ set type [lindex $optdesc 0]
601
+ if { [string equal $type "Synonym"] } {
602
+ set option [lindex $optdesc 1]
603
+ set optdesc $classopt($option)
604
+ set type [lindex $optdesc 0]
605
+ }
606
+ set pathopt($option) [$Widget::_optiontype($type) $option $value [lindex $optdesc 3]]
607
+ set pathinit($option) $pathopt($option)
608
+ }
609
+ }
610
+
611
+ # Widget::parseArgs --
612
+ #
613
+ # Given a widget class and a command-line spec, cannonize and validate
614
+ # the given options, and return a keyed list consisting of the
615
+ # component widget and its masked portion of the command-line spec, and
616
+ # one extra entry consisting of the portion corresponding to the
617
+ # megawidget itself.
618
+ #
619
+ # Arguments:
620
+ # class widget class to parse for.
621
+ # options command-line spec
622
+ #
623
+ # Results:
624
+ # result keyed list of portions of the megawidget and that segment of
625
+ # the command line in which that portion is interested.
626
+
627
+ proc Widget::parseArgs {class options} {
628
+ upvar 0 ${class}::opt classopt
629
+ upvar 0 ${class}::map classmap
630
+
631
+ foreach {option val} $options {
632
+ if { ![info exists classopt($option)] } {
633
+ error "unknown option \"$option\""
634
+ }
635
+ set optdesc $classopt($option)
636
+ set type [lindex $optdesc 0]
637
+ if { [string equal $type "Synonym"] } {
638
+ set option [lindex $optdesc 1]
639
+ set optdesc $classopt($option)
640
+ set type [lindex $optdesc 0]
641
+ }
642
+ if { [string equal $type "TkResource"] } {
643
+ # Make sure that the widget used for this TkResource exists
644
+ Widget::_get_tkwidget_options [lindex [lindex $optdesc 3] 0]
645
+ }
646
+ set val [$Widget::_optiontype($type) $option $val [lindex $optdesc 3]]
647
+
648
+ if { [info exists classmap($option)] } {
649
+ foreach {subpath subclass realopt} $classmap($option) {
650
+ lappend maps($subpath) $realopt $val
651
+ }
652
+ } else {
653
+ lappend maps($class) $option $val
654
+ }
655
+ }
656
+ return [array get maps]
657
+ }
658
+
659
+ # Widget::initFromODB --
660
+ #
661
+ # Initialize a megawidgets options with information from the option
662
+ # database and from the command-line arguments given.
663
+ #
664
+ # Arguments:
665
+ # class class of the widget.
666
+ # path path of the widget -- should already exist.
667
+ # options command-line arguments.
668
+ #
669
+ # Results:
670
+ # None.
671
+
672
+ proc Widget::initFromODB {class path options} {
673
+ variable _inuse
674
+ variable _class
675
+
676
+ upvar 0 ${class}::$path:opt pathopt
677
+ upvar 0 ${class}::$path:mod pathmod
678
+ upvar 0 ${class}::map classmap
679
+
680
+ if { [info exists pathopt] } {
681
+ unset pathopt
682
+ }
683
+ if { [info exists pathmod] } {
684
+ unset pathmod
685
+ }
686
+ # We prefer to use the actual widget for option db queries, but if it
687
+ # doesn't exist yet, do the next best thing: create a widget of the
688
+ # same class and use that.
689
+ set fpath [_get_window $class $path]
690
+ set rdbclass [string map [list :: ""] $class]
691
+ if { ![winfo exists $path] } {
692
+ set fpath ".#BWidget.#Class#$class"
693
+ # encapsulation frame to not pollute '.' childspace
694
+ if {![winfo exists ".#BWidget"]} { frame ".#BWidget" }
695
+ if { ![winfo exists $fpath] } {
696
+ frame $fpath -class $rdbclass
697
+ }
698
+ }
699
+
700
+ foreach {option optdesc} [array get ${class}::opt] {
701
+ set pathmod($option) 0
702
+ if { [info exists classmap($option)] } {
703
+ continue
704
+ }
705
+ set type [lindex $optdesc 0]
706
+ if { [string equal $type "Synonym"] } {
707
+ continue
708
+ }
709
+ if { [string equal $type "TkResource"] } {
710
+ set alt [lindex [lindex $optdesc 3] 1]
711
+ } else {
712
+ set alt ""
713
+ }
714
+ set optdb [lindex [_configure_option $option $alt] 0]
715
+ set def [option get $fpath $optdb $rdbclass]
716
+ if { [string length $def] } {
717
+ set pathopt($option) $def
718
+ } else {
719
+ set pathopt($option) [lindex $optdesc 1]
720
+ }
721
+ }
722
+
723
+ if {![info exists _inuse($class)]} { set _inuse($class) 0 }
724
+ incr _inuse($class)
725
+
726
+ set _class($path) $class
727
+ array set pathopt $options
728
+ }
729
+
730
+
731
+
732
+ # ----------------------------------------------------------------------------
733
+ # Command Widget::destroy
734
+ # ----------------------------------------------------------------------------
735
+ proc Widget::destroy { path } {
736
+ variable _class
737
+ variable _inuse
738
+
739
+ if {![info exists _class($path)]} { return }
740
+
741
+ set class $_class($path)
742
+ upvar 0 ${class}::$path:opt pathopt
743
+ upvar 0 ${class}::$path:mod pathmod
744
+ upvar 0 ${class}::$path:init pathinit
745
+
746
+ if {[info exists _inuse($class)]} { incr _inuse($class) -1 }
747
+
748
+ if {[info exists pathopt]} {
749
+ unset pathopt
750
+ }
751
+ if {[info exists pathmod]} {
752
+ unset pathmod
753
+ }
754
+ if {[info exists pathinit]} {
755
+ unset pathinit
756
+ }
757
+
758
+ if {![string equal [info commands $path] ""]} { rename $path "" }
759
+
760
+ ## Unset any variables used in this widget.
761
+ foreach var [info vars ::${class}::$path:*] { unset $var }
762
+
763
+ unset _class($path)
764
+ }
765
+
766
+
767
+ # ----------------------------------------------------------------------------
768
+ # Command Widget::configure
769
+ # ----------------------------------------------------------------------------
770
+ proc Widget::configure { path options } {
771
+ set len [llength $options]
772
+ if { $len <= 1 } {
773
+ return [_get_configure $path $options]
774
+ } elseif { $len % 2 == 1 } {
775
+ return -code error "incorrect number of arguments"
776
+ }
777
+
778
+ variable _class
779
+ variable _optiontype
780
+
781
+ set class $_class($path)
782
+ upvar 0 ${class}::opt classopt
783
+ upvar 0 ${class}::map classmap
784
+ upvar 0 ${class}::$path:opt pathopt
785
+ upvar 0 ${class}::$path:mod pathmod
786
+
787
+ set window [_get_window $class $path]
788
+ foreach {option value} $options {
789
+ if { ![info exists classopt($option)] } {
790
+ return -code error "unknown option \"$option\""
791
+ }
792
+ set optdesc $classopt($option)
793
+ set type [lindex $optdesc 0]
794
+ if { [string equal $type "Synonym"] } {
795
+ set option [lindex $optdesc 1]
796
+ set optdesc $classopt($option)
797
+ set type [lindex $optdesc 0]
798
+ }
799
+ if { ![lindex $optdesc 2] } {
800
+ set newval [$_optiontype($type) $option $value [lindex $optdesc 3]]
801
+ if { [info exists classmap($option)] } {
802
+ set window [_get_window $class $window]
803
+ foreach {subpath subclass realopt} $classmap($option) {
804
+ if { [string length $subclass] } {
805
+ set curval [${subclass}::cget $window$subpath $realopt]
806
+ ${subclass}::configure $window$subpath $realopt $newval
807
+ } else {
808
+ set curval [$window$subpath cget $realopt]
809
+ $window$subpath configure $realopt $newval
810
+ }
811
+ }
812
+ } else {
813
+ set curval $pathopt($option)
814
+ set pathopt($option) $newval
815
+ }
816
+ set pathmod($option) [expr {![string equal $newval $curval]}]
817
+ }
818
+ }
819
+
820
+ return {}
821
+ }
822
+
823
+
824
+ # ----------------------------------------------------------------------------
825
+ # Command Widget::cget
826
+ # ----------------------------------------------------------------------------
827
+ proc Widget::cget { path option } {
828
+ if { ![info exists ::Widget::_class($path)] } {
829
+ return -code error "unknown widget $path"
830
+ }
831
+
832
+ set class $::Widget::_class($path)
833
+ if { ![info exists ${class}::opt($option)] } {
834
+ return -code error "unknown option \"$option\""
835
+ }
836
+
837
+ set optdesc [set ${class}::opt($option)]
838
+ set type [lindex $optdesc 0]
839
+ if {[string equal $type "Synonym"]} {
840
+ set option [lindex $optdesc 1]
841
+ }
842
+
843
+ if { [info exists ${class}::map($option)] } {
844
+ foreach {subpath subclass realopt} [set ${class}::map($option)] {break}
845
+ set path "[_get_window $class $path]$subpath"
846
+ return [$path cget $realopt]
847
+ }
848
+ upvar 0 ${class}::$path:opt pathopt
849
+ set pathopt($option)
850
+ }
851
+
852
+
853
+ # ----------------------------------------------------------------------------
854
+ # Command Widget::subcget
855
+ # ----------------------------------------------------------------------------
856
+ proc Widget::subcget { path subwidget } {
857
+ set class $::Widget::_class($path)
858
+ upvar 0 ${class}::$path:opt pathopt
859
+ upvar 0 ${class}::map$subwidget submap
860
+ upvar 0 ${class}::$path:init pathinit
861
+
862
+ set result {}
863
+ foreach realopt [array names submap] {
864
+ if { [info exists pathinit($submap($realopt))] } {
865
+ lappend result $realopt $pathopt($submap($realopt))
866
+ }
867
+ }
868
+ return $result
869
+ }
870
+
871
+
872
+ # ----------------------------------------------------------------------------
873
+ # Command Widget::hasChanged
874
+ # ----------------------------------------------------------------------------
875
+ proc Widget::hasChanged { path option pvalue } {
876
+ upvar $pvalue value
877
+ set class $::Widget::_class($path)
878
+ upvar 0 ${class}::$path:mod pathmod
879
+
880
+ set value [Widget::cget $path $option]
881
+ set result $pathmod($option)
882
+ set pathmod($option) 0
883
+
884
+ return $result
885
+ }
886
+
887
+ proc Widget::hasChangedX { path option args } {
888
+ set class $::Widget::_class($path)
889
+ upvar 0 ${class}::$path:mod pathmod
890
+
891
+ set result $pathmod($option)
892
+ set pathmod($option) 0
893
+ foreach option $args {
894
+ lappend result $pathmod($option)
895
+ set pathmod($option) 0
896
+ }
897
+
898
+ set result
899
+ }
900
+
901
+
902
+ # ----------------------------------------------------------------------------
903
+ # Command Widget::setoption
904
+ # ----------------------------------------------------------------------------
905
+ proc Widget::setoption { path option value } {
906
+ # variable _class
907
+
908
+ # set class $_class($path)
909
+ # upvar 0 ${class}::$path:opt pathopt
910
+
911
+ # set pathopt($option) $value
912
+ Widget::configure $path [list $option $value]
913
+ }
914
+
915
+
916
+ # ----------------------------------------------------------------------------
917
+ # Command Widget::getoption
918
+ # ----------------------------------------------------------------------------
919
+ proc Widget::getoption { path option } {
920
+ # set class $::Widget::_class($path)
921
+ # upvar 0 ${class}::$path:opt pathopt
922
+
923
+ # return $pathopt($option)
924
+ return [Widget::cget $path $option]
925
+ }
926
+
927
+ # Widget::getMegawidgetOption --
928
+ #
929
+ # Bypass the superfluous checks in cget and just directly peer at the
930
+ # widget's data space. This is much more fragile than cget, so it
931
+ # should only be used with great care, in places where speed is critical.
932
+ #
933
+ # Arguments:
934
+ # path widget to lookup options for.
935
+ # option option to retrieve.
936
+ #
937
+ # Results:
938
+ # value option value.
939
+
940
+ proc Widget::getMegawidgetOption {path option} {
941
+ set class $::Widget::_class($path)
942
+ upvar 0 ${class}::${path}:opt pathopt
943
+ set pathopt($option)
944
+ }
945
+
946
+ # Widget::setMegawidgetOption --
947
+ #
948
+ # Bypass the superfluous checks in cget and just directly poke at the
949
+ # widget's data space. This is much more fragile than configure, so it
950
+ # should only be used with great care, in places where speed is critical.
951
+ #
952
+ # Arguments:
953
+ # path widget to lookup options for.
954
+ # option option to retrieve.
955
+ # value option value.
956
+ #
957
+ # Results:
958
+ # value option value.
959
+
960
+ proc Widget::setMegawidgetOption {path option value} {
961
+ set class $::Widget::_class($path)
962
+ upvar 0 ${class}::${path}:opt pathopt
963
+ set pathopt($option) $value
964
+ }
965
+
966
+ # ----------------------------------------------------------------------------
967
+ # Command Widget::_get_window
968
+ # returns the window corresponding to widget path
969
+ # ----------------------------------------------------------------------------
970
+ proc Widget::_get_window { class path } {
971
+ set idx [string last "#" $path]
972
+ if { $idx != -1 && [string equal [string range $path [expr {$idx+1}] end] $class] } {
973
+ return [string range $path 0 [expr {$idx-1}]]
974
+ } else {
975
+ return $path
976
+ }
977
+ }
978
+
979
+
980
+ # ----------------------------------------------------------------------------
981
+ # Command Widget::_get_configure
982
+ # returns the configuration list of options
983
+ # (as tk widget do - [$w configure ?option?])
984
+ # ----------------------------------------------------------------------------
985
+ proc Widget::_get_configure { path options } {
986
+ variable _class
987
+
988
+ set class $_class($path)
989
+ upvar 0 ${class}::opt classopt
990
+ upvar 0 ${class}::map classmap
991
+ upvar 0 ${class}::$path:opt pathopt
992
+ upvar 0 ${class}::$path:mod pathmod
993
+
994
+ set len [llength $options]
995
+ if { !$len } {
996
+ set result {}
997
+ foreach option [lsort [array names classopt]] {
998
+ set optdesc $classopt($option)
999
+ set type [lindex $optdesc 0]
1000
+ if { [string equal $type "Synonym"] } {
1001
+ set syn $option
1002
+ set option [lindex $optdesc 1]
1003
+ set optdesc $classopt($option)
1004
+ set type [lindex $optdesc 0]
1005
+ } else {
1006
+ set syn ""
1007
+ }
1008
+ if { [string equal $type "TkResource"] } {
1009
+ set alt [lindex [lindex $optdesc 3] 1]
1010
+ } else {
1011
+ set alt ""
1012
+ }
1013
+ set res [_configure_option $option $alt]
1014
+ if { $syn == "" } {
1015
+ lappend result [concat $option $res [list [lindex $optdesc 1]] [list [cget $path $option]]]
1016
+ } else {
1017
+ lappend result [list $syn [lindex $res 0]]
1018
+ }
1019
+ }
1020
+ return $result
1021
+ } elseif { $len == 1 } {
1022
+ set option [lindex $options 0]
1023
+ if { ![info exists classopt($option)] } {
1024
+ return -code error "unknown option \"$option\""
1025
+ }
1026
+ set optdesc $classopt($option)
1027
+ set type [lindex $optdesc 0]
1028
+ if { [string equal $type "Synonym"] } {
1029
+ set option [lindex $optdesc 1]
1030
+ set optdesc $classopt($option)
1031
+ set type [lindex $optdesc 0]
1032
+ }
1033
+ if { [string equal $type "TkResource"] } {
1034
+ set alt [lindex [lindex $optdesc 3] 1]
1035
+ } else {
1036
+ set alt ""
1037
+ }
1038
+ set res [_configure_option $option $alt]
1039
+ return [concat $option $res [list [lindex $optdesc 1]] [list [cget $path $option]]]
1040
+ }
1041
+ }
1042
+
1043
+
1044
+ # ----------------------------------------------------------------------------
1045
+ # Command Widget::_configure_option
1046
+ # ----------------------------------------------------------------------------
1047
+ proc Widget::_configure_option { option altopt } {
1048
+ variable _optiondb
1049
+ variable _optionclass
1050
+
1051
+ if { [info exists _optiondb($option)] } {
1052
+ set optdb $_optiondb($option)
1053
+ } else {
1054
+ set optdb [string range $option 1 end]
1055
+ }
1056
+ if { [info exists _optionclass($option)] } {
1057
+ set optclass $_optionclass($option)
1058
+ } elseif { [string length $altopt] } {
1059
+ if { [info exists _optionclass($altopt)] } {
1060
+ set optclass $_optionclass($altopt)
1061
+ } else {
1062
+ set optclass [string range $altopt 1 end]
1063
+ }
1064
+ } else {
1065
+ set optclass [string range $option 1 end]
1066
+ }
1067
+ return [list $optdb $optclass]
1068
+ }
1069
+
1070
+
1071
+ # ----------------------------------------------------------------------------
1072
+ # Command Widget::_get_tkwidget_options
1073
+ # ----------------------------------------------------------------------------
1074
+ proc Widget::_get_tkwidget_options { tkwidget } {
1075
+ variable _tk_widget
1076
+ variable _optiondb
1077
+ variable _optionclass
1078
+
1079
+ set widget ".#BWidget.#$tkwidget"
1080
+ # encapsulation frame to not pollute '.' childspace
1081
+ if {![winfo exists ".#BWidget"]} { frame ".#BWidget" }
1082
+ if { ![winfo exists $widget] || ![info exists _tk_widget($tkwidget)] } {
1083
+ set widget [$tkwidget $widget]
1084
+ # JDC: Withdraw toplevels, otherwise visible
1085
+ if {[string equal $tkwidget "toplevel"]} {
1086
+ wm withdraw $widget
1087
+ }
1088
+ set config [$widget configure]
1089
+ foreach optlist $config {
1090
+ set opt [lindex $optlist 0]
1091
+ if { [llength $optlist] == 2 } {
1092
+ set refsyn [lindex $optlist 1]
1093
+ # search for class
1094
+ set idx [lsearch $config [list * $refsyn *]]
1095
+ if { $idx == -1 } {
1096
+ if { [string index $refsyn 0] == "-" } {
1097
+ # search for option (tk8.1b1 bug)
1098
+ set idx [lsearch $config [list $refsyn * *]]
1099
+ } else {
1100
+ # last resort
1101
+ set idx [lsearch $config [list -[string tolower $refsyn] * *]]
1102
+ }
1103
+ if { $idx == -1 } {
1104
+ # fed up with "can't read classopt()"
1105
+ return -code error "can't find option of synonym $opt"
1106
+ }
1107
+ }
1108
+ set syn [lindex [lindex $config $idx] 0]
1109
+ # JDC: used 4 (was 3) to get def from optiondb
1110
+ set def [lindex [lindex $config $idx] 4]
1111
+ lappend _tk_widget($tkwidget) [list $opt $syn $def]
1112
+ } else {
1113
+ # JDC: used 4 (was 3) to get def from optiondb
1114
+ set def [lindex $optlist 4]
1115
+ lappend _tk_widget($tkwidget) [list $opt $def]
1116
+ set _optiondb($opt) [lindex $optlist 1]
1117
+ set _optionclass($opt) [lindex $optlist 2]
1118
+ }
1119
+ }
1120
+ }
1121
+ return $_tk_widget($tkwidget)
1122
+ }
1123
+
1124
+
1125
+ # ----------------------------------------------------------------------------
1126
+ # Command Widget::_test_tkresource
1127
+ # ----------------------------------------------------------------------------
1128
+ proc Widget::_test_tkresource { option value arg } {
1129
+ # set tkwidget [lindex $arg 0]
1130
+ # set realopt [lindex $arg 1]
1131
+ foreach {tkwidget realopt} $arg break
1132
+ set path ".#BWidget.#$tkwidget"
1133
+ set old [$path cget $realopt]
1134
+ $path configure $realopt $value
1135
+ set res [$path cget $realopt]
1136
+ $path configure $realopt $old
1137
+
1138
+ return $res
1139
+ }
1140
+
1141
+
1142
+ # ----------------------------------------------------------------------------
1143
+ # Command Widget::_test_bwresource
1144
+ # ----------------------------------------------------------------------------
1145
+ proc Widget::_test_bwresource { option value arg } {
1146
+ return -code error "bad option type BwResource in widget"
1147
+ }
1148
+
1149
+
1150
+ # ----------------------------------------------------------------------------
1151
+ # Command Widget::_test_synonym
1152
+ # ----------------------------------------------------------------------------
1153
+ proc Widget::_test_synonym { option value arg } {
1154
+ return -code error "bad option type Synonym in widget"
1155
+ }
1156
+
1157
+ # ----------------------------------------------------------------------------
1158
+ # Command Widget::_test_color
1159
+ # ----------------------------------------------------------------------------
1160
+ proc Widget::_test_color { option value arg } {
1161
+ if {[catch {winfo rgb . $value} color]} {
1162
+ return -code error "bad $option value \"$value\": must be a colorname \
1163
+ or #RRGGBB triplet"
1164
+ }
1165
+
1166
+ return $value
1167
+ }
1168
+
1169
+
1170
+ # ----------------------------------------------------------------------------
1171
+ # Command Widget::_test_string
1172
+ # ----------------------------------------------------------------------------
1173
+ proc Widget::_test_string { option value arg } {
1174
+ set value
1175
+ }
1176
+
1177
+
1178
+ # ----------------------------------------------------------------------------
1179
+ # Command Widget::_test_flag
1180
+ # ----------------------------------------------------------------------------
1181
+ proc Widget::_test_flag { option value arg } {
1182
+ set len [string length $value]
1183
+ set res ""
1184
+ for {set i 0} {$i < $len} {incr i} {
1185
+ set c [string index $value $i]
1186
+ if { [string first $c $arg] == -1 } {
1187
+ return -code error "bad [string range $option 1 end] value \"$value\": characters must be in \"$arg\""
1188
+ }
1189
+ if { [string first $c $res] == -1 } {
1190
+ append res $c
1191
+ }
1192
+ }
1193
+ return $res
1194
+ }
1195
+
1196
+
1197
+ # -----------------------------------------------------------------------------
1198
+ # Command Widget::_test_enum
1199
+ # -----------------------------------------------------------------------------
1200
+ proc Widget::_test_enum { option value arg } {
1201
+ if { [lsearch $arg $value] == -1 } {
1202
+ set last [lindex $arg end]
1203
+ set sub [lreplace $arg end end]
1204
+ if { [llength $sub] } {
1205
+ set str "[join $sub ", "] or $last"
1206
+ } else {
1207
+ set str $last
1208
+ }
1209
+ return -code error "bad [string range $option 1 end] value \"$value\": must be $str"
1210
+ }
1211
+ return $value
1212
+ }
1213
+
1214
+
1215
+ # -----------------------------------------------------------------------------
1216
+ # Command Widget::_test_int
1217
+ # -----------------------------------------------------------------------------
1218
+ proc Widget::_test_int { option value arg } {
1219
+ if { ![string is int -strict $value] || \
1220
+ ([string length $arg] && \
1221
+ ![expr [string map [list %d $value] $arg]]) } {
1222
+ return -code error "bad $option value\
1223
+ \"$value\": must be integer ($arg)"
1224
+ }
1225
+ return $value
1226
+ }
1227
+
1228
+
1229
+ # -----------------------------------------------------------------------------
1230
+ # Command Widget::_test_boolean
1231
+ # -----------------------------------------------------------------------------
1232
+ proc Widget::_test_boolean { option value arg } {
1233
+ if { ![string is boolean -strict $value] } {
1234
+ return -code error "bad $option value \"$value\": must be boolean"
1235
+ }
1236
+
1237
+ # Get the canonical form of the boolean value (1 for true, 0 for false)
1238
+ return [string is true $value]
1239
+ }
1240
+
1241
+
1242
+ # -----------------------------------------------------------------------------
1243
+ # Command Widget::_test_padding
1244
+ # -----------------------------------------------------------------------------
1245
+ proc Widget::_test_padding { option values arg } {
1246
+ set len [llength $values]
1247
+ if {$len < 1 || $len > 2} {
1248
+ return -code error "bad pad value \"$values\":\
1249
+ must be positive screen distance"
1250
+ }
1251
+
1252
+ foreach value $values {
1253
+ if { ![string is int -strict $value] || \
1254
+ ([string length $arg] && \
1255
+ ![expr [string map [list %d $value] $arg]]) } {
1256
+ return -code error "bad pad value \"$value\":\
1257
+ must be positive screen distance ($arg)"
1258
+ }
1259
+ }
1260
+ return $values
1261
+ }
1262
+
1263
+
1264
+ # Widget::_get_padding --
1265
+ #
1266
+ # Return the requesting padding value for a padding option.
1267
+ #
1268
+ # Arguments:
1269
+ # path Widget to get the options for.
1270
+ # option The name of the padding option.
1271
+ # index The index of the padding. If the index is empty,
1272
+ # the first padding value is returned.
1273
+ #
1274
+ # Results:
1275
+ # Return a numeric value that can be used for padding.
1276
+ proc Widget::_get_padding { path option {index 0} } {
1277
+ set pad [Widget::cget $path $option]
1278
+ set val [lindex $pad $index]
1279
+ if {$val == ""} { set val [lindex $pad 0] }
1280
+ return $val
1281
+ }
1282
+
1283
+
1284
+ # -----------------------------------------------------------------------------
1285
+ # Command Widget::focusNext
1286
+ # Same as tk_focusNext, but call Widget::focusOK
1287
+ # -----------------------------------------------------------------------------
1288
+ proc Widget::focusNext { w } {
1289
+ set cur $w
1290
+ while 1 {
1291
+
1292
+ # Descend to just before the first child of the current widget.
1293
+
1294
+ set parent $cur
1295
+ set children [winfo children $cur]
1296
+ set i -1
1297
+
1298
+ # Look for the next sibling that isn't a top-level.
1299
+
1300
+ while 1 {
1301
+ incr i
1302
+ if {$i < [llength $children]} {
1303
+ set cur [lindex $children $i]
1304
+ if {[string equal [winfo toplevel $cur] $cur]} {
1305
+ continue
1306
+ } else {
1307
+ break
1308
+ }
1309
+ }
1310
+
1311
+ # No more siblings, so go to the current widget's parent.
1312
+ # If it's a top-level, break out of the loop, otherwise
1313
+ # look for its next sibling.
1314
+
1315
+ set cur $parent
1316
+ if {[string equal [winfo toplevel $cur] $cur]} {
1317
+ break
1318
+ }
1319
+ set parent [winfo parent $parent]
1320
+ set children [winfo children $parent]
1321
+ set i [lsearch -exact $children $cur]
1322
+ }
1323
+ if {[string equal $cur $w] || [focusOK $cur]} {
1324
+ return $cur
1325
+ }
1326
+ }
1327
+ }
1328
+
1329
+
1330
+ # -----------------------------------------------------------------------------
1331
+ # Command Widget::focusPrev
1332
+ # Same as tk_focusPrev, except:
1333
+ # + Don't traverse from a child to a direct ancestor
1334
+ # + Call Widget::focusOK instead of tk::focusOK
1335
+ # -----------------------------------------------------------------------------
1336
+ proc Widget::focusPrev { w } {
1337
+ set cur $w
1338
+ set origParent [winfo parent $w]
1339
+ while 1 {
1340
+
1341
+ # Collect information about the current window's position
1342
+ # among its siblings. Also, if the window is a top-level,
1343
+ # then reposition to just after the last child of the window.
1344
+
1345
+ if {[string equal [winfo toplevel $cur] $cur]} {
1346
+ set parent $cur
1347
+ set children [winfo children $cur]
1348
+ set i [llength $children]
1349
+ } else {
1350
+ set parent [winfo parent $cur]
1351
+ set children [winfo children $parent]
1352
+ set i [lsearch -exact $children $cur]
1353
+ }
1354
+
1355
+ # Go to the previous sibling, then descend to its last descendant
1356
+ # (highest in stacking order. While doing this, ignore top-levels
1357
+ # and their descendants. When we run out of descendants, go up
1358
+ # one level to the parent.
1359
+
1360
+ while {$i > 0} {
1361
+ incr i -1
1362
+ set cur [lindex $children $i]
1363
+ if {[string equal [winfo toplevel $cur] $cur]} {
1364
+ continue
1365
+ }
1366
+ set parent $cur
1367
+ set children [winfo children $parent]
1368
+ set i [llength $children]
1369
+ }
1370
+ set cur $parent
1371
+ if {[string equal $cur $w]} {
1372
+ return $cur
1373
+ }
1374
+ # If we are just at the original parent of $w, skip it as a
1375
+ # potential focus accepter. Extra safety in this is to see if
1376
+ # that parent is also a proc (not a C command), which is what
1377
+ # BWidgets makes for any megawidget. Could possibly also check
1378
+ # for '[info commands ::${origParent}:cmd] != ""'. [Bug 765667]
1379
+ if {[string equal $cur $origParent]
1380
+ && [info procs ::$origParent] != ""} {
1381
+ continue
1382
+ }
1383
+ if {[focusOK $cur]} {
1384
+ return $cur
1385
+ }
1386
+ }
1387
+ }
1388
+
1389
+
1390
+ # ----------------------------------------------------------------------------
1391
+ # Command Widget::focusOK
1392
+ # Same as tk_focusOK, but handles -editable option and whole tags list.
1393
+ # ----------------------------------------------------------------------------
1394
+ proc Widget::focusOK { w } {
1395
+ set code [catch {$w cget -takefocus} value]
1396
+ if { $code == 1 } {
1397
+ return 0
1398
+ }
1399
+ if {($code == 0) && ($value != "")} {
1400
+ if {$value == 0} {
1401
+ return 0
1402
+ } elseif {$value == 1} {
1403
+ return [winfo viewable $w]
1404
+ } else {
1405
+ set value [uplevel \#0 $value $w]
1406
+ if {$value != ""} {
1407
+ return $value
1408
+ }
1409
+ }
1410
+ }
1411
+ if {![winfo viewable $w]} {
1412
+ return 0
1413
+ }
1414
+ set code [catch {$w cget -state} value]
1415
+ if {($code == 0) && ($value == "disabled")} {
1416
+ return 0
1417
+ }
1418
+ set code [catch {$w cget -editable} value]
1419
+ if {($code == 0) && ($value == 0)} {
1420
+ return 0
1421
+ }
1422
+
1423
+ set top [winfo toplevel $w]
1424
+ foreach tags [bindtags $w] {
1425
+ if { ![string equal $tags $top] &&
1426
+ ![string equal $tags "all"] &&
1427
+ [regexp Key [bind $tags]] } {
1428
+ return 1
1429
+ }
1430
+ }
1431
+ return 0
1432
+ }
1433
+
1434
+
1435
+ proc Widget::traverseTo { w } {
1436
+ set focus [focus]
1437
+ if {![string equal $focus ""]} {
1438
+ event generate $focus <<TraverseOut>>
1439
+ }
1440
+ focus $w
1441
+
1442
+ event generate $w <<TraverseIn>>
1443
+ }
1444
+
1445
+
1446
+ # Widget::varForOption --
1447
+ #
1448
+ # Retrieve a fully qualified variable name for the option specified.
1449
+ # If the option is not one for which a variable exists, throw an error
1450
+ # (ie, those options that map directly to widget options).
1451
+ #
1452
+ # Arguments:
1453
+ # path megawidget to get an option var for.
1454
+ # option option to get a var for.
1455
+ #
1456
+ # Results:
1457
+ # varname name of the variable, fully qualified, suitable for tracing.
1458
+
1459
+ proc Widget::varForOption {path option} {
1460
+ variable _class
1461
+ variable _optiontype
1462
+
1463
+ set class $_class($path)
1464
+ upvar 0 ${class}::$path:opt pathopt
1465
+
1466
+ if { ![info exists pathopt($option)] } {
1467
+ error "unable to find variable for option \"$option\""
1468
+ }
1469
+ set varname "::Widget::${class}::$path:opt($option)"
1470
+ return $varname
1471
+ }
1472
+
1473
+ # Widget::getVariable --
1474
+ #
1475
+ # Get a variable from within the namespace of the widget.
1476
+ #
1477
+ # Arguments:
1478
+ # path Megawidget to get the variable for.
1479
+ # varName The variable name to retrieve.
1480
+ # newVarName The variable name to refer to in the calling proc.
1481
+ #
1482
+ # Results:
1483
+ # Creates a reference to newVarName in the calling proc.
1484
+ proc Widget::getVariable { path varName {newVarName ""} } {
1485
+ variable _class
1486
+ set class $_class($path)
1487
+ if {![string length $newVarName]} { set newVarName $varName }
1488
+ uplevel 1 [list upvar \#0 ${class}::$path:$varName $newVarName]
1489
+ }
1490
+
1491
+ # Widget::options --
1492
+ #
1493
+ # Return a key-value list of options for a widget. This can
1494
+ # be used to serialize the options of a widget and pass them
1495
+ # on to a new widget with the same options.
1496
+ #
1497
+ # Arguments:
1498
+ # path Widget to get the options for.
1499
+ # args A list of options. If empty, all options are returned.
1500
+ #
1501
+ # Results:
1502
+ # Returns list of options as: -option value -option value ...
1503
+ proc Widget::options { path args } {
1504
+ if {[llength $args]} {
1505
+ foreach option $args {
1506
+ lappend options [_get_configure $path $option]
1507
+ }
1508
+ } else {
1509
+ set options [_get_configure $path {}]
1510
+ }
1511
+
1512
+ set result [list]
1513
+ foreach list $options {
1514
+ if {[llength $list] < 5} { continue }
1515
+ lappend result [lindex $list 0] [lindex $list end]
1516
+ }
1517
+ return $result
1518
+ }
1519
+
1520
+
1521
+ # Widget::getOption --
1522
+ #
1523
+ # Given a list of widgets, determine which option value to use.
1524
+ # The widgets are given to the command in order of highest to
1525
+ # lowest. Starting with the lowest widget, whichever one does
1526
+ # not match the default option value is returned as the value.
1527
+ # If all the widgets are default, we return the highest widget's
1528
+ # value.
1529
+ #
1530
+ # Arguments:
1531
+ # option The option to check.
1532
+ # default The default value. If any widget in the list
1533
+ # does not match this default, its value is used.
1534
+ # args A list of widgets.
1535
+ #
1536
+ # Results:
1537
+ # Returns the value of the given option to use.
1538
+ #
1539
+ proc Widget::getOption { option default args } {
1540
+ for {set i [expr [llength $args] -1]} {$i >= 0} {incr i -1} {
1541
+ set widget [lindex $args $i]
1542
+ set value [Widget::cget $widget $option]
1543
+ if {[string equal $value $default]} { continue }
1544
+ return $value
1545
+ }
1546
+ return $value
1547
+ }
1548
+
1549
+
1550
+ proc Widget::nextIndex { path node } {
1551
+ Widget::getVariable $path autoIndex
1552
+ if {![info exists autoIndex]} { set autoIndex -1 }
1553
+ return [string map [list #auto [incr autoIndex]] $node]
1554
+ }
1555
+
1556
+
1557
+ proc Widget::exists { path } {
1558
+ variable _class
1559
+ return [info exists _class($path)]
1560
+ }
1561
+
1562
+ proc Widget::theme {{bool {}}} {
1563
+ # Private, *experimental* API that may change at any time - JH
1564
+ variable _theme
1565
+ if {[llength [info level 0]] == 2} {
1566
+ # set theme-ability
1567
+ if {[catch {package require tile 0.6}]
1568
+ && [catch {package require tile 1}]} {
1569
+ return -code error "BWidget's theming requires tile 0.6+"
1570
+ } else {
1571
+ catch {style default BWSlim.Toolbutton -padding 0}
1572
+ }
1573
+ set _theme [string is true -strict $bool]
1574
+ }
1575
+ return $_theme
1576
+ }