############################################################################ # # File: button.icn # # Subject: Procedures for pushbutton sensors # # Author: Gregg M. Townsend # # Date: August 14, 1996 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # These procedures implement pushbuttons using the "evmux" event # multiplexor instead of the usual vidget library. # # button(win, label, proc, arg, x, y, w, h) # establishes a pushbutton. # # buttonrow(win,x,y,w,h,dx,dy, label,proc,arg, label,proc,arg, ...) # establishes a row of buttons. # # buttonlabel(handle, label) changes a button label. # ############################################################################ # # It is assumed that buttons do not overlap, and that fg, bg, and font # do not change beyond the initial call. These restrictions can be # accommodated if necessary by using a window clone. # # button(win, label, proc, arg, x, y, w, h) # # establishes a button of size (w,h) at (x,y) and returns a handle. # "label" is displayed as the text of the button. # When the button is pushed, proc(win, arg) is called. # # If proc is null, the label is drawn with no surrounding box, and # the button is not sensitive to mouse events. This can be used to # insert a label in a row of buttons. # # buttonlabel(handle, label) # # changes the label on a button. # # buttonrow(win,x,y,w,h,dx,dy, label,proc,arg, label,proc,arg, ...) # # establishes a row (or column) of buttons and returns a list of handles. # Every button has size (w,h) and is offset from its predecessor by # (dx,dy). # # (x,y) give the "anchor point" for the button row, which is a corner # of the first button. x specifies the left edge of that button unless # dx is negative, in which case it specifies the right edge. Similarly, # y is the top edge, or the bottom if dy is negative. # # One button is created for each argument triple of label,proc,arg. # An extra null argument is accepted to allow regularity in coding as # shown in the example below. # # If all three items of the triple are null, a half-button-sized # gap is inserted instead of a button. # # Example: # # Draw a pushbutton at (x,y) of size (w,h); # then change its label from "Slow" to "Reluctant" # When the button is pushed, call setspeed (win, -3). # # b := button (win, "Slow", setspeed, -3, x, y, w, h) # buttonlabel (b, "Reluctant") # # Make a set of buttons extending to the left from (490,10) # # blist := buttonrow(win, 490, 10, 50, 20, -60, 0, # "fast", setspeed, +3, # "med", setspeed, 0, # "slow", setspeed, -3, # ) # ############################################################################ # # Links: evmux, graphics # ############################################################################ # # Requires: Version 9 graphics # ############################################################################ # # See also: evmux.icn # ############################################################################ link evmux link graphics $define BORDER 2 # border width record Button_Rec(win, label, proc, arg, x, y, w, h) procedure button(win, label, proc, arg, x, y, w, h) local r r := Button_Rec(win, label, proc, arg, x, y, w, h) buttonlabel(r, label) if \proc then { BevelRectangle(win, x, y, w, h, BORDER) sensor(win, &lpress, Exec_Button, r, x, y, w, h) } return r end procedure buttonrow(win, x, y, w, h, dx, dy, args[]) local hlist, label, proc, arg if dx < 0 then x -:= w if dy < 0 then y -:= h hlist := [] repeat { label := get(args) | break proc := get(args) | break arg := get(args) | break if label === proc === arg === &null then { x +:= dx / 2 y +:= dy / 2 } else { put(hlist, button(win, label, proc, arg, x, y, w, h)) x +:= dx y +:= dy } } return hlist end procedure buttonlabel(r, s) r.label := s if /r.proc then EraseArea(r.win, r.x, r.y, r.w, r.h) # borderless button else EraseArea(r.win, r.x+BORDER, r.y+BORDER, r.w-2*BORDER, r.h-2*BORDER) CenterString(r.win, r.x + r.w/2, r.y + r.h/2, r.label) return end procedure Exec_Button(win, r, x, y) local e, b, t WAttrib(win, "drawop=reverse") FillRectangle(win, r.x + BORDER, r.y + BORDER, r.w - 2*BORDER, r.h -2*BORDER) BevelRectangle(win, r.x, r.y, r.w, r.h, b := -BORDER) while e := Event(win) do { x := &x y := &y case e of { &ldrag: { # drag t := (if ontarget(r, x, y) then -BORDER else BORDER) if b ~===:= t then { BevelRectangle(win, r.x, r.y, r.w, r.h, b) FillRectangle(win, r.x + BORDER, r.y + BORDER, r.w - 2*BORDER, r.h - 2*BORDER) } } &lrelease: { # release leftbutton if b < 0 then { BevelRectangle(win, r.x, r.y, r.w, r.h, BORDER) FillRectangle(win, r.x + BORDER, r.y + BORDER, r.w - 2*BORDER, r.h - 2*BORDER) WAttrib(win, "drawop=copy") r.proc(win, r.arg) } else WAttrib(win, "drawop=copy") return } } } end