3 # Some functions needed for the common dialog boxes. Probably need to go
6 # RCS: @(#) $Id: comdlg.tcl,v 1.9.2.1 2006/01/25 18:21:41 dgp Exp $
8 # Copyright (c) 1996 Sun Microsystems, Inc.
10 # See the file "license.terms" for information on usage and redistribution
11 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 # tclParseConfigSpec --
16 # Parses a list of "-option value" pairs. If all options and
17 # values are legal, the values are stored in
18 # $data($option). Otherwise an error message is returned. When
19 # an error happens, the data() array may have been partially
20 # modified, but all the modified members of the data(0 array are
21 # guaranteed to have valid values. This is different than
22 # Tk_ConfigureWidget() which does not modify the value of a
23 # widget record if any error occurs.
27 # w = widget record to modify. Must be the pathname of a widget.
30 # {-commandlineswitch resourceName ResourceClass defaultValue verifier}
34 # flags = currently unused.
36 # argList = The list of "-option value" pairs.
38 proc tclParseConfigSpec
{w specs flags argList
} {
41 # 1: Put the specs in associative arrays for faster access
44 if {[llength $spec] < 4} {
45 error "\"spec\" should contain 5 or 4 elements"
47 set cmdsw
[lindex $spec 0]
49 set rname
($cmdsw) [lindex $spec 1]
50 set rclass
($cmdsw) [lindex $spec 2]
51 set def
($cmdsw) [lindex $spec 3]
52 set verproc
($cmdsw) [lindex $spec 4]
55 if {[llength $argList] & 1} {
56 set cmdsw
[lindex $argList end
]
57 if {![info exists cmd
($cmdsw)]} {
58 error "bad option \"$cmdsw\": must be [tclListValidFlags cmd]"
60 error "value for \"$cmdsw\" missing"
63 # 2: set the default values
65 foreach cmdsw
[array names cmd
] {
66 set data
($cmdsw) $def($cmdsw)
69 # 3: parse the argument list
71 foreach {cmdsw value
} $argList {
72 if {![info exists cmd
($cmdsw)]} {
73 error "bad option \"$cmdsw\": must be [tclListValidFlags cmd]"
75 set data
($cmdsw) $value
81 proc tclListValidFlags
{v
} {
84 set len
[llength [array names cmd
]]
88 foreach cmdsw
[lsort [array names cmd
]] {
89 append errormsg
"$separator$cmdsw"
100 #----------------------------------------------------------------------
104 # Focus groups are used to handle the user's focusing actions inside a
107 # One example of using focus groups is: when the user focuses on an
108 # entry, the text in the entry is highlighted and the cursor is put to
109 # the end of the text. When the user changes focus to another widget,
110 # the text in the previously focused entry is validated.
112 #----------------------------------------------------------------------
115 # ::tk::FocusGroup_Create --
117 # Create a focus group. All the widgets in a focus group must be
118 # within the same focus toplevel. Each toplevel can have only
119 # one focus group, which is identified by the name of the
122 proc ::tk::FocusGroup_Create {t
} {
124 if {[winfo toplevel $t] ne
$t} {
125 error "$t is not a toplevel window"
127 if {![info exists Priv
(fg
,$t)]} {
129 set Priv
(focus,$t) ""
130 bind $t <FocusIn
> [list tk::FocusGroup_In $t %W
%d
]
131 bind $t <FocusOut
> [list tk::FocusGroup_Out $t %W
%d
]
132 bind $t <Destroy
> [list tk::FocusGroup_Destroy $t %W
]
136 # ::tk::FocusGroup_BindIn --
138 # Add a widget into the "FocusIn" list of the focus group. The $cmd will be
139 # called when the widget is focused on by the user.
141 proc ::tk::FocusGroup_BindIn {t w cmd
} {
144 if {![info exists Priv
(fg
,$t)]} {
145 error "focus group \"$t\" doesn't exist"
147 set FocusIn
($t,$w) $cmd
151 # ::tk::FocusGroup_BindOut --
153 # Add a widget into the "FocusOut" list of the focus group. The
154 # $cmd will be called when the widget loses the focus (User
155 # types Tab or click on another widget).
157 proc ::tk::FocusGroup_BindOut {t w cmd
} {
160 if {![info exists Priv
(fg
,$t)]} {
161 error "focus group \"$t\" doesn't exist"
163 set FocusOut
($t,$w) $cmd
166 # ::tk::FocusGroup_Destroy --
168 # Cleans up when members of the focus group is deleted, or when the
169 # toplevel itself gets deleted.
171 proc ::tk::FocusGroup_Destroy {t w
} {
180 foreach name
[array names FocusIn
$t,*] {
183 foreach name
[array names FocusOut
$t,*] {
184 unset FocusOut
($name)
187 if {[info exists Priv
(focus,$t)] && $Priv(focus,$t) eq
$w} {
188 set Priv
(focus,$t) ""
190 unset -nocomplain FocusIn
($t,$w) FocusOut
($t,$w)
194 # ::tk::FocusGroup_In --
196 # Handles the <FocusIn> event. Calls the FocusIn command for the newly
197 # focused widget in the focus group.
199 proc ::tk::FocusGroup_In {t w detail
} {
203 if {$detail ne
"NotifyNonlinear" && $detail ne
"NotifyNonlinearVirtual"} {
204 # This is caused by mouse moving out&in of the window *or*
205 # ordinary keypresses some window managers (ie: CDE [Bug: 2960]).
208 if {![info exists FocusIn
($t,$w)]} {
209 set FocusIn
($t,$w) ""
212 if {![info exists Priv
(focus,$t)]} {
215 if {$Priv(focus,$t) eq
$w} {
216 # This is already in focus
220 set Priv
(focus,$t) $w
225 # ::tk::FocusGroup_Out --
227 # Handles the <FocusOut> event. Checks if this is really a lose
228 # focus event, not one generated by the mouse moving out of the
229 # toplevel window. Calls the FocusOut command for the widget
230 # who loses its focus.
232 proc ::tk::FocusGroup_Out {t w detail
} {
236 if {$detail ne
"NotifyNonlinear" && $detail ne
"NotifyNonlinearVirtual"} {
237 # This is caused by mouse moving out of the window
240 if {![info exists Priv
(focus,$t)]} {
243 if {![info exists FocusOut
($t,$w)]} {
246 eval $FocusOut($t,$w)
247 set Priv
(focus,$t) ""
251 # ::tk::FDGetFileTypes --
253 # Process the string given by the -filetypes option of the file
254 # dialogs. Similar to the C function TkGetFileFilters() on the Mac
255 # and Windows platform.
257 proc ::tk::FDGetFileTypes {string} {
259 if {[llength $t] < 2 ||
[llength $t] > 3} {
260 error "bad file type \"$t\", should be \"typeName {extension ?extensions ...?} ?{macType ?macTypes ...?}?\""
262 eval lappend [list fileTypes
([lindex $t 0])] [lindex $t 1]
267 set label [lindex $t 0]
270 if {[info exists hasDoneType
($label)]} {
277 foreach ext
$fileTypes($label) {
281 regsub {^
[.
]} $ext "*." ext
282 if {![info exists hasGotExt
($label,$ext)]} {
284 if {[string length
$sep] && [string length
$name]>40} {
292 set hasGotExt
($label,$ext) 1
297 lappend types
[list $name $exts]
299 set hasDoneType
($label) 1