; Calc.jlogo (Lesson 15 - Global Variables)
; ----------
; See: http://www.bfoit.org/itp/Globals.html#figure15_5
;      for a structure drawing.

; Global Variable Declarations
; ----------------------------

; the number displayed - just computed or being entered
global "curNum

; previous number displayed - the number that will be
; added-to, subtracted-from-by, multiplied-by, or
; divided-by :curNum
global "prevNum

; mathOp contains the math operation that is to be
; performed when "=" (or another operation key) is
; mouse-clicked on.  the words it may contain are:
; div, eql, add, mul, sub, or nop.
; nop is for no-operation is pending.
global "mathOp


; Symbolic Constant Definitions
; -----------------------------
to black
  output 0
  end 
to blue
  output 1
  end 
to red
  output 4
  end 
to white
  output 7
  end 

to east
  output 90
  end 
to south
  output 180
  end 

; text metrics - setlableheight input and associated character sizing
to chHeight
  output 21
  end 
to chWidth :ch
  output labelwidth :ch
  end 

; location and size of the calculator and its two
; basic parts: the display and the keypad
to calcLeftX
  output -100
  end 
to calcTopY
  output 125
  end 
to calcKeySiz
  output 50
  end 
to calcWidth
  output product 4 calcKeySiz
  end 
to calcDispHeight
  output 50
  end 
to calcKeysTopY
  output difference calcTopY calcDispHeight
  end 
to calcHeight
  output sum calcDispHeight (product 4 calcKeySiz)
  end 

; the following thirty (30) symbolic constants are the x,y
; coordinates of the top-left corners of the fifteen keys
to calc0LeftX
  output calcLeftX
  end 
to calc0TopY
  output difference calcKeysTopY (product 3 calcKeySiz)
  end 
to calc1LeftX
  output calcLeftX
  end 
to calc1TopY
  output difference calcKeysTopY (product 2 calcKeySiz)
  end 
to calc2LeftX
  output sum calcLeftX calcKeySiz
  end 
to calc2TopY
  output difference calcKeysTopY (product 2 calcKeySiz)
  end 
to calc3LeftX
  output sum calcLeftX (product 2 calcKeySiz)
  end 
to calc3TopY
  output difference calcKeysTopY (product 2 calcKeySiz)
  end 
to calc4LeftX
  output calcLeftX
  end 
to calc4TopY
  output difference calcKeysTopY calcKeySiz
  end 
to calc5LeftX
  output sum calcLeftX calcKeySiz
  end 
to calc5TopY
  output difference calcKeysTopY calcKeySiz
  end 
to calc6LeftX
  output sum calcLeftX (product 2 calcKeySiz)
  end 
to calc6TopY
  output difference calcKeysTopY calcKeySiz
  end 
to calc7LeftX
  output calcLeftX
  end 
to calc7TopY
  output calcKeysTopY
  end 
to calc8LeftX
  output sum calcLeftX calcKeySiz
  end 
to calc8TopY
  output calcKeysTopY
  end 
to calc9LeftX
  output sum calcLeftX (product 2 calcKeySiz)
  end 
to calc9TopY
  output calcKeysTopY
  end 
to calcDivideLeftX
  output sum calcLeftX (product 3 calcKeySiz)
  end 
to calcDivideTopY
  output calcKeysTopY
  end 
to calcEqlsLeftX
  output sum calcLeftX (product 2 calcKeySiz)
  end 
to calcEqlsTopY
  output difference calcKeysTopY (product 3 calcKeySiz)
  end 
to calcMinusLeftX
  output sum calcLeftX (product 3 calcKeySiz)
  end 
to calcMinusTopY
  output difference calcKeysTopY (product 2 calcKeySiz)
  end 
to calcPlusLeftX
  output sum calcLeftX (product 3 calcKeySiz)
  end 
to calcPlusTopY
  output difference calcKeysTopY (product 3 calcKeySiz)
  end 
to calcTimesLeftX
  output sum calcLeftX (product 3 calcKeySiz)
  end 
to calcTimesTopY
  output difference calcKeysTopY calcKeySiz
  end 

; the following ten (10) symbolic constants are for components of
; the display area, most of them are the x,y coordinates for the
; locations of the pieces of the number that is displayed.
to calcDispTextY
  output difference calcTopY sum chHeight (quotient (difference calcDispHeight chHeight) 2)
  end 
to calcDispGap
  output 8
  end 
to calcDispChWid
  output 22
  end 
to calcDisp1sX
  output difference (sum calcLeftX calcWidth) sum calcDispChWid calcDispGap
  end 
to calcDisp10sX
  output difference calcDisp1sX calcDispChWid
  end 
to calcDisp100sX
  output difference calcDisp10sX calcDispChWid
  end 
to calcDisp1000sX
  output difference calcDisp100sX calcDispChWid
  end 
to calcDisp10000sX
  output difference calcDisp1000sX calcDispChWid
  end 
to calcDisp100000sX
  output difference calcDisp10000sX calcDispChWid
  end 
to calcDisp1000000sX
  output difference calcDisp100000sX calcDispChWid
  end 


; draw the outline of a rectangle
; the top-left corner is at x,y
to drawRect :x :y :width :height
  penup setxy :x :y pendown
  setheading east
  repeat 2 [forward :width right 90 forward :height right 90]
  end 

; fill the specified rectangular area
; the top-left corner is at x,y
to fillRect :x :y :width :height
  penup setxy (sum :x (quotient :width 2)) :y pendown
  setpensize :width setheading south
  forward :height
  end 

