; GridToolkit_11 - Library of Procedures For Drawing a Grid
; --------------
;
; In lesson 11 (User Interface Events) we added operators:
;
;   gridIndexForPos :pos    outputs the index of a cell given a POS sentence,
;                           an X,Y point in TurtleSpace
;
;   gridIndexForXY :x :y    outputs the index of a cell given X,Y coordinates
;                           in TurtleSpace
;
;   gridRowColForPos :pos   outputs a sentence of row and column numbers for
;                           a cell given a POS sentence, an X,Y point in
;                           TurtleSpace.
;
;   gridRowColForXY :x :y   outputs a sentence of row and column numbers. The
;                           row number is based on the Y coordinate input and
;                           the column number is based on the X input.
;
;   gridXtoColNum :x        outputs the column number for the given
;                           X TurtleSpace coordinate
;
;   gridYtoRowNum :y        outputs the row number for the given
;                           Y TurtleSpace coordinate


; Symbolic Constants
; -------- ---------

; SETPENCOLOR values
to black 
  output 0
  end
to white 
  output 7
  end
  
; color for a cell's background
to gridCellColor
  output white
  end

; color of grid's frame
to gridFrameColor
  output black
  end

; size of the sides of a grid cell 
to gridCellSize 
  output 40
  end 

; one-half the size of a side of a grid cell 
to gridHafCellSiz 
  output quotient gridCellSize 2
  end 

; number of columns in the grid 
to gridNumCol 
  output 8
  end 

; number of rows in the grid 
to gridNumRow 
  output 5
  end 

; number of cells in the grid 
to gridNumCells 
  output product gridNumCol gridNumRow
  end 

; height of grid in turtle steps 
to gridHeight 
  output product gridNumRow gridCellSize
  end 

; width of grid in turtle steps 
to gridWidth 
  output product gridNumCol gridCellSize
  end 

 ; X coordinate for left side of the grid 
 to gridLeftX 
   output minus product gridCellSize (quotient gridNumCol 2)
   end 

 ; X coordinate for right side of the grid 
 to gridRightX 
   output difference (sum gridLeftX gridWidth) 1
   end 

 ; Y coordinate for bottom of the grid 
 to gridBottomY 
   output minus product gridCellSize (quotient gridNumRow 2)
   end 

 ; Y coordinate for top of the grid 
 to gridTopY 
   output difference (sum gridBottomY gridHeight) 1
   end 


; Grid Procedures
; ---- ----------

; move the turtle to the top-left corner of the grid
to gridGotoTopLeft 
  penup
  setxy gridLeftX gridTopY
  end 

; move the turtle to the bottom-left corner of the cell
; specified by the index :idx
; indices start at zero for the top-left cell and increase
; left-to-right, top-to-bottom
to gridGotoCell :idx 
  gridGotoTopLeft
  setheading 180
  forward product gridCellSize (int quotient :idx gridNumCol)
  forward gridCellSize
  setheading 90
  forward product gridCellSize (remainder :idx gridNumCol)
  end 

; move the turtle to the bottom-left corner of the cell
; specified by the two-number sentence input :rowCol
; row numbers start at zero and increase to gridNumRow-1
; column numbers start at zero and increase to gridNumCol-1
to gridGotoRowColCell :rowCol 
  gridGotoTopLeft
  setheading 180
  forward product gridCellSize (first :rowCol)
  forward gridCellSize
  setheading 90
  forward product gridCellSize (last :rowCol)
  end 

; with the turtle at the bottom-left corner of
; a cell, move it to the center of the cell 
to gotoCellCtrHelper 
  setheading 90 forward gridHafCellSiz
  left 90 forward gridHafCellSiz
  end 

; move the turtle to the center of cell specified by the index :idx
; indices start at zero for the top-left cell and increase
; left-to-right, top-to-bottom
to gridGotoCellCtr :idx 
  gridGotoCell :idx
  gotoCellCtrHelper
  end 

; move the turtle to the center of the cell specified by the
; two number sentence input :rowCol
; row numbers start at zero and increase to gridNumRow-1
; column numbers start at zero and increase to gridNumCol-1
to gridGotoRowColCellCtr :rowCol 
  gridGotoRowColCell :rowCol
  gotoCellCtrHelper
  end 

