#!/usr/bin/wish -f ## ## SCRIPT: primesSieve_inResizableCanvas_createImg.tk ## ## PURPOSE: This Tk GUI script shows the primes and non-primes in the ## first Mmax-times-Nmax positive integers as colored pixels in a ## rectangular image area on a Tk Canvas --- where ## - Mmax and Nmax are hard-coded in this script, where Mmax and Nmax ## are the upper limits of 2 'scale' widgets that are used to ## specify image-size, MxN, of the image to be created, ## - each postive integer is represented as a pixel in the ## rectangular image area, ## - each prime is indicated by one color and each non-prime ## is indicated by another color, ## - the user can choose the two colors, ## - the integers (the color1 and color2 pixels) are plotted 'row-wise' ## in an image area in the Tk GUI, where the size of the image ## can be precisely set by the user via 2 'scale' widgets on the GUI, ## - the pixels (one for each integer) are plotted in M columns and N rows ## of pixels where M is the user-selected width of the image area ## in pixels and N is the user-selected height of the image area ## in pixels. ## ## METHOD: In this particular implementation, the 'image of the primes' is ## put on the canvas via a canvas 'image create' command ## --- and via 'put -to' command(s) on ## the image, where each color list is M elements/columns long. ## ## Thus the image may be built row-wise --- that is, a list of M colors ## is built and placed in the image with the 'put' command, until ## the image is built up by N such rows. ## ## Each time the user changes the x and/or y image size (M and/or N ## --- by using a couple of 'scale' widgets) of the Tk GUI window, the ## user can click the 'ReDraw' widget to rebuild the image. ## ## We 'hard-code' Mmax and Nmax values in this script. (These two ## values may be set by querying the screensize of the computer.) ## ## Then the primes among the first Mmax x Nmax integers are determined ## by calling a proc at the bottom of this script that executes ## a sieve of Eratosthenes procedure. ## ## Thus, to avoid having to determine the primes each time the image ## size is changed, the primes are determined in one call to one ## procedure, based on the setting of Mmax and Nmax (which can be set ## according to the screen size of the computer monitor). ## ## In other words, ## this script can query the current screen-size and then can ## apply the sieve of Eratosthenes method to determine the primes ## in the positive integers from 1 to (Mscrn x Nscrn), where ## Mscrn is the number of columns of pixels of the monitor sreen and ## Nscrn is the number of rows of pixels of the monitor. ## ## However, if you, a Tcl-Tk programmer, want to allow images larger ## then the screen size, then Mmax and Nmax could be set to a much ## larger size. The canvas widget is equipped with x and y scrollbars ## to allow for scrolling through a very large image. ## ## The prime/not-a-prime information is saved in a 1-dimensional array --- ## named 'parray' --- of ones and zeros. The array is used to populate ## the canvas image with pixels of one color or the other (of the 2 colors ## chosen by the user) --- on initial GUI display --- and each time the user ## clicks the 'ReDraw' button. ## ## (If it takes quite a number of seconds to build the 'primes array', ## the user may be supplied hints on the GUI --- say, ## 'Building sieve array...' and 'Array done.' messages on the GUI ## --- so that the user is aware of why there is a pause at ## the beginning of the presentation of the GUI.) ## ##+############## ## THE GUI DESIGN: ## ## The GUI made by this Tk script contains a rectangular CANVAS WIDGET ## on which the color-filled rectangular image will be drawn, using 2 colors. ## ## To do the drawing on the canvas, we use the 'image create' command to ## put an image on the canvas. ## ## After the (Mmax x Nmax) array of ones and zeros is built, ## we fill the interior of the image-rectangle by using 'put' commands like ## 'put -to 0 $y' ## on the image where each hexcolor in the 'scanline list' that ## is inside the rectangle is determined by the 2 colors that a user ## chooses, and by the ones and zeros of the 'primes array'. ## ###################################### ## RE-DRAWING THE IMAGE IN THE CANVAS: ## ## The user can change the size of the image area by using the x and y ## image-size 'scale' widgets on the GUI. ## ## A redraw of the 'primes image' is performed whenever the user ## clicks the 'ReDraw' button. ## ## **NOTE** ## We take this approach, so that the user has PRECISE control of ## the image size in the x and y directions. For example, the user ## can quickly and precisely set the x-size to 6 (or n*6) ## to see that a majority of the non-primes can be placed into ## into 4 of the 6 columns (or n*4 columns of the n*6 columns) ## --- tow-thirds of the columns. ## ## The user can quickly and PRECISELY experiment with how ## the pattern of primes changes when the primes are 'plotted' ## with a different width for the rows of integers/pixels. ## ## By setting the y-size of the limit to a low value, ## the user can make the redraw proceed quickly, by ## not drawing pixels for many of the Mmax x Nmax entries ## in the 1-dimensional array, 'parray'. ## ## The redraw includes clearing the canvas (deleting the image), ## recreating the image structure according to the current image size request, ## and redrawing (re-filling) the image with 'put -to' ## command(s). ## ## (If erasing the canvas and redrawing the rectangular image ## completes within a very small fraction of a second, it would ## be feasible to do the redraws 'dynamically', whenever either ## image-size scale is changed.) ## ################################### ## BUTTONS USED TO SET THE 2 COLORS: ## ## The GUI includes 2 buttons to call on a color selector GUI (an 'external' ## Tk script) to set the 2 colors --- for the primes and non-primes. ## ##+######################### ## USING THE GENERATED IMAGE: ## A screen/window capture utility (like 'gnome-screenshot' ## on Linux) can be used to capture the GUI image in a GIF ## or PNG file, say. ## ## If necessary, an image editor (like 'mtpaint' on Linux) ## can be used to crop the window capture image. ## ## The colored image file could be used with a utility (like the ## ImageMagick 'convert' command) to change one of the 2 colors ## to TRANSPARENT, making a partially transparent GIF ## (or PNG) file. Then the semi-transparent image file could be used ## --- for example, to overlay other backgrounds in HTML pages. ## ## This 'prime-filtering' of an arbitrary image would probably ## be more 'effective' if the primes were indicated by ## squares of pixels rather than single pixels. ## ##+######################################################################## ## 'CANONICAL' STRUCTURE OF THIS TK CODE: ## ## 0) Set general window & widget parms (win-name, win-position, ## win-color-scheme, fonts, widget-geometry-parms, win-size-control). ## ## 1a) Define ALL frames and sub-frames. ## 1b) Pack ALL frames and sub-frames. ## ## 2) Define all widgets in the frames --- typically going through the ## frames top-to-bottom and/or left-to-right --- and defining the ## widgets within each frame top-to-bottom and/or left-to-right. ## Pack the widgets after each frame has its widgets defined. ## ## 3) Define keyboard or mouse/touchpad/touch-sensitive-screen action ## BINDINGS, if needed. ## ## 4) Define PROCS, if needed. ## ## 5) Additional GUI INITIALIZATION (with procs), if needed. ## ## ## Some detail about the code structure of this particular script: ## ## 1a) Define ALL frames: ## ## Top-level : '.fRbuttons' , '.fRimagesize' , '.fRstatus' , '.fRcan' ## ## Sub-frames: none ## ## 1b) Pack ALL frames. ## ## 2) Define all widgets in the frames (and pack them): ## ## - In '.fRbuttons': 3 button widgets ('Exit', 'Help', 'ReDraw'), ## and ## 2 buttons (for setting 2 colors). ## - In '.fRimgsize': 2 scale widgets, for x,y image size in the ## canvas widget, below. ## - In '.fRstatus': 1 label widget in which to display 'status' msgs. ## - In '.fRcan': 1 'canvas' widget ## ## 3) Define bindings: ## ## None. We offer the 'ReDraw' button so the user can control when ## a redraw is done --- rather than doing an automatic redraw, ## for example, when the user alters either of the image size dimensions. ## ## 4) Define procs: ## ## - 'load_primes_sieve_array' - to load an array with ones and zeros ## indicating whether the integer index of the ## array is a prime or a non-prime. ## Called once in the 'Additional GUI Initialization' ## section at the bottom of this script. ## ## - 'redraw_primes' - to clear the image structure (if any) and ## create a new image structure according to the ## current requested width and height of the image area ## --- and then draw the on/off (colored) pixels in the ## rectangular image structure on the canvas. ## Called by the 'ReDraw' button. ## ## - 'set_color1' - shows a color selector GUI and uses the ## user-selected color-1 to do subsequent redraws ## of the 'primes image' on the canvas. ## Called by the color1 button. ## ## - 'set_color2' - shows a color selector GUI and uses the ## user-selected color-2 to do subsequent redraws ## of the 'primes image' on the canvas. ## Called by the color2 button. ## ## - 'update_colors_label' - updates the color and the text in ## either of the 2 color buttons. The text ## shows hex values of the current color1 ## or color2 settings. ## Called by the 'set_color*' procs. ## ## - 'popup_msgVarWithScroll' - reports help or other info (such a list of ## prime numbers) to the user. ## Called by the Help button. ## ## 5) Additional GUI initialization: Execute the 'load_primes_sieve_array' ## proc. Then execute the 'redraw_primes' ## proc once with an initial set ## of parms --- COLOR1hex, COLOR2hex ## --- to start with a 'primes image' on ## the canvas rather than a blank canvas. ## ##+######################################################################## ## DEVELOPED WITH: ## Tcl-Tk 8.5 on Ubuntu 9.10 (2009-october release, 'Karmic Koala'). ## ## $ wish ## % puts "$tcl_version $tk_version" ## showed 8.5 8.5 on Ubuntu 9.10 ## after Tcl-Tk 8.4 was replaced by 8.5 --- to get anti-aliased fonts. ##+####################################################################### ## MAINTENANCE HISTORY: ## Created by: Blaise Montandon 2013jul04 ## Changed by: Blaise Montandon 2015mar09 Changed location of color-selector ## script to use a common script in ## the 'tkGooies' FE system. ## Changed by: Blaise Montandon 2016jun27 Added '.fRimgsize' frame with ## two 'scale' widgets with which ## to control the image size in which ## to draw the primes-sieve image. ## Changed by: Blaise Montandon 2016jun28 Added 'Show Primes MxN Table' button. ## Changed by: Blaise Montandon 2016jun29 Added 'Show Primes Separation' and ## 'Show pi(n) #Primes < n' button. ##+####################################################################### ##+####################################################################### ## Set general window parms (title,position --- followed by ## color-scheme,fonts,window-minsize,etc.). ##+####################################################################### wm title . "Primes Sieve --- in a resizable image" wm iconname . "PrimesImage" wm geometry . +15+30 ##+###################################################### ## Set the color scheme for the window and its widgets. ## ## We set the initial 2 colors for the pixels of the ## 'primes image' at the bottom of this script, in the ## 'Additional GUI Initialization' section. ##+###################################################### tk_setPalette "#e0e0e0" # set listboxBKGD "#f0f0f0" # set entryBKGD "#f0f0f0" # set radbuttBKGD "#f0f0f0" set scaleBKGD "#f0f0f0" ##+########################################################## ## We use a VARIABLE-WIDTH FONT for label and button widgets. ## ## We use a FIXED-WIDTH FONT for entry fields, listboxes, and ## text or message widgets, if any. ##+########################################################## font create fontTEMP_varwidth \ -family {comic sans ms} \ -size -14 \ -weight bold \ -slant roman font create fontTEMP_SMALL_varwidth \ -family {comic sans ms} \ -size -12 \ -weight bold \ -slant roman ## Some other possible (similar) variable width fonts: ## Arial ## Bitstream Vera Sans ## DejaVu Sans ## Droid Sans ## FreeSans ## Liberation Sans ## Nimbus Sans L ## Trebuchet MS ## Verdana font create fontTEMP_fixedwidth \ -family {liberation mono} \ -size -14 \ -weight bold \ -slant roman font create fontTEMP_SMALL_fixedwidth \ -family {liberation mono} \ -size -12 \ -weight bold \ -slant roman ## Some other possible fixed width fonts (esp. on Linux): ## Andale Mono ## Bitstream Vera Sans Mono ## Courier 10 Pitch ## DejaVu Sans Mono ## Droid Sans Mono ## FreeMono ## Nimbus Mono L ## TlwgMono ##+########################################################### ## SET GEOM VARS FOR THE VARIOUS WIDGET DEFINITIONS. ## (e.g. width and height of canvas, and padding for Buttons) ##+########################################################### ## BUTTON geom parameters: set PADXpx_button 0 set PADYpx_button 0 set BDwidthPx_button 2 set RELIEF_button "raised" ## LABEL geom parameters: set PADXpx_label 0 set PADYpx_label 0 set BDwidthPx_label 2 set RELIEF_label "ridge" ## SCALE geom parameters: ## (Mmax and Nmax are the upper limits of the 2 scale widgets.) # set Mmax 1000 # set Nmax 800 set Mmax [winfo screenwidth .] set Nmax [winfo screenheight .] set BDwidthPx_scale 2 set scaleLengthPx 250 set scaleThicknessPx 10 set scaleRepeatDelayMillisecs 800 ## CANVAS geom parameters: set initCanWidthPx 400 set initCanHeightPx 300 ## NOTE: We could make these numbers smaller if ## we want a smaller initial canvas. # set BDwidthPx_canvas 2 set BDwidthPx_canvas 0 ##+################################################################### ## Set a MINSIZE of the window (roughly). ## ## For width, allow for the minwidth of the '.fRbuttons' frame: ## about 5 buttons --- Exit,Help,ReDraw,Color1,Color2. ## ## For height, allow for ## 2 chars high for the widgets in the '.fRbuttons' frame, ## 2 chars high for the scale widgets in the '.fRimgsize' frame, ## 2 chars high for the label widget in the '.fRstatus' frame, ## a canvas at least 24 pixels high ##+################################################################### set minWinWidthPx [font measure fontTEMP_varwidth \ "Exit Help Redraw Prime Color Non-Prime Color"] ## Add some pixels to account for right-left-side window decoration ## (about 8 pixels), about 5 x 4 pixels/widget for borders/padding for ## 5 widgets --- 5 buttons. 8 + 20 = 28 pixels. set minWinWidthPx [expr {28 + $minWinWidthPx}] ## NOTE: We want to be able to shrink the image rectangle quite a bit ## in the x-direction --- so we may not want to make the min-width very wide. ## One could use a smaller min-width than this, if one wants to ## make the canvas and the entire window very narrow. ## MIN HEIGHT --- for the 4 frames --- allow: ## 2 chars high for 'fRbuttons' ## 2 chars high for 'fRimgsize' ## 2 chars high for 'fRstatus' ## 24 pixels high for 'fRcan' set CharHeightPx [font metrics fontTEMP_varwidth -linespace] set minWinHeightPx [expr {24 + (6 * $CharHeightPx)}] ## Add about 28 pixels for top-bottom window decoration, ## about 4 pixels for each of the 4 stacked frames and their ## widgets (their borders/padding). 28 + 16 = 44. set minWinHeightPx [expr {$minWinHeightPx + 44}] ## FOR TESTING: # puts "minWinWidthPx = $minWinWidthPx" # puts "minWinHeightPx = $minWinHeightPx" wm minsize . $minWinWidthPx $minWinHeightPx ## We allow the window to be resizable and we pack the canvas with ## '-fill both -expand 1' so that the canvas can be enlarged by enlarging ## the window. ## If you want to make the window un-resizable, ## you can use the following statement. # wm resizable . 0 0 ##+#################################################################### ## Set a TEXT-ARRAY to hold text for buttons & labels on the GUI. ## NOTE: This can aid INTERNATIONALIZATION. This array can ## be set according to a nation/region parameter. ##+#################################################################### ## if { "$VARlocale" == "en"} ## For the 'fRbuttons' frame: set aRtext(buttonEXIT) "Exit" set aRtext(buttonHELP) "Help" set aRtext(buttonREDRAW) "ReDraw" set aRtext(buttonCOLOR1) "Primes Color" set aRtext(buttonCOLOR2) "Non-Primes Color" set aRtext(buttonSHOWPRIMES) "Show Primes MxN Table" set aRtext(buttonSHOWPRIMSEP) "Show Primes Separation List" set aRtext(buttonSHOWPIFUNC) "Show pi(n) (#primes < n)" ## For the 'fRimgsize' frame: set aRtext(labelXmaxPx) "Image size Xpixels:" set aRtext(labelYmaxPx) " Ypixels:" ## END OF if { "$VARlocale" == "en"} ##+################################################################ ## DEFINE *ALL* THE FRAMES: ## ## Top-level : 'fRbuttons' 'fRimgsize' 'fRstatus' 'fRcan' ## ## Sub-frames: none ##+################################################################ ## FOR TESTING change 0 to 1: ## (Example1: To see appearance of frames when borders are drawn.) ## (Example2: To see sizes of frames for various '-fill' options.) ## (Example3: To see how frames expand as window is resized.) if {0} { set RELIEF_frame raised set BDwidthPx_frame 2 } else { set RELIEF_frame flat set BDwidthPx_frame 0 } frame .fRbuttons -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRimgsize -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRstatus -relief $RELIEF_frame -borderwidth $BDwidthPx_frame frame .fRcan -relief $RELIEF_frame -borderwidth $BDwidthPx_frame ##+############################## ## PACK the top-level FRAMES. ##+############################## pack .fRbuttons \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRimgsize \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRstatus \ -side top \ -anchor nw \ -fill x \ -expand 0 pack .fRcan \ -side top \ -anchor nw \ -fill both \ -expand 1 ##+######################################################### ## OK. Now we are ready to define the widgets in the frames. ##+######################################################### ##+##################################################################### ## In the '.fRbuttons' FRAME --- DEFINE ## - Exit, Help, ReDraw buttons, ## and ## - 2 buttons ( to specify colors). ## Then PACK them. ##+##################################################################### button .fRbuttons.buttEXIT \ -text "$aRtext(buttonEXIT)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {exit} button .fRbuttons.buttHELP \ -text "$aRtext(buttonHELP)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -command {popup_msgVarWithScroll .fRhelp "$HELPtext"} button .fRbuttons.buttREDRAW \ -text "$aRtext(buttonREDRAW)" \ -font fontTEMP_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -state disabled \ -command {redraw_primes} button .fRbuttons.buttCOLOR1 \ -text "$aRtext(buttonCOLOR1)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -state disabled \ -command "set_color1" button .fRbuttons.buttCOLOR2 \ -text "$aRtext(buttonCOLOR2)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -state disabled \ -command "set_color2" button .fRbuttons.buttSHOWPRIMES \ -text "$aRtext(buttonSHOWPRIMES)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -state disabled \ -command "show_MxN_primes" button .fRbuttons.buttSHOWPRIMSEP \ -text "$aRtext(buttonSHOWPRIMSEP)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -state disabled \ -command "show_primes_separation" button .fRbuttons.buttSHOWPIFUNC \ -text "$aRtext(buttonSHOWPIFUNC)" \ -font fontTEMP_SMALL_varwidth \ -padx $PADXpx_button \ -pady $PADYpx_button \ -relief raised \ -bd $BDwidthPx_button \ -state disabled \ -command "show_pi_function" ##+########################################### ## Pack the widgets in the 'fRbuttons' frame. ##+########################################### pack .fRbuttons.buttEXIT \ .fRbuttons.buttHELP \ .fRbuttons.buttREDRAW \ .fRbuttons.buttCOLOR1 \ .fRbuttons.buttCOLOR2 \ .fRbuttons.buttSHOWPRIMES \ .fRbuttons.buttSHOWPRIMSEP \ .fRbuttons.buttSHOWPIFUNC \ -side left \ -anchor w \ -fill none \ -expand 0 ##+################################################################## ## In the '.fRimgsize' FRAME ---- DEFINE ## 1 LABEL and 1 SCALE widget for Xmax and ## 1 LABEL and 1 SCALE widget for Ymax. ## Then PACK the widgets. ##+################################################################### label .fRimgsize.labelXmaxPx \ -text "$aRtext(labelXmaxPx)" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief $RELIEF_label \ -bd $BDwidthPx_label ## Set this widget var in the 'Additional GUI Initialization' ## section at the bottom of this script. # set XmaxPx 500 scale .fRimgsize.scaleXmaxPx \ -from 1 -to $Mmax \ -resolution 1 \ -bigincrement 10 \ -repeatdelay $scaleRepeatDelayMillisecs \ -length $scaleLengthPx \ -font fontTEMP_varwidth \ -variable XmaxPx \ -showvalue true \ -orient horizontal \ -bd $BDwidthPx_scale \ -width $scaleThicknessPx pack .fRimgsize.labelXmaxPx \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRimgsize.scaleXmaxPx \ -side left \ -anchor w \ -fill x \ -expand 0 ## DEFINE LABEL-and-SCALE pair for YmaxPx. label .fRimgsize.labelYmaxPx \ -text "$aRtext(labelYmaxPx)" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief $RELIEF_label \ -bd $BDwidthPx_label ## Set this widget var in the 'Additional GUI Initialization' ## section at the bottom of this script. # set YmaxPx 400 scale .fRimgsize.scaleYmaxPx \ -from 1 -to $Nmax \ -resolution 1 \ -bigincrement 1 \ -repeatdelay $scaleRepeatDelayMillisecs \ -length $scaleLengthPx \ -font fontTEMP_varwidth \ -variable YmaxPx \ -showvalue true \ -orient horizontal \ -bd $BDwidthPx_scale \ -width $scaleThicknessPx pack .fRimgsize.labelYmaxPx \ -side left \ -anchor w \ -fill none \ -expand 0 pack .fRimgsize.scaleYmaxPx \ -side left \ -anchor w \ -fill x \ -expand 0 ##+##################################################################### ## In the '.fRstatus' FRAME --- DEFINE ## a LABEL widget, to show status messages, like elapsed time for ## a redraw --- and 'processing in progress' messages. ## Then PACK the widget. ##+##################################################################### label .fRstatus.labelSTATUS \ -text "" \ -font fontTEMP_SMALL_varwidth \ -justify left \ -anchor w \ -relief raised \ -bg "#66FF66" \ -bd $BDwidthPx_label ##+########################################### ## Pack the widget in the 'fRstatus' frame. ##+########################################### pack .fRstatus.labelSTATUS \ -side left \ -anchor w \ -fill x \ -expand 1 ##+###################################################### ## In the '.fRcan' FRAME - ## DEFINE the 'canvas' widget and its 2 scrollbars. ## Then PACK these 3 widgets. ##+###################################################### ## We highlightthickness & borderwidth of the canvas to ## zero, as suggested on page 558, Chapter 37, 'The Canvas ## Widget', in the 4th edition of the book 'Practical ## Programming in Tcl and Tk'. ##+###################################################### canvas .fRcan.can \ -width $initCanWidthPx \ -height $initCanHeightPx \ -relief flat \ -highlightthickness 0 \ -borderwidth 0 \ -yscrollcommand ".fRcan.scrolly set" \ -xscrollcommand ".fRcan.scrollx set" scrollbar .fRcan.scrolly \ -orient vertical \ -command ".fRcan.can yview" scrollbar .fRcan.scrollx \ -orient horizontal \ -command ".fRcan.can xview" ##+####################################################### ## PACK the widgets in frame '.fRcan'. ## ## NOTE: ## NEED TO PACK THE SCROLLBARS BEFORE THE CANVAS WIDGET. ## OTHERWISE THE CANVAS WIDGET TAKES ALL THE FRAME SPACE. ##+####################################################### pack .fRcan.scrolly \ -side right \ -anchor e \ -fill y \ -expand 0 pack .fRcan.scrollx \ -side bottom \ -anchor s \ -fill x \ -expand 0 ## !!!NEED TO USE '-expand 0' FOR THE X AND Y SCROLLBARS, so that ## the canvas is allowed to fill the remaining frame-space nicely ## --- without a gap between the canvas and its scrollbars. pack .fRcan.can \ -side top \ -anchor nw \ -fill both \ -expand 1 ##+######################################## ## END OF the DEFINITION OF THE GUI WIDGETS ##+######################################## ##+############################### ## BINDINGS SECTION: ##+###################################################################### ## None. We offer the 'ReDraw' button so the user can control when ## a redraw is done --- rather than doing an automatic redraw, ## for example, when the user alters either of the image size dimensions ## via the 2 'scale' widgets. ##+###################################################################### ## We could put a button1-release binding on the canvas to show ## the info for a particular pixel --- such as which integer the pixel ## represents, whether it is a prime --- and even more, such as ## a (prime) factorization of the integer if it is not prime. ##+###################################################################### ##+###################################################################### ## PROCS SECTION: ## ## - 'load_primes_sieve_array' - to load an array with zeros and ones ## indicating whether the integer index of the ## array is a non-prime or a prime. ## Called once in the 'Additional GUI Initialization' ## section at the bottom of this script. ## ## - 'redraw_primes' - to clear the image structure (if any) and ## create a new image structure according to the ## current width and height of the canvas widget --- ## and then draw the on/off (colored) pixels in the ## rectangular image structure on the canvas. ## Called by the 'ReDraw' button. ## ## - 'set_color1' - shows a color selector GUI and uses the ## user-selected color-1 to do a redraw ## of the 'primes image' on the canvas. ## Called by the color1 button. ## ## - 'set_color2' - shows a color selector GUI and uses the ## user-selected color-2 to do a redraw ## of the 'primes image' on the canvas. ## Called by the color2 button. ## ## - 'update_colors_label' - updates the color and the text in ## either of the 2 color buttons. The text ## shows hex values of the current color1 ## or color2 settings. ## Called by the 'set_color*' procs. ## ## - 'show_MxN_primes' - shows a rows and columns table of integers ## with the primes indicated. ## Called by the 'Show MxN Primes' button. ## ## - 'popup_msgVarWithScroll' - reports help or other info (such a list of ## prime numbers) to the user. ## Called by the Help button. ## ##+####################################################################### ##+###################################################################### ## proc load_primes_sieve_array ## ## PURPOSE: To load an array 'parray' with zeros and ones ## indicating whether the integer index of the ## array is a non-prime or a prime. ## ## METHOD: Uses the hard-coded scale-limit variables, Mmax and Nmax, ## to set the size of the 1-dimensional array to MN = ## Mmax times Nmax. ## ## Uses the Erathosthenes sieve method to set the values ## of the array to zeros or ones, where the index of the ## array is integers, from 1 to MN: ## One for a prime index; zero for a non-prime. ## ## CALLED BY: The 'Additional GUI Initialization' section at the ## bottom of this script. ##+##################################################################### proc load_primes_sieve_array {} { global parray Mmax Nmax ################################################## ## Set the current time, for determining elapsed ## time for building the array. ################################################## set t0 [clock milliseconds] ################################################### ## Set the size of the 1-dimensional array, parray. ################################################### set MN [expr {$Mmax * $Nmax}] ################################################## ## Initialize the parray to all ones, where one ## is the indicator of a prime. ################################################## for {set i 1} {$i <= $MN} {incr i} { set parray($i) 1 } ## END OF parray initialization ################################################## ## Set the limit on the size of the primes we will ## use in performing the sieve operation. ################################################## set LIM [expr { int( sqrt($MN) ) }] ## FOR TESTING: # puts "proc 'load_primes_sieve_array' > Finding primes based on:" # puts " Mmax: $Mmax Nmax: $Nmax MN: $MN LIM: $LIM" ################################################################## ## We let the index of the 'parray' be integers starting at one ## and increasing. We set the first element of the array, rather ## arbitrarily, to zero. ## ## Historically, the integer one was orginally considered to be a ## prime. Around the 1800's, it was decided that 1 should not ## be considered to be a prime, for various reasons. For example, ## you cannot claim that each integer has a unique factorization ## into primes if you allow 1 to be prime, because you could ## and make an infinite number of factorizations of each integer ## by allowing 1,2,3,... factors of 1 to make many factorizations ## of any integer into primes. ## ## Recall that we assume that the index of the array is the integer ## that we are determining to be prime (one) or non-prime (zero). ################################################################# set parray(1) 0 ################################################################# ## Set the initial prime to use in the sieve operation. ## This variable will also hold the index to the last prime ## that we used to complete a 'sieve-sweep'. ################################################################# set nextPrime 2 ################################################################# ## Build the set of one's and zero's in array 'parray' --- ## in a 'while' loop. Since we initialized the array to all ones, ## we just need to set the array to zero whenever an index is ## NOT prime. ################################################################# while {$nextPrime <= $LIM} { ##################################################################### ## For the current value of 'nextPrime', for each integer-index ## that is a multiple of 'nextPrime', set the 'parray' to zero at ## that index (indicating a non-prime) --- using another 'while' loop. ##################################################################### set i [expr {$nextPrime + $nextPrime}] while {$i <= $MN} { set parray($i) 0 set i [expr {$i + $nextPrime}] } ## END OF i-loop to set parray values to zero whenever the ## array index has the current 'nextPrime' value as a factor. ## FOR TESTING: # puts "proc 'load_primes_sieve_array' > For prime $nextPrime, some loaded array values:" # puts " parray($nextPrime): $parray($nextPrime)" # puts " parray([expr {$nextPrime + 1}]): $parray([expr {$nextPrime + 1}])" ################################################################ ## Get 'nextPrime'. ## It should be the next index for which the parray has value one, ## rather than zero. ################################################################ set prevPrime $nextPrime for {set j [expr {$nextPrime + 1}]} {$j <= $MN} {incr j} { if {$parray($j) == 1} { set nextPrime $j } ## END OF check whether $j is the next prime ########################################## ## Exit this loop when we find the prime. ########################################## if {$nextPrime > $prevPrime} {break} } ## END OF j-loop to get 'nextPrime' ############################################################## ## FOR TESTING: (un-comment the following 'puts' statement) ## The primes printed out by this statement have been verified ## by the list of the 1st 1,000 primes at ## http://primes.utm.edu/lists/small/1000.txt. ############################################################## # puts "Found NEXT prime $nextPrime" ######################################################### ## NOTE: ## We could put code here (and above) to write out each ## prime found to a text-variable and show the ## text variable at the bottom of this proc by using ## the 'popup_msgVarWithScroll' proc. ######################################################### ## Assure that we exit this loop. if {$nextPrime > $LIM} {break} } ## END OF the 'while {$nextPrime <= $LIM}' sieve loop ###################################################### ## Put the array-creation-time in the status label. ## We use 'update' to make sure this info is 'posted'. ###################################################### .fRstatus.labelSTATUS configure -text \ "$MN integers classified as primes and non-primes. TIME TAKEN: [expr {[clock milliseconds] - $t0}] millisecs elapsed." update ################################################################### ## FOR TESTING: (Set the 0 to 1 in the 'if {0}' statement, to show the primes.) ## The numbers printed out have been verified by looking at ## the primes listed at http://www.naturalnumbers.org/P-100000.txt ## --- which is a link from the page http://www.naturalnumbers.org/primes.html. ## The link shows the 1st 100,000 primes, between 1 and 1,299,709. ################################################################### if {0} { set primesSTR "" set primesCNT 0 for {set j 1} {$j <= $MN} {incr j} { if {$parray($j) == 1} { set primesSTR "$primesSTR $j" incr primesCNT } } puts "Found the following $primesCNT primes, from 1 to $MN :" puts "$primesSTR" puts "Found $primesCNT primes, from 1 to $MN ." } ## END OF 'puts' display of the primes found. } ## END OF proc 'load_primes_sieve_array' ##+##################################################################### ## proc redraw_primes ## ## PURPOSE: ## Draws the 'primes image' in an image structure on the canvas, ## using the 2 user-specified colors. ## ## METHOD: Clears the image structure (if any) and ## creates a new image structure according to the ## current width and height requested for the image via ## the XmaxPx and YmaxPx. ## Then draws the on/off (colored) pixels in the ## rectangular image structure on the canvas. ## ## This proc may do the draw a horizontal scan-line at a time, ## with calls like: ## imgID put $hexcolorsLIST -to 0 $y ## where 0 $y is the leftmost position of a horizontal line of ## hexcolors for the pixels. ## ## CALLED BY: The 'Additional GUI Initialization' section at the ## bottom of this script --- and, perhaps, by the ## two set-color procs. ##+##################################################################### proc redraw_primes {} { global parray COLOR1hex COLOR2hex XmaxPx YmaxPx ## FOR TESTING: # puts "proc 'redraw_primes' > Some loaded array values:" # puts " parray(1): $parray(1)" # puts " parray(2): $parray(2)" # puts " parray(3): $parray(3)" # puts " parray(4): $parray(4)" # puts " parray(5): $parray(5)" ######################################################################### ## Delete the current image structure. ## We especially need to do this after a new image-size has been requested, ## so that we can redraw the image according to the new requested size. ######################################################################### catch {image delete imgID} ########################################################## ## Put a 'processing in progress' msg in the status label. ########################################################## .fRstatus.labelSTATUS configure -text "\ Building $XmaxPx x $YmaxPx Image. PROCESSING IN PROGRESS. Please wait ..." update ################################################### ## Set the current time, for determining elapsed ## time for building the 'photo' image. ################################################### set t0 [clock milliseconds] ######################################################################### ## Initialize the width & height of the image that we are going to create ## --- to the requested image-size. ######################################################################### set imgWidthPx $XmaxPx set imgHeightPx $YmaxPx ################################## ## Make the new image structure. ################################## image create photo imgID -width $imgWidthPx -height $imgHeightPx ################################## ## Put the image on the canvas. ################################## .fRcan.can create image 0 0 -anchor nw -image imgID ############################################################ ## Set the 'scrollregion' of the canvas according to the ## requested image size. (A simple 'update' does not work.) ############################################################ .fRcan.can configure -scrollregion "0 0 $imgWidthPx $imgHeightPx" ############################################################# ## We use a 'wm geometry' command to get the window to resize ## appropriately --- even after the user has manually resized ## the top window. ## ## Reference: wiki.tcl.tk/10720 and wiki.tcl.tk/44 ## and page 237 of Ousterhout's book 'Tcl and the Tk Toolkit': ## "If you would like to restore a window to its natural ## size, you can invoke 'wm geometry' with an empty ## geometry string." ############################################################# wm geometry . {} ############################################################## ## HERE IS WHERE WE DRAW THE NEW IMAGE: ## In a double-loop over the image height and image width, ## draw each row of the image, using the 'parray' to determine ## the color to set each pixel in a given row of pixels. ############################################################## ## We allow the y-variable to go from 0 to imgHieghtPx minus 1. ## We allow the x-variable to go from 0 to imgWidthPx minus 1. ############################################################## ## We now draw the image --- by horizontal scan-lines. ## ## For each y (going from the top of the image area to the bottom), ## we set the colors in the horizontal scan-lines. ## ## In more detail: ## We iterate from the top of the image yPx=0 up to the bottom of the image ## yPx=img-height, and then iterate over xPx going from the left of the ## image xPx=0 up to the right of the image xPx=image-width. ## ## We build horizontal scanline at height $yPx by building a color-list ## in which we set a pixel color at the $xPx-th entry of the list to ## color1 if parray($k) is one, and set the color at $i to color2 if ## parray($k) is zero, where k = ($yPx * $imgWidthPx) + $xPx + 1. ## ## We 'put' the list of colors on the image structure, with its ## 'left-location' at 0 $yPx. #################################################################### for {set yPx 0} {$yPx < $imgHeightPx} {incr yPx} { ########################################################### ## Reset the string-vars for the next horizontal scanline. ## (We could use a list here instead of a string. ## We could initiate the list with the 'lappend' command. ## "You can call 'lappend' with the name of an undefined ## variable and the variable will be created." ## We could use 'unset' to make sure we can re-use the ## same list name over and over. Example: ## unset scanlineLIST ## lappend scanlineLIST ) ########################################################## set hexcolorsSTR "" ############################################################### ## We iterate over the pixels of the next horizontal scan-line. ############################################################### for {set xPx 0} {$xPx < $imgWidthPx} {incr xPx} { ############################################### ## Set the appropriate hexcolor for this pixel. ############################################### set idx [expr {($yPx * $imgWidthPx) + $xPx + 1}] if {$parray($idx) == 1} { set hexcolor $COLOR1hex } else { set hexcolor $COLOR2hex } ############################################################## ## Add the appropriate hexcolor for this pixel to the scanline ## string. ## (We can use the string command 'append' to do this efficiently. ## "The 'append' command provides an efficient way to add ## items to the end of a string. It modifies a variable ## directly so it can exploit the memory allocation scheme ## used internally by Tcl.") ############################################################### ## Less efficient: # set hexcolorsSTR "$hexcolorsSTR $hexcolor" append hexcolorsSTR " $hexcolor" ## FOR TESTING: # if {$xPx == 5} { # puts "redraw_primes > xPx: $xPx yPx: $yPx hexcolor: $hexcolor" # } } ## END OF xPx loop ################################################################# ## Make a list from the color string. ## (We could eliminate this statement if we used a list variable ## instead of a string variable to build the scanlines.) ################################################################# set scanlineLIST [list $hexcolorsSTR] #################################### ## Draw the scanline at height $yPx. #################################### imgID put $scanlineLIST -to 0 $yPx ## FOR TESTING: (show the progress after drawing each horizontal ## scanline for a yPx value) # update } ## END OF yPx loop ## FOR TESTING: (put a horizontal swath of color on each scanline) # imgID put [list {#888888 #888888 #888888 #888888 #888888} ] -to 0 $yPx] ## FOR TESTING: # puts "redraw_primes > hexcolorsSTR: $hexcolorsSTR" ############################################################# ## Put the image size (rows,cols of pixels) and the draw-time ## in the status label. ############################################################# .fRstatus.labelSTATUS configure -text \ "Processing DONE on ${imgWidthPx}x$imgHeightPx pixels - width,height of canvas-image. DRAW TIME: [expr {[clock milliseconds] - $t0}] millisecs elapsed." } ## END OF proc 'redraw_primes' ##+##################################################################### ## proc 'set_color1' ##+##################################################################### ## PURPOSE: ## ## This procedure is invoked to get an RGB triplet ## via 3 RGB slider bars on the FE Color Selector GUI. ## ## Uses that RGB value to set color #1 for the image-rectangle. ## ## Arguments: none ## ## CALLED BY: .fRbuttons.buttCOLOR1 button ##+##################################################################### proc set_color1 {} { global COLOR1r COLOR1g COLOR1b COLOR1hex ColorSelectorScript ## FOR TESTING: # puts "COLOR1r: $COLOR1r" # puts "COLOR1g: $COLOR1g" # puts "COLOR1b: $COLOR1b" set TEMPrgb [ exec $ColorSelectorScript $COLOR1r $COLOR1g $COLOR1b] ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB set COLOR1hex "#$hexRGB" set COLOR1r $r255 set COLOR1g $g255 set COLOR1b $b255 ######################################################### ## Set color of color1 button and update the button text. ######################################################### update_colors_label 1 ###################################################### ## Redraw the rectangular image with the new color #1. ## ## We COULD do this so the user does not have to ## click on the 'ReDraw' button. ## INSTEAD we post the advice below. ###################################################### # redraw_primes .fRstatus.labelSTATUS configure -text \ "Click on the 'ReDraw' button when you are ready to apply color changes." } ## END OF proc 'set_color1' ##+##################################################################### ## proc 'set_color2' ##+##################################################################### ## PURPOSE: ## ## This procedure is invoked to get an RGB triplet ## via 3 RGB slider bars on the FE Color Selector GUI. ## ## Uses that RGB value to set color2 for the image rectangle. ## ## Arguments: none ## ## CALLED BY: .fRbuttons.buttCOLOR1 button ##+##################################################################### proc set_color2 {} { global COLOR2r COLOR2g COLOR2b COLOR2hex ColorSelectorScript ## FOR TESTING: # puts "COLOR2r: $COLOR2r" # puts "COLOR2g: $COLOR2g" # puts "COLOR2b: $COLOR2b" set TEMPrgb [ exec $ColorSelectorScript $COLOR2r $COLOR2g $COLOR2b] ## FOR TESTING: # puts "TEMPrgb: $TEMPrgb" if { "$TEMPrgb" == "" } { return } scan $TEMPrgb "%s %s %s %s" r255 g255 b255 hexRGB set COLOR2hex "#$hexRGB" set COLOR2r $r255 set COLOR2g $g255 set COLOR2b $b255 ########################################################## ## Set color of color2 button and update the colors label. ########################################################## update_colors_label 2 ##################################################### ## Redraw the rectangular image with the new color #2. ## ## We COULD do this so the user does not have to ## click on the 'ReDraw' button. ## INSTEAD we post the advice below. ###################################################### # redraw_primes .fRstatus.labelSTATUS configure -text \ "Click on the 'ReDraw' button when you are ready to apply color changes." } ## END OF proc 'set_color2' ##+##################################################################### ## proc 'update_colors_label' ##+##################################################################### ## PURPOSE: ## ## This proc sets the background color of one of the color buttons ## to its current color --- and sets foreground color to a ## suitable black or white color, so that the text is readable. ## ## This procedure ALSO updates the text on a color button to ## show the hex value of its current color setting. ## ## Arguments: global color vars ## ## CALLED BY: 2 colors procs: ## 'set_color1' ## 'set_color2' ## and the additional-GUI-initialization section at ## the bottom of this script. ##+##################################################################### proc update_colors_label {buttID} { global COLOR1hex COLOR1r COLOR1g COLOR1b \ COLOR2hex COLOR2r COLOR2g COLOR2b \ aRtext ################################################################ ## Set a color level to use in setting the text foreground color. ################################################################ # set colorBREAK 300 set colorBREAK 250 if {$buttID == 1} { .fRbuttons.buttCOLOR1 configure -text \ "$aRtext(buttonCOLOR1) $COLOR1hex" .fRbuttons.buttCOLOR1 configure -bg $COLOR1hex set sumCOLOR1 [expr {$COLOR1r + $COLOR1g + $COLOR1b}] if {$sumCOLOR1 > $colorBREAK} { .fRbuttons.buttCOLOR1 configure -fg "#000000" } else { .fRbuttons.buttCOLOR1 configure -fg "#f0f0f0" } } ## END OF 'if {$butID == 1}' if {$buttID == 2} { .fRbuttons.buttCOLOR2 configure -text \ "$aRtext(buttonCOLOR2) $COLOR2hex" .fRbuttons.buttCOLOR2 configure -bg $COLOR2hex set sumCOLOR2 [expr {$COLOR2r + $COLOR2g + $COLOR2b}] if {$sumCOLOR2 > $colorBREAK} { .fRbuttons.buttCOLOR2 configure -fg "#000000" } else { .fRbuttons.buttCOLOR2 configure -fg "#f0f0f0" } } ## END OF 'if {$butID == 2}' } ## END OF proc 'update_colors_label' ##+###################################################################### ## PROC: show_MxN_primes ## ## PURPOSE: Show a list of the integers in rows-and-columns --- ## with the primes indicated/highlighted. ## ## METHOD: Uses the array 'parray' with zeros and ones ## indicating whether the integer index of the ## array is a non-prime or a prime. ## ## Builds the list in a text variable and then shows ## the list in a popup window via the ## 'popup_msgVarWithScroll' proc. ## ## Uses the scale variables, XmaxPx and YmaxPx, ## to set the number of columns and rows of the table, ## respectively. ## ## To avoid rows of integers that are too long to easily ## browse, if XmaxPx is greater than a hard-coded value, ## say 40, we use that limit as the number of columns ## in the table. ## ## To avoid a massive number of rows in the table, ## if YmaxPx is greater than a hard-coded value, ## say 250, we use that limit as the number of rows ## in the table. ## ## CALLED BY: The 'Show MxN Primes' button. ##+##################################################################### proc show_MxN_primes {} { global parray XmaxPx YmaxPx ############################################################## ## Set max columns in the table. ############################################################## set COLSlimit 40 set MAXcols $XmaxPx if {$MAXcols > $COLSlimit} {set MAXcols $COLSlimit} ############################################################## ## Set max rows in the table. ############################################################## set ROWSlimit 250 set MAXrows $YmaxPx if {$MAXrows > $ROWSlimit} {set MAXrows $ROWSlimit} ############################################################## ## Set number of entries in MAXrows,MAXcols table. ############################################################## set MN [expr {$MAXcols * $MAXrows}] #################################### ## Set the heading for the table. #################################### set PRIMEStext \ "Table of integers with each prime indicated by an asterisk (*). $MAXcols columns and $MAXrows rows: ( $MN table entries ) " ############################################################## ## HERE IS WHERE WE BUILD THE TABLE: ## In a double-loop over the rows index (1 to YmaxPx) and ## the columns index (1 to XmaxPx), ## build each row of the table, using the 'parray' to determine ## which integers are primes. ############################################################## for {set y 1} {$y <= $MAXrows} {incr y} { ############################################################### ## We iterate over the column numbers. ############################################################### for {set x 1} {$x <= $MAXcols} {incr x} { ############################################### ## Set the appropriate index in array 'parray' ## for the current row and column. ############################################### set idx [expr {( ($y - 1) * $MAXcols) + $x}] ############################################### ## Set the prime marker variable if ## parray($idx) is equal to one. ############################################### if {$parray($idx) == 1} { set PRIMEmarker "*" } else { set PRIMEmarker " " } ############################################### ## Add the integer, with prime marker, to the ## table row. ############################################### set idxFMTED [format "%+7s" $idx] append PRIMEStext " $idxFMTED$PRIMEmarker" } ## END OF x loop (over column numbers) ####################################### ## Add a line-feed to the current row. ####################################### append PRIMEStext "\n" } ## END OF y loop (over row numbers) ###################################################### ## Add columns & rows limit info below the table. ###################################################### append PRIMEStext " You can limit the number of columns and rows in the table by using the X and Y 'scale' widgets on the GUI --- which are used to control the size of the image that is built at any 'ReDraw'. However, if the X-limit is large, to avoid an extremely WIDE table, the number of columns is limited to $COLSlimit. You can put even fewer COLUMNS in the table by using a low value of the X-scale widget, like 6. To avoid an extremely TALL table, the total number of rows in the table is limited to $ROWSlimit. You can put even fewer ROWS in the table by using a low value of the Y-scale widget, like 10.\n" ########################################## ## Show the table. ########################################## popup_msgVarWithScroll .fRprimesTable "$PRIMEStext" } ## END OF proc 'show_MxN_primes' ##+###################################################################### ## PROC: show_primes_separation ## ## PURPOSE: Show a list of the primes, in a single column, ## showing the the difference of each prime from the ## previous prime --- along with a count of the number ## of each prime. ## ## METHOD: Uses the array 'parray' with zeros and ones ## indicating whether the integer index of the ## array is a non-prime or a prime. ## ## Builds the list in a text variable and then shows ## the list in a popup window via the ## 'popup_msgVarWithScroll' proc. ## ## Uses the product of the 2 scale variables, ## MN = XmaxPx * YmaxPx, to set the number of primes ## to list. ## ## To avoid a massively long list in the text variable, ## we limit the number of primes in the list to a ## hard-coded value, say 10,000. ## ## Since each line of 3 integers is about 20 chars long, ## a list of 10,000 lines would take about 200KB of ## computer memory. ## ## CALLED BY: The 'Show Primes Separation List' button. ##+##################################################################### proc show_primes_separation {} { global parray XmaxPx YmaxPx ############################################################## ## Set max lines (primes) in the list. ############################################################## set MAXprimes 10000 ############################################################## ## Set the number-of-prime-lines to build according to the ## product XmaxPx * YmaxPx. ############################################################## set NUMlines [expr {$XmaxPx * $YmaxPx}] if {$NUMlines > $MAXprimes} {set NUMlines $MAXprimes} #################################### ## Set the heading for the list. #################################### set PRIMEStext \ "List of primes --- with the separation of each prime from the previous prime. (preceded by a count of the number of each prime). N for the Prime Separation from Nth prime number previous prime --------- --------- --------------- " ############################################################## ## Initialize the prime-count variable and add the first line ## of the list to the text variable. ############################################################## set CNTprimes 1 set cntFMTED [format "%+9s" $CNTprimes] set primeFMTED [format "%+9s" 2] append PRIMEStext "$cntFMTED $primeFMTED\n" set PREVprime 2 ######################################################## ## Initialize a variable to collect the max separation, ## to report at the bottom of the list. ######################################################## set MAXsep 1 ############################################################## ## HERE IS WHERE WE BUILD THE LIST: ## In a single-loop over the integer index of array 'parray', ## add lines to the list using the 'parray' to determine which ## integers are primes. ############################################################## set idx 2 while {1} { incr idx ############################################### ## If parray($idx) is equal to one, build ## and add the next prime-line to the list. ############################################### if {$parray($idx) == 1} { incr CNTprimes set cntFMTED [format "%+9s" $CNTprimes] set CURprime $idx set primeFMTED [format "%+9s" $CURprime] set DIFF [expr {$CURprime - $PREVprime}] set diffFMTED [format "%+9s" $DIFF] append PRIMEStext "$cntFMTED $primeFMTED $diffFMTED\n" set PREVprime $CURprime ## Check that the MAXsep variable is set properly. if {$DIFF > $MAXsep} {set MAXsep $DIFF} } ## If the NUMlines limit is reached, break out of this ## 'while' loop. if {$CNTprimes >= $NUMlines} {break} } ## END OF idx loop (over the array 'parray') #################################### ## Add MAXsep to bottom of the list. #################################### set maxsepFMTED [format "%+9s" $MAXsep] append PRIMEStext "\nMaximum separation above: $maxsepFMTED\n" ###################################################### ## Add rows limit info below the table. ###################################################### append PRIMEStext " --- To avoid an extremely TALL list, the total number of lines of primes in the list is limited to $MAXprimes. However you can limit the number of lines even further by using a low value of the X-scale and the Y-scale widgets. The lines-limit is the product of those two integer values. For example, if you set the X-pixels limit to 6 and the Y-pixels limit to 10, the lines-limit will be 60.\n" ####################################### ## Add usage info to bottom of the list. ####################################### append PRIMEStext " --- With a mouse, you can highlight the lines above and paste them into a text editor window. Then you can use features of the text editor on the list --- and can save that text into a file.\n" ########################################## ## Show the list. ########################################## popup_msgVarWithScroll .fRprimesSep "$PRIMEStext" } ## END OF proc 'show_primes_separation' ##+###################################################################### ## PROC: show_pi_function ## ## PURPOSE: Show a list of the pi(n) function, which for each postive ## integer n gives the number of primes less than n. ## ## Each line of the list consists of 2 integers --- ## n and pi(n). ## ## METHOD: Uses the array 'parray' with zeros and ones ## indicating whether the integer index of the ## array is a non-prime or a prime. ## ## Builds the list in a text variable and then shows ## the list in a popup window via the ## 'popup_msgVarWithScroll' proc. ## ## Uses the product of the 2 scale variables, ## MN = XmaxPx * YmaxPx, to set the number of integers ## to list. ## ## To avoid a massively long list in the text variable, ## we limit the number of primes in the list to a ## hard-coded value, say 20,000. ## ## Since each line of 2 integers is about 16 chars long, ## a list of 20,000 lines would take about 320KB of ## computer memory. ## ## CALLED BY: The 'Show pi(n)' button. ##+##################################################################### proc show_pi_function {} { global parray XmaxPx YmaxPx ############################################################## ## Set max lines in the list. ############################################################## set MAXlines 20000 ############################################################## ## Set the number-of-lines to build according to the ## value MN = XmaxPx * YmaxPx. ############################################################## set NUMlines [expr {$XmaxPx * $YmaxPx}] if {$NUMlines > $MAXlines} {set NUMlines $MAXlines} #################################### ## Set the heading for the list. #################################### set PRIMEStext \ "List of values of the function pi(n) --- where for each postive integer n, pi(n) is the number of primes less than n. Integer n pi(n) --------- --------- ( $NUMlines lines ) " ################################################################ ## Initialize the variable that holds the current value of pi(n). ################################################################ set PIatN 0 ############################################################## ## HERE IS WHERE WE BUILD THE LIST: ## In a single-loop over the integer index of array 'parray', ## add lines to the list for each integer. ## Use the 'parray' to determine which integers are primes ## and increment the PIatN variable. ############################################################## for {set idx 1} {$idx <= $NUMlines} {incr idx} { ############################################### ## Increment PIatN if this integer is prime. ############################################### if {$parray($idx) == 1} { incr PIatN } ############################################### ## Build and add the next line to the list for ## the current integer. ############################################### set intFMTED [format "%+9s" $idx] set pinFMTED [format "%+9s" $PIatN] append PRIMEStext "$intFMTED $pinFMTED\n" } ## END OF idx loop (over the array 'parray') ###################################################### ## Add rows limit info below the table. ###################################################### append PRIMEStext " --- To avoid an extremely TALL list, the total number of lines in the list is limited to $MAXlines. However you can limit the number of lines even further by using a low value of the X-scale and the Y-scale widgets. The lines-limit is the product of those two integer values. For example, if you set the X-pixels limit to 6 and the Y-pixels limit to 10, the lines-limit will be 60.\n" ####################################### ## Add usage info to bottom of the list. ####################################### append PRIMEStext " --- With a mouse, you can highlight the lines above and paste them into a text editor window and save that text into a file. Then you can use that text file in a plot utility, such as 'gnuplot', to plot the 'pi' function.\n" ########################################## ## Show the list. ########################################## popup_msgVarWithScroll .fRprimesSep "$PRIMEStext" } ## END OF proc 'show_pi_function' ##+######################################################################## ## PROC 'popup_msgVarWithScroll' ##+######################################################################## ## PURPOSE: Report help or error conditions to the user. ## ## We do not use focus,grab,tkwait in this proc, ## because we use it to show help when the GUI is idle, ## and we may want the user to be able to keep the Help ## window open while doing some other things with the GUI ## such as putting a filename in the filename entry field ## or clicking on a radiobutton. ## ## For a similar proc with focus-grab-tkwait added, ## see the proc 'popup_msgVarWithScroll_wait' in a ## 3DterrainGeneratorExaminer Tk script. ## ## REFERENCE: page 602 of 'Practical Programming in Tcl and Tk', ## 4th edition, by Welch, Jones, Hobbs. ## ## ARGUMENTS: A toplevel frame name (such as .fRhelp or .fRerrmsg) ## and a variable holding text (many lines, if needed). ## ## CALLED BY: 'help' button ##+######################################################################## ## To have more control over the formatting of the message (esp. ## words per line), we use this 'toplevel-text' method, ## rather than the 'tk_dialog' method -- like on page 574 of the book ## by Hattie Schroeder & Mike Doyel,'Interactive Web Applications ## with Tcl/Tk', Appendix A "ED, the Tcl Code Editor". ##+######################################################################## proc popup_msgVarWithScroll { toplevName VARtext } { ## global fontTEMP_varwidth #; Not needed. 'wish' makes this global. ## global fontTEMP_fixedwidth #; Not needed. 'wish' makes this global. ## global env # bell # bell ################################################# ## Set VARwidth & VARheight from $VARtext. ################################################# ## To get VARheight, ## split at '\n' (newlines) and count 'lines'. ################################################# set VARlist [ split $VARtext "\n" ] ## For testing: # puts "VARlist: $VARlist" set VARheight [ llength $VARlist ] ## For testing: # puts "VARheight: $VARheight" ################################################# ## To get VARwidth, ## loop through the 'lines' getting length ## of each; save max. ################################################# set VARwidth 0 ############################################# ## LOOK AT EACH LINE IN THE LIST. ############################################# foreach line $VARlist { ############################################# ## Get the length of the line. ############################################# set LINEwidth [ string length $line ] if { $LINEwidth > $VARwidth } { set VARwidth $LINEwidth } } ## END OF foreach line $VARlist ## For testing: # puts "VARwidth: $VARwidth" ############################################################### ## NOTE: VARwidth works for a fixed-width font used for the ## text widget ... BUT the programmer may need to be ## careful that the contents of VARtext are all ## countable characters by the 'string length' command. ############################################################### ##################################### ## SETUP 'TOP LEVEL' HELP WINDOW. ##################################### catch {destroy $toplevName} toplevel $toplevName # wm geometry $toplevName 600x400+100+50 wm geometry $toplevName +100+50 wm title $toplevName "Note" # wm title $toplevName "Note to $env(USER)" wm iconname $toplevName "Note" ##################################### ## In the frame '$toplevName' - ## DEFINE THE TEXT WIDGET and ## its two scrollbars --- and ## DEFINE an OK BUTTON widget. ##################################### text $toplevName.text \ -wrap none \ -font fontTEMP_fixedwidth \ -width $VARwidth \ -height $VARheight \ -bg "#f0f0f0" \ -relief raised \ -bd 2 \ -yscrollcommand "$toplevName.scrolly set" \ -xscrollcommand "$toplevName.scrollx set" scrollbar $toplevName.scrolly \ -orient vertical \ -command "$toplevName.text yview" scrollbar $toplevName.scrollx \ -orient horizontal \ -command "$toplevName.text xview" button $toplevName.butt \ -text "OK" \ -font fontTEMP_varwidth \ -command "destroy $toplevName" ############################################### ## PACK *ALL* the widgets in frame '$toplevName'. ############################################### ## Pack the bottom button BEFORE the ## bottom x-scrollbar widget, pack $toplevName.butt \ -side bottom \ -anchor center \ -fill none \ -expand 0 ## Pack the scrollbars BEFORE the text widget, ## so that the text does not monopolize the space. pack $toplevName.scrolly \ -side right \ -anchor center \ -fill y \ -expand 0 ## DO NOT USE '-expand 1' HERE on the Y-scrollbar. ## THAT ALLOWS Y-SCROLLBAR TO EXPAND AND PUTS ## BLANK SPACE BETWEEN Y-SCROLLBAR & THE TEXT AREA. pack $toplevName.scrollx \ -side bottom \ -anchor center \ -fill x \ -expand 0 ## DO NOT USE '-expand 1' HERE on the X-scrollbar. ## THAT KEEPS THE TEXT AREA FROM EXPANDING. pack $toplevName.text \ -side top \ -anchor center \ -fill both \ -expand 1 ##################################### ## LOAD MSG INTO TEXT WIDGET. ##################################### ## $toplevName.text delete 1.0 end $toplevName.text insert end $VARtext $toplevName.text configure -state disabled } ## END OF PROC 'popup_msgVarWithScroll' ##+###################################################### ##+###################################################### ## End of PROC definitions. ##+###################################################### ##+###################################################### set HELPtext "\ \ \ \ \ \ ** HELP for this 'Primes Sieve' Display Utility ** ********** BACKGROUND: ********** At wiki.tcl.tk, there are some Tcl-Tk 'primes' demo scripts that show the first hundred consecutive integers (or so) in a columns-and-rows format. By use of an 'Eratosthenes sieve' technique, the prime numbers are marked (higlighted). But showing only about a hundred integers seems quite restrictive to me. I decided that I would like to see the rows-and-columns distribution of primes among about a million to 10 million integers --- that is, I wanted to see how the primes are distributed among about a million integers, in an 'overview'. In order to see a million-plus primes and non-primes at one time, I decided to show each prime and non-prime on a rectangular Tk canvas as a single pixel for each integer. I wanted to use 2 different colors --- one for the primes and one for the non-primes --- with the user having the option to choose the two colors. I decided to show the integers (pixels) in the usual fashion --- in rows, with the integers increasing from left to right. And I wanted to make the image rectangle resizable so that the user can experiment with seeing how the pattern of primes changes as one uses a different number of pixels (integers) per row. To make it easy and quick to change the image width (and height), I decided to provide 2 'scale' widgets on the GUI so that the user can specify the image size precisely. I saw in a recreational math book that if you arrange the primes into rows that are 6 columns wide, four of the columns are essentially all non-primes. In other words, all the primes are either in the first row (primes 2, 3, and 5) or in two of the 6 columns. The 2 scale widgets allow the user to PRECISELY set the image-width to a multiple of 6 pixels --- such as 6 * 10 = 60 or 6 * 100 = 600 or 6 * 80 = 480 or 6 * 120 = 720. Then the user can see that two-thirds of the one-pixel-wide columns are the non-prime color. The primes are confined to the first row of pixels or in one-third of the columns. Some examples of what I am talking about here are shown in tables of rows-and-columns of integers below --- for rows of length 6 and 12 and 7. With these goals in mind, this utility ended up with features that can be summarized as follows. ********************* THE MAIN GUI FEATURES: ********************* This Tk GUI script shows the primes and non-primes in the first M times N positive integers as colored pixels in a rectangular image area --- where - The user can specify the image area, M colmns of pixels by N rows of pixels, via 2 'scale' widgets on the GUI. - The maxiumum values on the 2 'scale' widgets --- say Mmax and Nmax --- are used to set the maximum number of integers the user can represent in the image area --- namely MN = Mmax times Nmax. (These upper limits of the 2 scales can be changed by editing this Tcl-Tk script.) - Each postive integer is represented as a single pixel in the image area. - Each prime is indicated by one color and each non-prime is indicated by another color. - The user can choose the two pixel-colors via 2 buttons on the GUI. - The increasing integers (the 'color1-or-color2 pixels') are plotted 'ROW-WISE' in an image area on the Tk GUI, where the size of the image area can be specified by the user using the 2 'scale' widgets. - The image area is shown on a scrollable Tk 'canvas' widget, with horizontal and vertical scrollbars. So the user can choose a very large image size and use the scrollbars to examine extreme edges of the image area. - Three buttons are provided by which to show 3 different types of lists of the integers or primes. (This can help examine the distribution of primes when it is hard to see what is happening with the individual pixels.) *************************** SOME OBSERVATIONS on PRIMES: *************************** --------------------- Density of the primes: --------------------- I must admit that I was rather surprised at first to see that the prime pixels were pretty evenly distributed over the entire rectangular canvas. I was expecting to see that the primes would be thinning out in the lower rows of the image, quite clearly. After some thought (and some web searches), I found that this is not so surprising after all. The density of the primes changes very gradually, even when you look at integers out beyond a million or more. When you think about how the sieve works, in the first pass, it removes all the even integers (except 2). Thus about half the integers are eliminated at the beginning. (It may not be proper to talk about half of infinity, but keep in mind that we are applying the sieve to a finite number of integers, albeit that we are using a large upper limit. So it is quite proper to say that we are eliminating essentially half the integers in the first step of the sieve operation.) Then when we eliminate the multiples of 3 (except 3 itself) in the second step, we are eliminating less than a third of the remaining integers --- because we have already eliminated 'even' multiples of 3 like 6 (=2*3) and 12 (=2*2*3) and 18 (=2*3*3) and 24 (=2*2*2*3) and on and on. And when we eliminate the multiples of 5 (except 5 itself) in the 3rd step, we are eliminating less than a fifth of the remaining integers --- because we have already eliminated multiples of 5 like 10 (=2*5) and 15 (=3*5) and 20 (=2*2*5) and 30 (=2*3*5) and on and on. And so on with 7 and 11. In fact, when we get to 11, we are eliminating less than one-eleventh of the remaining integers. We have already eliminated a 'strong majority' of the integers by casting out the multiples of 2, 3, and 5. After the first five passes of the sieve (with 2, 3, 5, 7, 11), we have cast out about 80% or more of the integers as non-prime --- and we are effectively coloring fewer and fewer pixels with the non-primes color with each succeeding step of the process. So it really should not have been so surprising that the distribution of the primes (shown as colored pixels in the rectangle of about a million or more pixels) looks like a fairly even distribution of 'prime-color' pixels throughout the rectangle --- because we are removing/coloring relatively few non-primes after the first several steps of the process. One of the show-list options allows for showing the rows-and-columns of primes and non-primes in a text table. ------------------------ Separation of the Primes: ------------------------ You can find pages on the web --- such as http://www.naturalnumbers.org/P-100000.txt --- which shows the first 100,000 primes, between 1 and 1,299,709. That listing shows that, throughout the listing, you keep seeing prime integers that are only 2, 4, 6, or 8 units apart. Here is a sample section of the listing around the primes near 713,600 : 57570, 713477, 10 57571, 713491, 14 57572, 713497, 6 57573, 713501, 4 57574, 713509, 8 57575, 713533, 24 57576, 713563, 30 57577, 713569, 6 57578, 713597, 28 57579, 713599, 2 57580, 713611, 12 57581, 713627, 16 57582, 713653, 26 57583, 713663, 10 57584, 713681, 18 57585, 713737, 56 57586, 713743, 6 57587, 713747, 4 57588, 713753, 6 57589, 713771, 18 57590, 713807, 36 57591, 713827, 20 57592, 713831, 4 57593, 713833, 2 57594, 713861, 28 57595, 713863, 2 The numbers in the middle column are the prime numbers. On the left is the count of the number of the prime --- and the number on the right is the difference of the prime from the preceding prime. So we can expect to see primes only 2, 4, 6, or 8 units apart as we go into the millions and billions. One of the show-list options allows for showing the separation of the primes, like in the sample above, but for thousands of primes. ------------------ The pi(n) function ------------------ If you look at a plot of the function pi(n) against n, where pi(n) is the number of primes less than n, it looks almost like a straight line --- but with a slight amount of curvature below and away from a straight line that is tangent to the start of the curve. So, indeed, the primes are thinning out (their density is decreasing) --- but very slowly. You can see a plot of pi(n) for the 1st 1,000 primes at http://curvebank.calstatela.edu/prime/prime.htm One of the show-list options allows for showing a list of the integer pairs --- n , pi(n) ---- for thousands of primes. --------------------- Columns of Non-Primes: --------------------- Another aspect of the distribution of the primes in the rectangle that surprised me is that there seem to be columns of non-primes in the image (vertical strips of the non-prime color, across the image) --- for certain choices of M, the number of integers displayed per row. By dragging the window into other widths, those columns of solid color turn into diagonals. And for some canvas widths, the columns and diagonals of solid color disappear altogether as the 'prime' pixels seem to be distributed pretty evenly (or randomly) throughout the rectangle. A prime numbers expert can probably explain why these phenomena occur in this type of display of the distribution of the primes --- but I am pretty sure that a rigorous technical explanation would give me a headache that I would rather avoid. ---------------------------------------------------------- Some Examples of Rows-and-Columns of Primes and Non-Primes: ---------------------------------------------------------- Following are 3 tables of integers using rows of length 6 and 12 and 7. The primes are indicated by an asterisk immediately following the prime number. See the comments below each table. ................ Rows of length 6: ................ 1 2* 3* 4 5* 6 7* 8 9 10 11* 12 13* 14 15 16 17* 18 19* 20 21 22 23* 24 25 26 27 28 29* 30 31* 32 33 34 35 36 37* 38 39 40 41* 42 43* 44 45 46 47* 48 49 50 51 52 53* 54 55 56 57 58 59* 60 61* 62 63 64 65 66 Note that there are three primes in row 1 (2, 3, and 5) --- and ALL the OTHER PRIMES are in columns 1 and 5. Note that columns 2, 4, and 6 contain only even integers --- no primes, except in the first row. And column 3 contains only multiples of three --- no primes, except in the first row. In terms of the colors for primes and non-primes, and ignoring the first row: - 4 of the 6 columns (two-thirds of the columns) will be colored non-prime. - the prime color will be located in 2 of the 6 columns (one-third of the columns) --- with some non-prime colored pixels scattered within those 2 columns. ................. Rows of length 12: ................. 1 2* 3* 4 5* 6 7* 8 9 10 11* 12 13* 14 15 16 17* 18 19* 20 21 22 23* 24 25 26 27 28 29* 30 31* 32 33 34 35 36 37* 38 39 40 41* 42 43* 44 45 46 47* 48 49 50 51 52 53* 54 55 56 57 58 59* 60 Columns 2,4,6,8,10,12 contain only even numbers --- no primes, except in the first row. Columns 3 and 9 contain only multiples of three --- no primes, except in the first row. After row 1, all the primes are confined to rows 1,5,7,11 --- where 7 = 6 + 1 and 11 = 6 + 5. In terms of the colors for primes and non-primes, and ignoring the first row: - 8 of the 12 columns (two-thirds of the columns) will be colored non-prime. - the prime color will be located in 4 of the 12 columns (one-third of the columns) --- with some non-prime colored pixels scattered within those 4 columns. ................................... Rows that are a multiple of 6 (n*6) : ................................... After row 1: For rows of length 6, 12, 18, ..., n*6, ... there are 4, 8, 12, ... , n*4 , ... columns containing only non-primes. In other words, two-thirds of the columns ( n*4 / n*6 ) contain non-primes. For those multiples-of-6 row lengths, the primes will be confined to 2, 4, 6, ..., n*2, ... columns. In other words, the primes are confined to one-third of the columns ( n*2 / n*6 ). ................ Rows of length 7: ................ 1 2* 3* 4 5* 6 7* 8 9 10 11* 12 13* 14 15 16 17* 18 19* 20 21 22 23* 24 25 26 27 28 29* 30 31* 32 33 34 35 36 37* 38 39 40 41* 42 43* 44 45 46 47* 48 49 50 51 52 53* 54 55 56 57 58 59* 60 61* 62 63 64 65 66 67* 68 69 70 Ignoring row 1: Column 7 is the only column that contains no primes --- only multiples of 7. The primes appear in diagonals across columns 1 through 6. ------ The implication from these examples is that for some choices of the number of columns of pixels in the image area, the prime-colored pixels may appear in diagonals instead of in columns. And for some choices of the number of pixels in the x-direction of the images, the primes may be scattered rather randomly across the image. For example, if you specify rows of length 877, a prime, the image looks like the primes are scattered rather randomly across the image. The primes 907 and 653 yield a similar image. But for many prime row-lengths, the prime pixels appear in diagonals. ***************************************** SOME POTENTIAL ENHANCEMENTS (to the GUI) : ***************************************** Eventually some other features may be added to this Tk script. For example: 1) The ability to show the primes and non-primes as colored 'squares' of pixels, rather than individual pixels, could be added. An entry widget could be added to the GUI in which an integer could be changed (from 1, say) to specify the number of pixels in each square. (The maximum image area, for a given Mmax and Nmax, would be very large --- but possibly manageable by using the scrollbars of the canvas, to handle many more pixels in the x and y directions.) The 'show-list' options may be a suitable alternative to making larger rows and columns, for the time being. 2) A button1-release binding could be added on the canvas widget so that the user could click on any pixel of the image and get a popup window that shows information about the corresponding integer --- such as the integer and whether the integer is a prime or a non-prime. If the integer is a non-prime, the popup window could also show the unique factorization of the non-prime into primes. This could be implemented by adding a proc that factors any given integer into primes. 3) Since the primes are never-changing, we could avoid the processing of the 'Eratosthenes sieve' by hard-coding the underlying 'primes-array' of ones and zeros. However, by having a proc to load the array allows for changing the size of the 'parray' --- which allows for showing a larger image. For example, we could add a couple of entry widgets to the GUI, so that the user can change the size of the 'primes-array' (and the upper limits of the two scale widgets), thus allowing for larger images to be used, 'on the fly', after the GUI starts up. " ##+##################################################### ##+##################################################### ## Additional GUI initialization, if needed (or wanted). ##+##################################################### ##+##################################################### ##+##################################################### ## Set the full-name of the RGB color-selector Tk script ## that may be used in procs above. ##+##################################################### ## FOR TESTING: # puts "argv0: $argv0" set DIRthisScript "[file dirname $argv0]" ## For ease of testing in a Linux/Unix terminal and located at the ## directory containing this Tk script. Set the full directory name. if {"$DIRthisScript" == "."} { set DIRthisScript "[pwd]" } set DIRupOne "[file dirname "$DIRthisScript"]" set DIRupTwo "[file dirname "$DIRupOne"]" set ColorSelectorScript "$DIRupTwo/SELECTORtools/tkRGBselector/sho_colorvals_via_sliders3rgb.tk" ## Alternatively: Put the RGB color-selector Tk script in the ## same directory as this Tk script and uncomment the following. # set ColorSelectorScript "$DIRthisScript/sho_colorvals_via_sliders3rgb.tk" ##+############################################################# ## Initialize the 2 colors for the pixels in the 'primes image'. ##+############################################################# # set COLOR1r 255 # set COLOR1g 255 # set COLOR1b 0 set COLOR1r 255 set COLOR1g 255 set COLOR1b 255 set COLOR1hex [format "#%02X%02X%02X" $COLOR1r $COLOR1g $COLOR1b] # set COLOR2r 255 # set COLOR2g 128 # set COLOR2b 0 set COLOR2r 255 set COLOR2g 0 set COLOR2b 255 set COLOR2hex [format "#%02X%02X%02X" $COLOR2r $COLOR2g $COLOR2b] ##+######################################################### ## Set the colors (and text) on the 2 color buttons. ##+######################################################### update_colors_label 1 update_colors_label 2 ##+#################################################### ## Set initial values for the image-size 'scale' widget ## variables. ##+#################################################### # set XmaxPx 400 # set YmaxPx 400 set XmaxPx $Mmax set YmaxPx $Nmax ##+######################################################### ## Set a msg in the GUI that a primes-array is being loaded, ## and display the GUI --- using the 'update' command. ##+######################################################### set MN [expr {$XmaxPx * $YmaxPx}] .fRstatus.labelSTATUS configure -text \ "Primes sieve PROCESSING IS IN PROGRESS. $XmaxPx times $YmaxPx = $MN integers are being classified as primes and non-primes. *** PLEASE WAIT SEVERAL SECONDS ..." update ##+######################################################### ## Load the array 'parray' of ones and zeros. ##+######################################################### load_primes_sieve_array ##+######################################################### ## Initialize the canvas-image using the 'redraw_primes' proc. ## ## We could wait about 3000 millisecs after the array-load, ## so that the user has time to see the msg about how long ## the array loading took. ##+######################################################### # after 3000 redraw_primes ##+######################################################### ## Now that the array 'parray' is created and the initial ## image is displayed, activate some of the GUI buttons that ## were initially disabled. ##+######################################################### .fRbuttons.buttREDRAW configure -state normal .fRbuttons.buttCOLOR1 configure -state normal .fRbuttons.buttCOLOR2 configure -state normal .fRbuttons.buttSHOWPRIMES configure -state normal .fRbuttons.buttSHOWPRIMSEP configure -state normal .fRbuttons.buttSHOWPIFUNC configure -state normal