# # 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