123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- # -*- mode: TCL; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
- #
- # $Id: FileBox.tcl,v 1.5 2004/03/28 02:44:57 hobbs Exp $
- #
- # FileBox.tcl --
- #
- # Implements the File Selection Box widget.
- #
- # Copyright (c) 1993-1999 Ioi Kim Lam.
- # Copyright (c) 2000-2001 Tix Project Group.
- # Copyright (c) 2004 ActiveState
- #
- # See the file "license.terms" for information on usage and redistribution
- # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- #
- # ToDo
- # (1) If user has entered an invalid directory, give an error dialog
- #
- tixWidgetClass tixFileSelectBox {
- -superclass tixPrimitive
- -classname TixFileSelectBox
- -method {
- filter invoke
- }
- -flag {
- -browsecmd -command -dir -directory -disablecallback
- -grab -pattern -selection -value
- }
- -configspec {
- {-browsecmd browseCmd BrowseCmd ""}
- {-command command Command ""}
- {-directory directory Directory ""}
- {-disablecallback disableCallback DisableCallback 0 tixVerifyBoolean}
- {-grab grab Grab global}
- {-pattern pattern Pattern *}
- {-value value Value ""}
- }
- -alias {
- {-selection -value}
- {-dir -directory}
- }
- -forcecall {
- -value
- }
- -default {
- {.relief raised}
- {*filelist*Listbox.takeFocus true}
- {.borderWidth 1}
- {*Label.anchor w}
- {*Label.borderWidth 0}
- {*TixComboBox*scrollbar auto}
- {*TixComboBox*Label.anchor w}
- {*TixScrolledListBox.scrollbar auto}
- {*Listbox.exportSelection false}
- {*directory*Label.text "Directories:"}
- {*directory*Label.underline 0}
- {*file*Label.text "Files:"}
- {*file*Label.underline 2}
- {*filter.label "Filter:"}
- {*filter*label.underline 3}
- {*filter.labelSide top}
- {*selection.label "Selection:"}
- {*selection*label.underline 0}
- {*selection.labelSide top}
- }
- }
- proc tixFileSelectBox:InitWidgetRec {w} {
- upvar #0 $w data
- global env
- tixChainMethod $w InitWidgetRec
- if {$data(-directory) eq ""} {
- set data(-directory) [pwd]
- }
- if {$data(-pattern) eq ""} {
- set data(-pattern) "*"
- }
- tixFileSelectBox:SetPat $w $data(-pattern)
- tixFileSelectBox:SetDir $w [tixFSNormalize $data(-directory)]
- set data(flag) 0
- set data(fakeDir) 0
- }
- #----------------------------------------------------------------------
- # Construct widget
- #----------------------------------------------------------------------
- proc tixFileSelectBox:ConstructWidget {w} {
- upvar #0 $w data
- tixChainMethod $w ConstructWidget
- set frame1 [tixFileSelectBox:CreateFrame1 $w]
- set frame2 [tixFileSelectBox:CreateFrame2 $w]
- set frame3 [tixFileSelectBox:CreateFrame3 $w]
- pack $frame1 -in $w -side top -fill x
- pack $frame3 -in $w -side bottom -fill x
- pack $frame2 -in $w -side top -fill both -expand yes
- }
- proc tixFileSelectBox:CreateFrame1 {w} {
- upvar #0 $w data
- frame $w.f1 -border 10
- tixComboBox $w.f1.filter -editable 1\
- -command [list $w filter] -anchor e \
- -options {
- slistbox.scrollbar auto
- listbox.height 5
- label.anchor w
- }
- set data(w:filter) $w.f1.filter
- pack $data(w:filter) -side top -expand yes -fill both
- return $w.f1
- }
- proc tixFileSelectBox:CreateFrame2 {w} {
- upvar #0 $w data
- tixPanedWindow $w.f2 -orientation horizontal
- # THE LEFT FRAME
- #-----------------------
- set dir [$w.f2 add directory -size 120]
- $dir config -relief flat
- label $dir.lab
- set data(w:dirlist) [tixScrolledListBox $dir.dirlist\
- -scrollbar auto\
- -options {listbox.width 4 listbox.height 6}]
- pack $dir.lab -side top -fill x -padx 10
- pack $data(w:dirlist) -side bottom -expand yes -fill both -padx 10
- # THE RIGHT FRAME
- #-----------------------
- set file [$w.f2 add file -size 160]
- $file config -relief flat
- label $file.lab
- set data(w:filelist) [tixScrolledListBox $file.filelist \
- -scrollbar auto\
- -options {listbox.width 4 listbox.height 6}]
- pack $file.lab -side top -fill x -padx 10
- pack $data(w:filelist) -side bottom -expand yes -fill both -padx 10
- return $w.f2
- }
- proc tixFileSelectBox:CreateFrame3 {w} {
- upvar #0 $w data
- frame $w.f3 -border 10
- tixComboBox $w.f3.selection -editable 1\
- -command [list tixFileSelectBox:SelInvoke $w] \
- -anchor e \
- -options {
- slistbox.scrollbar auto
- listbox.height 5
- label.anchor w
- }
- set data(w:selection) $w.f3.selection
- pack $data(w:selection) -side top -fill both
- return $w.f3
- }
- proc tixFileSelectBox:SelInvoke {w args} {
- upvar #0 $w data
- set event [tixEvent type]
- if {$event ne "<FocusOut>" && $event ne "<Tab>"} {
- $w invoke
- }
- }
- proc tixFileSelectBox:SetValue {w value} {
- upvar #0 $w data
- set data(i-value) $value
- set data(-value) [tixFSNative $value]
- }
- proc tixFileSelectBox:SetDir {w value} {
- upvar #0 $w data
- set data(i-directory) $value
- set data(-directory) [tixFSNative $value]
- }
- proc tixFileSelectBox:SetPat {w value} {
- upvar #0 $w data
- set data(i-pattern) $value
- set data(-pattern) [tixFSNative $value]
- }
- #----------------------------------------------------------------------
- # BINDINGS
- #----------------------------------------------------------------------
- proc tixFileSelectBox:SetBindings {w} {
- upvar #0 $w data
- tixChainMethod $w SetBindings
- tixDoWhenMapped $w [list tixFileSelectBox:FirstMapped $w]
- $data(w:dirlist) config \
- -browsecmd [list tixFileSelectBox:SelectDir $w] \
- -command [list tixFileSelectBox:InvokeDir $w]
- $data(w:filelist) config \
- -browsecmd [list tixFileSelectBox:SelectFile $w] \
- -command [list tixFileSelectBox:InvokeFile $w]
- }
- #----------------------------------------------------------------------
- # CONFIG OPTIONS
- #----------------------------------------------------------------------
- proc tixFileSelectBox:config-directory {w value} {
- upvar #0 $w data
- if {$value eq ""} {
- set value [pwd]
- }
- tixFileSelectBox:SetDir $w [tixFSNormalize $value]
- tixFileSelectBox:SetFilter $w $data(i-directory) $data(i-pattern)
- $w filter
- return $data(-directory)
- }
- proc tixFileSelectBox:config-pattern {w value} {
- upvar #0 $w data
- if {$value eq ""} {
- set value "*"
- }
- tixFileSelectBox:SetPat $w $value
- tixFileSelectBox:SetFilter $w $data(i-directory) $data(i-pattern)
- # Returning a value means we have overridden the value and updated
- # the widget record ourselves.
- #
- return $data(-pattern)
- }
- proc tixFileSelectBox:config-value {w value} {
- upvar #0 $w data
- tixFileSelectBox:SetValue $w [tixFSNormalize $value]
- tixSetSilent $data(w:selection) $value
- return $data(-value)
- }
- #----------------------------------------------------------------------
- # PUBLIC METHODS
- #----------------------------------------------------------------------
- proc tixFileSelectBox:filter {w args} {
- upvar #0 $w data
- $data(w:filter) popdown
- tixFileSelectBox:InterpFilter $w
- tixFileSelectBox:LoadDir $w
- }
- proc tixFileSelectBox:invoke {w args} {
- upvar #0 $w data
- if {[$data(w:selection) cget -value] ne
- [$data(w:selection) cget -selection]} {
- # this will in turn call "invoke" again ...
- #
- $data(w:selection) invoke
- return
- }
- # record the filter
- #
- set filter [tixFileSelectBox:InterpFilter $w]
- $data(w:filter) addhistory $filter
- # record the selection
- #
- set userInput [string trim [$data(w:selection) cget -value]]
- tixFileSelectBox:SetValue $w \
- [tixFSNormalize [file join $data(i-directory) $userInput]]
- $data(w:selection) addhistory $data(-value)
- $data(w:filter) align
- $data(w:selection) align
- if {[llength $data(-command)] && !$data(-disablecallback)} {
- set bind(specs) "%V"
- set bind(%V) $data(-value)
- tixEvalCmdBinding $w $data(-command) bind $data(-value)
- }
- }
- #----------------------------------------------------------------------
- # INTERNAL METHODS
- #----------------------------------------------------------------------
- # InterpFilter:
- # Interprets the value of the w:filter widget.
- #
- # Side effects:
- # Changes the fields data(-directory) and data(-pattenn)
- #
- proc tixFileSelectBox:InterpFilter {w {filter ""}} {
- upvar #0 $w data
- if {$filter == ""} {
- set filter [$data(w:filter) cget -selection]
- if {$filter == ""} {
- set filter [$data(w:filter) cget -value]
- }
- }
- set i_filter [tixFSNormalize $filter]
- if {[file isdirectory $filter]} {
- tixFileSelectBox:SetDir $w $i_filter
- tixFileSelectBox:SetPat $w "*"
- } else {
- set nDir [file dirname $filter]
- if {$nDir eq "" || $nDir eq "."} {
- tixFileSelectBox:SetDir $w [tixFSNormalize $data(i-directory)]
- } else {
- tixFileSelectBox:SetDir $w [tixFSNormalize $nDir]
- }
- tixFileSelectBox:SetPat $w [file tail $filter]
- }
- tixFileSelectBox:SetFilter $w $data(i-directory) $data(i-pattern)
- return $data(filter)
- }
- proc tixFileSelectBox:SetFilter {w dir pattern} {
- upvar #0 $w data
- set data(filter) [file join $dir $pattern]
- tixSetSilent $data(w:filter) $data(filter)
- }
- proc tixFileSelectBox:LoadDirIntoLists {w} {
- upvar #0 $w data
- $data(w:dirlist) subwidget listbox delete 0 end
- $data(w:filelist) subwidget listbox delete 0 end
- set dir $data(i-directory)
- # (1) List the directories
- #
- set isDrive [expr {[llength [file split $dir]] == 1}]
- foreach name [tixFSListDir $dir 1 0 1 1] {
- if {".." eq $name && $isDrive} { continue }
- $data(w:dirlist) subwidget listbox insert end $name
- }
- # (2) List the files
- #
- # %% UNIX'ISM:
- # If the pattern is "*" force glob to list the .* files.
- # However, since the user might not
- # be interested in them, shift the listbox so that the "normal" files
- # are seen first
- #
- # NOTE: if we pass $pat == "" but with $showHidden set to true,
- # tixFSListDir will list "* .*" in Unix. See the comment on top of
- # the tixFSListDir code.
- #
- if {$data(i-pattern) eq "*"} {
- set pat ""
- } else {
- set pat $data(i-pattern)
- }
- set top 0
- foreach name [tixFSListDir $dir 0 1 0 0 $pat] {
- $data(w:filelist) subwidget listbox insert end $name
- if {[string match .* $name]} {
- incr top
- }
- }
- $data(w:filelist) subwidget listbox yview $top
- }
- proc tixFileSelectBox:LoadDir {w} {
- upvar #0 $w data
- tixBusy $w on [$data(w:dirlist) subwidget listbox]
- tixFileSelectBox:LoadDirIntoLists $w
- if {[$data(w:dirlist) subwidget listbox size] == 0} {
- # fail safe, just in case the user has inputed an errnoeuos
- # directory
- $data(w:dirlist) subwidget listbox insert 0 ".."
- }
- tixWidgetDoWhenIdle tixBusy $w off [$data(w:dirlist) subwidget listbox]
- }
- # User single clicks on the directory listbox
- #
- proc tixFileSelectBox:SelectDir {w} {
- upvar #0 $w data
- if {$data(fakeDir) > 0} {
- incr data(fakeDir) -1
- $data(w:dirlist) subwidget listbox select clear 0 end
- $data(w:dirlist) subwidget listbox activate -1
- return
- }
- if {$data(flag)} {
- return
- }
- set data(flag) 1
- set subdir [tixListboxGetCurrent [$data(w:dirlist) subwidget listbox]]
- if {$subdir == ""} {
- set subdir "."
- }
- tixFileSelectBox:SetFilter $w \
- [tixFSNormalize [file join $data(i-directory) $subdir]] \
- $data(i-pattern)
- set data(flag) 0
- }
- proc tixFileSelectBox:InvokeDir {w} {
- upvar #0 $w data
- set theDir [$data(w:dirlist) subwidget listbox get active]
- tixFileSelectBox:SetDir $w \
- [tixFSNormalize [file join $data(i-directory) $theDir]]
- $data(w:dirlist) subwidget listbox select clear 0 end
- tixFileSelectBox:SetFilter $w $data(i-directory) $data(i-pattern)
- tixFileSelectBox:InterpFilter $w [tixFSNativeNorm $data(filter)]
- tixFileSelectBox:LoadDir $w
- if {![tixEvent match <Return>]} {
- incr data(fakeDir) 1
- }
- }
- proc tixFileSelectBox:SelectFile {w} {
- upvar #0 $w data
- if {$data(flag)} {
- return
- }
- set data(flag) 1
- # Reset the "Filter:" box to the current directory:
- #
- $data(w:dirlist) subwidget listbox select clear 0 end
- tixFileSelectBox:SetFilter $w $data(i-directory) $data(i-pattern)
- # Now select the file
- #
- set selected [tixListboxGetCurrent [$data(w:filelist) subwidget listbox]]
- if {$selected != ""} {
- # Make sure that the selection is not empty!
- #
- tixFileSelectBox:SetValue $w \
- [tixFSNormalize [file join $data(i-directory) $selected]]
- tixSetSilent $data(w:selection) $data(-value)
- if {[llength $data(-browsecmd)]} {
- tixEvalCmdBinding $w $data(-browsecmd) "" $data(-value)
- }
- }
- set data(flag) 0
- }
- proc tixFileSelectBox:InvokeFile {w} {
- upvar #0 $w data
- set selected [tixListboxGetCurrent [$data(w:filelist) subwidget listbox]]
- if {$selected != ""} {
- $w invoke
- }
- }
- # This is only called the first this fileBox is mapped -- load the directory
- #
- proc tixFileSelectBox:FirstMapped {w} {
- if {![winfo exists $w]} {
- return
- }
- upvar #0 $w data
- tixFileSelectBox:SetFilter $w $data(i-directory) $data(i-pattern)
- tixFileSelectBox:LoadDir $w
- $data(w:filter) align
- }
- #----------------------------------------------------------------------
- #
- #
- # C O N V E N I E N C E R O U T I N E S
- #
- #
- #----------------------------------------------------------------------
- # This is obsolete. Use the widget tixFileSelectDialog instead
- #
- #
- proc tixMkFileDialog {w args} {
- set option(-okcmd) ""
- set option(-helpcmd) ""
- tixHandleOptions option {-okcmd -helpcmd} $args
- toplevel $w
- wm minsize $w 10 10
- tixStdDlgBtns $w.btns
-
- if {$option(-okcmd) != ""} {
- tixFileSelectBox $w.fsb \
- -command "[list wm withdraw $w]; $option(-okcmd)"
- } else {
- tixFileSelectBox $w.fsb -command [list wm withdraw $w]
- }
- $w.btns button ok config -command [list $w.fsb invoke]
- $w.btns button apply config -command [list $w.fsb filter] -text Filter
- $w.btns button cancel config -command [list wm withdraw $w]
- if {$option(-helpcmd) == ""} {
- $w.btns button help config -state disabled
- } else {
- $w.btns button help config -command $option(-helpcmd)
- }
- wm protocol $w WM_DELETE_WINDOW [list wm withdraw $w]
- pack $w.btns -side bottom -fill both
- pack $w.fsb -fill both -expand yes
- return $w.fsb
- }
|