#
# The standard constants
#
$include "guiconst.icn"
#
# Width of one colour cell in pixels
#
$define CELL_WIDTH 30
#
# The Palette class
#
class Palette : SubMenu(
   colour,                 # Colour number selected
   palette,                # List of colours
   box_size,               # Width/height in cells
   temp_win                # Temporary window
   )
   #
   # Get the result
   #
   method get_colour()
      return palette[colour]
   end
   #
   # Set the palette list
   #
   method set_palette(l)
      box_size := integer(sqrt(*l))
      return palette := l
   end
   #
   # This is called by the toolkit; it is a convenient
   # place to initialize any sizes.
   #
   method resize()
      w := h := box_size * CELL_WIDTH + 2 * BORDER_WIDTH
   end
   #
   # Called to display the item.  The x, y coordinates
   # have been set up for us and give the top left hand
   # corner of the display.
   #
   method display()
      if /temp_win then {
         #
         # Open a temporary area for the menu and copy.
         #
         temp_win := WOpen("canvas=hidden",
                              "size=" || w || "," || h)
         CopyArea(parent_menu_bar.get_parent_win(),
            temp_win, x, y, w, h, 0, 0)
         }
      cw := Clone(parent_menu_bar.cwin)
      #
      # Clear area and draw rectangle around whole
      #
      EraseRectangle(cw, x, y, w, h)
      DrawRaisedRectangle(cw, x, y, w, h)
      #
      # Draw the colour grid.
      #
      y1 := y + BORDER_WIDTH
      e := create "fg=" || !palette
      every 1 to box_size do {
         x1 := x + BORDER_WIDTH
         every 1 to box_size do {
            WAttrib(cw, @e)
            FillRectangle(cw, x1, y1, CELL_WIDTH, CELL_WIDTH)
            x1 +:= CELL_WIDTH
            }
         y1 +:= CELL_WIDTH
         }
      Uncouple(cw)
   end
   #
   # Test whether pointer in palette_region, and if
   # so which cell it's in
   #
   method in_palette_region()
      if (x <= &x < x + w) & (y <= &y < y + h) then {
         x1 := (&x - x - BORDER_WIDTH) / CELL_WIDTH
         y1 := (&y - y - BORDER_WIDTH) / CELL_WIDTH
         return 1 + x1 + y1 * box_size
         }
   end
   #
   # Will be called if our menu is open.  We return one of three
   # codes depending on whether we have a result (SUCCEED), we
   # have a non-result, such as a mouse event outside our
   # region (FAIL_2) or neither a definite success or failure
   # (CONTINUE).
   #
   method handle_event(e)
      if i := in_palette_region() then {
         if integer(e) = (&lrelease|&rrelease|&mrelease) then {
            colour := i
            return MenuEvent(SUCCEED, e, self, 0)
            }
         }
      else {
         if integer(e) = (&lrelease | &rrelease | &mrelease |
                          &lpress | &rpress | &mpress) then
            return MenuEvent(FAIL_2)
         }
      return MenuEvent(CONTINUE)
   end
   #
   # Close this menu.
   #
   method hide()
      #
      # Restore window area.
      #
      cw := parent_menu_bar.cwin
      EraseRectangle(cw, x, y, w, h)
      CopyArea(temp_win, parent_menu_bar.get_parent_win(), 0, 0,
               w, h, x, y)
      WClose(temp_win)
      temp_win := &null
   end
initially(argv[])
   self.SubMenu.initially()
   if *argv > 0 then set_fields(argv)

   #
   # Set the image to appear on the Menu above ours.  We
   # could design a tiny icon and use that instead of the
   # standard arrow if we wished.
   #
   set_img_right(img_style("arrow_right"))

end

#
# Test class dialog.
#
class TestPalette : _Dialog(text_menu_item, palette, clos)
   method dialog_event(ev)
      if \ev.get_component() then
         case ev.get_component() of {
            palette :
               write("Colour selected : " || palette.get_colour())
            clos :
               if ev.get_code() > 0 then
                  dispose()
            }
   end
initially
   local menu_bar, menu
   self._Dialog.initially()
   attrib("size=400,200", "bg=light gray",
                    "font=sans", "resize=on")
   #
   # Create a MenuBar structure which includes our palette as a
   # submenu
   #
   menu_bar := MenuBar("pos=0,0")
   menu := Menu("label=Test")
   text_menu_item := TextMenuItem("label=Anything")
   menu.add(text_menu_item)
   palette := Palette("label=Test menu")
   palette.set_palette(["red", "green", "yellow", "black",
                        "white","purple","gray","blue","pink"])
   menu.add(palette)
   menu_bar.add(menu)
   add(menu_bar)
   #
   # Add a close button.
   #
   clos := TextButton("label=Close", "pos=50%,66%", "align=c,c")
   add(clos)
   show_modal()
end

#
# Main program entry point.
#
procedure main()
   TestPalette()
end