; output TRUE if point is within specified rectangular area, otherwise FALSE
; point is a sentence, an x,y coordinate pair
; x is the left edge of the rectangular area, y is the top edge
; width and height specify its size
to inRect? :point :x :y :height :width
  if less? (first :point) :x [output "false]
  if greater? (last :point) :y [output "false]
  if greater? (first :point) sum :x (difference :width 1) [output "false]
  if less? (last :point) difference :y (difference :height 1) [output "false]
  output "true
  end 

; draw one of the keys that make up the calculator
; the input :x is the leftmost edge of the key
; the input :y is the top edge of the key
; the input :label is the single character word drawn in the key
to drawKey :x :y :label
  setpencolor black setpensize 5
  drawRect :x :y calcKeySiz calcKeySiz
  penup
  setx sum :x (quotient (difference calcKeySiz chWidth) 2)
  sety difference :y (sum chHeight (quotient (difference calcKeySiz (chHeight :label)) 2))
  setpencolor blue
  label :label
  end 

to drawKeypad
  drawKey calc0LeftX  calc0TopY "0
  drawKey calc1LeftX  calc1TopY "1
  drawKey calc2LeftX  calc2TopY "2
  drawKey calc3LeftX  calc3TopY "3
  drawKey calc4LeftX  calc4TopY "4
  drawKey calc5LeftX  calc5TopY "5
  drawKey calc6LeftX  calc6TopY "6
  drawKey calc7LeftX  calc7TopY "7
  drawKey calc8LeftX  calc8TopY "8
  drawKey calc9LeftX  calc9TopY "9
  drawKey calcDivideLeftX  calcDivideTopY "/
  drawKey calcEqlsLeftX    calcEqlsTopY   "=
  drawKey calcMinusLeftX   calcMinusTopY  "-
  drawKey calcPlusLeftX    calcPlusTopY   "+
  drawKey calcTimesLeftX   calcTimesTopY  "X
  end 

to clearDisplay
  setpencolor white
  fillRect calcLeftX calcTopY calcWidth calcDispHeight
  setpencolor black setpensize 5
  drawRect calcLeftX calcTopY calcWidth calcDispHeight
  end 

to drawChar :x :ch
  penup setxy :x calcDispTextY pendown
  setpencolor blue
  label :ch
  end 

to displayError
  clearDisplay
  drawChar calcDisp10000sX "E
  drawChar calcDisp1000sX "R
  drawChar calcDisp100sX "R
  drawChar calcDisp10sX "O
  drawChar calcDisp1sX "R
  end 

to drawMinusSign
  setc red
  penup setxy (sum calcLeftX calcDispGap) calcDispTextY pendown
  label "-
  end 

; draw a single digit (:digit) in the display area
; the :x input specifies which digit to draw.  it should be one of the
; symbolic constants: calcDisp1sX, calcDisp10sX, calcDisp100sX, etc...
to drawDigit :x :digit
  pu setxy :x calcDispTextY pd
  setpencolor blue
  label :digit
  end 


to displayCurNum
  ; need to add code to display the current number
  end 


to digit :num
  ; need to add code for when digit key clicked on
  end 

to doDivide
  ; need to add code to handle division (special case)
  end 

; perform the math operator in the mathOp global variable
; the first operand is in the prevNum global variable
; the second operand is in the curNum global variable
; the result is put into curNum and since it has changed,
; displayCurNum is invoked
to doMathOp
  ; need to add code
  end 

to equalsKey
  ; need to add code to compute new curNum
  end 

; a non-digit key was mouseclicked, either equals, minus, plus,
; quotient, or times was clicked on
; opcode contains "eql, "sub, "add, "div, or "mul, respectively
to operation :opcode
  ; need to add code
  end 

; output TRUE if the most recent mouse click was within the
; bounds of a specified calc key, otherwise it outputs FALSE
; the top-left corner of the calc key is at x,y
to mouseInKey? :x :y
  output inRect? (se mousex mousey) :x :y calcKeySiz calcKeySiz
  end 

to mouseClicked
  if mouseInKey? calc0LeftX  calc0TopY  [digit 0 stop]
  if mouseInKey? calc1LeftX  calc1TopY  [digit 1 stop]
  if mouseInKey? calc2LeftX  calc2TopY  [digit 2 stop]
  if mouseInKey? calc3LeftX  calc3TopY  [digit 3 stop]
  if mouseInKey? calc4LeftX  calc4TopY  [digit 4 stop]
  if mouseInKey? calc5LeftX  calc5TopY  [digit 5 stop]
  if mouseInKey? calc6LeftX  calc6TopY  [digit 6 stop]
  if mouseInKey? calc7LeftX  calc7TopY  [digit 7 stop]
  if mouseInKey? calc8LeftX  calc8TopY  [digit 8 stop]
  if mouseInKey? calc9LeftX  calc9TopY  [digit 9 stop]
  if mouseInKey? calcDivideLeftX calcDivideTopY  [operation "div stop]
  if mouseInKey? calcEqlsLeftX   calcEqlsTopY    [operation "eql stop]
  if mouseInKey? calcMinusLeftX  calcMinusTopY   [operation "sub stop]
  if mouseInKey? calcPlusLeftX   calcPlusTopY    [operation "add stop]
  if mouseInKey? calcTimesLeftX  calcTimesTopY   [operation "mul stop]
  end 


to main
  home clean hideturtle
  setlabelheight chHeight
  setpencolor black setpensize 5
  drawRect calcLeftX calcTopY calcWidth calcHeight
  drawKeypad
  ; ** initialize all of the global variables **
  ; ** display the current number - zero      **
  end 

main