#!/usr/bin/wish ## ##+######################################################################## ## Linux/Unix NOTE: ## If the 'wish' interpreter is in a different directory, such as ## /usr/local/bin, you can make a soft-link from 'wish' there to ## /usr/bin/wish, as root, with a command like ## ln -s /usr/local/bin/wish /usr/bin/wish ##+######################################################################## ## Tk SCRIPT NAME: plotquik_BarChart_XYdataEntry.tk ## ## --- adapted from the script 'plot_quik_xy_bars.tk' ## in the 'feHandyTools' subsystem of the 'Freedom Environment' ## subsystems at www.freedomenv.com --- adapted for putting a ## 'standalone' utility (with no 'source' statements) in the ## FE 'tkGooies' system. ##+####################################################################### ## PURPOSE: An intuitive, easy-to-use X-Y-AXIS BARCHART PLOT UTILITY ## to make 'presentation quality' plots QUICKLY --- plots that ## are suitable to include in web pages and emails --- to get an ## idea across. ## _____________________________________________________________ ## ## This Tk script presents a GUI with a canvas widget showing ## a barchart plot --- with titles and labels that can be ## dragged with the mouse. ## ## This script presents entry fields in the GUI to prompt for ## x,y data and titles and axis labels and limits. ## _____________________________________________________________ ## ## This is a plotting-utility implementation using BASIC ## Tcl-Tk commands, i.e. not requiring an 'extension' of Tcl or Tk. ## ## Unfortunately, there do not seem to be any FAIRLY GENERAL, yet ## RELATIVELY SIMPLE, bar chart plotting scripts at Tcl-Tk archive ## sites --- even in 2013, more than 20 years after the development ## of the necessary Tk canvas facilities to support plotting. ## ## Nor are such general, easy-to-use bar chart plotting Tk scripts ## available via web searches on keyword strings such as ## 'bin wish canvas' or 'bin wish rect'. ## ## Even searches on 'canvas' and 'rect' on the wiki.tcl.tk site, ## in early 2013, yield only simplistic line plot 'demos' that are ## not suited to general and FAST bar chart plots --- with entry ## fields for quick entry of user data. ## ## This script is meant to fill that long-time void. ## _____________________________________________________________ ## ## SOURCES and CREDITS: ## ## The technique of dragging canvas items came from the Tcl-Tk demo in ## /usr/local/lib/tk4.0/demos/plot.tcl (on SGI-IRIX Unix, 1995). ## However, that script allowed the user to drag the data points. ## This script allows the user to drag titles and labels. ## ## On Linux (for example, Ubuntu 9.10, circa 2009), see ## /usr/share/doc/tk8.4/examples/plot.tcl ## or /usr/share/doc/tk8.5/examples/plot.tcl ## There are 60-plus other Tcl-Tk code examples in the ## 'examples' directory. ## ## See also 'create oval' plot scripts like ## 'items.tcl' and 'twind.tcl' in /usr/share/doc/tk8.x/examples/. ## These scripts provide examples of procs to move 'items' around ## on the canvas with a mouse. ## ##+##################################################################### ## ## INPUTS (via entry fields on the GUI): ## plot title, axis-labels, axis min-max, xy data-points. ## ## OUTPUT: Intended for screen/window capture to an image file with a ## screen-capture tool (such as 'gnome-screenshot' on Linux). ## ## The image could be cropped with an image editor (such as ## 'mtpaint' on Linux) and the cropped image could be printed ## using an image view-print utility (such as 'eog' = Eye of ## Gnome, on Linux) --- or a web browser (which might have ## better image printing capability). ## ## If you are going to print the image, you will probably ## want to change the background color to white, via the ## 'CanvasColor' button at the top of the GUI. ## ## (For another hard-copy option, a Postscript-Print button and ## proc could be implemented.) ## ##+################# ## THE GUI WIDGETS: ## ## The options available to the user are indicated by ## the following 'sketch' of the GUI. ## ## In the sketch of the GUI 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-X indicates a Tk 'checkbutton' widget. ## CAPITAL-O indicates a Tk 'radiobutton' widget (if any). ## <----O----> indicates a Tk 'scale' widget (if any). ## ## ------------------------------------------------------------------------------------------------------- ## ## FRAMEnames ## VVVVVVVVVV ## ----------------------------------------------------------------------------------- ## tkPlotQuik - Bar Chart - from X,Y data entered below ## [window title] ## ----------------------------------------------------------------------------------- ## ## .fRbuttons {Exit}{Help}{CanvasColor}{BarColor} {UpdatePlot}{GetImg}{DwnCan}{UpCan}{PrtPreview}{Print} [entry field here ## shows a print command] ## .fRopts X BarOutlines X PlotBorder BarWidth (%): {--}{-} ___{+}{++} Legend:_______________________________________ ## ## .fRtitle_main PlotTitle:____________________________________________________________________________________________________ ## ## .fRtitles_xy XaxisTitle:____________________________________________ YaxisTitle:___________________________________________ ## ## .fRlims_xy XaxisMin:__________ XaxisMax:__________ XticDist:______ YaxisMin:__________ YaxisMax:__________ YticDist:_____ ## ## .fRvals_x XdataValues: _________________________________________________________________________________________________ ## ## .fRvals_y YdataValues: _________________________________________________________________________________________________ ## ## .fRlow .fRlow.fRmsg .fRlow.fRplot ## [ an area here contains a brief [ an area here ## guide in a text or label widget contains a canvas widget ## ... ... ## many to be populated with ## ... ... ## lines 'items' whenever the 'UpdatePlot' button ## ... ... ## deep. in frame 'fRbuttons' is poked. ## ] ] ## ## --------------------------------------------------------------------------------------------------------------- ## ##+############## ## GUI components: ## ## From the GUI 'sketch' above, it is seen that the GUI consists of about ## ## - 14 button widgets ## - 12 label widgets ## - 13 entry widgets ## - 1 text widget (with scroll bars someday?) (or one more label instead) ## - 1 canvas widget (with scroll bars someday?) ## - 2 checkbutton widgets ## - 0 radiobutton widgets ## - 0 listbox widgets ## - 0 scale widgets ## ##+##################################################################### ## STRUCTURE OF THIS CODE: ## ## 0) Set general window parms (win-name, win-position, color-scheme, ## fonts, widget-geom-parms, text-array-for-labels-etc, win-size-control). ## 1a) Define ALL frames (and sub-frames, if any). ## 1b) Pack ALL frames and sub-frames. ## 2) Define & pack ALL widgets within frames, frame by frame --- ## typically going top-to-bottom and/or left-to-right, frame by frame. ## ## After ALL widgets are defined for a frame, ## pack the widgets in the frame. ## ## 3) Define key and mouse/touchpad/touch-sensitive-screen 'event' ## BINDINGS, if any. ## 4) Define PROCS, if any. ## 5) Additional GUI INITIALIZATION (typically with one or two ## of the procs), if needed. ## ## In more detail for this particular script: ## ## 1a) Define ALL frames: From the top down on the GUI are several horizontal ## frames stretching across the GUI: ## ## - 'fRbuttons' and several entry-widget frames for ## plot title, axis titles, axis limits, and data values. ## ## - Below those frames, across the GUI, is a container frame: 'fRlow'. ## ## There are 2 sub-frames on the left and right of the 'fRlow' frame: ## 'fRlow.fRmsg' and 'fRlow.fRplot' ## ## Help text is in the '.fRlow.fRmsg' frame. ## The plot is in the '.fRlow.fRplot' frame. ## ## 1b) Pack frames with appropriate '-side' '-anchor' '-fill' '-expand' ## parameters to get proper behavior of widgets within the frames, ## during window expansion. (Window expansion is allowed.) ## ## 2) Define & pack all widgets in the frames -- basically going through ## frames & their interiors in top-to-bottom, left-to-right order: ## ## - 'fRbuttons' contains buttons -- ## Exit, Help, UpdatePlot, etc. buttons. ## ## - 'fRtitle_main' contains 1 label & 1 entry widget. ## - 'fRtitles_xy' contains 2 pairs of label & entry widgets. ## - 'fRlims_xy' contains 6 pairs of label & entry widgets. ## - 'fRvals_x' contains 1 label & 1 entry widget. ## - 'fRvals_y' contains 1 label & 1 entry widget. ## ## - 'fRlow.fRmsg' contains a message in a label (or text) widget, on ## the left side of the 'fRlow' frame. ## ## - 'fRlow.fRplot' contains a canvas widget, on the right side of ## the 'fRlow' frame --- to be populated with ## 'items' whenever the 'update_plot' proc is ## executed, such as when the 'UpdatePlot' button ## of frame 'fRbuttons' is poked). ## ## 3) Define bindings: (See BINDINGS code section.) ## ## To Drag plot-title and axis-titles (and tic-mark labels). ## Basically: ## - .fRame.canvas bind TAGmoveable "itemSelect .fRame.canvas %x %y" ## - bind .fRame.canvas "itemMove .fRame.canvas %x %y" ## - .fRame.canvas bind TAGmoveable ".fRame.canvas dtag TAGselected" ## ## To Change color of titles (and tic-mark labels) during move. ## Basically: ## .fRame.canvas bind TAGtext ".fRame.canvas itemconfig current -fill " ## .fRame.canvas bind TAGtext ".fRame.canvas itemconfig current -fill " ## ## 4) Define procs: (See PROCS code section.) ## ## - 'update_plot' - Called by 'UpdatePlot' button --- and by ## 'downsize_canvas' and 'upsize_canvas' procs --- and ## in the 'Additional GUI Initialization' section at the ## bottom of this script. ## (Re)Sets contents of canvas widget!! ## ## - 'set_margins' - Called by proc 'update_plot'. ## Sets margins around the 'plot rectangle' on the canvas. ## ## - 'itemSelect' - Called by a binding on the canvas. ## Selects a canvas item. ## - 'itemMove' - Called by a binding on the canvas. ## Moves a canvas item. ## ## - 'getSet_canvasColor' - Called by 'CanvasColor' button. ## ## - 'downsize_canvas' - Called by the 'DwnCan' button. ## - 'upsize_canvas' - Called by the 'UpCan' button. ## - 'resize_win' - Called by procs 'downsize_canvas' & 'upsize_canvas'. ## ## - 'draw_border' - Called by proc 'update_plot' of the ## 'PlotBorder' checkbutton is ON. ## ## - 'getPut_image' - Called by 'GetImage' button. ## ## - 'print_preview' - Called by the 'PrtPreview' button. ## - 'print_plot' - Called by the 'Print' button. ## ## - 'popup_msgVarWithScroll' - Called by the 'Help' button --- and may be used ## to pop up a msg whenever needed. ## ## 5) Additional GUI initialization: ## Set various directory and helper-app and plot parameter variables. ## Set some sample data for the entry fields. ## Issue 'update_plot' to present an intitial demo plot on the canvas. ## ##+####################################################################### ## 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 2013jul19 Started development, on Ubuntu 9.10, ## based on the code ## 'plot_quik_xy_bars.tk' ## in the 'feHandyTools' subsystem of ## the 'Freedom Environment' subsystems ## at www.freedomenv.com --- adapted for ## donation of this code to the Tcl-Tk ## wiki at wiki.tcl.tk. Suspended. ## Updated by: Blaise Montandon 2017oct04 Restarted development for the FE ## 'tkGooies' system. ## Updated by: Blaise Montandon 2017????? Released this script at freedomenv.com. ##+######################################################################## ##+####################################################################### ## SET WINDOW TITLES. ##+####################################################################### wm title . "PlotQuik - Bar Chart - from X,Y data entered below" wm iconname . "PlotBars" # 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_WIN_LOC_GEOM)" } ##+####################################################################### ## SET COLOR SCHEME (palette) for the window and its widgets. ##+####################################################################### if {1} { ## Grayish palette set Rpal255 210 set Gpal255 210 set Bpal255 210 } if {0} { ## Bluish palette set Rpal255 180 set Gpal255 180 set Bpal255 255 } if {0} { ## Greenish palette set Rpal255 180 set Gpal255 255 set Bpal255 180 } if {0} { ## Reddish palette set Rpal255 255 set Gpal255 180 set Bpal255 180 } ## If env vars R255,G255,B255 were set, then we could use the following ## format statement to get a hex value for specifying tkGUI colors, ## after 'catch'-ing the three values into Rpal255,Gpal255,Bpal255 Tcl vars. # catch { set Rpal255 "$env(R255)" } # catch { set Gpal255 "$env(G255)" } # catch { set Bpal255 "$env(B255)" } set hexCOLORpal [format "#%02X%02X%02X" $Rpal255 $Gpal255 $Bpal255] ## Or could set palette from a hex-valued env var. # catch { set hexCOLORpal "$env(FE_PLOT_WINCOLOR)" } tk_setPalette "$hexCOLORpal" ##+####################################################### ## Set background colors for GUI widgets. ## ## Some other colors, such as outline-color for the bars ## and 'foreground-text' color are set in the ## 'getSet_canvasColor' proc. ## These are color for 'items' on the canvas. ##+####################################################### set msgBKGD "#ffcccc" set entryBKGD "#f0f0f0" # set textBKGD "#f0f0f0" set textBKGD $msgBKGD set chkbuttBKGD "#c0c0c0" ## Following widgets are not used, yet. # set listboxBKGD "#f0f0f0" # # set radbuttBKGD "#c0c0c0" # set radbuttBKGD $msgBKGD # set radbuttSELECTCOLOR "#cccccc" # set scaleBKGD "#f0f0f0" ##+####################################################################### ## SET FONT VARS to use in the 'font create' statements below. ## ## We use a VARIABLE-WIDTH FONT for label and button widgets. ## ## We use a FIXED-WIDTH FONT for entry fields and ## text widgets and listboxes, if any. ##------------------------------------------------------------------------ ## Some possible (similar) VARIABLE WIDTH fonts: ## Arial ## Bitstream Vera Sans ## Comic Sans MS ## DejaVu Sans ## Droid Sans ## FreeSans ## Liberation Sans ## Nimbus Sans L ## Trebuchet MS ## Verdana ## ## 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 ## Liberation Mono ## Nimbus Mono L ## TlwgMono ##+####################################################################### set FONTsize 14 set FONT_SMALLsize 12 set fontFamily "comic sans ms" set FONTparms_varwidth " -family {$fontFamily} \ -size -$FONTsize -weight bold -slant roman" set FONTparms_SMALL_varwidth " -family {$fontFamily} \ -size -$FONT_SMALLsize -weight normal -slant roman " # set fontFamily "dejavu sans mono" # set fontFamily "freemono" set fontFamily "liberation mono" set FONTparms_fixedwidth " -family {$fontFamily} \ -size -$FONTsize -weight bold -slant roman " set FONTparms_SMALL_fixedwidth " -family {$fontFamily} \ -size -$FONT_SMALLsize -weight normal -slant roman " ##+##################################################################### ## DEFINE (temporary) FONT VARS to be used in '-font' widget specs below ## --- and for some plot titles on the canvas. ##+##################################################################### eval font create fontTEMP_varwidth $FONTparms_varwidth eval font create fontTEMP_fixedwidth $FONTparms_fixedwidth eval font create fontTEMP_SMALL_varwidth $FONTparms_SMALL_varwidth eval font create fontTEMP_SMALL_fixedwidth $FONTparms_SMALL_fixedwidth eval font create fontTEMP_button $FONTparms_varwidth eval font create fontTEMP_chkbutt $FONTparms_varwidth eval font create fontTEMP_label $FONTparms_varwidth eval font create fontTEMP_entry $FONTparms_fixedwidth eval font create fontTEMP_msg $FONTparms_fixedwidth eval font create fontTEMP_text $FONTparms_fixedwidth # eval font create fontTEMP_listbox $FONTparms_fixedwidth eval font create fontTEMP_SMALL_button $FONTparms_SMALL_varwidth eval font create fontTEMP_SMALL_chkbutt $FONTparms_SMALL_varwidth eval font create fontTEMP_SMALL_label $FONTparms_SMALL_varwidth eval font create fontTEMP_SMALL_entry $FONTparms_SMALL_fixedwidth eval font create fontTEMP_SMALL_msg $FONTparms_SMALL_fixedwidth eval font create fontTEMP_SMALL_text $FONTparms_SMALL_fixedwidth # eval font create fontTEMP_SMALL_listbox $FONTparms_SMALL_fixedwidth ## For the text in the plot canvas: (NOT USED, yet) # eval font create fontTEMP_plottitle $FONTparms_varwidth # eval font create fontTEMP_axistitle $FONTparms_varwidth # eval font create fontTEMP_ticlabel $FONTparms_SMALL_varwidth ## We were going to allow entry fields on the GUI for a 'legend' ## and for a 'source' line, that could be moved on the canvas. ## ## Rather than complicating the GUI and using more space on it, ## we let the user add such info with the 'wheeeDiagram' or ## 'TitleBlock' 'tkGooies'. # eval font create fontTEMP_legend $FONTparms_SMALL_varwidth # eval font create fontTEMP_source $FONTparms_SMALL_varwidth ##+####################################################################### ## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS. ## (e.g. padx, pady for Buttons) ## ## Possible values for '-relief' are: ## flat, groove, raised, ridge, solid, and sunken. ##+####################################################################### ## For BUTTON widgets: set PADXpx_button 0 set PADYpx_button 0 set BDwidthPx_button 2 set RELIEF_button raised ## For LABEL widgets: set PADXpx_label 0 set PADYpx_label 0 set BDwidthPx_label 2 set RELIEF_label flat ## For ENTRY widgets: set BDwidthPx_entry 2 set RELIEF_entry sunken ## CHECKBUTTON geom parameters: set PADXpx_chkbutt 0 set PADYpx_chkbutt 0 set BDwidthPx_chkbutt 2 # set RELIEF_chkbutt raised set RELIEF_chkbutt ridge ## For TEXT widgets: set BDwidthPx_text 2 # set RELIEF_text raised set RELIEF_text ridge ## For CANVAS widgets: # set BDwidthPx_canvas 2 # set RELIEF_canvas raised set BDwidthPx_canvas 0 set RELIEF_canvas flat set initCanWidthPx 200 set initCanHeightPx 200 set minCanHeightPx 24 ## For LISTBOX widgets: (not used, yet) # set BDwidthPx_listbox 2 ##+############################################################## ## Set a TEXT-ARRAY to hold text for buttons, labels, and other ## widgets 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(buttonCANCOLOR) "CanvasColor" set aRtext(buttonBARCOLOR) "BarColor" set aRtext(buttonUPDATE) "UpdatePlot" set aRtext(buttonIMAGE) "GetImage" set aRtext(buttonDWNCAN) "DwnCan" set aRtext(buttonUPCAN) "UpCan" set aRtext(buttonPRTPREVIEW) "PrtPreview" set aRtext(buttonPRINT) "Print" set aRtext(labelPRTCMD) "Print command:" ## For '.fRopts' frame: set aRtext(chkbuttOUTLINES) "BarOutlines" set aRtext(chkbuttBORDER) "PlotBorder" set aRtext(labelBARWIDTH) " BarWidth(%) :" set aRtext(buttMINUSMINUS) "--" set aRtext(buttMINUS) "-" set aRtext(buttPLUS) "+" set aRtext(buttPLUSPLUS) "++" set aRtext(labLEGEND) "Legend" ## NOT USED, yet: # set aRtext(chkbuttSOURCE) "SourceNote" ## For '.fRtitle_main' frame: set aRtext(labelPLOTTITLE) "PlotTitle:" ## For '.fRtitles_xy' frame: set aRtext(labelXAXISTITLE) "XaxisTitle:" set aRtext(labelYAXISTITLE) "YaxisTitle:" ## For '.fRlims_xy' frame: set aRtext(labelXAXISMIN) "XaxisMin:" set aRtext(labelXAXISMAX) "XaxisMax:" set aRtext(labelXTICDIST) "XticDist:" set aRtext(labelYAXISMIN) "YaxisMin:" set aRtext(labelYAXISMAX) "YaxisMax:" set aRtext(labelYTICDIST) "YticDist:" ## For '.fRvals_x' frame: set aRtext(labelXVALS) "XdataVals:" ## For '.fRvals_y' frame: set aRtext(labelYVALS) "YdataVals:" ## For '.fRlow.fRmsg' frame: set aRtext(labelHELPMSG) \ "To the right is a 'canvas' to contain a 2-dimensional bar-chart plot, with various plot options. Recommended order of actions: 1. Increase the canvas AND plot size with the 'UpCan' button. Downsize with 'DwnCan'. Use the 'CanvasColor' button to change background color. 2. After making changes in any of the several entry fields, use the 'UpdatePlot' button. 3. You can drag any of the titles or tic-mark labels with mouse-button-1. When you use the 'UpdatePlot' button, labels and title are returned to their initial locations (handy to restore labels if pulled off-canvas). You can drag labels back where wanted. 4. You can use screen-grab, image- editor, and image-view-print utilities to make an image file or to print the plot." ## END OF if { "$VARlocale" == "en"} ##+################################################################### ## Set a MINSIZE of the window (roughly). ## ## For WIDTH, allow for the minwidth of the '.fRbuttons' frame: ## about 9 widgets --- Exit, Help, UpdatePlot, etc. buttons. ## ## For HEIGHT, allow ## about 1 char high for the '.fRbuttons' frame and entry frames ## below that frame, ## about 24 pixels high for the '.fRlow' frame. ##+################################################################### set minWinWidthPx [font measure fontTEMP_varwidth \ "$aRtext(buttonEXIT) $aRtext(buttonHELP) \ $aRtext(buttonCANCOLOR) $aRtext(buttonBARCOLOR) \ $aRtext(chkbuttOUTLINES) $aRtext(chkbuttBORDER) \ $aRtext(buttonUPDATE) \ $aRtext(buttonIMAGE) \ $aRtext(buttonDWNCAN) $aRtext(buttonUPCAN) \ $aRtext(buttonPRINT) $aRtext(buttonPRTPREVIEW)"] ## Add some pixels to account for right-left-side window decoration ## (about 8 pixels), about 10 x 4 pixels/widget for borders/padding for ## about 10 button widgets. set minWinWidthPx [expr {48 + $minWinWidthPx}] ## MIN HEIGHT --- ## for the 8 stacked frames allow ## 1 char high for 'fRbuttons' ## 1 char high for 'fRopts' ## 1 char high for 'fRtitle_main' ## 1 char high for 'fRtitles_xy' ## 1 char high for 'fRlims_xy' ## 1 char high for 'fRvals_x' ## 1 char high for 'fRvals_y' ## 24 pixels high for 'fRlow.fRplot'. set CharHeightPx [font metrics fontTEMP_varwidth -linespace] set minWinHeightPx [expr {7 * $CharHeightPx}] set minWinHeightPx [expr {$minWinHeightPx + 24}] ## Add about 28 pixels for top-bottom window decoration, ## about 8x4 pixels for each of the 8 stacked frames and their ## widgets (their borders/padding). set minWinHeightPx [expr {$minWinHeightPx + 60}] ## FOR TESTING: # puts "minWinWidthPx = $minWinWidthPx" # puts "minWinHeightPx = $minWinHeightPx" wm minsize . $minWinWidthPx $minWinHeightPx ## We allow the window to be resizable and we pack the canvas with ## '-fill both -expand 1' so that the canvas 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 ##+#################################################################### ##+#################################################################### ## DEFINE *ALL* THE FRAMES -- (top to bottom): ## ## - 'fRbuttons' contains buttons -- ## Exit, Help, UpdatePlot, etc. buttons. ## - 'fRopts' contains various checkbutton and button widgets. ## - 'fRtitle_main' contains 1 label & 1 entry widget. ## - 'fRtitles_xy' contains 2 pairs of label & entry widgets. ## - 'fRlims_xy' contains 6 pairs of label & entry widgets. ## - 'fRvals_x' contains 1 label & 1 entry widget. ## - 'fRvals_y' contains 1 label & 1 entry widget. ## ## Then the sub-frames: ## - '.fRlow.fRmsg' contains a mini-guide in a label (or text) widget. ## ## - '.fRlow.fRplot' contains a canvas widget. ## ##+#################################################################### ## FOR TESTING change 0 to 1: ## (Example1: To see appearance of frames when 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 RELIEF_frame raised set BDwidthPx_frame 2 } else { set RELIEF_frame flat set BDwidthPx_frame 0 } frame .fRbuttons -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRopts -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRtitle_main -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRtitles_xy -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRlims_xy -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRvals_x -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRvals_y -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRlow -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRlow.fRmsg -relief raised -borderwidth 2 frame .fRlow.fRplot -relief raised -borderwidth 2 ##+######################################################## ## PACK *ALL* the FRAMES. ##+######################################################## ## PACK THE FRAMES IN SEPARATELY, in order to ## experiment with different behaviors in window expansion. ##+######################################################## pack .fRbuttons \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRopts \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRtitle_main \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRtitles_xy \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRlims_xy \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRvals_x \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRvals_y \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRlow \ -side top \ -anchor center \ -fill both \ -expand 1 ## Pack the sub-frames. pack .fRlow.fRmsg \ -side left \ -anchor nw \ -fill y \ -expand 0 pack .fRlow.fRplot \ -side right \ -anchor ne \ -fill both \ -expand 1 ##+################################################################ ## Finished defining all the frames. ##+################################################################ ## START DEFINING & PACKING WIDGETS WITHIN THEIR FRAMES. ##+################################################################ ##+################################################################ ##+######################################################## ## IN THE 'fRbuttons' frame -- ## DEFINE about 8 BUTTON and 2 CHECKBUTTON widgets ## --- and 1 pair of LABEL and ENTRY widgets. ## THEN PACK EM. ##+######################################################## button .fRbuttons.buttExit \ -text "$aRtext(buttonEXIT)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {exit} button .fRbuttons.buttHelp \ -text "$aRtext(buttonHELP)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {popup_msgVarWithScroll .topHelp "$HELPtext" +10+30} button .fRbuttons.buttCanvasColor \ -text "$aRtext(buttonCANCOLOR)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {getSet_canvasColor} button .fRbuttons.buttBarColor \ -text "$aRtext(buttonBARCOLOR)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {get_barColor} button .fRbuttons.buttUpdate \ -text "$aRtext(buttonUPDATE)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {update_plot} button .fRbuttons.buttImage \ -text "$aRtext(buttonIMAGE)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {getPut_image} button .fRbuttons.buttDWNwin \ -text "$aRtext(buttonDWNCAN)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {downsize_canvas} button .fRbuttons.buttUPwin \ -text "$aRtext(buttonUPCAN)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {upsize_canvas} button .fRbuttons.buttPrtPreview \ -text "$aRtext(buttonPRTPREVIEW)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {print_preview} button .fRbuttons.buttPrint \ -text "$aRtext(buttonPRINT)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {print_plot} label .fRbuttons.labPRTCMD \ -text "$aRtext(labelPRTCMD)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. Example: # set ENTRYprintcmd "$PRINTcmd" entry .fRbuttons.entPRTCMD \ -textvariable ENTRYprintcmd \ -width 25 \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry ## Pack the widgets in frame '.fRbuttons'. ## (We might want to change the order someday.) pack .fRbuttons.buttExit \ .fRbuttons.buttHelp \ .fRbuttons.buttCanvasColor \ .fRbuttons.buttBarColor \ .fRbuttons.buttUpdate \ .fRbuttons.buttImage \ .fRbuttons.buttDWNwin \ .fRbuttons.buttUPwin \ .fRbuttons.buttPrtPreview \ .fRbuttons.buttPrint \ .fRbuttons.labPRTCMD \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRbuttons.entPRTCMD \ -side left \ -anchor w \ -fill x \ -expand 1 ##+######################################################## ## IN THE '.fRopts' frame -- ## DEFINE 2 CHECKBUTTON widgets and ## some BUTTON widgets and an ENTRY or LABEL widget. ## THEN PACK THEM. ##+######################################################## ## The checkbutton variable, barOutines0or1, will be initialized ## in the 'Additional GUI Initialization' section at the bottom of ## this Tk script. Example: ## set barOutines0or1 0 checkbutton .fRopts.chkbuttOutlines \ -variable barOutlines0or1 \ -selectcolor "$chkbuttBKGD" \ -text "$aRtext(chkbuttOUTLINES)" \ -font fontTEMP_SMALL_chkbutt \ -padx $PADXpx_chkbutt \ -pady $PADYpx_chkbutt \ -relief $RELIEF_chkbutt ## The checkbutton variable, plotBorder0or1, will be initialized ## in the 'Additional GUI Initialization' section at the bottom of ## this Tk script. Example: ## set plotBorder0or1 0 checkbutton .fRopts.chkbuttBorder \ -variable plotBorder0or1 \ -selectcolor "$chkbuttBKGD" \ -text "$aRtext(chkbuttBORDER)" \ -font fontTEMP_SMALL_chkbutt \ -padx $PADXpx_chkbutt \ -pady $PADYpx_chkbutt \ -relief $RELIEF_chkbutt label .fRopts.labBARWIDTH \ -text "$aRtext(labelBARWIDTH)" \ -font fontTEMP_SMALL_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label button .fRopts.buttMINUSMINUS \ -text "$aRtext(buttMINUSMINUS)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {increment_barwidth_var -10} button .fRopts.buttMINUS \ -text "$aRtext(buttMINUS)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {increment_barwidth_var -1} ## We could initialize this in the 'Additional GUI Initialization' ## section at the bottom of this script. set ENTRYbarwidthPercent 50 entry .fRopts.entBARwidthPERCENT \ -textvariable ENTRYbarwidthPercent \ -width 3 \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry \ -state disabled button .fRopts.buttPLUS \ -text "$aRtext(buttPLUS)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {increment_barwidth_var +1} button .fRopts.buttPLUSPLUS \ -text "$aRtext(buttPLUSPLUS)" \ -font fontTEMP_button \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief $RELIEF_button \ -command {increment_barwidth_var +10} ## THE 'LEGEND' ENTRY FIELD IS NOT IMPLEMENTED, yet. if {0} { label .fRopts.labLegend \ -text "$aRtext(labelLEGEND)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. # set ENTRYlegend {"1 - Blah Blah Blah" "2 - Blech Blech Blech" "3 - Barf Barf Barf"} entry .fRopts.entLegend \ -textvariable ENTRYlegend \ -width 60 \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry } ## END OF LEGEND label and entry widget definitions. ## PACK the widgets in frame 'fRopts'. pack .fRopts.chkbuttOutlines \ .fRopts.chkbuttBorder \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRopts.labBARWIDTH \ .fRopts.buttMINUSMINUS \ .fRopts.buttMINUS \ .fRopts.entBARwidthPERCENT \ .fRopts.buttPLUS \ .fRopts.buttPLUSPLUS \ -side left \ -anchor w \ -fill none \ -expand 0 ## NOT IMPLEMENTED, yet. if {0} { pack .fRopts.labLegend \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRopts.entLegend \ -side left \ -anchor w \ -fill x \ -expand 1 } ##+######################################################## ## IN THE 'fRtitle_main' frame -- ## DEFINE 1 LABEL & 1 ENTRY WIDGET. THEN PACK EM. ##+######################################################## label .fRtitle_main.labPlotTitle \ -text "$aRtext(labelPLOTTITLE)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. # set ENTRYtitleMain " MAIN PLOT TITLE here." entry .fRtitle_main.entPlotTitle \ -textvariable ENTRYtitleMain \ -width 75 \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry ## Pack the widgets in frame '.fRtitle_main'. pack .fRtitle_main.labPlotTitle \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRtitle_main.entPlotTitle \ -side left \ -anchor w \ -fill x \ -expand 1 ##+############################################################ ## IN THE 'fRtitles_xy' frame -- ## DEFINE 2 pairs of LABEL & ENTRY widgets for x-axis & y-axis. ## THEN PACK the 4 widgets. ##+############################################################ label .fRtitles_xy.labXaxisTitle \ -text "$aRtext(labelXAXISTITLE)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. # set ENTRYtitleXaxis " X-AXIS TITLE here." entry .fRtitles_xy.entXaxisTitle \ -textvariable ENTRYtitleXaxis \ -width 40 \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry ##+######################################################## ## Now, for the y-axis: ##+######################################################## label .fRtitles_xy.labYaxisTitle \ -text "$aRtext(labelYAXISTITLE)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. # set ENTRYtitleYaxis " Y-AXIS TITLE here. " entry .fRtitles_xy.entYaxisTitle \ -textvariable ENTRYtitleYaxis \ -width 40 \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry ## PACK x-and-y axis-title widgets in frame '.fRtitles_xy'. pack .fRtitles_xy.labXaxisTitle \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRtitles_xy.entXaxisTitle \ -side left \ -anchor w \ -fill x \ -expand 1 pack .fRtitles_xy.labYaxisTitle \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRtitles_xy.entYaxisTitle \ -side left \ -anchor w \ -fill x \ -expand 1 ##+########################################################### ## IN THE 'fRlims_xy' frame -- ## DEFINE 6 pairs of LABEL & ENTRY widgets for --- ## x-axis min & max &tic-dist and ## y-axis min & max & tic-dist. ## AND PACK the 12 widgets. ##+########################################################### set entWIDTHchars 8 label .fRlims_xy.labXaxisMIN \ -text "$aRtext(labelXAXISMIN)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. Examples: # set ENTRYxaxismin "0" # set ENTRYxaxismin "0.0" ; ## Causes tic-labels to go to 1-decimal format. entry .fRlims_xy.entXaxisMIN \ -textvariable ENTRYxaxismin \ -width $entWIDTHchars \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry label .fRlims_xy.labXaxisMAX \ -text "$aRtext(labelXAXISMAX)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. Examples: # set ENTRYxaxismax "100" # set ENTRYxaxismax "100.0" ; ## Causes tic-labels to go to 1-decimal format. entry .fRlims_xy.entXaxisMAX \ -textvariable ENTRYxaxismax \ -width $entWIDTHchars \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry label .fRlims_xy.labXticDIST \ -text "$aRtext(labelXTICDIST)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. Examples: # set ENTRYxticdist "10.0" entry .fRlims_xy.entXticDIST \ -textvariable ENTRYxticdist \ -width $entWIDTHchars \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry ## Now define the Y-AXIS min-max-ticdist widgets: label .fRlims_xy.labYaxisMIN \ -text "$aRtext(labelYAXISMIN)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. Examples: # set ENTRYyaxismin "0" # set ENTRYyaxismin "0.0" ; ## Causes tic-labels to go to 1-decimal format. entry .fRlims_xy.entYaxisMIN \ -textvariable ENTRYyaxismin \ -width $entWIDTHchars \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry label .fRlims_xy.labYaxisMAX \ -text "$aRtext(labelYAXISMAX)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. Examples: # set ENTRYyaxismax "100" # set ENTRYyaxismax "100.0" ; ## Causes tic-labels to go to 1-decimal format. entry .fRlims_xy.entYaxisMAX \ -textvariable ENTRYyaxismax \ -width $entWIDTHchars \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry label .fRlims_xy.labYticDIST \ -text "$aRtext(labelYTICDIST)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. Examples: # set ENTRYyticdist "10.0" entry .fRlims_xy.entYticDIST \ -textvariable ENTRYyticdist \ -width $entWIDTHchars \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry ## PACK the XaxisMIN, XaxisMAX, XticDIST widgets ## and the YaxisMIN, YaxisMAX, YticDIST widgets in frame '.fRlims_xy': pack .fRlims_xy.labXaxisMIN \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRlims_xy.entXaxisMIN \ -side left \ -anchor w \ -fill x \ -expand 1 pack .fRlims_xy.labXaxisMAX \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRlims_xy.entXaxisMAX \ -side left \ -anchor w \ -fill x \ -expand 1 pack .fRlims_xy.labXticDIST \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRlims_xy.entXticDIST \ -side left \ -anchor w \ -fill x \ -expand 1 pack .fRlims_xy.labYaxisMIN \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRlims_xy.entYaxisMIN \ -side left \ -anchor w \ -fill x \ -expand 1 pack .fRlims_xy.labYaxisMAX \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRlims_xy.entYaxisMAX \ -side left \ -anchor w \ -fill x \ -expand 1 pack .fRlims_xy.labYticDIST \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRlims_xy.entYticDIST \ -side left \ -anchor w \ -fill x \ -expand 1 ##+######################################################## ## IN THE 'fRvals_x' frame -- ## DEFINE 1 LABEL & 1 ENTRY WIDGETs. THEN PACK THEM. ##+######################################################## label .fRvals_x.labXvals \ -text "$aRtext(labelXVALS)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. # set ENTRYxvals "10.0 30.0 50.0 70.0 90.0" entry .fRvals_x.entXvals \ -textvariable ENTRYxvals \ -width 80 \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry ## PACK the widgets in frame '.fRvals_x'. pack .fRvals_x.labXvals \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRvals_x.entXvals \ -side left \ -anchor w \ -fill x \ -expand 1 ##+######################################################## ## IN THE 'fRvals_y' frame -- ## DEFINE 1 LABEL & 1 ENTRY WIDGETs. THEN PACK THEM. ##+######################################################## label .fRvals_y.labYvals \ -text "$aRtext(labelYVALS)" \ -font fontTEMP_label \ -anchor w \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## We initialize this var at the bottom of this script, ## in the GUI inititalization section. # set ENTRYyvals "10.0 30.0 50.0 70.0 90.0" entry .fRvals_y.entYvals \ -textvariable ENTRYyvals \ -width 80 \ -font fontTEMP_entry \ -bg $entryBKGD \ -bd $BDwidthPx_entry \ -relief $RELIEF_entry ## PACK the widgets in frame '.fRvals_y'. pack .fRvals_y.labYvals \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRvals_y.entYvals \ -side left \ -anchor w \ -fill x \ -expand 1 ##+######################################################## ## IN THE 'fRlow.fRmsg' frame -- DEFINE 1 LABEL WIDGET. ## THEN PACK IT. ##+######################################################## label .fRlow.fRmsg.labMSG \ -text "$aRtext(labelHELPMSG)" \ -font fontTEMP_SMALL_label \ -anchor nw \ -justify left \ -padx $PADXpx_label \ -pady $PADYpx_label \ -relief $RELIEF_label ## Pack the widget in frame '.fRlow.fRmsg'. pack .fRlow.fRmsg.labMSG \ -side top \ -anchor nw \ -fill none \ -expand 0 ##+######################################################## ## IN THE 'fRlow.fRplot' frame -- DEFINE 1 CANVAS WIDGET. ## THEN PACK IT. ## ## We 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'. ##+######################################################## ## Instead of hard-coding an initial canvas size, like this ## set canWidthPx 500 ## set canHeightPx 375 ## we set the canvas size in proportion to the screen size. set SCRNsizexPx [winfo screenwidth .] set SCRNsizeyPx [winfo screenheight .] set INITcanWidthPx [ expr {int(6 * $SCRNsizexPx / 10)} ] set INITcanHeightPx [ expr {int(6 * $SCRNsizeyPx / 10)} ] ## FOR TESTING: # puts "INITcanWidth: $INITcanWidthPx" # puts "INITcanHeight: $INITcanHeightPx" canvas .fRlow.fRplot.can \ -width $INITcanWidthPx \ -height $INITcanHeightPx \ -highlightthickness 0 \ -borderwidth 0 \ -relief $RELIEF_canvas ## Pack the widget in frame '.fRlow.fRplot'. ## Allow it to expand to fill window. Anchor at 'nw'. pack .fRlow.fRplot.can \ -side top \ -anchor nw \ -fill both \ -expand 1 ##+################################################################## ## Finished defining widgets in all the frames. ##+####################################################################### ##+####################################################################### ## END OF MAIN GUI BUILDING SECTION. ##+####################################################################### ##+####################################################################### ##+####################################################################### ##+####################################################################### ## DEFINE BINDINGS -- for mouse actions: ## - to Drag titles (and tic-mark labels and images). ## - to Change color of titles and labels during their move. ## ## NOTE1: ## In the following, instead of using 'TAGtitles' and 'TAGticmarks' and ## 'TAGimages', we use 'TAGmoveable' for any movable item, and we tag ## the moveable items with tag 'TAGmoveable' instead of (or in addition to) ## 'TAGtitles' and 'TAGticmarks' and 'TAGimages'. ## ## But 'TAGtitles' and 'TAGticmarks' and 'TAGimages' may prove useful for ## other operations on titles or ticmarks or images. ## ## NOTE2: ## The 'itemSelect' proc puts the tag 'TAGselected' on the item selected. ## The tag 'TAGselected' is used in the 'itemMove' proc to determine the ## item to be moved. ## ## NOTE#: ## We use tag 'TAGtext' on titles and tic-mark labels, to support a color ## change while they are being moved. ##+####################################################################### ##+####################################################################### ##+############################################### ## To Drag titles (and tic-mark labels and images): ##+############################################### ## The tag 'TAGmoveable' limits the select-and-move ## operations to items that we want to make moveable ## on the canvas. ##+################################################# .fRlow.fRplot.can bind TAGmoveable {itemSelect .fRlow.fRplot.can %x %y} bind .fRlow.fRplot.can {itemMove .fRlow.fRplot.can %x %y} .fRlow.fRplot.can bind TAGmoveable {.fRlow.fRplot.can dtag TAGselected} ##+################################################ ## To Change color of text items during their move: ##+################################################ .fRlow.fRplot.can bind TAGtext \ {.fRlow.fRplot.can itemconfig current -fill "#$textCOLORselHEX"} .fRlow.fRplot.can bind TAGtext \ {.fRlow.fRplot.can itemconfig current -fill "#$textCOLORregHEX"} ##+##################################################################### ## End of bindings. ##+##################################################################### ##+##################################################################### ## DEFINE PROCEDURES: ## ## - 'update_plot' - Called by the 'UpdatePlot' button --- and by the ## 'downsize_canvas' and 'upsize_canvas' procs --- ## and in the 'Additional GUI Initialization' section ## at the bottom of this script. ## ## Performs the plot including titles, x and y axes, ## tic-marks, tic-mark labels, and the bars. ## ## - 'set_margins' - Called by the 'update_plot' proc. ## Sets margins around 'central plot rectangle'. ## ## - 'get_deciPlaces' - Called by the 'update_plot' proc. ## ## - 'format_deciPlaces' - Called by the 'update_plot' proc. ## ## - 'itemSelect' - Called by a ButtonPress-1 binding on the canvas. ## Selects a canvas item to move. ## ## - 'itemMove' - Called by a Button1-Motion binding on the canvas. ## Moves a selected canvas item. ## ## - 'draw_border' - Called by the 'update_plot' proc --- ## if the 'Border' checkbutton is ON. ## Puts a border around the plot. ## ## - 'getSet_canvasColor' - Called by the 'CanvasColor' button. ## Gets-and-sets bkgd color for canvas, via a ## separate RGB color-selector Tk script. ## ## - 'update_cancolor_button' - Called by proc 'getSet_canvasColor' and in the ## Additional GUI Initialization' section at the ## bottom of this script. ## Sets the background color of the 'CanvasColor' ## button to the same color as the current ## background color of the canvas. ## ## - 'set_plotColors' - Called by proc 'getSet_canvasColor' and at bottom ## of script to initialize canvas color and related ## contrasting colors --- like text item colors and ## outline color for the bars. ## ## - 'blackORwhite_farthestFromHexRGBcolor' - Called by proc 'set_plotColors'. ## Sets a contrasting color for ## text item colors and outline color for the bars. ## ## - 'invert_hexRGBcolor' - Called by proc 'set_plotColors'. ## (Alternative to 'blackORwhite_farthestFromHexRGBcolor'.) ## ## - 'augment_hexRGBcolor' - Called by proc 'set_plotColors'. ## Sets a color for text items when they are moved. ## ## Other, utility procs: ## ## - 'downsize_canvas' - Called by the 'DwnCan' button. ## Reduces the GUI (and canvas) size by a fixed percentage. ## ## - 'upsize_canvas' - Called by the 'UpCan' button. ## Increases the GUI (and canvas) size by a fixed percentage. ## ## - 'resize_win' - Called by the 'downsize_canvas' and 'upsize_canvas' procs. ## Increase/decrease GUI window size by a factor. ## ## - 'getPut_image' - Called by the 'GetImg' button. ## Gets and puts an image on the canvas. ## ## - 'print_preview' - Called by the 'PrtPreview' button. ## Puts plot image in Postscript file and shows it to user. ## ## - 'print_plot' - Called by the 'PrtPlot' button. ## Puts plot image in Postscript file and sends to a printer. ## ## - 'popup_shortmsg' - Called by various procs --- 'update_plot' and maybe more. ## ## - 'popup_msgVarWithScroll' - Called by the 'Help' button. ## Used to popup msgs, such as help, to user. ## ##+##################################################################### ##+##################################################################### ##+##################################################################### ## PROC 'update_plot' (for barchart plot) ##+##################################################################### ## PURPOSE: ## This procedure is invoked to (re)create the canvas items using the ## current GUI entries and the current canvas size. ## Uses 'create rect' to make the bars of the plot. ## Uses 'create line' to create axes and tic-marks. ## Uses 'create text' for titles (main,x-axis,y-axis) and tic-mark labels. ## ## Arguments: none ## ## CALLED BY: button .fRbuttons.buttUpdate ##+##################################################################### proc update_plot {} { ## Titles from 'entry' widgets follow. global ENTRYtitleMain ENTRYtitleYaxis ENTRYtitleXaxis ## Plot limits and data values from 'entry' widgets follow. global ENTRYxaxismax ENTRYxaxismin ENTRYxticdist global ENTRYyaxismax ENTRYyaxismin ENTRYyticdist global ENTRYxvals ENTRYyvals ## Margins set by 'set_margins' proc follow. global MARGNleftPx MARGNrightPx MARGNtopPx MARGNbotPx ## CharHeightPx is set where win minsize is set, at top of script. global CharHeightPx ## 'Regular' colors for text (titles and tic-mark labels) and ## lines (axes and tic-marks) and bar outlines follow. ## ## The text and line colors are set in proc 'set_plotColors' based ## on the choice of canvas color. ## ## We may temporarily change color while a text item is being moved ## to textCOLORselHEX. See BINDINGS section. global textCOLORregHEX lineCOLORhex ## Line width global variable --- for data-point connector lines, ## axes, and tic-marks. global lineWIDTHpx ## Checkbutton variables follow. global barOutlines0or1 plotBorder0or1 ## We may need to share the current canvas dimensions with other ## procs --- such as 'draw_border'. global CURcanWidthPx CURcanHeightPx ## Bar color and bar width percent --- set in 'get_barColor' and ## 'increment_barwidth_var' procs. global BARrgbHEX ENTRYbarwidthPercent ## Checkbutton variables to turn on/off display of a legend ## and source-of-data. NOT USED, yet. # global legend0or1 source0or1 ## Some pixel parameters that may need to be shared with proc 'draw_???'. # global XaxisMINpx PX2UNITSx YaxisBOTpx PX2UNITSy ######################################################################### ## CHECK FOR EQUAL NUMBER OF ENTRYxvals & ENTRYyvals. ######################################################################### set NXvals [ llength $ENTRYxvals ] set NYvals [ llength $ENTRYyvals ] if { $NXvals != $NYvals } { set ERRmessage "Number-of-Xvals NOT = Number-of-Yvals." set ERRtitle "Input Err" popup_shortmsg "$ERRtitle" "$ERRmessage" return } ########################################################## ## Make sure we are using the current canvas dimensions to ## place items on the plot canvas. ########################################################## set CURcanWidthPx [winfo width .fRlow.fRplot.can] set CURcanHeightPx [winfo height .fRlow.fRplot.can] ########################################################## ## Set some margin vars to be used to set endpoints of ## x and y axes, etc. --- in pixel units. ## (NOTE: The contents of the 'set_margins' proc may ## need to take into account, i.e. use, various ## axis-location-related 'if' statements ## in this 'update_plot' code --- further below.) ########################################################## set_margins ##################################################################### ## CLEAR THE CANVAS WIDGET in preparation for redraw. ##################################################################### ## Rather drastic: # .fRlow.fRplot.can delete all ## To avoid deletion of images/logo: .fRlow.fRplot.can delete TAGrects .fRlow.fRplot.can delete TAGlines .fRlow.fRplot.can delete TAGtext .fRlow.fRplot.can delete TAGborder ## where TAGrects is the tag for the bars (filled-rectangles), ## TAGlines is the tag for the axes and tic-marks, ## TAGtext is the tag for the main title, axis-labels, and ## ticmark labels. ## TAGtext is the tag for the drawn border, if any. ########################################################### ## PUT MAIN TITLE NEAR TOP OF THE PLOT-CANVAS, ## anchored to the left side of the plot area. ## NOTE: ## The user can put leading spaces in the plot-title entry ## field to adjust the title to the right. ## In addition, the user can drag the title. ########################################################### # set xPX 10 set xPX $MARGNleftPx ## Below we are placing the text with '-anchor nw'. ## ## We set the northwest corner of the plot-title text ## just a few pixels below the top of the canvas ## and at the left side of the 'plot rectangle' set ## in the 'set_margins' proc. set yPX 4 .fRlow.fRplot.can create text \ $xPX $yPX \ -anchor nw \ -text "$ENTRYtitleMain" \ -font fontTEMP_label \ -fill "#$textCOLORregHEX" \ -tag {TAGmoveable TAGtext TAGtitles} # -justify center \ ########################################################### ## SET XaxisMINpx,XaxisMAXpx,YaxisTOPpx,YaxisBOTpx ## (in canvas pixels) for global use for end-points of axes. ########################################################### ## YaxisTOPpx & YaxisBOTpx refer to locations at the top and ## bottom of the canvas area. ## XaxisMINpx & XaxisMAXpx refer to locations on the left and ## right of the canvas area. ########################################################### set XaxisMINpx $MARGNleftPx set XaxisMAXpx [expr { $CURcanWidthPx - $MARGNrightPx } ] set YaxisTOPpx $MARGNtopPx set YaxisBOTpx [expr { $CURcanHeightPx - $MARGNbotPx }] ########################################################### ## We put the Y-axis title near the top of the plot, ## anchored to the left side of the plot area. ## NOTE: The user can use leading-spaces in the yaxis-title ## entry field to adjust the title to the right. ########################################################### # set xPX [expr { $MARGNleftPx + 4 } ] set xPX $MARGNleftPx ## Note that we are placing the text with '-anchor nw' below. ## ## We set the northwest corner of the yaxis-title text ## at the top of the left side of the 'plot rectangle' ## set in the 'set_margins' proc. # set yPX [expr { $MARGNtopPx - 3 }] set yPX $MARGNtopPx .fRlow.fRplot.can create text \ $xPX $yPX \ -anchor nw \ -justify left \ -text "$ENTRYtitleYaxis" \ -font fontTEMP_label \ -fill "#$textCOLORregHEX" \ -tags {TAGmoveable TAGtext TAGtitles} ########################################################### ## We put the X-axis title near the bottom of the plot, ## anchored to the left side of the plot area. ## NOTE: The user can use leading-spaces in the xaxis-title ## entry field to adjust the title to the right. ########################################################### # set xPX [expr { $MARGNleftPx + 4 } ] set xPX $MARGNleftPx ## Note that we are placing the text with '-anchor sw' below. ## ## We set the southwest corner of the xaxis-title text ## just a few pixels above the bottom of the canvas ## and at the left side of the 'plot rectangle' set ## in the 'set_margins' proc. # set yPX $YaxisBOTpx set yPX [expr { $CURcanHeightPx - 5 }] .fRlow.fRplot.can create text \ $xPX $yPX \ -anchor sw \ -justify left \ -text "$ENTRYtitleXaxis" \ -font fontTEMP_label \ -fill "#$textCOLORregHEX" \ -tags {TAGmoveable TAGtext TAGtitles} ##################################################### ## SETUP FACTORS THAT WILL BE USED TO ## CONVERT DATA VALS TO PIXEL COORDS. ## Units: Pixels per 'world coordinate' units. ## Data type: floating point (not integer) ##################################################### set PX2UNITSx [expr { double( $XaxisMAXpx - $XaxisMINpx ) / ( $ENTRYxaxismax - $ENTRYxaxismin ) } ] set PX2UNITSy [expr { double( $YaxisBOTpx - $YaxisTOPpx ) / ( $ENTRYyaxismax - $ENTRYyaxismin ) } ] ## FOR TESTING: # puts "PX2UNITSx: $PX2UNITSx" # puts "PX2UNITSy: $PX2UNITSy" ########################################################### ## SET X-AXIS VERTICAL LOCATION (IN PIXELS) --- in XAXISyPX. ## If ENTRYyaxismax & ENTRYyaxismin (in 'world coordinates') straddle 0, ## set X-axis vert-loc according to the location of y=0 IN PIXELS ## --- else use YaxisBOTpx. ## ## NOTE: These kinds of checks will probably need to be ## put in the 'set_margins' proc. ########################################################### set XAXISyPX $YaxisBOTpx if { $ENTRYyaxismax > 0 && $ENTRYyaxismin < 0 } { set XAXISyPX [ expr { $YaxisBOTpx + int( $PX2UNITSy * $ENTRYyaxismin) } ] } ############################################################## ## SET Y-axis horizontal location (in pixels) --- in YAXISxPX. ## If ENTRYyaxismax & ENTRYyaxismin straddle 0, ## set Y-axis horiz-loc according to location of x=0 IN PIXELS ## --- else use XaxisMINpx. ## ## NOTE: These kinds of checks will probably need to be ## put in the 'set_margins' proc. ############################################################## set YAXISxPX $XaxisMINpx if { $ENTRYxaxismax > 0 && $ENTRYxaxismin < 0 } { set YAXISxPX [ expr { $XaxisMINpx - int($PX2UNITSx * $ENTRYxaxismin) } ] } ########################################################### ## DRAW X-AXIS ON THE (BAR-CHART) PLOT-CANVAS. ########################################################### set x0PX $XaxisMINpx set y0PX $XAXISyPX set x1PX $XaxisMAXpx set y1PX $XAXISyPX .fRlow.fRplot.can create line \ $x0PX $y0PX \ $x1PX $y1PX \ -fill black \ -width $lineWIDTHpx -capstyle round \ -fill "#$lineCOLORhex" -tag TAGlines ########################################################### ## DRAW enough X-AXIS TIC-MARKS to fit between X min & max ## --- and label them. ## ## These hard-coded x-axis tic-mark offsets may need to be ## set as a small percentage of the canvas height. ########################################################### # set ticOFFSETpx 15 set ticOFFSETpx 5 set xTicTopPx [expr { $y0PX - $ticOFFSETpx } ] set xTicBotPx [expr { $y0PX + $ticOFFSETpx } ] set Nxtics [expr { int ( ($ENTRYxaxismax - $ENTRYxaxismin) / $ENTRYxticdist) } ] set xTicIncrWrld $ENTRYxticdist set xTicIncrPx [expr { $PX2UNITSx * $xTicIncrWrld } ] set xDeciPlaces [get_deciPlaces "$xTicIncrWrld"] for {set i 0} {$i <= $Nxtics} {incr i} { set xPX [expr {$x0PX + ($i * $xTicIncrPx)}] .fRlow.fRplot.can create line \ $xPX $y0PX \ $xPX $xTicTopPx \ -width $lineWIDTHpx -capstyle round \ -fill "#$lineCOLORhex" -tag TAGlines set ticText [ format_deciPlaces [expr {$ENTRYxaxismin + ($xTicIncrWrld * $i)}] $xDeciPlaces ] .fRlow.fRplot.can create text \ $xPX $xTicBotPx \ -text $ticText \ -anchor n \ -font fontTEMP_SMALL_label \ -fill "#$textCOLORregHEX" \ -tags {TAGmoveable TAGtext TAGtitles} } ## END OF LOOP for {set i 0} {$i <= $Nxtics} {incr i} ############################################################ ## DRAW Y-AXIS ON THE (BAR-CHART) PLOT CANVAS, ## in the 'plot rectangle'. ############################################################ set x0PX $YAXISxPX set y0PX $YaxisBOTpx set x1PX $YAXISxPX set y1PX $YaxisTOPpx .fRlow.fRplot.can create line \ $x0PX $y0PX \ $x1PX $y1PX \ -fill black \ -width $lineWIDTHpx -capstyle round \ -fill "#$lineCOLORhex" -tag TAGlines ########################################################### ## DRAW enough Y-AXIS TIC-MARKS to fit between Y min & max ## --- and label them. ## ## These hard-coded y-axis tic-mark offsets may need to be ## set as a small percentage of the canvas width. ########################################################### # set ticOFFSETpx 15 set ticOFFSETpx 5 set yTicLeftPx [expr { $x0PX - $ticOFFSETpx } ] set yTicRightPx [expr { $x0PX + $ticOFFSETpx } ] set Nytics [expr { int ( ($ENTRYyaxismax - $ENTRYyaxismin) / $ENTRYyticdist) } ] set yTicIncrWrld $ENTRYyticdist set yTicIncrPx [expr { $PX2UNITSy * $yTicIncrWrld } ] set yDeciPlaces [get_deciPlaces "$yTicIncrWrld"] for {set i 0} {$i <= $Nytics} {incr i} { set yPX [expr {$y0PX - ($i*$yTicIncrPx)}] .fRlow.fRplot.can create line \ $x0PX $yPX \ $yTicRightPx $yPX \ -width $lineWIDTHpx -capstyle round \ -fill "#$lineCOLORhex" -tag TAGlines set ticText [ format_deciPlaces [expr {$ENTRYyaxismin + ($yTicIncrWrld * $i)}] $yDeciPlaces ] .fRlow.fRplot.can create text \ $yTicLeftPx $yPX \ -text $ticText \ -anchor e \ -justify right \ -font fontTEMP_SMALL_label \ -fill "#$textCOLORregHEX" \ -tags {TAGmoveable TAGtext TAGtitles} } ## END OF LOOP for {set i 0} {$i <= $Nytics} {incr i} ##################################################### ## PLOT DATA POINTS as bars (rectangles), ## with an data value at the top of each bar. ## (The user can drag these off-canvas if not wanted.) ##################################################### ##################################################### ## SET WIDTH OF BARS according to the variable ## ## (Could be set by user, via spinbox widget, say.) ##################################################### set HALFWIDTHpx_bars [expr {$PX2UNITSx * ($ENTRYbarwidthPercent/100.0) * ($ENTRYxticdist / 2.0)}] ## FOR TESTING: # puts "HALFWIDTHpx_bars: $HALFWIDTHpx_bars" ######################################################## ## LOOP THRU X,Y DATA LISTS, CREATING BARS. ######################################################## for {set i 0} {$i < $NXvals} {incr i} { ## FOR TESTING: # puts "ENTRYxaxismin: $ENTRYxaxismin" # puts "ENTRYxvals(i): [lindex $ENTRYxvals $i]" # puts "i: $i" ## We used var 'xTicIncrPx' set above in making x-tic-marks. # set xPX [expr {$XaxisMINpx + (($i + 1) * $xTicIncrPx)}] ## But we need to make the bars at x-data values. ## So we could try something like: set xPX [expr {$XaxisMINpx + int( $PX2UNITSx * ( [lindex $ENTRYxvals $i] - $ENTRYxaxismin ) ) } ] ## yPX calculated relative to the x-axis (y=0). # set yPX [expr {$XAXISyPX - ( $PX2UNITSy * [lindex $ENTRYyvals $i] ) } ] ## yPx calculated relative to the bottom of the 'plot rectangle'. set yPX [expr {$YaxisBOTpx - int( $PX2UNITSy * ( [lindex $ENTRYyvals $i] - $ENTRYyaxismin ) ) } ] ## FINALLY, we draw the bars. if {$barOutlines0or1 == 1} { set tempOutline "-outline #$lineCOLORhex -width $lineWIDTHpx" } else { set tempOutline "-width 0" } eval .fRlow.fRplot.can create rect \ [expr {$xPX - $HALFWIDTHpx_bars}] $XAXISyPX \ [expr {$xPX + $HALFWIDTHpx_bars}] $yPX \ $tempOutline \ -fill "#$BARrgbHEX" -tag TAGrects ############################################################ ## CREATE TEXT LABEL (Y value) for the current bar, ## above the top of the bar. ############################################################ set text_y [expr {$yPX + 2}] ## To put text in middle of bar. Does not work well for short bars. # set text_y [expr {$XAXISyPX - ( $PX2UNITSy * ([lindex $ENTRYyvals $i] / 2.0) ) } ] .fRlow.fRplot.can create text \ $xPX $text_y \ -anchor s \ -text "[lindex $ENTRYyvals $i]"\ -font fontTEMP_SMALL_label \ -fill "#$textCOLORregHEX" \ -tag {TAGmoveable TAGtext} } ## END OF LOOP for {set i 0} {$i < $NXvals} {incr i} TO CREATE BARS ## If the 'PlotBorder' checkbutton is ON, draw a plot border. if {$plotBorder0or1 == 1} {draw_border} ## Put a legend on the canvas from ENTRYlegend 'list' info. ## NOT USED, yet. # if {$legend0or1 == 1} {put_legend} ## Put data-source info on the canvas from ENTRYsource string info. ## NOT USED, yet. # if {$source0or1 == 1} {put_source} } ## END of proc 'update_plot' ##+##################################################################### ## PROC 'set_margins' ##+##################################################################### ## PURPOSE: ## Sets 4 'MARGN' variables that can be used to consistently set the ## limits of the 'plot rectangle' within the canvas widget. ## ## The 'plot rectangle' is the area on the canvas to which we want ## to confine the plotting of the data points. ## ## (Often the X-axis will be drawn at the bottom of the 'plot rectangle' ## and the Y-axis will be drawn at the left of the 'plot rectangle' ## --- BUT NOT ALWAYS.) ## ## The 4 'MARGN' values, in pixels, are meant to be: ## ## MARGNtopPx distance between TOP side of canvas and ## TOP side of 'plot rectangle' ## MARGNleftPx distance between LEFT side of canvas and ## LEFT side of 'plot rectangle' ## MARGNrightPx distance between RIGHT side of canvas and ## RIGHT side of 'plot rectangle' ## MARGNbotPx distance between BOTTOM side of canvas and ## BOTTOM side of 'plot rectangle' ## ## (Whenever the canvas is resized, these 'MARGN' values can be ## used to resize the 'central' plot rectangle.) ## #################################### ## SPECIFICS OF THE 'plot rectangle': (top,left,right,bottom) ## ## The 'plot rectangle' is always meant to allow some margin at ## the TOP of the canvas for a plot title --- without data points ## going into the plot title. ## ## The 'plot rectangle' is typically meant to allow some margin ## at the LEFT of the canvas, for some tic-mark labels on the ## left of a vertical Y-axis --- especially when that Y-axis is ## drawn at the left of the 'plot rectangle'. ## ## The 'plot rectangle' is typically meant to allow some margin ## at the RIGHT of the canvas, for some tic-mark labels on the ## right of a vertical Y-axis --- especially when the ## Y-axis is drawn at the right of the 'plot rectangle' ## (for example at x=0 when that is the right end of the x-axis). ## ## The 'plot rectangle' is typically meant to allow some margin ## at the BOTTOM of the canvas, for some tic-mark labels on the ## bottom side of a horizontal X-axis --- especially when the ## X is drawn at the bottom of the 'plot rectangle'. ## ######################################### ## MORE SPECIFICS OF THE 'plot rectangle': (dimensions) ## ## The 'plot rectangle', horizontally, starts at one end ## of the x-axis and goes to the other end of the x-axis ## --- in other words, the horizontal dimension of the ## 'plot rectangle' is supposed to be exactly equal to ## the length of the x-axis. ## ## The 'plot rectangle', vertically, starts at one end ## of the y-axis and goes to the other end of the y-axis ## --- in other words, the vertical dimension of the ## 'plot rectangle' is supposed to be exactly equal to ## the length of the y-axis. ## ## In short, the 'plot rectangle' is the smallest rectangle ## containing the drawing of the x and y axes. ## ############################################# ## USING FONT SIZES IN SETTING 'MARGN' VALUES: ## ## The plot-titles, axis-titles, and tic-mark labels generally ## lie outside the 'plot rectangle', so these 4 'MARGN' values ## should take those items into account (allow room for them). ## (Since the plot-titles, axis-titles, and tic-mark labels in ## this app can be moved, we have a little lee-way in setting ## the margins --- but not much.) ## ## Because of the text items in the margins, the choice of fonts ## (set at top of script) can/should be used to set these 4 ## 'MARGN' values (in pixels). ## ## Note that we set these margins in 'absolute' pixel units ## rather than as 'proportionality factors' to be applied ## to the canvas dimensions. ## ## These 4 'margin values' will be used to set variables that ## will be used to define the ending points (in pixel units) ## of the plot axes within the plot canvas, ## say XaxisMINpx,XaxisMAXpx,YaxisTOPpx,YaxisBOTpx (in pixels). ##+######################################################## ## Example use: ## set XaxisMINpx $MARGNleftPx ## set XaxisMAXpx [expr { $CURCURcanWidthPx - $MARGNrightPx } ] ## set YaxisTOPpx $MARGNtopPx ## set YaxisBOTpx [expr { $CURcanHeightPx - $MARGNbotPx }] ##+######################################################## ## CALLED BY: the 'update_plot' proc ##+######################################################## proc set_margins {} { ## The 'MARGN' settings below assume a Y axis at the left ## of the 'plot rectangle' and an X-axis at the bottom. ## ## Eventually we will want to put in logic, like some in ## the 'update_plot' proc, to take into account situations ## like X-axis above the bottom --- even at the top --- ## and Y axis in the middle or on the right. ## The variable 'CharHeightPx' was set where the GUI window ## minsize was set, near the top of this script. Specifically: ## set CharHeightPx [font metrics fontTEMP_varwidth -linespace] ## ## But we did not set a 'CharWidthPx' variable. ## We do that here. global CharHeightPx \ MARGNleftPx MARGNrightPx MARGNtopPx MARGNbotPx set CharWidthPx [font measure fontTEMP_varwidth "W"] ## NOTE: We are setting margins (in pixels) according ## to the font being used for text on the plot --- ## irrespective of the current dimensions of the canvas. ## I.e. we are not using percentages of canvas dimensions. set MARGNleftPx [expr {4 * $CharWidthPx}] set MARGNrightPx [expr {2 * $CharWidthPx}] set MARGNtopPx [expr {2 * $CharHeightPx}] set MARGNbotPx [expr {3 * $CharHeightPx}] } ## END of proc 'set_margins' ##+##################################################################### ## 'get_deciPlaces' PROCEDURE ##+##################################################################### ## PURPOSE: Get the number of decimal places in a number string. ## ## Argument: a number string like 10.0 or 10 or 0.25 ## ## CALLED BY: the 'update_plot' proc ##+##################################################################### proc get_deciPlaces {input} { set deciPlaces [string length [lindex [split "$input" "."] 1]] return "$deciPlaces" } ## END of proc 'get_deciPlaces' ##+##################################################################### ## 'format_deciPlaces' PROCEDURE ##+##################################################################### ## PURPOSE: Format a number string to have a given number of ## decimal places. ## ## Arguments: a number string AND an integer specifying the ## number of decimal places ## ## CALLED BY: the 'update_plot' proc ##+##################################################################### proc format_deciPlaces {input places} { set FORMAT4number "%0.${places}f" set output [format "$FORMAT4number" $input] return "$output" } ## END of proc 'format_deciPlaces' ##+##################################################################### ## PROC 'increment_barwidth_var' ##+##################################################################### ## PURPOSE: ## This procedure increments the ENTRYbarwidthPercent variable ## a specified amount, keeping the value between 1 and 100, inclusive. ## ## Arguments: amt (an integer like -1 or -10 or +1 or +10) ## ## CALLED BY: the '--', '-', '+', '++' BarWidth buttons ##+##################################################################### proc increment_barwidth_var {amt} { global ENTRYbarwidthPercent incr ENTRYbarwidthPercent $amt if {$ENTRYbarwidthPercent > 100} {set ENTRYbarwidthPercent 100} if {$ENTRYbarwidthPercent < 1} {set ENTRYbarwidthPercent 1} } ## END of proc 'increment_barwidth_var' ##+##################################################################### ## PROC 'itemSelect' ##+##################################################################### ## PURPOSE: ## This procedure is invoked when the mouse is pressed over a ## canvas item. It sets up a state to allow the point to be dragged ## by marking the item with the tag 'TAGselected'. ## ## Arguments: ## w - The canvas window. ## x, y - The coordinates of the mouse press. ## ## CALLED BY: a binding on a window 'w', which in this ## application is always the canvas window/widget: ## .fRlow.fRplot.can bind ... ##+##################################################################### set lastXsel 0 set lastYsel 0 proc itemSelect {w x y} { global lastXsel lastYsel ## Delete the tag 'TAGselected' to assure that no items are ## marked with tag 'TAGselected'. $w dtag TAGselected ## Add the tag 'TAGselected' to the currently selected item. $w addtag TAGselected withtag current $w raise current set lastXsel $x set lastYsel $y } ## END of proc 'itemSelect' ##+##################################################################### ## PROC 'itemMove' ##+##################################################################### ## PURPOSE: ## This procedure is invoked during mouse motion events. ## It drags the currently selected, which is marked by ## the tag 'TAGselected'. ## ## Arguments: ## w - The canvas window. ## x, y - The coordinates of the mouse. ## ## CALLED BY: a binding on a window 'w', which in this ## application is always the canvas window/widget: ## .fRlow.fRplot.can bind ... ##+##################################################################### proc itemMove {w x y} { global lastXsel lastYsel $w move TAGselected [expr {$x - $lastXsel}] [expr {$y - $lastYsel}] set lastXsel $x set lastYsel $y } ## END of proc 'itemMove' ##+##################################################################### ## PROC 'draw_border' ##+##################################################################### ## PURPOSE: To draw a border around the edge of the canvas. ## ## METHOD: ## Uses 'create line' to draw 4 straight lines and uses ## 'create arc' to draw 4 rounded corners. ## ## Arguments: none ## ## CALLED BY: button .fRbuttons.buttBorder ##+##################################################################### proc draw_border {} { ## Get current canvas dimensions, set in 'update_plot' proc. global CURcanWidthPx CURcanHeightPx lineCOLORhex lineWIDTHpx ################################################# ## Set border limits. ################################################# set BDxminPx [expr { int(0.01 * $CURcanWidthPx) } ] set BDxmaxPx [expr { int(0.99 * $CURcanWidthPx) } ] set BDytopPx [expr { int(0.01 * $CURcanHeightPx) }] set BDybotPx [expr { int(0.99 * $CURcanHeightPx) }] ################################################# ## Set corner arc radius. ################################################# set minDimPx $CURcanWidthPx if { $minDimPx > $CURcanHeightPx } { set minDim $CURcanHeightPx } set BDradPx [expr { 0.03 * $minDimPx } ] ################################################# ## Draw the four border lines (left,right,top,bot). ################################################# .fRlow.fRplot.can create line \ $BDxminPx [expr { $BDytopPx + $BDradPx } ] \ $BDxminPx [expr { $BDybotPx - $BDradPx } ] \ -width $lineWIDTHpx -fill "#$lineCOLORhex" \ -tags TAGborder .fRlow.fRplot.can create line \ $BDxmaxPx [expr { $BDytopPx + $BDradPx } ] \ $BDxmaxPx [expr { $BDybotPx - $BDradPx } ] \ -width $lineWIDTHpx -fill "#$lineCOLORhex" \ -tags TAGborder .fRlow.fRplot.can create line \ [expr { $BDxminPx + $BDradPx } ] $BDytopPx \ [expr { $BDxmaxPx - $BDradPx } ] $BDytopPx \ -width $lineWIDTHpx -fill "#$lineCOLORhex" \ -tags TAGborder .fRlow.fRplot.can create line \ [expr { $BDxminPx + $BDradPx } ] $BDybotPx \ [expr { $BDxmaxPx - $BDradPx } ] $BDybotPx \ -width $lineWIDTHpx -fill "#$lineCOLORhex" \ -tags TAGborder ################################################# ## Draw the four border arcs (UL,UR,LR,LL). ################################################# .fRlow.fRplot.can create arc \ $BDxminPx $BDytopPx \ [expr { $BDxminPx + 2*$BDradPx } ] [expr { $BDytopPx + 2*$BDradPx } ] \ -start 90 \ -extent 90 \ -style arc -width $lineWIDTHpx -outline "#$lineCOLORhex" \ -tags TAGborder .fRlow.fRplot.can create arc \ $BDxmaxPx $BDytopPx \ [expr { $BDxmaxPx - 2*$BDradPx } ] [expr { $BDytopPx + 2*$BDradPx } ] \ -start 0 \ -extent 90 \ -style arc -width $lineWIDTHpx -outline "#$lineCOLORhex" \ -tags TAGborder .fRlow.fRplot.can create arc \ $BDxmaxPx $BDybotPx \ [expr { $BDxmaxPx - 2*$BDradPx } ] [expr { $BDybotPx - 2*$BDradPx } ] \ -start 270 \ -extent 90 \ -style arc -width $lineWIDTHpx -outline "#$lineCOLORhex" \ -tags TAGborder .fRlow.fRplot.can create arc \ $BDxminPx $BDybotPx \ [expr { $BDxminPx + 2*$BDradPx } ] [expr { $BDybotPx - 2*$BDradPx } ] \ -start 180 \ -extent 90 \ -style arc -width $lineWIDTHpx -outline "#$lineCOLORhex" \ -tags TAGborder } ## END of proc 'draw_border' ##+############################################################################## ## PROC 'put_legend' (NOT USED, yet --- ENTRYlegend field not implemented, yet) ##+############################################################################## ## PURPOSE: Puts a 'legend' (a table indexed by x-axis labels) on the canvas, ## from an ENTRYlegend field on the GUI. ## ## METHOD: ## If a 'legend' was requested, ## PUT THE TEXT AT THE VERY BOTTOM OF CANVAS. ## (Note that the user can drag the lines of the legend elsewhere. ## We put the legend/table in a lower corner of the canvas. ## In some help instructions, we can tell the user to ## drag the legend-lines where they want them.) ## ## CALLED BY: the 'update_plot' proc if a 'legend0or1' ## checkbutton variable is set ON. ####################################################################### proc put_legend {} { global CURcanWidthPx CURcanHeightPx MARGNleftPx MARGNrightPx global ENTRYlegend textCOLORregHEX ############################################################# ## PUT LEGEND AT BOTTOM OF CANVAS --- loop through the ## 'bar names' of the ENTRYlegend variable. ############################################################# set NBARnames [ llength $ENTRYlegend ] if { $NBARnames != $NYvals } { set ERRmessage "Number-of-BarNames-for-Legend NOT EQUAL Number-of-Yvals." set ERRtitle "Input Err" popup_shortmsg "$ERRtitle" "$ERRmessage" return } ## Indent legend-text-items from left of canvas. # set text_x 10 set text_x $MARGNleftPx ## Set top of legend at (NBARnames + 1) chars above bottom of canvas. set CharHeightPx [font metrics fontTEMP_SMALL_label -linespace] set text_y [ expr {$CURcanHeightPx - (($NBARnames + 1) * $CharHeightPx) - 4} ] ############################################################### ## START OF LOOP ON NBARnames, to make legend. ############################################################### for {set i 0} {$i < $NBARnames} {incr i} { ############################################################ ## SET Y-LOCATION OF CURRENT LEGEND TEXT ITEM. ## (Put each item down by the legend font height.) ############################################################ set text_y [ expr {$text_y + $CharHeightPx} ] ## FOR TESTING: # puts "update_plot > Making legend." # puts "i: $i" # puts "text_x: $text_x" # puts "text_y: $text_y" ############################################################ ## CREATE A LEGEND TEXT ITEM. ############################################################ .fRlow.fRplot.can create text \ $text_x $text_y \ -anchor nw \ -fill "$textCOLORregHEX" \ -text "[expr {$i + 1}] - [ lindex $ENTRYlegend $i ]"\ -font fontTEMP_SMALL_label \ -tag {TAGmoveable TAGtext} } ## END OF LOOP "{set i 0} {$i < $Npcnts} {incr i}" TO CREATE LEGEND } ## END OF proc 'put_legend' ##+##################################################################### ## PROC 'put_source' (NOT USED, yet --- no ENTRYsource field, yet) ##+##################################################################### ## PURPOSE: Puts some data-source info on the canvas, ## from an ENTRYsource field on the GUI. ## ## METHOD: ## If a DataSource/Note was requested, ## PUT THE TEXT AT THE VERY BOTTOM OF CANVAS. ## (Note that the user can drag it elsewhere. ## We put the note in a lower corner of the canvas. ## In some help instructions, we can tell the user to ## drag the note where they want it.) ## ## CALLED BY: the 'update_plot' proc if a 'source0or1' ## checkbutton variable is set ON. ####################################################################### proc put_source {} { global CURcanWidthPx CURcanHeightPx MARGNrightPx ENTRYsource textCOLORregHEX ## Indent the 'source' note from right of canvas: set text_x [ expr {$CURcanWidthPx - 2} ] # set text_x [ expr {$CURcanWidthPx - $MARGNrightPx}] ## Set bottom of note near the bottom of canvas. set text_y [ expr {$CURcanHeightPx - 2} ] ############################################################ ## PLACE the DataSource/Note TEXT on the canvas. ## 'se' = lower right ; 'sw' = lower left ############################################################ .fRlow.fRplot.can create text \ $text_x $text_y \ -anchor se \ -fill "#$textCOLORregHEX" \ -text "$ENTRYsource"\ -font fontTEMP_source \ -tag {TAGmoveable TAGtext} } ## END OF proc 'put_source' ##+##################################################################### ## PROC 'getSet_canvasColor' ##+##################################################################### ## PURPOSE: Gets an RGB hex-color value (via a GUI with 3 RGB slider bars). ## The user uses the RGB color-selector GUI to select a color. ## ## Then sets the canvas 'bg' (background) to that color. ## ## Calls proc 'set_plotColors' to set some variables to hold ## colors that are in contrast with the canvas background color. ## ## NOTE: We always expect hex-color variables to hold the color in a ## form like 'ffffff' rather than '#ffffff'. We will supply the ## '#' wherever we use the hex-color variable. ## ## Arguments: none ## ## CALLED BY: the 'CanvasColor' button ##+##################################################################### proc getSet_canvasColor {} { global CANr255 CANg255 CANb255 CANrgbHEX RGBcolorSelectorScript ## FOR TESTING: # puts "CANr255: $CANr255" # puts "CANg255: $CANg255" # puts "CANb255: $CANb255" set TEMPrgb [ exec $RGBcolorSelectorScript $CANr255 $CANg255 $CANb255] ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } ## Script 'sho_colorvals_via_sliders3rgb.tk' puts out 4 strings ## of the form 'r255 g255 b255 hexRGB' where the ## first 3 are integers (0-255) and the last is a 6-char hex RGB code. scan $TEMPrgb "%s %s %s %s" CANr255 CANg255 CANb255 CANrgbHEX ## FOR TESTING: # puts "PROC 'getSet_canvasColor' :" # puts "TEMPrgb: $TEMPrgb" # puts "CANr255: $CANr255" # puts "CANg255: $CANg255" # puts "CANb255: $CANb255" ## Set the canvas background color and 'related' plot colors. set_plotColors "$CANrgbHEX" ## Update the plot to apply the new colors. # update update_plot ## Update the background and foreground colors on the ## background-color button. update_cancolor_button } ## END OF proc 'getSet_canvasColor' ##+##################################################################### ## proc 'update_cancolor_button' ##+##################################################################### ## PURPOSE: ## This procedure is invoked to update the color (and, optionally, the ## text) on the canvas background-color button --- ## to show current canvas color (and, optionally, hex value of the color) ## as the background-color on the canvas-color button. ## ## This proc sets the background color of the 'CanvasColor' button to the ## canvas background color as set in the 'getSet_canvasColor' proc ## --- and sets foreground color to a suitable black or white color, ## so that the label text is readable. ## ## Arguments: global color vars ## ## CALLED BY: proc 'getSet_canvasColor' ## and the additional-GUI-initialization section at ## the bottom of this script. ##+##################################################################### proc update_cancolor_button {} { global aRtext CANr255 CANg255 CANb255 CANrgbHEX ## Set background color on the 'CanvasColor' button and ## set the foreground color of the button. .fRbuttons.buttCanvasColor configure -bg "#$CANrgbHEX" set sumCOLOR [expr {$CANr255 + $CANg255 + $CANb255}] if {$sumCOLOR > 300} { .fRbuttons.buttCanvasColor configure -fg "#000000" } else { .fRbuttons.buttCanvasColor configure -fg "#f0f0f0" } ## We could also put the background color in the text on the button ## --- if we did not mind a 2-char high button. # .fRbuttons.buttCanvasColor configure -text "$aRtext(buttonCANCOLOR) # $CANrgbHEX" } ## END OF proc 'update_cancolor_button' ##+##################################################################### ## PROC 'get_barColor' ##+##################################################################### ## PURPOSE: Gets an RGB hex-color value (via a GUI with 3 RGB slider bars). ## The user uses the RGB color-selector GUI to select a color. ## ## Then sets a bar-color variable to the selected color. ## The next time proc 'update_plot' is executed, the bars ## are drawn in this color. ## ## NOTE: We always expect hex-color variables to hold the color in a ## form like 'ffffff' rather than '#ffffff'. We will supply the ## '#' wherever we use the hex-color variable. ## ## Arguments: none ## ## CALLED BY: the 'BarColor' button ##+##################################################################### proc get_barColor {} { global BARr255 BARg255 BARb255 BARrgbHEX RGBcolorSelectorScript ## FOR TESTING: # puts "BARr255: $BARr255" # puts "BARg255: $BARg255" # puts "BARb255: $BARb255" set TEMPrgb [ exec $RGBcolorSelectorScript $BARr255 $BARg255 $BARb255] ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } ## Script 'sho_colorvals_via_sliders3rgb.tk' puts out 4 strings ## of the form 'r255 g255 b255 hexRGB' where the ## first 3 are integers (0-255) and the last is a 6-char hex RGB code. scan $TEMPrgb "%s %s %s %s" BARr255 BARg255 BARb255 BARrgbHEX ## FOR TESTING: # puts "PROC 'get_barColor' :" # puts "TEMPrgb: $TEMPrgb" # puts "BARr255: $BARr255" # puts "BARg255: $BARg255" # puts "BARb255: $BARb255" # puts "BARrgbHEX: $BARrgbHEX" ## Update the background and foreground colors on the ## bar-color button. update_barcolor_button } ## END OF proc 'get_barColor' ##+##################################################################### ## proc 'update_barcolor_button' ##+##################################################################### ## PURPOSE: ## This procedure is invoked to update the color (and optionally ## the text) on the bar-color button --- ## to show currently chosen bar color (and, optionally, the hex value ## of the color) as the background-color on the bar-color button. ## ## This proc sets the background color of the 'BarColor' button to the ## current bar color as set in the 'get_barColor' proc ## --- and sets foreground color to a suitable black or white color, ## so that the label text is readable. ## ## Arguments: global color vars ## ## CALLED BY: proc 'get_barColor' ## and the additional-GUI-initialization section at ## the bottom of this script. ##+##################################################################### proc update_barcolor_button {} { global aRtext BARr255 BARg255 BARb255 BARrgbHEX ## Set background color on the 'BarColor' button and ## set the foreground color of the button. .fRbuttons.buttBarColor configure -bg "#$BARrgbHEX" set sumCOLOR [expr {$BARr255 + $BARg255 + $BARb255}] if {$sumCOLOR > 300} { .fRbuttons.buttBarColor configure -fg "#000000" } else { .fRbuttons.buttBarColor configure -fg "#f0f0f0" } ## We could also put the background color in the text on the button ## --- if we did not mind a 2-char high button. # .fRbuttons.buttBarColor configure -text "$aRtext(buttonBARCOLOR) # $BARrgbHEX" } ## END OF proc 'update_barcolor_button' ##+##################################################################### ## PROC 'set_plotColors' ##+##################################################################### ## PURPOSE: ## For a given hex RGB color, set the canvas background color ## and set 'related' (global) color variables: ## lineCOLORhex ## textCOLORregHEX ## textCOLORselHEX ## 'reg' = regular ; 'sel' = selected ## ## Argument: a hex RGB color string, like 'ff9933' ## ## CALLED BY: proc 'getSet_canvasColor' and at bottom of this script, in ## the 'Additional GUI Initialization' section, to ## initialize canvas color and related colors. ##+##################################################################### proc set_plotColors {hexRGBcolor} { global lineCOLORhex textCOLORregHEX textCOLORselHEX pointCOLORregHEX ############################################ ## Apply the color to the canvas background. ############################################ .fRlow.fRplot.can configure -bg "#$hexRGBcolor" ##+########################################### ## SET COLORS FOR CANVAS LINE and TEXT ITEMS. ## 'reg' = regular ; 'sel' = selected ## ## For line and text colors, we can use a choice ## of procs --- such as ## 'invert_hexRGBcolor' or ## 'blackORwhite_farthestFromHexRGBcolor' ## ## For the 'sel' text color, we want a color ## distinct from the 'reg' color. We use an ## 'augment_hexRGBcolor' proc. ##+########################################### # set lineCOLORhex [invert_hexRGBcolor "$hexRGBcolor"] set lineCOLORhex [blackORwhite_farthestFromHexRGBcolor "$hexRGBcolor"] # set textCOLORregHEX [invert_hexRGBcolor "$hexRGBcolor"] set textCOLORregHEX [blackORwhite_farthestFromHexRGBcolor "$hexRGBcolor"] set textCOLORselHEX [augment_hexRGBcolor "$textCOLORregHEX"] ######################################################### ## Set color for points (interior of ovals/circles). ## ## In the 'update_plot' proc, the outline of the circles ## is drawn with $lineCOLORhex. For some contrast, we ## used a differentiated color, such as $textCOLORselHEX ## --- the 'selected' text color --- or the canvas color, ## which should be quite different from the line color. ######################################################### ## A medium gray. # set pointCOLORregHEX "888888" # set pointCOLORregHEX "$textCOLORselHEX" set pointCOLORregHEX "$hexRGBcolor" ## FOR TESTING: if {0} { puts "PROC 'set_plotColors' :" puts "Canvas color: $hexRGBcolor" puts "Line color: $lineCOLORhex" puts "Text-regular color: $textCOLORregHEX" puts "Text-selected color: $textCOLORselHEX" puts "Point (circle) color: $pointCOLORregHEX" } } ## END OF proc 'set_plotColors' ##+##################################################################### ## PROC 'blackORwhite_farthestFromHexRGBcolor' ##+##################################################################### ## PURPOSE: For a given hex RGB color, returns either black or white ## --- as the hex RGB string '000000' or 'ffffff'. ## ## Argument:a hex RGB color string, like 'ff9933' ## ## CALLED BY: proc 'set_plotColors' ##+##################################################################### proc blackORwhite_farthestFromHexRGBcolor {hexRGBin} { scan $hexRGBin "%2x%2x%2x" r255 g255 b255 set tempRGBtot [expr {$r255 + $g255 + $b255}] set tempTOTlim 360 # set tempTOTlim 200 if {$tempRGBtot > $tempTOTlim} { set hexRGBout "000000" } else { set hexRGBout "ffffff" } return "$hexRGBout" } ## END OF proc 'blackORwhite_farthestFromHexRGBcolor' ##+##################################################################### ## PROC 'invert_hexRGBcolor' ##+##################################################################### ## PURPOSE: For a given hex RGB color, invert it. ## Returns the inverted color as a hex RGB string. ## ## Argument:a hex RGB color string, like 'ff9933' ## ## CALLED BY: proc 'set_plotColors' ##+##################################################################### proc invert_hexRGBcolor {hexRGBin} { ## FOR TESTING: # puts "PROC 'invert_hexRGBcolor' :" # puts "hexRGBin: $hexRGBin" scan $hexRGBin "%2x%2x%2x" r255 g255 b255 set R255 [expr {255 - $r255}] set G255 [expr {255 - $g255}] set B255 [expr {255 - $b255}] set hexRGBout [format "%02x%02x%02x" $R255 $G255 $B255] return $hexRGBout } ## END OF proc 'invert_hexRGBcolor' ##+##################################################################### ## PROC 'augment_hexRGBcolor' ##+##################################################################### ## PURPOSE: For a given hex RGB color, make a color fairly distinct ## from it --- without exceeding the 0-255 limit for the ## RGB channels. ## Returns the 'augmented' color as a hex RGB string. ## ## Argument:a hex RGB color string, like 'ff9933' ## ## CALLED BY: proc 'set_plotColors' ##+##################################################################### proc augment_hexRGBcolor {hexRGBin} { scan $hexRGBin "%2x%2x%2x" r255 g255 b255 ## AUGamt should be less than half of 255, less than 127. # set AUGamt 40 set AUGamt 80 set R255 [expr {$r255 + $AUGamt}] if {$R255 > 255} { set R255 [expr {$r255 - $AUGamt}] } set G255 [expr {$g255 + $AUGamt}] if {$G255 > 255} { set G255 [expr {$g255 - $AUGamt}] } set B255 [expr {$b255 + $AUGamt}] if {$B255 > 255} { set B255 [expr {$b255 - $AUGamt}] } set hexRGBout [format "%02x%02x%02x" $R255 $G255 $B255] return $hexRGBout } ## END OF proc 'augment_hexRGBcolor' ##+##################################################################### ## PROC 'downsize_canvas' ##+##################################################################### ## PURPOSE: To DOWN-size the canvas. ## ## METHOD: ## We apply a factor to the current width and height of the canvas. ## Then we call 'update_plot' to redo the plot. ## ## Actually we resize the entire GUI window and let the Tk 'pack' ## geometry manager take care of resizing the canvas appropriately ## according to the various '-fill' and '-expand' parameters for ## the widgets of the GUI. ## ## NOTE: ## The user can keep clicking the 'DwnCan' button to downsize ~5% per click. ## ## Arguments: none ## ## CALLED BY: the 'DwnCan' button ##+##################################################################### proc downsize_canvas {} { ############################################################## ## Downsize the GUI (top level) window somewhat. ############################################################## resize_win 0.95 ############################################################# ## Re-do the plot, according to the new canvas size --- which ## should be reduced because entire GUI window was reduced. ## ## The 'update' is necessary because 'update_plot' does not ## do 'update' before querying for the current canvas size. ############################################################# update update_plot } ## END OF proc 'downsize_canvas' ##+##################################################################### ## PROC 'upsize_canvas' ##+##################################################################### ## PURPOSE: To UP-size the canvas. ## ## METHOD: ## We apply a factor to the current width and height of the canvas. ## Then we call 'update_plot' to redo the plot. ## ## Actually we resize the entire GUI window and let the Tk 'pack' ## geometry manager take care of resizing the canvas appropriately ## according to the various '-fill' and '-expand' parameters for ## the widgets of the GUI. ## ## NOTE: ## The user can keep clicking the 'UpCan' button to upsize ~5% per click. ## ## Arguments: none ## ## CALLED BY: the 'UpCan' button ##+##################################################################### proc upsize_canvas {} { ################################################################ ## Upsize the GUI (top level) window somewhat. ################################################################ resize_win 1.05 ########################################################### ## Re-do the plot, according to the new canvas size --- ## which should be enlarged because window was enlarged. ## ## The 'update' is necessary because 'update_plot' does not ## do 'update' before querying for the current canvas size. ########################################################### update update_plot } ## END OF proc 'upsize_canvas' ##+##################################################################### ## PROC 'resize_win' ##+##################################################################### ## PURPOSE: To UP/DOWN-size the Tk window by a given factor. ## ## METHOD: Several methods could be used. ## For now, we query the top level (GUI) window width and height ## (and location) with 'wm' (rather than 'winfo') and apply the ## input argument ('factor') to the current window width and height. ## ## Then reset the window size (and location) with 'wm'. ## ## Arguments: one --- 'factor' ## ## CALLED BY: 'upsize_canvas' and 'downsize_canvas' procs ##+##################################################################### proc resize_win {factor} { ## This is not the exact window DIMENSIONS we want. ## These do not include the window decoration. # set winXlenPx [ winfo width . ] # set winYlenPx [ winfo height . ] ## FOR TESTING: # puts "FROM proc 'resize_win':" # puts "winfo-width-winXlenPx : $winXlenPx" # puts "winfo-width-winYlenPx : $winYlenPx" ## This is not the window LOCATION we want. ## It is the upper-left of the window without the window decoration. # set winXlocPx [ winfo rootx . ] # set winYlocPx [ winfo rooty . ] ## FOR TESTING: # puts "FROM proc 'resize_win':" # puts "winfo-rootx-winXlocPx : $winXlocPx" # puts "winfo-rooty-winYlocPx : $winYlocPx" ## NOTE: ## [wm geometry .] returns integers of the form ## ${winXlenPx}x${winYlenPx}+${winXlocPx}+${winYlocPx} set WMgeom [wm geometry .] set winXYlenPx [lindex [split $WMgeom '+'] 0] set winXlenPx [lindex [split $winXYlenPx 'x'] 0] set winYlenPx [lindex [split $winXYlenPx 'x'] 1] set winXlocPx [lindex [split $WMgeom '+'] 1] set winYlocPx [lindex [split $WMgeom '+'] 2] ## FOR TESTING: # puts "FROM proc 'resize_win':" # puts "wm-winXlenPx : $winXlenPx" # puts "wm-winYlenPx : $winYlenPx" # puts "wm-winXlocPx : $winXlocPx" # puts "wm-winYlocPx : $winYlocPx" ## Reduce the window size according to argument 'factor'. set winXlenPx [expr {int(floor ( $factor * $winXlenPx ))} ] set winYlenPx [expr {int(floor ( $factor * $winYlenPx ))} ] ## Adjust the 'locPx' vars for the window manager border. ## EVEN 'wm' does not account for the window decoration!!! ## We will have to adjust, to (try to) keep the upper-left corner ## of the window in place. set winXlocPx [ expr {$winXlocPx - 3} ] set winYlocPx [ expr {$winYlocPx - 23} ] wm geometry . ${winXlenPx}x${winYlenPx}+${winXlocPx}+${winYlocPx} } ## END OF proc 'resize_win' ##+##################################################################### ## PROC 'getPut_image' ##+##################################################################### ## PURPOSE: To put one or more images (e.g. a logo) on the canvas. ## ## METHOD: ## Uses 'tk_getOpenFile' dialog to get an image filename (GIF or PNG). ## Uses Tk 'image create photo' command to create an in-memory image structure. ## Uses canvas 'create image' command to put the image on the canvas. ## ## NOTE: (on a Tk postscript limitation) ## A Tk image on a Tk canvas is not captured by the Tk canvas 'postscript' ## command. But a screen image could be captured --- in a PNG or GIF or JPEG ## file --- with a screen capture utility such as 'gnome-screenshot' --- ## for use in e-mails, web pages, or other docs. ## The screen image, in a PNG file say, could be printed with the Print ## option in a utility such as a web browser. ## ## Arguments: none ## ## CALLED BY: the 'GetImg' button ##+##################################################################### proc getPut_image {} { ## For de-activating this proc: # return ## DIRimages is set in the 'Additional GUI Initialization' section ## at the bottom of this script. global CURcanWidthPx CURcanHeightPx DIRimages set fName "" set fName [tk_getOpenFile -parent . \ -title "Select an image file (GIF or PNG)." \ -initialdir "$DIRimages" ] ## FOR TESTING: # puts "fName : $fName" if {"$fName" == ""} {return} if {[file exists "$fName"]} { ################################################ ## If the filename from the file selector exits, ## 1) create the in-memory image ## 2) put the in-memory image on the canvas ## --- near bottom-right of canvas. ############################################### set imgID [image create photo -file "$fName"] set xPx [expr { int(0.95 * $CURcanWidthPx) } ] set yPx [expr { int(0.95 * $CURcanHeightPx) }] .fRlow.fRplot.can create image \ $xPx $yPx -anchor se -image $imgID \ -tags {TAGmoveable TAGimage} ## Could pop a message here to user letting them know ## that the image is draggable --- and that Tk ## Postscript output from a Tk canvas will not show ## the image --- and they can 'delete' the image ## by dragging it off the canvas. Alternative: ## .fRlow.fRplot.can delete TAGimage } ## END OF if {[file exists "$fName"]} } ## END of proc 'getPut_image' ##+##################################################################### ## PROC 'print_preview' ##+##################################################################### ## PURPOSE: To make and view a Postscript file of the canvas image. ## ## Arguments: none ## ## CALLED BY: the 'PrtPreview' button ##+##################################################################### proc print_preview {} { global env PSviewer DIRtemp #################################################### ## Make a name of the to-be-created postscript file. #################################################### set tmp_filename "${DIRtemp}/$env(USER)_tmp_tkplot.ps" ##################################################### ## Remove a file by the same name from a previous run. ##################################################### ## It looks like we can do it without this 'eval' method. # eval exec rm -f "$tmp_filename" exec rm -f "$tmp_filename" ############################### ## Make the postscript file. ############################### .fRlow.fRplot.can postscript -file "$tmp_filename" \ -colormode color \ -pageheight 10i \ -pagewidth 7i \ -pagex 1i \ -pagey 1i \ -pageanchor sw # -colormode color # -colormode gray # -colormode monochrome ################################################ ## Show the postscript file in a viewer program. ################################################ ## It looks like we can do it without this 'eval' method. # eval exec "$PSviewer \"$tmp_filename\" &" exec $PSviewer "$tmp_filename" & ###################################################### ## We could delete the file. But leave it for the user ## in case they want to do something else with it. ###################################################### # exec rm -f "$tmp_filename" } ## END of proc 'print_preview' ##+##################################################################### ## PROC 'print_plot' ##+##################################################################### ## PURPOSE: To make and send a Postscript file of the canvas image ## to a printer. ## ## Arguments: none ## ## CALLED BY: the 'Print' button ##+##################################################################### proc print_plot {} { global env PRINTcmd DIRtemp #################################################### ## Make a name of the to-be-created postscript file. #################################################### set tmp_filename "${DIRtemp}/$env(USER)_tmp_tkplot.ps" ##################################################### ## Remove a file by the same name from a previous run. ##################################################### eval exec rm -f "$tmp_filename" ################################################### ## Make the postscript file. ################################################### .fRlow.fRplot.can postscript -file "$tmp_filename" \ -colormode color \ -pageheight 10i \ -pagewidth 7i \ -pagex 1i \ -pagey 1i \ -pageanchor sw # -colormode color # -colormode gray # -colormode monochrome ################################################ ## Print the postscript file using a command ## set in the 'ADDITIONAL GUI INITIALIZATION' ## section at the bottom of this script. ################################################ eval exec $PRINTcmd "$tmp_filename" ###################################################### ## We could delete the file. But leave it for the user ## in case they want to do something else with it. ###################################################### # eval exec rm "$tmp_filename" } ## END of proc 'print_plot' ##+######################################################################## ## PROC: 'popup_shortmsg' ##+######################################################################## ## PURPOSE: Popup a short message to user --- usually a one or two ## line error message. ## ## METHOD: We can use 'tk_dialog' or we can use the ## 'popup_msgVarWithScroll' proc below. ## ## CALLED BY: various procs --- 'update_plot' and maybe more. ##+####################################################################### proc popup_shortmsg { title message } { tk_dialog .xxx "$title" "$message" warning 0 Close # popup_msgVarWithScroll .xxx "$message" +40+40 } ## END of proc 'popup_shortmsg' ##+######################################################################## ## 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 can use this 'toplevel-text' method, rather than ## the 'tk_dialog' method -- example 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 ULloc} { ## global fontTEMP_varwidth #; Not needed. 'wish' makes these 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 geometry $toplevName $ULloc 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_SMALL_fixedwidth \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 \ -yscrollcommand "$toplevName.scrolly set" \ -xscrollcommand "$toplevName.scrollx set" ## -font fontTEMP_SMALL_varwidth 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_SMALL_fixedwidth \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 ## -font fontTEMP_SMALL_varwidth } 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 } ################################################ ## Set some 'event' bindings to allow for ## easy scrolling through huge listings. ## is a press of the Page-Down key. ## is a press of the Page-Up key. ## is a press of the Home key ## to go to the top of the listing. ## is a press of the End key ## to go to the bottom of the listing. ## is a press of the Up-arrow key. ## is a press of the Down-arrow key. ################################################ bind $toplevName "$toplevName.text yview scroll +1 page" bind $toplevName "$toplevName.text yview scroll -1 page" bind $toplevName "$toplevName.text see 1.0" bind $toplevName "$toplevName.text see end" bind $toplevName "$toplevName.text yview scroll -1 unit" bind $toplevName "$toplevName.text yview scroll +1 unit" ##################################### ## LOAD MSG INTO TEXT WIDGET. ##################################### ## $toplevName.text delete 1.0 end $toplevName.text insert end $VARtext $toplevName.text configure -state disabled } ## END OF PROC 'popup_msgVarWithScroll' ##+############################################### ## END OF PROCS SECTION. ##+############################################### ## SET HELP TEXT variable. ##+############################################### set HELPtext \ "********* tkPlotQuik - Bar Chart Utility ********* This Tk GUI script provides an intuitive, easy-to-use X-Y-AXIS BAR CHART PLOT UTILITY that can be used to make 'presentation quality' plots very QUICKLY. This Tk script presents a GUI with a canvas widget that shows a 2-D bar chart plot --- with titles and labels that can be dragged with the mouse. This script presents entry fields in the GUI to prompt for - plot title - x,y axis titles - x,y axis min-max limits - x,y axis tic-mark distances. - x,y data from which the bar chart is drawn. *************** OPERATING GUIDE: When the GUI first comes up, it is populated with some sample titles and some sample x,y data --- AND that data is rendered as a bar chart plot in the canvas area. The title names indicate WHERE the 3 types of titles initially appear on the GUI. The user can 'drag' these 3 titles around to different places on the 'canvas' with a mouse. Just click on a title, hold down the button (button-1), and drag to a new position. Then release the button. In fact, you can 'whip' titles out-of-sight --- off an edge of the 'canvas'. If you want the titles back, you can simply click on the 'UpdatePlot' button. AND ... you can 'drag' the tic-mark labels. If you decide there are too many, you can 'whip' them off the canvas. You can also drag the y-data-values shown at the top of the bars. If you do not want these values, you can drag them off the canvas. You are not given the option to drag the bars (or bar height), because you could end up with a plot that is not in 'sync' with the data shown in the 'entry' fields of the GUI. BUT you can move bars by simply changing some x or y data values (or axis limits) and then click on the 'UpdatePlot' button. The GUI could be initialized with different data and titles. At the bottom of the script --- in the 'Additional GUI Initialization' section --- there are some other sample data values that could be activated instead of this set of data. --- There are a good number of plot options. Here are some. *********************** CANVAS BACKGROUND COLOR: You can click on the 'CanvasColor' button and use an RGB color selector GUI that pops up to change the canvas background color. If you are going to capture the plot in an image file (such as PNG or GIF) and then print the image (say by reading the image file into a web browser and using the print capability of the web browser), you will probably want to change the plot background to WHITE --- to save on ink. Rather than make a crowded GUI more crowded by supplying buttons to set colors of text (titles and tic-mark labels) and colors of lines (axes, tic-marks, bar outlines), the text and line colors are set 'automatically' based on the canvas color that is chosen. In particular, if a dark canvas color is chosen, the text and lines will be shown in a light color --- and if a light canvas color is chosen, the text and lines will be shown in a dark color. ******************************** THE 'DwnCan' and 'UpCan' BUTTONS: The 'canvas' area expands and contracts if you expand or contract the entire GUI window --- and click on the 'UpdatePlot' button. A faster way to quickly downsize or upsize the window is to click on the 'DwnCan' or 'UpCan' button. This can be quicker than trying to get the attention of an extremely thin 'sensitive edge' of the GUI to drag the window to a different size. One thing to be aware of: The 'DwnCan' button will probably not work if the user has maximized the GUI window via the window manager 'Maximize' option or by repeated use of the 'UpCan' button. To make the 'DwnCan' button useable again, you can simply use the 'UnMaximize' ('Restore') option of the window manager. ************ BAR OUTLINES: You can click on the 'BarOutlines' checkbutton to turn it ON, and then click on the 'UpdatePlot' button to cause the bars to be redrawn, with outlines. Turn the 'BarOutlines' checkbutton OFF and click 'UpdatePlot' to revert to a bars-without-outlines plot. *********** PLOT BORDER: You can click on the 'PlotBorder' checkbutton to turn it ON, and then click on the 'UpdatePlot' button to cause a border to be drawn around the plot. Turn the 'PlotBorder' checkbutton OFF and click 'UpdatePlot' to revert to a plot without the border. ********** BAR WIDTH: The width of the bars can be changed at the 'BarWidth(%)' prompt of the GUI. The '+' and '-' buttons take the width-percent up and down one percent per click. The '++' and '--' buttons take the width-percent up and down 10 percent per click. After setting the BarWidthPercent, click on 'UpdatePlot' to redraw the bars at the new width. The bar width percent is applied to the x-tic-distance specified. If the x-data-values match the x-tic-marks, then 100 percent means the bars will touch each other. One percent results in bars that look more like lines. ******************* THE 'GetImg' BUTTON: The 'GetImg' button at the top of the GUI allows the user to get an image (like a logo) to put on the plot canvas. A file-selector GUI pops up and allows the user to select an image file (GIF or PNG) to put on the canvas. When a user selects a filename and clicks on the OK button of the file-selector, the file-selector dialog window disappears and the image appears at the lower-right of the 'canvas' area. Like for titles and tick-marks, the user can 'drag' the image from its initial placement on the canvas to anywhere else on the canvas --- and the image can be 'whipped' off of the canvas. More than one image can be fetched and placed on the canvas. ********************************** POSTSCRIPT PREVIEW & PRINT OPTIONS: The 'PrtPreview' and the 'Print' buttons create a Postscript file in a '/tmp' directory. The 'PrtPreview' button uses a PDF/Postscript viewer utility --- such as 'evince' --- to show the Postscript file that is created. And the 'Print' button uses a print-command --- shown in an 'entry' field at the top-right of the GUI --- to send the Postscript code to a user's printer. The temporary-files-directory, the PDF/Postscript viewer-command, and the print-command can be changed by the user who downloads this script by changing 3 variables in 'set' statements at the bottom of the script in the 'Additional GUI Initialization' section: - DIRtemp - PSviewer - PRINTcmd For the print command, I found that the program '/usr/bin/cupsdoprint' of the CUPS printing system worked quite nicely --- on my Ubuntu 9.10 Linux system --- with the set of parameters seen in this code. NOTE: The Tk canvas 'postscript' option does not capture an image placed on the canvas. It captures points, curves, and text placed on the canvas. If you want to capture an image of the plot including any GIF or PNG images put on the canvas, you can use an image capture utility (such as 'gnome-screenshot') to capture the image in a PNG or GIF or JPEG file. You can crop the image with an interactive image editor (such as 'mtpaint') and then print the image file with an image-view/print utility (such as 'eog' = 'eye of gnome') or a web browser, as described above --- in the Canvas Background Color section. NOTE: The Postscript options are not What-You-See-Is-What-You-Get (WYSIWYG). You may find that you get a better quality plot using a screen capture. ***************** THE 'Help' BUTTON: The 'Help' button on the GUI can provide more extensive help than the brief guide on the left side of the GUI. In fact, it presents this help. ********** CONCLUSION: This is a plotting-utility implementation using BASIC Tcl-Tk commands, i.e. not requiring an 'extension' of Tcl or Tk. Unfortunately, there do not seem to be any FAIRLY GENERAL, yet RELATIVELY SIMPLE, bar-chart plotting scripts at Tcl-Tk archive sites --- even in 2017, more than 20 years after the development of the necessary Tk 'canvas' facilities to support plotting of lines and rectangles and text and images. Nor are such GENERAL, INTERACTIVE, easy-to-use bar chart plotting Tk scripts available via web searches on keyword strings such as 'bin wish canvas' or 'bin wish rect' or 'bin wish line'. Even searches on 'canvas' and 'line' and 'rect' on the wiki.tcl.tk site, in early 2013, yielded only simplistic line plot 'demos' that are not suited to general and FAST point-or-line plots. There were none with entry fields for quick entry of user data and essential plot parameters. This script is meant to fill that long-time void. " ##+############################################################## ##+############################################################## ## ADDITIONAL GUI INITIALIZATION: ##+###################################################### ## - Set line-width value (for axes, tic-marks, bar outlines) ## --- which is not currently settable via widgets on the GUI. ## (GUI too 'busy' and too many choices already) ## ## - Set initial canvas background color and from that canvas ## color set line color (for axes, tic-mark labels, bar outlines) ## and set text color (for titles and tic-mark labels). ## NOTE: ## Line and text colors are not currently settable via widgets ## on the GUI. (GUI too 'busy' and too many choices already) ## So we set those colors 'automatically' from the canvas color. ## ## - Set some directories and helper-apps. ## ## - Set some initial 'entry' field values for a plot and ## make a plot from those entries. ##+###################################################### ##+####################################################################### ## Set line width (in pixels) --- for drawing lines such as ## axis lines and tic-mark lines and rectangles on the canvas. ## ## NOTE: ## Instead of hard-coding a value, we could set the width based on ## the screenwidth --- like 0.001 or 0.002 of screenwidth in pixels. ##+####################################################################### # set lineWIDTHpx 2 set SCRNsizexPx [winfo screenwidth .] # set lineWIDTHfactor 0.002 set lineWIDTHfactor 0.001 set lineWIDTHpx [expr {int($lineWIDTHfactor * $SCRNsizexPx) + 1}] ##+#################################################### ## Set an initial BACKGROUND COLOR FOR THE CANVAS --- ## and use that to set some 'related' (global) color variables: ## lineCOLORhex ## textCOLORregHEX ## textCOLORselHEX ## 'reg' = regular ; 'sel' = selected ## ## We set the canvas color a little lighter (brighter) ## than the GUI 'palette' color --- to make it stand out. ##+#################################################### set CANr255 230 set CANg255 230 set CANb255 230 set CANrgbHEX [format "%02X%02X%02X" $CANr255 $CANg255 $CANb255] set_plotColors "$CANrgbHEX" update_cancolor_button ##+#################################################### ## Set an initial BAR COLOR FOR THE CANVAS. ## ## We set the canvas color a little lighter (brighter) ## than the GUI 'palette' color --- to make it stand out. ##+#################################################### set BARr255 230 set BARg255 0 set BARb255 0 set BARrgbHEX [format "%02X%02X%02X" $BARr255 $BARg255 $BARb255] update_barcolor_button ##+#################################################### ## Set the full-name of the RGB color-selector Tk script ## that is used in one or more procs above. ##+#################################################### ## FOR TESTING: # puts "argv0: $argv0" set DIRthisScript "[file dirname $argv0]" ## For ease of testing in a Linux/Unix terminal and located at the ## directory containing this Tk script: Set the full directory name. if {"$DIRthisScript" == "."} { set DIRthisScript "[pwd]" } ## If the color selector script is in the directory with this Tk script: # set RGBcolorSelectorScript "$DIRthisScript/sho_colorvals_via_sliders3rgb.tk" ## Alternatively: If the RGB color-selector Tk script is in the ## SELECTORtools directory of the FE 'tkGooies' menu/toolchest system, ## use something like the following. set DIRupOne "[file dirname "$DIRthisScript"]" set DIRupTwo "[file dirname "$DIRupOne"]" set RGBcolorSelectorScript "$DIRupTwo/SELECTORtools/tkRGBselector/sho_colorvals_via_sliders3rgb.tk" ##+####################################################### ## Set a directory from which to get images. ## (We could put a few images in the directory with this ## Tk script --- or a lot of images in an 'images' ## subdirectory of the directory of this Tk script. ## Or use some subdirectory of the user's home directory.) ##+####################################################### # set DIRimages "$env(HOME)/Photos" # set DIRimages "${DIRthisScript}/images_GIF" # set DIRimages "${DIRthisScript}/images_PNG" set DIRimages "$DIRthisScript" ##+#################################################### ## Set a files directory for the Postscript print ## options --- 'PrtPreview' and 'Print' --- ## for a 'temporary' Postcript file. ##+#################################################### set DIRtemp "/tmp" ##+#################################################### ## Set a Postscript viewer program for use in the ## 'print_preview' proc. ##+#################################################### # set PSviewer "/usr/bin/xpdf" # set PSviewer "evince" set PSviewer "/usr/bin/evince" ##+#################################################### ## Set a print-command for use in the 'print_plot' proc. ## Show the print-command in an 'entry' widget at the ## top of the GUI. ##+#################################################### # set PRINTcmd "/usr/bin/kprinter" # set PRINTcmd "/usr/bin/hp-print" set PRINTcmd "/usr/bin/cupsdoprint -P EPSON-Epson-Stylus-NX430 -H localhost:631" set ENTRYprintcmd "$PRINTcmd" ##+#################################################### ## We can activate one of the following sets of initial ## plot settings by changing 'if {0}' to 'if {1}'. ##+#################################################### ## NOTE: ## The user can add leading spaces to the titles to help ## position them horizontally. In addition, the titles ## can be dragged. ##+#################################################### ## A generic plot example. ## ## Since desc. of each point along x-axis is short (about 4 char nums), ## we do not use a legend (longer explanatory names for the bars). ## We want to label the x-axis with the nums. ## ## We do not indicate a data source in this generic plot example. if {1} { set ENTRYtitleMain " MAIN PLOT TITLE here." set ENTRYtitleXaxis " X-AXIS TITLE here." set ENTRYtitleYaxis " Y-AXIS TITLE here." set ENTRYxaxismin "0" set ENTRYxaxismax "100" set ENTRYxticdist "10" set ENTRYyaxismin "0" set ENTRYyaxismax "1000" set ENTRYyticdist "100" set ENTRYxvals "10.0 30.0 50.0 70.0 90.0" set ENTRYyvals "150.0 390.0 450.0 790.0 620.0" set ENTRYlegend "" # set ENTRYsource "" } ## END OF if {0}/{1} ## Sample data Group1, for further testing of this GUI: ## World population growth (xaxis = years) ## ## The desc. of each point along x-axis is short (4-digit years). ## ## We do NOT need to use a legend (longer explanatory names for the bars). ## We want to label the x-axis with the years. if {0} { set ENTRYtitleMain " World Population Growth" set ENTRYtitleXaxis " Year" set ENTRYtitleYaxis " Population in millions" set ENTRYxaxismin "1700" set ENTRYxaxismax "2100" set ENTRYxticdist "50" set ENTRYyaxismin "0" set ENTRYyaxismax "6000" set ENTRYyticdist "1000" set ENTRYxvals "1750 1800 1850 1900 1950 2000" set ENTRYyvals "750 1000 1250 1650 2500 6000" set ENTRYlegend "" set legend0or1 0 set source0or1 1 set ENTRYsource "Historical population books, U.S.Gov data, and U.N. data" } ## END OF if {0}/{1} ## Sample data Group2, for further testing of this GUI: ## Bison population in No.America (xaxis = years) ## ## The desc. of each point along x-axis is short (4-digit years). ## ## We do NOT use a legend (longer explanatory names for the bars). ## We want to simply label the x-axis with the years. ## ## We provide a source of the data. if {0} { set ENTRYtitleMain " North American (pure) Bison Population" set ENTRYtitleXaxis " Year" set ENTRYtitleYaxis " Population (thousands)" set ENTRYxaxismin "1600" set ENTRYxaxismax "2050" set ENTRYxticdist "50" set ENTRYyaxismin "0" set ENTRYyaxismax "50000" set ENTRYyticdist "10000" set ENTRYxvals "1700 1870 2010" set ENTRYyvals "30000 2 30" set ENTRYlegend "" set legend0or1 0 set source0or1 1 set ENTRYsource "Source: www.defenders.org/bison/basic-facts & www.fws.gov/bisonrange/timeline.htm" } ## END OF if {0}/{1} ## Sample data Group3, for further testing of this GUI: ## Lion population in Africa (xaxis = years ; only 2 data points) ## ## The desc. of each point along x-axis is short (4-digit years). ## ## We do NOT need to use a legend (longer explanatory names for the bars). ## We want to label the x-axis with the years. ## ## We could indicate that a source of the data is forthcoming. if {0} { set ENTRYtitleMain "Lion Population (de)Growth in Africa" set ENTRYtitleXaxis " Year" set ENTRYtitleYaxis " Population" set ENTRYxaxismin "1960" set ENTRYxaxismax "2010" set ENTRYxticdist "10" set ENTRYyaxismin "0" set ENTRYyaxismax "300000" set ENTRYyticdist "50000" set ENTRYxvals "1960 2010" set ENTRYyvals "250000 20000" set ENTRYlegend "" set legend0or1 0 set source0or1 1 set ENTRYsource "Source: http:??? (to be added)" } ## END OF if {0}/{1} ## Sample data Group4, for further testing of this GUI: ## Oyster harvest in Chesapeake Bay (xaxis = years) ## ## The desc. of each point along x-axis is short (4-digit years). ## ## We do NOT need to use a legend (longer explanatory names for the bars). ## We want to label the x-axis with the years. ## ## We could provide a source of the data. if {0} { set ENTRYtitleMain "Oyster Harvest (Commercial) in the Chesapeake Bay" set ENTRYtitleXaxis " Year" set ENTRYtitleYaxis " Bushels (thousands)" set ENTRYxaxismin "1960" set ENTRYxaxismax "2010" set ENTRYxticdist "10" set ENTRYyaxismin "0" set ENTRYyaxismax "7000" set ENTRYyticdist "1000" set ENTRYxvals "1960 1970 1980 1990 2000 2010" set ENTRYyvals "5500 3500 3200 800 400 200" set ENTRYlegend "" set legend0or1 0 set source0or1 1 set ENTRYsource "Source: www.cheapeakebay.net/status_oysertharvest.aspx" } ## END OF if {0}/{1} ## Sample data Group5, for further testing of this GUI: ## Cheetah population in the world (xaxis = years) ## ## The desc. of each point along x-axis is short (4-digit years). ## ## We do NOT need to use a legend (longer explanatory names for the bars). ## We want to simply label the x-axis with the years. ## ## We could provide a source of the data. if {0} { set ENTRYtitleMain "Cheetah Population (de)Growth in the world" set ENTRYtitleXaxis " Year" set ENTRYtitleYaxis " Population (thousands)" set ENTRYxaxismin "1900" set ENTRYxaxismax "2010" set ENTRYxticdist "10" set ENTRYyaxismin "0" set ENTRYyaxismax "1000" set ENTRYxticdist "100" set ENTRYxvals "1900 1980 2010" set ENTRYyvals "1000 23 2" set ENTRYlegend "" set legend0or1 0 set source0or1 1 set ENTRYsource "Source: www.american.edu/TED/cheetah.htm" } ## END OF if {0}/{1} ## Sample data Group6, for further testing of this GUI. ## Elephant population in Africa (xaxis = years) ## ## The desc. of each point along x-axis is short (4-digit years). ## ## We do NOT use a legend (longer explanatory names for the bars). ## We want to label the x-axis with the years. ## ## We provide a source of the data. if {0} { set ENTRYtitleMain " Estimated Elephant Population in Africa" set ENTRYtitleXaxis " Year" set ENTRYtitleYaxis " Population (thousands)" set ENTRYxaxismin "1900" set ENTRYxaxismax "2010" set ENTRYxticdist "10" set ENTRYyaxismin "0" set ENTRYyaxismax "5000" set ENTRYyticdist "1000" set ENTRYxvals "1930 2010" set ENTRYyvals "4000 400" set ENTRYlegend "" set legend0or1 0 set source0or1 1 set ENTRYsource "Source: wwf.panda.org/what_we_do/endangered_species/elephants/african_elephants/ & en.wikipedia.org/wiki/Elephant" } ## END OF if {0}/{1} ## Sample data Group7, for further testing of this GUI: ## U.S. Budget Surplus/Deficit (xaxis = years) ## ## The desc. of each point along x-axis is short (4-digit years). ## ## We do NOT use a legend (longer explanatory names for the bars). ## We want to label the x-axis with the years. ## ## In place of data-source, we could provide a note on who was president in various years. if {0} { set ENTRYtitleMain "U.S. Budget Surplus/Deficit" set ENTRYtitleXaxis "Year" set ENTRYtitleYaxis "Billions of dollars" set ENTRYxaxismin "1980" set ENTRYxaxismax "2010" set ENTRYxticdist "10" set ENTRYyaxismin "-500" set ENTRYyaxismax "200" set ENTRYyticdist "100" set ENTRYxvals "1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004" set ENTRYyvals "-150 -210 -260 -290 -250 -200 -160 -105 -10 70 110 220 110 -160 -380 -510" set ENTRYlegend "" set legend0or1 0 set source0or1 1 set ENTRYsource "Bush Sr. (1989-1992), Clinton (1993-2000), Bush Jr. (2001-2004)" } ## END OF if {0}/{1} ## Sample data Group8, for further testing of this GUI: ## Federal budget 2012 (xaxis = integers, an identifier of each bar) ## ## Since desc. of each point along x-axis is long, we could ## use a legend (longer explanatory names for the bars) ## corresponding to integers along the x axis. if {0} { set ENTRYtitleMain " President's proposed federal budget, sent to Congress Feb 2012" set ENTRYtitleXaxis " Budget items" set ENTRYtitleYaxis " Percent of Budget" set ENTRYxaxismin "0" set ENTRYxaxismax "6" set ENTRYxticdist "1" set ENTRYyaxismin "0" set ENTRYyaxismax "100" set ENTRYyticdist "10" set ENTRYxvals "1 2 3 4 5 6" set ENTRYyvals "60 4 5 6 6 19" set ENTRYlegend "\ \"1 - Military (DeptOfDefense, Wars, VetAffairs, NuclearWeaponsPrograms)\" \ \"2 - DeptOfHomelandSec.\" \ \"3 - StateDept\" \ \"4 - HealthAndHumanServices\" \ \"5 - Education\" \ \"6 - Other (HUD, Ag, Justice, NASA, Energy excl. NukeWeapons, Labor, Interior, EPA, etc.)\"" set legend0or1 1 set source0or1 0 set ENTRYsource "" } ## END OF if {0}/{1} ##+########################################################### ## Use the current entry field settings and canvas size ## to initialize the plot area with a bar chart plot. ## ## (Since 'update_plot' does not do an 'update' before ## querying the current canvas size, we need to do it here ## --- to force the 'wish' interpreter to do all the ## widget packing with the 'pack' geometry manager, ## before 'update_plot' does its thing.) ##+########################################################### update update_plot