; with the turtle at the center of a cell, 
; repaint the cell with a specified background color 
to fillCellHelper :color 
  setpensize gridCellSize setpencolor :color
  setheading 0 forward gridHafCellSiz 
  pendown back gridCellSize
  left 90 penup forward gridHafCellSiz
  setpensize 1 setpencolor gridFrameColor setheading 0
  pendown repeat 4 [forward gridCellSize right 90]
  end 

; draw/redraw the cell specified by the index :idx
; indices start at zero for the top-left cell and increase
; left-to-right, top-to-bottom
; the :color input specifies the cell's background color
to gridCellFill :idx :color 
  gridGotoCellCtr :idx
  fillCellHelper :color
  end 

; draw/redraw the cell specified by the two number sentence input :rowCol
; row numbers start at zero and increase to gridNumRow-1
; column numbers start at zero and increase to gridNumCol-1
; the :color input specifies the cell's background color
to gridRowColCellFill :rowCol :color 
  gridGotoRowColCellCtr :rowCol
  fillCellHelper :color
  end 

; with the turtle at the bottom-left corner of a cell, label
; the cell with a specified character in a specified color
to labelCellHelper :ch :color
  setheading 0
  setlabelheight difference gridCellSize 8
  forward 4
  right 90
  forward quotient (difference gridCellSize (labelwidth :ch)) 2
  setpencolor :color
  label :ch
  end 

; label the cell specified by the index :idx
; indices start at zero for the top-left cell and increase
; left-to-right, top-to-bottom
; the :ch input, the label, is a single character word
; the :color input specifies the character's color
to gridCellLabel :idx :ch :color 
  gridGotoCell :idx
  labelCellHelper :ch :color
  end 

; label the cell specified by by the two number sentence input :rowCol
; row numbers start at zero and increase to gridNumRow-1
; column numbers start at zero and increase to gridNumCol-1
; the :ch input, the label, is a single character word
; the :color input specifies the character's color
to gridRowColCellLabel :rowCol :ch :color 
  gridGotoRowColCell :rowCol
  labelCellHelper :ch :color
  end 


;draw the grid 
to gridPaint 
  gridGotoTopLeft
  setheading 180 forward quotient gridHeight 2 setheading 90
  setpensize gridHeight setpencolor gridCellColor
  pendown forward gridWidth
  gridGotoTopLeft
  setpensize 1 setpencolor gridFrameColor
  setheading 180 pendown
  repeat gridNumRow [fd gridCellSize lt 90 fd gridWidth bk gridWidth rt 90]
  gridGotoTopLeft
  setheading 90 pendown
  repeat gridNumCol [fd gridCellSize rt 90 fd gridHeight bk gridHeight lt 90]
  end 


; Output a column number given an X TurtleSpace coordinate
; *note* the X coordinate must be within the bounds of the grid.
to gridXtoColNum :x
  output int quotient (difference :x gridLeftX) gridCellSize
  end

; Output a row number given a Y TurtleSpace coordinate
; *note* the Y coordinate must be within the bounds of the grid.
to gridYtoRowNum :y
  output int quotient (difference gridTopY :y) gridCellSize
  end

; Output the index of a cell given a POS sentence, an X,Y point
; in TurtleSpace.
; *note* the X and Y coordinates in :pos must be within the
;        bounds of the grid.
to gridIndexForPos :pos
  output sum product (gridYtoRowNum (last :pos)) gridNumCol ~
             gridXtoColNum (first :pos)
  end

; Output the index of a cell given TurtleSpace X and Y coordinates
; *note* the X and Y coordinates must be within the bounds of the grid.  
to gridIndexForXY :x :y
  output sum (product (gridYtoRowNum :y) gridNumCol) ~
             gridXtoColNum :x  
  end

; Output a sentence of row and column numbers identifying a cell
; given a POS sentence, an X,Y point in TurtleSpace.
; *note* the X and Y coordinates in :pos must be within the
;        bounds of the grid.
to gridRowColForPos :pos
  output sentence (gridYtoRowNum (last :pos)) ~
                  (gridXtoColNum (first :pos))
  end

; Output a sentence of row and column numbers identifying a cell
; given TurtleSpace X and Y coordinates.
; *note* the X and Y coordinates must be within the bounds of the grid.
to gridRowColForXY :x :y
  output sentence (gridYtoRowNum :y) (gridXtoColNum :x)
  end