00001 # Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00002 # 00003 # This file is free software; as a special exception the author gives 00004 # unlimited permission to copy and/or distribute it, with or without 00005 # modifications, as long as this notice is preserved. 00006 # 00007 # This program is distributed in the hope that it will be useful, but 00008 # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 00009 # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00010 00011 ## ---------------------------------------------------------------------------- 00012 ## FileSelector - dialog to select files and directories. 00013 ## This class implements an improved file selection dialog using the classes 00014 ## VisDirectory and VisFile. 00015 ## 00016 ## \author Michael Daum 00017 ## 00018 ## $Id: FileSelector.tcl,v 1.12 2004/02/25 14:42:08 micha Exp $ 00019 ## ---------------------------------------------------------------------------- 00020 class FileSelector { 00021 inherit iwidgets::Shell 00022 00023 # -- variables ------------------------------------------------------------- 00024 public variable showHidden 0 00025 public variable filter "*" 00026 public variable directory "" 00027 public variable mode "multi" 00028 public variable selection "" 00029 00030 private variable _history {} 00031 private variable _historyIndex 0 00032 private variable _useHistory 1 00033 private variable _currentFilter "*" 00034 00035 # -- methods --------------------------------------------------------------- 00036 public method show {{dirName ""}}; ## \type TclString 00037 public method activate {args}; ## \type TclList 00038 00039 constructor {args} {}; ## \type TclList 00040 00041 private method _okCommand {} 00042 private method _cancelCommand {} 00043 private method _directoryCommand {} 00044 private method _homeCommand {} 00045 private method _upCommand {} 00046 private method _reloadCommand {} 00047 private method _selectionCommand {} 00048 private method _chdirHandle {} 00049 private method _backwardHistory {} 00050 private method _forwardHistory {} 00051 private method _updateHistory {} 00052 private method _selectHandle {} 00053 private method _newCommand {} 00054 private method _deleteCommand {} 00055 }; 00056 00057 ## ---------------------------------------------------------------------------- 00058 ## constructor 00059 ## ---------------------------------------------------------------------------- 00060 body FileSelector::constructor {args} { 00061 00062 # the filearea 00063 itk_component add visDirectory { 00064 VisDirectory $itk_interior.visDirectory \ 00065 -hscrollmode dynamic \ 00066 -vscrollmode none \ 00067 -sbwidth 12 \ 00068 -autoresize 0 \ 00069 -chdircommand [code $this _chdirHandle] \ 00070 -selectioncommand [code $this _selectHandle] \ 00071 -finishcommand [code $this _okCommand] 00072 } {} 00073 00074 # the toolbar 00075 itk_component add toolbar { 00076 iwidgets::toolbar $itk_interior.toolbar \ 00077 -balloonfont {-adobe-helvetica-medium-r-normal--12-*-*-*-*-*-*-*} \ 00078 -balloonbackground lightyellow 00079 } {} 00080 00081 $itk_component(toolbar) add FlatButton backward \ 00082 -image [YadaImages::get backward] \ 00083 -relief flat \ 00084 -balloonstr "back" \ 00085 -command [code $this _backwardHistory] \ 00086 -state disabled 00087 00088 $itk_component(toolbar) add FlatButton forward \ 00089 -image [YadaImages::get forward] \ 00090 -relief flat \ 00091 -balloonstr "forward" \ 00092 -command [code $this _forwardHistory] \ 00093 -state disabled 00094 00095 00096 $itk_component(toolbar) add FlatButton upward \ 00097 -image [YadaImages::get up] \ 00098 -relief flat \ 00099 -balloonstr "upwards" \ 00100 -command [code $this _upCommand] 00101 00102 $itk_component(toolbar) add FlatButton home \ 00103 -image [YadaImages::get home] \ 00104 -relief flat \ 00105 -command [code $this _homeCommand] \ 00106 -balloonstr "go home" 00107 00108 $itk_component(toolbar) add FlatButton reload \ 00109 -image [YadaImages::get reload] \ 00110 -relief flat \ 00111 -balloonstr "reload" \ 00112 -command [code $this _reloadCommand] 00113 00114 $itk_component(toolbar) add FlatButton new \ 00115 -image [YadaImages::get lamp] \ 00116 -relief flat \ 00117 -balloonstr "new" \ 00118 -command [code $this _newCommand] 00119 00120 $itk_component(toolbar) add FlatButton delete \ 00121 -image [YadaImages::get delete] \ 00122 -relief flat \ 00123 -balloonstr "delete" \ 00124 -command [code $this _deleteCommand] 00125 00126 itk_component add directory { 00127 iwidgets::combobox $itk_component(toolbar).directory \ 00128 -textvariable [scope directory] \ 00129 -editable 0 \ 00130 -selectioncommand [code $this _directoryCommand] 00131 } {} 00132 00133 itk_component add ff { 00134 frame $itk_interior.ff 00135 } 00136 00137 itk_component add selection { 00138 iwidgets::combobox $itk_component(ff).selection \ 00139 -labeltext "Selection:" \ 00140 -textvariable [scope selection] \ 00141 -selectioncommand [code $this _selectionCommand] \ 00142 -completion false 00143 } {} 00144 00145 00146 itk_component add filter { 00147 iwidgets::combobox $itk_component(ff).filter \ 00148 -labeltext "Filter:" \ 00149 -textvariable [scope _currentFilter] \ 00150 -selectioncommand [code $this show] \ 00151 -completion false 00152 } { } 00153 00154 itk_component add showHidden { 00155 checkbutton $itk_component(ff).showHidden \ 00156 -text "Show hidden" \ 00157 -highlightthickness 0 \ 00158 -variable [scope showHidden] \ 00159 -command [code $this show] 00160 } 00161 00162 00163 itk_component add okButton { 00164 button $itk_component(ff).okButton \ 00165 -text "Ok" \ 00166 -command [code $this _okCommand] 00167 } 00168 00169 itk_component add cancelButton { 00170 button $itk_component(ff).cancelButton \ 00171 -text "Cancel" \ 00172 -command [code $this _cancelCommand] 00173 } 00174 00175 itk_component add message { 00176 iwidgets::messagedialog $itk_interior.message \ 00177 -title "Yada - Caution" \ 00178 -modality application \ 00179 -master $itk_component(hull) 00180 } { } 00181 $itk_component(message) buttonconfigure OK -text "Yes" 00182 $itk_component(message) buttonconfigure Cancel -text "No" 00183 $itk_component(message) hide Apply 00184 $itk_component(message) hide Help 00185 00186 # packing 00187 pack $itk_component(toolbar) -side top -fill x -pady 5 00188 pack $itk_component(directory) -side left -fill x -padx 5 -expand 1 00189 pack $itk_component(visDirectory) -side top -fill both -expand 1 -padx 5 -pady 5 00190 pack $itk_component(ff) -side top -fill x -padx 5 -pady 5 00191 00192 grid columnconfigure $itk_component(ff) 0 -weight 1 00193 grid $itk_component(selection) -sticky ew -row 0 -column 0 -columnspan 2 -pady 5 -padx 5 00194 grid $itk_component(filter) -sticky ew -row 1 -column 0 -pady 5 -padx 5 00195 grid $itk_component(showHidden) -sticky ew -row 1 -column 1 -pady 5 -padx 5 00196 00197 grid $itk_component(okButton) -sticky ew -row 0 -column 2 -pady 5 -padx 5 00198 grid $itk_component(cancelButton) -sticky ew -row 1 -column 2 -pady 5 -padx 5 00199 00200 iwidgets::Labeledwidget::alignlabels \ 00201 $itk_component(selection) \ 00202 $itk_component(filter) 00203 00204 # binding 00205 bind [$itk_component(filter) component entry] <Return> [code $this show] 00206 bind [$itk_component(selection) component entry] <Return> [code $this show] 00207 00208 configure -modality application -master . 00209 00210 eval itk_initialize $args 00211 } 00212 00213 ## ---------------------------------------------------------------------------- 00214 ## _okCommand 00215 ## ---------------------------------------------------------------------------- 00216 body FileSelector::_okCommand {} { 00217 00218 set result "" 00219 set pwd [pwd] 00220 foreach item $selection { 00221 lappend result [file join $pwd $item] 00222 } 00223 00224 # update the selection combobox 00225 set selection $result 00226 namespace inscope ::iwidgets::Combobox \ 00227 [list $itk_component(selection) _addToList] 00228 00229 deactivate 00230 } 00231 00232 ## ---------------------------------------------------------------------------- 00233 ## _cancelCommand 00234 ## ---------------------------------------------------------------------------- 00235 body FileSelector::_cancelCommand {} { 00236 $itk_component(visDirectory) clearSelection 00237 00238 deactivate 00239 } 00240 00241 ## ---------------------------------------------------------------------------- 00242 ## _directoryCommand 00243 ## ---------------------------------------------------------------------------- 00244 body FileSelector::_directoryCommand {} { 00245 show $directory 00246 } 00247 00248 ## ---------------------------------------------------------------------------- 00249 ## _homeCommand 00250 ## ---------------------------------------------------------------------------- 00251 body FileSelector::_homeCommand {} { 00252 show ~ 00253 } 00254 00255 ## ---------------------------------------------------------------------------- 00256 ## _chdirHandle 00257 ## ---------------------------------------------------------------------------- 00258 body FileSelector::_chdirHandle {} { 00259 00260 set directory [pwd] 00261 00262 # update upward button 00263 if {$directory == "/"} { 00264 $itk_component(toolbar) itemconfigure upward \ 00265 -state disabled 00266 } else { 00267 $itk_component(toolbar) itemconfigure upward \ 00268 -state normal 00269 } 00270 00271 # update history 00272 _updateHistory 00273 00274 # update the filter component 00275 namespace inscope ::iwidgets::Combobox \ 00276 [list $itk_component(filter) _addToList] 00277 00278 # update the directory hierarchy 00279 $itk_component(directory) clear 00280 $itk_component(directory) selection clear 0 end 00281 set prefix "" 00282 foreach part [file split $directory] { 00283 set prefix [file join $prefix $part] 00284 $itk_component(directory) insert list 0 $prefix 00285 } 00286 } 00287 00288 ## ---------------------------------------------------------------------------- 00289 ## _reloadCommand 00290 ## ---------------------------------------------------------------------------- 00291 body FileSelector::_reloadCommand {} { 00292 set _useHistory 0 00293 show 00294 set _useHistory 1 00295 } 00296 00297 ## ---------------------------------------------------------------------------- 00298 ## _upCommand 00299 ## ---------------------------------------------------------------------------- 00300 body FileSelector::_upCommand {} { 00301 cd .. 00302 show [pwd] 00303 } 00304 00305 ## ---------------------------------------------------------------------------- 00306 ## _updateHistory 00307 ## ---------------------------------------------------------------------------- 00308 body FileSelector::_updateHistory {} { 00309 if {!$_useHistory} { 00310 return 00311 } 00312 00313 if {$directory == "."} { 00314 return 00315 } 00316 00317 # truncate history 00318 set endIndex [expr [llength $_history] -1] 00319 if {$_historyIndex < $endIndex} { 00320 set _history [lreplace $_history [expr $_historyIndex +1] end] 00321 set endIndex $_historyIndex 00322 } 00323 00324 # append history, omit double entries 00325 set lastDir [lindex $_history end] 00326 if {$lastDir != $directory} { 00327 lappend _history $directory 00328 incr endIndex 00329 } 00330 00331 # set the current history index 00332 set _historyIndex [expr [llength $_history] -1] 00333 00334 # update the balloons 00335 if {$_historyIndex > 0} { 00336 set prevDir [lindex $_history [expr $_historyIndex -1]] 00337 $itk_component(toolbar) itemconfigure backward \ 00338 -balloonstr "back to $prevDir" \ 00339 -state normal 00340 } else { 00341 $itk_component(toolbar) itemconfigure backward \ 00342 -balloonstr "back" \ 00343 -state disabled 00344 } 00345 $itk_component(toolbar) itemconfigure forward \ 00346 -balloonstr "forward" \ 00347 -state disabled 00348 00349 } 00350 00351 ## ---------------------------------------------------------------------------- 00352 ## _backwardHistory 00353 ## ---------------------------------------------------------------------------- 00354 body FileSelector::_backwardHistory {} { 00355 if {$_historyIndex == 0} { 00356 return 00357 } 00358 00359 # show previous directory 00360 incr _historyIndex -1 00361 set _useHistory 0 00362 show [lindex $_history $_historyIndex] 00363 set _useHistory 1 00364 00365 # udpdate the balloons of the bach and forward buttons 00366 if {$_historyIndex == 0} { 00367 $itk_component(toolbar) itemconfigure backward \ 00368 -balloonstr "back" \ 00369 -state disabled 00370 } else { 00371 set prevDir [lindex $_history [expr $_historyIndex -1]] 00372 $itk_component(toolbar) itemconfigure backward \ 00373 -balloonstr "back to $prevDir" \ 00374 -state normal 00375 } 00376 set nextDir [lindex $_history [expr $_historyIndex +1]] 00377 $itk_component(toolbar) itemconfigure forward \ 00378 -balloonstr "forward to $nextDir" \ 00379 -state normal 00380 00381 } 00382 00383 ## ---------------------------------------------------------------------------- 00384 ## _forwardHistory 00385 ## ---------------------------------------------------------------------------- 00386 body FileSelector::_forwardHistory {} { 00387 set endIndex [expr [llength $_history] -1] 00388 if {$_historyIndex >= $endIndex} { 00389 return 00390 } 00391 00392 # show next directory 00393 incr _historyIndex 00394 set _useHistory 0 00395 show [lindex $_history $_historyIndex] 00396 set _useHistory 1 00397 00398 # udpdate the balloons of the bach and forward buttons 00399 if {$_historyIndex == $endIndex} { 00400 $itk_component(toolbar) itemconfigure forward \ 00401 -balloonstr "forward" \ 00402 -state disabled 00403 } else { 00404 set nextDir [lindex $_history [expr $_historyIndex +1]] 00405 $itk_component(toolbar) itemconfigure forward \ 00406 -balloonstr "forward to $nextDir" \ 00407 -state normal 00408 } 00409 set prevDir [lindex $_history [expr $_historyIndex -1]] 00410 $itk_component(toolbar) itemconfigure backward \ 00411 -balloonstr "back to $prevDir" \ 00412 -state normal 00413 00414 } 00415 00416 ## ---------------------------------------------------------------------------- 00417 ## show 00418 ## ---------------------------------------------------------------------------- 00419 body FileSelector::show {{dirName ""}} { 00420 $itk_component(visDirectory) setFilter $_currentFilter 00421 $itk_component(visDirectory) setShowHidden $showHidden 00422 $itk_component(visDirectory) setMode $mode 00423 00424 if {$dirName != ""} { 00425 set directory $dirName 00426 } 00427 00428 if {$directory == ""} { 00429 set directory [pwd] 00430 } 00431 00432 $itk_component(visDirectory) show $directory 00433 } 00434 00435 ## ---------------------------------------------------------------------------- 00436 ## _selectHandle 00437 ## ---------------------------------------------------------------------------- 00438 body FileSelector::_selectHandle {} { 00439 set selection [$itk_component(visDirectory) getSelection] 00440 if {$selection == ""} { 00441 $itk_component(toolbar) itemconfigure delete \ 00442 -state disabled 00443 } else { 00444 $itk_component(toolbar) itemconfigure delete \ 00445 -state normal 00446 } 00447 } 00448 00449 ## ---------------------------------------------------------------------------- 00450 ## activate 00451 ## ---------------------------------------------------------------------------- 00452 body FileSelector::activate {args} { 00453 eval configure $args 00454 set _historyIndex 0 00455 set _history "" 00456 _selectionCommand 00457 center [cget -master] 00458 Shell::activate 00459 return "$selection" 00460 } 00461 00462 ## ---------------------------------------------------------------------------- 00463 ## _selectionCommand 00464 ## ---------------------------------------------------------------------------- 00465 body FileSelector::_selectionCommand {} { 00466 set oldSelection "$selection" 00467 set selItem [lindex $selection 0] 00468 show [file dirname $selItem] 00469 $itk_component(visDirectory) select "$oldSelection" 00470 } 00471 00472 ## ---------------------------------------------------------------------------- 00473 ## _newCommand 00474 ## ---------------------------------------------------------------------------- 00475 body FileSelector::_newCommand {} { 00476 $itk_component(visDirectory) new 00477 } 00478 00479 ## ---------------------------------------------------------------------------- 00480 ## _deleteCommand 00481 ## ---------------------------------------------------------------------------- 00482 body FileSelector::_deleteCommand {} { 00483 if {$selection == ""} { 00484 return 00485 } 00486 00487 $itk_component(message) configure -text \ 00488 "Are you sure that you want to delete [llength $selection] file(s)?" 00489 00490 $itk_component(message) center [$itk_component(message) cget -master] 00491 00492 if {![$itk_component(message) activate]} { 00493 return 00494 } 00495 00496 eval file delete -- $selection 00497 00498 show [pwd] 00499 } 00500 00501 ## ---------------------------------------------------------------------------- 00502 ## -filter 00503 ## ---------------------------------------------------------------------------- 00504 configbody FileSelector::filter { 00505 $itk_component(filter) delete list 0 end 00506 $itk_component(filter) delete entry 0 end 00507 foreach item $itk_option(-filter) { 00508 set _currentFilter $item 00509 namespace inscope ::iwidgets::Combobox \ 00510 [list $itk_component(filter) _addToList] 00511 } 00512 set _currentFilter [lindex $itk_option(-filter) 0] 00513 }