#!/usr/bin/wish ## ## If 'wish' is at a location like /usr/local/bin/wish, not /usr/bin/wish, ## you can do 'sudo ln -s /usr/local/bin/wish /usr/bin/wish' on the ## appropriate host(s). ## ##+######################################################################## ## Tk SCRIPT NAME: scriptSelector_2listboxes.tk ## ## WHERE: typically installed in an 'apps' directory ## such as $HOME/apps/tkScriptApplicator ## ##+######################################################################## ## PURPOSE: Provides a Graphical User Interface (GUI) for ## SELECTING A SCRIPT, from a hierarchy of subdirectories of scripts. ## ## Intended to be called from a file(s)-selector utility, the Tk script ## 'tkScriptApplicator_multifilesSelector_2listboxes.tk'. Via that ## GUI, the user can select one or more files in a listbox ## and then click on an 'Apply-a-Script' button to bring up this GUI, ## with which to select a script. The selected shell script ## is to be run, by feeding the selected file(s) to the ## chosen shell script. ## ## This set of 'tkScriptApplicator' GUI's does not provide the 'Nautilus' ## shell scripts that are to be applied to the selected file(s), but ## such shell scripts can be found in the typical locations for those ## scripts in the Gnome 2 and MATE desktop-environment systems: ## ## $HOME/.gnome2/nautilus-scripts ## or ## $HOME/.config/caja/scripts ## ################################# ## CONFIGURING THIS Tk GUI SCRIPT: ## ## The user can change the 'set' statement at the bottom of this ## 'scriptSelector_2listboxes.tk' Tk script to point to the ## desired directory that holds the 'Nautilus scripts'. ## ## Typically, the 'set' statements look like ## ## set DIRshellScripts "$env(HOME)/.gnome2/nautilus-scripts" ## OR ## set DIRshellScripts "$env(HOME)/.config/caja/scripts" ## ## but the 'Nautilus scripts' could be placed in any directory. ## Example: $env(HOME)/ScriptsThatMakeMeHappy ## ## A package of more than 450 'Nautilus scripts' is available at ## www.freedomenv.com, for installation in any of those ## shell-scripts directories. ## #################################### ## AN OVERVIEW OF THIS Tk GUI SCRIPT: ## (how this Tk script fits in the 'tkScriptApplicator' mini-system) ## ## The set of several Tk scripts constituting the 'tkScriptApplicator' ## mini-system is intended to serve as an alternative to the ## 'select-files-and-right-click-to-choose-a-script-to-apply- ## to-the-selected-files' capability of the Gnome2-Nautilus ## file manager. ## ## This 'script-selector' GUI is intended to supply the 'choose-a-script ## to-apply-to-the-selected-files' part of that capability. ## ##+################################### ## The GUI DESIGN and OPERATION BASICS: ## ## The two main Tk GUI's of this utility (the 'file(s)-selector' and ## the 'script-selector') could be implemented in many different ways. ## ## For example, a SINGLE listbox could be used to hold both ## sub-directory names and filenames of a 'current directory'. ## But these GUI's use a TWO-listbox layout --- ONE listbox for ## sub-directory names and ONE listbox for 'regular' filenames. ## ## There are TWO, SIDE-BY-SIDE LISTBOXES in this 'script-selector' GUI: ## - a LEFT listbox for SUB-DIRECTORIES of the 'Nautilus' scripts directory ## and ## - a RIGHT listbox for the SCRIPTS (files) in a user-selected ## 'Nautilus' scripts sub-directory. ## ## A script is selected by clicking on a filename in the right-hand, ## files-listbox. The GUI supports a mask for 'filtering' filenames ## such as '.sh'. ## ## In other words, this utility is based on assuming the scripts all ## have the same suffix, like '.sh', '.ksh', or '.bsh' or whatever. ## (This avoids having to do a lot of extra processing, say using ## a 'file' command, to determine the files that are scripts and ## displaying, or accepting-selection-of, only those files.) ## ## This utility is initialized to a mask of '*.sh' under the assumption ## that all the 'Nautilus scripts' will have a suffix of '.sh'. But ## that mask can be changed in a 'set DIRFILmask' statement at the ## bottom of this 'script-selector' script. ## ## A script is selected by clicking on a filename in the right-hand, ## files-listbox. (Using the Ctrl and Shift keys to select more than ## one script is not supported in the 'script-selector' GUI.) ## ## Unlike the 'file(s)-selector' Tk script GUI, this 'script-selector' ## Tk script GUI does NOT provide a 'Jump2dir' button --- because the ## user is typically not going to want to 'jump' to another ## directory hierarchy when using this 'script-selector' GUI. ## ## 'Hidden' (dot prefixed) directories and files could be shown in ## the two listboxes --- we could choose not to hide them. ## ## A message in the GUI window indicates to the user the main options: ## - Navigate-dirs (click in the left listbox) ## - Select-a-script (click in the right listbox) ## - Run-the script (click on the 'UseIt' button) ## ## NOTE: Actually this Tk script does NOT run the selected script. ## This Tk script writes the script-name to 'stdout' and thus ## passes the scriptname back to the calling Tk script. ## The calling 'file(s)-selector' Tk script executes the selected ## shell script, with the selected filename(s) as arguments. ## ## In addition, the user can ## - show Help (click on the 'Help' button) ## - Cancel (click on the 'Cancel' button) ## ## The options available to the user in this implmentation ## are indicated by the following 'sketch' of the GUI: ## ## --------------------------------------------------------------------- ## ## THE SKETCH CONVENTIONS for GUI sketch below: ## ## SQUARE-BRACKETS indicate a comment not to be included on the GUI. ## BRACES indicate a Tk 'button' widget. ## UNDERSCORES indicate a Tk 'entry' widget. ## A COLON indicates that the text before the colon is on ## a 'label' widget. ## CAPITAL-O indicates a Tk 'radiobutton' widget. ## CAPITAL-X indicates a Tk 'checkbutton' widget. ## ## ---------------------------------------------------------------------------------------- ## Script Selector - verYYYYMMMDD ## [window title] ## ---------------------------------------------------------------------------------------- ## ## TopLevel Frame ## and SubFrame ## names ## | ## V ## ## .fRdirmaskHead CURRENT DIRECTORY & FILE MASK: ## ## .fRdirfilmask $env(HOME)/.gnome2/nautilus-scripts/*.sh________________________________ ## ## .fRlists [This 'fRlists' frame is to contain two subframes --- 'fRdir' and 'fRfil' --- ## with 'fRdir' on the left of 'fRfil'.] ## ## .fRlists.fRdir This frame is to contain a listbox with x-and-y scrollbars. ## This frame is also to contain a heading (in a label) above the listbox. ## ## .fRlists.fRfil This frame is to contain a listbox with x-and-y scrollbars. ## This frame is also to contain a heading (in a label) above the listbox. ## ## .fRscriptHead SCRIPT SELECTION: ## ## .fRscriptSel __________________________________________________ ## ## .fRcntlbutts1 {UseIt} {Cancel} {Help} {Refresh} ## ## .fRcntlbutts2 {naroDir} {wideDir} {naroFil} {wideFil} {tallWin} {shortWin} ## ## .fRstatusmsg Click on a Script (on the right) and click 'UseIt' -OR- Click on a Dir (on ## the left) to Navigate -OR- Cancel. ## ## [This initial message in a text widget may be changed in response to various ## user actions on the GUI --- directory selection, etc.] ## ##+############## ## GUI components: ## ## From the GUI 'sketch' above, it is seen that the GUI consists of ABOUT: ## ## 10 'button' widgets ## 5 'label' widgets (mostly for headings) ## 2 'entry' widgets (for the current-directory-and-file-mask and for selected-script) ## 2 'listbox' widgets (with scrollbars) ## 1 'text' widget ## 0 'checkbutton' widgets ## 0 'radiobutton' widgets ## 0 'scale' widgets ## 0 'canvas' widgets ## ##+############################### ## NOTE on the 'CURRENT DIRECTORY': ## ## This script does not change the 'current-working-directory' (with the ## Tcl 'cd' command) at any point in processing user actions, such as ## during directory navigation. ## ## This script is intended to simply write the fully-qualified filename ## of the selected script to 'stdout'. ## ## There is no need to change the CWD (current working directory) in ## the process of navigating to and selecting the 'Nautilus' shell script. ## ##+######################################################################## ## NOTES on 'PLATFORMS' (operating systems): ## ## The Tcl 'glob' command is used to get the filenames --- both ## directory names and 'regular' file names --- to fill the 2 listboxes ## of this 'script-selector' GUI. ## ## Furthermore, Tcl 'file' commands, such as ## ## file type $file (Returns: file, directory, characterSpecial, ## blockSpecial, fifo, link, OR socket) ## file readlink $file (Good for finding the target of a link.) ## file pathtype $file (Returns: relative, absolute, OR volumerelative) ## file exists $file ## ## are used to get the directory names and 'regular' file names for ## the current directory specified at the top of the GUI. ## ## Although there are typically no 'symbolic links' in a Nautilus ## scripts directory structure, we use 'fill_lists' code like that ## in the 'file(s)-selector' Tk script --- with the intent of trying ## to handle 'link' files as well as 'directory' and 'file' files --- ## even if a link is 'broken' (pointing to a file that no longer exists). ## ## With these factors in mind, this 'tkScriptApplicator' mini-system ## utility will probably support a variety of Linux and Unix hosts ## (most Linux distros, BSD flavors, HP-UX, IBM-AIX, Sun-Solaris, ## etc. --- and probably the Apple Mac OS, since it is BSD-based). ## ## Note that a main requirement is that the 'Nautilus' scripts (that ## are to be applied to the selected files) are available and run on ## the user's operating system. ALSO, any utility programs called by ## those shell scripts need to be available on the the user's ## operating system and need to be runnable on that operating system. ## ## So the nature of the 'Nautilus' scripts is a key factor in ## determining on which operating systems this 'tkScriptApplicator' ## mini-system can be run. ## ##+########################### ## NOTE on 'SYMBOLIC LINKS': ## ## With respect to the Tcl 'file' statements used in this ## 'file(s)-selector' Tk script, an example of how the listbox-filling ## code could be constructed can be seen in the 'dirview' script on ## pages 229-234 of the first edition of the book ## 'Graphical Applications with Tcl & Tk' (1996) by Eric F. Johnson. ## ## However, that code needs quite a bit of enhancement to handle ## 'symbolic-links' robustly (whether they are broken or intact). ## ## This Tk script-system is being released in 2014jul in a preliminary ## form that is intended to handle 'symbolic links' in a robust fashion. ## ## Some testing has been done --- especially with the 'file(s)-selector' ## Tk script --- in an attempt to implement 'robust navigation' of ## symbolic-links to directories --- even when the links are 'broken' (not ## pointing to an existing directory anymore). ## ## (The 'file(s)-selector' and 'script-selector' GUI's could notify the user ## of 'broken links' that are encountered. But that has not been done in ## the 2014jul release. Broken links are simply not shown in the listboxes.) ## ## Navigating directories that are symbolic-links will typically not be ## an issue, because the 'file(s)-selector' Tk script is usually selecting ## files from a user's home directory, and the user is not typically making ## 'symbolic links' in the various sub-directories of his/her home ## directory. ## ## Furthermore, navigating symbolic-links will typically not be an issue for ## the 'script-selector' Tk script, because the sub-directories containing ## the 'Nautilus' shell scripts are typically not symbolic-links. ## ## HOWEVER, there are times when it may be nice to make a symbolic link for ## a directory --- for example, to point to a directory with a longer name, ## that is, with many more directory levels. ## ## If it turns out that there is a type of symbolic-link (for example, ## a symbolic-link that points to a series of symbolic-links, with relative ## and/or absolute paths) that is not handled successfully/properly, ## note that the user may work around this issue by navigating to the ## actual target of a 'symbolic link'. ## ##+######################################################################## ## STRUCTURE OF THIS CODE: ## ## 0) Set general window & widget parms (win-name, win-position, ## win-color-scheme, fonts, widget-geom-parms, text-array-for-labels-etc, ## win-size-control). ## ## 1a) Define ALL frames (& sub-frames, if any). ## 1b) Pack the frames. ## ## 2) Then define & pack all widgets in the frames -- frame by frame. ## After all the widgets for a frame are defined, pack them in the frame. ## ## 3) Define keyboard and/or mouse/touchpad/touch-sensitive-screen 'event' ## BINDINGS, if needed. ## 4) Define PROCS, if needed. ## 5) Additional GUI INITIALIZATION (typically with one or more of ## the procs), if needed. ## ## In more detail, for this particular Tk script: ## ## 1a) Define ALL frames -- and sub-frames: ## ## '.fRdirmaskHead' to hold a label widget. ## ## '.fRdirfilmask' to hold an entry widget. ## ## '.fRlists' to contain the following two subframes --- 'fRdir' and 'fRfil' --- ## with 'fRdir' on the left of 'fRfil'. ## ## '.fRlists.fRdir' to contain a listbox with x-and-y scrollbars --- ## with a label widget above the listbox. ## ## '.fRlists.fRfil' to contain a listbox with x-and-y scrollbars --- ## with a label widget above the listbox. ## ## '.fRscriptHead' to hold a label widget. ## ## '.fRscriptSel' to hold an entry widget. ## ## '.fRcntlbutts1' to contain about 4 button widgets. ## ## '.fRcntlbutts2' to contain about 6 button widgets. ## ## '.fRstatusmsg' to contain a label widget. ## ## This is about 8 top-level frames. ## Most of these toplevel-frames are 1 character high. ## Exceptions: '.fRlists' and '.fRstatusmsg' ## ## 1b) Pack ALL these frames and sub-frames. ## ## 2) Define & pack all widgets in the frames -- basically going through ## frames & their interiors in top-to-bottom and/or left-to-right order. ## ## 3) Define BINDINGS. See BINDINGS section below. ## ## SOME examples: ## - Enter key press in DirFilMask entry field (run 'fill_lists' proc) ## - Single-click (button release) on dir-listbox (run 'navigate' proc) ## - Single-click (button release) on fil-listbox (run 'get_selected_file' proc) ## - Enter key press in ScriptSelection entry field (run 'put_var_exit' proc) ## ## 4) Define PROCS. See the PROCS section below. ## ## SOME examples: ## ## 'fill_lists' - fills the 2 listboxes based on the current dir and mask. ## 'navigate' - chgs ref-dir & runs 'fill_lists'. ## 'get_selected_file' - uses selected rel-filename to set FULFILname. ## 'set_status_msg' - puts a message in the StatusMsg label. ## 'put_var_exit' - puts $FULFILname to stdout and exits. ## ## And for the 6 'window-size' buttons: ## 'dir_listbox_width_increase' ## 'dir_listbox_width_reduce' ## 'fil_listbox_width_increase' ## 'fil_listbox_width_reduce' ## 'tall_win' ## 'short_win' ## ## 5) ADDITIONAL GUI INITIALIZATION section. ## See this section at the bottom of this script. ## ##+##################################################################### ## OUTPUT: ## A single, fully-qualified filename to standard out. ## If no script is selected (Cancel button or user Closes window), ## nothing is sent to stdout. ## ## In a script calling this Tk script, the programmer would typically ## capture stdout in a variable like SCRIPTNAME and, if SCRIPTNAME were ## null, typically do nothing with SCRIPTNAME or exit the application. ## ## See the 'CALL FORMAT' section below for an example of this script ## setting SCRIPTNAME. ## ##+######################################################################## ## CALL FORMAT: ## (Here are two examples -- one in a Tcl-Tk script and one in a ## Linux/Unix shell script.) ## ##----------------------- ## EXAMPLE1 (in Tk script): ##----------------------- ## ## set SCRIPTname [ $DIRscripts/scriptSelector_2listboxes.tk ] ## ## if { "$SCRIPTname" == "" } { ## return (or some other processing) ## } ## ## exec $SCRIPTname ... filenames ... ## ##--------------------------- ## EXAMPLE2 (in shell script): ##--------------------------- ## ## SCRIPTNAME=`$DIR_SCRIPTS/scriptSelector_2listboxes.tk` ## ## if test "$SCRIPTNAME" = "" ## then ## exit (or some other processing) ## fi ## ## $SCRIPTNAME ... filenames ... ## ##+##################################################################### ## MAIN INTERNAL (GLOBAL & LOCAL) VARS: ## ## DIRFILmask Set initially to a 'base' scripts directory name, with ## a files mask such as '*' or '*.sh'. Each time there is a ## single click on a subdir name, the directory portion of ## this DIRFILmask var is changed, while the mask portion ## is not changed. ## ## CURdir Extracted when needed from DIRFILmask. ## ## FILmask Holds the mask, '*' OR '*.sh' OR whatever. ## ## RELDIRsel Extracted from 'dir' listbox, in the ## 'navigate' proc. (Should NOT contain an ## ending '/' (slash), nor preceding slashes. ## No slashes at all.) ## ## FULFILname Set from file-listbox, in 'get_selected_file' proc. ## ## NOTE: In various parts of this script, at places indicated by a ## '## FOR TESTING:' line, there are commented 'puts' statements ## to help in development and testing. In particular, ## there are commented 'puts' statements in the 'fill_lists' proc ## (and procs that it calls) that can be uncommented to test/verify ## the settings of the various 'dir' and 'fil' (and 'mask') vars ## in various navigation scenarios. ##+##################################################################### ## WIDGET NAMING CONVENTION: ## ## In this script, in a widget hierarchy, the names of ## ## frames are prefixed by 'fR' ## buttons are prefixed by 'butt' or 'but' ## labels are prefixed by 'lab' or 'label' ## entry-boxes are prefixed by 'ent' or 'entry' ## listboxes are prefixed by 'listbox' or 'lbox' ## scrollbars are prefixed by 'scrbar' ## text are prefixed by 'text' ## ## Although not used in this script, conventions for other widgets: ## ## radio-buttons are prefixed by 'radbutt' or 'radbut' ## check-buttons are prefixed by 'chkbutt' or 'chkbut' ## ## A 'generic' example for an entry widget and its parent frames: ## .fRtop.fRdir.entDir ##+######################################################################## ## NOTE ON SEPARATING CODE FROM COMMENTS: ## ## You can see only the non-commented, executable lines of this ## script by using ## egrep -v '^ *##|^ *# ' ## or ## grep -v '^ *##' | grep -v '^ *# ' ## ## OR, extract most of the comments with ## egrep '^ *##|^ *# ' ## ##+####################################################################### ## DEVELOPED WITH: Tcl-Tk 8.5 on Ubuntu 9.10 (2009-october, 'Karmic Koala') ## ## $ wish ## % puts "$tcl_version $tk_version" ## ## showed ## 8.5 8.5 ## but this script should work in most previous 8.x versions, and probably ## even in some 7.x versions (if font handling is made 'old-style'). ##+######################################################################## ## MAINTENANCE HISTORY: ## Started by: Blaise Montandon 2014jul18 Started developing this script ## and auxiliary Tk scripts ## based on similar FE scripts from ## the 'feHappyScripts' system. ## Started putting code in the ## 'fill_lists' proc. ## Changed by: Blaise Montandon 2014jul27 Replaced an 'ls -Ap' technique ## by a 'glob' technique. ## Changed by: Blaise Montandon 2014jul29 A cleanup pass on this script. ##+######################################################################## ## HEY, ME! ## IF YOU UPDATE THIS SCRIPT, REMEMBER TO CHANGE THE FOLLOWING VERSION ID!!! ##+######################################################################## ## For window title: set VERSIONfilesel "ver2014jul29" ##+###################################################### ## Set WINDOW TITLE and POSITION. ##+###################################################### wm title . \ "Script-Selector - $VERSIONfilesel" wm iconname . "ScriptSelector" wm geometry . +30+45 ##+###################################################### ## Set the COLOR SCHEME for the window and its widgets --- ## such as listbox and entry field background color. ##+###################################################### tk_setPalette "#e0e0e0" # set headBKGD "#b0b0b0" # set headBKGD "#99ff99" set entryBKGD "#ffffff" set listboxBKGD "#ffffff" # set STATUSmsgBKGD "#f0f0f0" set STATUSmsgBKGD "#ff9999" # set radbuttBKGD "#c0c0c0" # set chkbuttBKGD "#c0c0c0" # set scaleBKGD "#f0f0f0" ##+######################################################## ## DEFINE (temporary) FONT NAMES. ## ## We use a VARIABLE-WIDTH font for text on LABEL and ## BUTTON widgets. ## ## We use a FIXED-WIDTH font for LISTBOX lists, ## for text in ENTRY fields --- and often for text in ## TEXT widgets. ## ## 'weight' can be 'bold' or 'normal'. ## 'slant' can be 'roman' or 'italic'. ##+######################################################## font create fontTEMP_varwidth \ -family {comic sans ms} \ -size -12 \ -weight normal \ -slant roman font create fontTEMP_SMALL_varwidth \ -family {comic sans ms} \ -size -10 \ -weight normal \ -slant roman ## Some possible (similar) variable width fonts: ## Arial ## Bitstream Vera Sans ## Comic Sans MS ## DejaVu Sans ## Droid Sans ## FreeSans ## Liberation Sans ## Nimbus Sans L ## Trebuchet MS ## Verdana font create fontTEMP_fixedwidth \ -family {droid sans mono} \ -size -12 \ -weight normal \ -slant roman font create fontTEMP_SMALL_fixedwidth \ -family {droid sans mono} \ -size -10 \ -weight normal \ -slant roman ## Some possible fixed width fonts (esp. on Linux): ## Andale Mono ## Bitstream Vera Sans Mono ## Courier 10 Pitch ## DejaVu Sans Mono ## Droid Sans Mono ## FreeMono ## Liberation Mono ## Nimbus Mono L ## TlwgMono ##+########################################################### ## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS. ## (e.g. width and height of canvas, and padding for Buttons) ##+########################################################### ## Some WINDOW-MANAGER BORDER width settings: ## (We could try to set these parameters via a re-usable proc ## that uses the 'wm' and 'winfo' commands. But that may not ## work for all window managers and operating systems. ## So we simply set the values here.) set wmPIXELS_left 3 set wmPIXELS_top 23 ## LABEL widget geom settings: set PADXpx_label 0 set PADYpx_label 0 set BDwidthPx_label 2 set RELIEF_label_lo "flat" ## BUTTON widget geom settings: set PADXpx_button 0 set PADYpx_button 0 set BDwidthPx_button 2 ## We use '-relief raised' for all 'button' widgets. ## ENTRY widget geom settings: set BDwidthPx_entry 2 ## We use '-relief sunken' for all 'entry' widgets. ## LISTBOX widget geom settings: set initWIDTHchars_dir_listbox 25 ## This width was set so that the label at the top of ## the listbox is not clipped. set initWIDTHchars_fil_listbox 85 ## This width was set to accomodate the long script filenamse ## in some FE NautilusScripts directories, such as 'AUDIOtools'. set initHEIGHTchars_fil_listbox 15 set minHEIGHTchars_fil_listbox 1 set BDwidthPx_listbox 2 ## We use '-relief sunken' for the 'listbox' widget. ## TEXT widget geom settings: set BDwidthPx_text 2 # set RELIEF_numtext "ridge" ## We nullify the following settings. NOT USED, yet. if {0} { ## RADIOBUTTON widget geom settings: set PADXpx_radbutton 0 set PADYpx_radbutton 0 set BDwidthPx_radbutt 2 set RELIEF_radbutt_hi "raised" ## CHECKBUTTON widget geom settings: set PADXpx_chkbutton 0 set PADYpx_chkbutton 0 set BDwidthPx_chkbutt 2 set RELIEF_chkbutt_hi "raised" ## SCALE widget geom parameters: # set BDwidthPx_scale 2 # set scaleThicknessPx 10 } ## END OF if {0} (to nullify these settings) ##+#################################################################### ## Set a TEXT-ARRAY to hold text for buttons & labels on the GUI. ## NOTE: This can aid INTERNATIONALIZATION. This array can ## be set according to a nation/region parameter. ##+#################################################################### ## if { "$VARlocale" == "en"} ## For the 'fRdirfilmask' frame: set aRtext(labCurDirMask) "CURRENT DIRECTORY & FILE MASK:" ## For the 'fRlists.fRdir' frame: set aRtext(labListSubdirs) \ "Parent Dir \[..\] & N Sub-Dirs \[ Navigate = Single-Click \]" ## For the 'fRlists.fRfil' frame: set aRtext(labListFiles) \ "N Files \[ Select = Single-Click \]" ## For the 'fRscriptHead' frame: set aRtext(labScrSelection) "SCRIPT SELECTION:" ## For the 'fRcntlbutts1' frame: set aRtext(buttOK) "UseIt" set aRtext(buttCancel) "Cancel" set aRtext(buttHelp) "Help" set aRtext(buttFilter) "Refresh" set aRtext(buttFontSize) "TogFontSize" set aRtext(YbarsSIDE) "<-Ybars->" ## For the 'fRcntlbutts2' frame: set aRtext(buttDirListLeft) "naroDir" set aRtext(buttDirListRight) "wideDir" set aRtext(buttFilListLeft) "naroFil" set aRtext(buttFilListRight) "wideFil" set aRtext(buttTallWin) "tallWin" set aRtext(buttShortWin) "shortWin" ## For the 'fRstatusmsg' frame: set aRtext(filledSTATUSmsg) \ "Click on a Script (on the right) and click 'UseIt' -OR- Click on a Dir (on the left) to Navigate -OR- Cancel." set aRtext(twolineSTATUSmsg) \ "Select-File(s)-and-Apply-a-Script -OR- Select-Subdir-to-Navigate -OR- Jmp2dir -OR- Exit." set aRtext(unfilledSTATUSmsg) \ "If 'Current-Directory-and-FileMask' is OK, click the 'Refresh' button to fill the two listboxes. Then click on a Script (on the right) and click 'UseIt' -OR- Cancel." set aRtext(maskExamplesSTATUSmsg) \ "If the Directory-and-File-Mask is OK, **CLICK 'Refresh' TO START**. Examples of valid file masks: * (all files) OR *.sh OR *CROP*.sh" ## END OF if { "$VARlocale" == "en"} ##+###################################################################### ## Set a MIN-SIZE of the window (roughly). ## ## For WIDTH, allow for a min-width for the side-by-side sub-directories ## and files listboxes. ## ## For HEIGHT, allow for the stacked frames: ## 1 char high for the '.fRdirmaskHead' frame ## 1 char high for the '.fRdirfilmask' frame ## N chars high for the '.fRlists' frame ## 1 char high for the '.fRscriptHead' frame ## 1 char high for the '.fRscriptSel' frame ## 1 char high for the '.fRcntlbutts1' frame ## 1 char high for the '.fRcntlbutts2' frame ## 2 chars high for the '.fRstatusmsg' frame ## where N = $minHEIGHTchars_fil_listbox + 3 chars, where ## 3 chars allows for a 2-line label above the listboxes and ## the horizontal scrollbar of the 2 listboxes. ##+##################################################################### ## FOR WIDTH: ## We set the min-width according to character units. ## We allow for about 10 characters minimum for the directories ## listbox and about 20 chars minimum for the files listbox: set charWidthPx [font measure fontTEMP_varwidth "W"] set DIRminwidthPX [expr {10 * $charWidthPx}] set FILminwidthPX [expr {20 * $charWidthPx}] set minWinWidthPx [expr {$DIRminwidthPX + $FILminwidthPX}] ## We will use the DIRminwidthPX,FILminwidthPX vars in ## some procs below for the 'naroDir' and 'naroFil' buttons. ##+################################################# ## For HEIGHT --- for ## 1 char high for the '.fRdirmaskHead' frame ## 1 char high for the '.fRdirfilmask' frame ## N chars high for the '.fRlists' frame ## 1 char high for the '.fRscriptHead' frame ## 1 char high for the '.fRscriptSel' frame ## 1 char high for the '.fRcntlbutts1' frame ## 1 char high for the '.fRcntlbutts2' frame ## 2 chars high for the '.fRstatusmsg' frame ## -------- ## 8+N chars high for the 8 frames ## where N = $minHEIGHTchars_fil_listbox + 3 chars, where ## 3 chars allows for a 2-line label above the listboxes and ## allows (roughly) for the horizontal scrollbar of the 2 listboxes. ##+################################################# set charHeightPx [font metrics fontTEMP_varwidth -linespace] set minWinHeightPx [expr {(11 + $minHEIGHTchars_fil_listbox) * $charHeightPx}] ## Add about 25 pixels for top-bottom window decoration -- ## and some pixels for top-and-bottom of frame/widget borders ## (~8 widgets x 4 pixels/widget = 32 pixels). set minWinHeightPx [expr {57 + $minWinHeightPx}] ## FOR TESTING: # puts "minWinWidthPx = $minWinWidthPx" # puts "minWinHeightPx = $minWinHeightPx" wm minsize . $minWinWidthPx $minWinHeightPx ## We need to allow the window to be resizable --- ## so that the 'fRdir' and 'fRfil' frames can expand, ## both horizontally and vertically. ## If you want to make the window un-resizable, ## you can use the following statement. # wm resizable . 0 0 ## If you want the window to resize in x-direction, but not y. # wm resizable . 1 0 ##+####################################################################### ##+####################################################################### ## ## DEFINE *ALL* TOP-LEVEL frames -- (top to bottom): ## ## - 'fRdirmaskHead' to contain a label widget ## - 'fRdirfilmask' to contain an entry widget ## - 'fRlists' to contain 'dir' & 'files' frames, side-by-side ## - 'fRscriptHead' to contain a label widget ## - 'fRscriptSel' to contain an entry widget ## - 'fRcntlbutts1' to contain bottom buttons - UseIt,Cancel,Help,... ## - 'fRcntlbutts2' to contain bottom buttons - naroDir,wideDir,...,tallWin,shortWin ## - 'fRstatusmsg' to contain a label widget ## ## Also define the two side-by-side frames within 'lists' -- ## 'fRlists.fRdir' & 'fRlists.fRfil'. ##+####################################################################### ##+####################################################################### set RELIEF_frame flat set BDwidthPx_frame 0 ## FOR TESTING of expansion of frames (esp. during window expansion): # set RELIEF_frame raised # set BDwidthPx_frame 2 frame .fRdirmaskHead -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRdirfilmask -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRlists -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRscriptHead -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRscriptSel -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRcntlbutts1 -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRcntlbutts2 -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRstatusmsg -relief $RELIEF_frame -borderwidth $BDwidthPx_frame ## The two SUB-FRAMES: frame .fRlists.fRdir -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRlists.fRfil -relief $RELIEF_frame -borderwidth $BDwidthPx_frame ##+######################################################## ## PACK *ALL* the top-level FRAMES. ##+######################################################## ## The following direct, top-to-bottom approach ## would be nice, but it does not have ## good control of various frames. ## ## We want 'fRlists' to 'fill y' and y-expand (as well as ## 'fill x' and x-expand) -- but we do not want 'fRdirmaskHead', ## 'fRdirfilmask', 'fRscriptHead', 'fRscriptSel', ## 'fRcntlbutts1', 'fRcntlbutts2', and 'fRstatusmsg' to y-expand. ## ##+######################################################## ## WE WILL HAVE TO PACK THEM IN SUB-GROUPS, *NOT* like this: ## ## pack .fRdirmaskHead \ ## .fRdirfilmask \ ## .fRlists \ ## .fRscriptHead \ ## .fRscriptSel \ ## .fRcntlbutts1 \ ## .fRcntlbutts2 \ ## .fRstatusmsg \ ## -side top \ ## -anchor nw \ ## -fill both \ ## -expand 0 ## ##+######################################################## ##+######################################################## ## We want the following for the 'fRlists.fRdir' & ## 'fRlists.fRfil' SUB-frames: ## -fill both -expand 1 ## so that the listboxes within these frames can expand. ##+######################################################## ## GENERAL 'pack' RULE FOR A LISTBOX & ITS SCROLLBARS: ## ## To allow a listbox to expand-xy ## and its y-scrollbar to expand-y ## and its x-scrollbar to expand-x, ## ## any 'parent'-frames containing these widgets ## should use parms: ## -fill both -expand 1 ## ## For packing the widgets themselves, we use: ## y-scrollbar: -fill y -expand 0 ## x-scrollbar: -fill x -expand 0 ## listbox: -fill both -expand 1 ## The order of packing these widgets is important. ## See comments below, where these widgets are packed. ##+######################################################## ##+####################################################### ## PACK 'fRdirmaskHead' & 'fRdirfilmask' FRAMEs -- ## at TOP of window. ##+####################################################### ## DO NOT USE '-expand 1' HERE. ## THAT WOULD ALLOW these FRAMES TO Y-EXPAND. ##+####################################################### pack .fRdirmaskHead \ .fRdirfilmask \ -side top \ -anchor nw \ -fill x \ -expand 0 ##+############################################################ ## PACK 'fRscriptHead' & 'fRscriptSel' & ## 'fRcntlbutts1' & 'fRcntlbutts2' & 'fRstatusmsg' FRAMEs ## at BOTTOM of window. ##+############################################################ ## DO NOT USE '-expand 1' HERE; THAT WOULD KEEP THE ## 'fRlists' LISTBOX FRAME FROM Y-EXPANDING fully. ##+############################################################ pack .fRstatusmsg \ .fRcntlbutts2 \ .fRcntlbutts1 \ .fRscriptSel \ .fRscriptHead \ -side bottom \ -anchor sw \ -fill x \ -expand 0 ##+################################################################# ## PACK 'fRlists' FRAME -- ## *UNDER* 'fRdirmaskHead' & 'fRdirfilmask' FRAMEs ## AND ## *OVER* 'fRscriptHead' & 'fRscriptSel' & ## 'fRcntlbutts1' & 'fRcntlbutts2' & 'fRstatusmsg' & FRAMEs. ##+################################################################ ## NOTE: We pack the 'fRlists' frame AFTER the bottom 3 frames, ## to keep the bottom 3 frames from 'scrunching up' ## when the user grabs the bottom edge of the window ## and moves it up. I.e. we want to make the 'fRlist' frame ## scrunch up before the bottom 3 frames scrunch up. ##+############################################################ pack .fRlists \ -side top \ -anchor nw \ -fill both \ -expand 1 ##+############################################################## ## PACK THE two SUB-FRAMES of the 'fRlists' FRAME -- ## 'fRdir' and 'fRfil'. ##+############################################################## ## '-fill both' AND '-expand 1' ## SHOULD BE USED HERE, TO ALLOW THE LISTBOX IN '.fRlists.fRdir' ## and THE LISTBOX IN '.fRlists.fRfil' TO FILL AND XY-EXPAND. ##+############################################################## pack .fRlists.fRdir \ -side left \ -anchor nw \ -fill both \ -expand 1 pack .fRlists.fRfil \ -side left \ -anchor nw \ -fill both \ -expand 1 ##+################################################################ ##+################################################################ ## START DEFINING & PACKING WIDGETS WITHIN THEIR FRAMES. ##+################################################################ ##+################################################## ## IN THE 'fRdirmaskHead' FRAME -- ## DEFINE a LABEL WIDGET. THEN PACK IT. ##+################################################## label .fRdirmaskHead.lab \ -text "$aRtext(labCurDirMask)" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd 0 pack .fRdirmaskHead.lab \ -side top \ -anchor nw \ -fill none \ -expand 0 ##+################################################## ## IN THE 'fRdirfilmask' FRAME -- ## DEFINE an ENTRY WIDGET. THEN PACK IT. ##+################################################## entry .fRdirfilmask.entryDIRFILmask \ -textvariable DIRFILmask \ -font fontTEMP_fixedwidth \ -relief sunken \ -borderwidth $BDwidthPx_entry \ -bg $entryBKGD ## Protect the refdir-and-mask from 'direct' change by the user. ## The user changes the directory here by clicking on the 'dirs' listbox. .fRdirfilmask.entryDIRFILmask config -state disabled .fRdirfilmask.entryDIRFILmask config -disabledbackground "#ccffcc" .fRdirfilmask.entryDIRFILmask config -disabledforeground "#999999" ## Pack the widget in frame '.fRdirfilmask'. pack .fRdirfilmask.entryDIRFILmask \ -side left \ -anchor w \ -fill x \ -expand 1 ##+############################################################### ## USE '-fill x' ONLY IF YOU WANT WIDGETS (like entry) TO FILL OUT ## THE ENTIRE 'fRdirfilmask' FRAME (for a very wide entry field). ## We use '-fill x' on this entry widget, but NOT on button widgets ## and NOT on label widgets that precede a widget like an entry widget. ## ## YOU CAN USE '-expand 1' TO ALLOW SOME WIDGETS (like entry) ## TO SPREAD OUT. THEN YOU NEED TO BE SURE TO USE '-expand 0' IN ## PARENT FRAMES, like 'fRdirfilmask', TO KEEP WIDGETS (button, ## entry, and most label widgets) FROM Y-EXPANDING. ##+############################################################### ##+#################################################################### ## In the 'fRlists.fRdir' FRAME -- DEFINE WIDGETS: ## - LABEL (to be packed at top) ## - SCROLLBAR-Y and LISTBOX (to be left-to-right) ## - SCROLLBAR-X (to be at bottom). ## THEN PACK THEM. ##+#################################################################### ## NOTE: Set 'selectmode' of dir-listbox to 'single'. ##+#################################################################### label .fRlists.fRdir.lab \ -text "$aRtext(labListSubdirs)" \ -font fontTEMP_varwidth \ -justify left \ -width $initWIDTHchars_dir_listbox \ -anchor w \ -relief flat \ -bd 0 listbox .fRlists.fRdir.listbox \ -width $initWIDTHchars_dir_listbox \ -font fontTEMP_fixedwidth \ -relief sunken \ -borderwidth $BDwidthPx_listbox \ -bg $listboxBKGD \ -selectmode single \ -yscrollcommand ".fRlists.fRdir.scrbary set" \ -xscrollcommand ".fRlists.fRdir.scrbarx set" scrollbar .fRlists.fRdir.scrbary \ -orient vertical \ -command ".fRlists.fRdir.listbox yview" scrollbar .fRlists.fRdir.scrbarx \ -orient horizontal \ -command ".fRlists.fRdir.listbox xview" ##+################################################# ## PACK all the widgets in frame 'fRlists.fRdir' --- ## lab, scrbarx,scrbary,listbox -- in that order. ##+################################################# ## DO NOT USE '-expand 1' for the X-SCROLLBAR. ## THAT WOULD KEEP THE LISTBOX FROM Y-EXPANDING. ##+################################################# ## DO NOT USE '-expand 1' for Y-SCROLLBAR. ## THAT WOULD ALLOW the Y-SCROLLBAR TO X-EXPAND, WHICH ## PUTS BLANK SPACE BETWEEN Y-SCROLLBAR & ITS LISTBOX. ##+################################################# pack .fRlists.fRdir.lab \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRlists.fRdir.scrbarx \ -side bottom \ -anchor sw \ -fill x \ -expand 0 pack .fRlists.fRdir.scrbary \ -side left \ -anchor nw \ -fill y \ -expand 0 ##+################################################### ## NOTE: WE PACK THE SCROLL BARS BEFORE THE LISTBOX. ## THE LISTBOX WOULD TAKE ALL THE FRAME-SPACE, ## WITH '-fill both -expand 1'. ##+################################################### pack .fRlists.fRdir.listbox \ -side left \ -anchor nw \ -fill both \ -expand 1 ##+#################################################################### ## In the 'fRlists.fRfil' FRAME -- DEFINE WIDGETS: ## - label (to be packed at top) ## - listbox and scrollbar-y (to be packed left-to-right) ## - scrollbar-x (to be packed at bottom). ## THEN PACK THEM. ##+#################################################################### ## NOTE: Set 'selectmode' of fil-listbox to 'single', rather than ## 'extended'. We want to select only one script at a time. ##+#################################################################### label .fRlists.fRfil.lab \ -text "$aRtext(labListFiles)" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd 0 listbox .fRlists.fRfil.listbox \ -width $initWIDTHchars_fil_listbox \ -height $initHEIGHTchars_fil_listbox \ -font fontTEMP_fixedwidth \ -relief sunken \ -borderwidth $BDwidthPx_listbox \ -bg $listboxBKGD \ -selectmode single \ -yscrollcommand ".fRlists.fRfil.scrbary set" \ -xscrollcommand ".fRlists.fRfil.scrbarx set" ##+####################################################### ## We specify an initial HEIGHT of the 'fil' listbox. ## That height (in conjunction with '-fill' and -expand' ## pack parameters) determines the height of the 'dir' listbox ## as well as the height of the 'fil' listbox. ##+####################################################### scrollbar .fRlists.fRfil.scrbary \ -orient vertical \ -command ".fRlists.fRfil.listbox yview" scrollbar .fRlists.fRfil.scrbarx \ -orient horizontal \ -command ".fRlists.fRfil.listbox xview" ##+############################################### ## PACK all the widgets in frame 'fRlists.fil' --- ## label, scrbarx,scrbary,listbox -- in that order. ##+############################################### ## DO NOT USE '-expand 1' for the X-SCROLLBAR. ## THAT WOULD KEEP THE LISTBOX FROM Y-EXPANDING ##+############################################### ## DO NOT USE '-expand 1' for the Y-SCROLLBAR. ## THAT WOULD ALLOW Y-SCROLLBAR TO X-EXPAND, which ## PUTS BLANK SPACE BETWEEN Y-SCROLLBAR & ITS LISTBOX. ##+############################################### pack .fRlists.fRfil.lab \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRlists.fRfil.scrbarx \ -side bottom \ -anchor sw \ -fill x \ -expand 0 pack .fRlists.fRfil.scrbary \ -side left \ -anchor nw \ -fill y \ -expand 0 ##+################################################### ## NOTE: PACK THE SCROLL BARS BEFORE THE LISTBOX. ## THE LISTBOX WOULD TAKE ALL THE FRAME-SPACE, ## WITH '-fill both -expand 1'. ##+################################################### pack .fRlists.fRfil.listbox \ -side left \ -anchor nw \ -fill both \ -expand 1 ##+########################################### ## In the 'fRscriptHead' FRAME -- ## DEFINE a LABEL WIDGET. THEN PACK IT. ##+########################################### label .fRscriptHead.lab \ -text "$aRtext(labScrSelection)" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd 0 pack .fRscriptHead.lab \ -side top \ -anchor nw \ -fill x \ -expand 0 ##+########################################### ## In the 'fRscriptSel' FRAME -- ## DEFINE an ENTRY WIDGET. THEN PACK IT. ##+########################################### entry .fRscriptSel.entry \ -font fontTEMP_fixedwidth \ -textvariable FULFILname \ -relief sunken \ -borderwidth $BDwidthPx_entry \ -bg $entryBKGD pack .fRscriptSel.entry \ -side top \ -anchor nw \ -fill x \ -expand 1 ##+############################################# ## In the 'fRcntlbutts1' FRAME -- ## DEFINE some BUTTON WIDGETS: ## 'OK/UseIt', 'Cancel', 'Help', 'Refresh', etc. ## THEN PACK THEM. ##+############################################# button .fRcntlbutts1.buttOK \ -text "$aRtext(buttOK)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {put_var_exit} button .fRcntlbutts1.buttCancel \ -text "$aRtext(buttCancel)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {exit} button .fRcntlbutts1.buttHelp \ -text "$aRtext(buttHelp)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {popup_msgVarWithScroll .topHELP "$HELPtext"} button .fRcntlbutts1.buttFilter \ -text "$aRtext(buttFilter)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {fill_lists} button .fRcntlbutts1.buttFontSize \ -text "$aRtext(buttFontSize)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {toggle_fontsize} button .fRcntlbutts1.buttYbarsSIDE \ -text "$aRtext(YbarsSIDE)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {toggle_ybars} ##+################################################# ## PACK all the widgets of frame '.fRcntlbutts1'. ## NOTE: You can change the left-to-right order of the ## buttons by changing this packing order. ##+################################################# pack .fRcntlbutts1.buttCancel \ .fRcntlbutts1.buttOK \ .fRcntlbutts1.buttHelp \ .fRcntlbutts1.buttFilter \ .fRcntlbutts1.buttFontSize \ .fRcntlbutts1.buttYbarsSIDE \ -side left \ -anchor w \ -fill none \ -expand 0 ##+############################################### ## In the 'fRcntlbutts2' FRAME -- ## DEFINE about 6 BUTTON WIDGETS: ## 'naroDir', 'wideDir', ..., 'tallWin', 'shortWin' ## THEN PACK THEM. ##+############################################### button .fRcntlbutts2.buttDirListLeft \ -text "$aRtext(buttDirListLeft)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {dir_listbox_width_reduce} button .fRcntlbutts2.buttDirListRight \ -text "$aRtext(buttDirListRight)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {dir_listbox_width_increase} button .fRcntlbutts2.buttFilListLeft \ -text "$aRtext(buttFilListLeft)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {fil_listbox_width_reduce} button .fRcntlbutts2.buttFilListRight \ -text "$aRtext(buttFilListRight)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {fil_listbox_width_increase} button .fRcntlbutts2.buttTallWin \ -text "$aRtext(buttTallWin)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {tall_win} button .fRcntlbutts2.buttShortWin \ -text "$aRtext(buttShortWin)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {short_win} ##+################################################# ## PACK all the widgets in frame '.fRcntlbutts2'. ## NOTE: You can change the left-to-right order of ## the buttons by changing this packing order. ##+################################################# pack .fRcntlbutts2.buttDirListLeft \ .fRcntlbutts2.buttDirListRight \ .fRcntlbutts2.buttFilListLeft \ .fRcntlbutts2.buttFilListRight \ .fRcntlbutts2.buttTallWin \ .fRcntlbutts2.buttShortWin \ -side left \ -anchor w \ -fill none \ -expand 0 ##+####################################### ## In 'fRstatusmsg' FRAME -- ## DEFINE A LABEL WIDGET. THEN PACK IT. ##+####################################### label .fRstatusmsg.lab \ -text "$aRtext(filledSTATUSmsg)" \ -font fontTEMP_fixedwidth \ -justify left \ -anchor w \ -bd $BDwidthPx_label \ -relief raised \ -bg "$STATUSmsgBKGD" pack .fRstatusmsg.lab \ -side top \ -anchor w \ -fill x \ -expand 1 ## Note: ## If frame '.fRstatusmsg' is packed with '-expand 0', that can be ## used to keep the '.fRstatusmsg.lab' widget from y-expanding. ##+##################################################################### ##+##################################################################### ## END OF MAIN SECTION TO SETUP THE GUI. ##+##################################################################### ##+##################################################################### ##+##################################################################### ##+##################################################################### ## DEFINE BINDINGS (to procs): ## ## Fill -and- Navigate(chgdir) -and- Return-key bindings: ## ## - .fRdirfilmask.entryDIRFILmask ('fill_lists') ## (Not used if we disable changes to that entry field.) ## ## - .fRlists.fRdir.listbox ('navigate', which uses 'fill_lists') ## ## - .fRlists.fRfil.listbox ('get_selected_file') ## - .fRscriptSel.entry ('put_var_exit') ## ## Listbox *keyboard*-bindings: ## ## - .fRlists.fRdir.listbox (set focus when mouse enters listbox) ## - .fRlists.fRfil.listbox (set focus when mouse enters listbox) ## ## - .fRlists.fRdir.listbox (go to top of listbox) ## - .fRlists.fRfil.listbox (go to top of listbox) ## - .fRlists.fRdir.listbox (go to bottom of listbox) ## - .fRlists.fRfil.listbox (go to bottom of listbox) ## ## - Listbox (override default behavior) ## - Listbox (override default behavior) ## ## - .fRlists.fRdir.listbox (page up) ## - .fRlists.fRfil.listbox (page up) ## - .fRlists.fRdir.listbox (page down) ## - .fRlists.fRfil.listbox (page down) ## ## - .fRlists.fRdir.listbox (1 line up) ## - .fRlists.fRfil.listbox (1 line up) ## - .fRlists.fRdir.listbox (1 line down) ## - .fRlists.fRfil.listbox (1 line down) ## ##+##################################################################### ##+##################################################################### ##+######################################################### ## .fRdirfilmask.entryDIRFILmask BINDING ##+######################################################### ## PURPOSE: Fills the subdirs & fils listboxes. ## Simply calls the 'fill_lists' proc. ##+######################################################### ## CALLED BY: ## THE USER HITTTING RETURN AFTER EDITING THE DIR&FILE-MASK ## ENTRY FIELD in the '.fRdirfilmask.entryDIRFILmask' widget. ##+######################################################### ## (Not used if we disable changes to that entry field.) ##+######################################################### bind .fRdirfilmask.entryDIRFILmask {fill_lists} ##+########################################################## ## .fRlists.fRdir.listbox BINDING ##+########################################################## ## PURPOSE: Runs the 'navigate' proc, which uses a selected ## subdir and the current 'reference directory' to ## change the 'reference directory' and exec the ## 'fill_lists' proc to refresh the listboxes. ##+######################################################### ## CALLED BY: ## MOUSE-BUTTON-1 IS SINGLE-CLICKED (& released) ## ON A (SUB)DIRECTORY in the ## '.fRlists.fRdir.listbox' widget. ##+########################################################## ## This routine essentially navigates the directory ## structure. It ## 1) resets the DIRFILmask entry ## 2) runs the 'fill_lists' procedure. ##+########################################################## bind .fRlists.fRdir.listbox {navigate} ##+######################################################### ## .fRscriptSel.entry BINDING ##+######################################################### ## PURPOSE: Runs the 'put_var_exit' proc, to return the ## selected filename to the calling application. ##+######################################################### ## 'put_var_exit' should ## 1) write $FULFILname to stdout (if it is a valid name) ## 2) exit ##+######################################################### ## CALLED BY: ## THE USER HITTING RETURN AFTER PASTING/EDITING ## THE CURRENT Script Selection, in the ## '.fRscriptSel.entry' widget. ##+######################################################### bind .fRscriptSel.entry {put_var_exit} ##+############################################################# ## .fRlists.fRfil.listbox BINDING ##+############################################################# ## PURPOSE: Runs the 'get_selected_file' proc, which uses a selected ## relative-filename and the current 'reference directory' ## to build a fully-qualified filename and put that ## name into the 'filselection' entry box. ## ##+############################################################ ## CALLED BY: ## MOUSE-BUTTON-1 IS SINGLE-CLICKED (& released) ## ON A FILE in the '.fRlists.fRfil.listbox' widget. ##+############################################################ bind .fRlists.fRfil.listbox {get_selected_file} ##+################################################################ ## KEYBOARD BINDINGS FOLLOW: ##+################################################################ ##+################################################################ ## all BINDING (not implemented currently) ##+################################################################ ## Executes if THE ESCAPE KEY IS HIT (while cursor is in the window). ##+################################################################ # bind all { # exit # } ##+################################################# ## FOR TESTING KEY-BINDINGS: ## TO SHOW THE 'KEYSYM' FOR A PARTICULAR KEY ## on this system. Uses a binding to the widget ## '.' and event . ##+################################################# ## Reference: the Brent Welch book, 'Practical ## Programming in Tcl and Tk', Chapter 23, 'Binding ## Commands to Events, page 291. ##+################################################# # # bind . { # # ## FOR TESTING: # # puts "In widget '.' : Keysym for key pressed: %K" # # puts "In widget '.' , for a key press :" # puts "Keysym: %K Print-char-and-modifiers: %A" # puts "" # # } # ## END OF BINDING for . ##+######################################################## ## TEST: Show default bindings of .fRlists.fRdir.listbox ## with 'bindtags': ##+################################################# ## Reference: the Brent Welch book, 'Practical ## Programming in Tcl and Tk', Chapter 23, 'Binding ## Commands to Events, page 287. ##+######################################################## ## SHOWS: BINDtags: .fRlists.fRdir.listbox Listbox . all ##+######################################################## # # set BINDtags [ bindtags .fRlists.fRdir.listbox ] # puts ".fRlists.fRdir.listbox BINDtags: $BINDtags" ##+####################################################### ## If it were needed, we could ## OVER-RIDE THE Class 'Listbox' BINDINGS, ## WITH THE BINDINGS WE SET FOR '.fRlists.fRdir.listbox'. ##+####################################################### # bindtags .fRlists.fRdir.listbox [ list .fRlists.fRdir.listbox ] ## OR: # bindtags .fRlists.fRdir.listbox \ # [ list Listbox . .fRlists.fRdir.listbox all ] ##+################################################## ## TEST: Show new bindings with 'bindtags': ##+################################################## # # set BINDtags [ bindtags .fRlists.fRdir.listbox ] # puts ".fRlists.fRdir.listbox BINDtags: $BINDtags" ##+######################################################### ## BINDINGs: ## ## - .fRlists.fRdir.listbox ## - .fRlists.fRfil.listbox ## ## PURPOSE: ## To put keyboard focus into one of these two ## listboxes when the mouse cursor enters it ## --- SO THAT THE FOLLOWING KEYBOARD BINDINGS ## CAN TAKE EFFECT --- for keys: ## Home, End, Prior, Next, up-arrow, down-arrow. ##+######################################################### bind .fRlists.fRdir.listbox { focus .fRlists.fRdir.listbox ## FOR TESTING: # puts "Entered widget: .fRlists.fRdir.listbox" } ## END OF BINDING for .fRlists.fRdir.listbox bind .fRlists.fRfil.listbox { focus .fRlists.fRfil.listbox ## FOR TESTING: # puts "Entered widget: .fRlists.fRfil.listbox" } ## END OF BINDING for .fRlists.fRfil.listbox ##+#################################################### ## key BINDINGs: ## - .fRlists.fRdir.listbox ## - .fRlists.fRfil.listbox ##+#################################################### bind .fRlists.fRdir.listbox { .fRlists.fRdir.listbox see 1 ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRdir.listbox bind .fRlists.fRfil.listbox { .fRlists.fRfil.listbox see 1 ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRfil.listbox ##+#################################################### ## key BINDINGs: ## - .fRlists.fRdir.listbox ## - .fRlists.fRfil.listbox ##+#################################################### bind .fRlists.fRdir.listbox { .fRlists.fRdir.listbox see end ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRdir.listbox bind .fRlists.fRfil.listbox { .fRlists.fRfil.listbox see end ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRfil.listbox ##+#################################################### ## De-activate the default binding for ## Listboxes -- to avoid selecting top entry when ## key is used. ##+#################################################### bind Listbox {} ##+#################################################### ## De-activate the default binding for ## Listboxes -- to avoid selecting bottom entry when ## key is used. ##+#################################################### bind Listbox {} ##+#################################################### ## BINDINGs: (Page-Up key) ## - .fRlists.fRdir.listbox ## - .fRlists.fRfil.listbox ##+#################################################### bind .fRlists.fRdir.listbox { .fRlists.fRdir.listbox yview scroll -1 page ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRdir.listbox bind .fRlists.fRfil.listbox { .fRlists.fRfil.listbox yview scroll -1 page ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRfil.listbox ##+#################################################### ## BINDINGs: (Page-Down key) ## - .fRlists.fRdir.listbox ## - .fRlists.fRfil.listbox ##+#################################################### bind .fRlists.fRdir.listbox { .fRlists.fRdir.listbox yview scroll +1 page ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRdir.listbox bind .fRlists.fRfil.listbox { .fRlists.fRfil.listbox yview scroll +1 page ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRfil.listbox ##+#################################################### ## BINDINGs: (Up-arrow key) ## - .fRlists.fRdir.listbox ## - .fRlists.fRfil.listbox ##+#################################################### bind .fRlists.fRdir.listbox { .fRlists.fRdir.listbox yview scroll -1 unit ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRdir.listbox bind .fRlists.fRfil.listbox { .fRlists.fRfil.listbox yview scroll -1 unit ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRfil.listbox ##+#################################################### ## BINDINGs: (Down-arrow key) ## - .fRlists.fRdir.listbox ## - .fRlists.fRfil.listbox ##+#################################################### bind .fRlists.fRdir.listbox { .fRlists.fRdir.listbox yview scroll +1 unit ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRdir.listbox bind .fRlists.fRfil.listbox { .fRlists.fRfil.listbox yview scroll +1 unit ## FOR TESTING: # puts "Key pressed: %K" } ## END OF BINDING for .fRlists.fRfil.listbox ##+###################################################### ## FOR TESTING: (show current bindings --- ## to bindtags '.fRlists.fRdir' & 'Frame' & '.' & 'all'). ##+###################################################### # # set BINDings [ bind .fRlists.fRdir ] # puts ".fRlists.fRdir BINDings: $BINDings" # # set BINDings [ bind .fRlists.fRdir ] # puts ".fRlists.fRdir BINDings: $BINDings" # # set BINDings [ bind Frame ] # puts "Frame BINDings: $BINDings" # # set BINDings [ bind . ] # puts ". BINDings: $BINDings" # # set BINDings [ bind all ] # puts "all BINDings: $BINDings" ##+################################################################# ##+################################################################# ## END OF mouse/touchpad/touch-sensitive-screen and keyboard BINDINGS ##+################################################################# ##+################################################################# ##+################################################################# ##+################################################################# ## DEFINE PROCEDURES: ## ## 'fill_lists' - fills the dirs and fils listboxes based on ## the current value of $DIRFILmask ## ## 'get_subdirs_inCURdir' - called by 'fill_lists' proc ## 'get_files_inCURdir' - called by 'fill_lists' proc ## ## 'get_selected_file' - uses the selected relative-filename to set ## the $FULFILname entry field ## ## 'navigate' - changes the directory in the $DIRFILmask entry field ## and runs proc 'fill_list' ## ## 'set_status_msg' - puts supplied msg into the Status msg frame ## ## 'put_var_exit' - puts $FULFILname (the name of the selected script) ## to stdout and exits. ## ## The following 6 procs are used for the 'naroDir', ..., 'shortWin' buttons. ## ## 'dir_listbox_width_increase' ## 'dir_listbox_width_reduce' ## 'fil_listbox_width_increase' ## 'fil_listbox_width_reduce' ## 'tall_win' ## 'short_win' ## ## 'toggle_fontsize' - for the 'TogFontSize' button ## 'toggle_ybars' - for the '<-Ybars->' button ## ## 'popup_msgVarWithScroll' - used to show the $HELPtext var ; also used ## to show user various popup messages for ## info, warnings, errors, etc. ## ##+################################################################# ##+################################################################# ##+################################################################### ## PROC 'fill_lists' ##+################################################################### ## PURPOSE: ## Fills the two listboxes (dirs & fils), according to the contents ## of var DIRFILmask. ## ## CALLED BY: the 'navigate' proc -OR- ## the 'Filter'/'Refresh'/'ReFill' button -OR- ## the fRdirfilmask.entryDIRFILmask BINDING ). ##+################################################################### ## LOGIC NOTES: ## Basically, 'fill_lists' should accept DIRFILmask (a global var) and ## 1) Set CURdir from DIRFILmask (chars before last "/") ## 2) Set FILmask from DIRFILmask (chars after last "/") ## 3) Fill the 'dir' listbox with directory names under/in $CURdir ## 4) Fill the 'fil' listbox with relative-filenames matching ## $DIRFILmask = $CURdir/$FILmask ## Ideally, steps 3 and 4 will support 'symbolic links' (broken or not). ##+#################################################################### proc fill_lists { } { global DIRFILmask FULFILname CURdir FILmask aRtext env #################################################### ## TRIM DIRFILmask (of leading or trailing blanks). #################################################### set DIRFILmask [ string trim "$DIRFILmask" ] ############################################# ## EXTRACT CURdir & FILmask from $DIRFILmask. ############################################# set CURdir [ file dirname "$DIRFILmask" ] set FILmask [ file tail "$DIRFILmask" ] if { "$FILmask" == "" } { set FILmask {*} } ############################################# ## FOR TESTING: (show CURdir & FILmask vars) ############################################# if {0} { puts "proc 'fill_lists' : (just entered the proc)" puts " DIRFILmask: $DIRFILmask" puts " CURdir: $CURdir" puts " FILmask: $FILmask" } ################################################################### ## CHECK IF THE DIRECTORY in the DIRFILmask var EXISTS. ## Pop an error msg if it does not -- and get out. ################################################################### if { ! [ file isdirectory $CURdir ] } { popup_msgVarWithScroll .topErr \ "The DIRECTORY in the DirFileMask entry field $CURdir WAS NOT FOUND. Change it and use the 'Refresh' button or Enter key. Or 'Cancel'." set_status_msg \ "The DIRECTORY in the DirFileMask entry field $CURdir was NOT FOUND. Change it and use the 'Refresh' button or Enter key. Or 'Cancel'." return } ## END OF if { ! [ file isdirectory $CURdir ] } ################################################### ## TURN THE CURSOR INTO A WATCH. ## (Not needed? The listboxes fill rapidly, ## even for directories with more than 1500 files.) ################################################### # . configure -cursor watch ## Needed only to change the cursor? # update ################################################## ## RESET THE FULFILname (selected script) TO NULL. ## (no; the user may want it even if it goes ## with a previously navigated-to directory.) ################################################## ## If necessary, do this at appropriate place ## in 'navigate' proc. ################################################## ## set FULFILname "" ############################################# ## RESET THE STATUS MESSAGE TO NULL. ## (or indicate that filling is starting) ############################################# # set_status_msg "" set_status_msg "Filling listbox ..." ####################################################################### ## (RE)FILL THE DIRECTORY LISTBOX. ## (See the code in proc 'get_subdirs_inCURdir'.) ####################################################################### # if { "$CURdir" == "" } { set CURdir "/" } set SubDirsLIST [get_subdirs_inCURdir_inclLinks] ################################################################### ## APPEND $SubDirsLIST TO THE 'dir' LISTBOX. (without using a loop) ################################################################### ## Ref: Brent Welch, Practical Programming in Tcl & Tk, ## Chapter 29, The Listbox Widget, page 359 ############################################################## ## To get this to work WITHOUT USING A listbox-insert LOOP, ## we use a Tcl list of dirs. ############################################################## .fRlists.fRdir.listbox delete 0 end eval .fRlists.fRdir.listbox insert end $SubDirsLIST ############################################# ## GET THE NUMBER OF SUBDIRS IN THE LISTBOX. ############################################# set num_dirs [ .fRlists.fRdir.listbox size ] ###################################################### ## RESET THE HEADING OF THE DIRECTORY ('dir') LISTBOX. ###################################################### .fRlists.fRdir.lab configure -text \ "$num_dirs Dirs - ParentDir\[..\] & SubDirs \[ Navigate = Single-Click \]" ####################################################################### ## (RE)FILL THE non-directory-FILES ('fil') LISTBOX. ## (See the code in proc 'get_files_inCURdir'.) ####################################################################### set FilesLIST [get_files_inCURdir_inclLinks] ###################################################################### ## APPEND FILENAMES TO THE 'fil' LISTBOX (avoiding a 'foreach' loop). ###################################################################### ## Ref: Brent Welch, Practical Programming in Tcl & Tk, ## Chapter 29, The Listbox Widget, page 359 ############################################################## ## To get this to work WITHOUT USING A listbox-insert LOOP, ## we use a Tcl list of filenames. ############################################################## .fRlists.fRfil.listbox delete 0 end eval .fRlists.fRfil.listbox insert end $FilesLIST ############################################# ## GET THE NUMBER OF FILES IN THE LISTBOX. ############################################# set num_files [ .fRlists.fRfil.listbox size ] ################################################ ## RESET THE HEADING OF THE FILES ('fil) LISTBOX. ################################################ .fRlists.fRfil.lab configure -text \ " $num_files File(s) matching the mask \[ Select = Single-Click \]" ################################################################## ## PUT A MSG IN THE STATUS MSG AREA? ## (Yes, for when the 'Refresh' button is clicked. For other cases, ## where other procs call this 'fill_lists' proc -- like ## 'navigate' -- the other proc can overwrite the status msg area.) ################################################################## set_status_msg "$aRtext(filledSTATUSmsg)" ############################################# ## RETURN THE CURSOR TO A 'LEFT POINTER'. ############################################# # . configure -cursor { left_ptr red white } } ## END OF PROC 'fill_lists' ##+############################################################## ## PROC 'get_subdirs_inCURdir_inclLinks' ##+############################################################## ## PURPOSE: ## For given CURdir, this routine returns a Tcl list of the ## directory files in CURdir --- including 'symbolic links' ## to directories (handling broken links 'appropriately'). ################################################################# ## METHOD: ## To find the sub-directories of CURdir, for the 'dir' listbox, ## we use the Tcl 'glob' command. ## ## For example, to find the sub-directories to put in the 'dir' ## listbox, the following seems to work to show get both non-hidden ## and hidden files: ## ## glob -nocomplain $CURdir/* $CURdir/.* ## ## (The '-nocomplain' allows for returning an empty list without ## raising an error.) ## ## We show 'hidden' sub-directories (dot-prefix on the filenames) ## as well as 'non-hidden' sub-directories. (The showing of 'hidden' ## files could be made an option via a checkbutton on the GUI.) ## ## From this list of filenames, in a 'foreach' loop, we can select ## the 'directory' files. ## ## Among the files returned by the 'glob' above, there could be ## 'symbolic links' to directories. In the same 'foreach' loop ## that is used to select out the directory files, we find the ## 'link' files and figure out which links point to directories. ## ## If there is a 'directory-link', we append the link to the list ## of directories, for display in the 'dir' listbox. (We can ## check if the link is 'broken', and we can choose to NOT ## append it --- or popup a warning.) ## ## --- ## ## In the 'foreach' loop, we can make use of Tcl commands like ## ## file type $file (Returns: file, directory, characterSpecial, ## blockSpecial, fifo, link, OR socket) ## file readlink $file (Good for finding the target of a link.) ## file pathtype $file (Returns: relative, absolute, OR volumerelative) ## ## file exists $file ## ## If necessary, we could also make use of Tcl 'file' commands like ## ## file isdirectory $file ## file isfile $file ## ## file link $file ## file stat $file aRfileStat ## file lstat $file aRlinkStat ## ....................................................................... ## Ref: the Eric Johnson book " Graphical Applications with Tcl & Tk", ## page 225-226, Chapter 6 Lists, Files, and Directories. ## --- ## The 'dirview.tcl' script in chapter 6 gives an example of using ## a 'foreach' loop to extract directories and non-directories ## from 'glob' output. But that code would have to be made more ## robust to handle 'symbolic links' properly --- and exclude ## special files like fifo, socket, and device files. ##+########################################################## ## CALLED BY: 'fill_lists' proc ##+########################################################## proc get_subdirs_inCURdir_inclLinks {} { global CURdir DEBUGlink0or1 ############################################################# ## Get the list of files to check for 'directory' and 'link' ## file types. (We do not expect any of the sub-directories ## of the scripts to be 'hidden' via a dot-prefix.) ############################################################ if {"$CURdir" == "/"} { # set tempFilesLIST [glob -nocomplain /* /.*] set tempFilesLIST [glob -nocomplain /*] } else { # set tempFilesLIST [glob -nocomplain $CURdir/* $CURdir/.*] set tempFilesLIST [glob -nocomplain $CURdir/*] lappend tempFilesLIST ".." } ## Alternative (using 'catch' to get return-code): # set tempFilesLIST "" # set RETcode [ catch { set tempFilesLIST [ .... ] } ] ## FOR TESTING: # puts "tempFilesLIST: $tempFilesLIST" # puts "RETcode: $RETcode" ################################################################ ## Make sure the variable 'tempDirsLIST' does not exist. ## ## "You can call 'lappend' with the name of an undefined ## variable and the variable will be created." - page 66 of the ## 4th edition of 'Practical Programming in Tcl and Tk' by ## Welch, Jones, Hobbs. ############################################################### catch {unset tempDirsLIST} ################################################################### ## Peform the 'foreach' loop to append the files of type ## 'directory' to the Tcl list 'tempDirsLIST'. ################################################################### ## If a file is of type 'link', we determine if the link is of type ## 'directory'. If so, we append the link-name to 'tempDirsLIST'. ################################################################### ## If 'file readlink' is not sufficient, ## we may eventually have to handle the case where the ## a symbolic link points to another symbolic link and ## on and on until the eventual target is determined. ## We could put that logic in a proc with a name like ## 'get_link_target'. ################################################################### foreach tempFilename $tempFilesLIST { ############################################################ ## If 'tempFilename' is of type 'directory', append the ## filename to tempDirsLIST and 'continue' to the next file. ############################################################ ## Exceptions are the sub-dirs "." and "..". We do not ## show "." and we show ".." for all directories except root. ############################################################ if {[file type $tempFilename] == "directory"} { set tempTail [file tail "$tempFilename"] if {"$tempTail" == "."} {continue} if {"$tempTail" == ".." && "$CURdir" == "/"} {continue} lappend tempDirsLIST "$tempTail" continue } ######################################################## ## If 'tempFilename' is NOT of type 'link', ## 'continue' to the next file in the loop. ######################################################## if {[file type $tempFilename] != "link"} {continue} ######################################################## ## The remainder of this loop is to handle 'link' files. ######################################################## ## Get the filename of the target of the link. ## (If we need to do a more complex check for the *ultimate* ## target of the link, we could put that logic in a proc ## with a name like 'get_link_target'.) ######################################################## set targetName [file readlink $tempFilename] ## FOR TESTING: if {$DEBUGlink0or1} { puts "" puts "proc 'get_subdirs_inCURdir_inclLinks' :" puts "tempFilename: $tempFilename" puts "targetName: $targetName" } if {[file pathtype $targetName] == "relative"} { set targetName "$CURdir/$targetName" ## FOR TESTING: if {$DEBUGlink0or1} { puts "targetName: $targetName RESET" } } ####################################################### ## If the target does not exist (i.e. 'broken link'), ## 'continue' to the next file in the loop. ## (We could insert a popup warning message to alert ## the user of the broken link.) ####################################################### if {![file exists $targetName]} { ## FOR TESTING: if {$DEBUGlink0or1} { puts "targetName: $targetName DOES NOT EXIST." } continue } ####################################################### ## Get the file-type of the target of the link. ####################################################### set targetType [file type $targetName] ## FOR TESTING: if {$DEBUGlink0or1} { puts "targetType: $targetType" } ###################################################### ## If the file-type of the target is 'directory', ## add the link-filename to tempDirsLIST. ###################################################### if {"$targetType" == "directory"} { lappend tempDirsLIST [file tail "$tempFilename"] } } ## END OF foreach tempFilename $tempFilesLIST ###################################################### ## Return the sub-directories list, sorted. ###################################################### if {[info exists tempDirsLIST]} { return [lsort $tempDirsLIST] } else { return "" } } ## END OF PROC 'get_subdirs_inCURdir_inclLinks' ##+############################################################## ## PROC 'get_files_inCURdir_inclLinks' ##+############################################################## ## PURPOSE: ## For given CURdir, this routine returns a Tcl list of the ## 'regular' files in CURdir --- including 'symbolic links' ## to 'regular' files (handling broken links 'appropriately'). ####################################################################### ## METHOD: ## To get the files for the 'fil' listbox, for a given CURdir and ## FILmask, we can use a 'glob' like the following: ## ## glob -nocomplain $CURdir/$FILmask ## ## In a 'foreach' loop, we could select the 'regular' files. ## ## If the user wanted to see hidden files, the user could add a ## dot-prefix in the file-mask. Alternatively, we could ALWAYS ## show the 'hidden' files by using a 'glob' like ## ## glob -nocomplain $CURdir/$FILmask $CURdir/.$FILmask ## ## For example, if FILmask='*', this 'glob' would look like ## ## glob -nocomplain $CURdir/* $CURdir/.* ## ## Among the files returned by the 'glob' above, there could be ## 'symbolic links' to 'regular' files. In the same 'foreach' loop ## that is used to select out the regular files, we find the ## 'link' files and figure out which links point to regular files. ## ## If there is a 'regular-file-link', we append the link to the list ## of files for the 'fil' listbox. (We can check if the link is 'broken', ## and we can choose to not append it --- or popup a warning.) ## ## --- ## ## In the 'foreach' loop, we can make use of Tcl 'file' commands like ## ## file type $file (Returns: file, directory, characterSpecial, ## blockSpecial, fifo, link, OR socket) ## ## file readlink $file (Good for finding the target of a link.) ## file pathtype $file (Returns: relative, absolute, OR volumerelative) ## ## file exists $file ## ## If necessary, we could also make use of Tcl 'file' commands like ## ## file isdirectory $file ## file isfile $file ## ## file link $file ## ## file stat $file aRfileStat ## file lstat $file aRlinkStat ## ## ................................................................... ## Ref: the Eric Johnson book " Graphical Applications with Tcl & Tk", ## page 225-226, Chapter 6 Lists, Files, and Directories. ## --- ## The 'dirview.tcl' script in chapter 6 gives an example of using ## a 'foreach' loop to extract directories and non-directories ## from 'glob' output. But that code would have to be made more ## robust to handle 'symbolic links' properly --- and exclude ## special files like fifo and device files --- and exclude ## special files like fifo, socket, and device files. ##+########################################################## ## CALLED BY: 'fill_lists' proc ##+########################################################## proc get_files_inCURdir_inclLinks {} { global CURdir FILmask DEBUGlink0or1 ############################################################# ## Get the list of files to check for 'directory' and 'link' ## file types. (We do not expect any of the filenames ## of the scripts to be 'hidden' via a dot-prefix, so we ## do not glob for hidden files.) ## (We don't expect to navigate up the the root directory ## either but we include that case.) ############################################################ if {"$CURdir" == "/"} { # set tempFilesLIST [glob -nocomplain /$FILmask /.$FILmask] set tempFilesLIST [glob -nocomplain /$FILmask] } else { # set tempFilesLIST [glob -nocomplain $CURdir/$FILmask $CURdir/.$FILmask] set tempFilesLIST [glob -nocomplain $CURdir/$FILmask] } ## Alternative (using 'catch' to get return-code): # set tempFilesLIST "" # set RETcode [ catch { set tempFilesLIST [ .... ] } ] ## FOR TESTING: # puts "tempFilesLIST: $tempFilesLIST" # puts "RETcode: $RETcode" ################################################################ ## Make sure the variable 'tempRegFilesLIST' does not exist. ## ## "You can call 'lappend' with the name of an undefined ## variable and the variable will be created." - page 66 of the ## 4th edition of 'Practical Programming in Tcl and Tk' by ## Welch, Jones, Hobbs. ############################################################### catch {unset tempRegFilesLIST} ################################################################## ## Peform the 'foreach' loop to append the files of type ## 'file' to the Tcl list 'tempRegFilesLIST'. ################################################################## ## If a file is of type 'link', we determine if the link is of ## type 'file'. If so, we append the link-name to 'tempRegFilesLIST'. ############################################################## ## If 'file readlink' is not sufficient, ## we may eventually have to handle the case where the ## a symbolic link points to another symbolic link and ## on and on until the eventual target is determined. ## We could put that logic in a proc with a name like ## 'get_link_target'. ############################################################## foreach tempFilename $tempFilesLIST { ########################################################### ## If 'tempFilename' is of type 'file', append the filename ## to tempRegFilesLIST and 'continue' to the next file. ########################################################### if {[file type $tempFilename] == "file"} { lappend tempRegFilesLIST [file tail "$tempFilename"] continue } ######################################################## ## If 'tempFilename' is NOT of type 'link', ## 'continue' to the next file in the loop. ######################################################## if {[file type $tempFilename] != "link"} {continue} ######################################################## ## The remainder of this loop is to handle 'link' files. ######################################################## ## Get the filename of the target of the link. ## (If we need to do a more complex check for the *ultimate* ## target of the link, we could put that logic in a proc ## with a name like 'get_link_target'.) ######################################################## set targetName [file readlink $tempFilename] ## FOR TESTING: if {$DEBUGlink0or1} { puts "" puts "proc 'get_files_inCURdir_inclLinks' :" puts "tempFilename: $tempFilename" puts "targetName: $targetName" } if {[file pathtype $targetName] == "relative"} { set targetName "$CURdir/$targetName" ## FOR TESTING: if {$DEBUGlink0or1} { puts "targetName: $targetName RESET" } } ####################################################### ## If the target does not exist (i.e. 'broken link'), ## 'continue' to the next file in the loop. ## (We could insert a popup warning message to alert ## the user of the broken link.) ####################################################### if {![file exists $targetName]} { ## FOR TESTING: if {$DEBUGlink0or1} { puts "targetName: $targetName DOES NOT EXIST." } continue } ####################################################### ## Get the file-type of the target of the link. ####################################################### set targetType [file type $targetName] ## FOR TESTING: if {$DEBUGlink0or1} { puts "targetType: $targetType" } ###################################################### ## If the file-type of the target is 'file', ## add the link-filename to tempRegFilesLIST. ###################################################### if {"$targetType" == "file"} { lappend tempRegFilesLIST [file tail "$tempFilename"] } } ## END OF foreach tempFilename $tempFilesLIST ###################################################### ## Return the regular-files list, sorted. ###################################################### if {[info exists tempRegFilesLIST]} { return [lsort $tempRegFilesLIST] } else { return "" } } ## END OF PROC 'get_files_inCURdir_inclLinks' ##+############################################################## ## PROC 'get_selected_file' ##+############################################################## ## PURPOSE: ## This routine essentially reloads the FULFILname entry ## field -- by prefixing the selected relative-filename, ## from the files-listbox, with $CURdir. ##+########################################################## ## CALLED BY: ## the .fRlists.fRfil.listbox BINDING ## WHEN MOUSE-BUTTON-1 IS SINGLE-CLICKED ## ON A FILE in the '.fRlists.fRfil.listbox' widget. ##+############################################################# proc get_selected_file { } { global DIRFILmask FULFILname aRtext ################################################ ## RETURN THE CURSOR TO A 'LEFT POINTER'. ## (In case cursor was left as a 'watch' ## after a failure in 'fill_lists' proc, like ## a CURdir permission error.) ################################################ # . configure -cursor { left_ptr red white } ####################################################### ## FIND OUT WHICH FILE IS BEING SELECTED. ####################################################### set FULFILname "" set sel_index [ .fRlists.fRfil.listbox curselection ] #################################################### ## RESET THE STATUS MESSAGE TO NULL. #################################################### set_status_msg "" ####################################################### ## IF A LIST ITEM WAS NOT SELECTED, pop a msg & return. ####################################################### if { "$sel_index" == "" } { popup_msgVarWithScroll .topErr \ "NO item was selected in the listbox." set_status_msg \ "NO item was selected in the listbox." return } #################################################### ## GET THE 'RELATIVE' FILENAME. #################################################### set RELFILsel [ .fRlists.fRfil.listbox get $sel_index ] ############################################# ## EXTRACT CURdir from $DIRFILmask. ############################################# set CURdir [ file dirname "$DIRFILmask" ] #################################################### ## UPDATE THE CURRENT FILE-SELECTION ENTRY ## WITH THE NEW, FULL FILENAME. #################################################### set FULFILname "${CURdir}/$RELFILsel" ############################################## ## PUT A MSG IN THE STATUS MSG AREA. ############################################## set_status_msg "Click 'UseIt' to accept the 'Script Selection' entry." #################################################### ## MAKE SURE THE FAR-RIGHT END OF THE TEXT IN THE ## FILE-SELECTION ENTRY BOX IS IN VIEW. #################################################### .fRscriptSel.entry xview end } ## END OF PROC 'get_selected_file' ##+############################################################## ## PROC 'navigate' ##+############################################################## ## PURPOSE: ## This routine essentially navigates the directory ## structure. It ## 1) resets the DIRFILmask entry according to a subdir ## selected in the subdirs-listbox, and ## 2) runs the 'fill_lists' procedure, to refresh both the ## subdirs-listbox and the relfiles-listbox. ## ##+############################################################## ## CALLED BY: ## the fRlists.fRdir.listbox BINDING ## WHEN MOUSE-BUTTON-1 IS SINGLE-CLICKED (& released) ## ON A (SUB)DIRECTORY in the '.fRlists.fRdir.listbox' widget. ##+############################################################## proc navigate { } { global DIRFILmask aRtext env #################################################### ## FIND OUT WHICH SUB-DIRECTORY WAS SELECTED. #################################################### set sel_index [ .fRlists.fRdir.listbox curselection ] #################################################### ## RESET THE STATUS MESSAGE TO NULL. #################################################### set_status_msg "" ###################################################### ## IF A LIST ITEM WAS NOT SELECTED, pop a msg & return. ###################################################### if { "$sel_index" == "" } { popup_msgVarWithScroll .topErr \ "Navigate Procedure: NO item was selected in the Dirs (left) listbox." set_status_msg \ "Navigate Procedure: NO item was selected in the Dirs (left) listbox." return } #################################################### ## GET THE 'BASENAME' of the selected SUBDIRECTORY. #################################################### set RELDIRsel [ .fRlists.fRdir.listbox get $sel_index ] ################################################################### ## CHECK HERE IF THE USER HAS 'cd' PERMISSION TO $RELDIRsel. ## Pop a msg if not -- and return. ################################################################### set CURdir [ file dirname "$DIRFILmask" ] if {"$CURdir" == "/"} { set CHECKdir "/$RELDIRsel" } else { set CHECKdir "$CURdir/$RELDIRsel" } if { ! [ file executable "$CHECKdir" ] } { popup_msgVarWithScroll .topErr \ "The DIRECTORY $CHECKdir is NOT ACCESSIBLE TO YOU, as user $env(USER)." set_status_msg \ "The DIRECTORY $CHECKdir is NOT ACCESSIBLE TO YOU, as user $env(USER)." return } ## END OF if { ! [ file executable "$CHECKdir" ] } ################################################## ## EXTRACT FILmask from $DIRFILmask. ################################################## set FILmask [ file tail "$DIRFILmask" ] ########################################################## ## SET THE NEW FULL-DIRNAME in CURdir, using $RELDIRsel. ## If RELDIRsel is '..' (parent directory) instead of a ## sub-directory, set CURdir to its parent directory. ########################################################## ## NOTE: 'file dirname' of '/home' and '/' both yield '/'. ## % file dirname /home ## / ## % file dirname / ## / ## % file dirname /usr ## / ######################################################### if { "$RELDIRsel" == ".." } then { ## Save where we were, before setting CURdir to the parent directory. ## This will be used in subdir high-lighting below. set relCHILDdir [ file tail $CURdir ] set CURdir [ file dirname "$CURdir" ] } else { if { "$CURdir" == "/" } { ## Avoid CURdir being double-slash. set CURdir "/$RELDIRsel" } else { set CURdir "${CURdir}/$RELDIRsel" } } ####################################################### ## RESET $DIRFILmask in the DIRFILmask entry field, AND ## to be used by 'fill_lists' proc. ## NOTE: CURdir is extracted (again) from $DIRFILmask ## in the 'fill_lists' proc. ####################################################### if {"$CURdir" == "/"} { ## Avoid DIRFILmask starting with double-slash. set DIRFILmask "/$FILmask" } else { set DIRFILmask "${CURdir}/$FILmask" } ############################################################## ## CALL 'fill_lists' to fill the subdir & relfil listboxes. ############################################################## fill_lists ########################################################## ## If the user is navigating to a parent directory (i.e., ## if '..' was clicked), position the list in the updated ## 'dir' listbox such that the subdirectory that the user ## is 'climbing out of' is seen the the 'dir' listbox. ########################################################## if { "$RELDIRsel" == ".." } then { set IDXsubdir [lsearch [.fRlists.fRdir.listbox get 1 end] $relCHILDdir] .fRlists.fRdir.listbox see $IDXsubdir .fRlists.fRdir.listbox selection set [expr {$IDXsubdir + 1}] } ############################################## ## PUT A MSG IN THE STATUS MSG AREA. ############################################## set_status_msg "$aRtext(filledSTATUSmsg)" ####################################################### ## MAKE SURE THE FAR-RIGHT END OF TEXT IN THE ## ENTRY BOXES IS IN VIEW, when this 'navigate' is done. ####################################################### .fRdirfilmask.entryDIRFILmask xview end .fRscriptSel.entry xview end } ## END OF PROC 'navigate' ##+######################################################################## ## PROC 'set_status_msg' ##+######################################################################## ## PURPOSE: To put an informational message to the user into the ## bottom 'status-msg' area of the GUI. ## CALLED BY: various procs ##+######################################################################## ## MESSAGE-CONTENT NOTE: The message string can include line-feeds. ##+######################################################################## proc set_status_msg { message } { ############################################# ## RETURN THE CURSOR TO A 'LEFT POINTER'. ## (In case cursor was left as a 'watch' ## after a failure in 'fill_list' proc, like ## a subdir permission error.) ############################################# # . configure -cursor { left_ptr red white } .fRstatusmsg.lab configure -text "$message" } ## END OF PROC 'set_status_msg' ##+################################################################# ## PROC 'put_var_exit' ##+################################################################# ## PURPOSE: ## This procedure contitutes the main purpose of this file-selector ## GUI -- sending a fully-qualified filename to stdout (and exiting). ## ## This procedure checks the validity of the filename. ## If invalid, there is no exit -- an error message ## line is shown in a status message widget. ## ##+################################################################# ## CALLED BY: The 'OK'/'UseIt' button -OR- ## the .fRfilselection.entry BINDING ##+#################################################################### proc put_var_exit { } { global FULFILname DIRFILmask ############################################## ## GET RID OF LEADING AND TRAILING WHITE SPACE ## IN THE SELECTED FILE, that comes ## from the 'filselection.entry' widget. ############################################## set FULFILname [ string trim "$FULFILname" ] ############################################## ## IF THE 'SELECTION' FILE FIELD OS EMPTY, ## POPUP A MSG AND RETURN. ############################################## if { "$FULFILname" == "" } then { popup_msgVarWithScroll .topErr \ "The 'Script Selection' entry field is empty. Select-a-filename or Cancel." set_status_msg \ "The 'Script Selection' entry field is empty. Select-a-filename or Cancel." return } ############################################## ## IF THE 'SELECTION' FILE DOES NOT EXIST, ## POPUP A MSG AND RETURN. ############################################## if { ! [ file exists "$FULFILname" ] } then { popup_msgVarWithScroll .topErr \ "The file specified in the 'Script Selection' entry field $FULFILname CANNOT BE FOUND. Try again or Cancel." set_status_msg \ "The file specified in the 'Script Selection' entry field $FULFILname CANNOT BE FOUND. Try again or Cancel." return } ############################################################## ## IF THE 'SELECTION' FILE IS A DIRECTORY, ## POPUP A MSG AND RETURN. ############################################################## ## This should not be the case if the user ## selected the file via the files-listbox. ## But the user could paste/enter the name. ############################################################## if { [ file isdirectory "$FULFILname" ] } then { popup_msgVarWithScroll .topErr \ "The file selected in the 'Script Selection' entry field $FULFILname is a DIRECTORY, not a regular file. Try again or Cancel." set_status_msg \ "The file selected in the 'Script Selection' entry field $FULFILname IS A DIRECTORY, not a regular file. Try again or Cancel." return } ################################################################ ## If the 'SELECTION' FILEname has a trailing '/', ## ISSUE A WARNING AND RETURN. ################################################################ if { "[ file tail \"$FULFILname\" ]" == "" } { # set FULFILname [ file dirname "$FULFILname" ] popup_msgVarWithScroll .topErr \ "The file specified in the 'Script Selection' entry field $FULFILname ends with a slash (/). Remove the slash, try again, or Cancel." set_status_msg "The file specified in the 'Script Selection' entry field $FULFILname ends with a slash (/). Remove the slash, try again or Cancel." #################################################### ## MAKE SURE THE FAR-RIGHT END OF THE TEXT IN THE ## SELECTION ENTRY BOX IS IN VIEW. (needed?) #################################################### .fRscriptSel.entry xview end return } ## All looks OK. Put out the filename. puts "$FULFILname" exit } ## END OF PROC 'put_var_exit' ##+############################################################## ## PROC 'toggle_fontsize' ##+############################################################## ## PURPOSE: ## This routine toggles the size of fonts for about 18 different ## widgets --- between a small font and a larger font. ##+############################################################## ## CALLED BY: the button command of the button ## .fRcntlbutts1.buttFontSize . ##+############################################################## set FONT_sizeFLAG "large" proc toggle_fontsize { } { global FONT_sizeFLAG ## FOR TESTING: (must be commented for 'production' use) # puts "Changing font size." if { "$FONT_sizeFLAG" == "small" } then { set FONT_sizeFLAG "large" .fRdirmaskHead.lab configure -font fontTEMP_varwidth .fRdirfilmask.entryDIRFILmask configure -font fontTEMP_fixedwidth .fRlists.fRdir.lab configure -font fontTEMP_varwidth .fRlists.fRdir.listbox configure -font fontTEMP_fixedwidth .fRlists.fRfil.lab configure -font fontTEMP_varwidth .fRlists.fRfil.listbox configure -font fontTEMP_fixedwidth .fRscriptHead.lab configure -font fontTEMP_varwidth .fRscriptSel.entry configure -font fontTEMP_fixedwidth .fRcntlbutts1.buttOK configure -font fontTEMP_varwidth .fRcntlbutts1.buttCancel configure -font fontTEMP_varwidth .fRcntlbutts1.buttFilter configure -font fontTEMP_varwidth .fRcntlbutts1.buttHelp configure -font fontTEMP_varwidth .fRcntlbutts1.buttFontSize configure -font fontTEMP_varwidth .fRcntlbutts2.buttDirListLeft configure -font fontTEMP_varwidth .fRcntlbutts2.buttDirListRight configure -font fontTEMP_varwidth .fRcntlbutts2.buttFilListLeft configure -font fontTEMP_varwidth .fRcntlbutts2.buttFilListRight configure -font fontTEMP_varwidth .fRcntlbutts2.buttTallWin configure -font fontTEMP_varwidth .fRcntlbutts2.buttShortWin configure -font fontTEMP_varwidth .fRstatusmsg.lab configure -font fontTEMP_fixedwidth } else { set FONT_sizeFLAG "small" .fRdirmaskHead.lab configure -font fontTEMP_SMALL_varwidth .fRdirfilmask.entryDIRFILmask configure -font fontTEMP_SMALL_fixedwidth .fRlists.fRdir.lab configure -font fontTEMP_SMALL_varwidth .fRlists.fRdir.listbox configure -font fontTEMP_SMALL_fixedwidth .fRlists.fRfil.lab configure -font fontTEMP_SMALL_varwidth .fRlists.fRfil.listbox configure -font fontTEMP_SMALL_fixedwidth .fRscriptHead.lab configure -font fontTEMP_SMALL_varwidth .fRscriptSel.entry configure -font fontTEMP_SMALL_fixedwidth .fRcntlbutts1.buttOK configure -font fontTEMP_SMALL_varwidth .fRcntlbutts1.buttCancel configure -font fontTEMP_SMALL_varwidth .fRcntlbutts1.buttFilter configure -font fontTEMP_SMALL_varwidth .fRcntlbutts1.buttHelp configure -font fontTEMP_SMALL_varwidth .fRcntlbutts1.buttFontSize configure -font fontTEMP_SMALL_varwidth .fRcntlbutts2.buttDirListLeft configure -font fontTEMP_SMALL_varwidth .fRcntlbutts2.buttDirListRight configure -font fontTEMP_SMALL_varwidth .fRcntlbutts2.buttFilListLeft configure -font fontTEMP_SMALL_varwidth .fRcntlbutts2.buttFilListRight configure -font fontTEMP_SMALL_varwidth .fRcntlbutts2.buttTallWin configure -font fontTEMP_SMALL_varwidth .fRcntlbutts2.buttShortWin configure -font fontTEMP_SMALL_varwidth .fRstatusmsg.lab configure -font fontTEMP_SMALL_fixedwidth } } ## END OF PROC 'toggle_fontsize' ######################################################################## ## PROC 'toggle_ybars' ######################################################################## ## PURPOSE: To switch the side of the 2 y-scrollbars, ## on the sides of the 'dir' and 'fil' listboxes. ## ## CALLED BY: .fRcntlbutts1.buttYbarsSIDE ######################################################################## set SIDE_Ybars "left" proc toggle_ybars {} { global SIDE_Ybars if { "$SIDE_Ybars" == "left" } { set SIDE_Ybars "right" set SIDE_other "left" } else { set SIDE_Ybars "left" set SIDE_other "right" } ## FOR TESTING: # puts "SIDE_Ybars: $SIDE_Ybars" # puts "SIDE_other: $SIDE_other" pack forget .fRlists.fRdir.scrbary .fRlists.fRdir.listbox \ .fRlists.fRfil.scrbary .fRlists.fRfil.listbox pack .fRlists.fRdir.scrbary \ -side $SIDE_Ybars \ -anchor n \ -fill y \ -expand 0 pack .fRlists.fRdir.listbox \ -side $SIDE_other \ -anchor n \ -fill both \ -expand 1 pack .fRlists.fRfil.scrbary \ -side $SIDE_Ybars \ -anchor n \ -fill y \ -expand 0 pack .fRlists.fRfil.listbox \ -side $SIDE_other \ -anchor n \ -fill both \ -expand 1 } ## END of proc 'toggle_ybars' ##+################################################################# ## PROC 'dir_listbox_width_increase' ##+################################################################# ## PURPOSE: ## This routine increases the width of the directory listbox frame ## (measured in pixels). ## ## Note that our intent is to increase the width of the frame's ## 2 interior widgets (label and listbox). Those widths are ## specified in chars, not pixels. ## ## To avoid conversions between pixels and chars, we try to do ## the widening in pixels-only --- using an 'INCRpixelsRIGHT' var. ## ## There are many ways this could be implemented. This is just one. ## This routine, and its partner 'dir_listbox_width_reduce', ## are just routines that seem to work reasonably well. ## ## ARGUMENTS: See the global vars. ## ## CALLED BY: the button command of the button ## .fRcntlbutts2.butDirListRight . ##+############################################################## proc dir_listbox_width_increase {} { global INCRpixelsRIGHT SCREENwidthPx wmPIXELS_top wmPIXELS_left # global CHARWIDTHpixels INCRcharsRIGHT ## An alternate method could be to use 'INCRcharsRIGHT' instead of ## 'INCRpixelsRIGHT', on the frame contents instead of on the frame ## --- to do the increase in chars-only instead of pixels-only. set winXlen [ winfo width . ] set DIRwidthPX [winfo width .fRlists.fRdir] set FILwidthPX [winfo width .fRlists.fRfil] ## FOR TESTING: if {0} { puts "*******************************************************" puts "proc 'dir_listbox_width_increase' : (just entered proc)" puts "dirFRAMEwidth via winfo = $DIRwidthPX pixels, on entering proc." puts "filFRAMEwidth via winfo = $FILwidthPX pixels." puts "window-width via winfo = $winXlen pixels." puts "INCRpixelsRIGHT = $INCRpixelsRIGHT pixels." } ####################################################################### ## We do not try to increase the dir-listbox width if the entire window ## is already at the screen width. I.e. we only do the following ## computations if there is some room to expand the dir-listbox. ####################################################################### if { $winXlen < $SCREENwidthPx } { ## Adjust the 'loc' vars for the window manager border. set winXloc [ winfo rootx . ] set winYloc [ winfo rooty . ] set winXloc [ expr {$winXloc - $wmPIXELS_left} ] set winYloc [ expr {$winYloc - $wmPIXELS_top} ] ############################################################################## ## Increase the window width about as much as the increase in dir-frame-width, ## while keeping the location of the upper-left corner constant. ############################################################################## set winYlen [ winfo height . ] set winXlen [expr {$winXlen + $INCRpixelsRIGHT}] wm geometry . ${winXlen}x${winYlen}+${winXloc}+${winYloc} ##################################################################### ## After we request an increase to the window size, we increase ## the size of the dir-listbox-frame. ##################################################################### set DIRwidthPX [expr {$DIRwidthPX + $INCRpixelsRIGHT}] ## FOR TESTING: if {0} { puts "" puts "proc 'dir_listbox_width_increase' : (new-DIR & same-FIL width parms)" puts "DIRwidthPX: $DIRwidthPX" puts "FILwidthPX: $FILwidthPX" } ###################################################################### ## Increase the dir-frame width, but keep the fil-frame width the same. ###################################################################### ## Strangely, the fil-listbox expands unless I add the ## 'pack propagate ... false' statement --- on the dir-listbox, ## NOT the fil-listbox. ## ## It seems that the 'pack propagate' should not be necessary (since ## I am specifically configuring the width of the 2 listboxes). AND ## it seems the 'pack propagate ... false' should be applied to ## the fil-listbox, NOT the dir-listbox. None of this section works the ## way I would expect. ###################################################################### .fRlists.fRdir configure -width $DIRwidthPX .fRlists.fRfil configure -width $FILwidthPX pack propagate .fRlists.fRdir false } ## END OF if { $winXlen < $SCREENwidthPx } } ## END OF PROC 'dir_listbox_width_increase' ##+############################################################## ## PROC 'dir_listbox_width_reduce' ##+############################################################## ## PURPOSE: ## This routine reduces the width of the directory listbox frame ## (measured in pixels). ## ## Note that our intent is to decrease the width of the frame's ## 2 interior widgets (label and listbox). Those widths are ## specified in chars, not pixels. ## ## To avoid conversions between pixels and chars, we try to do ## the narrowing in pixels-only --- using an 'INCRpixelsLEFT' var. ## ## There are many ways this could be implemented. This is just one. ## This routine, and its partner 'dir_listbox_width_increase', ## are just routines that seem to work reasonably well. ## ## ARGUMENTS: See the global vars. ## ## CALLED BY: the button command of the button ## .fRcntlbutts2.butDirListLeft . ##+############################################################## proc dir_listbox_width_reduce {} { global INCRpixelsLEFT DIRminwidthPX wmPIXELS_top wmPIXELS_left # global CHARWIDTHpixels INCRcharsLEFT ## An alternate method could be to use 'INCRcharsLEFT' instead of ## 'INCRpixelsLEFT', on the frame contents instead of on the frame ## --- to do the reduction in chars-only instead of pixels-only. set DIRwidthPX [winfo width .fRlists.fRdir] set FILwidthPX [winfo width .fRlists.fRfil] set winXlen [ winfo width . ] ## FOR TESTING: if {0} { puts "*****************************************************" puts "proc 'dir_listbox_width_reduce' : (just entered proc)" puts "dirFRAMEwidth via winfo = $DIRwidthPX pixels." puts "filFRAMEwidth via winfo = $FILwidthPX pixels." puts "window-width via winfo = $winXlen pixels." puts "INCRpixelszLEFT = $INCRpixelsLEFT pixels." } ###################################################################### ## We do not try to decrease the dir-listbox width if it is ## already at a designated minwidth. I.e. we only do the following ## computations if there is some latitude to decrement the dir-listbox. ###################################################################### if { $DIRwidthPX > $DIRminwidthPX } { set DIRwidthPX [expr {$DIRwidthPX - $INCRpixelsLEFT}] set deltaDIRwidthPX $INCRpixelsLEFT if { $DIRwidthPX < $DIRminwidthPX } { set deltaDIRwidthPX [expr {($DIRwidthPX + $INCRpixelsLEFT) - $DIRminwidthPX}] set DIRwidthPX $DIRminwidthPX } ## FOR TESTING: if {0} { puts "" puts "proc 'dir_listbox_width_reduce' : (new-DIR & same-FIL width parms)" puts "DIRwidthPX: $DIRwidthPX" puts "FILwidthPX: $FILwidthPX" } ###################################################################### ## Decrease the dir-frame width, but keep the fil-frame width the same. ###################################################################### ## Strangely, the fil-listbox decrements unless I add the ## 'pack propagate ... false' statement --- on the dir-listbox, ## NOT the fil-listbox. ## ## It seems that the 'pack propagate' should not be necessary (since ## I am specifically configuring the width of the 2 listboxes). AND ## it seems the 'pack propagate ... false' should be applied to ## the fil-listbox, NOT the dir-listbox. None of this works the ## way I would expect. ###################################################################### .fRlists.fRdir configure -width $DIRwidthPX .fRlists.fRfil configure -width $FILwidthPX pack propagate .fRlists.fRdir false ######################################################### ## We narrow the window by the amount we narrow the ## directory box --- as follows. ######################################################### set winXloc [ winfo rootx . ] set winYloc [ winfo rooty . ] ## Adjust the 'loc' vars for the window manager border. set winXloc [ expr {$winXloc - $wmPIXELS_left} ] set winYloc [ expr {$winYloc - $wmPIXELS_top} ] set winXlen [ winfo width . ] set winYlen [ winfo height . ] ############################################################################## ## Reduce the window width about as much as the decrease in dir-frame-width, ## while keeping the location of the upper-left corner constant. ############################################################################## set winXlen [expr {$winXlen - $deltaDIRwidthPX}] ## FOR TESTING: if {0} { puts "" puts "proc 'dir_listbox_width_reduce' : (new WINwidth parm)" puts "winXlen: $winXlen" } wm geometry . ${winXlen}x${winYlen}+${winXloc}+${winYloc} } ## END OF if { $DIRwidthPX > $DIRminwidthPX } } ## END OF PROC 'dir_listbox_width_reduce' ##+############################################################## ## PROC 'fil_listbox_width_increase' ##+############################################################## ## PURPOSE: ## This routine increases the width of the 'fil' listbox frame ## (measured in pixels). ## ## Note that our intent is to increase the width of the frame's ## 2 interior widgets (label and listbox). Those widths are ## specified in chars, not pixels. ## ## To avoid conversions between pixels and chars, we try to do ## the widening in pixels-only --- using an 'INCRpixelsRIGHT' var. ## ## There are many ways this could be implemented. This is just one. ## This routine, and its partner 'fil_listbox_width_reduce', ## are just routines that seem to work reasonably well. ## ## ARGUMENTS: See the global vars. ## ## CALLED BY: the button command of the button ## .fRcntlbutts2.butFilListRight . ##+############################################################## proc fil_listbox_width_increase {} { global INCRpixelsRIGHT SCREENwidthPx wmPIXELS_top wmPIXELS_left # global CHARWIDTHpixels INCRcharsRIGHT ## An alternate method could be to use 'INCRcharsRIGHT' instead of ## 'INCRpixelsRIGHT', on the frame contents instead of on the frame ## --- to do the increase in chars-only instead of pixels-only. set winXlen [ winfo width . ] set FILwidthPX [winfo width .fRlists.fRfil] set DIRwidthPX [winfo width .fRlists.fRdir] ## FOR TESTING: if {0} { puts "*******************************************************" puts "proc 'fil_listbox_width_increase' : (just entered proc)" puts "filFRAMEwidth via winfo = $FILwidthPX pixels." puts "dirFRAMEwidth via winfo = $DIRwidthPX pixels." puts "window-width via winfo = $winXlen pixels." puts "INCRpixelsRIGHT = $INCRpixelsRIGHT pixels." } ######################################################################## ## We do not try to increase the fil-listbox width if the entire window ## is already at the screen width. I.e. we only do the following ## computations if there is some room to expand the fil-listbox. ######################################################################## if { $winXlen < $SCREENwidthPx } { ## Adjust the 'loc' vars for the window manager border. set winXloc [ winfo rootx . ] set winYloc [ winfo rooty . ] set winXloc [ expr {$winXloc - $wmPIXELS_left} ] set winYloc [ expr {$winYloc - $wmPIXELS_top} ] ############################################################################## ## Increase the window width about as much as the increase in fil-frame-width, ## while keeping the location of the upper-left corner constant. ############################################################################## set winYlen [ winfo height . ] set winXlen [expr {$winXlen + $INCRpixelsRIGHT}] ## FOR TESTING: if {0} { puts "" puts "proc 'fil_listbox_width_increase' : (new WINwidth parm)" puts "winXlen: $winXlen" } wm geometry . ${winXlen}x${winYlen}+${winXloc}+${winYloc} ################################################################### ## After we request an increase to the window size, we increase the ## size of the fil-listbox-frame. ################################################################### set FILwidthPX [expr {$FILwidthPX + $INCRpixelsRIGHT}] ## FOR TESTING: if {0} { puts "" puts "proc 'fil_listbox_width_increase' : (new-FIL & same-DIR width parms)" puts "FILwidthPX: $FILwidthPX" puts "DIRwidthPX: $DIRwidthPX" } ###################################################################### ## Increase the fil-frame width, but keep the dir-frame width the same. ###################################################################### ## Strangely, the dir-lisbox expands until I added the ## 'pack propagate ... false' statement --- on the fil-listbox, ## NOT the dir-listbox. ## ## It seems that the 'pack propagate' should not be necessary (since ## I am specifically configuring the width of the 2 listboxes). AND ## it seems the 'pack propagate ... false' should be applied to ## the dir-listbox, NOT the fil-listbox. None of this section works the ## way I would expect. ###################################################################### .fRlists.fRdir configure -width $DIRwidthPX .fRlists.fRfil configure -width $FILwidthPX pack propagate .fRlists.fRfil false } ## END OF if { $winXlen < $SCREENwidthPx } } ## END OF PROC 'fil_listbox_width_increase' ##+############################################################## ## PROC 'fil_listbox_width_reduce' ##+############################################################## ## PURPOSE: ## This routine reduces the width of the 'filenames' listbox frame ## (measured in pixels). ## ## Note that our intent is to decrease the width of the frame's ## 2 interior widgets (label and listbox). Those widths are ## specified in chars, not pixels. ## ## To avoid conversions between pixels and chars, we try to do ## the narrowing in pixels-only --- using an 'INCRpixelsLEFT' var. ## ## There are many ways this could be implemented. This is just one. ## This routine, and its partner 'fil_listbox_width_increase', ## are just routines that seem to work reasonably well. ## ## ARGUMENTS: See the global vars. ## ## CALLED BY: the button command of the button ## .fRcntlbutts2.butFilListLeft . ##+############################################################## proc fil_listbox_width_reduce {} { global INCRpixelsLEFT FILminwidthPX wmPIXELS_top wmPIXELS_left # global CHARWIDTHpixels INCRcharsLEFT ## An alternate method could be to use 'INCRcharsLEFT' instead of ## 'INCRpixelsLEFT', on the frame contents instead of on the frame ## --- to do the reduction in chars-only instead of pixels-only. set FILwidthPX [winfo width .fRlists.fRfil] set DIRwidthPX [winfo width .fRlists.fRdir] set winXlen [ winfo width . ] ## FOR TESTING: if {0} { puts "*****************************************************" puts "proc 'fil_listbox_width_reduce' : (just entered proc)" puts "filFRAMEwidth via winfo = $FILwidthPX pixels, on entering proc." puts "dirFRAMEwidth via winfo = $DIRwidthPX pixels, on entering proc." puts "window-width via winfo = $winXlen pixels." puts "INCRpixelszLEFT = $INCRpixelsLEFT pixels." } ###################################################################### ## We do not try to decrease the fil-listbox width if it is ## already at a designated minwidth. I.e. we only do the following ## computations if there is some latitude to decrement the fil-listbox. ###################################################################### if { $FILwidthPX > $FILminwidthPX } { set FILwidthPX [expr {$FILwidthPX - $INCRpixelsLEFT}] set deltaFILwidthPX $INCRpixelsLEFT if { $FILwidthPX < $FILminwidthPX } { set deltaFILwidthPX [expr {($FILwidthPX + $INCRpixelsLEFT) - $FILminwidthPX}] set FILwidthPX $FILminwidthPX } ## FOR TESTING: if {0} { puts "" puts "proc 'fil_listbox_width_reduce' : (new-FIL & same-DIR width parms)" puts "FILwidthPX: $FILwidthPX" puts "DIRwidthPX: $DIRwidthPX" } ###################################################################### ## Decrease the fil-frame width, but keep the dir-frame width the same. ###################################################################### ## Strangely, the dir-listbox decrements (along with the fil-listbox) ## unless I add the 'pack propagate ... false' statement --- on the ## fil-listbox, NOT the dir-listbox. ## ## It seems that the 'pack propagate' should not be necessary (since ## I am specifically configuring the width of the 2 listboxes). AND ## it seems the 'pack propagate ... false' should be applied to ## the dir-listbox, NOT the fil-listbox. None of this works the ## way I would expect. ###################################################################### .fRlists.fRdir configure -width $DIRwidthPX .fRlists.fRfil configure -width $FILwidthPX pack propagate .fRlists.fRfil false ######################################################### ## We narrow the window by the amount we narrow the ## file listbox --- as follows. ######################################################### set winXloc [ winfo rootx . ] set winYloc [ winfo rooty . ] ## Adjust the 'loc' vars for the window manager border. set winXloc [ expr {$winXloc - $wmPIXELS_left} ] set winYloc [ expr {$winYloc - $wmPIXELS_top} ] ############################################################################ ## Reduce the window width about as much as the decrease in fil-frame-width, ## while keeping the location of the upper-left corner constant. ############################################################################ set winYlen [ winfo height . ] set winXlen [expr {$winXlen - $deltaFILwidthPX}] ## FOR TESTING: if {0} { puts "" puts "proc 'fil_listbox_width_reduce' : (new WINwidth parm)" puts "winXlen: $winXlen" } wm geometry . ${winXlen}x${winYlen}+${winXloc}+${winYloc} } ## END OF if { $FILwidthPX > $FILminwidthPX } } ## END OF PROC 'fil_listbox_width_reduce' ##+##################################################################### ## PROC 'tall_win' ##+##################################################################### ## PURPOSE: ## This procedure is invoked to 'TALL' the Tk window. ## Several methods could be used. ## For now, we query the current height (and location) of the window ## (with 'winfo') and upsize the height by ~20%. ## ## The user can keep clicking the button to upsize ~20% per click. ## ## ARGUMENTS: see the global vars ## ## CALLED BY: .fRcntlbutts2.buttTallWin ##+##################################################################### proc tall_win {} { global INCRfactor wmPIXELS_top wmPIXELS_left set winXlen [ winfo width . ] set winYlen [ winfo height . ] set winXloc [ winfo rootx . ] set winYloc [ winfo rooty . ] ## FOR TESTING: # puts "Entering 'tall_win' proc :" # puts "winXlen : $winXlen" # puts "winYlen : $winYlen" # puts "winXloc : $winXloc" # puts "winYloc : $winYloc" ## Increase the window height about 20%. set winYlen [expr {int(floor ( $INCRfactor * $winYlen ))} ] ## Adjust the 'loc' vars for the window manager border --- ## because 'winfo rootx' and 'winfo rooty' do not get the right values. set winXloc [ expr $winXloc - $wmPIXELS_left ] set winYloc [ expr $winYloc - $wmPIXELS_top ] ## Apply the new window height. wm geometry . ${winXlen}x${winYlen}+${winXloc}+${winYloc} ## FOR TESTING: # puts "Exiting 'tall_win' proc :" # puts "winXlen : $winXlen" # puts "winYlen : $winYlen" # puts "winXloc : $winXloc" # puts "winYloc : $winYloc" } ## END OF PROC 'tall_win' ##+##################################################################### ## PROC 'short_win' ##+##################################################################### ## PURPOSE: ## This procedure is invoked to 'SHORTEN' the Tk window. ## Several methods could be used. ## For now, we query the current height (and location) of the window ## (with 'winfo') and downsize the height by ~20%. ## ## The user can keep clicking the button to downsize ~10% per click. ## ## ARGUMENTS: see the global vars ## ## CALLED BY: .fRcntlbutts2.buttShortWin ##+##################################################################### proc short_win {} { global INCRfactor wmPIXELS_top wmPIXELS_left set winXlen [ winfo width . ] set winYlen [ winfo height . ] set winXloc [ winfo rootx . ] set winYloc [ winfo rooty . ] ## FOR TESTING: # puts "Entering 'short_win' proc :" # puts "winXlen : $winXlen" # puts "winYlen : $winYlen" # puts "winXloc : $winXloc" # puts "winYloc : $winYloc" ## Reduce the window height about 20%. set winYlen [expr {int(floor ( $winYlen / $INCRfactor ))} ] ## Adjust the 'loc' vars for the window manager border --- ## because 'winfo rootx' and 'winfo rooty' do not get the right values. set winXloc [ expr $winXloc - $wmPIXELS_left ] set winYloc [ expr $winYloc - $wmPIXELS_top ] ## Apply the new window height. wm geometry . ${winXlen}x${winYlen}+${winXloc}+${winYloc} ## FOR TESTING: # puts "Exiting 'short_win' proc :" # puts "winXlen : $winXlen" # puts "winYlen : $winYlen" # puts "winXloc : $winXloc" # puts "winYloc : $winYloc" } ## END OF PROC 'short_win' ##+######################################################################## ## PROC 'popup_msgVarWithScroll' ##+######################################################################## ## PURPOSE: Report help or error conditions to the user. ## ## We do not use focus,grab,tkwait in this proc, ## because we use it to show help when the GUI is idle, ## and we may want the user to be able to keep the Help ## window open while doing some other things with the GUI ## such as putting a filename in the filename entry field ## or clicking on a radiobutton. ## ## For a similar proc with focus-grab-tkwait added, ## see the proc 'popup_msgVarWithScroll_wait' in a ## 3DterrainGeneratorExaminer Tk script. ## ## REFERENCE: page 602 of 'Practical Programming in Tcl and Tk', ## 4th edition, by Welch, Jones, Hobbs. ## ## ARGUMENTS: A toplevel frame name (such as .fRhelp or .fRerrmsg) ## and a variable holding text (many lines, if needed). ## ## CALLED BY: 'help' button ##+######################################################################## ## To have more control over the formatting of the message (esp. ## words per line), we use this 'toplevel-text' method, ## rather than the 'tk_dialog' method -- like on page 574 of the book ## by Hattie Schroeder & Mike Doyel,'Interactive Web Applications ## with Tcl/Tk', Appendix A "ED, the Tcl Code Editor". ##+######################################################################## proc popup_msgVarWithScroll { toplevName VARtext } { ## global fontTEMP_varwidth #; Not needed. 'wish' makes this global. ## global env # bell # bell ################################################# ## Set VARwidth & VARheight from $VARtext. ################################################# ## To get VARheight, ## split at '\n' (newlines) and count 'lines'. ################################################# set VARlist [ split $VARtext "\n" ] ## For testing: # puts "VARlist: $VARlist" set VARheight [ llength $VARlist ] ## For testing: # puts "VARheight: $VARheight" ################################################# ## To get VARwidth, ## loop through the 'lines' getting length ## of each; save max. ################################################# set VARwidth 0 ############################################# ## LOOK AT EACH LINE IN THE LIST. ############################################# foreach line $VARlist { ############################################# ## Get the length of the line. ############################################# set LINEwidth [ string length $line ] if { $LINEwidth > $VARwidth } { set VARwidth $LINEwidth } } ## END OF foreach line $VARlist ## For testing: # puts "VARwidth: $VARwidth" ############################################################### ## NOTE: VARwidth works for a fixed-width font used for the ## text widget ... BUT the programmer may need to be ## careful that the contents of VARtext are all ## countable characters by the 'string length' command. ############################################################### ##################################### ## SETUP 'TOP LEVEL' HELP WINDOW. ##################################### catch {destroy $toplevName} toplevel $toplevName # wm geometry $toplevName 600x400+100+50 wm geometry $toplevName +100+50 wm title $toplevName "Note" # wm title $toplevName "Note to $env(USER)" wm iconname $toplevName "Note" ##################################### ## In the frame '$toplevName' - ## DEFINE THE TEXT WIDGET and ## its two scrollbars --- and ## DEFINE an OK BUTTON widget. ##################################### if {$VARheight > 10} { text $toplevName.text \ -wrap none \ -font fontTEMP_fixedwidth \ -width $VARwidth \ -height 30 \ -bg "#f0f0f0" \ -relief raised \ -bd 2 \ -yscrollcommand "$toplevName.scrolly set" \ -xscrollcommand "$toplevName.scrollx set" ## -height $VARheight \ scrollbar $toplevName.scrolly \ -orient vertical \ -command "$toplevName.text yview" scrollbar $toplevName.scrollx \ -orient horizontal \ -command "$toplevName.text xview" } else { text $toplevName.text \ -wrap none \ -font fontTEMP_fixedwidth \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 } button $toplevName.butt \ -text "OK" \ -font fontTEMP_varwidth \ -command "destroy $toplevName" ############################################### ## PACK *ALL* the widgets in frame '$toplevName'. ############################################### ## Pack the bottom button BEFORE the ## bottom x-scrollbar widget, pack $toplevName.butt \ -side bottom \ -anchor center \ -fill none \ -expand 0 if {$VARheight > 10} { ## Pack the scrollbars BEFORE the text widget, ## so that the text does not monopolize the space. pack $toplevName.scrolly \ -side right \ -anchor center \ -fill y \ -expand 0 ## DO NOT USE '-expand 1' HERE on the Y-scrollbar. ## THAT ALLOWS Y-SCROLLBAR TO EXPAND AND PUTS ## BLANK SPACE BETWEEN Y-SCROLLBAR & THE TEXT AREA. pack $toplevName.scrollx \ -side bottom \ -anchor center \ -fill x \ -expand 0 ## DO NOT USE '-expand 1' HERE on the X-scrollbar. ## THAT KEEPS THE TEXT AREA FROM EXPANDING. pack $toplevName.text \ -side top \ -anchor center \ -fill both \ -expand 1 } else { pack $toplevName.text \ -side top \ -anchor center \ -fill both \ -expand 1 } ##################################### ## LOAD MSG INTO TEXT WIDGET. ##################################### ## $toplevName.text delete 1.0 end $toplevName.text insert end $VARtext $toplevName.text configure -state disabled } ## END OF PROC 'popup_msgVarWithScroll' ##+#################################################################### ## END OF procs SECTION. ##+#################################################################### ##+######################## ## Set HELPtext var. ##+######################## set HELPtext \ " ** HELP for this 'Script-Selector' Utility GUI ** This utility provides a Graphical User Interface (GUI) for SELECTING A SCRIPT, from a hierarchy of subdirectories of scripts. This 'script-selector' GUI is presented via a Tk script --- 'scriptSelector_2listboxes.tk'. This 'script-selector' Tk script is intended to be called from a 'file(s)-selector' utility --- the Tk script 'tkScriptApplicator_multifilesSelector_2listboxes.tk'. Via that 'file(s)-selector' GUI, the user can select one or more files (from a listbox) and then click on an 'Apply-a-Script' button to bring up this 'script-selector' GUI, with which to select a script. The selected shell script is to be run, by feeding the selected file(s) to the selected shell script. This set of Tk GUI's does not provide the 'Nautilus' shell scripts that are to be applied to the selected file(s), but such shell scripts can be found in the typical locations for those scripts in the Gnome 2 and MATE desktop-environment systems: \$HOME/.gnome2/nautilus-scripts or \$HOME/.config/caja/scripts ****************************** CONFIGURING THIS Tk GUI SCRIPT: ****************************** The user can change the 'set' statement at the bottom of this 'scriptSelector_2listboxes.tk' Tk script to point to the desired directory that holds the 'Nautilus scripts'. Typically, the 'set' statements look like set DIRshellScripts \"\$env(HOME)/.gnome2/nautilus-scripts\" OR set DIRshellScripts \"\$env(HOME)/.config/caja/scripts\" but the 'Nautilus scripts' could be placed in any directory. Example: \$env(HOME)/ScriptsThatMakeMeHappy ********************************* AN OVERVIEW OF THIS Tk GUI SCRIPT: ********************************* The set of several Tk scripts constituting the 'tkScriptApplicator' mini-system is intended to serve as an alternative to the 'select-files-and-right-click-to-choose-a-script-to-apply- to-the-selected-files' capability of the Gnome2-Nautilus file manager. This 'script-selector' GUI is intended to supply the 'choose-a-script to-apply-to-the-selected-files' part of that capability. There are TWO, SIDE-BY-SIDE LISTBOXES in this 'script-selector' GUI: - a LEFT listbox for SUB-DIRECTORIES of the 'Nautilus' scripts directory and - a RIGHT listbox for the SCRIPTS (files) in a user-selected 'Nautilus' scripts sub-directory. A script is selected by clicking on a filename in the right-hand, files-listbox. The GUI supports a mask for 'filtering' filenames such as '.sh'. In other words, this utility is based on assuming the scripts all have the same suffix, like '.sh', '.ksh', or '.bsh' or whatever. (This avoids having to do a lot of extra processing, say using a 'file' command, to determine the files that are scripts and displaying, or accepting-selection-of, only those files.) This utility is initialized to a mask of '*.sh' under the assumption that all the 'Nautilus scripts' will have a suffix of '.sh'. But that mask can be changed in a 'set DIRFILmask' statement at the bottom of this 'script-selector' script. " ##+#################################################################### ## ADDITIONAL GUI-INITIALIZATION SECTION. ##+#################################################################### ##+##################################################################### ## Set a global variable to turn on messages for testing of ## 'symbolic link' processing in procs ## 'get_subdirs_inCURdir_inclLinks' & and 'get_files_inCURdir_inclLinks'. ##+##################################################################### set DEBUGlink0or1 0 # set DEBUGlink0or1 1 ##+############################################################## ## Set some global variables for the dir and fil listbox width ## widening and narrowing procs. ##+############################################################## set CHARWIDTHpixels [font measure fontTEMP_fixedwidth "0"] ## FOR TESTING: # puts "CHARWIDTHpixels = $CHARWIDTHpixels" set INCRpixelsLEFT 90 set INCRpixelsRIGHT 80 # set INCRpixelsLEFT 50 # set INCRpixelsRIGHT 40 set SCREENwidthPx [winfo screenwidth .] ##+############################################################## ## Set some global variables for the window-height ## incrementing and decrementing procs. ##+############################################################## # set INCRfactor 1.1 set INCRfactor 1.2 # set SCREENheightPx [winfo screenheight .] ##+#################################################################### ## Set the directory that contains the 'Nautilus scripts'. ##+#################################################################### set DIRshellScripts "$env(HOME)/.gnome2/nautilus-scripts" # set DIRshellScripts "$env(HOME)/.config/caja/scripts" # set DIRshellScripts "$env(HOME)/ScriptsThatMakeMeHappy" ##+#################################################################### ## Set the initial value of the 'DIRFILmask' variable. ##+#################################################################### set DIRFILmask "$DIRshellScripts/*.sh" ##+#################################################################### ## Run the 'fill_lists' proc. ##+#################################################################### ## NOTE: 'fill_lists' fills the dir and fil ## listboxes according to the value of DIRFILmask. ## Should have DIRFILmask set properly when calling 'fill_lists'. ##+################################################################### fill_lists ##+#################################################################### ## END OF FINAL GUI-INITIALIZATION SECTION ## *AND* ## END OF this Tk SCRIPT. ##+####################################################################