[uniquename] - 2012aug13 I recently published the code for a color selector Tk script on a page titled [A non-obfuscated color selector GUI], at this site. I have one more 'selector' script that I think would be helpful to publish on this site --- helpful to Tcl-Tk 'newbies' who need complete examples of working, useful scripts to speed up their learning process --- and perhaps helpful to someone still looking for a better font selector GUI. By doing a search on this site with keywords like 'font chooser', you will find that everyone seems to have their own idea as to what they need in a font chooser --- [A little font chooser], [A small font chooser], [Another Font Chooser Dialog]. And there is the code for yet another font chooser in the book 'Practical Programming in Tcl and Tk' (4th edition) by Brent Welch, Ken Jones, and Jeffrey Hobbs --- page 643 --- where this image is shown --- along with the code used to generate it. [font_selection_application_BrentWelchBook4thEd_281x226.gif] I built my font selector based on that code --- but I reorganized the code according to a 'canonical' code structure that I have used for all my Tk scripts written in the past 10 years or so (on the order of a hundred Tk scripts): 0) Set general window parms (win-name, win-position, win-color-scheme, fonts, widget-geom-parms, win-size-control). 1) Define ALL frames (and sub-frames). Pack them. 2) Define & pack all widgets in the frames. 3) Define key/mouse action BINDINGS, if needed. 4) Define PROCS, if needed. 5) Additional GUI initialization (typically with one or more of the procs), if needed. When I need to find a proc (or a binding, or a widget definition, or an example pack statement, etc. etc.) in my scripts, I can find what I need relatively quickly. In addition to the code reorganization, I added a few features to the example presented in the Welch book. Some of those features can be seen by comparing the following image to the image above. [feFontSelectorGUI_screenshot_570x400.png] The code for this font selector GUI is about twice as long (in bytes/characters) as the code for the color selector GUI. Part of the reason it is so long is that I have 'left in' many of my comments that explain the usage of the GUI and the structure and intent of the code. The comments may be helpful to Tcl-Tk 'newbies' -- to help them read the code. In spite of the length, it may be helpful to publish the code here, if only to give some examples of using widgets not used in the color selector GUI script --- to aid Tcl-Tk 'newbies' who are looking for code samples. (Besides, even though it might take more than 30 PageDown key strokes to page through this code image, when considered in bytes, the file holding this code is less than 2% of the size of the typical JPEG file from a 12 megapixel digital camera.) Anyway, the widgets in this font selector GUI include 'listbox' (with y-scrollbar), 'text' widget with both x and y scrollbars, 'radiobutton' widgets, 'checkbutton' widgets --- even a 'tk_optionMenu' button widget (a predecessor of the newer 'spinbox' widget). I stick with the 'tk_optionMenu' widget so that this code will run even for people using an old 7.x era 'wish' interpreter. Alternatively, I could replace the 'tk_optionMenu' button with the 'spinner' proc at the [spinbox] page. It is "a concoction of a 1-line high listbox with two tiny buttons", so it would run with old 7.x wish interpreters. Maybe I will do that --- someday. _______________ After I retired and started assembling the software in my 'Freedom Environment' (FE) software system (see [http://www.freedomenv.com]), I used this font selector GUI as a font setting utility in the 'xpg', 'feAppMenus, and 'feHandyTools' subsystems of my Freedom Environment software. That was my single, main motivation for making this font selector. It is a font selector that blends in with the other Tk GUI's in my FE systems. Plus, it does exactly what I need it to do. I provide all the FE code as free and open source code. A lot of the FE Tcl-Tk scripts (such as the code for the 'xpg' utility) are really too long for a page on this Tcl-Tk wiki. But the code for this font-selector utility is probably useful enough to risk stretching the bounds of propriety in regard to script length in these pages. __________________ In my FE subsystems, I use some Tk 'include' scripts in my scripts to provide some parameter setting that is shared with other utility scripts. I have replaced the corresponding 'source' statements with the essential Tk statements from those 'include' scripts. (Some of the 'include' statements, involving parameters for 'entry' and 'message' widgets, widgets not used in this GUI, may be left in this code --- and commented, for the most part. Those statments can be useful if other GUIs are made using this code as a starting point.) ____________________________ For this particular GUI, when one chooses to display a font in a really big size, the sample text widget needs to be allowed to expand --- to full screen size if necessary. To help restore the window to a more desirable size, when going back to a smaller font size from a really big font size, there is a 'DwnWin' button on the GUI. You can click on that button repeatedly to quickly down-size the window, in increments of about 10%. I find this much more speedy and less frustrating than trying to grab a really thin edge of the window, to drag the window edge, to make a smaller window. _____________________________ As I do in all my Tk scripts, I have put the four main pack parameters --- '-side', '-anchor', '-fill', '-expand' --- on the 'pack' command for the various frames and widgets. That helps me when I am initially testing the behavior of a GUI (the various widgets within it) as I resize the main window. I think I have found a good setting of the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various widgets. In particular ... The 'listbox' widget and the sample 'text' area widget expand/contract appropriately when the window size is changed --- and button and label widgets stay fixed in size and relative-location as the window size is changed. However, if anyone wants to change the way the GUI configures itself as the main window size is changed, they can experiment with the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various widgets --- to get the widget behavior that they want. (I leave it as an 'exercise for the reader' to change the 'tk_optionMenu' widget to a 'spinbox'-like widget.) ====== #!/usr/bin/wish -f ## ## Tk SCRIPT NAME: select_tkFont_standAlone.tk ## ## ('stand-alone' version --- no 'source' statements) ## ## FROM: $FEDIR_TKGUIS = $FEDIR/tkGUIs ## ## where $FEDIR is the installation ## directory of an FE subsystem. ## Ref: www.freedomenv.com ## ##+####################################################################### ## PURPOSE: This TkGUI script provides a GUI for selecting a set of ## Tcl-Tk font specification values (6 of them): ## ## family, size (pixels or points ; negative or positive integers), ## normal/bold, roman/italic, underscore/null, overstrike/null. ## ## This script displays a set of sample text (the alphabet, numeric ## digits, and special characters) in a scrollable text widget. ## ## ----------------------------------------------------------------------- ## ## This script is useful, for example, to a Tcl-Tk app developer ## so that he can offer a user the option of specifying a font ## for a major area of a Tk GUI, like a text area that occupies ## most of the GUI real estate. ## ## In addition, this Tcl-Tk script may be called from a shell ## script. The 6 vars, which go to stdout, can be caught in ## a shell script variable for use in the shell script. ## ##+########### ## GUI DESIGN: ## ## The GUI includes a scrolling listbox to present the font families ## known to Tcl-Tk. The listbox is loaded via the 'font families' Tk command. ## ## We use a Tk optMenu to get the font size. ## (We use 'tk_optionMenu' to display a fixed set of sizes, about 20 of them. ## This may be changed someday to use another widget, like a spinbox widget ## or a faster-spinning widget. ## But, for now, use of 'tk_optionMenu' makes this utility more compatible ## with older versions of the 'wish' interpreter.) ## ## We use a couple of radiobuttons for the user to specify pixels or points. ## ## We use 4 checkboxes for the user to specify bold and/or italic ## and/or underline and/or overstrike. ## ## In summary, we are using 1 listbox, 1 optMenu, ## 2 radiobuttons, and 4 checkbuttons --- to completely specify a font. ## ## The GUI shows an example display of the chosen font: upper and lower case ## alphabetic characters, numerals, and special characters. ## ## We use 'bindings' to the 'selector' widgets, to update the font of the ## sample-text area, as soon as one of the widgets is used. ## ## The GUI also has several buttons --- including OK/UseIt, ## Cancel, and Help buttons. ## ## Clicking on the OK/UseIt button returns the font specification ## (the six specification values) to the calling application. ## ##+##################################################################### ## CALLED BY: In its original 'non-stand-alone' form, the ## 'select_tkFont.tk' script is called by ## the 'shofil.tk' Tk script that is the guts of the ## so-called 'xpg' utility, which is part of the 'FE' ## (Freedom Environment) system. Ref: www.freedomenv.com ## ## Also called by 'make_chest.tk' in the 'feAppMenus' ## and 'feHandyTools' FE subsystems --- ## and probably by more FE Tcl-Tk scripts in the future. ##+##################################################################### ## INPUTS: User selects font properties from the widgets of the ## GUI generated by this script. ## ## OUTPUT: A set of values specifying the font that the user saw ## displayed in a text-numerics-punctuation sample in the GUI. ## ## If the user clicks the 'UseIt' button, the font info for ## the user-selected font is sent to stdout. ## ## Sample output string: { helvetica -12 { bold roman null null } } ## --- in this case, an array of 4 items. ## Actually this is a Tcl list with 3 items, ## where the 3rd item is, ordinarily, a list ## of 2 to 4 items. ##+##################################################################### ## CALL FORMAT: (in a Tcl-Tk script) ## ## [ exec $feDIR_tkguis/select_tkFont.tk ] (with no input parameters) ## ## ------------ ## EXAMPLE CALL in a shell script: ## ## TEMP=`$FEDIR_TKGUIS/select_tkFont.tk` ## ## (Note: A command like 'cut' or 'awk' could separate the values in TEMP ## into 6 separate variables.) ##+######################################################################## ## 'CANONICAL' STRUCTURE OF THIS CODE: ## ## 0) Set general window parms (win-name,win-position,color-scheme, ## fonts,widget-geom-parameters,win-size-control,etc.). ## 1a) Define ALL frames (and sub-frames). ## 1b) Pack ALL frames and sub-frames. ## 2) Define & pack all widgets in the frames. ## ## 3) Define key and mouse/touchpad/touch-sensitive-screen action ## BINDINGS, if needed. ## 4) Define PROCS, if needed. ## 5) Additional GUI INITIALIZATION (typically with one or two procs ## from section 4), if needed. ## ## Some detail on the code structure of this particular Tk script: ## ## 1a) Define ALL frames: ## ## Top-level : 'fRleft' and 'fRright' ## ## Sub-frames of 'fRleft': none, just one listbox with scrollbar(s) ## ## Sub-frames of 'fRright' (top to bottom): ## - 'fRbuttons' for OK/UseIt and Cancel (and Help and Color) buttons ## - 'fRsize' for optMenu and 2 radiobuttons ## - 'fRcheck1' for bold and italic checkbuttons as well as ## underline and overstrike checkbuttons ## - 'fRtext' for two text widgets (one to hold, in one line, the ## font family name and font size ## --- the 2nd, in about 8 lines, to hold sample text) ## ## 1b) Pack ALL frames. ## ## 2) Define & pack all widgets in the frames -- basically going through ## frames & their interiors in left-to-right, top-to-bottom order: ## ## 3) Define bindings: none currently ## ## 4) Define procs: ## - 'loadfams2listbox' - for GUI initialization ## - 'font_update' - for bindings to font-attribute setting widgets ## - 'put_vars' - for the OK/UseIt button ## ## - 'getset_bkgdcolor' - for Color button ## (gets r255,g255,b255 via a GUI with 3 slider bars, ## then calls 'set_palette') ## - 'set_palette' - used by the 'getset_bkgdcolor' proc --- ## and may be used for GUI initializaton ## (sets window color scheme from r255,g255,b255) ## - 'downsize_win' - for the DwnWin button ## ## 5) Additional GUI initialization: run 'loadfams2listbox' ## ##+####################################################################### ## DEVELOPED WITH: Tcl-Tk 8.4 on Ubuntu 9.10 (2009oct version, 'Karmic Koala'). ## wish> puts "$tcl_version $tk_version" ## 8.4 8.4 ##+######################################################################## ## FE system Copyright 2006+ by Blaise Montandon ##+######################################################################## ## MAINTENANCE HISTORY: ## Started by: Blaise Montandon 2010aug21 Started development, on Ubuntu 9.10. ## for use in Freedom Environment (FE) ## subsystems, such as 'xpg', ## 'feAppMenus', and 'feHandyTools'. ## See www.freedomenv.com ## Changed by: Blaise Montandon 2012aug Converted 'select_tkFont.tk' script, ## the 2011oct05 version that is ## used the FE subsystems, ## to be 'stand-alone'. I.e. the code ## from Tk 'include' files that are ## incorporated into the script code ## via 'source' statements, was ## hard-coded into this script --- ## to make a 'stand-alone' script. ##+####################################################################### ## For window title: set VERSIONfontsel "ver2011oct05" ## For debugging msgs, below: set THISscript "select_tkFont_standAlone.tk" ##+####################################################################### ## SET THE TOP WINDOW NAME. ##+####################################################################### wm title . "FE Font Selector - $VERSIONfontsel" wm iconname . "FontSel" # catch { wm title . "$env(FE_WINTITLE)" } # catch { wm iconname . "$env(FE_ICONTITLE)" } ##+####################################################################### ## SET THE TOP WINDOW POSITION. ##+####################################################################### wm geometry . +50+50 # catch {eval wm geometry . "$env(FE_FONTSEL_GEOM)" } ##+####################################################################### ## SET COLOR SCHEME (palette) FOR THE WINDOW. ##+####################################################################### ## and ##+####################################################################### ## SET BACKGROUND COLOR vars FOR WIDGETS, like ENTRY & LISTBOX widgets. ##+####################################################################### ## Gray palette set r255 210 set g255 210 set b255 210 set COLOR_pal [format "#%02X%02X%02X" $r255 $g255 $b255] tk_setPalette $COLOR_pal ## "#BCD2EE" is a "lightsteelblue2". Change it if you want. ## "#FFFFFF" (white) may be too bright. set feBGcolor_entry "#BCD2EE" set feBGcolor_listbox $feBGcolor_entry ##+####################################################################### ## SET FONT VARS for use in the 'font create' statements below. ##+####################################################################### set FONTsize 14 set FONT_SMALLsize 12 ## For variable width: set FONT_varwidth \ " -family {comic sans ms} -size -$FONTsize -weight bold -slant roman " set FONT_SMALL_varwidth \ " -family {comic sans ms} -size -$FONT_SMALLsize -weight normal -slant roman " ## For fixed width: set FONT_fixedwidth \ " -family {dejavu sans mono} -size -$FONTsize -weight bold -slant roman " set FONT_SMALL_fixedwidth \ " -family {dejavu sans mono} -size -$FONT_SMALLsize -weight normal -slant roman " ##+##################################################################### ## DEFINE (temporary) FONT NAMES using 'font create'. ## The font names are to be used in '-font' widget specs below. ##+##################################################################### eval font create fontTEMP_button $FONT_varwidth eval font create fontTEMP_label $FONT_varwidth eval font create fontTEMP_entry $FONT_fixedwidth eval font create fontTEMP_listbox $FONT_fixedwidth eval font create fontTEMP_text $FONT_fixedwidth # eval font create fontTEMP_msg $FONT_fixedwidth eval font create fontTEMP_SMALL_button $FONT_SMALL_varwidth eval font create fontTEMP_SMALL_label $FONT_SMALL_varwidth eval font create fontTEMP_SMALL_entry $FONT_SMALL_fixedwidth eval font create fontTEMP_SMALL_listbox $FONT_SMALL_fixedwidth eval font create fontTEMP_SMALL_text $FONT_SMALL_fixedwidth # eval font create fontTEMP_SMALL_msg $FONT_SMALL_fixedwidth ##+####################################################################### ## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS. ## (e.g. padx,pady for Buttons) ##+####################################################################### ## For BUTTON widgets: set fePADY_button 0 set fePADX_button 0 set feBDwidth_button 2 ## For LABEL widgets: set feBDwidth_label 2 ## For ENTRY widgets: set feBDwidth_entry 2 ## For LISTBOX widgets: set feBDwidth_listbox 2 ## For TEXT and MESSAGE widgets: set feBDwidth_text 2 # set feBDwidth_msg 2 ##+####################################################################### ## SET the top window MIN-SIZE (roughly). ## ## We could do a better job here by using 'font measure' (for width) ## and 'font metric' (for height) commands on the initially chosen fonts ## --- along with taking into account the text in widgets across the GUI ## (for width) and taking into account the frames up-and-down the GUI ## (for height). That technique would allow for adapting this script to ## various device sizes --- simply by changing the default fonts above. ##+####################################################################### wm minsize . 650 400 catch {eval wm minsize . "$env(FE_FONTSEL_MINSIZE)" } ## Alternative to minsize (make win not resizable). ## That is not suitable to this app. ## Some fonts can cause the sample text area to overflow. ## We need that widget to expand as needed. # wm resizable . 0 0 ##+####################################################### ## Set WINDOW-MANAGER TOP and LEFT-SIDE WIDTHS (in pixels) ## for the currently used window manager. ##+####################################################### ## NOTE: ## We could probably generate these widths using ## some Tk queries like ## ## [winfo . rootx] and [winfo . rooty] ## ## versus what we get by parsing ## ## [wm geometry .] ## ## But, we avoid doing this processing by simply setting ## the values here and allowing the user to change the values ## --- once for all the FE subsystem GUIs --- according ## to the window manager being used. ## ## (Besides, there is a question whether such a routine ## based on those Tk queries would work for ALL Linux/Unix ## and other OS window managers.) ## ## USED BY: the 'downsize_win' proc. ##+############################################################ set wmPIXELS_top 23 set wmPIXELS_left 3 ##+####################################################################### ## GET AN INITIAL FONT DEFINITION PARAMETERS STRING, if it is ## being passed into this Tk script. ## ## We use this in FE subsytems to position the font listbox at a specific ## font, and have that font displayed in the sample text area ## when this GUI first comes up. ## ## The string should be a string like this: ## ## -family {dejavu sans mono} -size -12 -weight bold -slant roman -underline 0 -overstrike 0 ## ## The underline, overstrike, and slant parms (and even weight) could be missing, ## in which case, the values would be defaulted to Tcl-Tk defaults. ##+####################################################################### set argc [llength $argv] if {$argc != 0} { ## The following join of the argv Tcl-list into a string ## works for either one-word or multi-word fams in args. set feINITfontparms [join $argv " "] ## FOR TESTING: # puts "feINITfontparms: $feINITfontparms" eval font create fontINIT $feINITfontparms } else { eval font create fontINIT $FONT_fixedwidth } ##+#################################################################### ##+#################################################################### ## DEFINE *ALL* THE FRAMES: ## ## Top-level : 'fRleft' and 'fRright' ## ## Sub-frames of 'fRleft': none, just one listbox with scrollbar(s) ## ## Sub-frames of 'fRright' (top to bottom): ## ## - 'fRbuttons' for OK and Cancel (and Help) buttons ## - 'fRsize' for optMenu and 2 radiobuttons ## - 'fRcheck1' for bold and italic checkbuttons & ## underline and overstrike checkbuttons ## - 'fRtext' for two text widgets (one to hold the ## font family name, or more specs) ##+#################################################################### ##+#################################################################### ## FOR TESTING of expansion of frames (esp. during window expansion): # set feRELIEF_frame raised # set feBDwidth_frame 2 set feRELIEF_frame flat set feBDwidth_frame 0 frame .fRleft -relief $feRELIEF_frame -borderwidth $feBDwidth_frame frame .fRright -relief $feRELIEF_frame -borderwidth $feBDwidth_frame frame .fRright.fRbuttons \ -relief $feRELIEF_frame -borderwidth $feBDwidth_frame frame .fRright.fRspacer1 \ -relief $feRELIEF_frame -borderwidth $feBDwidth_frame -height 20 frame .fRright.fRsize \ -relief $feRELIEF_frame -borderwidth $feBDwidth_frame frame .fRright.fRcheck1 \ -relief $feRELIEF_frame -borderwidth $feBDwidth_frame frame .fRright.fRspacer2 \ -relief $feRELIEF_frame -borderwidth $feBDwidth_frame -height 20 frame .fRright.fRtext \ -relief $feRELIEF_frame -borderwidth $feBDwidth_frame ##+######################################################## ## PACK *ALL* the FRAMES. ##+######################################################## pack .fRleft \ -side left \ -anchor w \ -fill both \ -expand 1 pack .fRright \ -side right \ -anchor e \ -fill both \ -expand 1 ## PACK the subframes of '.fRright'. pack .fRright.fRbuttons \ -side top \ -anchor n \ -fill none \ -expand 0 # -fill x pack .fRright.fRspacer1 \ -side top \ -anchor n \ -fill x \ -expand 0 pack .fRright.fRsize \ -side top \ -anchor n \ -fill x \ -expand 0 pack .fRright.fRcheck1 \ -side top \ -anchor n \ -fill x \ -expand 0 pack .fRright.fRspacer2 \ -side top \ -anchor n \ -fill x \ -expand 0 pack .fRright.fRtext \ -side top \ -anchor center \ -fill both \ -expand 0 ##+################################################################ ##+################################################################ ## START DEFINING & PACKING WIDGETS WITHIN THEIR FRAMES. ##+################################################################ ##+################################################################ ##+######################################################## ## IN THE 'fRleft' frame -- DEFINE 1 listbox widget, ## with vertical scrollbar. ##+######################################################## listbox .fRleft.listbox \ -width 30 \ -height 25 \ -font fontTEMP_listbox \ -relief raised \ -borderwidth 2 \ -state normal \ -yscrollcommand ".fRleft.scrbary set" # -width 0 \ # -height 0 \ scrollbar .fRleft.scrbary -command ".fRleft.listbox yview" pack .fRleft.listbox \ -side left \ -anchor center \ -fill both \ -expand 1 pack .fRleft.scrbary \ -side right \ -anchor center \ -fill y \ -expand 0 ##+############################################################# ## START DEFINING WIDGETS and PACKING in THE *RIGHT-SIDE* FRAME: ##+############################################################# ##+########################################################## ## IN THE 'fRright.fRbuttons' frame -- ## DEFINE several BUTTONS ## --- OK/UseIt, Cancel, DwnWin/Update, Help, ColorMe. ##+########################################################## ## Label Widget on which to write the number of families ## read in by the 'loadfams2listbox' proc. label .fRright.fRbuttons.label \ -text "" \ -font fontTEMP_label \ -justify left \ -anchor w \ -relief flat \ -bd 0 ## Buttons: OK/UseIt, Cancel, DwnWin, Help, ColorMe button .fRright.fRbuttons.buttOK \ -text "UseIt" \ -font fontTEMP_button \ -padx $fePADX_button \ -pady $fePADY_button \ -relief raised \ -bd $feBDwidth_button \ -command {put_vars} button .fRright.fRbuttons.buttCANCEL \ -text "Cancel" \ -font fontTEMP_button \ -padx $fePADX_button \ -pady $fePADY_button \ -relief raised \ -bd $feBDwidth_button \ -command {exit} button .fRright.fRbuttons.buttDWNWIN \ -text "DwnWin" \ -font fontTEMP_button \ -padx $fePADX_button \ -pady $fePADY_button \ -relief raised \ -bd $feBDwidth_button \ -command { downsize_win } ## Could implement this Help button someday. ## It IS implemented in the FE systems. # button .fRright.fRbuttons.buttHELP \ # -text "Help" \ # -font fontTEMP_button \ # -padx $fePADX_button \ # -pady $fePADY_button \ # -relief raised \ # -bd $feBDwidth_button \ # -command "eval exec $feDIR_tkguis/shofil.tk \ # $feDIR_helps/select_tkFont.hlp &" button .fRright.fRbuttons.buttCOLOR \ -text "ColorMe" \ -font fontTEMP_button \ -padx $fePADX_button \ -pady $fePADY_button \ -relief raised \ -bd $feBDwidth_button \ -command {getset_bkgdcolor} ##+######################################## ## Pack the widgets in the 'fRbuttons' frame ##+######################################## pack .fRright.fRbuttons.buttOK \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRright.fRbuttons.buttCANCEL \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRright.fRbuttons.buttDWNWIN \ -side left \ -anchor w \ -fill none \ -expand 0 ## Implement someday? like in FE systems. # pack .fRright.fRbuttons.buttHELP \ # -side left \ # -anchor w \ # -fill none \ # -expand 0 pack .fRright.fRbuttons.buttCOLOR \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRright.fRbuttons.label \ -side left \ -anchor w \ -fill none \ -expand 0 ##+######################################################## ## IN THE 'fRright.fRsize' frame -- ## DEFINE 1 OPTMENU widget (for specifying font-size) --- ## and 2 RADIOBUTTONS (pixels,points) ## and 1 LABEL widget. ##+######################################################## label .fRright.fRsize.label \ -text "Size :" \ -font fontTEMP_label \ -justify left \ -anchor w \ -relief flat \ -bd 2 pack .fRright.fRsize.label \ -side left \ -anchor w \ -fill none \ -expand 0 ## Option menu of sizes: # set fontSIZE 12 set fontSIZE 14 set menu1 [ tk_optionMenu .fRright.fRsize.optbuttSIZE fontSIZE \ 7 8 9 10 11 12 13 14 15 16 17 18 19 20 24 28 32 36 48 60 72 ] ## A shorter list used by Welch: ## 7 8 10 12 14 18 24 36 72 .fRright.fRsize.optbuttSIZE configure -font fontTEMP_button .fRright.fRsize.optbuttSIZE configure -pady $fePADY_button $menu1 entryconfigure 0 -command font_update $menu1 entryconfigure 1 -command font_update $menu1 entryconfigure 2 -command font_update $menu1 entryconfigure 3 -command font_update $menu1 entryconfigure 4 -command font_update $menu1 entryconfigure 5 -command font_update $menu1 entryconfigure 6 -command font_update $menu1 entryconfigure 7 -command font_update $menu1 entryconfigure 8 -command font_update $menu1 entryconfigure 9 -command font_update $menu1 entryconfigure 10 -command font_update $menu1 entryconfigure 11 -command font_update $menu1 entryconfigure 12 -command font_update $menu1 entryconfigure 13 -command font_update $menu1 entryconfigure 14 -command font_update $menu1 entryconfigure 15 -command font_update $menu1 entryconfigure 16 -command font_update $menu1 entryconfigure 17 -command font_update $menu1 entryconfigure 18 -command font_update $menu1 entryconfigure 19 -command font_update $menu1 entryconfigure 20 -command font_update ## DEFINE Radiobuttons for units - pixels or points : radiobutton .fRright.fRsize.radbuttPIX \ -text "Pixels" \ -font fontTEMP_button \ -anchor w \ -variable fontUNITS \ -value "pix" \ -selectcolor "#cccccc" \ -relief flat \ -bd 2 radiobutton .fRright.fRsize.radbuttPTS \ -text "Points" \ -font fontTEMP_button \ -anchor w \ -variable fontUNITS \ -value "pts" \ -selectcolor "#cccccc" \ -relief flat \ -bd 2 ## fontUNITS is the var for the Pixels & Points radiobuttons. set PIXperPOINT "[format "%.3f" [tk scaling]]" label .fRright.fRsize.labelRight \ -text " ($PIXperPOINT pixels/point)" \ -font fontTEMP_label \ -justify left \ -anchor w \ -relief flat \ -bd 2 ## PACK the '.fRsize' buttons. pack .fRright.fRsize.optbuttSIZE \ .fRright.fRsize.radbuttPIX \ .fRright.fRsize.radbuttPTS \ .fRright.fRsize.labelRight \ -side left \ -anchor w \ -fill none \ -expand 0 ##+######################################################## ## IN THE 'fRright.fRcheck1' frame -- ## DEFINE 4 CHECKBUTTON widgets ## (for bold,italic,underline,overstrike). ##+######################################################## set fontBOLD01 1 checkbutton .fRright.fRcheck1.chkbuttBOLD \ -text "Bold" \ -font fontTEMP_button \ -variable fontBOLD01 \ -selectcolor "#cccccc" \ -relief raised set fontITALIC01 0 checkbutton .fRright.fRcheck1.chkbuttITALIC \ -text "Italic" \ -font fontTEMP_button \ -variable fontITALIC01 \ -selectcolor "#cccccc" \ -relief raised ## Two more checkbuttons: set fontUNDERLINE01 0 checkbutton .fRright.fRcheck1.chkbuttUNDERLINE \ -text "Underline" \ -font fontTEMP_button \ -variable fontUNDERLINE01 \ -selectcolor "#cccccc" \ -relief raised set fontOVERSTRIKE01 0 checkbutton .fRright.fRcheck1.chkbuttOVERSTRIKE \ -text "Overstrike" \ -font fontTEMP_button \ -variable fontOVERSTRIKE01 \ -selectcolor "#cccccc" \ -relief raised ## PACK the checkbuttons: pack .fRright.fRcheck1.chkbuttBOLD \ .fRright.fRcheck1.chkbuttITALIC \ .fRright.fRcheck1.chkbuttUNDERLINE \ .fRright.fRcheck1.chkbuttOVERSTRIKE \ -side left \ -anchor w \ -fill none \ -expand 0 ##+######################################################## ## IN THE 'fRright.fRtext' frame -- ## DEFINE 2 TEXT areas ## --- 1 for family name (and size), ## and 1 below the first text area --- for the text sample ## (alphabet, numerics, special chars). ##+######################################################## ##+################################################################### ## Text widget#1, 'txtFONTNAME', displays the current font family name. ##+################################################################### text .fRright.fRtext.txtFONTNAME \ -relief raised \ -borderwidth 2 \ -height 1 \ -width 38 \ -wrap none \ -font fontTEMP_button ##+######################################################## ## PACK the 1st text widget in the '.fRright.fRtext' frame. ##+######################################################## pack .fRright.fRtext.txtFONTNAME \ -side top \ -anchor center \ -fill x \ -expand 1 ##+############################################################## ## Initialize the FONTNAME text area with the current family name ## of the initial font. (Also show the font size --- via index 3 ## in the 'font actual' query.) ##+############################################################## set fontFAMILY [ lindex [font actual fontINIT] 1 ] set fontSIZE [ lindex [font actual fontINIT] 3 ] if { $fontSIZE < 0 } { set fontSIZE [expr {0 - $fontSIZE}] ## fontUNITS is the var for the Pixels & Points radiobuttons. set fontUNITS "pix" } else { set fontUNITS "pts" } ## FOR TESTING: # set fontACTUAL [font actual fontINIT] # puts "'font actual fontINIT' gives : $fontACTUAL" .fRright.fRtext.txtFONTNAME insert end "Family: $fontFAMILY ; Size: $fontSIZE $fontUNITS" ##+############################################################## ## Text widget#2, 'txtSAMPLE', displays a sampler of characters ## to be re-rendered each time the user changes a font attribute. ##+############################################################## text .fRright.fRtext.txtSAMPLE \ -relief raised \ -borderwidth 4 \ -height 9 \ -width 18 \ -wrap none \ -font fontINIT \ -yscrollcommand ".fRright.fRtext.scrbary set" \ -xscrollcommand ".fRright.fRtext.scrbarx set" scrollbar .fRright.fRtext.scrbary \ -command ".fRright.fRtext.txtSAMPLE yview" scrollbar .fRright.fRtext.scrbarx \ -orient horizontal \ -command ".fRright.fRtext.txtSAMPLE xview" pack .fRright.fRtext.scrbary \ -side right \ -anchor center \ -fill y \ -expand 0 pack .fRright.fRtext.scrbarx \ -side bottom \ -anchor center \ -fill x \ -expand 0 pack .fRright.fRtext.txtSAMPLE \ -side left \ -anchor w \ -fill both \ -expand 1 ##+############################################# ## Load this text area with the 'insert' command. ##+############################################# .fRright.fRtext.txtSAMPLE insert end \ " ABCDEFGHIJKLM 41-4D hex NOPQRSTUVWXYZ 4E-5A hex abcdefghijklm 61-6D hex nopqrstuvwxyz 6E-7A hex 01234 30-34 hex 56789 35-39 hex !\"#$%&'()* 20-2A hex +,-./:;<=>? 2B-2F,3A-3F hex @\[\\\]^_`{|}~ 40,5B-60,7B-7E hex " ## SPECIAL CHARS WERE (like in Welch's Tcl-Tk book ## --- but the brackets were not escaped in the book) : ## ## !@#$%^&*()_+- ## =\[\]{} ;:\"'`~, ## .<>/?\\| ## ## Changed so there are exactly 11 chars on the 3 lines ## of special characters. ##+################################################# ## Keep the user from changing the sample text, ## in case they type in the widget. ##+################################################# .fRright.fRtext.txtSAMPLE configure -state disabled ##+######################################################## ## PACK the 2nd text widget in the '.fRright.fRtext' frame. ##+######################################################## pack .fRright.fRtext.txtSAMPLE \ -side top \ -anchor center \ -fill x \ -expand 1 ##+##################################################################### ## END OF MAIN SECTION TO SETUP THE GUI. ##+##################################################################### ##+##################################################################### ##+##################################################################### ## DEFINE BINDINGS: ## - Run the 'font_update' proc whenever one of the font ## attribute widgets have a event. ##+##################################################################### bind .fRleft.listbox "font_update" bind .fRright.fRsize.radbuttPIX "font_update" bind .fRright.fRsize.radbuttPTS "font_update" bind .fRright.fRcheck1.chkbuttBOLD "font_update" bind .fRright.fRcheck1.chkbuttITALIC "font_update" bind .fRright.fRcheck1.chkbuttUNDERLINE "font_update" bind .fRright.fRcheck1.chkbuttOVERSTRIKE "font_update" ##+##################################################################### ##+##################################################################### ## DEFINE PROCEDURES: ## - 'loadfams2listbox' - for GUI initialization ## - 'font_update' - for Button1-Release bindings to font-attribute widgets ## - 'put_vars' - for OK/UseIt button ## ## - 'getset_bkgdcolor' - for Color button ## (gets r255,g255,b255 via a GUI with 3 slider bars, ## then calls 'set_palette') ## - 'set_palette' - used by the 'getset_bkgdcolor' proc --- ## and may be used for GUI initializaton ## (sets window color scheme from r255,g255,b255) ## - 'downsize_win' - for 'DwnWin' button ##+##################################################################### ##+##################################################################### ##+##################################################################### ## PROCEDURE -- loadfams2listbox ## ## Purpose: Loads font family names to listbox. ## Done once, at GUI initialization. ## ## Called by: at bottom of this Tk script ##+##################################################################### proc loadfams2listbox { } { ## 'fontFAMILY' is the family name we got when setting up text widget#2, ## the 'txtSAMPLE' widget. global fontFAMILY ## Get the font family names. # set allfams [font families] set allfams [lsort -dictionary [font families]] ## Get the number of names. ## (We could display the num fonts, for user info.) set numfams [llength $allfams] .fRright.fRbuttons.label configure -text "$numfams Font Families " ## Make sure the listbox is empty. .fRleft.listbox delete 0 end ## Insert each family name into the listbox list. foreach family $allfams { .fRleft.listbox insert end $family } #################################################### ## INITIALIZE THE POSITION IN THE LISTBOX so that ## the font of the 'textSAMPLE' text widget is ## selected and in view. #################################################### set INDEXofINITfont [ lsearch -exact $allfams $fontFAMILY ] ## FOR TESTING: # puts "INDEXofINITfont: $INDEXofINITfont" if { "$INDEXofINITfont" != "-1" } { set seeINDEX [expr {$INDEXofINITfont - 4} ] if { "$seeINDEX" < "0" } { set seeINDEX "0" } .fRleft.listbox see $seeINDEX .fRleft.listbox selection set $INDEXofINITfont } } ## END of 'loadfams2listbox' proc ##+##################################################################### ## PROCEDURE -- font_update ## ## Purpose: Reconfigures the font parms of the ## 2 text widgets in the sample text area. ## ## Called by: bindings (above) on various radio & check buttons ##+##################################################################### proc font_update {} { global fontFAMILY fontSIZE fontUNITS fontBOLD01 fontITALIC01 \ fontUNDERLINE01 fontOVERSTRIKE01 set sel_index [ .fRleft.listbox curselection ] if { $sel_index != "" } { set fontFAMILY [ .fRleft.listbox get $sel_index ] } ## FOR TESTING: # puts "font_update: fontFAMILY = $fontFAMILY" # puts "font_update: fontSIZE = $fontSIZE" # puts "font_update: fontUNITS = $fontUNITS" ## Load in the fontname in the text-1 area with the 'insert' command. .fRright.fRtext.txtFONTNAME delete 1.0 end .fRright.fRtext.txtFONTNAME insert end "Family: $fontFAMILY ; Size: $fontSIZE $fontUNITS" ## Configure the font parms of the 2 text areas. if { "$fontBOLD01" == "1" } { set fontBOLD "bold" } else { set fontBOLD "normal" } if { "$fontITALIC01" == "1" } { set fontITALIC "italic" } else { set fontITALIC "roman" } if { "$fontUNITS" == "pix" } { set fontSIZEsigned [ expr {-$fontSIZE} ] } else { set fontSIZEsigned $fontSIZE } set fontPARMS [list -family $fontFAMILY -size $fontSIZEsigned \ -weight $fontBOLD -slant $fontITALIC \ -underline $fontUNDERLINE01 -overstrike $fontOVERSTRIKE01 ] .fRright.fRtext.txtSAMPLE configure -font $fontPARMS } ## END of 'font_update' proc ##+##################################################################### ## PROCEDURE -- put_vars ## ## Purpose: Puts font-setting parms to stdout. ## ## Called by: button .fRright.fRbuttons.buttOK ##+##################################################################### proc put_vars { } { global fontFAMILY fontSIZE fontUNITS fontBOLD01 fontITALIC01 \ fontUNDERLINE01 fontOVERSTRIKE01 if { "$fontBOLD01" == "1" } { set fontBOLD "bold" } else { set fontBOLD "normal" } if { "$fontITALIC01" == "1" } { set fontITALIC "italic" } else { set fontITALIC "roman" } if { "$fontUNITS" == "pix" } { set fontSIZEsigned [ expr {-$fontSIZE} ] } else { set fontSIZEsigned $fontSIZE } puts "-family \"$fontFAMILY\" -size $fontSIZEsigned \ -weight $fontBOLD -slant $fontITALIC \ -underline $fontUNDERLINE01 -overstrike $fontOVERSTRIKE01" exit } ## END of 'put_vars' proc ##+##################################################################### ## 'getset_bkgdcolor' PROCEDURE ##+##################################################################### ## ## PURPOSE: ## This procedure is invoked to get an RGB triplet (r255 g255 b255) ## via 3 RGB slider bars. ## ## Then uses 'set_palette' proc to set window color scheme, esp. ## color of text widget, .fRmain.text. ## ## Arguments: none ## ## CALLED BY: .fRright.fRbuttons.buttCOLOR button ##+##################################################################### proc getset_bkgdcolor {} { global r255 g255 b255 feDIR_tkguis ## FOR TESTING: # puts "r255: $r255" # puts "g255: $g255" # puts "b255: $b255" set TEMPrgb [ exec \ ./sho_colorvals_via_sliders3rgb.tk \ $r255 $g255 $b255] # $feDIR_tkguis/sho_colorvals_via_sliders3rgb.tk \ ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } ## 2010aug23 changed output of 'sho_colorvals_via_sliders3rgb.tk'. ## It no longer has the strings 'R255=','G255=','B255='. ## ## WAS: scan $TEMPrgb "R255=%s ; G255=%s ; B255=%s" r255 g255 b255 scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" # puts "r255: $r255" # puts "g255: $g255" # puts "b255: $b255" eval set r255 $r255 eval set g255 $g255 eval set b255 $b255 set_palette } ## END OF 'getset_bkgdcolor' PROCEDURE ##+##################################################################### ## 'set_palette' PROCEDURE ##+##################################################################### ## ## PURPOSE: ## This procedure is invoked to set the 'palette' for this tkGUI's ## window --- based on three global vars: r255 g255 b255. ## Uses the 'tk_setPalette' Tcl-Tk command. ## ## [Could also set the foreground [text] colors, for all the widgets in the GUI, ## to black or (off-)white depending on a calculated luminance value of the chosen ## palette background color. ## ## Since setting the foreground color is built into the 'tk_setPalette' command, ## we do not try to set the foreground color. But, if that ever proves ## desirable, this proc would be a good place to do it.] ## ## Arguments: 3 global vars: r255 g255 b255 ## ## CALLED BY: proc 'getset_bkgdcolor', which is invoked by ## .fRright.fRbuttons.buttCOLOR button ## ## (Could be called as an initialization procedure at the ## bottom of this script if we wanted to set the palette ## there instead of in the colors-setting section above.) ##+##################################################################### proc set_palette {} { global r255 g255 b255 set COLOR4gui [format "#%02X%02X%02X" $r255 $g255 $b255] tk_setPalette $COLOR4gui } ## END OF 'set_palette' PROCEDURE ##+##################################################################### ## 'downsize_win' PROCEDURE ##+##################################################################### ## ## PURPOSE: ## This procedure is invoked to downsize the Tk window. ## This is handy after the display of a very large-sized font has ## caused the window to expand mightily. ## ## METHOD: ## Several methods could be used. ## For now, we query the current width and height of the window ## (with 'winfo') and downsize those by 10%. ## ## Arguments: none ## ## CALLED BY: .fRright.fRbuttons.buttDWNWIN ## ## The user can keep clicking the button to downsize 10% per click. ## ##+##################################################################### proc downsize_win {} { ## These wm border parms should be set in 'set_widget_geom.tki'. global wmPIXELS_top wmPIXELS_left set winXlen [ winfo width .] set winYlen [ winfo height .] set winXloc [ winfo rootx . ] set winYloc [ winfo rooty . ] ## Reduce the window size about 10% set winXlen [expr {int( 0.9 * $winXlen )} ] set winYlen [expr {int( 0.9 * $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} } ## END OF 'downsize_win' PROCEDURE ##+###################################################### ## Additional GUI INITIALIZATION: ##+###################################################### ## The default values of various widgets (checkbutton and ## radiobutton) are set above but could be set here. ## They can/should be set according to an initial, default font. # set fontSIZE 14 # set fontUNITS "pix" # set fontBOLD01 1 # set fontITALIC01 0 # set fontUNDERLINE01 0 # set fontOVERSTRIKE01 0 ## Load the listbox. loadfams2listbox ====== I hope that some Tcl-Tk 'newbies' can learn from this useful script and its many widget types. Thanks to Brent Welch et. al. for putting in the tremendous amount of work it takes to provide 'lasting' reference works on the Tcl-Tk programming system --- where twenty to thirty years is 'lasting' in this fast moving information age. And thanks to Ousterhout for - the '''vision''' to create the Tk toolkit, - the excellent initial '''implementation''' of that vision that makes Tk such a joy to use compared to coding GUI's in a language such as C or C++, along with the many library routines involved (He has sheltered us --- leaving us only the essentials to specify --- hiding a lot of coding, underneath the covers, that we should not really have to do. Yet he allowed for a tremendous amount of flexibility and capability. He made a tremendous number of excellent choices.) - the '''perspiration''' that it took to implement those hundreds (nay thousands) of GUI parameters and functions that give Tcl-Tk code nerds (I mean warriors) such an array of coding weapons. ___ [uniquename] 2012oct28 '''UPDATE''' The code that was above has been replaced. The new code includes the following changes: * Comments were re-organized and improved --- and it was noted in the comments that this is a 'stand-alone' script that was converted from a script that used 'source' statements to incorporate 'common' code from some Tk 'include' files. * Indenting was improved to a more consistent format, and some white-space at the start of many widget-definition and widget-packing lines was removed. * Braces were added to 'expr' statments. * The bindings section was compacted. * The font setting section was compacted somewhat. * The initial part of the code was re-organized to follow the 'canonical' format that I use in most of the other Tk scripts that I have posted here. That format is described on the page titled [A Canonical Structure for Tk Code --- and variations]. <>GUI