#!/usr/bin/wish -f ##+######################################################################## ## ## SCRIPT: meters_forFileSystemsUsage_hidef-image.tk ## ## PURPOSE: This script is meant to show a GUI with a ## tachometer-style METER which shows the PERCENT-USED ## storage SPACE of a FILE-SYSTEM --- typically, for the file-system ## (i.e. disk partition) with the least free-space remaining. ## ## In other words, the meter shows the RATIO of used-space ## to total-allocated-space --- for a file-system. Typically, the ## user wants to check %-used for the file system for which the ## 'used-space-ratio' is the highest. ## ## This utility is designed for computer operating systems of the ## Linux/Unix/BSD type --- computers that have a 'df' command and ## commands like awk, grep, sed, and sort. The 'df' command ## displays file-system space-usage info for the file system ## mount points of a Unix/BSD/Linux type file system. ## ## On computers with a single, 'root' file system, the user would ## typically want the value shown on the meter to be for that ## one 'root' file system. ## ## On computers with both a 'root' (/) and a 'home' (/home) ## file system (and/or other file systems), the user will typically ## want the value shown on the meter to be for the file system with ## the highest 'percent-used'. ## ## Or, if TWO meters are to be shown, the user would typically ## want to show the percent used of the 'root' file system and ## the percent used of another file system with the highest ## percent used --- or the 2nd-highest percent used, if the ## 'root' file system is the 'fullest' file system. ## ## To simplify, we show just one meter (for a user-specified ## file system mount point) rather than two or more meters, ## for multiple file systems on the computer. ## ## When the GUI first appears, the meter may show the %-used ## for the 'root' file system. ## ## Of course, a Tck-Tk programmer could change this script to initially ## show the %-used for the 'most full' file system --- AND the ## GUI could be changed to show more than one meter at a time. For ## relative simplicity of coding, we do not do that in this version. ## ##+###################### ## CHOOSING A FILE SYSTEM (a USER-SPECIFIED MOUNT POINT): ## ## This script was developed on Linux and uses the 'df' command ## to get 'percent-used' data to locate the position of the ## meter pointer for a user-specified mount point. A pop-down/out ## menu of the available mount points is provided on the GUI, ## Thus the user can choose the file system whose %-used is to be ## shown on the meter. ## ## A red-line area of the meter could indicate that when the ## %-used gets above about 85%, the user should take heed. ## ## The total-allocated and total-used space (in Gigabytes) ## is also shown as text just above or below the %-used meter. ## ##+###################################### ## AUTO-UPDATE of the METER and TEXT-DATA for the mount point: ## ## The pointer on the meter may be updated periodically to ## show the percent of storage space currently in-use, ## for a file system that needs monitoring. ## ## The amount of time between updates is controlled by a ## scale widget on the GUI --- defaulted to 60 or 120 seconds, ## say (or more). And an 'Update'/'Refresh' button on the GUI ## can be used to force an update at any moment. ## ## The auto-refresh feature is, typically, not very dynamic for ## filesystem space, which, typically, is not changing much ## within seconds --- or even within many minutes. ## ## However, if a user is running a job that is creating ## many files or a huge file in a file system, then the ## auto-refresh feature may be useful --- to monitor the ## rapid-consumption of space in a file system. ## ##+################# ## A 'REPORT' OPTION: ## ## The 'df' command can be used to show space 'allocated' and ## 'used' and '%-used' data, for ALL the mount points of ## the computer. The user can click on a 'Report' button on the ## GUI to show the report in a pop-up scrollable Tk text widget. ## The user can copy-paste the text from that window to another ## window such as a text editor window or a word processor window. ## ############################## ## METHOD OF DRAWING THE METER: ## ## A previously published version of this utility, by this author, ## used Tk canvas 'create arc' and 'create line' commands to draw a ## tachometer-style meter --- using a 'shadow-circle' technique of ## Marco Maggi (http://wiki.tcl.tk/9107) to make nice-looking ## meter components. ## ## 'create line' was used to draw tic marks around the meter arc. ## Furthermore, 'create line' was used to draw a needle on the meter, ## at various angles. ## ## THIS Tk script uses the Tk canvas 'create image' command to put a ## nice-looking, HD (high-definition) meter background on a Tk canvas ## widget. ## ## Then 'create line' may (optionally) be used to put tic marks, ## in an arc, on the meter background --- if there are not tic marks ## on the background image already. ## ## To avoid technicalities that may come in trying to draw an HD (hi-def) needle ## at various angles on the meter, we use a 'bullet' image (a small 'blunt-pointer' ## image), placed along the tic-marks arc, to indicate the current value of ## the %-used. We generally use a color for this 'bullet' ## which contrasts well with the background image for the meter. ## ## By means of Tcl arrays, we allow the user to choose from multiple ## 'themes' for the meter. (The user can choose a theme via a ## 'scale' widget rather than 'radiobuttons' --- to allow for ## supporting an almost unlimited number of themes, rather than being ## limited by the amount of space that radiobuttons consume on the GUI.) ## ## Each theme (indexed via an integer) includes the following items, ## stored in Tcl arrays: ## - a BACKGROUND IMAGE (a GIF or PNG file) - and we allow for a ## small, medium, and large background images (about 200, 350, ## and 500 pixels high) ## - a BULLET/POINTER IMAGE (a small transparent GIF or PNG file) ## - a RIVET IMAGE (a small transparent GIF or PNG file), which ## is shown optionally, according to a checkbutton on the GUI ## - some parameters, such as ## - the CENTER LOCATION on the background image (in case it is ## not symmetric) --- typically about 0.5,0.5 ## - a RADIUS for an arc, for positioning tic marks and tic mark ## labels --- as well as for positioning the 'bullet' image. ## (Typically this radius value will be about 0.25.) ## - an indicator of whether the tic marks & labels should be ## PLACED ON THE INSIDE OR THE OUTSIDE OF THE ARC. (This ## indicator is set to 'in' or 'out'.) ## - an indicator of WHETHER TIC MARKS ARE TO BE DRAWN/PLACED. ## Tic marks are not needed if they are already on the ## background image. ## - START and EXTENT angles for the arc, such as -70 and 320, ## where 320 = 70 + 180 + 70. ## (The arc is drawn counter-clockwise, but we use it in a ## clockwise fashion.) ## ## NOTE1: ## The center location and radius parameters are to be given as ## ratios (not pixels) --- so that they work for any size of the ## background image --- small, medium, or large. ## NOTE2: ## We do not require the meter background images to be square. ## They can be rectangular. ## NOTE3: ## The 'theme arrays' are set in one section of this script. To change ## the themes, simply edit the 'set' statements for those arrays. ## To add themes, add similar array-setting statements and change the ## range of the theme-scale. ## ################### ## THE GUI LAYOUT: ## ## The options available to the user are indicated ## by the following 'sketch' of the GUI. ## ## In the GUI 'sketch' below: ## ## - SQUARE BRACKETS indicate a comment (not to be placed on the GUI). ## - BRACES indicate a Tk 'button' widget. ## - A COLON indicates that the text before the colon is on a 'label' widget. ## - UNDERSCORES indicate a Tk 'entry' widget. ## - CAPITAL-O indicates a Tk 'radiobutton' widget. ## - CAPITAL-X indicates a Tk 'checkbutton' widget. ## - A LINE OF HYPHENS with arrow-heads on each end (<-------->) ## indicates a 'scale' widget. ## ## --------------------------------------------------------------- ## FileSystem Space Use [window title] ## --------------------------------------------------------------- ## {Exit} {Help} {Report} {Refresh} O Small O Medium O Large ## ## {ShowMounts} Monitor Mount: /__________ ## ## Theme for ## the meter : <--------------------> X DrawTicLabels ## ## X DrawTicsArc X ShowCornerFeatures (if in theme) ## ## SampleRate Samples: NNN ## (seconds) : <----------------------------> ## ## ## [The meter will be placed in a frame in the area below. ## The frame will contain several label lines above a canvas widget. ## A meter background image will be placed on the canvas widget.] ## ## [Tic marks can be drawn in an arc on the meter background, ## with 'create line', if they are not already on the ## background image.] ## ## [The check-buttons, above, can be used by the user ## to specify whether the labels (0 to 100) should be ## drawn/shown (with 'create text') --- and whether an ## arc should be drawn/shown (with 'create arc') along the ## path of the tic marks.] ## ## [Optionally, as part of the 'theme' selected, 4 images ## ('rivets' or screw-heads or whatever) can be placed ## in the 4 corners of the background image.] ## ##+################ ## NOTES ON THE GUI: ## ## 0) There is an ENTRY widget to hold a mount-point of a file ## system whose space-usage is to be monitored. ## ## 1) There is a SCALE widget for the user to set a ## 'wait-seconds' parameter for auto-refresh of the meter --- ## in seconds --- up to about 200 seconds (several minutes). ## ## 2) There is an '.fRcanvases.fRcanvas1' frame to contain a ## CANVAS widget that holds the meter image. Also the ## 'fRcanvas1' frame holds 3 LABEL widgets, to show, as text items, ## Total-allocated-space, Used+Reserved-space, and Available-space ## for the selected file system. ## ## 3) A 'Refresh' button on the GUI can be used to reset ## the start time for sampling --- at the current rate ## (a sampling interval, set via the sample-rate scale widget). ## ## The 'Refresh' button is useful if the sampling rate is set ## too high or too low and the user wants to immediately ## reset the sampling rate. ## ## 4) There is a 'Report' button to give a quick overview of ## the %-used status of ALL the file-systems of the computer. ## ## 5) There is a 'ShowMounts' button to show the user the list ## of available directory mount-points. ## ##+############## ## GUI components: ## ## From the GUI 'sketch' and notes above, it is seen that the GUI consists of ## about ## ## - 5 button widgets ## - 7 label widgets ## - 3 radiobutton widgets in 1 group ## - 3 checkbutton widgets ## - 2 scale widgets ## - 1 canvas widget ## - 1 entry widget (for mount point/directory of file system) ## - 0 listbox widgets ## ## ##+################################ ## METHOD USED to update the meter(s): ## ## A Tcl 'exec' command calls on a separate shell script that uses ## the 'df' command to get the storage space data for the file-systems ## of the computer and reformat the data for return to this Tk script. ## ## The shell script will be capable of returning info of 3 types: ## 1) a report of the status of ALL the file systems known to 'df' ## 2) a list of the file-system mount-points ## 3) %-used, allocated-Gigabytes, used-Gigabytes for a user-specified ## mount-point. ## ##+####################### ## CAPTURING THE GUI IMAGE: ## ## There may not be many scenarios in which a user would want to ## send an image of the %-used meter(s) to anyone, but in case ## the user would ever want to capture an image: ## ## A screen/window capture utility (like 'gnome-screenshot' ## on Linux) can be used to capture the GUI image in a PNG ## or GIF file, say. ## ## If necessary, an image editor (like 'mtpaint' on Linux) ## can be used to crop the window capture image. The image ## could also be down-sized, with the editor --- say, to make ## a smaller image suitable for use in a web page or an email. ## ##+####################################################################### ## '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, 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 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. ## ##+################################# ## Some detail of the code structure of this particular script: ## ## 1a) Define ALL frames: ## ## Top-level : ## '.fRbuttons' - to contain 'Exit', 'Help', 'Report', 'Refresh' buttons ## '.fRmount' - to contain a 'ShowMounts' button --- and an entry widget ## '.fRtheme1' - to contain a scale widget and a checkbutton widget ## '.fRtheme2' - to contain checkbutton widgets ## '.fRsamprate' - to contain a scale widget, with a label widget. ## '.fRcanvases' - to contain a frame for canvas widget with several label ## widgets above the canvas. ## Sub-frames: ## '.fRcanvases.fRcanvas1' - for 3 label widgets & 1 canvas widget ## ## (We use the sub-frame 'fRcanvas1', in case this script were ever to ## be altered to allow multiple meters to be shown at one time.) ## ## 1b) Pack the frames and sub-frames. ## ## 2) Define & pack all widgets in the frames -- basically going through ## frames & their interiors in left-to-right, or top-to-bottom order. ## ## 3) Define BINDINGS: perhaps a few ## (See the BINDINGS section of the code for details.) ## ## 4) Define PROCS: ## ## 'make_meters' - to draw a meter within a Tk canvas. ## ## (Although we implement one meter for now, someday ## we may want to display multiple meters, so we ## use the 'make_meters' and 'make_one_meter' procs.) ## ## The size of the canvas will be determined ## by the size of the background image, which in ## turn is determined by the theme-index and ## the setting of the Small-Medium-Large radiobuttons. ## ## 'make_one_meter' - called by 'make_meters', to make each meter. ## ## 'update_pointers' - to update the needles on the one (or someday more) ## meters. ## ## 'update_one_needle' - called by 'update_pointers', to draw the ## needle on each meter. ## ## 'Refresh' - called by 'Refresh' button. Runs ## 'make_meters' and 'update_pointers'. ## ## 'popup_msgVarWithScroll' - called by 'Help' button to show HELPtext var. ## Also used by the 'Report' button and the ## 'Mounts' button. ## ## 5) Additional GUI Initialization: ## - call 'make_meters' to put the meter(s) on the canvas(es) ## - call 'update_pointers' --- to initialize the needle location(s) ## and start the point updating process. ## ##+####################################################################### ## 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 2015oct31 Started the code on Linux, ## Ubuntu 9.10. ## Changed by: Blaise Montandon 2015nov09 Finalized set of 10 themes and ## their positioning parameters. ##+######################################################################## ##+###################################################### ## Set WINDOW TITLE and POSITION. ##+###################################################### wm title . "FileSystem Space Use" wm iconname . "FilesysUse" wm geometry . +15+30 ##+###################################################### ## Set the COLOR SCHEME for the window and its widgets --- ## such as entry field and scale-trough background color. ##+###################################################### tk_setPalette "#e0e0e0" set entryBKGD "#ffffff" set scaleBKGD "#f0f0f0" set radbuttBKGD "#f0f0f0" set chkbuttBKGD "#f0f0f0" set textBKGD "#f0f0f0" # set listboxBKGD "#ffffff" ##+######################################################## ## DEFINE (temporary) FONT NAMES. ## ## We use a VARIABLE-WIDTH font for text on LABEL and ## BUTTON widgets. ## ## We use a FIXED-WIDTH font for the text in LISTBOX lists, ## for text in ENTRY fields --- and often for text in a ## TEXT widget. ##+######################################################## font create fontTEMP_varwidth \ -family {comic sans ms} \ -size -14 \ -weight bold \ -slant roman font create fontTEMP_SMALL_varwidth \ -family {comic sans ms} \ -size -12 \ -weight bold \ -slant roman ## Some other possible (similar) variable width fonts: ## Arial ## Bitstream Vera Sans ## DejaVu Sans ## Droid Sans ## FreeSans ## Liberation Sans ## Nimbus Sans L ## Trebuchet MS ## Verdana font create fontTEMP_fixedwidth \ -family {liberation mono} \ -size -14 \ -weight bold \ -slant roman font create fontTEMP_SMALL_fixedwidth \ -family {liberation mono} \ -size -12 \ -weight bold \ -slant roman ## Some other possible fixed width fonts (esp. on Linux): ## Andale Mono ## Bitstream Vera Sans Mono ## Courier 10 Pitch ## DejaVu Sans Mono ## Droid Sans Mono ## FreeMono ## Nimbus Mono L ## TlwgMono ##+########################################################### ## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS. ## (e.g. width and height of canvas, and padding for Buttons) ##+########################################################### ## BUTTON widget geom settings: set PADXpx_button 0 set PADYpx_button 0 set BDwidthPx_button 2 ## LABEL widget geom settings: set PADXpx_label 0 set PADYpx_label 0 set BDwidthPx_label 2 ## ENTRY widget geom settings: set BDwidthPx_entry 2 ## RADIOBUTTON widget geom settings: set PADXpx_radbutton 0 set PADYpx_radbutton 0 set BDwidthPx_radbutt 2 ## CHECKBUTTON widget geom settings: set PADXpx_chkbutton 0 set PADYpx_chkbutton 0 set BDwidthPx_chkbutt 2 ## SCALE widget geom parameters: set BDwidthPx_scale 2 set scaleThicknessPx 10 ## CANVAS widget geom settings: set initCanWidthPx 200 set initCanHeightPx 200 # set BDwidthPx_canvas 2 set BDwidthPx_canvas 0 ##+###################################################################### ## Set a MIN-SIZE of the window (roughly). ## ## For MIN-WIDTH, allow for the min-width of the '.fRbuttons' frame. ## ## For MIN-HEIGHT, allow for the stacked frames: ## 1 char high for the '.fRbuttons' frame, ## 1 char high for the '.fRmount' frame, ## 2 chars high for 'fRtheme1' frame, ## 1 char high for 'fRtheme2' frame, ## 2 chars high for 'fRsamprate' frame, ## at least 50 pixels high for the '.fRmeter' frame. ##+##################################################################### ## FOR MIN-WIDTH: set minWidthPx [font measure fontTEMP_varwidth \ " Exit Help Report Refresh S M L "] ## We add some pixels to account for right-left-size of ## window-manager decoration (~8 pixels) and some pixels for ## frame/widget borders (~7 widgets x 4 pixels/widget = 28 pixels). set minWinWidthPx [expr {36 + $minWidthPx}] ## For MIN-HEIGHT --- for ## 1 char high for 'fRbuttons' ## 1 char high for 'fRmount' ## 2 chars high for 'fRtheme1' ## 1 char high for 'fRtheme2' ## 2 chars high for 'fRsamprate' ## 50 pixels high for 'fRmeters' set charHeightPx [font metrics fontTEMP_varwidth -linespace] set minWinHeightPx [expr {7 * $charHeightPx}] ## Add about 50 pixels for height of the canvas ## AND add about 20 pixels for top-bottom window decoration -- ## and some pixels for top-and-bottom of frame/widget borders ## (~5 widgets x 4 pixels/widget = 20 pixels). set minWinHeightPx [expr {90 + $minWinHeightPx}] ## FOR TESTING: # puts "minWinWidthPx = $minWinWidthPx" # puts "minWinHeightPx = $minWinHeightPx" wm minsize . $minWinWidthPx $minWinHeightPx ## We may allow the window to be resizable. We pack the canvases ## (and the frames that contain them) with '-fill both -expand 1' ## so that the canvases can be enlarged by enlarging the window. ## 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 '.fRbuttons' frame: set aRtext(buttonEXIT) "Exit" set aRtext(buttonHELP) "Help" set aRtext(buttonREPORT) "Report" set aRtext(buttonREFRESH) "Refresh" set aRtext(radbuttSMALL) "S" set aRtext(radbuttMEDIUM) "M" set aRtext(radbuttLARGE) "L" ## For '.fRmount' frame: set aRtext(buttonMOUNTS) "ShowMounts" set aRtext(labelMOUNT) " MonitorMount:" ## For '.fRtheme1' frame: set aRtext(labelTHEMEscale) "Theme for the meter :" set aRtext(chkbuttLABELS) "DrawTicLabels" ## For '.fRtheme2' frame: set aRtext(chkbuttARC) "DrawTicsArc" set aRtext(chkbuttCORNERS) "ShowCornerFeatures (if in theme)" ## For '.fRsamprate' frame: set aRtext(labelSAMPLEscale) "SampleRate (seconds) :" set aRtext(labelSAMPLECOUNT) "Samples:" ## END OF if { "$VARlocale" == "en"} ##+############################################################## ## DEFINE THE AVAILABLE THEMES, VIA SEVERAL ARRAYS. ## ## Each theme (indexed via an integer) includes the following items, ## stored in Tcl arrays: ## - a BACKGROUND IMAGE (a GIF or PNG file) - and we allow for a ## small, medium, and large background images (about 200, 350, ## and 500 pixels high) ## - a BULLET/POINTER IMAGE (a small transparent GIF or PNG file) ## - a RIVET IMAGE (a small transparent GIF or PNG file), which ## is shown optionally, according to a checkbutton on the GUI ## (If null, of course it is not available to be shown.) ## - some parameters, such as ## - the CENTER LOCATION on the background image (in case it is ## not symmetric) --- typically about 0.5,0.5 ## - a RADIUS for an arc, for positioning tic marks and tic mark ## labels --- as well as for positioning the 'bullet' image. ## (Typically this radius value will be about 0.35.) ## - an indicator of whether the tic marks & labels should be ## PLACED ON THE INSIDE OR THE OUTSIDE OF THE ARC. (This ## indicator is set to 'in' or 'out'.) ## - an indicator of WHETHER TIC MARKS ARE TO BE DRAWN/PLACED. ## Tic marks are not needed if they are already on the ## background image. ## - START and EXTENT angles for the arc, such as -70 and 320. ## (The arc is drawn counter-clockwise, but we use it in a ## clockwise fashion.) ## ##+############################################################## ## Theme 1: set aRimgBkgd(1) "meter_background_A12_circularlyPolishedMetal_lightVersion" set aRticsYorN(1) "N" set aRcenterX(1) 0.5 set aRcenterY(1) 0.5 set aRradiusArc(1) 0.35 set aRinORout(1) "in" set aRhexcolorText(1) "#000000" set aRhexcolorTics(1) "#000000" set aRimgPointer(1) "emerald_green_transp_24x26" set aRimgCornerFeature(1) "screwheadPhillipsWorn_gray_transp_37x37" set aRstartAngle(1) -70 set aRextentAngle(1) 320 ## Theme 2: set aRimgBkgd(2) "meter_background_A14_glossyBlueDisk_blackHilitedEdge_blackBkgd" set aRticsYorN(2) "N" set aRcenterX(2) 0.50 set aRcenterY(2) 0.52 set aRradiusArc(2) 0.25 set aRinORout(2) "in" set aRhexcolorText(2) "#ffffff" set aRhexcolorTics(2) "#ffffff" set aRimgPointer(2) "lightningBolt_blue_transp_25x25" set aRimgCornerFeature(2) "" set aRstartAngle(2) -44 set aRextentAngle(2) 268 ## Theme 3: set aRimgBkgd(3) "meter_background_A26_whiteSolidDisk_graySixLevelEdge_whiteBkgd" set aRticsYorN(3) "N" set aRcenterX(3) 0.5 set aRcenterY(3) 0.5 set aRradiusArc(3) 0.28 set aRinORout(3) "in" set aRhexcolorText(3) "#ffffff" set aRhexcolorTics(3) "#ffffff" set aRimgPointer(3) "lockAngled_yellow_transp_25x25" set aRimgCornerFeature(3) "" set aRstartAngle(3) -70 set aRextentAngle(3) 320 ## Theme 4: set aRimgBkgd(4) "meter_background_A27_whiteSolidDisk_lightBlueTubularEdge_whiteBkgd" set aRticsYorN(4) "N" set aRcenterX(4) 0.50 set aRcenterY(4) 0.50 set aRradiusArc(4) 0.31 set aRinORout(4) "in" set aRhexcolorText(4) "#000000" set aRhexcolorTics(4) "#000000" set aRimgPointer(4) "moleculeTetra_grays_transp_25x25" set aRimgCornerFeature(4) "screwheadPhillips_1_transp_32x32" set aRstartAngle(4) -70 set aRextentAngle(4) 320 ## Theme 5: set aRimgBkgd(5) "meter_background_A34_redWhiteBlueWavesOnOrb" set aRticsYorN(5) "N" set aRcenterX(5) 0.5 set aRcenterY(5) 0.5 set aRradiusArc(5) 0.25 set aRinORout(5) "out" set aRhexcolorText(5) "#dddddd" set aRhexcolorTics(5) "#dddddd" set aRimgPointer(5) "pencilStub_yellow_transp_25x25" set aRimgCornerFeature(5) "screwheadPhillips_4_transp_18x18" set aRstartAngle(5) -70 set aRextentAngle(5) 320 ## Theme 6: set aRimgBkgd(6) "meter_background_A35_blueLock" set aRticsYorN(6) "N" set aRcenterX(6) 0.50 set aRcenterY(6) 0.67 set aRradiusArc(6) 0.28 set aRinORout(6) "in" set aRhexcolorText(6) "#000000" set aRhexcolorTics(6) "#ffffff" set aRimgPointer(6) "pig_pink_transp_25x25" set aRimgCornerFeature(6) "" set aRstartAngle(6) -70 set aRextentAngle(6) 320 ## Theme 7: set aRimgBkgd(7) "meter_background_A38_WhiteShinySphere_whiteBkgd" set aRticsYorN(7) "N" set aRcenterX(7) 0.50 set aRcenterY(7) 0.48 set aRradiusArc(7) 0.33 set aRinORout(7) "out" set aRhexcolorText(7) "#000000" set aRhexcolorTics(7) "#000000" set aRimgPointer(7) "rubberDuckie_transp_25x25" set aRimgCornerFeature(7) "screwheadPhillips_4_transp_18x18" set aRstartAngle(7) -70 set aRextentAngle(7) 320 ## Theme 8: ## meter_background_A44_coin_gold1ounce_sideA_americanIndian_whiteBkgd set aRimgBkgd(8) "meter_background_A46_coin_lincoln-penny_2013_InGoodWeTrust" set aRticsYorN(8) "N" set aRcenterX(8) 0.50 set aRcenterY(8) 0.50 set aRradiusArc(8) 0.38 set aRinORout(8) "in" set aRhexcolorText(8) "#000000" set aRhexcolorTics(8) "#000000" set aRimgPointer(8) "shield_blueWhite_transp_25x25" set aRimgCornerFeature(8) "" set aRstartAngle(8) -70 set aRextentAngle(8) 320 ## Theme 9: set aRimgBkgd(9) "meter_background_A45_LightBulb_glossyOrangeBulb_whiteBkgd" set aRticsYorN(9) "N" set aRcenterX(9) 0.50 set aRcenterY(9) 0.30 set aRradiusArc(9) 0.30 set aRinORout(9) "in" set aRhexcolorText(9) "#000000" set aRhexcolorTics(9) "#000000" set aRimgPointer(9) "tuxPenguin_transp_25x25" set aRimgCornerFeature(9) "" set aRstartAngle(9) -70 set aRextentAngle(9) 320 ## Theme 10: set aRimgBkgd(10) "meter_background_A49_SoccerBall_black-whiteSphere_whiteBkgd" set aRticsYorN(10) "N" set aRcenterX(10) 0.44 set aRcenterY(10) 0.40 set aRradiusArc(10) 0.30 set aRinORout(10) "in" set aRhexcolorText(10) "#000000" set aRhexcolorTics(10) "#000000" set aRimgPointer(10) "smiley_blackOnSteelSquare_transp_25x25" set aRimgCornerFeature(10) "" set aRstartAngle(10) -70 set aRextentAngle(10) 320 ## Alternate/additional meter backgrounds: ## meter_background_A56_glassyHump_withMetallicRing_grayCCCCCCbkgd ## meter_background_B02_grayShadedDisk_grayShadedEdge_whiteBkgd ## Alternate/additional pointers: ## yingyang_blueWhite_transp_25x25 ## Alternate/additional corner features: ## screwheadPhillipsWorn_gray_transp_37x37 ## This 'Nthemes' variable will be used to define the 'samprate' scale. set Nthemes 10 ##+################################################################ ## DEFINE *ALL* THE FRAMES: ## ## Top-level : '.fRbuttons' , '.fRtheme1', '.fRtheme2', ## '.fRsamprate' , '.fRcanvases' ## ## Sub-frames: '.fRcanvases.fRcanvas1' one meter, for now. ##+################################################################ ## FOR TESTING change 0 to 1: ## (Example1: To see appearance of frames when their borders are drawn.) ## (Example2: To see sizes of frames for various '-fill' options.) ## (Example3: To see how frames expand as window is resized.) if {0} { set BDwidth_frame 2 set RELIEF_frame raised } else { set BDwidth_frame 0 set RELIEF_frame flat } frame .fRbuttons -relief $RELIEF_frame -bd $BDwidth_frame frame .fRmount -relief $RELIEF_frame -bd $BDwidth_frame frame .fRtheme1 -relief $RELIEF_frame -bd $BDwidth_frame frame .fRtheme2 -relief $RELIEF_frame -bd $BDwidth_frame # frame .fRsamprate -relief $RELIEF_frame -bd $BDwidth_frame frame .fRsamprate -relief raised -bd 2 frame .fRcanvases -relief $RELIEF_frame -bd $BDwidth_frame frame .fRcanvases.fRcanvas1 -relief raised -bd 2 ##+############################## ## PACK the top-level FRAMES. ##+############################## pack .fRbuttons \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRmount \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRtheme1 \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRtheme2 \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRsamprate \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRcanvases \ -side top \ -anchor nw \ -fill both \ -expand 1 ##+###################################################### ## We pack a single 'canvases' sub-frame, for now. ## ## Someday we may allow for at least two meters. ## However, we do not want the additional meters ## to show if they are not going to be used --- for ## example, on computers with only one (root) file system. ##+###################################################### pack .fRcanvases.fRcanvas1 \ -side left \ -anchor nw \ -fill both \ -expand 1 ##+########################################################## ## The FRAMES ARE PACKED. START PACKING WIDGETS IN THE FRAMES. ##+########################################################## ##+########################################################## ## In FRAME '.fRbuttons' - ## DEFINE-and-PACK 'BUTTON' WIDGETS ## --- Exit, Help, Refresh, Report BUTTONS. ##+########################################################## button .fRbuttons.buttEXIT \ -text "$aRtext(buttonEXIT)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {exit} button .fRbuttons.buttHELP \ -text "$aRtext(buttonHELP)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {popup_msgVarWithScroll .topHelp "$HELPtext"} button .fRbuttons.buttREPORT \ -text "$aRtext(buttonREPORT)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {Report} button .fRbuttons.buttREFRESH \ -text "$aRtext(buttonREFRESH)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {Refresh} ## DEFINE Radiobuttons for Small/Medium/Large meters (background images) : radiobutton .fRbuttons.radbuttSMALL \ -text "$aRtext(radbuttSMALL)" \ -font fontTEMP_varwidth \ -anchor w \ -variable RADVARsizeSML \ -value "SMALL" \ -selectcolor "$radbuttBKGD" \ -relief flat \ -bd $BDwidthPx_radbutt radiobutton .fRbuttons.radbuttMEDIUM \ -text "$aRtext(radbuttMEDIUM)" \ -font fontTEMP_varwidth \ -anchor w \ -variable RADVARsizeSML \ -value "MEDIUM" \ -selectcolor "$radbuttBKGD" \ -relief flat \ -bd $BDwidthPx_radbutt radiobutton .fRbuttons.radbuttLARGE \ -text "$aRtext(radbuttLARGE)" \ -font fontTEMP_varwidth \ -anchor w \ -variable RADVARsizeSML \ -value "LARGE" \ -selectcolor "$radbuttBKGD" \ -relief flat \ -bd $BDwidthPx_radbutt ## PACK the widgets in frame '.fRbuttons'. pack .fRbuttons.buttEXIT \ .fRbuttons.buttHELP \ .fRbuttons.buttREPORT \ .fRbuttons.buttREFRESH \ .fRbuttons.radbuttSMALL \ .fRbuttons.radbuttMEDIUM \ .fRbuttons.radbuttLARGE \ -side left \ -anchor w \ -fill none \ -expand 0 ##+########################################################## ## In FRAME '.fRmount' - ## DEFINE a BUTTON and a LABEL-AND-ENTRY widget pair. ## Then PACK THEM. ##+########################################################## button .fRmount.buttMOUNTS \ -text "$aRtext(buttonMOUNTS)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {show_mounts} label .fRmount.labelMOUNT \ -text "$aRtext(labelMOUNT)" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label ## Here is the ENTRY field for the filesys-mount-point. ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set MOUNTname "/" entry .fRmount.entryMOUNT \ -textvariable MOUNTname \ -bg $entryBKGD \ -font fontTEMP_fixedwidth \ -width 9 \ -relief sunken \ -bd $BDwidthPx_entry ## PACK the widgets in the 'fRmount' frame. pack .fRmount.buttMOUNTS \ .fRmount.labelMOUNT \ .fRmount.entryMOUNT \ -side left \ -anchor w \ -fill none \ -expand 0 ##+########################################################## ## In FRAME '.fRtheme1' - ## DEFINE a LABEL, a SCALE, and 1 CHECKBUTTON. ## Then PACK THEM. ##+########################################################## label .fRtheme1.labelTHEME \ -text "$aRtext(labelTHEMEscale)" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set THEMEindex 1 scale .fRtheme1.scaleTHEME \ -from 1 -to $Nthemes \ -resolution 1 \ -font fontTEMP_SMALL_varwidth \ -variable THEMEindex \ -showvalue true \ -orient horizontal \ -bd $BDwidthPx_scale \ -length 100 \ -width $scaleThicknessPx set LABELS0or1 1 checkbutton .fRtheme1.chkbuttLABELS \ -text "$aRtext(chkbuttLABELS)" \ -font fontTEMP_varwidth \ -padx $PADXpx_chkbutton \ -pady $PADYpx_chkbutton \ -bd $BDwidthPx_chkbutt \ -variable LABELS0or1 \ -selectcolor "$chkbuttBKGD" \ -relief flat ## Pack the widgets in the '.fRtheme1' frame: pack .fRtheme1.labelTHEME \ .fRtheme1.scaleTHEME \ .fRtheme1.chkbuttLABELS \ -side left \ -anchor w \ -fill none \ -expand 0 ##+########################################################## ## In FRAME '.fRtheme2' - ## DEFINE 2 CHECKBUTTON widgets. ## Then PACK THEM. ##+########################################################## set ARC0or1 1 checkbutton .fRtheme2.chkbuttARC \ -text "$aRtext(chkbuttARC)" \ -font fontTEMP_varwidth \ -padx $PADXpx_chkbutton \ -pady $PADYpx_chkbutton \ -bd $BDwidthPx_chkbutt \ -variable ARC0or1 \ -selectcolor "$chkbuttBKGD" \ -relief flat set CORNERS0or1 1 checkbutton .fRtheme2.chkbuttCORNERS \ -text "$aRtext(chkbuttCORNERS)" \ -font fontTEMP_varwidth \ -padx $PADXpx_chkbutton \ -pady $PADYpx_chkbutton \ -bd $BDwidthPx_chkbutt \ -variable CORNERS0or1 \ -selectcolor "$chkbuttBKGD" \ -relief flat ## Pack the widgets in the '.fRtheme2' frame: pack .fRtheme2.chkbuttARC \ .fRtheme2.chkbuttCORNERS \ -side left \ -anchor w \ -fill none \ -expand 0 ##+########################################################## ## In FRAME '.fRsamprate' - ## DEFINE a LABEL-AND-SCALE widget pair --- ## and another pair of LABEL widgets. ## Then PACK THEM. ##+########################################################## ## Here is the LABEL-AND-SCALE pair for the wait-seconds (sample rate). label .fRsamprate.labelSAMPLEscale \ -text "$aRtext(labelSAMPLEscale)" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief flat \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label ## Set this widget var in the GUI initialization section ## at the bottom of this script. # set WAITseconds 60 set LIMITseconds 120.0 scale .fRsamprate.scaleSECONDS \ -from 0.1 -to $LIMITseconds \ -resolution 0.1 \ -font fontTEMP_SMALL_varwidth \ -variable WAITseconds \ -showvalue true \ -orient horizontal \ -bd $BDwidthPx_scale \ -length 180 \ -width $scaleThicknessPx ## Here is a label to show the current sample count. label .fRsamprate.labelSAMPLECOUNT \ -text "$aRtext(labelSAMPLECOUNT)" \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd 0 label .fRsamprate.labelCOUNT \ -textvariable VARsampcnt \ -font fontTEMP_varwidth \ -justify left \ -anchor w \ -relief flat \ -bd 0 ## Pack the widgets in frame '.fRsamprate'. pack .fRsamprate.labelSAMPLEscale \ .fRsamprate.scaleSECONDS \ .fRsamprate.labelSAMPLECOUNT \ .fRsamprate.labelCOUNT \ -side left \ -anchor w \ -fill none \ -expand 0 ##+######################################################## ## In FRAME '.fRcanvases.fRcanvas1' - ## DEFINE several LABEL lines and ONE CANVAS WIDGET (no scrollbars). ## Then PACK THEM. ## ## We set highlightthickness & borderwidth of the canvas to ## zero, as suggested on page 558, Chapter 37, 'The Canvas ## Widget', in the 4th edition of the book 'Practical ## Programming in Tcl and Tk'. ##+####################################################### label .fRcanvases.fRcanvas1.labelINFO1 \ -text "" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief raised \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label label .fRcanvases.fRcanvas1.labelINFO2 \ -text "" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief raised \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label label .fRcanvases.fRcanvas1.labelINFO3 \ -text "" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief raised \ -padx $PADXpx_label \ -pady $PADYpx_label \ -bd $BDwidthPx_label canvas .fRcanvases.fRcanvas1.can \ -width $initCanWidthPx \ -height $initCanHeightPx \ -relief flat \ -highlightthickness 0 \ -borderwidth 0 ## PACK the widgets in frame '.fRcanvases.fRcanvas1'. pack .fRcanvases.fRcanvas1.labelINFO1 \ .fRcanvases.fRcanvas1.labelINFO2 \ .fRcanvases.fRcanvas1.labelINFO3 \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRcanvases.fRcanvas1.can \ -side top \ -anchor center \ -fill none \ -expand 0 ##+################################################## ## END OF DEFINITION of the GUI widgets. ##+################################################## ## Start of BINDINGS, PROCS, Added-GUI-INIT sections. ##+################################################## ##+################################################################## ##+################################################################## ## BINDINGS SECTION: ##+################################################################## bind .fRmount.entryMOUNT {Refresh} bind .fRbuttons.radbuttSMALL {Refresh} bind .fRbuttons.radbuttMEDIUM {Refresh} bind .fRbuttons.radbuttLARGE {Refresh} bind .fRtheme1.scaleTHEME {Refresh} bind .fRtheme1.chkbuttLABELS {Refresh} bind .fRtheme2.chkbuttARC {Refresh} bind .fRtheme2.chkbuttCORNERS {Refresh} ## The Refresh' proc runs both the 'make_meters' proc and the ## 'update_pointers' proc. ## ## In the CHECKBUTTON 'events' above, the theme (in particular, the ## meter background, and size) has not changed, so we do not ## need to rebuild the entire meter. For example, reloading the ## meter background image is not really necessary. (The same ## can be said of the 'entryMOUNT' event.) ## ## But the use of these checkbuttons is very seldom, if at all, ## in a session. So running 'Refresh' for those events is not ## really incurring an inordinate amount of processing. We use ## 'Refresh' for these events, rather than breaking up the ## 'make_one_meter' proc into a smaller sequence of procs --- or ## adding arguments to the 'make_one_meter' proc to turn various ## sections of the make-meter processing off and on. ##+################################################################## ##+################################################################## ## DEFINE PROCS SECTION: ## ## 'make_meters' - to draw meter(s) within Tk (square) canvas(es). ## ## We allow the Tk canvas(es) to resize according to ## a resizing of the window. This proc will draw the ## meter/s with size based on the current size of the ## 'fRmeters' frame. ## ## 'make_one_meter' - to draw one tachometer. Called by 'make_meters' ## to make the meter(s). ## ## 'update_pointers' - to update the pointer(s) on the meter(s). ## Called initially at the bottom of this script. ## And called in the 'Refresh' proc. ## ## 'update_one_pointer' - to draw one pointer in a specified meter-canvas. ## Called by 'update_pointers' to update each of the ## pointers on the one or more meters. ## ## 'Refresh' - called by the 'Refresh' button. Runs the procs ## 'make_meters' and 'update_pointers' --- in particular, ## for the user to force the meter(s) to be resized if ## the user resizes the window --- and whenever the user ## wants a new 'reading'. ## ## 'Report' - called by the 'Report' button. This Report proc ## calls on the 'get_fileSystems_spaceData.sh' script ## with the 'all' parameter. ## ## 'show_mounts' - called by the 'ShowMounts' button. This proc ## calls on the 'get_fileSystems_spaceData.sh' script ## with the 'mounts' parameter. ## ## 'popup_msgVarWithScroll' - to show the HELPtext var. Called by the 'Help' button. ## Also used by the 'Report' and 'ShowMounts' buttons. ##+############################################################################ ##+######################################################################## ## PROC 'make_meters' ##+######################################################################## ## PURPOSE: Draws all features of one or more tachometer-style meters (except ## the pointers) --- in a 'nice filling-size' according to the ## current canvas dimensions. ## ## We will allow the canvas(es) to resize according to ## a resizing of the window. This proc will redraw the ## meter(s) in proportion to the new size of the canvas. ## ## CALLED BY: once, at the 'Additional GUI Initialization' section, ## at the bottom of this script --- and ## in the 'ReDraw...' proc. ##+######################################################################## # set Nmeters 1 proc make_meters {} { ## FOR TESTING: (to dummy out this proc) # return # global Nmeters ######################################################### ## Draw meter1 (without pointer). ######################################################### make_one_meter .fRcanvases.fRcanvas1.can ######################################################### ## IF we were using mulitple meters, we might do something ## like the following loop. ## ## Draw the Nmeters meters (without their pointers). ######################################################### # for {set i 1} {$i < $Nmeters} {incr i} { # eval make_one_meter .fRcanvases.fRcanvas$i.can # } } ## END OF proc 'make_meters' ##+######################################################################## ## PROC 'make_one_meter' ##+######################################################################## ## PURPOSE: Draws all features of a 'high-definition' meter (except the ## pointer). ## ## The features include: ## 1) the meter background image - with canvas 'create image' ## 2) tic-marks following an arc path - with canvas 'create line' ## 3) optionally (according to a checkbutton setting), an arc ## along the tic-marks - with canvas 'create arc' ## 4) optionally (according to a checkbutton setting), labels ## for the tic-marks - with canvas 'create text' ## 5) optionally (according to a checkbutton setting), decorative ## 'features' (rivets or whatever) at the 4 corners of the ## meter background image. ## ## The theme arrays (in particular, the dimensions of the meter ## background image and the 'center point' and 'radius' ratio-parameters) ## are used to set top-right and bottom-left coordinates to specify ## the location of the arc --- along which tic-marks and labels ## are drawn. ## ## CALLED BY: proc 'make_meters' ##+####################################################################### ## The following variables are used in the 'make_one_meter' proc. ## We set them at the bottom of this script, in the ## 'Additonal GUI Initialization' section, along with other parameter ## settings that the user may want to change. # set pi [expr {4.0 * atan(1.0)}] # set radsPERdeg [expr {$pi/180.0}] # set Nsegs 10 # set ticLabels "0 10 20 30 40 50 60 70 80 90 100" proc make_one_meter {canvas} { ## FOR TESTING: (to dummy out this proc) # return global pi radsPERdeg Nsegs ticLabels THEMEindex \ aRimgBkgd aRimgPointer aRimgCornerFeature \ aRcenterX aRcenterY aRradiusArc aRinORout aRticsYorN \ aRhexcolorText aRhexcolorTics aRstartAngle aRextentAngle \ RADVARsizeSML ARC0or1 LABELS0or1 CORNERS0or1 \ imgSUFFIX DIRmeterBackgrounds DIRpointers DIRcornerFeatures \ centerXpx centerYpx radiusPx ################################################################ ## Remove any previously drawn elements in this canvas, if any. ################################################################ catch {$canvas delete all} ################################################################## ## CREATE THE TK IN-MEMORY IMAGE STRUCTURE FROM THE ## METER-BACKGROUND-IMAGE FILE --- determined by the current ## theme index, $THEMEindex. ################################################################## image create photo imgID_meter -file \ "$DIRmeterBackgrounds/$aRimgBkgd($THEMEindex)_${RADVARsizeSML}.$imgSUFFIX" ################################################## ## PUT THE BACKGROUND IMAGE ON THE CANVAS. ################################################## $canvas create image 0 0 -anchor nw -image imgID_meter ## FOR TESTING: (exit this proc before adding more to the meter) # return ################################################################## ## CREATE THE TK IN-MEMORY IMAGE STRUCTURE FROM THE ## POINTER-IMAGE FILE --- determined by the current ## theme index, $THEMEindex --- IF the file is specified in ## the theme. ################################################################## if {"$aRimgPointer($THEMEindex)" != ""} { image create photo imgID_pointer -file \ "$DIRpointers/$aRimgPointer($THEMEindex).$imgSUFFIX" } ################################################################## ## Start setting parameters that may be used to place/draw other ## items on the meter --- tic-marks, arc, tic-labels, ## a-feature-in-4-corners, meter-title. ################################################################## ## GET the WIDTH AND HEIGHT OF THE BACKGROUND IMAGE for the meter. ################################################################## set meterWidthPx [image width imgID_meter] set meterHeightPx [image height imgID_meter] set meterMinPx $meterWidthPx if {$meterHeightPx < $meterMinPx} {set meterMinPx $meterHeightPx} ################################################################## ## FORCE THE CANVAS TO CHANGE SIZE ACCORDING TO THE NEW METER IMAGE. ################################################################## $canvas configure -width $meterWidthPx $canvas configure -height $meterHeightPx ########################################################### ## SET parameters for drawing TIC-MARKS and/or LABELS ## around the ARC. ########################################################### ## NOTE: centerXpx centerYpx radiusPx are calculated in this proc. ## They are also used in the 'update_one_pointer' proc. ## ## Since the same meter-background-image with the ## same center-location and radius-for-tic-marks parameters ## are used for both meters, we declare these 3 parameters ## as global parameters and use them in the ## 'update_one_pointer' proc, for both meters. ########################################################### set centerXpx [expr {$meterWidthPx * $aRcenterX($THEMEindex)}] set centerYpx [expr {$meterHeightPx * $aRcenterY($THEMEindex)}] set radiusPx [expr {$meterMinPx * $aRradiusArc($THEMEindex)}] set DEGperTIC [expr {double($aRextentAngle($THEMEindex)) / $Nsegs}] ################################################# ## IF the ARC checkbutton is ON. ## DRAW ARC-LINE along which to put tic marks, ################################################# ## EXAMPLE ## (if aRextentAngle($THEMEindex) = 320 degrees ## and aRstartAngle($THEMEindex) = -70 degrees): ## ## 320 degrees counter-clockwise from -70 degrees ## (based at 3 oclock) is 70 degrees beyond 180. ## I.e. -70 + 320 = 250 = 180 + 70 ################################################# if {$ARC0or1 == 1} { set x1 [expr {$centerXpx - $radiusPx}] set y1 [expr {$centerYpx - $radiusPx}] set x2 [expr {$centerXpx + $radiusPx}] set y2 [expr {$centerYpx + $radiusPx}] $canvas create arc $x1 $y1 $x2 $y2 \ -start $aRstartAngle($THEMEindex) \ -extent $aRextentAngle($THEMEindex) -style arc \ -outline $aRhexcolorTics($THEMEindex) -width 2 ####################################################### ## Draw red-line arc-segment (danger zone) of the meter. ####################################################### ## Recall that the '-start' of 'create arc' is at ## the 3 o'clock (east) position. ## We have the arc of 0 to 100 percent going from ## $aRstartAngle($THEMEindex) for $aRextentAngle($THEMEindex) ## degrees as we traverse the 'dial' counter-clockwise. ## ## So we can draw the red-line from $aRstartAngle($THEMEindex) ## a certain number of degrees --- say 15-percent of ## $aRextentAngle($THEMEindex) --- going clockwise. ####################################################### set redLineWidthPx 8 set redLineIndentPx [expr {0.6 * $redLineWidthPx}] set x1 [expr {$x1 + $redLineIndentPx}] set y1 [expr {$y1 + $redLineIndentPx}] set x2 [expr {$x2 - $redLineIndentPx}] set y2 [expr {$y2 - $redLineIndentPx}] set extentDegrees [expr {0.15 * $aRextentAngle($THEMEindex)}] $canvas create arc $x1 $y1 $x2 $y2 \ -start $aRstartAngle($THEMEindex) \ -extent $extentDegrees -style arc \ -outline red -fill red -width $redLineWidthPx } ## END OF if {$ARC0or1 == 1} ## FOR TESTING: (exit this proc before adding more to the meter) # return ########################################################### ## DRAW TIC-MARKS around the meter. ## (The ticmarks are drawn according to the value of the ## array setting $aRticsYorN($THEMEindex).) ########################################################### if { "$aRticsYorN($THEMEindex)" == "N" } { ## Set the outer or inner location (radius) of the TICMARKS, ## according to the value of $aRinORout($THEMEindex). if { "$aRinORout($THEMEindex)" == "in" } { set radius2Px [expr {0.90 * $radiusPx}] } if { "$aRinORout($THEMEindex)" == "out" } { set radius2Px [expr {1.10 * $radiusPx}] } set angle0 [expr {$aRextentAngle($THEMEindex) + $aRstartAngle($THEMEindex)}] for {set i 0} {$i <= $Nsegs} {incr i} { set rads [expr {($angle0 - ($DEGperTIC * $i)) * $radsPERdeg}] set x1 [expr {$centerXpx + $radiusPx * cos($rads)}] set y1 [expr {$centerYpx - $radiusPx * sin($rads)}] set x2 [expr {$centerXpx + $radius2Px * cos($rads)}] set y2 [expr {$centerYpx - $radius2Px * sin($rads)}] $canvas create line \ $x1 $y1 $x2 $y2 \ -fill $aRhexcolorTics($THEMEindex) -width 2 } ## END OF for {set i 0} ... (for drawing TIC MARKS) } ## END OF if { "$aRticsYorN($THEMEindex)" == "N" } ## FOR TESTING: (exit this proc before adding more to the meter) # return ########################################################### ## DRAW LABELS around the meter. ## (The labels are drawn if the LABELS check button is ON.) ########################################################### if {$LABELS0or1 == 1} { ## Set the outer or inner location (radius) of the LABELS, ## according to the value of $aRinORout($THEMEindex). if { "$aRinORout($THEMEindex)" == "in" } { set radius2Px [expr {0.80 * $radiusPx}] } if { "$aRinORout($THEMEindex)" == "out" } { set radius2Px [expr {1.20 * $radiusPx}] } set angle0 [expr {$aRextentAngle($THEMEindex) + $aRstartAngle($THEMEindex)}] for {set i 0} {$i <= $Nsegs} {incr i} { set rads [expr {($angle0 - ($DEGperTIC * $i)) * $radsPERdeg}] ## Calculate a center point for the i-th label. set x1 [expr {$centerXpx + $radius2Px * cos($rads)}] set y1 [expr {$centerYpx - $radius2Px * sin($rads)}] ## Get the i-th label from the list of labels. set ticlabel [lindex $ticLabels $i] ## Draw the tic-label on the canvas. $canvas create text \ $x1 $y1 \ -anchor center -justify center \ -fill $aRhexcolorText($THEMEindex) \ -text "$ticlabel" -font { Helvetica 10 } } ## END OF for {set i 0} ... (for drawing TIC LABELS) } ## END OF if {$LABELS0or1 == 1} ## FOR TESTING: (exit this proc before adding more to the meter) # return ############################################################# ## IF the CORNERS checkbutton is ON, ## PLACE 4 'FEATURES' AT THE CORNERS of the meter background. ############################################################# if {$CORNERS0or1 == 1 && "$aRimgCornerFeature($THEMEindex)" != ""} { ################################################################## ## CREATE THE TK IN-MEMORY IMAGE STRUCTURE FROM THE ## CORNER-FEATURE-IMAGE FILE --- determined by the current ## theme index, $THEMEindex. ################################################################## image create photo imgID_feature -file \ "$DIRcornerFeatures/$aRimgCornerFeature($THEMEindex).$imgSUFFIX" ############################################################### ## We set the corner coordinates of the 'outside-corner' of ## the 4 features at a fixed offset. ## ## (We could change this to position the 4 features based on ## its image dimensions and the width and height of the ## meter background.) ############################################################### ## Get the current imgID_feature width and height. set featureWidthPx [image width imgID_feature] set featureHeightPx [image height imgID_feature] # set featureMaxPx $featureWidthPx # if {$featureHeightPx > $featureMaxPx} {set featureMaxPx $featureHeightPx} # set FEATUREoffsetPx 8 set FEATUREoffsetPx [expr {0.02 * $meterMinPx}] ## Place upper-left feature. set x1 $FEATUREoffsetPx set y1 $FEATUREoffsetPx $canvas create image $x1 $y1 \ -anchor nw -image imgID_feature ## Place upper-right feature. set x1 [expr {$meterWidthPx - $FEATUREoffsetPx}] set y1 $FEATUREoffsetPx $canvas create image $x1 $y1 \ -anchor ne -image imgID_feature ## Place lower-left feature. set x1 $FEATUREoffsetPx set y1 [expr {$meterHeightPx - $FEATUREoffsetPx}] $canvas create image $x1 $y1 \ -anchor sw -image imgID_feature ## Place lower-right feature. set x1 [expr {$meterWidthPx - $FEATUREoffsetPx}] set y1 [expr {$meterHeightPx - $FEATUREoffsetPx}] $canvas create image $x1 $y1 \ -anchor se -image imgID_feature } ## END OF if {$CORNERS0or1 == 1} ## FOR TESTING: (exit this proc before adding more to the meter) # return #################################################################### ## DRAW A '%' TEXT-LABEL, ## near the top of the meter arc. #################################################################### $canvas create text \ $centerXpx [expr {$centerYpx - (0.50 * $radiusPx)}] \ -anchor center -justify center \ -fill $aRhexcolorText($THEMEindex) \ -text "%" -font { Helvetica 10 normal roman} } ## END OF proc 'make_one_meter' ##+######################################################################## ## PROC 'update_pointers' ##+######################################################################## ## PURPOSE: Updates pointer on a canvas (perhaps more than one someday) ## --- using the Linux/Unix/BSD/Mac 'df' command to get ## filesystem storage space (%-used,allocated-Gig, and used-Gig). ## ## This proc uses the 'update_one_pointer' proc to update ## the pointer for each of the Nmeters canvases, where ## each canvas corresponds to a file system. ## ## CALLED BY: the 'Additional GUI Initialization' section at the ## bottom of this script. ##+######################################################################## proc update_pointers {} { ## FOR TESTING: (dummy out this proc) # return global DIRthisScript WAITseconds MOUNTname VARsampcnt # global Nmeters ############################################################### ## For a given file-system mount-point-name, get tne 'df' data ## --- %-used, alloc-gig, used-gig, free-gig, device-name. ## ## Here is an example of the output of the '' script ## for a given mount name (directory name): ## $ ./get_fileSystems_spaceData.sh /home ## /home 46 75.973 32.542 39.572 /dev/sda5 ## ## We use the Tcl 'foreach-break' 'trick' to put the ## space-separated values into separate variables. ############################################################### foreach {MOUNTname PERCENTused ALLOCgig USEDgig AVAILgig DEVICEname} \ [exec $DIRthisScript/get_fileSystems_spaceData.sh $MOUNTname] {break} incr VARsampcnt ## FOR TESTING: if {0} { puts "proc 'update_pointers': (parms returned from shell script)" puts "MOUNTname: $MOUNTname" puts "PERCENTused: $PERCENTused" puts "ALLOCgig: $ALLOCgig" puts "USEDgig: $USEDgig" puts "AVAILgig: $AVAILgig" puts "DEVICEname: $DEVICEname" } ######################################################### ## Update the pointers on up to Nmeters canvases. ######################################################### # for {set i 1} {$i <= $Nmeters} {incr i} { # eval update_one_pointer .fRmeters.fRmeter$i \ # $aRallocated($i) $aRused($i) $aRavail($i) "$aRfilesystem($i)" # } update_one_pointer .fRcanvases.fRcanvas1 \ $ALLOCgig $USEDgig $AVAILgig "$MOUNTname" ################################################################ ## 'Pseudo-Recursively' 'fork off' another (delayed) instance of ## 'update_pointers' here to support the wait-seconds scale widget ## --- using the 'after ms cmd arg arg ...' form of the 'after' ## command. ## ## (We recalculate WAITmillisecs in case the user has changed the ## WAITseconds value via the 'samprate' scale widget.) ################################################################ set WAITmillisecs [expr {int($WAITseconds * 1000)}] after $WAITmillisecs update_pointers } ## END OF proc 'update_pointers' ##+######################################################################## ## PROC 'update_one_pointer' ##+######################################################################## ## PURPOSE: Updates a pointer on a specified canvas --- using the canvas ## frame ID and the allocated,used,filesys data passed as arguments. ## ## CALLED BY: the 'update_pointers' proc ##+######################################################################## proc update_one_pointer {frame TOT USED AVAIL FILESYS} { ## FOR TESTING: (dummy out this routine) # return global pi radsPERdeg Nsegs centerXpx centerYpx radiusPx \ aRextentAngle aRstartAngle aRimgPointer aRinORout THEMEindex ## 'aRcenterX aRcenterY aRradiusArc' ## are not needed. We use the globals 'centerXpx centerYpx radiusPx' ## that were calculated in 'make_one_meter' instead. ################################################################## ## Set the text in the 3 label lines above the canvas-meter-image. ################################################################## ## Better to use AVAIL instead of USED to calculate the %-used. ## Reference: ## http://larsmichelsen.com/open-source/answer-why-does-df-k-show-wrong-percentage-usage/ ## which references 'man mke2fs' --- explanation of '-m' parameter ## --- a reserved-blocks-percentage which is typically about 5%. ## So replaced this statement by the following. # set PERcent [expr {($USED * 100.0) / $TOT}] set USED2 [format "%6.3f" [expr {$TOT - $AVAIL}]] set PERcent [expr {($USED2 * 100.0) / $TOT}] set TOTtext "Total space for filesys '$FILESYS' = $TOT Gigabytes" set USEDtext "Used+Reserved in filesys '$FILESYS' = $USED2 Gigabytes" set AVAILtext "Available in filesys '$FILESYS' = $AVAIL Gigabytes" $frame.labelINFO1 configure -text "$TOTtext" $frame.labelINFO2 configure -text "$USEDtext" $frame.labelINFO3 configure -text "$AVAILtext" ############################################################ ## Use 'PERcent' to locate the pointer around the arc-of-tic-marks. ## To do this: ## Convert PERcent to an angle in radians on the arc. ## ## First, set the angle for the zero-point on the arc-of-tic-marks. ############################################################ set angle0 [expr {$aRextentAngle($THEMEindex) + $aRstartAngle($THEMEindex)}] ######################################################### ## Convert PERcent to an angle in radians on the arc. ######################################################### set degsPointer [expr {$angle0 - (double($aRextentAngle($THEMEindex)) * $PERcent / 100.0)}] set radsPointer [expr {$degsPointer * $radsPERdeg}] ## FOR TESTING: # puts "proc 'update_one_pointer'." # puts "TOT: $TOT USED: $USED AVAIL: $AVAIL" # puts "PERcent: $PERcent degsPointer: $degsPointer radsPointer: $radsPointer" ##################################### ## Remove a previous pointer, if any. ##################################### catch {$frame.can delete -tags TAGpointer} ################################################## ## If an image was supplied for a pointer, ## PUT THE POINTER-IMAGE ON THE CANVAS --- ## otherwise draw a red pointer 'needle' with ## canvas 'create line'. ################################################## if {"$aRimgPointer($THEMEindex)" != ""} { ################################################################ ## Calculate the coordinates for the tip and base of the ## IMAGE pointer --- according to whether aRinORout is ## "in" or "out". ################################################################ if {"$aRinORout($THEMEindex)" == "in"} { set x1 [expr {$centerXpx + 0.60 * $radiusPx*cos($radsPointer)}] set y1 [expr {$centerYpx - 0.60 * $radiusPx*sin($radsPointer)}] } else { set x1 [expr {$centerXpx + 1.35 * $radiusPx*cos($radsPointer)}] set y1 [expr {$centerYpx - 1.35 * $radiusPx*sin($radsPointer)}] } $frame.can create image $x1 $y1 -anchor center \ -image imgID_pointer -tag TAGpointer } else { ################################################################ ## Calculate the coordinates for the tip and base of the ## NEEDLE pointer. ################################################################ set xtip [expr {$centerXpx + 0.60 * $radiusPx*cos($radsPointer)}] set ytip [expr {$centerYpx - 0.60 * $radiusPx*sin($radsPointer)}] set xbase $centerXpx set ybase $centerYpx #################################################################### ## Draw a red-line pointer and a reddish-white line on either side ## --- for an (attempted) anti-aliasing effect. ## ## NOTE: This attempt at anti-aliasing did not work out well. ## This code needs improvement --- or simply one 'create line'. #################################################################### $frame.can create line \ $xbase $ybase $xtip $ytip \ -fill #ff0000 -width 4 -tag TAGpointer $frame.can create line \ [expr {$xbase + 1}] [expr {$ybase + 1}] \ [expr {$xtip + 1}] [expr {$ytip + 1}] \ -fill #ff8888 -width 2 -tag TAGpointer $frame.can create line \ [expr {$xbase - 1}] [expr {$ybase - 1}] \ [expr {$xtip - 1}] [expr {$ytip - 1}] \ -fill #ff8888 -width 2 -tag TAGpointer } ## END OF if {"$aRimgPointer" != ""} } ## END OF proc 'update_one_pointer' ##+############################################################# ## proc Refresh ## ## PURPOSE: 'Refresh' the one (or more) meters and their pointers --- ## for when the user wants a new start-time of getting ## file-system usage values ## and/or when the user changes the meter features. ## ## CALLED BY: 'Refresh' button and various bindings ##+############################################################# proc Refresh {} { ## Cancel pending pointer update(s), before redrawing ## the meter(s) and restarting the update_pointers cycle. set LISTids [after info] foreach ID $LISTids { after cancel $ID } make_meters update_pointers } ## END OF proc 'Refresh' ##+############################################################# ## proc show_mounts ## ## PURPOSE: Shows available mount points (directories), in a ## popup message window. ## ## CALLED BY: 'ShowMounts' button ##+############################################################# proc show_mounts {} { global DIRthisScript set MOUNTS [exec $DIRthisScript/get_fileSystems_spaceData.sh mounts] popup_msgVarWithScroll .topMOUNTS "$MOUNTS" } ## END OF proc 'show_mounts' ##+############################################################# ## proc Report ## ## PURPOSE: Shows a report on space-usage for all mount points, ## in a popup message window. ## ## CALLED BY: 'Report' button ##+############################################################# proc Report {} { global DIRthisScript set USAGEtext [exec $DIRthisScript/get_fileSystems_spaceData.sh all] popup_msgVarWithScroll .topREPORT "$USAGEtext" } ## END OF proc 'Report' ##+######################################################################## ## 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 $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_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 PROC definitions. ##+######################## ## Set HELPtext var. ##+######################## set HELPtext "\ \ \ ** HELP for this 'File System Space Usage' Monitoring Utility ** This utility is meant to show a GUI that holds a tachometer-style METER, with a range of zero to one hundred percent. The 'pointer' on the meter shows the PERCENT of available FILE-SYSTEM STORAGE SPACE IN USE --- for a user-specifiable file-system 'mount point' (directory name). The meter background is an image file shown on a Tk 'canvas' widget. Initially, the file system is set to the 'root' file system --- directory name '/'. The 'ShowMounts' button can be used to show other mount-points (directories) of other file-systems (in other words, disk partitions) of this computer, if any. For example, if '/home' is a mount point, that directory name can be entered in an entry field to reset the file-system for which the meter displays the PERCENT-USED. *************** DATA COLLECTION: The pointer on the meter is updated periodically --- according to a 'SampleRate' (seconds) setting on the GUI. The seconds-setting can be reset by a 'scale' widget. Alternatively, instead of depending on auto-updates, the user may choose to click on a 'Refresh' button --- to immediately update the meter with the current PERCENT-USED value for the user-selected mount point. Then auto-updates continue at the current SampleRate setting. Besides showing PERCENT-USED on an arc on the meter, the actual 'Allocated', 'Used', and 'Available' space values (in Gigabytes) are shown for the metered file system. The user can click on a 'Report' button on the GUI to show the allocated, used, available, and percent-used values for the several file systems of the computer. The report is shown in a popup text window. The user can copy-and-paste the text into another window, such as a text editor or word processor window. This Tcl-Tk script was developed on Linux and uses the 'df' command to get the file-system storage-space data --- for the meter and for the 'Report' option. ************************************ THE SCRIPT USED to update the meter(s): A Tcl 'exec' command calls on a separate shell script --- 'get_fileSystems_spaceData.sh' --- that uses the 'df -kl' command to get the 'Allocated' and 'Used' data for the 'local' file systems. That shell script extracts-and-formats the data for return to this Tk script. This shell script is used for 3 functions of this GUI: 1) To show %-SPACE-USAGE via the meter, for a USER-SPECIFIED MOUNT POINT. 2) To show THE MOUNT POINTS (directories) known to this computer. 3) To present a SPACE-USAGE REPORT for ALL the file systems known to this computer. If the 'df' command is not available on your computer, then you are probably not using a Linux, Unix, BSD, or Apple-Mac system. For other operating systems, you may need to write a C program to get file system 'allocated', 'used', 'available', and 'percent-used' data. ************* METER RESIZE: The user can choose to resize the meter. The Small/Medium/Large radiobuttons at the top of the GUI allow the user to quickly choose a different size for the percent-used meter. ************ TIC-FEATURES (and corner features) There are 3 checkbuttons on the GUI that can be used to turn off the placement of - Tic Labels - the Tic Arc - corner-features (like rivets or screwheads) in the 4 corners of the meter. ************ METER THEMES: About 10 different themes for the meters (including the pointers) are quickly selectable via a 'Theme' scale widget on the GUI. The themes are selected by an integer --- from 1 to 10, say. The themes include 3 images: - a meter background image - a pointer image - an optional 'corner feature' image (such as a rivet in 4 corners). The images are stored in 3 sub-directories of this Tk script: - 'meter_backgrounds' - 'pointers' - 'corner_features' The user can add or change images in those 3 subdirectories. In this Tk script, there are 12 arrays that are used to store data for each 'meter-theme'. The user can add/change a theme by adding/changing some 'set' statements. Here is an example of the array set statements for a theme 1: set aRimgBkgd(1) \"meter_background_3DsphericalPuzzle-whiteBkgd\" set aRticsYorN(1) \"N\" set aRcenterX(1) 0.5 set aRcenterY(1) 0.5 set aRradiusArc(1) 0.35 set aRinORout(1) \"in\" set aRhexcolorText(1) \"#000000\" set aRhexcolorTics(1) \"#000000\" set aRimgPointer(1) \"bullet_earth_whiteOnBlue_transp_25x25\" set aRimgCornerFeature(1) \"screwHeadSlotted_30deg_gray_transp_27x27\" set aRstartAngle(1) -70 set aRextentAngle(1) 320 The 3 images are specified in the arrays named 'aRimgBkgd', 'aRimgPointer', and 'aRimgCornerFeature'. In addition to these image names, there are parameters that indicate: - whether tic marks are on the meter-background image. (If 'N', tic marks may be drawn on the background image.) - the center and radius for the tic-marks arc of the meter (as ratios between 0.0 and 1.0). - whether the tic-marks should be drawn to the inside or outside of the arc ('in' or 'out'). - a color for the tic-marks and the tic-labels (#000000 = black). - a start-angle and extent-angle for drawing the tic-marks arc, counter-clockwise (specified relative to a horizontal, right-pointing x-axis). Note that this GUI is very malleable. Not only can the user edit the Tk script and change the themes, but ALSO essentially anything about the GUI is changeable. For example, the fonts used for the text on buttons and labels are changeable. The organization of the elements on the GUI are changeable --- some such changes are as easy as changing the order of some 'pack' statements. *********************** CAPTURING THE GUI IMAGE: A screen/window capture utility (like 'gnome-screenshot' on Linux) can be used to capture the GUI image in a PNG or GIF file, say. If necessary, an image editor (like 'mtpaint' on Linux) can be used to crop the window capture image. The image could also be down-sized --- say to make a smaller image suitable for use in a web page or an email. " ##+################################################################ ##+################################################################ ## Additional GUI INITIALIZATION: Mainly to ## - Set various parameters, esp. ones that the user may want to change. ## - Put the meter on its canvas, with 'make_meters'. ## - Start an execution loop for the 'update_pointers' proc. ##+################################################################ ##+############################################################## ## THE 'THEMES-ARRAYS' are defined far above --- just below the ## section where the 'aRtext' array values are set. ## You can change the themes there, if you wish. ##+############################################################## #+################################################################# ## Set the image type to use --- GIF or PNG. ## If you use the 8.5 or earlier versions of the 'wish' interpreter, ## you may need to use GIF files for the images --- if you do not ## want to use Tcl-Tk 'extensions'. For version 8.6 and later, ## you can use PNG files. ## ## If you change the image type, change the DIR variables below. #+################################################################# set imgSUFFIX "gif" # set imgSUFFIX "png" ##+############################################################# ## Get the directory that this Tk script is in. That will be the ## directory that the 'external' utility shell script should be ## in. This directory is used to call the shell script that ## is used in the 'update_pointers' proc. ##+############################################################# ## FOR TESTING: # puts "argv0: $argv0" # set DIRthisScript "." # set DIRthisScript "[pwd]" # set DIRthisScript "$env(HOME)/apps/tkUtils" set DIRthisScript "[file dirname $argv0]" set DIRmeterBackgrounds "$DIRthisScript/meter_backgrounds/GIFs" set DIRpointers "$DIRthisScript/pointers/GIFs" set DIRcornerFeatures "$DIRthisScript/corner_features/GIFs" ##+############################################################# ## Initialize a couple of variables that are needed for the ## first call to the 'update_pointers' proc. Variables: ## VARsampcnt and MOUNTname. ##+############################################################# set VARsampcnt 0 ## We start with the root file system as the file system ## whose %-used is shown on the meter. set MOUNTname "/" ##+################################################### ## Set the scale widget var for initial 'refresh rate' ## (actually wait-time = 'wave-length', not 'frequency') ## --- in seconds. ##+################################################### # set WAITseconds 120.0 # set WAITseconds 60.0 set WAITseconds 30.0 ## FOR TESTING: # set WAITseconds 4.0 ##+############################################################# ## Set the default value for the set of S/M/Lradiobuttons. ##+############################################################# set RADVARsizeSML "SMALL" # set RADVARsizeSML "MEDIUM" # set RADVARsizeSML "LARGE" ##+#################################################### ## Initialize variables that will be used in the ## 'make_one_meter' and 'update_one_pointer' procs. ##+#################################################### set pi [expr {4.0 * atan(1.0)}] set radsPERdeg [expr {$pi/180.0}] set Nsegs 10 set ticLabels "0 10 20 30 40 50 60 70 80 90 100" ##+################################################# ## Draw the meter(s) --- without pointer(s). ##+################################################# make_meters ##+############################################################# ## Do an initial draw of the pointer(s). ## ## NOTE: ## 'update_pointers' starts a loop to keep updating the pointers. ## ## The proc 'update_pointers' re-schedules itself --- ## with 'after '. ##+############################################################# update_pointers