[uniquename] - 2012nov17 I indicated in April 2012, on my 'biography page' at [uniquename], that I was inspired by Mark Stucky and Gerhard Sookahet to create some 3D model viewing utilities --- complete with fairly robust 3D model data importers (for a variety of 3D data formats --- such as CAD-like data files, Wavefront OBJ files, Cyberware PLY files, STL stereolithography files, etc.). Well, I am getting started on some 3D viewing projects, and I am starting to put together some test 3D models. I would like to have some nice colors for the facets (polygons) and/or vertices of these models so I have been giving some thought to the nice colors that can be made from the RGB ('primary', 'additive') colors and the CMY ('complementary', 'subtractive') colors. If you have seen an image of the 'HSV hexcone', like the following, you probably know what I am talking about. [hsv_hexcone_358x300.jpg] In fact, I am talking about 'going through' the colors on the perimeter of the circle at the top of that cone --- as seen in this image. [RYGCBM_colorDisk_225x225.jpg] I decided to put together a GUI utility that shows me those colors --- AND gradations between them --- along with the capability to generate a set of Tcl 'set' statements that can be used to set up a 'color array' variable that can be used as a 'look up table' to assign colors to facets and vertices. Here is an animated GIF image of the GUI that gives an idea of what I am talking about. [colorCircleRYGCBM_orangeTOgreenTObluish_GUIscreenshot_492x167_ani.gif] The actual GUI goes through the colors much more smoothly. (In fact, I may replace this animated GIF by a movie file someday. With the good compression ratios of movies nowadays, using H.264 format, for example, it is possible to get movie files that are actually more compact than their corresponding, but not so smooth, GIF animations --- in cases where the successive images are not changing in very many pixel locations. Unfortunately, that may not be the case with this animation.) ------ '''HELP Text''' Here is the text from the 'Help' button in the GUI to let give you more clarity on what this Tk script does: ** HELP for this RYGCMB Color Circle Animation and Tcl-Color-Array-Setting-Statements Generator Utility ** This Tk GUI script 'travels around' the 'color circle' --- through the 6 primary and complementary colors --- Red-Yellow-Green-Cyan-Blue-Magenta --- and back to Red, then repeating. The phrase 'travel around', in this particular GUI, means that a sequence of colors, gradiating between pairs of the 6 RYGCBM colors, is displayed in a 'color swatch' on the GUI. The animation continues until the user clicks the Stop button --- or the user can click the Exit button --- or close the window. Thus this script provides a repeating color-sequence animation. The color sequence is somewhat similar to the color spectrum of a prism or rainbow. This animation gives the user a quick, dynamic overview of the color combinations of the primary and complementary colors as one blends the colors in the rather natural sequence RYGCBMR. --- A SECOND (probably more useful) PURPOSE of this GUI is to generate a file containing 'set' statements for an ARRAY OF 1530 COLORS. In addition to the animation, this GUI provides an array of the the 6 x 255 = 1530 hexcolors traversed. The 'set' statements for the array are put in a text file. The 'set' statements can be used in other Tk scripts to set up a 'look-up table' of colors. For example, in a 3D modeling application, one may wish to apply colors to the facets (polygons) or vertices of a 3D model --- either randomly or via some pattern. Integers in the range 1 to 1530 (or some subset thereof) can be generated --- randomly or in some algorithmic pattern --- to apply look-up colors to facets of the model. (Note that since 1530 has many factors --- 1530 = 5 x 2 x 3 x 3 x 17 --- there are quite a few subsets of 'equally-spaced' colors that you can use to cycle 'nicely' through those 1530 colors. Every 2 colors, every 3, every 5, every 6, every 9, every 10, every 15, every 17, every 18, ...) --- A THIRD PURPOSE of this GUI - demo of a NEW WIDGET: This script also introduces a new scale-like widget, dubbed 'miniscaleH' (for miniscale-horizontal) --- to control the speed of the color transition (color steps per second --- from about 50 to 1000 per second). (At 1 per second, it would take 25 minutes to traverse the 1530 steps and start over. A setting in the range of 50 to 400 is probably more suited to those with other things to do.) The 'miniscaleH' widget is made up of 4 'button' widgets and one 'label' widget --- arrayed from left to right --- the label in the middle, with 2 buttons on either side. The '+' and '++' buttons on the right increment the scale numbers; the '-' and '--' buttons on the left decrement. The '++' and '--' buttons are for high-speed incrementing/decrementing. The 'miniscaleH' widget is more compact than the 'scale' widget --- and its labels and buttons can be decorated with background images, via the '-image' and '-compound center' options. So the 'miniscaleH' widget may have some use in 'embellished' Tk GUI's. In contrast, the 'scale' widget does not have a '-image' option. ------ '''miniscaleH widget''' On the subject of the 'miniscaleH' widget, I would just like to point out that it is a 'horizontal' variation on the 'miniscale' widget that I devised for the GUI that I presented at [A color-gradient-button-maker GUI with 6 'miniscale' widgets]. AND ... because I can decorate the 'miniscaleH' widget with background images on the 4 buttons and the label from which the 'miniscaleH' widget is made, I may return to the Tk-GUI-embellishment project that I published at [Version 2 of a demo of THEMES for Tk GUI's, using images and colors] and replace the 'scale' widget in that demo GUI with the 'miniscaleH' widget --- but enhanced with background images. ------ '''The code''' I provide the code for this 1530-color RYGCBMR animation (and color-array 'set'-statements generator) GUI below. I follow my usual 'canonical' structure for Tk code, for this Tk script: 0) Set general window & widget parms (win-name, win-position, win-color-scheme, fonts, widget-geometry-parms, win-size-control, text-array-for-labels-etc). 1a) Define ALL frames (and sub-frames, if any). 1b) Pack ALL frames and sub-frames. 2) Define & pack all widgets in the frames, frame by frame. 3) Define keyboard and mouse/touchpad/touch-sensitive-screen action BINDINGS, if needed. 4) Define PROCS, if needed. 5) Additional GUI initialization (typically with one or more of the procs), if needed. This makes it easy for me to find code sections --- while generating and testing this script, and when looking for code snippets to include in other scripts (code re-use). Since this script also includes a proc to generate the 'miniscaleH' widget, I have added the following step to the typical code structure outline above: 1c) Provide proc(s) to be used to define widget(s) made from other Tk widgets. In addition, I call your attention to step-zero. One new thing that I have started doing recently is using a text-array for text in labels, buttons, and other widgets in the GUI. This can make it easier for people to internationalize my scripts. I will be using a text-array like this in most of my scripts in the future. ------ '''Experimenting with the GUI''' As in all my scripts that use the 'pack' geometry manager (which is all of my 100-plus scripts, so far), I provide the four main pack parameters --- '-side', '-anchor', '-fill', '-expand' --- on all of the 'pack' commands for the frames and widgets. That helps me when I am initially testing the behavior of a GUI (the various widgets within it) as I resize the main window. You can experiment with the '-side', '-anchor', '-fill', and '-expand' parameters on the 'pack' commands for the various frames and widgets --- to get the widget behavior that you want. ___ In addition, you might want to change the fonts used for the various GUI widgets. For example, you could change '-weight' from 'bold' to 'normal' --- or '-slant' from 'roman' to 'italic'. Or change font families. In fact, you may NEED to change the font families, because the families I used may not be available on your computer --- and the default font that the 'wish' interpreter chooses may not be very pleasing. I use variables to set geometry parameters of widgets --- parameters such as border-widths and padding. And I have included the '-relief' parameter on the definitions of frames and widgets. Feel free to experiment with those 'appearance' parameters as well. ___ That said, here's the code --- with plenty of comments to describe what most of the code-sections are doing. The code that generates the 1530 colors for the animation and for writing the color-array file is in the proc 'DrawRYGCBM'. It is my hope that the copious comments in the code will help Tcl-Tk coding 'newbies' get started in making GUI's like this --- and perhaps learn to make new widgets (such as even more variations on the 'miniscale' widget). Without the comments, it might not be clear how the 'stopani0or1' and 'write0or1' flags are being used to control the animation and the writing of the color-array file. Without the comments, potential young Tcler's might be tempted to return to their iPhones and iPads and iPods --- to watch LFHV (Luxembourg's Funniest Home Videos). ====== #!/usr/bin/wish -f ## ## SCRIPT: aniColorCircle_RYGCBM_in1530steps_miniscaleH.tk ## ## PURPOSE: This TkGUI script 'travels around' the 'color circle' --- ## through the 6 'interspersed' primary and complementary colors ## --- Red-Yellow-Green-Cyan-Blue-Magenta --- and back to Red. ## ## The phrase 'travel around' means to convey that a ## sequence of colors, gradiating between pairs of the ## 6 RYGCBM colors, is displayed in a 'color swatch' on the GUI. ## ## By default, the color display will keep cycling --- ## at a rate that is changeable by the user. ## ## I.e. this is a color animation that keeps cycling through ## a sequence of colors (blended from the primary and complementary ## colors), and the user can control the number of color changes ## per second. ## ## The 'swatch' is simply a Tk 'frame' widget for which the ## background color is being reset as this Tk script 'marches' ## through the sequence of colors. ## ## This GUI provides an animation that 'cycles' through a series ## of pretty nice looking colors --- somewhat similar to the color ## spectrum of a prism or rainbow. ## ## This gives the user a quick, dynamic overview of the color ## combinations of the primary and complementary colors as one ## blends the colors in the rather natural sequence RYGCBMR. ## ## A second purpose of this GUI - write a file ## of 1530 'set' COLOR-ARRAY STATEMENTS: ## ## In addition to the animation, this GUI can provide an array ## of the 6 x 255 = 1530 hexcolors traversed (with no duplicates). ## The Tcl 'set' statements for loading the array are put in a ## text file. ## ## The 'set' statements can be used in other Tk scripts to ## set up a 'look-up table' of colors. For example, in a 3D ## modeling application, one may wish to apply colors to the ## facets (polygons) of a 3D model --- either randomly or ## via some pattern. ## ## Integers in the range 1 to 1530 (or some subset thereof) ## can be generated --- randomly or in some algorithmic ## pattern --- to apply 'look-up colors' to facets of the model. ## ## A third purpose of this GUI - demo of a NEW WIDGET: ## ## This script also introduces a new scale-like widget, ## dubbed 'miniscaleH' (for miniscale-horizontal) --- ## to control the speed of the color transition (color ## steps per second --- from about 10 to 1000 per second). ## ## (At 1 per second, it would take 25 minutes to traverse ## the 1530 steps and start over. A setting in the range ## of 10 to 400 per sec is probably more suited to those with ## other things to do. At 1000 colors-per-second, the animation ## would go through a complete cycle in less than 2 seconds.) ## ## The 'miniscaleH' widget is made up of 4 'button' widgets ## and one 'label' widget --- arrayed from left to right --- ## the label in the middle, with 2 buttons on either side. ## ## The '+' and '++' buttons on the right increment the scale ## numbers; the '-' and '--' buttons on the left decrement. ## The '++' and '--' buttons are for high-speed ## incrementing/decrementing. ## ## The 'miniscaleH' widget is more compact than the 'scale' ## widget --- and its labels and buttons can be decorated ## with background images, via the '-image' and ## '-compound center' options. So the 'miniscaleH' widget ## may have some use in 'embellished' Tk GUI's. In contrast, ## the 'scale' widget does not have a '-image' option. ## ######### ## METHOD: The script 'marches' through the 6 basic colors taking 255 steps ## between the successive pairs of colors in the sequence RYGCBMR ## for a total of 6 x 255 = 1530 steps --- updating the color ## swatch for each successive color. ## ## The display of the colors in the 'color swatch' is repeated ## (i.e. keeps cycling) until the user stops the cycle. ## ## The user can use 'Exit' or 'Stop' buttons on the GUI to ## stop the color-cycle animation. ## ## A 'WriteColors' button on the GUI will, if the animation ## is stopped, write a file of Tcl 'set' statements that ## load a Tcl array with the 1530 distinct colors. ## ## The file is written in a fraction of a second and the file ## is shown to the user in a GUI text-editor. (The user can ## edit the 'DrawRYGCBM' proc to set the text-editor to use.) ## ## The following diagram indicates the passage through the ## 6 colors, transitioning from color to color in 255 steps ## for each pair. Note that we go, alternately, from 0-to-254, ## then 255-to-1. ## R G B ## --- --- --- ## R = 255 0 0 ## 255 1 0 ## 255 . 0 ## 255 . 0 R=255 , G = 0 to 254 , B=0 ## 255 . 0 ## 255 254 0 ## Y = 255 255 0 ## 254 255 0 ## . 255 0 ## . 255 0 R = 255 to 1 , G=255 , B=0 ## . 255 0 ## 1 255 0 ## G = 0 255 0 ## 0 255 1 ## 0 255 . ## 0 255 . R=0 , G = 255 , B = 0 to 254 ## 0 255 . ## 0 255 254 ## C = 0 255 255 ## 0 254 255 ## 0 . 255 ## 0 . 255 R=0 , G = 255 to 1 , B=255 ## 0 . 255 ## 0 1 255 ## B = 0 0 255 ## 1 0 255 ## . 0 255 ## . 0 255 R = 0 to 254, G=0 , B=255 ## . 0 255 ## 254 0 255 ## M = 255 0 255 ## 255 0 254 ## 255 0 . ## 255 0 . R=255 , G=0 , B = 255 to 1 ## 255 0 . ## 255 0 1 ## and we are ready to start again at: ## R = 255 0 0 ## ## Similarly, when the user uses the 'WriteColors' button, these ## colors, in hex format, are put in a 1530-element array, say ## 'aRrygcbmr1530'. (Of course, the user can change the name ## in the 1530 set statements with a change-all in a text editor.) ## ############# ## GUI LAYOUT: ## There are 2 frames in the GUI --- TOP and BOTTOM. ## ## The TOP frame contains some buttons, such as 'Exit', 'Help', ## 'Stop', 'Start', and 'WriteColors' --- as well as the 'miniscaleH' ## widget for controlling the speed of the color animation. ## ## The BOTTOM frame contains nothing. It is the 'color-swatch' ## and is used simply by changing its background color. ## ##+###################################################################### ## 'CANONICAL' STRUCTURE OF THIS CODE: ## ## 0) Set general window parms (name,position,[size,]color-scheme,fonts, ## widget-geometry-parms,etc.). ## 1) Define ALL frames (and sub-frames). Pack them. ## 2) Define all widgets in the frames. Pack them. ## ## 3) Define keyboard or mouse action BINDINGS, if needed. ## 4) Define PROCS, if needed. ## 5) Additional GUI INITIALIZATION (with procs), if needed. ## ############################ ## The code-structure detail for this particular script: ## ## 1a) Define ALL frames: ## ## Top-level : '.fRbuttons' , '.fRswatch' ## ## Sub-frames: none ## ## 1b) Pack ALL frames. ## ## 1c) Provide the 'miniscaleH' proc to be used to define a 'miniscaleH' ## widget in the '.fRbuttons' frame. ## ## 2) Define all widgets in the frames (and pack them): ## ## - In '.fRbuttons': 5 button widgets ('Exit','Stop','Start','Help',''WriteColors') ## and a 'miniscaleH' widget (consisting of ## 2buttons-1label-2buttons), ## ## - In '.fRswatch' frame: no widgets ## ## 3) Define BINDINGS: none in this section, but there are bindings ## built-into the miniscaleH widget ## ## 4) Define PROCS: ## ## - 'DrawRYGCBM' invoked by the following added-GUI-initialization ## section and by the 'Start' button (after a stop) ## ## - 'popup_msg_var_scroll' invoked by the 'Help' button ## ## 5) Additional GUI initialization: Execute 'DrawRYGCBM' to start off ## the animation. ##+######################################################################## ## 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 on Ubuntu 9.10. ##+####################################################################### ## MAINTENANCE HISTORY: ## Created by: Blaise Montandon 2012nov16 ## Changed by: ...... ......... 2012 ##+####################################################################### ##+####################################################################### ## Set WINDOW TITLES and POSITION. ##+####################################################################### # wm title . "Animate color circle: Red-Yellow-Green-Cyan-Blue-Magenta-Red" wm title . "Animate color circle: R-Y-G-C-B-M-R" wm iconname . "RYGCBMcircle" wm geometry . +15+30 ##+############################################################# ## Set the COLOR SCHEME (palette) for the window and its widgets. ## ## Also set BACKGROUND OF WIDGETS like entry, listbox, ## radiobutton, checkbutton, ... ##+############################################################# set R255pal 210 set G255pal 210 set B255pal 210 ## chartreuse2 # set R255pal 118 # set G255pal 238 # set B255pal 0 set hexCOLORpal [format "#%02X%02X%02X" $R255pal $G255pal $B255pal] tk_setPalette "$hexCOLORpal" # set radbuttBKGD "#ffffff" ##+########################################################### ## Set FONT-NAMES. ## We use a VARIABLE-WIDTH font for text on labels and buttons. ## ## We use a FIXED-WIDTH font for listbox and text widgets, ## so that the line-up of columns is preserved. ##+########################################################### font create fontTEMP_varwidth \ -family {comic sans ms} \ -size -14 \ -weight bold \ -slant roman font create fontTEMP_SMALL_varwidth \ -family {comic sans ms} \ -size -12 \ -weight bold \ -slant roman ## Some other possible (similar) variable width fonts: ## Arial ## Bitstream Vera Sans ## DejaVu Sans ## Droid Sans ## FreeSans ## Liberation Sans ## Nimbus Sans L ## Trebuchet MS ## Verdana font create fontTEMP_fixedwidth \ -family {liberation mono} \ -size -14 \ -weight bold \ -slant roman font create fontTEMP_SMALL_fixedwidth \ -family {liberation mono} \ -size -12 \ -weight bold \ -slant roman ## Some other possible fixed width fonts (esp. on Linux): ## Andale Mono ## Bitstream Vera Sans Mono ## Courier 10 Pitch ## DejaVu Sans Mono ## Droid Sans Mono ## FreeMono ## Nimbus Mono L ## TlwgMono ##+########################################################### ## Set GEOM VARS for the VARIOUS WIDGET DEFINITIONS. ## (e.g. padding and borderwidth for buttons, labels) ##+########################################################### ## For LABELS: set PADXpx_label 0 set PADYpx_label 0 set BDwidthPx_label 2 ## For BUTTONS: set PADXpx_button 0 set PADYpx_button 0 set BDwidthPx_button 2 ##+####################################################### ## Set a MINSIZE of the WINDOW (roughly), according to the ## approx max WIDTH of the chars in the 'fRbuttons' frame ## --- about 4 buttons and a 'miniscaleH' widget. ## ## --- and according to the approx HEIGHT of the 2 frames ## --- 'fRbuttons' and 'fRswatch'. ##+####################################################### set minWinWidthPx [font measure fontTEMP_varwidth \ "Exit Stop Start WriteColors Help ++ + 100 + ++"] ## Add some to account for right-left window border (about ## 6 pixels) and for widget border-widths and padding --- ## about 8 widgets x 2 pixels/widget. set minWinWidthPx [expr {22 + $minWinWidthPx}] ## Allow 1 char high for 'fRbuttons', ## 100 pixels high for 'fRswatch'. set minCharHeightPx [font metrics fontTEMP_SMALL_fixedwidth -linespace] set minWinHeightPx [expr { 100 + $minCharHeightPx}] ## Add some to account for top-bottom window decoration (about 23 pixels) ## and frame/widget padding (about 3 pixels/frame x 2 frames). set minWinHeightPx [expr 29 + $minWinHeightPx] ## FOR TESTING: # puts "minWinWidthPx = $minWinWidthPx" # puts "minWinHeightPx = $minWinHeightPx" wm minsize . $minWinWidthPx $minWinHeightPx ## We may allow the window to be resizable and we pack the swatch frame with ## '-fill both' so that the swatch-frame can be enlarged by enlarging the ## window. ## If you want to make the window un-resizable, ## you can use the following statement. # wm resizable . 0 0 ####################################################################### ## Set a TEXT-ARRAY to hold text for buttons & labels on the GUI. ## NOTE: This can aid INTERNATIONALIZATION. This array can ## be set according to a nation/region parameter. ####################################################################### ## if { "$VARlocale" == "en"} set aRtext(buttonEXIT) "Exit" set aRtext(buttonHELP) "Help" set aRtext(buttonSTOP) "Stop" set aRtext(buttonSTART) "Start" set aRtext(buttonWRITE) "WriteColors" set aRtext(labelSPEED) "ColorsPerSecond:" ## END OF if { "$VARlocale" == "en"} ##+################################################################ ## DEFINE *ALL* THE FRAMES: ## ## Top-level : 'fRbuttons', 'fRswatch' ## ## Sub-frames: none ##+################################################################ ## FOR TESTING of expansion of frames (esp. during window expansion): # set RELIEF_frame raised # set BDwidth_frame 2 set RELIEF_frame flat set BDwidth_frame 0 frame .fRbuttons -relief $RELIEF_frame -borderwidth $BDwidth_frame frame .fRswatch -relief $RELIEF_frame -borderwidth $BDwidth_frame ##+############################## ## PACK the 2 top-level FRAMES. ##+############################## pack .fRbuttons \ -side top \ -anchor nw \ -fill none \ -expand 0 pack .fRswatch \ -side top \ -anchor nw \ -fill both \ -expand 1 ## OK. All frames are defined and packed. ##+######################### ## DEFINE PROC 'miniscaleH' ## (for use in making an animation-speed-control widget below) ##+############################################################## ## By using font-name and widget-geometry global variables ## - fontTEMP_SMALL_varwidth ## - PADXpx_label ## - PADYpx_label ## - BDwidthPx_label ## - PADXpx_button ## - PADYpx_button ## - BDwidthPx_button ## for the decorative & geometric elements/parameters of the GUI, ## we keep the arguments of this widget-made-on-the-fly down ## to 8 MAIN ELEMENTS/VARIABLES: ## ## - the parent widget/window --- a (sub)frame widget, ## ## - the name of the variable that is to hold the current scale value, ## ## - the min value of the range of the scale, ## - the max value of the range of the scale, ## ## - an initial value at which to initially set the scale variable value ## --- and show in the 'label' widget of this 'miniscaleH' widget, ## ## - a 'resolution' of the scale, such as 1 or 5 or 0.1 or 0.25 or 0.002. ## Each click on the '++' or '+' or '-' or '--' button of the 'miniscaleH' ## widget increases or decreases the variable associated with this ## 'miniscaleH' widget, by an amount equal to this resolution value ## (or a multiple thereof). ## ## - a number-of-digits/chars specification to allow space for the digits/chars ## to the left of a decimal point --- which can keep the right-most digit ## in the same place, instead of shifting left/right as the magnitude ## of the scale value decreases/increases. ## Example: 3 to allow for values 0 to 255 to stay justified right. ## and 4 to allow values -1.0 to +1.0 in tenths to stay justified. ## ## - a fractional digits specification to make sure arithmetic precision errors ## do not result in numbers like 0.30000000000000004 instead of 0.3. ## Example values: 0 for integers and 1 for tenths. ## ## - a milliseconds specification to establish a 'base' change rate for ## the scale numbers. The '++' and '--' hi-speed buttons use this delay rate. ## The '+' and '-' buttons use a rate about 8 times slower --- ## i.e. they use about 8 times that delay. ##+############################################################## proc miniscaleH {w scalevar minval maxval initval unit nonfracdigits fracdigits milsecs} { global PADXpx_button PADYpx_button BDwidthPx_button \ PADXpx_label PADYpx_label BDwidthPx_label ## The font-names are also available: fontTEMP_varwidth fontTEMP_SMALL_varwidth ##+############################################################### ## NOTE: Since the 4 buttons and label are laid out side-by-side, ## left-to-right, we do not need to define any extra subframes. ## We can simply pack them within the specified parent widget, $w. ## From left to right, we have ## '--' button, '-' button, label , '+' button , '++' button. ##+############################################################### ##+#################################################### ## Initialize the 'miniscaleH' variable. ####################################################### set $scalevar $initval ## FOR TESTING: # puts "$scalevar : [set $scalevar]" ##+#################################################### ## In FRAME '$w', ## DEFINE the '--' BUTTON. ##+#################################################### button $w.buttMINUSMINUS \ -text "--" \ -font fontTEMP_varwidth \ -width 2 -height 1 \ -pady 0 \ -padx 0 \ -command "" # -command "increment_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits $milsecs" ##+#################################################### ## In FRAME '$w', ## DEFINE the '-' BUTTON. ##+#################################################### button $w.buttMINUS \ -text "-" \ -font fontTEMP_varwidth \ -width 1 -height 1 \ -pady 0 \ -padx 0 \ -command "" ##+#################################################### ## In FRAME '$w', ## DEFINE a LABEL widget to show the current ## 'miniscaleH' widget value. ##+#################################################### label $w.labelVAL \ -text "$initval" \ -font fontTEMP_varwidth \ -justify right \ -anchor e \ -width [expr $nonfracdigits + $fracdigits] \ -relief flat \ -fg red \ -bd $BDwidthPx_label ##+#################################################### ## In FRAME '$w', ## DEFINE a '+' BUTTON. ##+#################################################### button $w.buttPLUS \ -text "+" \ -font fontTEMP_varwidth \ -width 1 -height 1 \ -pady 0 \ -padx 0 \ -command "" # -command "increment_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits $milsecs" ##+#################################################### ## In FRAME '$w', ## DEFINE a '++' BUTTON. ##+#################################################### button $w.buttPLUSPLUS \ -text "++" \ -width 2 -height 1 \ -font fontTEMP_varwidth \ -pady 0 \ -padx 0 \ -command "" # -command "decrement_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits $milsecs" ################################################## ## Pack the 4 buttons and 1 label within frame $w. ################################################## pack $w.buttMINUSMINUS \ $w.buttMINUS \ $w.labelVAL \ $w.buttPLUS \ $w.buttPLUSPLUS \ -side left \ -anchor w \ -fill none \ -expand 0 ##+##################################################### ## SET BINDING on the buttons in this new-widget so that ## increments/decrements the ## scalevar rapidly as the button continues to ## be pressed. ## ## These bindings could be COMMENTED --- if we implement ## the '-command' option on the 4 buttons to call on ## these commands. ##+##################################################### bind $w.buttMINUSMINUS \ "decrement_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits $milsecs" bind $w.buttMINUS \ "decrement_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits [expr 8 * $milsecs]" bind $w.buttPLUS \ "increment_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits [expr 8 * $milsecs]" bind $w.buttPLUSPLUS \ "increment_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits $milsecs" bind $w.buttMINUSMINUS "set STOPminiscaleH 1" bind $w.buttMINUS "set STOPminiscaleH 1" bind $w.buttPLUS "set STOPminiscaleH 1" bind $w.buttPLUSPLUS "set STOPminiscaleH 1" ## Initialize STOPminiscaleH. global STOPminiscaleH set STOPminiscaleH 0 ##+############################################################# ## PROC 'increment_miniscale' - ## ## CALLED BY: 'ButtonPress-1' binding on the '+' or '++' button. ##+############################################################# proc increment_miniscaleH {w scalevar minval maxval unit nonfracdigits fracdigits milsecs} { ## This 'upvar' associates the local var 'cur_scale_var' with ## the outer var 'scalevar' that is to contain the scale value. ## It is like an EQUIVALENCE statement in FORTRAN. upvar #0 $scalevar cur_scale_val global STOPminiscaleH while { $STOPminiscaleH != 1} { ## FOR TESTING: # puts "cur_scale_val: $cur_scale_val" set cur_scale_val [expr $cur_scale_val + $unit] if { $cur_scale_val > $maxval} { set cur_scale_val $maxval } set cur_scale_val [format %${nonfracdigits}.${fracdigits}f $cur_scale_val] $w.labelVAL configure -text "$cur_scale_val" ## Slow down the change of the scale to human reaction time levels. after $milsecs ## 'update' is needed to check for a button-release that sets STOPminiscaleH to 1. update ## FOR TESTING: # puts "cur_scale_val: $cur_scale_val" } ## END OF LOOP while { $STOPminiscaleH != 1} set STOPminiscaleH 0 ## The following are not needed. # set $scalevar $cur_scale_val ## FOR TESTING: # puts "$scalevar : [set $scalevar]" } ## END OF proc 'increment_miniscale' ##+############################################################### ## PROC 'decrement_miniscale' - ## ## CALLED BY: 'ButtonPress-1' binding on the '-' and '--' buttons. ##+############################################################### proc decrement_miniscaleH {w scalevar minval maxval unit nonfracdigits fracdigits milsecs} { ## This 'upvar' associates the local var 'cur_scale_var' with ## the outer var 'scalevar' that is to contain the scale value. ## It is like an EQUIVALENCE statement in FORTRAN. upvar #0 $scalevar cur_scale_val global STOPminiscaleH while { $STOPminiscaleH != 1} { ## FOR TESTING: # puts "cur_scale_val: $cur_scale_val" set cur_scale_val [expr $cur_scale_val - $unit] if { $cur_scale_val < $minval} { set cur_scale_val $minval } set cur_scale_val [format %${nonfracdigits}.${fracdigits}f $cur_scale_val] $w.labelVAL configure -text "$cur_scale_val" ## Slow down the change of the scale to human reaction time levels. after $milsecs ## 'update' is needed to check for a button-release that sets STOPminiscaleH to 1. update ## FOR TESTING: # puts "cur_scale_val: $cur_scale_val" } ## END OF LOOP while { $STOPminiscaleH != 1} set STOPminiscaleH 0 ## The following are not needed. # set $scalevar $cur_scale_val ## FOR TESTING: # puts "$scalevar : [set $scalevar]" } ## END OF proc 'decrement_miniscale' } ## END OF 'miniscaleH' PROC ##+######################################################### ## OK. Now we are ready to define the widgets in the frames. ##+######################################################### ##+################################################################ ## IN THE '.fRbuttons' frame - ## DEFINE the several BUTTONS --- 'Exit' 'Help' 'Stop' 'Start' --- ## and one 'miniscaleH' widget for 'colors-per-sec' speed control, ## with a label widget in front for 'ColorsPerSec:' text. ##+################################################################ button .fRbuttons.buttEXIT \ -text "$aRtext(buttonEXIT)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {exit} button .fRbuttons.buttHELP \ -text "$aRtext(buttonHELP)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {popup_msg_var_scroll "$HELPtext"} button .fRbuttons.buttSTOP \ -text "$aRtext(buttonSTOP)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {set stopani0or1 1} button .fRbuttons.buttSTART \ -text "$aRtext(buttonSTART)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {set stopani0or1 0 ; DrawRYGCBM} button .fRbuttons.buttWRITE \ -text "$aRtext(buttonWRITE)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {set write0or1 1 ; DrawRYGCBM ; set write0or1 0} #################################################################### ## Define 1 label widget and 1 'miniscaleH' widget. ## ## NOTE: We define a frame here to hold the 'miniscaleH' widget --- ## instead of in the 'define-and-pack-all-frames' section above. ## We define a frame here rather than above, because this ## frames is actually the widget (at least, the container ## of the widget). ##+################################################################# label .fRbuttons.labSPEED \ -text "$aRtext(labelSPEED)" \ -font fontTEMP_varwidth \ -padx $PADXpx_label \ -pady $PADYpx_label \ -justify left \ -anchor w \ -relief flat \ -bd $BDwidthPx_label ## DEFINE the 'miniscaleH' widget for var 'colorsPERsec'. frame .fRbuttons.fRspeed -relief flat -bd 0 set colorsPERsec 200 miniscaleH .fRbuttons.fRspeed colorsPERsec 50 1000 $colorsPERsec 50 4 0 20 ## Parameters: w scalevar minval maxval initval unit nonfracdigit fracdigit milsecs ##+########################################### ## Pack the widgets in the 'fRbuttons' frame. ##+########################################### pack .fRbuttons.buttEXIT \ .fRbuttons.buttHELP \ .fRbuttons.buttSTOP \ .fRbuttons.buttSTART \ .fRbuttons.buttWRITE \ .fRbuttons.labSPEED \ .fRbuttons.fRspeed \ -side left \ -anchor w \ -fill none \ -expand 0 ##+####################################################### ## END OF DEFINING-and-PACKING ALL WIDGETS and ## END OF DEFINING the GUI. ##+####################################################### ##+####################################################################### ## BINDINGS SECTION: ## - one, for button1-release on the miniscaleH widget ##+####################################################################### ## NOT NEEDED? Bindings within the 'miniscaleH' proc should do? if {0} { bind .fRbuttons.fRspeed.buttMINUSMINUS {set STOPminiscaleH 1} bind .fRbuttons.fRspeed.buttMINUS {set STOPminiscaleH 1} bind .fRbuttons.fRspeed.buttPLUS {set STOPminiscaleH 1} bind .fRbuttons.fRspeed.buttPLUSPLUS {set STOPminiscaleH 1} } ## END OF 'if {1/0}' SECTION ## To easily disable the bindings. ##+###################################################################### ## PROCS SECTION: ## ## - 'DrawRYGCBM' to perform the color animation by 'marching' ## thru the RYGCMBR color cycle, changing the ## background color of frame '.fRswatch'. ## ## - 'popup_msg_var_scroll' invoked by the 'Help' button ## ##+###################################################################### ##+######################################################################## ## PROC 'DrawRYGCBM' ##+######################################################################## ## PURPOSE: Performs the color animation by 'marching' ## thru the RYGCMBR color cycle, changing the ## background color of frame '.fRswatch'. ## ## Also writes out ## ## CALLED BY: the 'Start' button and in the added-GUI-initialization ## section at the bottom of the script. ########################################################################### ## OVERVIEW OF THE METHOD: ## The following diagram indicates the passage through the ## 6 colors, transitioning from color to color in 255 steps ## for each pair. Note that we go, alternately, from 0-to-254, ## then 255-to-1. ## R G B ## --- --- --- ## R = 255 0 0 ## 255 1 0 ## 255 . 0 ## 255 . 0 R=255 , G = 0 to 254 , B=0 ## 255 . 0 ## 255 254 0 ## Y = 255 255 0 ## 254 255 0 ## . 255 0 ## . 255 0 R = 255 to 1 , G=255 , B=0 ## . 255 0 ## 1 255 0 ## G = 0 255 0 ## 0 255 1 ## 0 255 . ## 0 255 . R=0 , G = 255 , B = 0 to 254 ## 0 255 . ## 0 255 254 ## C = 0 255 255 ## 0 254 255 ## 0 . 255 ## 0 . 255 R=0 , G = 255 to 1 , B=255 ## 0 . 255 ## 0 1 255 ## B = 0 0 255 ## 1 0 255 ## . 0 255 ## . 0 255 R = 0 to 254, G=0 , B=255 ## . 0 255 ## 254 0 255 ## M = 255 0 255 ## 255 0 254 ## 255 0 . ## 255 0 . R=255 , G=0 , B = 255 to 1 ## 255 0 . ## 255 0 1 ## and we are ready to start again at: ## R = 255 0 0 ## ## Similarly, when the user uses the 'WriteColors' button, these ## colors, in hex format, are put in a 1530-element array, say ## 'aRrygcbmr1530'. (Of course, the user can change the name ## in the 1530 set statements with a change-all in a text editor.) ## ############################################################################# proc DrawRYGCBM {} { global stopani0or1 colorsPERsec write0or1 env outDIR EDITOR_text ## 'write0or1' 'env' 'outDir' 'EDITOR_text' are vars used in putting the ## 'set-color-array' statements in a file. ## If write0or1=1 and stopani0or1=0 (animation is allowed), ## turn off the animation (set stopani0or1 to 1). if {$write0or1 == 1 && $stopani0or1 == 0} { set stopani0or1 1 } ## write0or1=0 & stopani0or1=1: The animate flag is at stop. Abort. if {$write0or1 == 0 && $stopani0or1 == 1} { set write0or1 0 return } ## Other cases to consider: ## write0or1=1 & stopani0or1=1: Go ahead. We generate & write the file, ## then jump out (or we could set ## write0or1=0 & stopani0or1=0 and start ## animating). ## write0or1=0 & stopani0or1=0: Go ahead. Animation is requested. ## For safety's sake, lets abort if the flags are not 0 or 1. if {$write0or1 != 0 && $write0or1 != 1} { puts "write0or1 is not 0 or 1." return } if {$stopani0or1 != 0 && $stopani0or1 != 1} { puts "stopani0or1 is not 0 or 1." return } ## If write-file was requested, ## open a file to which to write the 'set-color-array' statements, ## and initialize a count for making the array. if {$write0or1 == 1} { set userID "$env(USER)" if {"$outDIR" == ""} {set outDIR "/tmp"} set OUTfilename "$outDIR/${userID}_RYGCMBcolorArray1530_setStatements.tcl" set f [open $OUTfilename w] set CNT1530 0 } ## FOR TESTING: # set loopCNT 1 ########################################################################## ## Loop until the user hits the Stop or Exit button, or closes the window. ########################################################################## while {1} { ## See the bottom of this 'while' loop for the exit check which is ## based on the value of $stopani0or1. ## Recalculate the WAITmillisecs, in case colorsPERsec has been ## changed by the user, using the miniscaleH widget. set WAITmillisecs [expr { 1000 / $colorsPERsec }] ## FOR TESTING: # puts "proc 'DrawRYGCBM' > WAITmillisecs: $WAITmillisecs colorsPERsec: $colorsPERsec" # exit ######################################################################### ## DISPLAY COLORS FROM R TO Y: (not including Y) ## R G B ## --- --- --- ## R = 255 0 0 ## 255 1 0 ## 255 . 0 ## 255 . 0 R=255 , G = 0 to 254 , B=0 ## 255 . 0 ## 255 254 0 ## not including Y = 255 255 0 ####################################################################### set r255 255 set g255 0 set b255 0 ## G = 0 thru 254 for {set i 0} {$i < 255} {incr i} { set g255 $i set hexcolor [format "#%02X%02X%02X" $r255 $g255 $b255] ## NOTE: Even though 2 of these components are not changing we ## (re)format from all 3 integers, because we may need ## do this anyway (process 2-of-3 or all-3 of the RGB integers), ## for example, to avoid wavering brightness of the colors in ## the animation. if {$write0or1 == 1} { ## Write out a 'set' statement for a color array. incr CNT1530 puts $f "set aRrybcbmr1530($CNT1530) '$hexcolor'" } else { ## Stop immediately if the stop flag is set. if {$stopani0or1 != 0} {return} ## Change the swatch color. after $WAITmillisecs .fRswatch configure -bg "$hexcolor" update } } ## END OF for {set i 0} {$i < 255} {incr i} ## G = 0 thru 254 ######################################################################### ## DISPLAY COLORS FROM Y TO G: (not including G) ## Y = 255 255 0 ## 254 255 0 ## . 255 0 ## . 255 0 R = 255 to 1 , G=255 , B=0 ## . 255 0 ## 1 255 0 ## not including G = 0 255 0 ######################################################################## ## set r255 255 set g255 255 ## set b255 0 ## R = 255 thru 1 for {set i 255} {$i > 0} {incr i -1} { set r255 $i set hexcolor [format "#%02X%02X%02X" $r255 $g255 $b255] if {$write0or1 == 1} { ## Write out a 'set' statement for a color array. incr CNT1530 puts $f "set aRrybcbmr1530($CNT1530) '$hexcolor'" } else { ## Stop immediately if the stop flag is set. if {$stopani0or1 != 0} {return} ## Change the swatch color. after $WAITmillisecs .fRswatch configure -bg "$hexcolor" update } } ## END OF for {set i 255} {$i > 0} {incr i -1} ## R = 255 thru 1 ######################################################################### ## DISPLAY COLORS FROM G TO C: (not including C) ## G = 0 255 0 ## 0 255 1 ## 0 255 . ## 0 255 . R=0 , G = 255 , B = 0 to 254 ## 0 255 . ## 0 255 254 ## not including C = 0 255 255 ######################################################################### set r255 0 ## set g255 255 ## set b255 0 ## B = 0 thru 254 for {set i 0} {$i < 255} {incr i} { set b255 $i set hexcolor [format "#%02X%02X%02X" $r255 $g255 $b255] if {$write0or1 == 1} { ## Write out a 'set' statement for a color array. incr CNT1530 puts $f "set aRrybcbmr1530($CNT1530) '$hexcolor'" } else { ## Stop immediately if the stop flag is set. if {$stopani0or1 != 0} {return} ## Change the swatch color. after $WAITmillisecs .fRswatch configure -bg "$hexcolor" update } } ## END OF for {set i 0} {$i < 255} {incr i} ## B = 0 thru 254 ######################################################################### ## DISPLAY COLORS FROM C TO B: (not including B) ## C = 0 255 255 ## 0 254 255 ## 0 . 255 ## 0 . 255 R=0 , G = 255 to 1 , B=255 ## 0 . 255 ## 0 1 255 ## not including B = 0 0 255 ######################################################################## ## set r255 0 ## set g255 255 set b255 255 ## G = 255 thru 1 for {set i 255} {$i > 0} {incr i -1} { set g255 $i set hexcolor [format "#%02X%02X%02X" $r255 $g255 $b255] if {$write0or1 == 1} { ## Write out a 'set' statement for a color array. incr CNT1530 puts $f "set aRrybcbmr1530($CNT1530) '$hexcolor'" } else { ## Stop immediately if the stop flag is set. if {$stopani0or1 != 0} {return} ## Change the swatch color. after $WAITmillisecs .fRswatch configure -bg "$hexcolor" update } } ## END OF for {set i 255} {$i > 0} {incr i -1} ## G = 255 thru 1 ######################################################################### ## DISPLAY COLORS FROM B TO M: (not including M) ## B = 0 0 255 ## 1 0 255 ## . 0 255 ## . 0 255 R = 0 to 254, G=0 , B=255 ## . 0 255 ## 254 0 255 ## not including M = 255 0 255 ######################################################################## ## set r255 0 set g255 0 ## set b255 255 ## R = 0 thru 254 for {set i 0} {$i < 255} {incr i} { set r255 $i set hexcolor [format "#%02X%02X%02X" $r255 $g255 $b255] if {$write0or1 == 1} { ## Write out a 'set' statement for a color array. incr CNT1530 puts $f "set aRrybcbmr1530($CNT1530) '$hexcolor'" } else { ## Stop immediately if the stop flag is set. if {$stopani0or1 != 0} {return} ## Change the swatch color. after $WAITmillisecs .fRswatch configure -bg "$hexcolor" update } } ## END OF for {set i 0} {$i < 255} {incr i} ## R = 0 thru 254 ######################################################################### ## DISPLAY COLORS FROM M TO R: (not including R) ## M = 255 0 255 ## 255 0 254 ## 255 0 . ## 255 0 . R=255 , G=0 , B = 255 to 1 ## 255 0 . ## 255 0 1 ## not including R = 255 0 0 ## and we are back where we started. ######################################################################## set r255 255 ## set g255 0 ## set b255 255 ## B = 255 thru 1 for {set i 255} {$i > 0} {incr i -1} { set b255 $i set hexcolor [format "#%02X%02X%02X" $r255 $g255 $b255] if {$write0or1 == 1} { ## Write out a 'set' statement for a color array. incr CNT1530 puts $f "set aRrybcbmr1530($CNT1530) '$hexcolor'" } else { ## Stop immediately if the stop flag is set. if {$stopani0or1 != 0} {return} ## Change the swatch color. after $WAITmillisecs .fRswatch configure -bg "$hexcolor" update } } ## END OF for {set i 255} {$i > 0} {incr i -1} ## B = 255 thru 1 ########################################################## ## If we were writing the 'set-array' statements to a file ## during the first pass of the loop, we could close the ## file here and show it in a text editor. ########################################################## if {$write0or1 == 1} { set write0or1 0 close $f # exec /usr/bin/sh -c "$EDITOR_text "$OUTfilename" > /dev/null 2>&1" exec $EDITOR_text "$OUTfilename" ## Exit this proc. We have generated the requested file. ## The user can click the Start button if they want to ## restart the animation. (Alternatively, we could set ## stopani0or1 to 0 and let animation commence by ## commenting out this return statement.) return } ## END OF if {$write0or1 == 1} ## FOR TESTING: # puts "proc 'DrawRYGCBM' > loopCNT: $loopCNT" # incr loopCNT } ## END OF while {$stopani0or1 == 0} } ## END OF proc 'DrawRYGCBM' ##+######################################################################## ## PROC 'popup_msg_var_scroll' ##+######################################################################## ## PURPOSE: Report help or error conditions to the user. ## CALLED BY: 'help' button ##+######################################################################## ## To have more control over the formatting of the message (esp. ## words per line), we use this 'toplevel-text' method, ## rather than the 'tk_dialog' method -- like on page 574 of the book ## by Hattie Schroeder & Mike Doyel,'Interactive Web Applications ## with Tcl/Tk', Appendix A "ED, the Tcl Code Editor". ##+######################################################################## proc popup_msg_var_scroll { VARtext } { ## global fontTEMP_varwidth #; Not needed. 'wish' makes this global. ## global env # bell # bell ################################################# ## Set VARwidth & VARheight from $VARtext. ################################################# ## To get VARheight, ## split at '\n' (newlines) and count 'lines'. ################################################# set VARlist [ split $VARtext "\n" ] ## For testing: # puts "VARlist: $VARlist" set VARheight [ llength $VARlist ] ## For testing: # puts "VARheight: $VARheight" ################################################# ## To get VARwidth, ## loop through the 'lines' getting length ## of each; save max. ################################################# set VARwidth 0 ############################################# ## LOOK AT EACH LINE IN THE LIST. ############################################# foreach line $VARlist { ############################################# ## Get the length of the line. ############################################# set LINEwidth [ string length $line ] if { $LINEwidth > $VARwidth } { set VARwidth $LINEwidth } } ## END OF foreach line $VARlist ## For testing: # puts "VARwidth: $VARwidth" ############################################################### ## NOTE: VARwidth works for a fixed-width font used for the ## text widget ... BUT the programmer may need to be ## careful that the contents of VARtext are all ## countable characters by the 'string length' command. ############################################################### ##################################### ## SETUP 'TOP LEVEL' HELP WINDOW. ##################################### catch {destroy .fRtopmsg} toplevel .fRtopmsg # wm geometry .fRtopmsg 600x400+100+50 wm geometry .fRtopmsg +100+50 wm title .fRtopmsg "Note" # wm title .fRtopmsg "Note to $env(USER)" wm iconname .fRtopmsg "Note" ##################################### ## In the frame '.fRtopmsg' - ## DEFINE THE TEXT WIDGET and ## its two scrollbars --- and ## DEFINE an OK BUTTON widget. ##################################### text .fRtopmsg.text \ -wrap none \ -font fontTEMP_varwidth \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 \ -yscrollcommand ".fRtopmsg.scrolly set" \ -xscrollcommand ".fRtopmsg.scrollx set" scrollbar .fRtopmsg.scrolly \ -orient vertical \ -command ".fRtopmsg.text yview" scrollbar .fRtopmsg.scrollx \ -orient horizontal \ -command ".fRtopmsg.text xview" button .fRtopmsg.butt \ -text "OK" \ -font fontTEMP_varwidth \ -command "destroy .fRtopmsg" ############################################### ## PACK *ALL* the widgets in frame '.fRtopmsg'. ############################################### ## Pack the bottom button BEFORE the ## bottom x-scrollbar widget, pack .fRtopmsg.butt \ -side bottom \ -anchor center \ -fill none \ -expand 0 ## Pack the scrollbars BEFORE the text widget, ## so that the text does not monopolize the space. pack .fRtopmsg.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 .fRtopmsg.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 .fRtopmsg.text \ -side top \ -anchor center \ -fill both \ -expand 1 ##################################### ## LOAD MSG INTO TEXT WIDGET. ##################################### ## .fRtopmsg.text delete 1.0 end .fRtopmsg.text insert end $VARtext .fRtopmsg.text configure -state disabled } ## END OF PROC 'popup_msg_var_scroll' set HELPtext "\ ** HELP for this RYGCMB Color Circle Animation and Tcl-Color-Array-Setting-Statements Generator Utility ** This Tk GUI script 'travels around' the 'color circle' --- through the 6 primary and complementary colors --- Red-Yellow-Green-Cyan-Blue-Magenta --- and back to Red, then repeating. The phrase 'travel around', in this particular GUI, means that a sequence of colors, gradiating between pairs of the 6 RYGCBM colors, is displayed in a 'color swatch' on the GUI. The animation continues until the user clicks the Stop button --- or the user can click the Exit button --- or close the window. Thus this script provides a repeating color-sequence animation. The color sequence is somewhat similar to the color spectrum of a prism or rainbow. This animation gives the user a quick, dynamic overview of the color combinations of the primary and complementary colors as one blends the colors in the rather natural sequence RYGCBMR. --- A SECOND (probably more useful) PURPOSE of this GUI is to generate a file containing 'set' statements for an ARRAY OF 1530 COLORS. In addition to the animation, this GUI provides an array of the the 6 x 255 = 1530 hexcolors traversed. The 'set' statements for the array are put in a text file. The 'set' statements can be used in other Tk scripts to set up a 'look-up table' of colors. For example, in a 3D modeling application, one may wish to apply colors to the facets (polygons) or vertices of a 3D model --- either randomly or via some pattern. Integers in the range 1 to 1530 (or some subset thereof) can be generated --- randomly or in some algorithmic pattern --- to apply look-up colors to facets of the model. --- A THIRD PURPOSE of this GUI - demo of a NEW WIDGET: This script also introduces a new scale-like widget, dubbed 'miniscaleH' (for miniscale-horizontal) --- to control the speed of the color transition (color steps per second --- from about 50 to 1000 per second). (At 1 per second, it would take 25 minutes to traverse the 1530 steps and start over. A setting in the range of 50 to 400 is probably more suited to those with other things to do.) The 'miniscaleH' widget is made up of 4 'button' widgets and one 'label' widget --- arrayed from left to right --- the label in the middle, with 2 buttons on either side. The '+' and '++' buttons on the right increment the scale numbers; the '-' and '--' buttons on the left decrement. The '++' and '--' buttons are for high-speed incrementing/decrementing. The 'miniscaleH' widget is more compact than the 'scale' widget --- and its labels and buttons can be decorated with background images, via the '-image' and '-compound center' options. So the 'miniscaleH' widget may have some use in 'embellished' Tk GUI's. In contrast, the 'scale' widget does not have a '-image' option. " ##+##################################################### ## Additional GUI initialization, if needed (or wanted). ##+##################################################### ## Set the dir for the file of 'set-color-statements'. set outDIR "/tmp" ## Set the editor with which to view the file. # set EDITOR_text "gedit" # set EDITOR_text "/usr/bin/gedit" set EDITOR_text "$env(HOME)/apps/gscite_2.27/SciTE" ## Show the GUI before starting the animation calcs. update ## Make sure the stop-animation flag is not set to stop. set stopani0or1 0 ## Start with the write-file flag turned off. set write0or1 0 ## FOR TESTING: (Go right into the write-file logic.) # set stopani0or1 1 # set write0or1 1 ## Start the animation as soon as the GUI starts up. DrawRYGCBM ====== Note that the user can set the variable 'EDITOR_text' at the bottom of the script to choose an appropriate GUI text editor in which the file of Tcl 'set' statements will be shown. The editor is called up from within the Tk script by using the Tcl 'exec' command. --- The 1530-set-statments generation is so fast that IMMEDIATELY after clicking on the 'WriteColors' button, the text-editor pops up displaying the 'set'-statements file. You can change the name of the array variable if you wish, and save the file in a directory of your choice. ------ I find it interesting to note that a lot of the reason we center our attention on the RGB colors (and the pigments CMY that 'suck' those colors out of reflected light) is because of the way our eyes react to those colors and because of those colors' positions in the frequency/wavelength spectrum (within an 'octave' of each other): [RGB_waveLengths_blackONwhite_552x276.jpg] It is reported that some animals do not see all the colors that we see. Unlucky them. In my case, I am partially red-green blind. I think if my sensitivty to red and green were plotted like this, my red and green 'humps' might be about as tall as that 'blue' hump. Maybe that is why blue is my favorite color. In any case, ... ------ It took a couple of days to get this code in shape. But now I am in a position to generate some 3D model files and liven them up some with a variety of colors. Tk, you make me :-) . ------ I plan to enhance this script so that it puts out smaller groups of 'set' statements --- corresponding to subsets of the 1,530 set statements --- all in the same output file. Then, when I need an array of about 20 'set' statements, say, to make an array of about 20 'equally spaced' colors for another Tk script, I can run this utility and extract out the group of 'set' statements that I need. I pointed out above that 1530 has many factors --- 1530 = 5 x 2 x 3 x 3 x 17. So there are quite a few subsets of 'equally-spaced' colors that you can use to cycle 'nicely' through those 1530 colors. I will probably make subsets of 'set' statements from every 2 colors, every 3, every 5, every 6, every 9, every 10, every 15, every 17, every 18, every 30, every 34, every 51, every 85, every 90, every 102, every 153, every 170 of the 1,530 color array. I may find that I use the 'every 85' set (18 colors) and 'every 90' (17 colors) and 'every 102' (15 colors) and 'every 153' (10 colors) and 'every 170' (9 colors) most often. And I may use some variations --- like replace some magentas with browns. <> GUI