home *** CD-ROM | disk | FTP | other *** search
- ###############################################################################
- # $Id: BtkFileSelector.tk,v 1.2 1995/06/30 17:17:57 bmott Exp $
- ###############################################################################
- # BtkFileSelector.tk - File Selector Widget for Tk
- #
- # Use the procedure BtkFileSelector to open a file selector widget. The
- # procedure accepts the following switches:
- #
- # -in <window> creates the file selector as a child of the window
- # -filter <*.setup> Sets the filter to the given string
- # -text <message> Message displayed at the top of the file selector
- #
- # Copyright (c) 1994
- # Bradford W. Mott
- # September 1,1994
- ###############################################################################
- # $Log: BtkFileSelector.tk,v $
- # Revision 1.2 1995/06/30 17:17:57 bmott
- # Changed font resources and made the file selector's size depend on
- # its parent's size
- #
- # Revision 1.1 1994/09/13 23:30:03 bmott
- # Initial revision
- #
- #
- ###############################################################################
-
- set btkFileSelector(path) [pwd]
-
- option add "*btkFileSelector*Font" "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-*" 40
- option add "*btkFileSelector*label*Font" "-*-helvetica-bold-r-normal--*-120-*-*-*-*-iso8859-*" 40
- option add "*btkFileSelector*Foreground" "black" 40
- option add "*btkFileSelector*Background" "gray80" 40
- option add "*btkFileSelector*activeForeground" "black" 40
- option add "*btkFileSelector*activeBackground" "gray65" 40
- option add "*btkFileSelector*scrollbar*foreground" "gray80" 40
- option add "*btkFileSelector*scrollbar*activeForeground" "gray65" 40
- option add "*btkFileSelector*selectForeground" "black" 40
- option add "*btkFileSelector*selectBackground" "gray65" 40
-
-
- ###############################################################################
- # Fill the selector's listbox with the files in the current directory
- ###############################################################################
- proc BtkFileSelectorUpdate {window} {
- global btkFileSelector
-
- ## Change the mouse pointer to the watch
- $window configure -cursor watch
-
- ## Tell tk to update the screen
- update idletasks
-
- ## Get the filter and path
- set filter $btkFileSelector(filter)
- set path $btkFileSelector(path)
-
- ## Update the filter entry field
- $window.filter.entry delete 0 end
- $window.filter.entry insert end $filter
- BtkFileSelectorEntryAlign $window.filter.entry end
-
- ## Update the path entry field
- $window.path.entry delete 0 end
- $window.path.entry insert end $path
- BtkFileSelectorEntryAlign $window.path.entry end
-
- ## Get a list of all of the files in the current directory
- if {$btkFileSelector(allFiles) == "yes"} {
- set files [glob -nocomplain $path/.* $path/*]
- set files [lrange $files 2 end]
- } else {
- set files [glob -nocomplain $path/*]
- }
-
- ## Start with an empty file list
- set filelist ""
-
- ## Build the rest of the file list
- foreach i $files {
- set file [file tail $i]
-
- ## Make sure file really exists (This is for wierd file systems like AFS)
- if {[file exists "$i"] == 1} {
- if {[file isdirectory "$i"] == 1} {
- lappend filelist "$file/"
- } else {
- if {[string match $filter $file] == 1} {
- lappend filelist "$file"
- }
- }
- }
- }
-
- ## Sort the file list
- set filelist [lsort $filelist]
-
- ## Add the parent directory to the top of the list if we're not at the root
- if {$btkFileSelector(path) != ""} {
- set filelist [linsert $filelist 0 "../"]
- }
-
- ## Clear the listbox
- $window.selection.listbox delete 0 end
-
- ## Put the file list in the listbox
- foreach i $filelist {
- $window.selection.listbox insert end "$i"
- }
-
- ## Change the mouse pointer back to the default
- $window configure -cursor {}
-
- ## Tell tk to update the screen
- update idletasks
- }
-
-
- ###############################################################################
- ## Process a click event on a file
- ###############################################################################
- proc BtkFileSelectorFileClicked {window y} {
- global btkFileSelector
-
- ## Get the listbox item nearest the y coordinate
- set nearest [$window nearest $y]
-
- if {$nearest >= 0} {
- $window select from $nearest
- $window select to $nearest
-
- set file [$window get $nearest]
- if {[regexp {^.*/$} $file] == 0} {
- ## Update the filename entry field
- $btkFileSelector(baseWindow).filename.entry delete 0 end
- $btkFileSelector(baseWindow).filename.entry insert end $file
- }
- }
- }
-
- ###############################################################################
- ## Process a double click event on a file
- ###############################################################################
- proc BtkFileSelectorFileDoubleClicked {window y} {
- global btkFileSelector
-
- ## Get the path
- set path $btkFileSelector(path)
-
- ## Get the listbox item nearest the y coordinate
- set nearest [$window nearest $y]
- if {$nearest >= 0} {
- set file [$window get $nearest]
- set filespec $path/$file
-
- ## If the file is a directory then try to change directories
- if {[regexp {^.*/$} $file] == 1} {
-
- ## See if we should move to the parent directory
- if {$file == "../"} {
- set filespec [file dirname [string trimright $path '/']]/
- }
-
- if {([file executable $path/$file]==1)&&([file readable $path/$file]==1)} {
-
- ## Update the path
- set btkFileSelector(path) [string trimright $filespec '/']
-
- BtkFileSelectorUpdate $btkFileSelector(baseWindow)
- } else {
-
- ## Get the current color of the background
- set current [lindex [$window configure -background] 4]
-
- ## Change the background to black
- $window configure -background Black
-
- ## Tell tk to update the screen
- update idletasks
-
- ## Wait
- after 50
-
- ## Restore the background
- $window configure -background $current
-
- ## Tell tk to update the screen
- update idletasks
- }
- } else {
- BtkFileSelectorFileSelected
- }
- }
- }
-
- ###############################################################################
- ## Handle the Okay button
- ###############################################################################
- proc BtkFileSelectorFileSelected {} {
- global btkFileSelector
-
- ## Get the selected file from the listbox
- set file [$btkFileSelector(baseWindow).filename.entry get]
- if {$file == ""} { return }
-
- set btkFileSelector(filespec) $btkFileSelector(path)/$file
- destroy $btkFileSelector(baseWindow)
- }
-
- ###############################################################################
- ## Handle the Cancel button
- ###############################################################################
- proc BtkFileSelectorCanceled {} {
- global btkFileSelector
-
- set btkFileSelector(filespec) ""
- destroy $btkFileSelector(baseWindow)
- }
-
- ###############################################################################
- ## Set the "common" bindings for the entry widgets
- ###############################################################################
- proc BtkFileSelectorSetEntryBindings { window } {
- global btkFileSelector
-
- ## See if the entry needs to be added to the list of entry widgets
- if {[lsearch -exact $btkFileSelector(entryList) $window] == -1} {
- lappend btkFileSelector(entryList) $window
- }
-
- bind $window <Left> "BtkFileSelectorEntryCursorPositionChange $window -1"
- bind $window <Right> "BtkFileSelectorEntryCursorPositionChange $window 1"
- bind $window <Tab> "BtkFileSelectorNextEntry"
- }
-
- ###############################################################################
- ## Move the focus to the next entry widget
- ###############################################################################
- proc BtkFileSelectorNextEntry {} {
- global btkFileSelector
-
- ## Get the current focus window path
- set current [focus]
-
- set currentIndex [lsearch -exact $btkFileSelector(entryList) $current]
- if {$currentIndex == -1} {
- set current [lindex $btkFileSelector(entryList) 0]
- } else {
- set i [expr $currentIndex + 1]
- if {$i >= [llength $btkFileSelector(entryList)]} {
- set i 0
- }
- set current [lindex $btkFileSelector(entryList) $i]
- }
-
- ## Change the entry focus
- catch {focus $current}
- }
-
- ###############################################################################
- ## Change the position of the insertion cursor in the given entry widget
- ###############################################################################
- proc BtkFileSelectorEntryCursorPositionChange {window offset} {
- global btkFileSelector
-
- set pos [$window index insert]
- incr pos $offset
- if {$pos < 0} {
- set pos 0
- }
- $window icursor $pos
-
- ## Move the cursor into view
- BtkFileSelectorEntryAlign $window insert
- }
-
- ###############################################################################
- ## Tell the entry widget to align the indexed character into view
- ###############################################################################
- proc BtkFileSelectorEntryAlign { window index } {
-
- set c [$window index $index]
-
- set left [$window index @0]
- if {$left >= $c} {
- if {$c > 0} {
- $window view [expr $c-1]
- } else {
- $window view $c
- }
- return
- }
-
- set x [expr [winfo width $window] - [lindex [$window config -bd] 4] - 1]
- while {([$window index @$x] < $c) && ($left < $c)} {
- set left [expr $left+1]
- $window view $left
- }
- }
-
- ###############################################################################
- ## Try to change the path to whatever is in the path entry widget
- ###############################################################################
- proc BtkFileSelectorSetPath {} {
- global btkFileSelector
-
- ## Get the path from the entry widget
- set path [string trimright [$btkFileSelector(baseWindow).path.entry get] '/']
-
- ## Make sure it's a valid path
- if {([file executable $path/]==1)&&([file readable $path/]==1)} {
- set btkFileSelector(path) $path
- BtkFileSelectorUpdate $btkFileSelector(baseWindow)
- } else {
- ## Update the path entry field
- $btkFileSelector(baseWindow).path.entry delete 0 end
- $btkFileSelector(baseWindow).path.entry insert end $btkFileSelector(path)
-
- ## Right align the view
- BtkFileSelectorEntryAlign $btkFileSelector(baseWindow).path.entry insert
- }
- }
-
-
- ###############################################################################
- ## Try to change the filter to whatever is in the filter entry widget
- ###############################################################################
- proc BtkFileSelectorSetFilter {} {
- global btkFileSelector
-
- ## Get the path from the entry widget
- set filter [$btkFileSelector(baseWindow).filter.entry get]
-
- ## Make sure there is a filter
- if {$filter == ""} { set filter "*" }
-
- set btkFileSelector(filter) $filter
-
- BtkFileSelectorUpdate $btkFileSelector(baseWindow)
- }
-
-
- ###############################################################################
- # Popup a file selector and wait for the user to select something
- ###############################################################################
- proc BtkFileSelector args {
- global btkFileSelector
-
- ## Clear the entry "next" list
- set btkFileSelector(entryList) ""
- ## Set the return value to nothing
- set btkFileSelector(filespec) ""
- ## Default Message
- set btkFileSelector(message) "Files:"
- ## Default to creating a toplevel window
- set btkFileSelector(parentWindow) "root"
- ## Default Filter
- set btkFileSelector(filter) "*"
-
- ## Parse the argument list
- for {set t 0} {$t < [llength $args]} {incr t} {
- set arg [lindex $args $t]
- if {$arg == "-text"} {
- incr t
- set btkFileSelector(message) [lindex $args $t]
- } elseif {$arg == "-in"} {
- incr t
- if {[lindex $args $t] == "."} {
- set btkFileSelector(parentWindow) ""
- } else {
- set btkFileSelector(parentWindow) [lindex $args $t]
- }
- } elseif {$arg == "-filter"} {
- incr t
- set btkFileSelector(filter) [lindex $args $t]
- } else {
- tkerror "Incorrect Arguments to BtkFileSelector!"
- return
- }
- }
-
- ## Create a toplevel window or a frame to hold the selector in
- if {$btkFileSelector(parentWindow) == "root"} {
- set btkFileSelector(baseWindow) ".btkFileSelector"
- set btkFileSelector(parentWindow) ".btkFileSelector"
-
- toplevel $btkFileSelector(baseWindow) -borderwidth 4
-
- wm geometry $btkFileSelector(baseWindow) 375x342
- wm title $btkFileSelector(baseWindow) "File Selector"
- } else {
- ## Get my parent's width and height
- if {$btkFileSelector(parentWindow) == ""} {
- scan [winfo geometry .] "%dx%d" parentWidth parentHeight
- } else {
- scan [winfo geometry $btkFileSelector(parentWindow)] "%dx%d" parentWidth parentHeight
- }
-
- ## Calculate size of my frame based on my parent's size
- if {$parentWidth > 375} {
- set myWidth 375
- } else {
- set myWidth [expr $parentWidth - 20]
- }
-
- if {$parentHeight > 350} {
- set myHeight 350
- } else {
- set myHeight [expr $parentHeight - 20]
- }
-
- ## Create my frame
- set btkFileSelector(baseWindow) \
- "$btkFileSelector(parentWindow).btkFileSelector"
-
- frame $btkFileSelector(baseWindow) -borderwidth 5 -relief ridge \
- -height $myHeight -width $myWidth
- place $btkFileSelector(baseWindow) -relx 0.5 -rely 0.5 -anchor center
-
- ## Turn off geometry propagation for the packer
- pack propagate $btkFileSelector(baseWindow) 0
- }
-
- frame $btkFileSelector(baseWindow).path
- label $btkFileSelector(baseWindow).path.label -text "Path:" -anchor w
- entry $btkFileSelector(baseWindow).path.entry -relief sunken
- BtkFileSelectorSetEntryBindings $btkFileSelector(baseWindow).path.entry
- bind $btkFileSelector(baseWindow).path.entry \
- <Return> "BtkFileSelectorSetPath"
- pack $btkFileSelector(baseWindow).path.label -side left
- pack $btkFileSelector(baseWindow).path.entry -side left -fill x -expand 1
-
- frame $btkFileSelector(baseWindow).filename
- label $btkFileSelector(baseWindow).filename.label \
- -text "File name:" -anchor w
- entry $btkFileSelector(baseWindow).filename.entry -relief sunken
- BtkFileSelectorSetEntryBindings $btkFileSelector(baseWindow).filename.entry
- bind $btkFileSelector(baseWindow).filename.entry \
- <Return> "BtkFileSelectorFileSelected"
- pack $btkFileSelector(baseWindow).filename.label -side left
- pack $btkFileSelector(baseWindow).filename.entry -side left \
- -fill x -expand 1
-
- frame $btkFileSelector(baseWindow).filter
- label $btkFileSelector(baseWindow).filter.label -text "Filter:" -anchor w
- entry $btkFileSelector(baseWindow).filter.entry -relief sunken -width 10
- BtkFileSelectorSetEntryBindings $btkFileSelector(baseWindow).filter.entry
- bind $btkFileSelector(baseWindow).filter.entry \
- <Return> "BtkFileSelectorSetFilter"
- checkbutton $btkFileSelector(baseWindow).filter.all \
- -text "Show all files" -offvalue "no" -onvalue "yes" \
- -variable btkFileSelector(allFiles) \
- -command {BtkFileSelectorUpdate $btkFileSelector(baseWindow)}
-
- pack $btkFileSelector(baseWindow).filter.label -side left
- pack $btkFileSelector(baseWindow).filter.entry -side left -fill x \
- -expand 1 -padx 4
- pack $btkFileSelector(baseWindow).filter.all -side left
-
- frame $btkFileSelector(baseWindow).selection
- label $btkFileSelector(baseWindow).selection.label \
- -text $btkFileSelector(message)
- scrollbar $btkFileSelector(baseWindow).selection.scrollbar \
- -relief sunken -orient vertical \
- -command "$btkFileSelector(baseWindow).selection.listbox yview"
- listbox $btkFileSelector(baseWindow).selection.listbox \
- -relief sunken -geometry 20x4 \
- -yscroll "$btkFileSelector(baseWindow).selection.scrollbar set"
- tk_listboxSingleSelect $btkFileSelector(baseWindow).selection.listbox
- bind $btkFileSelector(baseWindow).selection.listbox <Double-ButtonRelease-1> \
- "BtkFileSelectorFileDoubleClicked %W %y"
- bind $btkFileSelector(baseWindow).selection.listbox <ButtonPress-1> \
- "BtkFileSelectorFileClicked %W %y"
- bind $btkFileSelector(baseWindow).selection.listbox <Button1-Motion> \
- "BtkFileSelectorFileClicked %W %y"
-
- pack $btkFileSelector(baseWindow).selection.label \
- -side top -anchor w -fill x
- pack $btkFileSelector(baseWindow).selection.scrollbar \
- -side left -fill y
- pack $btkFileSelector(baseWindow).selection.listbox \
- -side left -fill both -expand 1
-
-
- frame $btkFileSelector(baseWindow).button
- button $btkFileSelector(baseWindow).button.okay \
- -text "Okay" -command "BtkFileSelectorFileSelected"
- button $btkFileSelector(baseWindow).button.filter \
- -text "Filter" -command "BtkFileSelectorSetFilter"
- button $btkFileSelector(baseWindow).button.cancel \
- -text "Cancel" -command "BtkFileSelectorCanceled"
-
- pack $btkFileSelector(baseWindow).button.okay \
- -side left -fill x -expand 1
- pack $btkFileSelector(baseWindow).button.filter \
- -side left -fill x -expand 1 -padx 4
- pack $btkFileSelector(baseWindow).button.cancel \
- -side left -fill x -expand 1
-
- pack $btkFileSelector(baseWindow).selection \
- -side top -padx 4 -pady 2 -fill both -expand 1
- pack $btkFileSelector(baseWindow).path \
- -side top -padx 4 -fill x
- pack $btkFileSelector(baseWindow).filename \
- -side top -padx 4 -fill x
- pack $btkFileSelector(baseWindow).filter \
- -side top -padx 4 -fill x
- pack $btkFileSelector(baseWindow).button \
- -side top -padx 4 -pady 7 -fill x
-
-
- ## Update the file selector's file list
- BtkFileSelectorUpdate $btkFileSelector(baseWindow)
-
- ## Make this a modal dialog
- tkwait visibility $btkFileSelector(baseWindow)
- while {[catch {grab set $btkFileSelector(baseWindow)}] == 1} {}
- tkwait window $btkFileSelector(baseWindow)
-
- ## Tell tk to update the screen (i.e. remove the file selector window)
- update idletasks
-
- return $btkFileSelector(filespec)
- }
-
-