############################################################################
#
#	File:     bitdemo.icn
#
#	Subject:  Program to demonstrate bitplanes
#
#	Author:   Gregg M. Townsend
#
#	Date:     November 14, 1994
#
############################################################################
#
#   This file is in the public domain.
#
############################################################################
#
#     bitdemo illustrates some of the techniques made available by the
#  bitplane package in the program library.
#
#     The upper rectangle is drawn using three bitplanes, reserving
#  one plane for each of the primary colors.  After clicking one of
#  the "draw" or "erase" buttons, you can draw or erase any one of
#  the bitplanes independently of the others.  Notice what happens
#  when the colors overlap.
#
#     Drawing is not constrained to the rectangle so that you can see
#  some of the possible consequences of using the bitplane routines
#  improperly.
#
#     The lower rectangle is drawn using four other bitplanes, one each
#  for the four types of objects.  Click once on a button to bring the
#  objects of that type to the front.  Click a second time to make them
#  invisible.
#
############################################################################
#
#  Requires:  Version 9 graphics
#
############################################################################
#
#  Links: button, evmux, bitplane, graphics
#
############################################################################

link button
link evmux
link bitplane
link graphics

$define BevelWidth 2
$define WindowMargin 10


global bitwin, rgbbase, panebase, panecolor


procedure main(args)
   local win, m, b, w, h, i
   local px, py, pw, ph, x, y, d, a
   local bw, bh
   local colors

   # get options and open window
   win := Window("size=800,600", "font=Helvetica,bold,14", args)

   # ensure that we can get the color map entries we will need
   bitwin := Clone(win)
   panebase := AlcPlane(bitwin, 4) | stop("can't get 4 planes")
   rgbbase := AlcPlane(bitwin, 3) | stop("can't get 3 planes")

   # get window geometry
   m := WindowMargin			# margins
   b := BevelWidth
   w := WAttrib("width") - 2 * m	# usable width
   h := WAttrib("height") - 2 * m	# usable height
   bw := 80				# button width
   bh := 24				# button height

   # establish global sensors; override later with buttons etc. in some areas
   sensor(win, &lpress, drag)
   sensor(win, &ldrag, drag)
   quitsensor(win)
   button(win, "quit", argless, exit, m, m + h - bh, bw, bh)

   # build drawing window and initialize with overlapping circles
   BevelRectangle(win, m + 100, m, w - 100, 250, -b)
   colors := [
      Bg(win), "red", "yellow", "red-yellow",
      "blue", "purple-magenta", "dark green", "dark brown"]
   every i := 0 to 7 do
      Color(bitwin, rgbbase + i, colors[i + 1])
   PlaneOp(bitwin, rgbbase, "copy")
   FillRectangle(bitwin, m + 100 + b, m + b, w - 100 - 2 * b, 250 - 2 * b)
   PlaneOp(bitwin, rgbbase+4, "set"); FillArc(bitwin, w/2-25, 100, 100, 100)
   PlaneOp(bitwin, rgbbase+2, "set"); FillArc(bitwin, w/2,     50, 100, 100)
   PlaneOp(bitwin, rgbbase+1, "set"); FillArc(bitwin, w/2+25, 100, 100, 100)
   Deplane(bitwin)

   # set up related buttons
   buttonrow(win, m, m, bw, bh, 0, bh + m,
      "draw red", draw, 1,
      "draw yel", draw, 2,
      "draw blu", draw, 4,
      &null, &null, &null,
      "erase red", erase, 1,
      "erase yel", erase, 2,
      "erase blu", erase, 4,
      )

   # set up structure for pane demo
   panecolor := table()
   panecolor[0] := Bg(win)
   px := m + 100
   py := m + 250 + 2 * m
   pw := m + w - px
   ph := m + h - py
   Fg(bitwin, panebase)
   FillRectangle(bitwin, px, py, pw, ph)
   BevelRectangle(win, px, py, pw, ph, -b)
   Clip(bitwin, px + b, py + b, pw - 2 * b, ph - 2 * b)
   buttonrow(win, m, py, bw, bh, 0, bh + m,
      "visible:", &null, &null,
      "grid", mvplane, 1,
      "curves", mvplane, 8,
      "squares", mvplane, 2,
      "circles", mvplane, 4,
      )

   # draw grid on plane 1
   FrontPlane(bitwin, panebase + 1, panecolor[1] := "light gray")
   PlaneOp(bitwin, panebase + 1, "set")
   every x := 20 to pw - 1 by 40 do
      FillRectangle(bitwin, px + x, py + b, 3, ph - 2 * b)
   every y := 20 to ph - 1 by 40 do
      FillRectangle(bitwin, px + b, py + y, pw - 2 * b, 3)

   # draw curves on plane 8
   FrontPlane(bitwin, panebase + 8, panecolor[8] := "dark blue")
   PlaneOp(bitwin, panebase + 8, "set")
   every y := 20 to ph-40 by 30 do {
      a := [bitwin]
      every put(a, px + (0 to pw+24 by 25)) do
         put(a, py + y + ?20)
      every 1 to 3 do {
         DrawCurve ! a
         every a[3 to *a by 2] +:= 1
         }
      }

   # draw squares on plane 2
   FrontPlane(bitwin, panebase + 2, panecolor[2] := "dark brown")
   PlaneOp(bitwin, panebase + 2, "set")
   d := 20
   every 1 to 50 do
      FillRectangle(bitwin, px + ?(pw - d), py + ?(ph - d), d, d)

   # draw circles on plane 4
   FrontPlane(bitwin, panebase + 4, panecolor[4] := "dark moderate green")
   PlaneOp(bitwin, panebase + 4, "set")
   every 1 to 50 do {
      d := 20 + ?10
      FillArc(bitwin, px + ?(pw - d), py + ?(ph - d), d, d)
      }

   # enter event loop
   Clip(bitwin)
   evmux(win)
end


## draw(w, v) -- set plane and drawing op in response to "draw" button

procedure draw(w, v)
   PlaneOp(bitwin, rgbbase + v, "set")
end


## erase(w, v) -- set plane and drawing op in response to "erase" button

procedure erase(w, v)
   PlaneOp(bitwin, rgbbase + v, "clear")
end


## drag(w, dummy, x, y) -- handle mouse drag by drawing (or erasing) on window

procedure drag(w, dummy, x, y)
   FillRectangle(bitwin, x - 5, y - 5, 10, 10)
end


## mvplane(w, v, x, y) -- handle click on visibility buttons
#
#  first click moves to front
#  second click makes invisible

procedure mvplane(w, v, x, y)
   static prev, rep
   initial prev := rep := 0

   if prev ~=:= v then
      rep := 0				# this is a new button
   else
      rep := (rep + 1) % 2		# repeat count for old button

   case rep of {
      0:  FrontPlane(bitwin, panebase + v, panecolor[v])
      1:  BackPlane(bitwin, panebase + v, panecolor[0])
      }
end
