#!/usr/bin/wish -f ## ## Tk SCRIPT NAME: dirSelector_orEditListOfFavoriteDirs_1listbox.tk ## ## WHERE: typically installed in an 'apps' directory ## such as $HOME/apps/tkScriptApplicator ## ##+####################################################################### ## PURPOSE: This Tk script provides a GUI for selecting a directory ## from a list of 'favorite' directories in a user favorites file: ## fave_dirs.lis ## ## The GUI includes ONE scrolling listbox to present the ## directory names that are extracted from the '.lis' file ## when this Tk script starts up. ## ## Clicking on a 'UseIt' button on the GUI causes a selected ## directory name to be put to 'stdout'. ## ## An 'EditDirs' button on the GUI allows for editing the '.lis' file. ## ## --- ## ## This Tk script is intended (originally) to be called from a ## 'file(s)-selector' utility, the Tk script ## 'tkScriptApplicator_multifilesSelector_2listboxes.tk'. ## This Tk script is called via a 'Jump2Dir' button on the ## 'file(s)-selector' GUI. ## --- ## The main function of the 'tkScriptApplicator' mini-system: ## ## Via the 'file(s)-selector' GUI, ## the user can select one or more files in a listbox, ## and then click on an 'Apply-a-Script' button to execute another ## Tk script, 'scriptSelector_2listboxes.tk', to bring up a GUI ## from which to select a SHELL SCRIPT filename. ## ## The selected shell script is then run, by feeding the selected ## file(s) to the selected shell script. ## ##+############ ## INSTALLATION: ## ## This Tk script and the other 2 Tk scripts --- ## 'tkScriptApplicator_multifilesSelector_2listboxes.tk' and ## 'scriptSelector_2listboxes.tk' --- may be installed in a ## a sub-directory of the user's home directory. Example: ## $HOME/apps/tkScriptApplicator ## ## The 'fave_dirs.lis' file may also be installed in a sub-directory ## of the user's home directory. For example, if the several Tk scripts ## of the 'tkScriptApplicator' mini-system are installed in directory ## $HOME/apps/tkScriptApplicator ## the 'fave_dirs.lis' file may be installed in that same directory. ## ## A 'DIRscripts' variable at the bottom of this script is used to ## hold the name of the directory that contains this script. That ## same directory is used to specify the location of the ## 'fave_dirs.lis' file, but that location can be changed. ## ## For example, in a large site with workstations that have an ## '/apps' directory NFS-mounted from a central server, the 3 Tk scripts ## could be installed in a central directory such as ## /apps/tkScriptApplicator ## ## Then the fully-qualified name of the '.lis' file in this script ## could be set to ## $env(HOME)/apps/tkScriptApplicator/fave_dirs.lis ## This would allow each user at the large site to have their own ## directory-favorites file. ## ##+################## ## OTHER APPLICATIONS: ## ## Note that although this Tk GUI script was written to be used ## in the 'tkScriptApplicator' mini-system, this Tk GUI script could ## be used in other file-selector applications. ## ## This script is useful to a Tcl-Tk app developer so that ## he/she can offer a user a choice of directories via a 'Jump2Dir' ## or 'FaveDir' or 'DirBookmarks' button in a Tk GUI script. ## ## In addition to being called from a Tk script, ## this Tcl-Tk script may be called from any *SHELL* script which ## needs to prompt the user for a directory name from a list of ## 'favorite directories'. ## ##+##################################################################### ## CALL FORMAT: ## ## EXAMPLE CALL in a TCL-TK script) ## ## set DIRnew [ exec $DIRscripts/dirSelector_orEditListOfFavorites_1listbox.tk ] ## ## (with no input parameters) ## ## ------------ ## EXAMPLE CALL in a SHELL script: ## ## DIR_NEW=`$DIR_SCRIPTS/dirSelector_orEditListOfFavorites_1listbox.tk` ## ## ##+################################### ## The GUI DESIGN and OPERATION BASICS: ## ## This GUI shows several buttons including: ## 'UseIt' (OK), 'Cancel', 'EditDirs', and several others. ## ## The 'EditDirs' button allows for editing the 'fave_dirs.lis' file. ## ## The following 'sketch' shows 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. ## ## ---------------------------------------------------------------------------------------- ## Directory Selector - 'Favorites' ## [window title] ## ---------------------------------------------------------------------------------------- ## ## TopLevel Frame ## names (no SubFrames) ## | ## V ## ## .fRbuttons {UseIt} {Cancel} {EditDirs} {Help} {tallWin} {shortWin} ## ## .fRmsg SELECT a directory and click 'UseIt' --- or 'Cancel'. ## If you 'EditDirs', this window may close when done. Start ## this selector interface again to select from the edited file. ## ## [This initial message is in a label widget.] ## ## .fRlistbox ------------------------------------------------------------ ## | ## Fully-qualified DIRECTORY NAMES - A ## | ## 'favorites'. | ## | ###################### | ## | ## My Home Directories: | ## | ###################### | ## | ~ | ## | ~/Documents | ## | ~/Downloads | ## | ~/Pictures | ## | ~/Desktop | ## | ~/apps | ## | ~/IMAGE_CAPTURE | ## | ~/.mozilla | ## | ~/.thumbnails | ## | #################### | ## | ## Other Directories: | ## | #################### | ## | /tmp | ## | /usr | ## | /usr/share | ## | /usr/lib | ## | /lib | ## | /etc | ## | /dev | ## | /var | ## | / | ## | V ## <----------------------------------------------------------> ## ## That is the GUI --- simply 3 frames, top to bottom. ## ## The listbox has x and y scrollbars --- shown here on the bottom and on ## the right of the listbox. ## ## The contents of the listbox are the lines of the 'fave_dirs.lis' file. ## As indicated here, the '.lis' file can include comment lines indicated ## by a '#' sign in column one. Clicking on a comment line does NOT ## result in a selection. ## ## Clicking on the 'UseIt' button causes a selected directory name to ## be passed back to the calling script. A 'puts' statement sends the ## directory name to 'stdout'. ## ## Clicking on the 'EditDirs' button causes the 'fave_dirs.lis' file ## to be brought up in a text editor. The text editor can be set in ## a 'set EDITORtext' statement at the bottom of this Tk script. ## ##+############## ## GUI components: ## ## From the GUI 'sketch' above, it is seen that the GUI consists of ABOUT: ## ## 6 'button' widgets ## 1 'label' widget (in the 'fRmsg' frame) ## 1 'listbox' widget (with scrollbars) ## 0 'entry' widgets ## 0 'text' widgets (except for the text widget in the proc used to show Help) ## 0 'checkbutton' widgets ## 0 'radiobutton' widgets ## 0 'scale' widgets ## 0 'canvas' widgets ## ##+##################################################################### ## INPUTS: User selects a directory in the listbox and clicks the ## 'UseIt' button. ## ## OUTPUT: A directory name (fully-qualified) to stdout. ## ##+######################################################################## ## 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 (and sub-frames, if any). ## 1b) Pack the frames. ## ## 2) 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: ## ## Top-level : 'fRbuttons', 'fRmsg', 'fRlistbox' ## (packed top-to-bottom, not left-to-right) ## ## Sub-frames: none ## ## 1b) Pack ALL frames. ## ## 2) Define & pack all widgets in the frames -- basically going through ## frames & their interiors in left-to-right and/or top-to-bottom order: ## ## 3) Define BINDINGS: See BINDINGS section in code below. ## ## 4) Define PROCS: ## ## 'loaddirs2listbox' - to read the '.lis' file into the listbox. ## ## 'put_vars' - called by the 'UseIt' button, to put the ## selected dirname to stdout. ## ## 'popup_msgVarWithScroll' - used to show the $HELPtext var ; also can ## be used to show user various popup messages ## for info, warnings, errors, etc. ## ## And for 2 'window-size' buttons: ## 'short_win' - to shorten the window with a single click ## 'tall_win' - to lengthen the window with a single click ## ## 5) ADDITIONAL GUI INITIALIZATION: run 'loaddirs2listbox' ## ##+####################################################################### ## 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 2014jul21 Started developing this script ## and auxiliary Tk scripts ## based on similar FE scripts from ## the 'feHappyScripts' system. ## Updated 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 VERSIONdirsel "ver2014jul29" ##+###################################################### ## Set WINDOW TITLE and POSITION. ##+###################################################### wm title . \ "Directory-Selector - 'Favorites' - $VERSIONdirsel" wm iconname . "DirSelector" wm geometry . +30+45 ##+###################################################### ## Set the COLOR SCHEME for the window and its widgets --- ## such as listbox and entry field background color. ##+###################################################### tk_setPalette "#f0f0f0" set listboxBKGD "#ffffff" # set entryBKGD "#ffffff" # set msgBKGD "#e0e0e0" set msgBKGD "#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'. ## ## "You can specify pixel-based sizes with negative numbers." ##+######################################################## 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. ## LISTBOX widget geom settings: set initWIDTHchars_listbox 25 ## This width can be set to accomodate any longer ## 'favorite directory' names of the user(s). set initHEIGHTchars_listbox 30 set minHEIGHTchars_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} { ## ENTRY widget geom settings: set BDwidthPx_entry 2 ## We use '-relief sunken' for all 'entry' widgets. ## 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 'fRbottons' frame: set aRtext(buttOK) "UseIt" set aRtext(buttCANCEL) "Cancel" set aRtext(buttEDITdirs) "EditDirs" set aRtext(buttHELP) "Help" set aRtext(buttTallWin) "tallWin" set aRtext(buttShortWin) "shortWin" # set aRtext(buttFontSize) "TogFontSize" ## For the 'fRmsg' frame: set aRtext(labelMSG) \ "SELECT a directory and click 'UseIt' --- or 'Cancel'. If you click 'EditDirs', this window may close when the editor starts up. You can start this selector interface again to select from the edited file." ## END OF if { "$VARlocale" == "en"} ##+###################################################################### ## Set a MIN-SIZE of the window (roughly). ## ## For WIDTH, allow for the buttons in frame '.fRbuttons'. ## ## For HEIGHT, allow for the stacked frames: ## 1 char high for the '.fRbuttons' frame ## 3 chars high for the '.fRmsg' frame ## N chars high for the '.fRlistbox' frame ## where N = $minHEIGHTchars_listbox + 1 char, where the 1 char ## allows some room for the horizontal scrollbar of the listbox. ##+##################################################################### ## FOR WIDTH: (allow for the several buttons in frame '.fRbuttons') set minWinWidthPx [font measure fontTEMP_varwidth \ "$aRtext(buttOK) $aRtext(buttCANCEL) $aRtext(buttEDITdirs) \ $aRtext(buttHELP) $aRtext(buttTallWin) $aRtext(buttShortWin)"] ##+############################################################# ## For HEIGHT --- for ## 1 char high for the '.fRbuttons' frame ## 3 chars high for the '.fRmsg' frame ## N chars high for the '.fRlistbox' frame ## -------- ## 4+N chars high for the 3 frames ## where N = $minHEIGHTchars_listbox + 1 char, where the 1 char ## allows some room for the horizontal scrollbar of the listbox. ##+############################################################ set charHeightPx [font metrics fontTEMP_varwidth -linespace] set minWinHeightPx [expr {(5 + $minHEIGHTchars_listbox) * $charHeightPx}] ## Add about 20 pixels for top-bottom window decoration -- ## and some pixels for top-and-bottom of frame/widget borders ## (~3 widgets x 4 pixels/widget = 12 pixels). set minWinHeightPx [expr {32 + $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 'fRlistbox' frame 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* THE FRAMES: ## ## Top-level : 'fRbuttons', 'fRmsg', 'fRlistbox' ## ## Sub-frames: none ##+#################################################################### ##+#################################################################### 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 .fRbuttons -relief $RELIEF_frame -bd $BDwidthPx_frame frame .fRmsg -relief $RELIEF_frame -bd $BDwidthPx_frame frame .fRlistbox -relief $RELIEF_frame -bd $BDwidthPx_frame ##+######################################################## ## PACK *ALL* the FRAMES. ##+######################################################## pack .fRbuttons \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRmsg \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRlistbox \ -side top \ -anchor nw \ -fill both \ -expand 1 ##+################################################################ ##+################################################################ ## START DEFINING & PACKING WIDGETS WITHIN THEIR FRAMES. ##+################################################################ ##+################################################################ ##+##################################################################### ## IN THE '.fRbuttons' frame -- DEFINE several buttons ## --- UseIt (OK), Cancel, EditDirs, ... THEN PACK THEM. ##+##################################################################### button .fRbuttons.buttOK \ -text "$aRtext(buttOK)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {put_vars} button .fRbuttons.buttCANCEL \ -text "$aRtext(buttCANCEL)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {exit} button .fRbuttons.buttEDITdirs \ -text "$aRtext(buttEDITdirs)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {edit_dirslist} button .fRbuttons.buttHELP \ -text "$aRtext(buttHELP)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {popup_msgVarWithScroll .topHELP "$HELPtext"} button .fRbuttons.buttTallWin \ -text "$aRtext(buttTallWin)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {tall_win} button .fRbuttons.buttShortWin \ -text "$aRtext(buttShortWin)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {short_win} ## Here is a label Widget on which to write the number of directories ## read in by the 'loaddirs2listbox' proc. label .fRbuttons.labelNdirs \ -text "" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ##+########################################## ## Pack all the widgets in frame '.fRbuttons'. ##+########################################## ## NOTE: You can rearrange the buttons by ## simply changing this packing order. ##+########################################## pack .fRbuttons.buttCANCEL \ .fRbuttons.buttOK \ .fRbuttons.buttHELP \ .fRbuttons.buttEDITdirs \ .fRbuttons.buttTallWin \ .fRbuttons.buttShortWin \ .fRbuttons.labelNdirs \ -side left \ -anchor w \ -fill none \ -expand 0 ##+##################################################################### ## IN THE '.fRmsg' frame -- DEFINE a LABEL widget and PACK IT. ##+##################################################################### label .fRmsg.label \ -text "$aRtext(labelMSG)" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief raised \ -bd $BDwidthPx_label \ -bg $msgBKGD pack .fRmsg.label \ -side left \ -anchor w \ -fill x \ -expand 0 ##+######################################################## ## IN THE 'fRlistbox' frame -- DEFINE 1 listbox widget, ## with vertical and horizontal scrollbars. ##+######################################################## listbox .fRlistbox.listbox \ -width $initWIDTHchars_listbox \ -height $initHEIGHTchars_listbox \ -font fontTEMP_fixedwidth \ -relief sunken \ -borderwidth $BDwidthPx_listbox \ -bg $listboxBKGD \ -selectmode single \ -yscrollcommand ".fRlistbox.scrbary set" \ -xscrollcommand ".fRlistbox.scrbarx set" scrollbar .fRlistbox.scrbary \ -orient vertical \ -command ".fRlistbox.listbox yview" scrollbar .fRlistbox.scrbarx \ -orient horizontal \ -command ".fRlistbox.listbox xview" ## Pack the scrollbars, then the listbox. pack .fRlistbox.scrbarx \ -side bottom \ -anchor sw \ -fill x \ -expand 0 pack .fRlistbox.scrbary \ -side right \ -anchor ne \ -fill y \ -expand 0 pack .fRlistbox.listbox \ -side left \ -anchor nw \ -fill both \ -expand 1 ##+##################################################################### ## END OF MAIN SECTION TO SETUP THE GUI. ##+##################################################################### ##+##################################################################### ##+##################################################################### ## DEFINE BINDINGS: none ##+##################################################################### ##+##################################################################### ##+##################################################################### ##+##################################################################### ## DEFINE PROCEDURES: ## 'edit_dirslist' - for 'EditDirs' button ## ## 'loaddirs2listbox' - for the 'ADDITIONAL GUI INITIALIZATION' ## section at the bottom of this script ## ## 'put_vars' - for the 'UseIt' button ## ## 'popup_msgVarWithScroll' - for the 'Help' button ## ##+##################################################################### ##+##################################################################### ##+##################################################################### ## PROC 'edit_dirslist' ##+##################################################################### ## PURPOSE: Edits the dirs list file, then reloads the listbox. ## ## CALLED BY: .fRbuttons.buttEDITdirs ##+##################################################################### proc edit_dirslist { } { global EDITORtext DIRSFILEfullname # global RETCODEedit ## I can't get 'gedit' to run in foreground mode. ## It wants to start up and then allow following Tcl-Tk ## statements to execute. ## ## The statements following the following statement, like ## 'loaddirs2listbox', proceed to execute ## (try to refill the listbox) while user is editing. # exec $EDITORtext "$DIRSFILEfullname" ## CLUTZY WORKAROUND METHOD to run in foreground mode ## (avoid executing following Tcl-Tk statements while the ## editor is 'up') : Use 'xterm -hold -e'. # exec xterm -hold -e $EDITORtext "$DIRSFILEfullname" # loaddirs2listbox ## 'update' is NOT needed after the loaddirs call. ############################################################# ## A CLEANER WORKAROUND: Start editor and issue exit command. ############################################################# ## NOTE: For some editors, if an instance is already 'up', ## a new edit window may not pop up. This '.lis' file may ## appear in an already-opened edit window. This may not ## be obvious to the user. A popup message could be added here. ############################################################## exec $EDITORtext "$DIRSFILEfullname" ## FOR TESTING: # puts "Exiting proc 'edit_dirslist'" exit } ## END OF PROC 'edit_dirslist' ##+##################################################################### ## PROC 'loaddirs2listbox' ##+##################################################################### ## PURPOSE: Loads directory names to listbox. ## Done once, at GUI initialization. ## ## CALLED BY: in the 'ADDITIONAL GUI INITIALIZATION' section ## at bottom of this Tk script ##+##################################################################### proc loaddirs2listbox { } { global DIRSFILEfullname env ## FOR TESTING: # puts "Entering proc 'loaddirs2listbox'." ## Make sure listbox is empty. .fRlistbox.listbox delete 0 end ## Open the directory-favorites file and load it into the listbox. set f [open "$DIRSFILEfullname"] while {![eof $f]} { set rec [gets $f] set char1 [ string index $rec 0 ] ## We could avoid loading comment lines into the listbox. ## But we go ahead and load them. # if { "$char1" == "#" } {continue} ## We could avoid loading blank lines into the listbox. ## But we go ahead and load them. # if { "$rec" == "" } {continue} ## Replace string '$HOME', if any, by the contents of $env(HOME). set HOMEstartIDX [string first {$HOME} $rec] set newrec "$rec" if { $HOMEstartIDX != -1 && "$char1" != "#"} { set HOMEendIDX [expr $HOMEstartIDX + 4] set newrec [string replace $rec $HOMEstartIDX $HOMEendIDX $env(HOME)] } .fRlistbox.listbox insert end $newrec } ## END of read-file loop close $f ## Show the number of lines loaded in a label on the GUI. set numdirs [.fRlistbox.listbox size] # set numdirs [expr $numdirs - 1] ## Not needed if $rec empty check is added. .fRbuttons.labelNdirs configure -text "$numdirs Lines in Listbox" #################################################### ## INITIALIZE THE POSITION IN THE LISTBOX so that ## a particular line is in view. ################################ ## COMMENTED for now. #################################################### # .fRlistbox.listbox see $seeINDEX } ## END OF PROC 'loaddirs2listbox' ##+##################################################################### ## PROC 'put_vars' ##+##################################################################### ## PURPOSE: Puts parms (just dirname for now) to stdout. ## ## CALLED BY: button .fRbuttons.buttOK ('UseIt') ##+##################################################################### proc put_vars { } { global env ## Get the directory from a selected line in the listbox. set sel_index [ .fRlistbox.listbox curselection ] if { $sel_index != "" } { set dirname [ .fRlistbox.listbox get $sel_index ] } else { # set dirname "" return } ## If the line selected is a comment line, return nothing. set char1 [ string index $dirname 0 ] if { "$char1" == "#" } {return} ## If the line selected is a null line, return nothing. if { "$dirname" == "" } {return} ## If the line selected starts with '~', replace the '~' ## with the user's home directory --- and return the dirname, ## and exit the GUI. if { "$char1" == "~" } { set dirname "$env(HOME)[string range $dirname 1 end]" } puts "$dirname" exit } ## END OF PROC 'put_vars' ##+##################################################################### ## PROC 'tall_win' PROCEDURE ##+##################################################################### ## PURPOSE: ## This procedure is invoked to 'TALL-en' (lengthen) the Tk window. ## Several methods could be used. ## For now, we query the current width and height of the window ## (with 'winfo') and upsize the height by 20%. ## ## ARGUMENTS: See the globals. ## ## CALLED BY: .fRbuttons.buttUPwin ## ## NOTE: The user can keep clicking the button to downsize ~20% per click. ##+##################################################################### # set INCRfactor 1.2 set INCRfactor 1.5 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 winXlen [expr {int(floor ( $INCRfactor * $winXlen ))} ] set winYlen [expr {int(floor ( $INCRfactor * $winYlen ))} ] ## Adjust the 'loc' vars for the window manager border. set winXloc [ expr {$winXloc - $wmPIXELS_left} ] set winYloc [ expr {$winYloc - $wmPIXELS_top} ] wm geometry . ${winXlen}x${winYlen}+${winXloc}+${winYloc} ## FOR TESTING: # puts "Leaving 'tall_win' proc:" # puts "winXlen : $winXlen" # puts "winYlen : $winYlen" # puts "winXloc : $winXloc" # puts "winYloc : $winYloc" } ## END OF PROC 'tall_win' ##+##################################################################### ## 'short_win' PROCEDURE ##+##################################################################### ## 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%. ## ## ARGUMENTS: See the globals. ## ## CALLED BY: .fRbuttons.buttDWNwin ## ## NOTE: The user can keep clicking the button to downsize ~10% per click. ## ##+##################################################################### 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 winXlen [expr {int(floor ( $winXlen / $INCRfactor ))} ] set winYlen [expr {int(floor ( $winYlen / $INCRfactor ))} ] ## Adjust the 'loc' vars for the window manager border. set winXloc [ expr {$winXloc - $wmPIXELS_left} ] set winYloc [ expr {$winYloc - $wmPIXELS_top} ] wm geometry . ${winXlen}x${winYlen}+${winXloc}+${winYloc} ## FOR TESTING: # puts "Leaving '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 'Directory Selector (Favorites)' Utility ** This utility provides a Graphical User Interface (GUI) for selecting a directory from a list of 'favorite' directories in a user favorites file: fave_dirs.lis This GUI is presented by a 'directory-selector' Tk script --- 'dirSelector_orEditListOfFavoriteDirs_1listbox.tk'. The GUI includes ONE scrolling listbox to present the directory names that are extracted from the '.lis' file when this Tk script starts up. Clicking on a 'UseIt' button on the GUI causes a selected directory name to be put to 'stdout'. An 'EditDirs' button on the GUI allows for editing the '.lis' file. --- This Tk script is intended (originally) to be called from a 'file(s)-selector' utility of the 'tkScriptApplicator' mini-system --- the Tk script 'tkScriptApplicator_multifilesSelector_2listboxes.tk'. Via that 'file(s)-selector' GUI, the user can select one or more files in a listbox, and then click on an 'Apply-a-Script' button to execute another Tk script, 'scriptSelector_2listboxes.tk', to bring up a GUI from which to select a SHELL SCRIPT filename. The selected shell script is then run, by feeding the selected file(s) to the selected shell script. In other words, the 'tkScriptApplicator' mini-system consists mainly of 3 Tk GUI scripts: - a 'file(s)-selector' GUI - a 'script-selector' GUI - a 'directory-selector' GUI and - a 'fave_dirs.lis' text file. ************ INSTALLATION: ************ This Tk script and the other 2 Tk scripts --- 'tkScriptApplicator_multifilesSelector_2listboxes.tk' and 'scriptSelector_2listboxes.tk' --- may be installed in a a sub-directory of the user's home directory. Example: \$HOME/apps/tkScriptApplicator The 'fave_dirs.lis' file may also be installed in a sub-directory of the user's home directory. For example, if the several Tk scripts of the 'tkScriptApplicator' mini-system are installed in directory \$HOME/apps/tkScriptApplicator the 'fave_dirs.lis' file may be installed in that same directory. A 'DIRscripts' variable at the bottom of this script is used to hold the name of the directory that contains this script. That same directory is used to specify the location of the 'fave_dirs.lis' file, but that location can be changed. For example, in a large site with workstations that have an '/apps' directory NFS-mounted from a central server, the 3 Tk scripts could be installed in a central file-server directory such as /apps/tkScriptApplicator Then the fully-qualified name of the '.lis' file in this Tk script could be set to 'home directory' filename \$env(HOME)/apps/tkScriptApplicator/fave_dirs.lis This can be done by simply changing a 'set DIRSFILEfullname' statement at the bottom of this Tk script. This would allow each user at the large site to have their own directory-favorites file --- whether the user home-directories were 'mounted' from a central file-server OR on local workstations. ****************** OTHER APPLICATIONS: ****************** Note that although this Tk GUI script was written to be used in the 'tkScriptApplicator' mini-system, this Tk GUI script could be used in other file-selector applications where a directory-selector is needed. This script is useful to a Tcl-Tk app developer so that he/she can offer a user a choice of directories via a 'Jump2Dir' or 'FaveDir' or 'DirBookmarks' button in a Tk GUI script. In addition to being called from a *Tk* script, this Tcl-Tk script may be called from any *SHELL* script which needs to prompt the user for a directory name from a list of 'favorite directories'. " ##+###################################################### ## ADDITIONAL GUI INITIALIZATION section: ##+###################################################### ##+################################################### ## Set the GUI text-editor to use on the '.lis' file. ##+################################################### # set EDITORtext "/usr/bin/kedit" # set EDITORtext "/usr/bin/gedit" # set EDITORtext "/usr/bin/scite" set EDITORtext "$env(HOME)/apps/gscite_2.27/SciTE" ##+############################################### ## Get the directory that contains this Tk script. ##+############################################### ## FOR TESTING: # puts "argv0: $argv0" # set DIRscripts "." # set DIRscripts "[pwd]" # set DIRscripts "$env(HOME)/apps/tkScriptApplicator" set DIRscripts "[file dirname $argv0]" ##+################################################# ## PUT the full filename of the 'fave_dirs.lis' file ## in a var, for use in a couple of procs. ##+################################################# # set DIRSFILEfullname "$env(HOME)/apps/tkScriptApplicator/fave_dirs.lis" set DIRSFILEfullname "$DIRscripts/fave_dirs.lis" ##+################################################# ## Load the listbox. ##+################################################# loaddirs2listbox