📄 tkfbox.tcl
字号:
upvar ::tk::dialog::file::$dataName data global tk_library tkPriv catch {unset data(updateId)} if {![info exists tkPriv(folderImage)]} { set tkPriv(folderImage) [image create photo -data {R0lGODlhEAAMAKEAAAD//wAAAPD/gAAAACH5BAEAAAAALAAAAAAQAAwAAAIghINhyycvVFsBQtmS3rjaH1Hg141WaT5ouprt2HHcUgAAOw==}] set tkPriv(fileImage) [image create photo -data {R0lGODlhDAAMAKEAALLA3AAAAP//8wAAACH5BAEAAAAALAAAAAAMAAwAAAIgRI4Ha+IfWHsOrSASvJTGhnhcV3EJlo3kh53ltF5nAhQAOw==}] } set folder $tkPriv(folderImage) set file $tkPriv(fileImage) set appPWD [pwd] if {[catch { cd $data(selectPath) }]} { # We cannot change directory to $data(selectPath). $data(selectPath) # should have been checked before ::tk::dialog::file::Update is called, so # we normally won't come to here. Anyways, give an error and abort # action. tk_messageBox -type ok -parent $w -message \ "Cannot change to the directory \"$data(selectPath)\".\nPermission denied."\ -icon warning cd $appPWD return } # Turn on the busy cursor. BUG?? We haven't disabled X events, though, # so the user may still click and cause havoc ... # set entCursor [$data(ent) cget -cursor] set dlgCursor [$w cget -cursor] $data(ent) config -cursor watch $w config -cursor watch update idletasks tkIconList_DeleteAll $data(icons) # Make the dir list # foreach f [lsort -dictionary [glob -nocomplain .* *]] { if {[string equal $f .]} { continue } if {[string equal $f ..]} { continue } if {[file isdir ./$f]} { if {![info exists hasDoneDir($f)]} { tkIconList_Add $data(icons) $folder $f set hasDoneDir($f) 1 } } } if { [string equal $class TkFDialog] } { # Make the file list if this is a File Dialog # if {[string equal $data(filter) *]} { set files [lsort -dictionary \ [glob -nocomplain .* *]] } else { set files [lsort -dictionary \ [eval glob -nocomplain $data(filter)]] } foreach f $files { if {![file isdir ./$f]} { if {![info exists hasDoneFile($f)]} { tkIconList_Add $data(icons) $file $f set hasDoneFile($f) 1 } } } } tkIconList_Arrange $data(icons) # Update the Directory: option menu # set list "" set dir "" foreach subdir [file split $data(selectPath)] { set dir [file join $dir $subdir] lappend list $dir } $data(dirMenu) delete 0 end set var [format %s(selectPath) ::tk::dialog::file::$dataName] foreach path $list { $data(dirMenu) add command -label $path -command [list set $var $path] } # Restore the PWD to the application's PWD # cd $appPWD if { [string equal $class TkFDialog] } { # Restore the Open/Save Button if this is a File Dialog # if {[string equal $data(type) open]} { $data(okBtn) config -text "Open" } else { $data(okBtn) config -text "Save" } } # turn off the busy cursor. # $data(ent) config -cursor $entCursor $w config -cursor $dlgCursor}# ::tk::dialog::file::SetPathSilently --## Sets data(selectPath) without invoking the trace procedure#proc ::tk::dialog::file::SetPathSilently {w path} { upvar ::tk::dialog::file::[winfo name $w] data trace vdelete data(selectPath) w [list ::tk::dialog::file::SetPath $w] set data(selectPath) $path trace variable data(selectPath) w [list ::tk::dialog::file::SetPath $w]}# This proc gets called whenever data(selectPath) is set#proc ::tk::dialog::file::SetPath {w name1 name2 op} { if {[winfo exists $w]} { upvar ::tk::dialog::file::[winfo name $w] data ::tk::dialog::file::UpdateWhenIdle $w # On directory dialogs, we keep the entry in sync with the currentdir. if { [string equal [winfo class $w] TkChooseDir] } { $data(ent) delete 0 end $data(ent) insert end $data(selectPath) } }}# This proc gets called whenever data(filter) is set#proc ::tk::dialog::file::SetFilter {w type} { upvar ::tk::dialog::file::[winfo name $w] data upvar \#0 $data(icons) icons set data(filter) [lindex $type 1] $data(typeMenuBtn) config -text [lindex $type 0] -indicatoron 1 $icons(sbar) set 0.0 0.0 ::tk::dialog::file::UpdateWhenIdle $w}# tk::dialog::file::ResolveFile --## Interpret the user's text input in a file selection dialog.# Performs:## (1) ~ substitution# (2) resolve all instances of . and ..# (3) check for non-existent files/directories# (4) check for chdir permissions## Arguments:# context: the current directory you are in# text: the text entered by the user# defaultext: the default extension to add to files with no extension## Return vaue:# [list $flag $directory $file]## flag = OK : valid input# = PATTERN : valid directory/pattern# = PATH : the directory does not exist# = FILE : the directory exists by the file doesn't# exist# = CHDIR : Cannot change to the directory# = ERROR : Invalid entry## directory : valid only if flag = OK or PATTERN or FILE# file : valid only if flag = OK or PATTERN## directory may not be the same as context, because text may contain# a subdirectory name#proc ::tk::dialog::file::ResolveFile {context text defaultext} { set appPWD [pwd] set path [::tk::dialog::file::JoinFile $context $text] # If the file has no extension, append the default. Be careful not # to do this for directories, otherwise typing a dirname in the box # will give back "dirname.extension" instead of trying to change dir. if {![file isdirectory $path] && [string equal [file ext $path] ""]} { set path "$path$defaultext" } if {[catch {file exists $path}]} { # This "if" block can be safely removed if the following code # stop generating errors. # # file exists ~nonsuchuser # return [list ERROR $path ""] } if {[file exists $path]} { if {[file isdirectory $path]} { if {[catch {cd $path}]} { return [list CHDIR $path ""] } set directory [pwd] set file "" set flag OK cd $appPWD } else { if {[catch {cd [file dirname $path]}]} { return [list CHDIR [file dirname $path] ""] } set directory [pwd] set file [file tail $path] set flag OK cd $appPWD } } else { set dirname [file dirname $path] if {[file exists $dirname]} { if {[catch {cd $dirname}]} { return [list CHDIR $dirname ""] } set directory [pwd] set file [file tail $path] if {[regexp {[*]|[?]} $file]} { set flag PATTERN } else { set flag FILE } cd $appPWD } else { set directory $dirname set file [file tail $path] set flag PATH } } return [list $flag $directory $file]}# Gets called when the entry box gets keyboard focus. We clear the selection# from the icon list . This way the user can be certain that the input in the # entry box is the selection.#proc ::tk::dialog::file::EntFocusIn {w} { upvar ::tk::dialog::file::[winfo name $w] data if {[string compare [$data(ent) get] ""]} { $data(ent) selection range 0 end $data(ent) icursor end } else { $data(ent) selection clear } tkIconList_Unselect $data(icons) if { [string equal [winfo class $w] TkFDialog] } { # If this is a File Dialog, make sure the buttons are labeled right. if {[string equal $data(type) open]} { $data(okBtn) config -text "Open" } else { $data(okBtn) config -text "Save" } }}proc ::tk::dialog::file::EntFocusOut {w} { upvar ::tk::dialog::file::[winfo name $w] data $data(ent) selection clear}# Gets called when user presses Return in the "File name" entry.#proc ::tk::dialog::file::ActivateEnt {w} { upvar ::tk::dialog::file::[winfo name $w] data set text [string trim [$data(ent) get]] set list [::tk::dialog::file::ResolveFile $data(selectPath) $text \ $data(-defaultextension)] set flag [lindex $list 0] set path [lindex $list 1] set file [lindex $list 2] switch -- $flag { OK { if {[string equal $file ""]} { # user has entered an existing (sub)directory set data(selectPath) $path $data(ent) delete 0 end } else { ::tk::dialog::file::SetPathSilently $w $path set data(selectFile) $file ::tk::dialog::file::Done $w } } PATTERN { set data(selectPath) $path set data(filter) $file } FILE { if {[string equal $data(type) open]} { tk_messageBox -icon warning -type ok -parent $w \ -message "File \"[file join $path $file]\" does not exist." $data(ent) selection range 0 end $data(ent) icursor end } else { ::tk::dialog::file::SetPathSilently $w $path set data(selectFile) $file ::tk::dialog::file::Done $w } } PATH { tk_messageBox -icon warning -type ok -parent $w \ -message "Directory \"$path\" does not exist." $data(ent) selection range 0 end $data(ent) icursor end } CHDIR { tk_messageBox -type ok -parent $w -message \ "Cannot change to the directory \"$path\".\nPermission denied."\ -icon warning $data(ent) selection range 0 end $data(ent) icursor end } ERROR { tk_messageBox -type ok -parent $w -message \ "Invalid file name \"$path\"."\ -icon warning $data(ent) selection range 0 end $data(ent) icursor end } }}# Gets called when user presses the Alt-s or Alt-o keys.#proc ::tk::dialog::file::InvokeBtn {w key} { upvar ::tk::dialog::file::[winfo name $w] data if {[string equal [$data(okBtn) cget -text] $key]} { tkButtonInvoke $data(okBtn) }}# Gets called when user presses the "parent directory" button#proc ::tk::dialog::file::UpDirCmd {w} { upvar ::tk::dialog::file::[winfo name $w] data if {[string compare $data(selectPath) "/"]} { set data(selectPath) [file dirname $data(selectPath)] }}# Join a file name to a path name. The "file join" command will break# if the filename begins with ~#proc ::tk::dialog::file::JoinFile {path file} { if {[string match {~*} $file] && [file exists $path/$file]} { return [file join $path ./$file] } else { return [file join $path $file] }}# Gets called when user presses the "OK" button#proc ::tk::dialog::file::OkCmd {w} { upvar ::tk::dialog::file::[winfo name $w] data set text [tkIconList_Get $data(icons)] if {[string compare $text ""]} { set file [::tk::dialog::file::JoinFile $data(selectPath) $text] if {[file isdirectory $file]} { ::tk::dialog::file::ListInvoke $w $text return } } ::tk::dialog::file::ActivateEnt $w}# Gets called when user presses the "Cancel" button#proc ::tk::dialog::file::CancelCmd {w} { upvar ::tk::dialog::file::[winfo name $w] data global tkPriv set tkPriv(selectFilePath) ""}# Gets called when user browses the IconList widget (dragging mouse, arrow# keys, etc)#proc ::tk::dialog::file::ListBrowse {w text} { upvar ::tk::dialog::file::[winfo name $w] data if {[string equal $text ""]} { return } set file [::tk::dialog::file::JoinFile $data(selectPath) $text] if {![file isdirectory $file]} { $data(ent) delete 0 end $data(ent) insert 0 $text if { [string equal [winfo class $w] TkFDialog] } { if {[string equal $data(type) open]} { $data(okBtn) config -text "Open" } else { $data(okBtn) config -text "Save" } } } else { if { [string equal [winfo class $w] TkFDialog] } { $data(okBtn) config -text "Open" } }}# Gets called when user invokes the IconList widget (double-click, # Return key, etc)#proc ::tk::dialog::file::ListInvoke {w text} { upvar ::tk::dialog::file::[winfo name $w] data if {[string equal $text ""]} { return } set file [::tk::dialog::file::JoinFile $data(selectPath) $text] set class [winfo class $w] if {[string equal $class TkChooseDir] || [file isdirectory $file]} { set appPWD [pwd] if {[catch {cd $file}]} { tk_messageBox -type ok -parent $w -message \ "Cannot change to the directory \"$file\".\nPermission denied."\ -icon warning } else { cd $appPWD set data(selectPath) $file } } else { set data(selectFile) $file ::tk::dialog::file::Done $w }}# ::tk::dialog::file::Done --## Gets called when user has input a valid filename. Pops up a# dialog box to confirm selection when necessary. Sets the# tkPriv(selectFilePath) variable, which will break the "tkwait"# loop in tkFDialog and return the selected filename to the# script that calls tk_getOpenFile or tk_getSaveFile#proc ::tk::dialog::file::Done {w {selectFilePath ""}} { upvar ::tk::dialog::file::[winfo name $w] data global tkPriv if {[string equal $selectFilePath ""]} { set selectFilePath [::tk::dialog::file::JoinFile $data(selectPath) \ $data(selectFile)] set tkPriv(selectFile) $data(selectFile) set tkPriv(selectPath) $data(selectPath) if {[file exists $selectFilePath] && [string equal $data(type) save]} { set reply [tk_messageBox -icon warning -type yesno\ -parent $w -message "File\ \"$selectFilePath\" already exists.\nDo\ you want to overwrite it?"] if {[string equal $reply "no"]} { return } } } set tkPriv(selectFilePath) $selectFilePath}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -