3 # Implements the "TK" standard file selection dialog box. This
4 # dialog box is used on the Unix platforms whenever the tk_strictMotif
7 # The "TK" standard file selection dialog box is similar to the
8 # file selection dialog box on Win95(TM). The user can navigate
9 # the directories by clicking on the folder icons or by
10 # selecting the "Directory" option menu. The user can select
11 # files by clicking on the file icons or by entering a filename
12 # in the "Filename:" entry.
14 # RCS: @(#) $Id: tkfbox.tcl,v 1.38.2.3 2003/11/12 00:04:32 hobbs Exp $
16 # Copyright (c) 1994-1998 Sun Microsystems, Inc.
18 # See the file "license.terms" for information on usage and redistribution
19 # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
22 #----------------------------------------------------------------------
26 # This is a pseudo-widget that implements the icon list inside the
27 # ::tk::dialog::file:: dialog box.
29 #----------------------------------------------------------------------
33 # Creates an IconList widget.
35 proc ::tk::IconList {w args} {
36 IconList_Config $w $args
40 proc ::tk::IconList_Index {w i} {
41 upvar #0 ::tk::$w data
42 upvar #0 ::tk::$w:itemList itemList
43 if {![info exists data(list)]} {set data(list) {}}
44 switch -regexp -- $i {
49 if { $i >= [llength $data(list)] } {
50 set i [expr {[llength $data(list)] - 1}]
55 return $data(index,active)
58 return $data(index,anchor)
61 return [llength $data(list)]
63 "@-?[0-9]+,-?[0-9]+" {
64 foreach {x y} [scan $i "@%d,%d"] {
67 set item [$data(canvas) find closest $x $y]
68 return [lindex [$data(canvas) itemcget $item -tags] 1]
73 proc ::tk::IconList_Selection {w op args} {
75 switch -exact -- $op {
77 if { [llength $args] == 1 } {
78 set data(index,anchor) [tk::IconList_Index $w [lindex $args 0]]
80 return $data(index,anchor)
84 if { [llength $args] == 2 } {
85 foreach {first last} $args {
88 } elseif { [llength $args] == 1 } {
89 set first [set last [lindex $args 0]]
91 error "wrong # args: should be [lindex [info level 0] 0] path\
94 set first [IconList_Index $w $first]
95 set last [IconList_Index $w $last]
96 if { $first > $last } {
102 foreach item $data(selection) {
103 if { $item >= $first } {
108 set ind [expr {[llength $data(selection)] - 1}]
109 for {} {$ind >= 0} {incr ind -1} {
110 set item [lindex $data(selection) $ind]
111 if { $item <= $last } {
117 if { $first > $last } {
120 set data(selection) [lreplace $data(selection) $first $last]
121 event generate $w <<ListboxSelect>>
122 IconList_DrawSelection $w
125 set index [lsearch -exact $data(selection) [lindex $args 0]]
126 return [expr {$index != -1}]
129 if { [llength $args] == 2 } {
130 foreach {first last} $args {
133 } elseif { [llength $args] == 1 } {
134 set last [set first [lindex $args 0]]
136 error "wrong # args: should be [lindex [info level 0] 0] path\
140 set first [IconList_Index $w $first]
141 set last [IconList_Index $w $last]
142 if { $first > $last } {
147 for {set i $first} {$i <= $last} {incr i} {
148 lappend data(selection) $i
150 set data(selection) [lsort -integer -unique $data(selection)]
151 event generate $w <<ListboxSelect>>
152 IconList_DrawSelection $w
157 proc ::tk::IconList_Curselection {w} {
159 return $data(selection)
162 proc ::tk::IconList_DrawSelection {w} {
164 upvar ::tk::$w:itemList itemList
166 $data(canvas) delete selection
167 foreach item $data(selection) {
168 set rTag [lindex [lindex $data(list) $item] 2]
169 foreach {iTag tTag text serial} $itemList($rTag) {
173 set bbox [$data(canvas) bbox $tTag]
174 $data(canvas) create rect $bbox -fill \#a0a0ff -outline \#a0a0ff \
177 $data(canvas) lower selection
181 proc ::tk::IconList_Get {w item} {
183 upvar ::tk::$w:itemList itemList
184 set rTag [lindex [lindex $data(list) $item] 2]
185 foreach {iTag tTag text serial} $itemList($rTag) {
191 # ::tk::IconList_Config --
193 # Configure the widget variables of IconList, according to the command
196 proc ::tk::IconList_Config {w argList} {
198 # 1: the configuration specs
202 {-multiple "" "" "0"}
205 # 2: parse the arguments
207 tclParseConfigSpec ::tk::$w $specs "" $argList
210 # ::tk::IconList_Create --
212 # Creates an IconList widget by assembling a canvas widget and a
213 # scrollbar widget. Sets all the bindings necessary for the IconList's
216 proc ::tk::IconList_Create {w} {
220 set data(sbar) [scrollbar $w.sbar -orient horizontal \
221 -highlightthickness 0 -takefocus 0]
222 set data(canvas) [canvas $w.canvas -bd 2 -relief sunken \
223 -width 400 -height 120 -takefocus 1]
224 pack $data(sbar) -side bottom -fill x -padx 2
225 pack $data(canvas) -expand yes -fill both
227 $data(sbar) config -command [list $data(canvas) xview]
228 $data(canvas) config -xscrollcommand [list $data(sbar) set]
230 # Initializes the max icon/text width and height and other variables
239 set data(selection) {}
240 set data(index,anchor) ""
241 set fg [option get $data(canvas) foreground Foreground]
248 # Creates the event bindings.
250 bind $data(canvas) <Configure> [list tk::IconList_Arrange $w]
252 bind $data(canvas) <1> [list tk::IconList_Btn1 $w %x %y]
253 bind $data(canvas) <B1-Motion> [list tk::IconList_Motion1 $w %x %y]
254 bind $data(canvas) <B1-Leave> [list tk::IconList_Leave1 $w %x %y]
255 bind $data(canvas) <Control-1> [list tk::IconList_CtrlBtn1 $w %x %y]
256 bind $data(canvas) <Shift-1> [list tk::IconList_ShiftBtn1 $w %x %y]
257 bind $data(canvas) <B1-Enter> [list tk::CancelRepeat]
258 bind $data(canvas) <ButtonRelease-1> [list tk::CancelRepeat]
259 bind $data(canvas) <Double-ButtonRelease-1> \
260 [list tk::IconList_Double1 $w %x %y]
262 bind $data(canvas) <Up> [list tk::IconList_UpDown $w -1]
263 bind $data(canvas) <Down> [list tk::IconList_UpDown $w 1]
264 bind $data(canvas) <Left> [list tk::IconList_LeftRight $w -1]
265 bind $data(canvas) <Right> [list tk::IconList_LeftRight $w 1]
266 bind $data(canvas) <Return> [list tk::IconList_ReturnKey $w]
267 bind $data(canvas) <KeyPress> [list tk::IconList_KeyPress $w %A]
268 bind $data(canvas) <Control-KeyPress> ";"
269 bind $data(canvas) <Alt-KeyPress> ";"
271 bind $data(canvas) <FocusIn> [list tk::IconList_FocusIn $w]
272 bind $data(canvas) <FocusOut> [list tk::IconList_FocusOut $w]
277 # ::tk::IconList_AutoScan --
279 # This procedure is invoked when the mouse leaves an entry window
280 # with button 1 down. It scrolls the window up, down, left, or
281 # right, depending on where the mouse left the window, and reschedules
282 # itself as an "after" command so that the window continues to scroll until
283 # the mouse moves back into the window or the mouse button is released.
286 # w - The IconList window.
288 proc ::tk::IconList_AutoScan {w} {
292 if {![winfo exists $w]} return
296 if {$data(noScroll)} {
299 if {$x >= [winfo width $data(canvas)]} {
300 $data(canvas) xview scroll 1 units
302 $data(canvas) xview scroll -1 units
303 } elseif {$y >= [winfo height $data(canvas)]} {
311 IconList_Motion1 $w $x $y
312 set Priv(afterId) [after 50 [list tk::IconList_AutoScan $w]]
315 # Deletes all the items inside the canvas subwidget and reset the IconList's
318 proc ::tk::IconList_DeleteAll {w} {
320 upvar ::tk::$w:itemList itemList
322 $data(canvas) delete all
323 catch {unset data(selected)}
324 catch {unset data(rect)}
325 catch {unset data(list)}
326 catch {unset itemList}
334 set data(selection) {}
335 set data(index,anchor) ""
336 $data(sbar) set 0.0 1.0
337 $data(canvas) xview moveto 0
340 # Adds an icon into the IconList with the designated image and text
342 proc ::tk::IconList_Add {w image items} {
344 upvar ::tk::$w:itemList itemList
345 upvar ::tk::$w:textList textList
347 foreach text $items {
348 set iTag [$data(canvas) create image 0 0 -image $image -anchor nw \
349 -tags [list icon $data(numItems) item$data(numItems)]]
350 set tTag [$data(canvas) create text 0 0 -text $text -anchor nw \
351 -font $data(font) -fill $data(fill) \
352 -tags [list text $data(numItems) item$data(numItems)]]
353 set rTag [$data(canvas) create rect 0 0 0 0 -fill "" -outline "" \
354 -tags [list rect $data(numItems) item$data(numItems)]]
356 foreach {x1 y1 x2 y2} [$data(canvas) bbox $iTag] {
359 set iW [expr {$x2 - $x1}]
360 set iH [expr {$y2 - $y1}]
361 if {$data(maxIW) < $iW} {
364 if {$data(maxIH) < $iH} {
368 foreach {x1 y1 x2 y2} [$data(canvas) bbox $tTag] {
371 set tW [expr {$x2 - $x1}]
372 set tH [expr {$y2 - $y1}]
373 if {$data(maxTW) < $tW} {
376 if {$data(maxTH) < $tH} {
380 lappend data(list) [list $iTag $tTag $rTag $iW $iH $tW \
382 set itemList($rTag) [list $iTag $tTag $text $data(numItems)]
383 set textList($data(numItems)) [string tolower $text]
388 # Places the icons in a column-major arrangement.
390 proc ::tk::IconList_Arrange {w} {
393 if {![info exists data(list)]} {
394 if {[info exists data(canvas)] && [winfo exists $data(canvas)]} {
396 $data(sbar) config -command ""
401 set W [winfo width $data(canvas)]
402 set H [winfo height $data(canvas)]
403 set pad [expr {[$data(canvas) cget -highlightthickness] + \
404 [$data(canvas) cget -bd]}]
409 incr W -[expr {$pad*2}]
410 incr H -[expr {$pad*2}]
412 set dx [expr {$data(maxIW) + $data(maxTW) + 8}]
413 if {$data(maxTH) > $data(maxIH)} {
419 set shift [expr {$data(maxIW) + 4}]
421 set x [expr {$pad * 2}]
422 set y [expr {$pad * 1}] ; # Why * 1 ?
424 foreach sublist $data(list) {
426 foreach {iTag tTag rTag iW iH tW tH} $sublist {
430 set i_dy [expr {($dy - $iH)/2}]
431 set t_dy [expr {($dy - $tH)/2}]
433 $data(canvas) coords $iTag $x [expr {$y + $i_dy}]
434 $data(canvas) coords $tTag [expr {$x + $shift}] [expr {$y + $t_dy}]
435 $data(canvas) coords $rTag $x $y [expr {$x+$dx}] [expr {$y+$dy}]
438 if {($y + $dy) > $H} {
439 set y [expr {$pad * 1}] ; # *1 ?
446 set sW [expr {$x + $dx}]
452 $data(canvas) config -scrollregion [list $pad $pad $sW $H]
453 $data(sbar) config -command ""
454 $data(canvas) xview moveto 0
457 $data(canvas) config -scrollregion [list $pad $pad $sW $H]
458 $data(sbar) config -command [list $data(canvas) xview]
462 set data(itemsPerColumn) [expr {($H-$pad)/$dy}]
463 if {$data(itemsPerColumn) < 1} {
464 set data(itemsPerColumn) 1
467 if {$data(curItem) != ""} {
468 IconList_Select $w [lindex [lindex $data(list) $data(curItem)] 2] 0
472 # Gets called when the user invokes the IconList (usually by double-clicking
473 # or pressing the Return key).
475 proc ::tk::IconList_Invoke {w} {
478 if {$data(-command) != "" && [llength $data(selection)]} {
479 uplevel #0 $data(-command)
483 # ::tk::IconList_See --
485 # If the item is not (completely) visible, scroll the canvas so that
486 # it becomes visible.
487 proc ::tk::IconList_See {w rTag} {
489 upvar ::tk::$w:itemList itemList
491 if {$data(noScroll)} {
494 set sRegion [$data(canvas) cget -scrollregion]
495 if {[string equal $sRegion {}]} {
499 if { $rTag < 0 || $rTag >= [llength $data(list)] } {
503 set bbox [$data(canvas) bbox item$rTag]
504 set pad [expr {[$data(canvas) cget -highlightthickness] + \
505 [$data(canvas) cget -bd]}]
507 set x1 [lindex $bbox 0]
508 set x2 [lindex $bbox 2]
509 incr x1 -[expr {$pad * 2}]
510 incr x2 -[expr {$pad * 1}] ; # *1 ?
512 set cW [expr {[winfo width $data(canvas)] - $pad*2}]
514 set scrollW [expr {[lindex $sRegion 2]-[lindex $sRegion 0]+1}]
515 set dispX [expr {int([lindex [$data(canvas) xview] 0]*$scrollW)}]
518 # check if out of the right edge
520 if {($x2 - $dispX) >= $cW} {
521 set dispX [expr {$x2 - $cW}]
523 # check if out of the left edge
525 if {($x1 - $dispX) < 0} {
529 if {$oldDispX != $dispX} {
530 set fraction [expr {double($dispX)/double($scrollW)}]
531 $data(canvas) xview moveto $fraction
535 proc ::tk::IconList_Btn1 {w x y} {
539 set x [expr {int([$data(canvas) canvasx $x])}]
540 set y [expr {int([$data(canvas) canvasy $y])}]
541 set i [IconList_Index $w @${x},${y}]
543 IconList_Selection $w clear 0 end
544 IconList_Selection $w set $i
545 IconList_Selection $w anchor $i
548 proc ::tk::IconList_CtrlBtn1 {w x y} {
551 if { $data(-multiple) } {
553 set x [expr {int([$data(canvas) canvasx $x])}]
554 set y [expr {int([$data(canvas) canvasy $y])}]
555 set i [IconList_Index $w @${x},${y}]
557 if { [IconList_Selection $w includes $i] } {
558 IconList_Selection $w clear $i
560 IconList_Selection $w set $i
561 IconList_Selection $w anchor $i
566 proc ::tk::IconList_ShiftBtn1 {w x y} {
569 if { $data(-multiple) } {
571 set x [expr {int([$data(canvas) canvasx $x])}]
572 set y [expr {int([$data(canvas) canvasy $y])}]
573 set i [IconList_Index $w @${x},${y}]
575 set a [IconList_Index $w anchor]
576 if { [string equal $a ""] } {
579 IconList_Selection $w clear 0 end
580 IconList_Selection $w set $a $i
584 # Gets called on button-1 motions
586 proc ::tk::IconList_Motion1 {w x y} {
591 set x [expr {int([$data(canvas) canvasx $x])}]
592 set y [expr {int([$data(canvas) canvasy $y])}]
593 set i [IconList_Index $w @${x},${y}]
595 IconList_Selection $w clear 0 end
596 IconList_Selection $w set $i
599 proc ::tk::IconList_Double1 {w x y} {
602 if {[llength $data(selection)]} {
607 proc ::tk::IconList_ReturnKey {w} {
611 proc ::tk::IconList_Leave1 {w x y} {
619 proc ::tk::IconList_FocusIn {w} {
622 if {![info exists data(list)]} {
626 if {[llength $data(selection)]} {
627 IconList_DrawSelection $w
631 proc ::tk::IconList_FocusOut {w} {
632 IconList_Selection $w clear 0 end
635 # ::tk::IconList_UpDown --
637 # Moves the active element up or down by one element
640 # w - The IconList widget.
641 # amount - +1 to move down one item, -1 to move back one item.
643 proc ::tk::IconList_UpDown {w amount} {
646 if {![info exists data(list)]} {
650 set curr [tk::IconList_Curselection $w]
651 if { [llength $curr] == 0 } {
654 set i [tk::IconList_Index $w anchor]
658 IconList_Selection $w clear 0 end
659 IconList_Selection $w set $i
660 IconList_Selection $w anchor $i
664 # ::tk::IconList_LeftRight --
666 # Moves the active element left or right by one column
669 # w - The IconList widget.
670 # amount - +1 to move right one column, -1 to move left one column.
672 proc ::tk::IconList_LeftRight {w amount} {
675 if {![info exists data(list)]} {
679 set curr [IconList_Curselection $w]
680 if { [llength $curr] == 0 } {
683 set i [IconList_Index $w anchor]
685 incr i [expr {$amount*$data(itemsPerColumn)}]
687 IconList_Selection $w clear 0 end
688 IconList_Selection $w set $i
689 IconList_Selection $w anchor $i
693 #----------------------------------------------------------------------
694 # Accelerator key bindings
695 #----------------------------------------------------------------------
697 # ::tk::IconList_KeyPress --
699 # Gets called when user enters an arbitrary key in the listbox.
701 proc ::tk::IconList_KeyPress {w key} {
704 append Priv(ILAccel,$w) $key
705 IconList_Goto $w $Priv(ILAccel,$w)
707 after cancel $Priv(ILAccel,$w,afterId)
709 set Priv(ILAccel,$w,afterId) [after 500 [list tk::IconList_Reset $w]]
712 proc ::tk::IconList_Goto {w text} {
714 upvar ::tk::$w:textList textList
716 if {![info exists data(list)]} {
720 if {[string equal {} $text]} {
724 if {$data(curItem) == "" || $data(curItem) == 0} {
727 set start $data(curItem)
730 set text [string tolower $text]
733 set len [string length $text]
734 set len0 [expr {$len-1}]
737 # Search forward until we find a filename whose prefix is an exact match
740 set sub [string range $textList($i) 0 $len0]
741 if {[string equal $text $sub]} {
746 if {$i == $data(numItems)} {
754 if {$theIndex > -1} {
755 IconList_Selection $w clear 0 end
756 IconList_Selection $w set $theIndex
757 IconList_Selection $w anchor $theIndex
758 IconList_See $w $theIndex
762 proc ::tk::IconList_Reset {w} {
765 catch {unset Priv(ILAccel,$w)}
768 #----------------------------------------------------------------------
770 # F I L E D I A L O G
772 #----------------------------------------------------------------------
774 namespace eval ::tk::dialog {}
775 namespace eval ::tk::dialog::file {
776 namespace import -force ::tk::msgcat::*
779 # ::tk::dialog::file:: --
781 # Implements the TK file selection dialog. This dialog is used when
782 # the tk_strictMotif flag is set to false. This procedure shouldn't
783 # be called directly. Call tk_getOpenFile or tk_getSaveFile instead.
786 # type "open" or "save"
787 # args Options parsed by the procedure.
790 proc ::tk::dialog::file:: {type args} {
792 set dataName __tk_filedialog
793 upvar ::tk::dialog::file::$dataName data
795 ::tk::dialog::file::Config $dataName $type $args
797 if {[string equal $data(-parent) .]} {
800 set w $data(-parent).$dataName
803 # (re)create the dialog box if necessary
805 if {![winfo exists $w]} {
806 ::tk::dialog::file::Create $w TkFDialog
807 } elseif {[string compare [winfo class $w] TkFDialog]} {
809 ::tk::dialog::file::Create $w TkFDialog
811 set data(dirMenuBtn) $w.f1.menu
812 set data(dirMenu) $w.f1.menu.menu
813 set data(upBtn) $w.f1.up
814 set data(icons) $w.icons
815 set data(ent) $w.f2.ent
816 set data(typeMenuLab) $w.f2.lab
817 set data(typeMenuBtn) $w.f2.menu
818 set data(typeMenu) $data(typeMenuBtn).m
819 set data(okBtn) $w.f2.ok
820 set data(cancelBtn) $w.f2.cancel
821 ::tk::dialog::file::SetSelectMode $w $data(-multiple)
824 # Dialog boxes should be transient with respect to their parent,
825 # so that they will always stay on top of their parent window. However,
826 # some window managers will create the window as withdrawn if the parent
827 # window is withdrawn or iconified. Combined with the grab we put on the
828 # window, this can hang the entire application. Therefore we only make
829 # the dialog transient if the parent is viewable.
831 if {[winfo viewable [winfo toplevel $data(-parent)]] } {
832 wm transient $w $data(-parent)
835 # Add traces on the selectPath variable
838 trace variable data(selectPath) w "::tk::dialog::file::SetPath $w"
839 $data(dirMenuBtn) configure \
840 -textvariable ::tk::dialog::file::${dataName}(selectPath)
842 # Initialize the file types menu
844 if {[llength $data(-filetypes)]} {
845 $data(typeMenu) delete 0 end
846 foreach type $data(-filetypes) {
847 set title [lindex $type 0]
848 set filter [lindex $type 1]
849 $data(typeMenu) add command -label $title \
850 -command [list ::tk::dialog::file::SetFilter $w $type]
852 ::tk::dialog::file::SetFilter $w [lindex $data(-filetypes) 0]
853 $data(typeMenuBtn) config -state normal
854 $data(typeMenuLab) config -state normal
857 $data(typeMenuBtn) config -state disabled -takefocus 0
858 $data(typeMenuLab) config -state disabled
860 ::tk::dialog::file::UpdateWhenIdle $w
862 # Withdraw the window, then update all the geometry information
863 # so we know how big it wants to be, then center the window in the
864 # display and de-iconify it.
866 ::tk::PlaceWindow $w widget $data(-parent)
867 wm title $w $data(-title)
869 # Set a grab and claim the focus too.
871 ::tk::SetFocusGrab $w $data(ent)
872 $data(ent) delete 0 end
873 $data(ent) insert 0 $data(selectFile)
874 $data(ent) selection range 0 end
875 $data(ent) icursor end
877 # Wait for the user to respond, then restore the focus and
878 # return the index of the selected button. Restore the focus
879 # before deleting the window, since otherwise the window manager
880 # may take the focus away so we can't redirect it. Finally,
881 # restore any grab that was in effect.
883 vwait ::tk::Priv(selectFilePath)
885 ::tk::RestoreFocusGrab $w $data(ent) withdraw
887 # Cleanup traces on selectPath variable
890 foreach trace [trace vinfo data(selectPath)] {
891 trace vdelete data(selectPath) [lindex $trace 0] [lindex $trace 1]
893 $data(dirMenuBtn) configure -textvariable {}
895 return $Priv(selectFilePath)
898 # ::tk::dialog::file::Config --
900 # Configures the TK filedialog according to the argument list
902 proc ::tk::dialog::file::Config {dataName type argList} {
903 upvar ::tk::dialog::file::$dataName data
907 # 0: Delete all variable that were set on data(selectPath) the
908 # last time the file dialog is used. The traces may cause troubles
909 # if the dialog is now used with a different -parent option.
911 foreach trace [trace vinfo data(selectPath)] {
912 trace vdelete data(selectPath) [lindex $trace 0] [lindex $trace 1]
915 # 1: the configuration specs
918 {-defaultextension "" "" ""}
919 {-filetypes "" "" ""}
920 {-initialdir "" "" ""}
921 {-initialfile "" "" ""}
926 # The "-multiple" option is only available for the "open" file dialog.
928 if { [string equal $type "open"] } {
929 lappend specs {-multiple "" "" "0"}
932 # 2: default values depending on the type of the dialog
934 if {![info exists data(selectPath)]} {
935 # first time the dialog has been popped up
936 set data(selectPath) [pwd]
937 set data(selectFile) ""
940 # 3: parse the arguments
942 tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
944 if {$data(-title) == ""} {
945 if {[string equal $type "open"]} {
946 set data(-title) "[mc "Open"]"
948 set data(-title) "[mc "Save As"]"
952 # 4: set the default directory and selection according to the -initial
955 if {$data(-initialdir) != ""} {
956 # Ensure that initialdir is an absolute path name.
957 if {[file isdirectory $data(-initialdir)]} {
959 cd $data(-initialdir)
960 set data(selectPath) [pwd]
963 set data(selectPath) [pwd]
966 set data(selectFile) $data(-initialfile)
968 # 5. Parse the -filetypes option
970 set data(-filetypes) [::tk::FDGetFileTypes $data(-filetypes)]
972 if {![winfo exists $data(-parent)]} {
973 error "bad window path name \"$data(-parent)\""
976 # Set -multiple to a one or zero value (not other boolean types
977 # like "yes") so we can use it in tests more easily.
978 if {![string compare $type save]} {
979 set data(-multiple) 0
980 } elseif {$data(-multiple)} {
981 set data(-multiple) 1
983 set data(-multiple) 0
987 proc ::tk::dialog::file::Create {w class} {
988 set dataName [lindex [split $w .] end]
989 upvar ::tk::dialog::file::$dataName data
993 toplevel $w -class $class
995 # f1: the frame with the directory option menu
998 bind [::tk::AmpWidget label $f1.lab -text "[mc "&Directory:"]" ] \
999 <<AltUnderlined>> [list focus $f1.menu]
1001 set data(dirMenuBtn) $f1.menu
1002 set data(dirMenu) [tk_optionMenu $f1.menu [format %s(selectPath) ::tk::dialog::file::$dataName] ""]
1003 set data(upBtn) [button $f1.up]
1004 if {![info exists Priv(updirImage)]} {
1005 set Priv(updirImage) [image create bitmap -data {
1006 #define updir_width 28
1007 #define updir_height 16
1008 static char updir_bits[] = {
1009 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00,
1010 0x20, 0x40, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x01, 0x10, 0x00, 0x00, 0x01,
1011 0x10, 0x02, 0x00, 0x01, 0x10, 0x07, 0x00, 0x01, 0x90, 0x0f, 0x00, 0x01,
1012 0x10, 0x02, 0x00, 0x01, 0x10, 0x02, 0x00, 0x01, 0x10, 0x02, 0x00, 0x01,
1013 0x10, 0xfe, 0x07, 0x01, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01,
1014 0xf0, 0xff, 0xff, 0x01};}]
1016 $data(upBtn) config -image $Priv(updirImage)
1018 $f1.menu config -takefocus 1 -highlightthickness 2
1020 pack $data(upBtn) -side right -padx 4 -fill both
1021 pack $f1.lab -side left -padx 4 -fill both
1022 pack $f1.menu -expand yes -fill both -padx 4
1024 # data(icons): the IconList that list the files and directories.
1026 if { [string equal $class TkFDialog] } {
1027 if { $data(-multiple) } {
1028 set fNameCaption [mc "File &names:"]
1030 set fNameCaption [mc "File &name:"]
1032 set fTypeCaption [mc "Files of &type:"]
1033 set iconListCommand [list ::tk::dialog::file::OkCmd $w]
1035 set fNameCaption [mc "&Selection:"]
1036 set iconListCommand [list ::tk::dialog::file::chooseDir::DblClick $w]
1038 set data(icons) [::tk::IconList $w.icons \
1039 -command $iconListCommand \
1040 -multiple $data(-multiple)]
1041 bind $data(icons) <<ListboxSelect>> \
1042 [list ::tk::dialog::file::ListBrowse $w]
1044 # f2: the frame with the OK button, cancel button, "file name" field
1045 # and file types field.
1047 set f2 [frame $w.f2 -bd 0]
1048 bind [::tk::AmpWidget label $f2.lab -text $fNameCaption -anchor e -pady 0]\
1049 <<AltUnderlined>> [list focus $f2.ent]
1050 set data(ent) [entry $f2.ent]
1052 # The font to use for the icons. The default Canvas font on Unix
1054 set ::tk::$w.icons(font) [$data(ent) cget -font]
1056 # Make the file types bits only if this is a File Dialog
1057 if { [string equal $class TkFDialog] } {
1058 # The "File of types:" label needs to be grayed-out when
1059 # -filetypes are not specified. The label widget does not support
1060 # grayed-out text on monochrome displays. Therefore, we have to
1061 # use a button widget to emulate a label widget (by setting its
1064 set data(typeMenuLab) [::tk::AmpWidget button $f2.lab2 \
1065 -text $fTypeCaption -anchor e -bd [$f2.lab cget -bd] \
1066 -highlightthickness [$f2.lab cget -highlightthickness] \
1067 -relief [$f2.lab cget -relief] \
1068 -padx [$f2.lab cget -padx] \
1069 -pady [$f2.lab cget -pady]]
1070 bindtags $data(typeMenuLab) [list $data(typeMenuLab) Label \
1071 [winfo toplevel $data(typeMenuLab)] all]
1072 set data(typeMenuBtn) [menubutton $f2.menu -indicatoron 1 \
1074 set data(typeMenu) [menu $data(typeMenuBtn).m -tearoff 0]
1075 $data(typeMenuBtn) config -takefocus 1 -highlightthickness 2 \
1076 -relief raised -bd 2 -anchor w
1077 bind $data(typeMenuLab) <<AltUnderlined>> [list \
1078 focus $data(typeMenuBtn)]
1081 # the okBtn is created after the typeMenu so that the keyboard traversal
1082 # is in the right order
1083 set data(okBtn) [::tk::AmpWidget button $f2.ok \
1084 -text "[mc "&OK"]" -default active -pady 3]
1085 set data(cancelBtn) [::tk::AmpWidget button $f2.cancel \
1086 -text "[mc "&Cancel"]" -default normal -pady 3]
1088 # grid the widgets in f2
1090 grid $f2.lab $f2.ent $data(okBtn) -padx 4 -sticky ew
1091 grid configure $f2.ent -padx 2
1092 if { [string equal $class TkFDialog] } {
1093 grid $data(typeMenuLab) $data(typeMenuBtn) $data(cancelBtn) \
1095 grid configure $data(typeMenuBtn) -padx 0
1097 grid x x $data(cancelBtn) -padx 4 -sticky ew
1099 grid columnconfigure $f2 1 -weight 1
1101 # Pack all the frames together. We are done with widget construction.
1103 pack $f1 -side top -fill x -pady 4
1104 pack $f2 -side bottom -fill x
1105 pack $data(icons) -expand yes -fill both -padx 4 -pady 1
1107 # Set up the event handlers that are common to Directory and File Dialogs
1110 wm protocol $w WM_DELETE_WINDOW [list ::tk::dialog::file::CancelCmd $w]
1111 $data(upBtn) config -command [list ::tk::dialog::file::UpDirCmd $w]
1112 $data(cancelBtn) config -command [list ::tk::dialog::file::CancelCmd $w]
1113 bind $w <KeyPress-Escape> [list tk::ButtonInvoke $data(cancelBtn)]
1114 bind $w <Alt-Key> [list tk::AltKeyInDialog $w %A]
1115 # Set up event handlers specific to File or Directory Dialogs
1118 if { [string equal $class TkFDialog] } {
1119 bind $data(ent) <Return> [list ::tk::dialog::file::ActivateEnt $w]
1120 $data(okBtn) config -command [list ::tk::dialog::file::OkCmd $w]
1121 bind $w <Alt-t> [format {
1122 if {[string equal [%s cget -state] "normal"]} {
1125 } $data(typeMenuBtn) $data(typeMenuBtn)]
1127 set okCmd [list ::tk::dialog::file::chooseDir::OkCmd $w]
1128 bind $data(ent) <Return> $okCmd
1129 $data(okBtn) config -command $okCmd
1130 bind $w <Alt-s> [list focus $data(ent)]
1131 bind $w <Alt-o> [list tk::ButtonInvoke $data(okBtn)]
1134 # Build the focus group for all the entries
1136 ::tk::FocusGroup_Create $w
1137 ::tk::FocusGroup_BindIn $w $data(ent) [list ::tk::dialog::file::EntFocusIn $w]
1138 ::tk::FocusGroup_BindOut $w $data(ent) [list ::tk::dialog::file::EntFocusOut $w]
1141 # ::tk::dialog::file::SetSelectMode --
1143 # Set the select mode of the dialog to single select or multi-select.
1146 # w The dialog path.
1147 # multi 1 if the dialog is multi-select; 0 otherwise.
1152 proc ::tk::dialog::file::SetSelectMode {w multi} {
1153 set dataName __tk_filedialog
1154 upvar ::tk::dialog::file::$dataName data
1156 set fNameCaption "[mc {File &names:}]"
1158 set fNameCaption "[mc {File &name:}]"
1160 set iconListCommand [list ::tk::dialog::file::OkCmd $w]
1161 ::tk::SetAmpText $w.f2.lab $fNameCaption
1162 ::tk::IconList_Config $data(icons) \
1163 [list -multiple $multi -command $iconListCommand]
1167 # ::tk::dialog::file::UpdateWhenIdle --
1169 # Creates an idle event handler which updates the dialog in idle
1170 # time. This is important because loading the directory may take a long
1171 # time and we don't want to load the same directory for multiple times
1172 # due to multiple concurrent events.
1174 proc ::tk::dialog::file::UpdateWhenIdle {w} {
1175 upvar ::tk::dialog::file::[winfo name $w] data
1177 if {[info exists data(updateId)]} {
1180 set data(updateId) [after idle [list ::tk::dialog::file::Update $w]]
1184 # ::tk::dialog::file::Update --
1186 # Loads the files and directories into the IconList widget. Also
1187 # sets up the directory option menu for quick access to parent
1190 proc ::tk::dialog::file::Update {w} {
1192 # This proc may be called within an idle handler. Make sure that the
1193 # window has not been destroyed before this proc is called
1194 if {![winfo exists $w]} {
1197 set class [winfo class $w]
1198 if {($class ne "TkFDialog") && ($class ne "TkChooseDir")} {
1202 set dataName [winfo name $w]
1203 upvar ::tk::dialog::file::$dataName data
1206 catch {unset data(updateId)}
1208 if {![info exists Priv(folderImage)]} {
1209 set Priv(folderImage) [image create photo -data {
1210 R0lGODlhEAAMAKEAAAD//wAAAPD/gAAAACH5BAEAAAAALAAAAAAQAAwAAAIghINhyycvVFsB
1211 QtmS3rjaH1Hg141WaT5ouprt2HHcUgAAOw==}]
1212 set Priv(fileImage) [image create photo -data {
1213 R0lGODlhDAAMAKEAALLA3AAAAP//8wAAACH5BAEAAAAALAAAAAAMAAwAAAIgRI4Ha+IfWHsO
1214 rSASvJTGhnhcV3EJlo3kh53ltF5nAhQAOw==}]
1216 set folder $Priv(folderImage)
1217 set file $Priv(fileImage)
1221 cd $data(selectPath)
1223 # We cannot change directory to $data(selectPath). $data(selectPath)
1224 # should have been checked before ::tk::dialog::file::Update is called, so
1225 # we normally won't come to here. Anyways, give an error and abort
1227 tk_messageBox -type ok -parent $w -icon warning -message \
1228 [mc "Cannot change to the directory \"%1\$s\".\nPermission denied." $data(selectPath)]
1233 # Turn on the busy cursor. BUG?? We haven't disabled X events, though,
1234 # so the user may still click and cause havoc ...
1236 set entCursor [$data(ent) cget -cursor]
1237 set dlgCursor [$w cget -cursor]
1238 $data(ent) config -cursor watch
1239 $w config -cursor watch
1242 ::tk::IconList_DeleteAll $data(icons)
1246 set dirs [lsort -dictionary -unique \
1247 [glob -tails -directory . -type d -nocomplain .* *]]
1250 if {$d eq "." || $d eq ".."} {
1255 ::tk::IconList_Add $data(icons) $folder $dirList
1257 if {$class eq "TkFDialog"} {
1258 # Make the file list if this is a File Dialog, selecting all
1259 # but 'd'irectory type files.
1261 set cmd [list glob -tails -directory . -type {f b c l p s} -nocomplain]
1262 if {[string equal $data(filter) *]} {
1265 eval [list lappend cmd] $data(filter)
1267 set fileList [lsort -dictionary -unique [eval $cmd]]
1268 ::tk::IconList_Add $data(icons) $file $fileList
1271 ::tk::IconList_Arrange $data(icons)
1273 # Update the Directory: option menu
1277 foreach subdir [file split $data(selectPath)] {
1278 set dir [file join $dir $subdir]
1282 $data(dirMenu) delete 0 end
1283 set var [format %s(selectPath) ::tk::dialog::file::$dataName]
1284 foreach path $list {
1285 $data(dirMenu) add command -label $path -command [list set $var $path]
1288 # Restore the PWD to the application's PWD
1292 if { [string equal $class TkFDialog] } {
1293 # Restore the Open/Save Button if this is a File Dialog
1295 if {[string equal $data(type) open]} {
1296 ::tk::SetAmpText $data(okBtn) [mc "&Open"]
1298 ::tk::SetAmpText $data(okBtn) [mc "&Save"]
1302 # turn off the busy cursor.
1304 $data(ent) config -cursor $entCursor
1305 $w config -cursor $dlgCursor
1308 # ::tk::dialog::file::SetPathSilently --
1310 # Sets data(selectPath) without invoking the trace procedure
1312 proc ::tk::dialog::file::SetPathSilently {w path} {
1313 upvar ::tk::dialog::file::[winfo name $w] data
1315 trace vdelete data(selectPath) w [list ::tk::dialog::file::SetPath $w]
1316 set data(selectPath) $path
1317 trace variable data(selectPath) w [list ::tk::dialog::file::SetPath $w]
1321 # This proc gets called whenever data(selectPath) is set
1323 proc ::tk::dialog::file::SetPath {w name1 name2 op} {
1324 if {[winfo exists $w]} {
1325 upvar ::tk::dialog::file::[winfo name $w] data
1326 ::tk::dialog::file::UpdateWhenIdle $w
1327 # On directory dialogs, we keep the entry in sync with the currentdir.
1328 if { [string equal [winfo class $w] TkChooseDir] } {
1329 $data(ent) delete 0 end
1330 $data(ent) insert end $data(selectPath)
1335 # This proc gets called whenever data(filter) is set
1337 proc ::tk::dialog::file::SetFilter {w type} {
1338 upvar ::tk::dialog::file::[winfo name $w] data
1339 upvar ::tk::$data(icons) icons
1341 set data(filter) [lindex $type 1]
1342 $data(typeMenuBtn) config -text [lindex $type 0] -indicatoron 1
1344 # If we aren't using a default extension, use the one suppled
1346 if {![info exists data(extUsed)]} {
1347 if {[string length $data(-defaultextension)]} {
1354 if {!$data(extUsed)} {
1355 # Get the first extension in the list that matches {^\*\.\w+$}
1356 # and remove all * from the filter.
1357 set index [lsearch -regexp $data(filter) {^\*\.\w+$}]
1359 set data(-defaultextension) \
1360 [string trimleft [lindex $data(filter) $index] "*"]
1362 # Couldn't find anything! Reset to a safe default...
1363 set data(-defaultextension) ""
1367 $icons(sbar) set 0.0 0.0
1369 ::tk::dialog::file::UpdateWhenIdle $w
1372 # tk::dialog::file::ResolveFile --
1374 # Interpret the user's text input in a file selection dialog.
1377 # (1) ~ substitution
1378 # (2) resolve all instances of . and ..
1379 # (3) check for non-existent files/directories
1380 # (4) check for chdir permissions
1383 # context: the current directory you are in
1384 # text: the text entered by the user
1385 # defaultext: the default extension to add to files with no extension
1388 # [list $flag $directory $file]
1390 # flag = OK : valid input
1391 # = PATTERN : valid directory/pattern
1392 # = PATH : the directory does not exist
1393 # = FILE : the directory exists by the file doesn't
1395 # = CHDIR : Cannot change to the directory
1396 # = ERROR : Invalid entry
1398 # directory : valid only if flag = OK or PATTERN or FILE
1399 # file : valid only if flag = OK or PATTERN
1401 # directory may not be the same as context, because text may contain
1402 # a subdirectory name
1404 proc ::tk::dialog::file::ResolveFile {context text defaultext} {
1408 set path [::tk::dialog::file::JoinFile $context $text]
1410 # If the file has no extension, append the default. Be careful not
1411 # to do this for directories, otherwise typing a dirname in the box
1412 # will give back "dirname.extension" instead of trying to change dir.
1413 if {![file isdirectory $path] && [string equal [file ext $path] ""]} {
1414 set path "$path$defaultext"
1418 if {[catch {file exists $path}]} {
1419 # This "if" block can be safely removed if the following code
1420 # stop generating errors.
1422 # file exists ~nonsuchuser
1424 return [list ERROR $path ""]
1427 if {[file exists $path]} {
1428 if {[file isdirectory $path]} {
1429 if {[catch {cd $path}]} {
1430 return [list CHDIR $path ""]
1437 if {[catch {cd [file dirname $path]}]} {
1438 return [list CHDIR [file dirname $path] ""]
1441 set file [file tail $path]
1446 set dirname [file dirname $path]
1447 if {[file exists $dirname]} {
1448 if {[catch {cd $dirname}]} {
1449 return [list CHDIR $dirname ""]
1452 set file [file tail $path]
1453 if {[regexp {[*]|[?]} $file]} {
1460 set directory $dirname
1461 set file [file tail $path]
1466 return [list $flag $directory $file]
1470 # Gets called when the entry box gets keyboard focus. We clear the selection
1471 # from the icon list . This way the user can be certain that the input in the
1472 # entry box is the selection.
1474 proc ::tk::dialog::file::EntFocusIn {w} {
1475 upvar ::tk::dialog::file::[winfo name $w] data
1477 if {[string compare [$data(ent) get] ""]} {
1478 $data(ent) selection range 0 end
1479 $data(ent) icursor end
1481 $data(ent) selection clear
1484 if { [string equal [winfo class $w] TkFDialog] } {
1485 # If this is a File Dialog, make sure the buttons are labeled right.
1486 if {[string equal $data(type) open]} {
1487 ::tk::SetAmpText $data(okBtn) [mc "&Open"]
1489 ::tk::SetAmpText $data(okBtn) [mc "&Save"]
1494 proc ::tk::dialog::file::EntFocusOut {w} {
1495 upvar ::tk::dialog::file::[winfo name $w] data
1497 $data(ent) selection clear
1501 # Gets called when user presses Return in the "File name" entry.
1503 proc ::tk::dialog::file::ActivateEnt {w} {
1504 upvar ::tk::dialog::file::[winfo name $w] data
1506 set text [$data(ent) get]
1507 if {$data(-multiple)} {
1508 # For the multiple case we have to be careful to get the file
1509 # names as a true list, watching out for a single file with a
1510 # space in the name. Thus we query the IconList directly.
1512 set selIcos [::tk::IconList_Curselection $data(icons)]
1513 set data(selectFile) ""
1514 if {[llength $selIcos] == 0 && $text ne ""} {
1515 # This assumes the user typed something in without selecting
1516 # files - so assume they only type in a single filename.
1517 ::tk::dialog::file::VerifyFileName $w $text
1519 foreach item $selIcos {
1520 ::tk::dialog::file::VerifyFileName $w \
1521 [::tk::IconList_Get $data(icons) $item]
1525 ::tk::dialog::file::VerifyFileName $w $text
1529 # Verification procedure
1531 proc ::tk::dialog::file::VerifyFileName {w filename} {
1532 upvar ::tk::dialog::file::[winfo name $w] data
1534 set list [::tk::dialog::file::ResolveFile $data(selectPath) $filename \
1535 $data(-defaultextension)]
1536 foreach {flag path file} $list {
1542 if {[string equal $file ""]} {
1543 # user has entered an existing (sub)directory
1544 set data(selectPath) $path
1545 $data(ent) delete 0 end
1547 ::tk::dialog::file::SetPathSilently $w $path
1548 if {$data(-multiple)} {
1549 lappend data(selectFile) $file
1551 set data(selectFile) $file
1553 ::tk::dialog::file::Done $w
1557 set data(selectPath) $path
1558 set data(filter) $file
1561 if {[string equal $data(type) open]} {
1562 tk_messageBox -icon warning -type ok -parent $w \
1563 -message "[mc "File \"%1\$s\" does not exist." [file join $path $file]]"
1564 $data(ent) selection range 0 end
1565 $data(ent) icursor end
1567 ::tk::dialog::file::SetPathSilently $w $path
1568 if {$data(-multiple)} {
1569 lappend data(selectFile) $file
1571 set data(selectFile) $file
1573 ::tk::dialog::file::Done $w
1577 tk_messageBox -icon warning -type ok -parent $w \
1578 -message "[mc "Directory \"%1\$s\" does not exist." $path]"
1579 $data(ent) selection range 0 end
1580 $data(ent) icursor end
1583 tk_messageBox -type ok -parent $w -message \
1584 "[mc "Cannot change to the directory \"%1\$s\".\nPermission denied." $path]"\
1586 $data(ent) selection range 0 end
1587 $data(ent) icursor end
1590 tk_messageBox -type ok -parent $w -message \
1591 "[mc "Invalid file name \"%1\$s\"." $path]"\
1593 $data(ent) selection range 0 end
1594 $data(ent) icursor end
1599 # Gets called when user presses the Alt-s or Alt-o keys.
1601 proc ::tk::dialog::file::InvokeBtn {w key} {
1602 upvar ::tk::dialog::file::[winfo name $w] data
1604 if {[string equal [$data(okBtn) cget -text] $key]} {
1605 ::tk::ButtonInvoke $data(okBtn)
1609 # Gets called when user presses the "parent directory" button
1611 proc ::tk::dialog::file::UpDirCmd {w} {
1612 upvar ::tk::dialog::file::[winfo name $w] data
1614 if {[string compare $data(selectPath) "/"]} {
1615 set data(selectPath) [file dirname $data(selectPath)]
1619 # Join a file name to a path name. The "file join" command will break
1620 # if the filename begins with ~
1622 proc ::tk::dialog::file::JoinFile {path file} {
1623 if {[string match {~*} $file] && [file exists $path/$file]} {
1624 return [file join $path ./$file]
1626 return [file join $path $file]
1630 # Gets called when user presses the "OK" button
1632 proc ::tk::dialog::file::OkCmd {w} {
1633 upvar ::tk::dialog::file::[winfo name $w] data
1636 foreach item [::tk::IconList_Curselection $data(icons)] {
1637 lappend filenames [::tk::IconList_Get $data(icons) $item]
1640 if {([llength $filenames] && !$data(-multiple)) || \
1641 ($data(-multiple) && ([llength $filenames] == 1))} {
1642 set filename [lindex $filenames 0]
1643 set file [::tk::dialog::file::JoinFile $data(selectPath) $filename]
1644 if {[file isdirectory $file]} {
1645 ::tk::dialog::file::ListInvoke $w [list $filename]
1650 ::tk::dialog::file::ActivateEnt $w
1653 # Gets called when user presses the "Cancel" button
1655 proc ::tk::dialog::file::CancelCmd {w} {
1656 upvar ::tk::dialog::file::[winfo name $w] data
1659 set Priv(selectFilePath) ""
1662 # Gets called when user browses the IconList widget (dragging mouse, arrow
1665 proc ::tk::dialog::file::ListBrowse {w} {
1666 upvar ::tk::dialog::file::[winfo name $w] data
1669 foreach item [::tk::IconList_Curselection $data(icons)] {
1670 lappend text [::tk::IconList_Get $data(icons) $item]
1672 if {[llength $text] == 0} {
1675 if { [llength $text] > 1 } {
1677 foreach file $text {
1678 set fullfile [::tk::dialog::file::JoinFile $data(selectPath) $file]
1679 if { ![file isdirectory $fullfile] } {
1680 lappend newtext $file
1686 set text [lindex $text 0]
1687 set file [::tk::dialog::file::JoinFile $data(selectPath) $text]
1688 set isDir [file isdirectory $file]
1691 $data(ent) delete 0 end
1692 $data(ent) insert 0 $text
1694 if { [string equal [winfo class $w] TkFDialog] } {
1695 if {[string equal $data(type) open]} {
1696 ::tk::SetAmpText $data(okBtn) [mc "&Open"]
1698 ::tk::SetAmpText $data(okBtn) [mc "&Save"]
1702 if { [string equal [winfo class $w] TkFDialog] } {
1703 ::tk::SetAmpText $data(okBtn) [mc "&Open"]
1708 # Gets called when user invokes the IconList widget (double-click,
1711 proc ::tk::dialog::file::ListInvoke {w filenames} {
1712 upvar ::tk::dialog::file::[winfo name $w] data
1714 if {[llength $filenames] == 0} {
1718 set file [::tk::dialog::file::JoinFile $data(selectPath) \
1719 [lindex $filenames 0]]
1721 set class [winfo class $w]
1722 if {[string equal $class TkChooseDir] || [file isdirectory $file]} {
1724 if {[catch {cd $file}]} {
1725 tk_messageBox -type ok -parent $w -message \
1726 "[mc "Cannot change to the directory \"%1\$s\".\nPermission denied." $file]"\
1730 set data(selectPath) $file
1733 if {$data(-multiple)} {
1734 set data(selectFile) $filenames
1736 set data(selectFile) $file
1738 ::tk::dialog::file::Done $w
1742 # ::tk::dialog::file::Done --
1744 # Gets called when user has input a valid filename. Pops up a
1745 # dialog box to confirm selection when necessary. Sets the
1746 # tk::Priv(selectFilePath) variable, which will break the "vwait"
1747 # loop in ::tk::dialog::file:: and return the selected filename to the
1748 # script that calls tk_getOpenFile or tk_getSaveFile
1750 proc ::tk::dialog::file::Done {w {selectFilePath ""}} {
1751 upvar ::tk::dialog::file::[winfo name $w] data
1754 if {[string equal $selectFilePath ""]} {
1755 if {$data(-multiple)} {
1756 set selectFilePath {}
1757 foreach f $data(selectFile) {
1758 lappend selectFilePath [::tk::dialog::file::JoinFile \
1759 $data(selectPath) $f]
1762 set selectFilePath [::tk::dialog::file::JoinFile \
1763 $data(selectPath) $data(selectFile)]
1766 set Priv(selectFile) $data(selectFile)
1767 set Priv(selectPath) $data(selectPath)
1769 if {[string equal $data(type) save]} {
1770 if {[file exists $selectFilePath]} {
1771 set reply [tk_messageBox -icon warning -type yesno\
1772 -parent $w -message \
1773 "[mc "File \"%1\$s\" already exists.\nDo you want to overwrite it?" $selectFilePath]"]
1774 if {[string equal $reply "no"]} {
1780 set Priv(selectFilePath) $selectFilePath