EFileBox.tcl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
  2. #
  3. # $Id: EFileBox.tcl,v 1.5 2004/03/28 02:44:57 hobbs Exp $
  4. #
  5. # EFileBox.tcl --
  6. #
  7. # Implements the Extended File Selection Box widget.
  8. #
  9. # Copyright (c) 1993-1999 Ioi Kim Lam.
  10. # Copyright (c) 2000-2001 Tix Project Group.
  11. # Copyright (c) 2004 ActiveState
  12. #
  13. # See the file "license.terms" for information on usage and redistribution
  14. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  15. #
  16. #
  17. # ToDo
  18. # (1) If user has entered an invalid directory, give an error dialog
  19. #
  20. tixWidgetClass tixExFileSelectBox {
  21. -classname TixExFileSelectBox
  22. -superclass tixPrimitive
  23. -method {
  24. filter invoke
  25. }
  26. -flag {
  27. -browsecmd -command -dialog -dir -dircmd -directory
  28. -disablecallback -filetypes -pattern -selection -showhidden -value
  29. }
  30. -forcecall {
  31. -filetypes
  32. }
  33. -configspec {
  34. {-browsecmd browseCmd BrowseCmd ""}
  35. {-command command Command ""}
  36. {-dialog dialog Dialog ""}
  37. {-dircmd dirCmd DirCmd ""}
  38. {-directory directory Directory ""}
  39. {-disablecallback disableCallback DisableCallback 0 tixVerifyBoolean}
  40. {-filetypes fileTypes FileTypes ""}
  41. {-pattern pattern Pattern *}
  42. {-showhidden showHidden ShowHidden 0 tixVerifyBoolean}
  43. {-value value Value ""}
  44. }
  45. -alias {
  46. {-dir -directory}
  47. {-selection -value}
  48. }
  49. -default {
  50. {*dir.label {Directories:}}
  51. {*dir.editable true}
  52. {*dir.history true}
  53. {*dir*listbox.height 5}
  54. {*file.label Files:}
  55. {*file.editable true}
  56. {*file.history false}
  57. {*file*listbox.height 5}
  58. {*types.label {List Files of Type:}}
  59. {*types*listbox.height 3}
  60. {*TixComboBox.labelSide top}
  61. {*TixComboBox*Label.anchor w}
  62. {*dir.label.underline 0}
  63. {*file.label.underline 0}
  64. {*types.label.underline 14}
  65. {*TixComboBox.anchor e}
  66. {*TixHList.height 7}
  67. {*filelist*listbox.height 7}
  68. {*hidden.wrapLength 3c}
  69. {*hidden.justify left}
  70. }
  71. }
  72. proc tixExFileSelectBox:InitWidgetRec {w} {
  73. upvar #0 $w data
  74. global env
  75. tixChainMethod $w InitWidgetRec
  76. if {$data(-directory) eq ""} {
  77. set data(-directory) [pwd]
  78. }
  79. set data(oldDir) ""
  80. set data(flag) 0
  81. }
  82. #----------------------------------------------------------------------
  83. # Construct widget
  84. #----------------------------------------------------------------------
  85. proc tixExFileSelectBox:ConstructWidget {w} {
  86. upvar #0 $w data
  87. tixChainMethod $w ConstructWidget
  88. # listbox frame
  89. set lf [frame $w.lf]
  90. # The pane that contains the two listboxes
  91. #
  92. set pane [tixPanedWindow $lf.pane -orientation horizontal]
  93. set dpane [$pane add 1 -size 160]
  94. set fpane [$pane add 2 -size 160]
  95. $dpane config -relief flat
  96. $fpane config -relief flat
  97. # The File List Pane
  98. #
  99. set data(w:file) [tixComboBox $fpane.file\
  100. -command [list tixExFileSelectBox:Cmd-FileCombo $w]\
  101. -prunehistory true \
  102. -options {
  103. label.anchor w
  104. }]
  105. set data(w:filelist) \
  106. [tixScrolledListBox $fpane.filelist \
  107. -command [list tixExFileSelectBox:Cmd-FileList $w 1] \
  108. -browsecmd [list tixExFileSelectBox:Cmd-FileList $w 0]]
  109. pack $data(w:file) -padx 8 -pady 4 -side top -fill x
  110. pack $data(w:filelist) -padx 8 -pady 4 -side top -fill both -expand yes
  111. # The Directory Pane
  112. #
  113. set data(w:dir) [tixComboBox $dpane.dir \
  114. -command [list tixExFileSelectBox:Cmd-DirCombo $w]\
  115. -prunehistory true \
  116. -options {
  117. label.anchor w
  118. }]
  119. set data(w:dirlist) \
  120. [tixDirList $dpane.dirlist \
  121. -command [list tixExFileSelectBox:Cmd-DirList $w]\
  122. -browsecmd [list tixExFileSelectBox:Browse-DirList $w]]
  123. pack $data(w:dir) -padx 8 -pady 4 -side top -fill x
  124. pack $data(w:dirlist) -padx 8 -pady 4 -side top -fill both -expand yes
  125. # The file types listbox
  126. #
  127. set data(w:types) [tixComboBox $lf.types\
  128. -command [list tixExFileSelectBox:Cmd-TypeCombo $w]\
  129. -options {
  130. label.anchor w
  131. }]
  132. pack $data(w:types) -padx 12 -pady 4 -side bottom -fill x -anchor w
  133. pack $pane -side top -padx 4 -pady 4 -expand yes -fill both
  134. # Buttons to the right
  135. #
  136. set bf [frame $w.bf]
  137. set data(w:ok) [button $bf.ok -text Ok -width 6 \
  138. -underline 0 -command [list tixExFileSelectBox:Ok $w]]
  139. set data(w:cancel) [button $bf.cancel -text Cancel -width 6 \
  140. -underline 0 -command [list tixExFileSelectBox:Cancel $w]]
  141. set data(w:hidden) [checkbutton $bf.hidden -text "Show Hidden Files"\
  142. -underline 0\
  143. -variable [format %s(-showhidden) $w] -onvalue 1 -offvalue 0\
  144. -command [list tixExFileSelectBox:SetShowHidden $w]]
  145. pack $data(w:ok) $data(w:cancel) $data(w:hidden)\
  146. -side top -fill x -padx 6 -pady 3
  147. pack $bf -side right -fill y -pady 6
  148. pack $lf -side left -expand yes -fill both
  149. tixDoWhenMapped $w [list tixExFileSelectBox:Map $w]
  150. if {$data(-filetypes) == ""} {
  151. $data(w:types) config -state disabled
  152. }
  153. }
  154. #----------------------------------------------------------------------
  155. # Configuration
  156. #----------------------------------------------------------------------
  157. proc tixExFileSelectBox:config-showhidden {w value} {
  158. upvar #0 $w data
  159. set data(-showhidden) $value
  160. tixExFileSelectBox:SetShowHidden $w
  161. }
  162. # Update both DirList and {file list and dir combo}
  163. #
  164. proc tixExFileSelectBox:config-directory {w value} {
  165. upvar #0 $w data
  166. set data(-directory) [tixFSNormalize $value]
  167. tixSetSilent $data(w:dirlist) $data(-directory)
  168. tixSetSilent $data(w:dir) $data(-directory)
  169. tixWidgetDoWhenIdle tixExFileSelectBox:LoadFiles $w reload
  170. return $data(-directory)
  171. }
  172. proc tixExFileSelectBox:config-filetypes {w value} {
  173. upvar #0 $w data
  174. $data(w:types) subwidget listbox delete 0 end
  175. foreach name [array names data] {
  176. if {[string match type,* $name]} {
  177. catch {unset data($name)}
  178. }
  179. }
  180. if {$value == ""} {
  181. $data(w:types) config -state disabled
  182. } else {
  183. $data(w:types) config -state normal
  184. foreach type $value {
  185. $data(w:types) insert end [lindex $type 1]
  186. set data(type,[lindex $type 1]) [lindex $type 0]
  187. }
  188. tixSetSilent $data(w:types) ""
  189. }
  190. }
  191. #----------------------------------------------------------------------
  192. # MISC Methods
  193. #----------------------------------------------------------------------
  194. proc tixExFileSelectBox:SetShowHidden {w} {
  195. upvar #0 $w data
  196. $data(w:dirlist) config -showhidden $data(-showhidden)
  197. tixWidgetDoWhenIdle tixExFileSelectBox:LoadFiles $w reload
  198. }
  199. # User activates the dir combobox
  200. #
  201. #
  202. proc tixExFileSelectBox:Cmd-DirCombo {w args} {
  203. upvar #0 $w data
  204. set dir [tixEvent flag V]
  205. set dir [tixFSExternal $dir]
  206. if {![file isdirectory $dir]} {
  207. return
  208. }
  209. set dir [tixFSNormalize $dir]
  210. $data(w:dirlist) config -value $dir
  211. set data(-directory) $dir
  212. }
  213. # User activates the dir list
  214. #
  215. #
  216. proc tixExFileSelectBox:Cmd-DirList {w args} {
  217. upvar #0 $w data
  218. set dir $data(-directory)
  219. catch {set dir [tixEvent flag V]}
  220. set dir [tixFSNormalize [tixFSExternal $dir]]
  221. tixSetSilent $data(w:dir) $dir
  222. set data(-directory) $dir
  223. tixWidgetDoWhenIdle tixExFileSelectBox:LoadFiles $w noreload
  224. }
  225. # User activates the dir list
  226. #
  227. #
  228. proc tixExFileSelectBox:Browse-DirList {w args} {
  229. upvar #0 $w data
  230. set dir [tixEvent flag V]
  231. set dir [tixFSNormalize [tixFSExternal $dir]]
  232. tixExFileSelectBox:Cmd-DirList $w $dir
  233. }
  234. proc tixExFileSelectBox:IsPattern {w string} {
  235. return [regexp "\[\[\\\{\\*\\?\]" $string]
  236. }
  237. proc tixExFileSelectBox:Cmd-FileCombo {w value} {
  238. upvar #0 $w data
  239. if {[tixEvent type] eq "<Return>"} {
  240. tixExFileSelectBox:Ok $w
  241. }
  242. }
  243. proc tixExFileSelectBox:Ok {w} {
  244. upvar #0 $w data
  245. set value [string trim [$data(w:file) subwidget entry get]]
  246. if {$value == ""} {
  247. set value $data(-pattern)
  248. }
  249. tixSetSilent $data(w:file) $value
  250. if {[tixExFileSelectBox:IsPattern $w $value]} {
  251. set data(-pattern) $value
  252. tixWidgetDoWhenIdle tixExFileSelectBox:LoadFiles $w reload
  253. } else {
  254. # ensure absolute path
  255. set value [file join $data(-directory) $value]; # native
  256. set data(-value) [tixFSNativeNorm $value]
  257. tixExFileSelectBox:Invoke $w
  258. }
  259. }
  260. proc tixExFileSelectBox:Cancel {w} {
  261. upvar #0 $w data
  262. if {$data(-dialog) != ""} {
  263. eval $data(-dialog) popdown
  264. }
  265. }
  266. proc tixExFileSelectBox:Invoke {w} {
  267. upvar #0 $w data
  268. # Save some old history
  269. #
  270. $data(w:dir) addhistory [$data(w:dir) cget -value]
  271. $data(w:file) addhistory $data(-pattern)
  272. $data(w:file) addhistory $data(-value)
  273. if {$data(-dialog) != ""} {
  274. eval $data(-dialog) popdown
  275. }
  276. if {$data(-command) != "" && !$data(-disablecallback)} {
  277. set bind(specs) "%V"
  278. set bind(%V) $data(-value)
  279. tixEvalCmdBinding $w $data(-command) bind $data(-value)
  280. }
  281. }
  282. proc tixExFileSelectBox:Cmd-FileList {w invoke args} {
  283. upvar #0 $w data
  284. set index [lindex [$data(w:filelist) subwidget listbox curselection] 0]
  285. if {$index == ""} {
  286. set index 0
  287. }
  288. set file [$data(w:filelist) subwidget listbox get $index]
  289. tixSetSilent $data(w:file) $file
  290. set value [file join $data(-directory) $file]
  291. set data(-value) [tixFSNativeNorm $value]
  292. if {$invoke == 1} {
  293. tixExFileSelectBox:Invoke $w
  294. } elseif {$data(-browsecmd) != ""} {
  295. tixEvalCmdBinding $w $data(-browsecmd) "" $data(-value)
  296. }
  297. }
  298. proc tixExFileSelectBox:Cmd-TypeCombo {w args} {
  299. upvar #0 $w data
  300. set value [tixEvent flag V]
  301. if {[info exists data(type,$value)]} {
  302. set data(-pattern) $data(type,$value)
  303. tixSetSilent $data(w:file) $data(-pattern)
  304. tixWidgetDoWhenIdle tixExFileSelectBox:LoadFiles $w reload
  305. }
  306. }
  307. proc tixExFileSelectBox:LoadFiles {w flag} {
  308. upvar #0 $w data
  309. if {$flag ne "reload" && $data(-directory) eq $data(oldDir)} {
  310. return
  311. }
  312. if {![winfo ismapped [winfo toplevel $w]]} {
  313. tixDoWhenMapped [winfo toplevel $w] \
  314. [list tixExFileSelectBox:LoadFiles $w $flag]
  315. return
  316. }
  317. set listbox [$data(w:filelist) subwidget listbox]
  318. $listbox delete 0 end
  319. set data(-value) ""
  320. tixBusy $w on [$data(w:dirlist) subwidget hlist]
  321. # wrap in a catch so you can't get stuck in a Busy state
  322. if {[catch {
  323. foreach name [tixFSListDir $data(-directory) 0 1 0 \
  324. $data(-showhidden) $data(-pattern)] {
  325. $listbox insert end $name
  326. }
  327. if {$data(oldDir) ne $data(-directory)} {
  328. # Otherwise if the user has already selected a file and then
  329. # presses "show hidden", the selection won't be wiped out.
  330. tixSetSilent $data(w:file) $data(-pattern)
  331. }
  332. } err]} {
  333. tixDebug "tixExFileSelectBox:LoadFiles error for $w\n$err"
  334. }
  335. set data(oldDir) $data(-directory)
  336. tixWidgetDoWhenIdle tixBusy $w off [$data(w:dirlist) subwidget hlist]
  337. }
  338. #
  339. # Called when thd listbox is first mapped
  340. proc tixExFileSelectBox:Map {w} {
  341. if {![winfo exists $w]} {
  342. return
  343. }
  344. upvar #0 $w data
  345. set bind(specs) "%V"
  346. set bind(%V) $data(-value)
  347. tixEvalCmdBinding $w bind \
  348. [list tixExFileSelectBox:Cmd-DirList $w] $data(-directory)
  349. }
  350. #----------------------------------------------------------------------
  351. # Public commands
  352. #
  353. #----------------------------------------------------------------------
  354. proc tixExFileSelectBox:invoke {w} {
  355. tixExFileSelectBox:Invoke $w
  356. }
  357. proc tixExFileSelectBox:filter {w} {
  358. tixExFileSelectBox:LoadFiles $w reload
  359. }