#!/usr/bin/wish -f ## ## SCRIPT: colorArrayGen_aniColorCircle_RYGCBM_upto1530colors_miniscaleH.tk ## ## PURPOSE: This TkGUI script creates a color animation by ## 'traveling around' a '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 is to WRITE A TEXT FILE of COLOR-TABLE ## MAKING Tcl 'set' STATEMENTS from a COLOR-ARRAY of 1,530 colors ## interpolated from the RYGCBMR sequence: ## ## In addition to the animation, this GUI can provide Color Tables ## made from the 6 x 255 = 1,530 colors traversed in the animation. ## 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 'scale'-type WIDGET: ## ## This script 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 100 to 400 per sec is probably more suited to those with ## other things to do. At 1,000 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 builds a color array by 'marching' through the ## 6 basic colors --- RYGCBM --- taking 255 steps between ## the successive pairs of colors in the sequence RYGCBMR ## for a total of 6 x 255 = 1,530 steps. ## ## The color array is used to change the color of the 'color ## swatch', going through each successive color in the array. ## ## 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 'Stop' or 'Exit' buttons on the GUI to ## stop the color-cycle animation. ## ## A 'WriteTables' button on the GUI will write a file of Tcl ## 'set' statements. The 'set' statements can be used to load ## a Tcl array with subsets of the 1,530 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 this script to change an 'EDITOR_text' variable ## to set the GUI text-editor to use.) ## ## The following diagram indicates how the 'load' proc builds ## the 1,530-color array via passage through the 6 RYGCBM ## colors, transitioning from color to color in 255 steps ## for each pair. Note that we alternately increment an RGB ## color component from 0-to-254, then decrement from 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 ## ## When the user uses the 'WriteTables' button, subsets of these ## 1,530 colors are used to make Tcl 'set' statements. ## The 'set' statements can be used in Tcl-Tk scripts to make ## color-tables whose sizes are factors of 1,530 --- ## whose prime factorization is 2 x 3 x 3 x 5 x 17. ## ## (Of course, the user can change the name used for the color-table ## arrays 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 'WriteTables' --- 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 (win-name, win-position, color-scheme, ## fonts, widget-geometry-parms, win-size-control, text-for-labels-etc). ## 1a) Define ALL frames (and sub-frames, if any). ## 1b) Pack the frames and sub-frames. ## ## 1c) Procs to define new widgets go here, if any. ## ## 2) Define all widgets in the frames, frame by frame. ## After defining ALL the widgets for a frame, pack the widgets ## in the 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. ## ############################ ## 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',''WriteTables') ## 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: ## ## - 'load_colorArray1530' Loads an array with 1530 hex-colors. ## Invoked in the added-GUI-initialization section ## at the bottom of the script ## ## - 'animate_RYGCBM' Animates a 'swatch' (frame) on the GUI by ## changing its color every few milliseconds, ## cycling through the 1530 colors. ## ## Invoked in the added-GUI-initialization section ## at the bottom of the script and by a ## 'Start' button on the GUI (after a stop). ## ## - 'writeColorTables_groupsOfSetStatements' ## Writes groups of Tcl 'set' statements to a ## text file and brings the text file up in a ## GUI text editor. ## Invoked by a 'WriteTables' button on the GUI. ## ## - 'popup_msg_var_scroll' invoked by the 'Help' button ## ## 5) Additional GUI initialization: Execute 'load_colorArray1530' and ## 'animate_RYGCBM' 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: Blaise Montandon 2013jan26 1) Chgd the 'milsecs' var of the ## 'miniscaleH' proc to 'delay_milsecs' ## and fixed some increment/decrement ## settings in the proc. ## 2) Broke the proc 'DrawRYGCBM' into ## three procs: ## - load_colorArray1530 ## - animate_RYGCBM ## - writeColorTables_groupsOfSetStatements ## 3) Added many sub-groups of the ## original 1,530 colors to the ## 'set' statements in the output ## 'ColorTables' text file. ## 4) Added an entry widget by which ## to request animating every Nth ## color of the 1530 colors, rather ## than just every color (N=1). ##+####################################################################### ##+####################################################################### ## 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 BKGD_entry "#f0f0f0" ##+########################################################### ## 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 -10 \ -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 -10 \ -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 LABEL widgets: set PADXpx_label 0 set PADYpx_label 0 set BDwidthPx_label 2 ## For BUTTON widgets: set PADXpx_button 0 set PADYpx_button 0 set BDwidthPx_button 2 ## For ENTRY widgets: set BDwidthPx_entry 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 WriteTables 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) "WriteTables" set aRtext(labelSPEED) " ColorsPerSecond:" set aRtext(labelNTH) "N, to animate every Nth of 1,530 colors:" ## 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: ## ## - 'w' - the parent widget/window --- a (sub)frame widget, ## ## - 'scalevar' - the name of the variable that is to hold the current scale value, ## ## - 'minval' & 'maxval' - the min value of the range of the scale, and ## the max value of the range of the scale, ## ## - 'initval' - an initial value at which to initially set the scale variable value ## --- and show in the 'label' widget of this 'miniscaleH' widget, ## ## - 'unit' - 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). ## The '++' and '--' buttons use 8 times this increment. ## The '+' and '-' buttons use this increment. ## See the details in the bind statements and increment/decrement procs below. ## Also see 'delay_milsecs' below. ## ## - 'nonfracdigits' - 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. ## ## - 'fracdigits' - 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. ## ## - 'delay_milsecs' - a delay-time to wait after a ButtonPress ## event before incrementing/decrementing the scale ## AGAIN by the 'unit' (or 8 times 'unit') amount. ## See the details in the bind statements and the increment/decrement procs below. ##+################################################################################# proc miniscaleH {w scalevar minval maxval initval unit nonfracdigits fracdigits delay_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 $delay_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 $delay_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 $delay_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 BINDINGS 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. ## ## The bindings are to stop ## the scale incrementing/decrementing in spite of ## pent-up requests for incrementing/decrementing. ##+##################################################### bind $w.buttMINUSMINUS \ "decrement_miniscaleH $w $scalevar $minval $maxval [expr 8 * $unit] $nonfracdigits $fracdigits $delay_milsecs" bind $w.buttMINUS \ "decrement_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits $delay_milsecs" bind $w.buttPLUS \ "increment_miniscaleH $w $scalevar $minval $maxval $unit $nonfracdigits $fracdigits $delay_milsecs" bind $w.buttPLUSPLUS \ "increment_miniscaleH $w $scalevar $minval $maxval [expr 8 * $unit] $nonfracdigits $fracdigits $delay_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 delay_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 $delay_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 delay_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 $delay_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 ; animate_RYGCBM} button .fRbuttons.buttWRITE \ -text "$aRtext(buttonWRITE)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {writeColorTables_groupsOfSetStatements} #################################################################### ## 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 Parameters: ## w scalevar minval maxval initval unit nonfracdigit fracdigit delay_milsecs ## Worked well before adding entry widget for VAReveryNth: # miniscaleH .fRbuttons.fRspeed colorsPERsec 50 1000 $colorsPERsec 50 4 0 200 ## Need to allow a smaller 'minval' and 'unit'. miniscaleH .fRbuttons.fRspeed colorsPERsec 1 1000 $colorsPERsec 1 4 0 200 #################################################################### ## Define 1 LABEL widget and 1 ENTRY widget --- ## for requesting every Nth color of the 1530-color array ## to be used for the color animation. #################################################################### label .fRbuttons.labelNTH \ -text "$aRtext(labelNTH)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_label \ -pady $PADYpx_label \ -justify left \ -anchor w \ -relief raised \ -bd $BDwidthPx_label set VAReveryNth "1" entry .fRbuttons.entryNTH \ -textvariable VAReveryNth \ -font fontTEMP_fixedwidth \ -width 5 \ -bg "$BKGD_entry" \ -relief sunken \ -bd $BDwidthPx_entry ##+########################################### ## 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 pack .fRbuttons.labelNTH \ -side left \ -anchor w \ -fill none \ -expand 0 \ -padx {20 0} pack .fRbuttons.entryNTH \ -side left \ -anchor w \ -fill none \ -expand 0 ##+####################################################### ## END OF DEFINING-and-PACKING ALL FRAMES and WIDGETS. ## END OF DEFINING the GUI. ## Now define BINDINGS and PROCS. ##+####################################################### ##+####################################################################### ## BINDINGS SECTION: ## Set some bindings to allow for putting a new N in the entry field, ## without causing the '' proc to crash. ## ## Note: There are also bindings within the 'miniscaleH' proc. ##+####################################################################### bind .fRbuttons.entryNTH "set stopani0or1 1" bind .fRbuttons.entryNTH "set stopani0or1 1" bind .fRbuttons.entryNTH "set stopani0or1 0 ; animate_RYGCBM" ##+###################################################################### ## PROCS SECTION: ## ## - 'load_colorArray1530' Loads 1530 'equally-spaced' colors into 2 arrays, ## by interpolating between the RYGCMBR colors. ## ## For the array names, we use 'aRrygcbmr1530hex' ## and 'aRrygcbmr1530rgb255'. ## ## - 'animate_RYGCBM' Performs the color animation by 'marching' ## thru the RYGCMBR color cycle, changing the ## background color of frame '.fRswatch'. ## ## We access the colors in the global var ## 'aRrygcbmr1530hex'. ## ## - 'writeColorTables_groupsOfSetStatements' ## Writes groups of 'set' statements into ## a text file that is then brought up in a ## GUI text editor. ## ## This script can be edited to change the ## 'EDITOR_text' var to a GUI text editor ## preferred by the user. ## ## For details on this 'write' proc, see the comments ## at the top of and within that proc, below. ## ## - 'popup_msg_var_scroll' Invoked by the 'Help' button to show ## a 'HELPtext' var. ## ##+###################################################################### ############################################################################### ## PROC 'load_colorArray1530' ############################################################################### ## PURPOSE: Loads 1530 'equally-spaced' colors into two arrays ## by interpolating between the RYGCMBR colors. ## ## One array is for hex-colors --- one hex-color for each element of ## the array. ## ## The other array is for triplets of RGB colors (0 to 255) --- ## a 3-element Tcl list for each element of the array. ## ## For the array names, we use 'aRrygcbmr1530hex' and ## 'aRrygcbmr1530rgb255'. ## ## OVERVIEW OF THE METHOD: ## The following diagram indicates the passage through the ## 6 RYGCBM colors, transitioning from color to color in 255 steps ## for each pair --- for a total of 6 x 255 = 1530 steps. ## ## Note that we alternately increase from 0-to-254, then ## decrease from 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 ## ## CALLED BY: the added-GUI-initialization section at the bottom of the script. ############################################################################### proc load_colorArray1530 {} { global aRrygcbmr1530hex aRrygcbmr1530rgb255 ################################################################### ## Initialize the counter that we will use to index into the array, ## from 1 thru 1530. ################################################################### set CNT1530 0 ######################################################################### ## LOAD 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] incr CNT1530 set aRrygcbmr1530hex($CNT1530) "$hexcolor" set aRrygcbmr1530rgb255($CNT1530) [list $r255 $g255 $b255] } ## END OF for {set i 0} {$i < 255} {incr i} ## G = 0 thru 254 ######################################################################### ## LOAD 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] incr CNT1530 set aRrygcbmr1530hex($CNT1530) "$hexcolor" set aRrygcbmr1530rgb255($CNT1530) [list $r255 $g255 $b255] } ## END OF for {set i 255} {$i > 0} {incr i -1} ## R = 255 thru 1 ######################################################################### ## LOAD 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] incr CNT1530 set aRrygcbmr1530hex($CNT1530) "$hexcolor" set aRrygcbmr1530rgb255($CNT1530) [list $r255 $g255 $b255] } ## END OF for {set i 0} {$i < 255} {incr i} ## B = 0 thru 254 ######################################################################### ## LOAD 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] incr CNT1530 set aRrygcbmr1530hex($CNT1530) "$hexcolor" set aRrygcbmr1530rgb255($CNT1530) [list $r255 $g255 $b255] } ## END OF for {set i 255} {$i > 0} {incr i -1} ## G = 255 thru 1 ######################################################################### ## LOAD 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] incr CNT1530 set aRrygcbmr1530hex($CNT1530) "$hexcolor" set aRrygcbmr1530rgb255($CNT1530) [list $r255 $g255 $b255] } ## END OF for {set i 0} {$i < 255} {incr i} ## R = 0 thru 254 ######################################################################### ## LOAD 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] incr CNT1530 set aRrygcbmr1530hex($CNT1530) "$hexcolor" set aRrygcbmr1530rgb255($CNT1530) [list $r255 $g255 $b255] } ## END OF for {set i 255} {$i > 0} {incr i -1} ## B = 255 thru 1 } ## END OF proc 'load_colorArray1530' ##+######################################################################## ## PROC 'animate_RYGCBM' ##+######################################################################## ## PURPOSE: Performs the color animation by 'marching' ## thru the RYGCMBR color cycle, changing the ## background color of frame '.fRswatch'. ## ## Uses the 1530 colors in the global array 'aRrygcbmr1530hex'. ## ## CALLED BY: the 'Start' button and in the added-GUI-initialization ## section at the bottom of the script. ########################################################################### proc animate_RYGCBM {} { global aRrygcbmr1530hex colorsPERsec stopani0or1 VAReveryNth ## Following var not needed? # global writing0or1 ################################################## ## If VAReveryNth is out of range, set it to one. ################################################## if {"$VAReveryNth" == ""} {set VAReveryNth 1} if {$VAReveryNth < 1 || $VAReveryNth > 1530} {set VAReveryNth 1} ########################################################################## ## THE COLOR ANIMATION LOOP: ## Loop until the user hits the 'Stop' button. ## The 'Stop' button sets var 'stopani0or1' to 1. ## The animation also will stop if the user hits the Exit button, ## or closes the window. ########################################################################## ## Initialize an index we will use into the array of 1,530 hex-colors. set IDXcolor 1 while {1} { ############################################################# ## Alternatively, this 'while' loop could be based on the ## value of $stopani0or1: while {$stopani0or1 == 0} ## Instead, we continually check on the value of $stopani0or1 ## below and 'return' if it is not zero. ############################################################# ################################################# ## Stop immediately if the stop flag is set. ################################################# if {$stopani0or1 != 0} {return} ## Similarly, we could stop the animation if the 'write' proc ## is running. (Not needed?) # if {$writing0or1 == 1} {return} ########################################################## ## Change the swatch color and force its display. ########################################################## .fRswatch configure -bg "$aRrygcbmr1530hex($IDXcolor)" update ################################################################### ## Increment the color index, but reset it to 1 if it exceeds 1530. ################################################################### ## We use 'catch' in case the user is blanking out and resetting ## VAReveryNth just before this section executes. ################################################################### catch {incr IDXcolor $VAReveryNth} if {$IDXcolor > 1530} {set IDXcolor 1} ################################################################### ## 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 'animate_RYGCBM' > WAITmillisecs: $WAITmillisecs colorsPERsec: $colorsPERsec" # exit ########################################################## ## Wait $WAITmillisecs before continuing the loop. ########################################################## after $WAITmillisecs ################################################## ## If VAReveryNth is out of range, set it to one. ################################################## if {"$VAReveryNth" == ""} {set VAReveryNth 1} if {$VAReveryNth < 1 || $VAReveryNth > 1530} {set VAReveryNth 1} } ## END OF 'while' (color-animation) LOOP. } ## END OF proc 'animate_RYGCBM' ########################################################################## ## PROC 'writeColorTables_groupsOfSetStatements' ########################################################################## ## PURPOSE: Writes groups of 'set' statements into a text file that is ## then brought up in a GUI text editor. ## ## This script can be edited to change the GUI ## text editor to one preferred by the user. ## ## The 'set' statements are meant to eventually ## be used in Tcl scripts to load a color table ## variable with colors. ## ## The 'set' statements use an array name like ## 'aRcolorTableHEX'. Of course, anyone using ## the 'set' statements in a Tcl script could ## do a global change to change the name of ## that array variable. ## ## METHOD: The colors in the 'set' statements come from the global vars ## 'aRrygcbmr1530hex' and 'aRrygcbmr1530rgb255'. ## ## Note that the integer 1530 = 6 x 255 can be factored ## into the prime integers: 2 x 3 x 3 x 5 x 17. ## ## The groups of 'set' statements are generated from ## the 1,530 color array by using: ## ## - every 170 (2x5x17), for a total of 1530/170 = 9 colors ## - every 153 (3x3x17), for a total of 1530/153 = 10 colors ## - every 102 (2x3x17), for a total of 1530/102 = 15 colors ## - every 90 (2x3x3x5), for a total of 1530/90 = 17 colors ## - every 85 (5x17) , for a total of 1530/85 = 18 colors ## - every 51 (3x17) , for a total of 1530/51 = 30 colors ## - every 45 (3x3x5) , for a total of 1530/45 = 34 colors ## - every 34 (2x17) , for a total of 1530/34 = 45 colors ## - every 30 (2x3x5) , for a total of 1530/30 = 51 colors ## - every 18 (2x3x3) , for a total of 1530/18 = 85 colors ## - every 17 , for a total of 1530/17 = 90 colors ## - every 15 (3x5) , for a total of 1530/15 = 102 colors ## - every 10 (2x5) , for a total of 1530/10 = 153 colors ## - every 9 (3x3) , for a total of 1530/9 = 170 colors ## - every 6 (2x3) , for a total of 1530/6 = 255 colors ## - every 5 , for a total of 1530/5 = 306 colors ## - every 3 , for a total of 1530/3 = 510 colors ## - every 2 , for a total of 1530/2 = 765 colors ## - evary 1 , for a total of 1530 colors. ## ## CALLED BY: by the 'WriteTables' button on the GUI ############################################################################# proc writeColorTables_groupsOfSetStatements {} { global env outDIR EDITOR_text aRrygcbmr1530hex aRrygcbmr1530rgb255 ## Following var not needed? # global writing0or1 ###################################################################### ## Open a file to which to write the 'set-color-array' statements ## for the groups of 'set' statements constituting each color table. ###################################################################### set userID "$env(USER)" if {"$outDIR" == ""} {set outDIR "/tmp"} set OUTfilename "$outDIR/${userID}_RYGCMBcolorTables_setStatements.tcl" set f [open $OUTfilename w] ######################################################################## ## Write the group of 'set' statements, from the 1530 HEX color array, ## by stepping every 170 (2x5x17), for a total of 1530/170 = 9 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 9-COLOR HEX-color table (every 170 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 170 incr CNTcolor } puts $f "" puts $f "## 9-COLOR RGB255-color table (every 170 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 170 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 153 (3x3x17), for a total of 1530/153 = 10 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 10-COLOR HEX-color table (every 153 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 153 incr CNTcolor } puts $f "" puts $f "## 10-COLOR RGB255-color table (every 153 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 153 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 102 (2x3x17), for a total of 1530/102 = 15 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 15-COLOR HEX-color table (every 102 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 102 incr CNTcolor } puts $f "" puts $f "## 15-COLOR RGB255-color table (every 102 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 102 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## every 90 (2x3x3x5), for a total of 1530/90 = 17 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 17-COLOR HEX-color table (every 90 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 90 incr CNTcolor } puts $f "" puts $f "## 17-COLOR RGB255-color table (every 90 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 90 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## every 85 (5x17) , for a total of 1530/85 = 18 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 18-COLOR HEX-color table (every 85 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 85 incr CNTcolor } puts $f "" puts $f "## 18-COLOR RGB255-color table (every 85 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 85 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 51 (3x17) , for a total of 1530/51 = 30 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 30-COLOR HEX-color table (every 51 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 51 incr CNTcolor } puts $f "" puts $f "## 30-COLOR RGB255-color table (every 51 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 51 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 45 (3x3x5) , for a total of 1530/45 = 34 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 34-COLOR HEX-color table (every 45 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 45 incr CNTcolor } puts $f "" puts $f "## 34-COLOR RGB255-color table (every 45 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 45 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 34 (2x17) , for a total of 1530/34 = 45 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 45-COLOR HEX-color table (every 34 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 34 incr CNTcolor } puts $f "" puts $f "## 45-COLOR RGB255-color table (every 34 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 34 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 30 (2x3x5) , for a total of 1530/30 = 51 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 51-COLOR HEX-color table (every 30 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 30 incr CNTcolor } puts $f "" puts $f "## 51-COLOR RGB255-color table (every 30 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 30 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 18 (2x3x3) , for a total of 1530/18 = 85 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 85-COLOR HEX-color table (every 18 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 18 incr CNTcolor } puts $f "" puts $f "## 85-COLOR RGB255-color table (every 18 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 18 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 17 , for a total of 1530/17 = 90 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 90-COLOR HEX-color table (every 17 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 17 incr CNTcolor } puts $f "" puts $f "## 90-COLOR RGB255-color table (every 17 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 17 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 15 (3x5) , for a total of 1530/15 = 102 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 102-COLOR HEX-color table (every 15 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 15 incr CNTcolor } puts $f "" puts $f "## 102-COLOR RGB255-color table (every 15 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 15 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 10 (2x5) , for a total of 1530/10 = 153 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 153-COLOR HEX-color table (every 10 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 10 incr CNTcolor } puts $f "" puts $f "## 153-COLOR RGB255-color table (every 10 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 10 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 9 (3x3) , for a total of 1530/9 = 170 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 170-COLOR HEX-color table (every 9 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 9 incr CNTcolor } puts $f "" puts $f "## 170-COLOR RGB255-color table (every 9 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 9 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 6 (2x3) , for a total of 1530/6 = 255 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 255-COLOR HEX-color table (every 6 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 6 incr CNTcolor } puts $f "" puts $f "## 255-COLOR RGB255-color table (every 6 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 6 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 5 , for a total of 1530/5 = 306 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 306-COLOR HEX-color table (every 5 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 5 incr CNTcolor } puts $f "" puts $f "## 306-COLOR RGB255-color table (every 5 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 5 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 3 , for a total of 1530/3 = 510 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 510-COLOR HEX-color table (every 3 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 3 incr CNTcolor } puts $f "" puts $f "## 510-COLOR RGB255-color table (every 3 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 3 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 2 , for a total of 1530/2 = 765 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 765-COLOR HEX-color table (every 2 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor 2 incr CNTcolor } puts $f "" puts $f "## 765-COLOR RGB255-color table (every 2 colors of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor 2 incr CNTcolor } ######################################################################## ## Write the group of 'set' statements, from the 1530 color array, ## by stepping every 1, for a total of 1530 colors ## in the color table. ######################################################################## puts $f "" puts $f "## 1530-COLOR HEX-color table (every color of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableHEX($CNTcolor) \"$aRrygcbmr1530hex($IDXcolor)\"" incr IDXcolor incr CNTcolor } puts $f "" puts $f "## 1530-COLOR RGB255-color table (every color of a 1530-color RYGCBMR cycle):" puts $f "" set IDXcolor 1 set CNTcolor 1 while {$IDXcolor <= 1530} { puts $f "set aRcolorTableRGB255($CNTcolor) \[ list $aRrygcbmr1530rgb255($IDXcolor) \]" incr IDXcolor incr CNTcolor } ########################################################## ## We done writing the 'set' statement groups to a file. ## We close the file and show it in a text editor. ########################################################## 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. } ## END OF proc 'writeColorTables_groupsOfSetStatements' ##+######################################################################## ## 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 ** RYGCBM 'Color Circle' Animation Utility ** and ** Tcl-Color-Array 'set'-Statements Generator Utility ** IMPLEMENTATION OF THE COLOR ANIMATION: This Tk GUI script provides a color animation by 'traveling around' a '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, interpolated between pairs of the 6 RYGCBM colors, is displayed in a 'color swatch' on the GUI. A set of 6 x 255 = 1,530 colors is generated --- graduating from Red to Yellow, then Yellow to Green, then Green to Cyan, then Cyan to Blue, then Blue to Magenta, then Magenta back to Red. Those colors are displayed in sequence to make the color animation. 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. --- CONTROLLING THE SPEED OF THE COLOR ANIMATION: The '+' '++' '-' and '--' buttons on the GUI allow you to control the number of COLORS-PER-SECOND shown during the color animation. You can SPEED UP the color animation by clicking the '+' or '++' buttons of the GUI. The '++' button increments the animation speed by an 8-times bigger factor than the '+' button. Similarly, you can SLOW DOWN the color animation by clicking the '-' or '--' buttons of the GUI. The '--' button decrements the animation speed by an 8-times bigger factor than the '-' button. --- CHANGING THE COLORS SHOWN IN THE ANIMATION: An entry field on the GUI allows you to choose to go through every Nth one of the 1,530 colors, instead of every one. When the mouse cursor goes over the entry field, the animation stops. When you enter an integer and press the Enter/Return key, the animation restarts using the new value of N. The integer 1530 can be factored into the product of primes: 2 x 3 x 3 x 5 x 17. The entry field was intended to allow for entering combinations of these factors, like 2 or 3 or 5 or 6 or 9 or 10 or 15 or 17 or 18 or 30 or ... But you can enter any integer between 1 and 1530. --- THE 'WRITE-TABLES' OPTION: A SECOND (probably more useful) PURPOSE of this GUI is to generate a file containing 'set' statements for making COLOR TABLE ARRAYS from the 1,530 colors. The 'WriteTables' button provides a way of generating tables of 'equally spaced colors' taken from the the 6 x 255 = 1530 colors that were generated to make the initial color animation. The color tables consist of 'set' statements to make array variables that contain 9 or 10 or 18 or ... or 765 or 1530 colors. Two kinds of arrays are made: arrays of hex-colors and arrays of triplets of RGB values (0 to 255). The 'set' statements for the 'HEX' and 'RGB255' color arrays are put in a text file. The user can select any group of the 'set' statements to 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 via some pattern or randomly chosen from the table. Integers in the range 1 to 1530 (or some subset thereof) can be generated --- randomly or in some algorithmic pattern --- to look-up colors to apply to faces/vertices of the model. Of course, the user can adjust the color values in the 'set' statements as needed. The 'set' statements are meant as a convenient starting point for further experimentation in any particular application. --- A THIRD PURPOSE of this GUI - demo of a NEW WIDGET: This script also introduces a new, compact 'scale'-like widget, dubbed 'miniscaleH' (for miniscale-horizontal). In this application, the widget is used to control the speed of the color transition in the animation --- in units of color-steps per second --- from about 1 to 1,000 per second, in this paricular application. At 1 per second, it would take 25 minutes to traverse the 1,530 color steps and start over. A colors-per-second setting in the range of 50 to 400 is probably more suited to those people with other things to do. However, if you choose to set N=90 to show every 90th color of the 1530, only 17 colors are being traversed, repeatedly. In this case, a colors-per-second setting of around 1 or 2 or 3 may be more suitable to keep the colors from changing too fast. 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 number; the '-' and '--' buttons on the left decrement. The '++' and '--' buttons are for high-speed incrementing/decrementing. The '++' button is currently set to increment the value of the 'scale' in 8 times bigger 'jumps' than the '+' button. The '--' button is currently set to decrement the value of the 'scale' in 8 times bigger 'jumps' than the '-' button. The 'miniscaleH' widget is more compact than the Tk '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 SECTION. ##+##################################################### ######################################################################## ## Set the output directory for the file of ColorTable 'set' statements. ######################################################################## set outDIR "/tmp" ################################################################ ## Set the editor with which to view the ColorTables text file. ################################################################ # set EDITOR_text "gedit" # set EDITOR_text "/usr/bin/gedit" set EDITOR_text "$env(HOME)/apps/gscite_2.27/SciTE" ######################################################## ## Load the 1530-color array variables that will be used ## by the 'animate' and 'write' procs. ######################################################## load_colorArray1530 ##################################################### ## Show the GUI before starting the animation loop. ##################################################### update ######################################################## ## Make sure the stop-animation flag is not set to stop. ######################################################## set stopani0or1 0 ######################################################## ## Start with the write-file status-flag turned off. ## (Not needed?) ######################################################## # set writing0or1 0 ####################################################### ## Start the animation so that it starts automatically ## after the GUI shows up. ####################################################### animate_RYGCBM