#!/usr/bin/wish -f ## ##+####################################################################### ## NOTE: ## If the 'wish' interpreter is in another directory, like ## /usr/local/bin, you, as root, can make a soft-link from 'wish' there ## to /usr/bin/wish --- with a command like ## ln -s /usr/bin/local/wish /usr/bin/wish ## The form of this command: ## ln -s ##+####################################################################### ## Tk SCRIPT NAME: tkSpeedGun-Convert-Select_kph-mph-etc.tk ## ##+####################################################################### ## PURPOSE: This TkGUI script provides a GUI for showing speeds ## between absolute zero and several thousand kilometers-per-hour ## --- in at least three different units: ## - kilometers-per-hour (kph) ## - miles-per-hour (mph) ## - 'wild' units, like lightyears-per-byr(billion years), say ## LPB for short, where we can convert kph to LPB with the ## factor 0.926 LPB/kph. In other words, one kph is approx. ## equal to one lightyear-per-billion-years. ## ## (We could add other units, such as meters-per-second.) ## ## These 3 different units are shown (and selected for conversion) ## via 3 'sliders' of 3 Tk 'scale' widgets. ## ## These 3 different (corresponding) numbers are also shown ## in 3 'text' widgets, a few characters wide --- from which ## a user can copy-and-paste the numbers from this GUI window ## to some other window. ## ## For any 'slider' change, this GUI script IMMEDIATELY updates ## the location of the other 2 'SLIDERS'. ## ## The 3 TEXT widgets, showing the speed in the 3 different ## units, are also IMMEDIATELY updated whenever any one of the 3 ## scale widget 'sliders' are changed. ## ## By clicking on a 'UseIt' button on the GUI, this script ## returns a string containing the current speed (in the ## 3 different units) to a calling script/application. ## ## This script will accept a speed (in kph) which is ## used to initialize the ## - setting of the 3 'sliders', and ## - the numbers shown in the 3 small text widgets. ## ############################# ## SOME USES for this utility: ## ## 1) Useful for helping math-science students get a visual ## 'feel' for the relation between mph, kph, and LPB. ## ## 2) Could be useful for a person wanting to convert ## from one unit to another --- for example, a tennis serve ## in miles-per-hour to kilometers-per-hour --- or vice versa. ## ## 3) IN A SHELL SCRIPT OR ANOTHER TK SCRIPT, this Tk script can ## ACT AS AN SPEED/VELOCITY SELECTOR by passing the current speed ## (in the 3 different units) to stdout, when the 'UseIt' button ## is clicked. ## Example output string: 60.0 ? ? ## (mph,kph,LPB) ##+######################################################################## ## 'CANONICAL' STRUCTURE OF THIS CODE: ## ## 0) Set general window parms (win-name, win-position, win-color-scheme, ## fonts, widget-geom-parms, win-size-control, text-array-for-labels-etc). ## 1a) Define ALL frames (and sub-frames). ## 1b) Pack ALL the frames and sub-frames. ## 2) Define & pack all widgets in the frames, frame by frame. ## ## 3) Define key and mouse/touchpad/touch-sensitive-screen 'event' ## BINDINGS, if needed. ## 4) Define PROCS, if needed. ## 5) Additional GUI INITIALIZATION (typically with one or two ## procs in section 4), if needed. ## ##+################################# ## The code structure in more detail, for this particular script: ## ## 1a) Define ALL frames: ## Top-level : 'fRbuttons' , 'fRsliders' ## ## Sub-frames: 'fRsliders.fRmph' , 'fRsliders.fRkph' , 'fRsliders.fRlpb' ## ## 'fRbuttons' is to be on the top of the GUI, and ## 'fRsliders' is to be on the bottom of the GUI. ## ## The 'fRmph', 'fRkph', 'fRlpb' sub-frames of the 'fRsliders' frame ## are to be packed top to bottom. ## ## The 3 scale widgets are to be oriented horizontally in the ## 3 sub-frames. ## ## 1b) Pack ALL 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: ## ## 'fRbuttons' - to contain several buttons --- and 3 pairs of ## label-and-text widgets to display the current ## speed, in the 3 different units, in the ## 3 text widgets. ## ## 'fRsliders' - to contain 3 sliders - 'scale' widgets, along with ## 3 'label' widgets. ## ## 3) Define BINDINGS: button1-release on the 3 sliders calls the proc ## 'speed_update'. ## ## 4) Define PROCS: ## 'speed_update' - called by button1-release bindings on 3 scale widgets. ## (One could someday try calling this proc in the ## '-command' options on the 3 scales.) ## 'put_vars' - called by the 'UseIt' button ## 'popup_msgVarWithScroll' - called by the 'Help' button ## ## 5) Additional GUI INITIALIZATION: none, except for setting ## the HELPtext var for the Help button. ## ##+####################################################################### ## DEVELOPED WITH: ## Tcl-Tk 8.5 on Ubuntu 9.10 (2009-october release, 'Karmic Koala'). ## ## $ wish ## % puts "$tcl_version $tk_version" ## showed 8.5 8.5 on Ubuntu 9.10 ## after Tcl-Tk 8.4 was replaced by 8.5 --- to get anti-aliased fonts. ##+######################################################################## ## MAINTENANCE HISTORY: ## Created by: Blaise Montandon 2013aug22 Started on Ubuntu 9.10, based ## on the color-selector script ## of the FE (Freedom Environment) ## subsystems. Ref: www.freedomenv.com ## Changed by: Blaise Montandon 20....... ##+############################################################################ ##+################################# ## SET THE TOP WINDOW NAME. ##+################################# wm title . \ "tkSpeedGun-Convert-Select - mph, kph, LPB" wm iconname . "SpeedConvert" # catch { wm title . "$env(FE_WIN_TITLE)" } # catch { wm iconname . "$env(FE_ICON_TITLE)" } ##+################################### ## SET THE TOP WINDOW POSITION. ##+################################### wm geometry . +15+30 # catch {eval wm geometry . "$env(FE_SPEEDSEL_GEOM)" } ##+####################################################################### ## SET COLOR SCHEME (palette) FOR THE WINDOW. ##+####################################################################### if {0} { ## Gray palette set Rpal255 210 set Gpal255 210 set Bpal255 210 } if {0} { ## Bluish palette set Rpal255 100 set Gpal255 0 set Bpal255 255 } if {1} { ## Greenish palette set Rpal255 160 set Gpal255 255 set Bpal255 0 } if {0} { ## Redish palette set Rpal255 255 set Gpal255 0 set Bpal255 100 } set hexCOLORpal [format "#%02X%02X%02X" $Rpal255 $Gpal255 $Bpal255] tk_setPalette $hexCOLORpal ## Set color background for some widgets. # set radbuttBKGD "#c0c0c0" # set chkbuttBKGD "#c0c0c0" # set listboxBKGD "#f0f0f0" # set entryBKGD "#f0f0f0" set scaleBKGD "#f0f0f0" set textBKGD "#f0f0f0" ##+####################################################################### ## SET FONT ATTRIBUTE VARS to 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 to be used in '-font' widget specs below. ## ## We use VARIABLE WIDTH fonts for LABEL and BUTTON widgets. ## ## We generally use FIXED WIDTH fonts for LISTBOX text, ## ENTRY widget text, and, often, for TEXT widget text. ##+##################################################################### eval font create fontTEMP_button $FONT_varwidth eval font create fontTEMP_label $FONT_varwidth eval font create fontTEMP_scale $FONT_varwidth # eval font create fontTEMP_entry $FONT_fixedwidth # eval font create fontTEMP_listbox $FONT_fixedwidth # eval font create fontTEMP_msg $FONT_fixedwidth eval font create fontTEMP_text $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_scale $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_msg $FONT_SMALL_fixedwidth # eval font create fontTEMP_SMALL_text $FONT_SMALL_fixedwidth ##+####################################################################### ## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS. ## (e.g. padx,pady for buttons) ##+####################################################################### ## For BUTTON widgets: set PADY_button 0 set PADX_button 0 set BDwidth_button 2 ## For LABEL widgets: set PADXpx_label 0 set PADYpx_label 0 set BDwidthPx_label 2 ## SCALE geom parameters: set BDwidthPx_scale 2 set initScaleLengthPx 300 set scaleWidthPx 10 ## For TEXT widgets: set BDwidth_text 2 if {0} { ## CANVAS geom parms: set initCanWidthPx 200 set initCanHeightPx 200 # set BDwidthPx_canvas 2 set BDwidthPx_canvas 0 ## For ENTRY widgets: set BDwidth_entry 2 ## For LISTBOX widgets: set BDwidth_listbox 2 ## For MESSAGE widgets: set BDwidth_msg 2 } ## END OF if {0} ##+################################################################### ## Set a MINSIZE of the window (roughly). (OR fix the window size.) ## ## For WIDTH, allow for a minwidth of the '.fRbuttons' frame: ## about 3 buttons (UseIt,Cancel,Help) and 3 pairs ## of label-and-text widgets. ## ## For HEIGHT, allow about ## 2 chars high for the '.fRbuttons' frame ## 300 pixels high for the '.fRsliders' frame. ##+####################################################################### ## We allow the window to be resizable and we pack the 'fRsliders' frame ## with '-fill both -expand 1' so that the sliders frame can be enlarged by ## enlarging the window. set minWinWidthPx [font measure fontTEMP_button \ " UseIt Cancel Help MPH: ??.? KPH: ??.? LPB: ??.?"] ## Add some pixels to account for right-left-side window decoration ## (about 8 pixels), about 8 widgets x 4 pixels/widget for borders/padding ## for 8 widgets --- buttons and labels. set minWinWidthPx [expr {40 + $minWinWidthPx}] ## MIN HEIGHT --- ## 2 chars high for the '.fRbuttons' frame ## 2 chars high for each of the 3 scales in the '.fRsliders' frame set CharHeightPx [font metrics fontTEMP_varwidth -linespace] set minWinHeightPx [expr {8 * $CharHeightPx}] ## Add about 28 pixels for top-bottom window decoration, ## about 4 frames x 4 pixels/frame for each of the 4 stacked frames ## and their widgets (their borders/padding). set minWinHeightPx [expr {44 + $minWinHeightPx}] ## FOR TESTING: # puts "minWinWidthPx = $minWinWidthPx" # puts "minWinHeightPx = $minWinHeightPx" wm minsize . $minWinWidthPx $minWinHeightPx ################################################ ## If you want to make the window un-resizable, ## you can use the following statement. ################################################ wm resizable . 0 0 ##+######################################################################## ## 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 '.fRsliders' frame: set aRtext(labelSCALEmph) "miles-per-hour (mph):" set aRtext(labelSCALEkph) "kilometers-per-hour (kph):" set aRtext(labelSCALElpb) "Lightyears-Per-Billion-years (LPB):" ## For '.fRbuttons' frame: set aRtext(buttonUSEIT) "UseIt" set aRtext(buttonCANCEL) "Cancel" set aRtext(buttonHELP) "Help" set aRtext(labelTEXTmph) " MPH:" set aRtext(labelTEXTkph) " KPH:" set aRtext(labelTEXTlpb) " LPB:" ## END OF if { "$VARlocale" == "en" ##+######################################################################## ## ## GET INPUT PARM VALUE -- ## i.e. set VARkph from ## ## 1) an argument passed to this script ## OR ## 2) environment var VAR_KPH ## ##+######################################################################## ##+######################################################################## ## Example argc/argv processing: ## ## if {$argc == 0} { ## set VARtext "$env(CONFIRM_TEXT)" ## } else { ## set VARtext [lindex $argv 0] ## } ##+######################################################################## if {$argc == 1} { set VARkph [lindex $argv 0] } else { set VARkph 100.0 catch { set VARkph "$env(VAR_KPH)" } } set VARmph [expr {0.6214 * $VARkph}] set VARlpb [expr {0.926 * $VARkph}] ##+#################################################################### ## DEFINE *ALL* THE FRAMES: ## TOP-LEVEL FRAMES: ## - 'fRbuttons' - to contain several buttons (UseIt,Cancel,Help), ## as well as 3 pairs of label-and-text widgets. ## - 'fRsliders' - to contain 3 sliderbars, with 3 labels. ## ## 'fRsliders' is packed below the 'fRbuttons' frame. ## ## SUB-FRAMES: ## - 'fRsliders.fRmph' (to contain 1 label-and-scale widgets pair) ## - 'fRsliders.fRkph' (to contain 1 label-and-scale widgets pair) ## - 'fRsliders.fRlpb' (to contain 1 label-and-scale widgets pair) ## ## These 3 sub-frames are packed top to bottom. ##+#################################################################### ## FOR TESTING: (like expansion of frames, during window expansion) # set RELIEF_frame raised # set BDwidth_frame 2 set RELIEF_frame flat set BDwidth_frame 0 frame .fRsliders -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRbuttons -relief $RELIEF_frame -borderwidth $BDwidth_frame set RELIEF_frame raised set BDwidth_frame 2 frame .fRsliders.fRmph -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRsliders.fRkph -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRsliders.fRlpb -relief $RELIEF_frame -borderwidth $BDwidth_frame ##+######################################################## ## PACK *ALL* the FRAMES. ##+######################################################## pack .fRbuttons \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRsliders \ -side top \ -anchor nw \ -fill x \ -expand 1 ## Pack the sub-frames. pack .fRsliders.fRmph \ .fRsliders.fRkph \ .fRsliders.fRlpb \ -side top \ -anchor nw \ -fill x \ -expand 0 ##+################################################################ ## The frames are now defined and packed. ##+################################################################ ## START DEFINING & PACKING WIDGETS WITHIN THEIR FRAMES. ##+################################################################ ##+################################################################ ##+######################################################## ## IN THE 'fRbuttons' frame -- DEFINE several BUTTONS --- ## 1 'UseIt' BUTTON, 1 'Cancel' BUTTON, ## 1 'Help' BUTTON, and ## 3 'TEXT' WIDGETS (rather than a 'label' or 'message' widget, ## so that it is possible to paste the text values ## to another window). Each text widget with a label widget. ## THEN PACK THE WIDGETS. ##+######################################################## button .fRbuttons.buttUSEIT \ -text "$aRtext(buttonUSEIT)" \ -font fontTEMP_button \ -padx $PADX_button \ -pady $PADY_button \ -relief raised \ -bd $BDwidth_button \ -command {put_vars} button .fRbuttons.buttCANCEL \ -text "$aRtext(buttonCANCEL)" \ -font fontTEMP_button \ -padx $PADX_button \ -pady $PADY_button \ -relief raised \ -bd $BDwidth_button \ -command {exit} button .fRbuttons.buttHELP \ -text "$aRtext(buttonHELP)" \ -font fontTEMP_button \ -padx $PADX_button \ -pady $PADY_button \ -relief raised \ -bd $BDwidth_button \ -command {popup_msgVarWithScroll .topHelp "$HELPtext"} ## Provide label-and-text widgets for the speed values ## in several different units. set widthChars 10 set widthFiller " " ## MPH: label .fRbuttons.labTEXTmph \ -text "$aRtext(labelTEXTmph)" \ -font fontTEMP_label \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label text .fRbuttons.txtVARmph \ -font fontTEMP_text \ -height 1 \ -width $widthChars \ -wrap none \ -relief raised \ -borderwidth $BDwidth_text \ -bg $scaleBKGD ## KPH: label .fRbuttons.labTEXTkph \ -text "$aRtext(labelTEXTkph)" \ -font fontTEMP_label \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label text .fRbuttons.txtVARkph \ -font fontTEMP_text \ -height 1 \ -width $widthChars \ -wrap none \ -relief raised \ -borderwidth $BDwidth_text \ -bg $scaleBKGD ## LPB: label .fRbuttons.labTEXTlpb \ -text "$aRtext(labelTEXTlpb)" \ -font fontTEMP_label \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label text .fRbuttons.txtVARlpb \ -font fontTEMP_text \ -height 1 \ -width $widthChars \ -wrap none \ -relief raised \ -borderwidth $BDwidth_text \ -bg $scaleBKGD ## Pack the widgets in frame '.fRbuttons'. pack .fRbuttons.buttUSEIT \ .fRbuttons.buttCANCEL \ .fRbuttons.buttHELP \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRbuttons.txtVARlpb \ .fRbuttons.labTEXTlpb \ .fRbuttons.txtVARkph \ .fRbuttons.labTEXTkph \ .fRbuttons.txtVARmph \ .fRbuttons.labTEXTmph \ -side right \ -anchor e \ -fill none \ -expand 0 ##+######################################################## ## Prepare some scale-parameter variables for use in ## defining the 3 scales below. ##+######################################################## # set scaleLenPx 350 # set scaleLenPx [expr {$minWinWidthPx - 40}] set scaleLenPx $minWinWidthPx set scaleThickPx 10 set KPHmin 0.0 set KPHmax 2000.0 set MPHmin 0.0 set MPHmax [expr {0.6214 * $KPHmax}] set LPBmin 0.0 set LPBmax [expr {0.926 * $KPHmax}] # set resolution 1 # set digits 4 set resolution 0.1 set digits 5 set labelChars 29 ##+######################################################## ## IN THE 'fRsliders.fRmph' frame -- DEFINE ## a LABEL widget and a SCALE widget. ## The scale is oriented horizontally. ## THEN PACK THEM --- the label above the scale. ##+######################################################## ## MPH: label .fRsliders.fRmph.label \ -text "$aRtext(labelSCALEmph)" \ -font fontTEMP_label \ -width $labelChars \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd 0 \ -highlightthickness 0 \ -bg $scaleBKGD scale .fRsliders.fRmph.scale \ -orient horizontal \ -from $MPHmin -to $MPHmax \ -resolution $resolution \ -digits $digits \ -length $scaleLenPx \ -variable VARmph \ -font fontTEMP_scale \ -showvalue true \ -bd $BDwidthPx_scale \ -highlightthickness 0 \ -width $scaleThickPx \ -bg $scaleBKGD ## -command {speed_update} .fRsliders.fRmph.scale set $VARmph ##+################################################# ## Pack the widgets in the frame '.fRsliders.fRmph'. ##+################################################# pack .fRsliders.fRmph.label \ -side top \ -anchor nw \ -fill none \ -expand 0 pack .fRsliders.fRmph.scale \ -side top \ -anchor nw \ -fill y \ -expand 1 ##+######################################################## ## IN THE 'fRsliders.fRkph' frame -- DEFINE ## a LABEL widget and a SCALE widget. ## The scale is oriented horizontally. ## THEN PACK THEM --- the label above the scale. ##+######################################################## ## KPH: label .fRsliders.fRkph.label \ -text "$aRtext(labelSCALEkph)" \ -font fontTEMP_label \ -width $labelChars \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd 0 \ -highlightthickness 0 \ -bg $scaleBKGD scale .fRsliders.fRkph.scale \ -orient horizontal \ -from $KPHmin -to $KPHmax \ -resolution $resolution \ -digits $digits \ -length $scaleLenPx \ -variable VARkph \ -font fontTEMP_scale \ -showvalue true \ -bd $BDwidthPx_scale \ -highlightthickness 0 \ -width $scaleThickPx \ -bg $scaleBKGD ## -command {speed_update} .fRsliders.fRkph.scale set $VARkph ##+################################################# ## Pack the widgets in the frame '.fRsliders.fRkph'. ##+################################################# pack .fRsliders.fRkph.label \ -side top \ -anchor nw \ -fill none \ -expand 0 pack .fRsliders.fRkph.scale \ -side top \ -anchor nw \ -fill y \ -expand 1 ##+######################################################## ## IN THE 'fRsliders.fRlpb' frame -- DEFINE ## a LABEL widget and a SCALE widget. ## The scale is oriented horizontally. ## THEN PACK THEM --- the label above the scale. ##+######################################################## ## LPB: label .fRsliders.fRlpb.label \ -text "$aRtext(labelSCALElpb)" \ -font fontTEMP_label \ -width $labelChars \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd 0 \ -highlightthickness 0 \ -bg $scaleBKGD scale .fRsliders.fRlpb.scale \ -orient horizontal \ -from $LPBmin -to $LPBmax \ -resolution $resolution \ -digits $digits \ -length $scaleLenPx \ -variable VARlpb \ -font fontTEMP_scale \ -showvalue true \ -bd $BDwidthPx_scale \ -highlightthickness 0 \ -width $scaleThickPx \ -bg $scaleBKGD ## -command {speed_update} .fRsliders.fRlpb.scale set $VARlpb ##+################################################# ## Pack the widgets in the frame '.fRsliders.fRlpb'. ##+################################################# pack .fRsliders.fRlpb.label \ -side top \ -anchor nw \ -fill none \ -expand 0 pack .fRsliders.fRlpb.scale \ -side top \ -anchor nw \ -fill y \ -expand 1 ##+####################################### ## END OF MAIN SECTION TO SETUP THE GUI. ## FRAMES AND WIDGETS ARE DEFINED. ##+####################################### ##+####################################################################### ##+####################################################################### ## BINDINGS section: 3 bindings on button1-release on the sliders (scales). ##+####################################################################### ##+####################################################################### bind .fRsliders.fRmph.scale \ {set TYPEchanged "MPH" ; speed_update 0} bind .fRsliders.fRkph.scale \ {set TYPEchanged "KPH" ; speed_update 0} bind .fRsliders.fRlpb.scale \ {set TYPEchanged "LPB" ; speed_update 0} ##+##################################################################### ##+##################################################################### ## PROCS section: ## 'speed_update' - called by button1-release bindings ## 'put_vars' - called by the 'UseIt' button ## 'popup_msgVarWithScroll' - called by the 'Help' button ##+##################################################################### ##+##################################################################### ##+##################################################################### ## proc 'speed_update' ##+##################################################################### ## PURPOSE: As any of the 3 sliders is changed, ## 1) set the other 2 sliders, and ## 2) update the text widgets that hold the speed in 3 ## different units. ## ## CALLED BY: button1-release on 3 scale widgets: ## - .fRsliders.fRmph.scale ## - .fRsliders.fRkph.scale ## - .fRsliders.fRlpb.scale ##+##################################################################### proc speed_update {x} { global TYPEchanged VARmph VARkph VARlpb \ widthChars widthFiller KPHmin KPHmax ######################################################## ## Reset the scale values of 2 scales from another scale. ######################################################## if {"$TYPEchanged" == "MPH"} { set VARmph [.fRsliders.fRmph.scale get] set VARkph [expr {$VARmph / 0.6214}] set VARlpb [expr {0.926 * $VARkph}] } if {"$TYPEchanged" == "KPH"} { set VARkph [.fRsliders.fRkph.scale get] set VARlpb [expr {0.926 * $VARkph}] set VARmph [expr {0.6214 * $VARkph}] } if {"$TYPEchanged" == "LPB"} { set VARlpb [.fRsliders.fRlpb.scale get] set VARkph [expr {$VARlpb / 0.926}] set VARmph [expr {0.6214 * $VARkph}] } ###################################################### ## Update the text numbers in the 3 text widgets. ###################################################### ####################################################### ## Show the current speed in MPH in a small text widget. ## Right-justify the number in the text widget. ####################################################### .fRbuttons.txtVARmph delete 1.0 end .fRbuttons.txtVARmph insert 1.0 "$widthFiller" set insertIDX [expr {$widthChars - [string length "$VARmph"]}] .fRbuttons.txtVARmph insert 1.$insertIDX $VARmph ## FOR TESTING: # puts "insertIDX: $insertIDX" ######################################################## ## Show the current speed in KPH in a small text widget. ## Right-justify the number in the text widget. ######################################################## .fRbuttons.txtVARkph delete 1.0 end .fRbuttons.txtVARkph insert 1.0 "$widthFiller" set insertIDX [expr {$widthChars - [string length "$VARkph"]}] .fRbuttons.txtVARkph insert 1.$insertIDX $VARkph ## FOR TESTING: # puts "insertIDX: $insertIDX" ######################################################## ## Show the current speed in LPB in a small text widget. ## Right-justify the number in the text widget. ######################################################## .fRbuttons.txtVARlpb delete 1.0 end .fRbuttons.txtVARlpb insert 1.0 "$widthFiller" set insertIDX [expr {$widthChars - [string length "$VARlpb"]}] .fRbuttons.txtVARlpb insert 1.$insertIDX $VARlpb ## FOR TESTING: # puts "insertIDX: $insertIDX" ###################################################### ## Reset the color-palette of the window --- between ## green (low-speed) and white (high-speed) --- according ## to the KPH value between the min and max KPH values. ###################################################### ## We want the white contribution to go from 0 to 255 as ## VARkph goes from 0 to KPHmax. ## We want the green contribution to go from 255 to 0 as ## VARkph goes from 0 to KPHmax. ###################################################### ##COMMENTED, for now. ###################################################### if {0} { set Rpal255 [expr {int(255 * $VARkph / $KPHmax)}] # set Gpal255 0 set Gpal255 100 set Bpal255 [expr {int(255 * ($KPHmax - $VARkph) / $KPHmax)}] set hexCOLORpal [format "#%02X%02X%02X" $Rpal255 $Gpal255 $Bpal255] tk_setPalette $hexCOLORpal } ## END OF if {0} } ## END of proc 'speed_update' ##+##################################################################### ## PROCEDURE -- put_vars ## ## PURPOSE: Puts a string containing the 3 speeds ## (VARmph, VARkph, VARlpb) ## to standard output. Then exits this GUI. ## ## Called by: button .fRbuttons.buttOK ##+##################################################################### proc put_vars { } { global VARmph VARkph VARlpb puts "$VARmph $VARkph $VARlpb" ## Exit this GUI after returning the speeds to stdout. exit } ## END of proc 'puts_vars' ##+######################################################################## ## 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_text \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 \ -yscrollcommand "$toplevName.scrolly set" \ -xscrollcommand "$toplevName.scrollx set" 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_varwidth \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 } button $toplevName.butt \ -text "OK" \ -font fontTEMP_label \ -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. ##+############################################### ## Setting of HELPtext variable follows. ##+############################################### set HELPtext "\ *** HELP for this tkSpeedGun-Convert-Select GUI **** This TkGUI script provides a GUI for showing speeds between zero and 2,000 kilometers-per-hour (this max is easy to change) --- in three different units: - mph (miles-per-hour) - kph (kilometers-per-hour) - LPB (Lightyears-Per-Billion-years). ******************************* SOME NOTEWORTHY SPEEDS (in kph): speed of light in a vacuum = 1.07925285 billion kph = 1,079,252,850 kph speed of sound in air at sea level = 1,225.044 kph = 343.2 meters/second (And sound travels about 4.3 times faster in water, and nearly 15 times faster in iron.) terminal velocity of a skydiver = about 200 kph speed limit of 80 mph = 128.7 kph max (burst) speed of a cheetah = about 112 kph speed limit of 60 mph = 96.6 kph max speed of a horse = about 88 kph human walking speed of 4 mph = 6.4 kph **************************************** CONVERSION FACTORS BETWEEN 'LPB' and KPH: 1 light-year = 9.4605284 × 10^12 kilometers = 9.46 trillion kilometers 1 billion years = ? hours = 10^9 years * 365 days/year * 24 hours/day = 8.760 x 10^12 hours = 8.76 trillion hours So 1 light-year/billion-years (LPB) = 1.0799 kph or 1 kph = 0.9260 LPB So multiply kph by 0.926 to get LPB. **************************** THE CONVERSION FUNCTIONALITY: Three different (but corresponding) speeds are shown (and selected for conversion) via 3 'slider-buttons' on 3 Tk 'scale' widgets. These 3 different (corresponding) speed numbers are also shown in 3 'text' widgets, several characters wide --- from which a user can copy-and-paste the numbers from this GUI window to some other window. For any 'slider' change, this GUI script IMMEDIATELY updates the location of the other 2 'SLIDERS' --- when you RELEASE the slider-button that you are moving. The 3 TEXT widgets, showing the speed in the 3 different units, are also IMMEDIATELY updated whenever any one of the 3 scale widget 'sliders' are changed. *************************** FINE CONTROL OF THE SLIDERS: Most people know that you can drag the sliders by clicking on the 'slider button' with mouse-button1 and dragging the slider button. This is a rather coarse way of moving the slider button. It is not so obvious that the Tk scale widget also allows you to move the 'slider button' by clicking in the 'trough' on EITHER SIDE of the slider button. By repeated clicking in the trough, the slider can be advanced one scale-resolution unit per click. Furthermore, one can RAPIDLY move the slider button ONE RESOLUTION UNIT per 'auto-click' by clicking in the trough and HOLDING down the mouse button. The slider moves one resolution unit repeatedly UNTIL the mouse button is RELEASED. ************************** THE SELECTOR FUNCTIONALITY: By clicking on the 'UseIt' button on the GUI, this script returns a string containing the current speed (in the 3 different units) to a calling script/application. When using this script in another script/program, this script will accept a speed (in kph) as an argument --- which is used to initialize the - setting of the 3 'sliders', and - the numbers shown in the 3 small text widgets. ************************* SOME USES of this utility: 1) Useful for helping math-science students get a visual 'feel' for the relation between mph, kph, and LPB. 2) Also could be useful for a person wanting to convert from one unit to another --- for example, a tennis serve in miles-per-hour to kilometers-per-hour --- or vice versa. 3) IN A SHELL SCRIPT or ANOTHER TK SCRIPT, this Tk script can ACT AS AN SPEED SELECTOR by passing the current speed (in the 3 different units) to stdout, when the 'UseIt' button is clicked. Example output string: 60.0 96.6 89.5 (mph , kph , LPB) Note: The user can set up this script as an icon on a desktop so that the GUI can be started up by a click (or two) on the icon --- say, while you are watching a tennis tournament. " ##+############################################### ## ADDITONAL GUI INITIALIZATION (if any) FOLLOWS. ##+############################################### ############################################################ ## See the setting of intial speeds --- from an initial KPH ## --- at the 'argv' section near the top of this code --- ## near the frame definitions. Note: You can pass an initial ## KPH value to this script. ############################################################ # update set TYPEchanged "kph" speed_update 0