choosedir.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:9k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # choosedir.tcl --
  2. #
  3. # Choose directory dialog implementation for Unix/Mac.
  4. #
  5. # Copyright (c) 1998-2000 by Scriptics Corporation.
  6. # All rights reserved.
  7. # RCS: @(#) $Id: choosedir.tcl,v 1.15.2.2 2006/01/25 18:21:41 dgp Exp $
  8. # Make sure the tk::dialog namespace, in which all dialogs should live, exists
  9. namespace eval ::tk::dialog {}
  10. namespace eval ::tk::dialog::file {}
  11. # Make the chooseDir namespace inside the dialog namespace
  12. namespace eval ::tk::dialog::file::chooseDir {
  13.     namespace import -force ::tk::msgcat::*
  14. }
  15. # ::tk::dialog::file::chooseDir:: --
  16. #
  17. # Implements the TK directory selection dialog.
  18. #
  19. # Arguments:
  20. # args Options parsed by the procedure.
  21. #
  22. proc ::tk::dialog::file::chooseDir:: {args} {
  23.     variable ::tk::Priv
  24.     set dataName __tk_choosedir
  25.     upvar ::tk::dialog::file::$dataName data
  26.     ::tk::dialog::file::chooseDir::Config $dataName $args
  27.     if {$data(-parent) eq "."} {
  28.         set w .$dataName
  29.     } else {
  30.         set w $data(-parent).$dataName
  31.     }
  32.     # (re)create the dialog box if necessary
  33.     #
  34.     if {![winfo exists $w]} {
  35. ::tk::dialog::file::Create $w TkChooseDir
  36.     } elseif {[winfo class $w] ne "TkChooseDir"} {
  37. destroy $w
  38. ::tk::dialog::file::Create $w TkChooseDir
  39.     } else {
  40. set data(dirMenuBtn) $w.f1.menu
  41. set data(dirMenu) $w.f1.menu.menu
  42. set data(upBtn) $w.f1.up
  43. set data(icons) $w.icons
  44. set data(ent) $w.f2.ent
  45. set data(okBtn) $w.f2.ok
  46. set data(cancelBtn) $w.f2.cancel
  47. set data(hiddenBtn) $w.f2.hidden
  48.     }
  49.     if {$::tk::dialog::file::showHiddenBtn} {
  50. $data(hiddenBtn) configure -state normal
  51. grid $data(hiddenBtn)
  52.     } else {
  53. $data(hiddenBtn) configure -state disabled
  54. grid remove $data(hiddenBtn)
  55.     }
  56.     # Dialog boxes should be transient with respect to their parent,
  57.     # so that they will always stay on top of their parent window.  However,
  58.     # some window managers will create the window as withdrawn if the parent
  59.     # window is withdrawn or iconified.  Combined with the grab we put on the
  60.     # window, this can hang the entire application.  Therefore we only make
  61.     # the dialog transient if the parent is viewable.
  62.     if {[winfo viewable [winfo toplevel $data(-parent)]] } {
  63. wm transient $w $data(-parent)
  64.     }
  65.     trace add variable data(selectPath) write [list ::tk::dialog::file::SetPath $w]
  66.     $data(dirMenuBtn) configure 
  67.     -textvariable ::tk::dialog::file::${dataName}(selectPath)
  68.     set data(filter) "*"
  69.     set data(previousEntryText) ""
  70.     ::tk::dialog::file::UpdateWhenIdle $w
  71.     # Withdraw the window, then update all the geometry information
  72.     # so we know how big it wants to be, then center the window in the
  73.     # display and de-iconify it.
  74.     ::tk::PlaceWindow $w widget $data(-parent)
  75.     wm title $w $data(-title)
  76.     # Set a grab and claim the focus too.
  77.     ::tk::SetFocusGrab $w $data(ent)
  78.     $data(ent) delete 0 end
  79.     $data(ent) insert 0 $data(selectPath)
  80.     $data(ent) selection range 0 end
  81.     $data(ent) icursor end
  82.     # Wait for the user to respond, then restore the focus and
  83.     # return the index of the selected button.  Restore the focus
  84.     # before deleting the window, since otherwise the window manager
  85.     # may take the focus away so we can't redirect it.  Finally,
  86.     # restore any grab that was in effect.
  87.     vwait ::tk::Priv(selectFilePath)
  88.     ::tk::RestoreFocusGrab $w $data(ent) withdraw
  89.     # Cleanup traces on selectPath variable
  90.     #
  91.     foreach trace [trace info variable data(selectPath)] {
  92. trace remove variable data(selectPath) [lindex $trace 0] [lindex $trace 1]
  93.     }
  94.     $data(dirMenuBtn) configure -textvariable {}
  95.     # Return value to user
  96.     #
  97.     
  98.     return $Priv(selectFilePath)
  99. }
  100. # ::tk::dialog::file::chooseDir::Config --
  101. #
  102. # Configures the Tk choosedir dialog according to the argument list
  103. #
  104. proc ::tk::dialog::file::chooseDir::Config {dataName argList} {
  105.     upvar ::tk::dialog::file::$dataName data
  106.     # 0: Delete all variable that were set on data(selectPath) the
  107.     # last time the file dialog is used. The traces may cause troubles
  108.     # if the dialog is now used with a different -parent option.
  109.     #
  110.     foreach trace [trace info variable data(selectPath)] {
  111. trace remove variable data(selectPath) [lindex $trace 0] [lindex $trace 1]
  112.     }
  113.     # 1: the configuration specs
  114.     #
  115.     set specs {
  116. {-mustexist "" "" 0}
  117. {-initialdir "" "" ""}
  118. {-parent "" "" "."}
  119. {-title "" "" ""}
  120.     }
  121.     # 2: default values depending on the type of the dialog
  122.     #
  123.     if {![info exists data(selectPath)]} {
  124. # first time the dialog has been popped up
  125. set data(selectPath) [pwd]
  126.     }
  127.     # 3: parse the arguments
  128.     #
  129.     tclParseConfigSpec ::tk::dialog::file::$dataName $specs "" $argList
  130.     if {$data(-title) eq ""} {
  131. set data(-title) "[mc "Choose Directory"]"
  132.     }
  133.     
  134.     # Stub out the -multiple value for the dialog; it doesn't make sense for
  135.     # choose directory dialogs, but we have to have something there because we
  136.     # share so much code with the file dialogs.
  137.     set data(-multiple) 0
  138.     # 4: set the default directory and selection according to the -initial
  139.     #    settings
  140.     #
  141.     if {$data(-initialdir) ne ""} {
  142. # Ensure that initialdir is an absolute path name.
  143. if {[file isdirectory $data(-initialdir)]} {
  144.     set old [pwd]
  145.     cd $data(-initialdir)
  146.     set data(selectPath) [pwd]
  147.     cd $old
  148. } else {
  149.     set data(selectPath) [pwd]
  150. }
  151.     }
  152.     if {![winfo exists $data(-parent)]} {
  153. error "bad window path name "$data(-parent)""
  154.     }
  155. }
  156. # Gets called when user presses Return in the "Selection" entry or presses OK.
  157. #
  158. proc ::tk::dialog::file::chooseDir::OkCmd {w} {
  159.     upvar ::tk::dialog::file::[winfo name $w] data
  160.     # This is the brains behind selecting non-existant directories.  Here's
  161.     # the flowchart:
  162.     # 1.  If the icon list has a selection, join it with the current dir,
  163.     #     and return that value.
  164.     # 1a.  If the icon list does not have a selection ...
  165.     # 2.  If the entry is empty, do nothing.
  166.     # 3.  If the entry contains an invalid directory, then...
  167.     # 3a.   If the value is the same as last time through here, end dialog.
  168.     # 3b.   If the value is different than last time, save it and return.
  169.     # 4.  If entry contains a valid directory, then...
  170.     # 4a.   If the value is the same as the current directory, end dialog.
  171.     # 4b.   If the value is different from the current directory, change to
  172.     #       that directory.
  173.     set selection [tk::IconList_Curselection $data(icons)]
  174.     if { [llength $selection] != 0 } {
  175. set iconText [tk::IconList_Get $data(icons) [lindex $selection 0]]
  176. set iconText [file join $data(selectPath) $iconText]
  177. ::tk::dialog::file::chooseDir::Done $w $iconText
  178.     } else {
  179. set text [$data(ent) get]
  180. if { $text eq "" } {
  181.     return
  182. }
  183. set text [eval file join [file split [string trim $text]]]
  184. if { ![file exists $text] || ![file isdirectory $text] } {
  185.     # Entry contains an invalid directory.  If it's the same as the
  186.     # last time they came through here, reset the saved value and end
  187.     # the dialog.  Otherwise, save the value (so we can do this test
  188.     # next time).
  189.     if { $text eq $data(previousEntryText) } {
  190. set data(previousEntryText) ""
  191. ::tk::dialog::file::chooseDir::Done $w $text
  192.     } else {
  193. set data(previousEntryText) $text
  194.     }
  195. } else {
  196.     # Entry contains a valid directory.  If it is the same as the
  197.     # current directory, end the dialog.  Otherwise, change to that
  198.     # directory.
  199.     if { $text eq $data(selectPath) } {
  200. ::tk::dialog::file::chooseDir::Done $w $text
  201.     } else {
  202. set data(selectPath) $text
  203.     }
  204. }
  205.     }
  206.     return
  207. }
  208. proc ::tk::dialog::file::chooseDir::DblClick {w} {
  209.     upvar ::tk::dialog::file::[winfo name $w] data
  210.     set selection [tk::IconList_Curselection $data(icons)]
  211.     if { [llength $selection] != 0 } {
  212. set filenameFragment 
  213. [tk::IconList_Get $data(icons) [lindex $selection 0]]
  214. set file $data(selectPath)
  215. if {[file isdirectory $file]} {
  216.     ::tk::dialog::file::ListInvoke $w [list $filenameFragment]
  217.     return
  218. }
  219.     }
  220. }    
  221. # Gets called when user browses the IconList widget (dragging mouse, arrow
  222. # keys, etc)
  223. #
  224. proc ::tk::dialog::file::chooseDir::ListBrowse {w text} {
  225.     upvar ::tk::dialog::file::[winfo name $w] data
  226.     if {$text eq ""} {
  227. return
  228.     }
  229.     set file [::tk::dialog::file::JoinFile $data(selectPath) $text]
  230.     $data(ent) delete 0 end
  231.     $data(ent) insert 0 $file
  232. }
  233. # ::tk::dialog::file::chooseDir::Done --
  234. #
  235. # Gets called when user has input a valid filename.  Pops up a
  236. # dialog box to confirm selection when necessary. Sets the
  237. # Priv(selectFilePath) variable, which will break the "vwait"
  238. # loop in tk_chooseDirectory and return the selected filename to the
  239. # script that calls tk_getOpenFile or tk_getSaveFile
  240. #
  241. proc ::tk::dialog::file::chooseDir::Done {w {selectFilePath ""}} {
  242.     upvar ::tk::dialog::file::[winfo name $w] data
  243.     variable ::tk::Priv
  244.     if {$selectFilePath eq ""} {
  245. set selectFilePath $data(selectPath)
  246.     }
  247.     if { $data(-mustexist) } {
  248. if { ![file exists $selectFilePath] || 
  249. ![file isdir $selectFilePath] } {
  250.     return
  251. }
  252.     }
  253.     set Priv(selectFilePath) $selectFilePath
  254. }