DIRECTORY Imager, List, Rope, ViewerClasses; PopUpButtons: CEDAR DEFINITIONS = { ROPE: TYPE = Rope.ROPE; Viewer: TYPE = ViewerClasses.Viewer; PropList: TYPE = List.AList; Class: TYPE = REF ClassPrivate; ClassPrivate: TYPE; MakeClass: PROC [spec: ClassSpec] RETURNS [class: Class]; GetSpec: PROC [class: Class] RETURNS [spec: ClassSpec]; ClassSpec: TYPE = RECORD [ classData: REF ANY _ NIL, proc: PopUpButtonProc, choices: ChoiceList _ NIL, decodeMouseButton, decodeShift, decodeControl: BOOL _ TRUE, fork: BOOL _ TRUE, guarded: BOOL _ FALSE, image: Image _ NIL, doc, disarmMsg: ROPE _ NIL ]; PopUpButtonProc: TYPE = PROC [viewer: Viewer, instanceData, classData, key: REF ANY]; ChoiceList: TYPE = LIST OF Choice; Choice: TYPE = RECORD [ key: REF ANY, doc: ROPE, image: Image _ NIL ]; nullChoice: Choice = [NIL, NIL, NIL]; Image: TYPE = REF ImagePrivate; ImagePrivate: TYPE = RECORD [ size: Imager.VEC, Draw: Drawer, data: REF ANY _ NIL ]; Drawer: TYPE = PROC [image: Image, context: Imager.Context, bounds: Imager.Rectangle, highlight, executing, guarded: BOOL]; ImageForRope: PROC [rope: ROPE, colors: Colors _ NIL, font: Imager.Font _ NIL] RETURNS [image: Image]; RopeImage: TYPE = REF RopeImagePrivate; RopeImagePrivate: TYPE = RECORD [ text: ROPE, colors: Colors, font: Imager.Font, org: Imager.VEC ]; defaultFont: Imager.Font; defaultColors, inverseColors: Colors; dontPaint: READONLY Imager.Color; Colors: TYPE = REF ColorsPrivate; ColorsPrivate: TYPE = ARRAY --button highlight--BOOL OF ARRAY --executing--BOOL OF ARRAY --guarded--BOOL OF RECORD [foreground, background: Imager.Color, strike: Imager.Color _ NIL]; Instantiate: PROC [class: Class, viewerInfo: ViewerClasses.ViewerRec _ [], instanceData: REF ANY _ NIL, image: Image _ NIL, paint: BOOL _ TRUE] RETURNS [button: Viewer]; InstanceSpec: TYPE = RECORD [ class: Class, instanceData: REF ANY, image: Image, processProps: PropList ]; GetInstanceSpec: PROC [button: Viewer] RETURNS [is: InstanceSpec]; SetImage: PROC [button: Viewer, image: Image, paint: BOOL _ TRUE]; AmbushClass: PROC [class: Class, spec: ClassSpec]; BeRope: PROC [r: ROPE] RETURNS [ROPE] = INLINE {RETURN [r]}; }. ^PopUpButtons.mesa Mike Spreitzer November 14, 1986 7:59:11 pm PST PopUpButtons are the long-discussed and anticipated attack on the problem of overloading buttons. A PopUpButton normally looks like a Button, and can decode mouse button and control and shift keys like a Button. But if the user is too slow (i.e., not fast) in hitting the button, a pop-up menu is presented. The first 12 (or 6 or 4 or 3 or 2 or 1 or 0) entries in the pop-up menu correspond to the mouse button and control/shift key decoded possibilities. Each PopUpButton is an instance of some class of PopUpButton. You must first make a class, then instantiate it. In general, a tool should make a class for every kind of button it has, and instantiate those classes at every instance of the tool. For client use. The order determines the coding; mouse button is least significant, then shift, then control. It's OK to leave these TRUE even if you don't have that many choices. For menus, the viewer field will contain the viewer containing the menu; for buttons, viewer will be the button Viewer itself. classData comes from the class, and instanceData from the instance. key indicates which choice was made. Implementation guide: the proc that calls a button proc has an ! ABORT => CONTINUE catch phrase so that the client may make use of Process.Abort to cancel execution. This is what's passed to the PopUpButtonProc to identify the choice taken. This describes this choice for the user. This doc should be short enough to fit in the message window. This doc may be NIL, but you don't want to shaft your users, do you? This specifies what's displayed in the pop-up menu. If NIL, it is taken from the key, which must then be reasonably straightforward to convert to a ROPE. If choices is non-empty, and a mouse button is held down in the button for more than a short while, a pop-up menu of the choices is created and selected from. Otherwise, the choice is taken from the choices according to the combination of mouse button, control, and shift keys used and the decoding instructions (decodeMouseButton, decodeShift, and decodeControl). Indicates a no-op. bounds describes the area to paint, in the context's current coordinate system; the caller tried to make it same as image.size; it might well be bigger; it should only be smaller if there's real trouble making it big enough. Do not assume the area has been cleared. highlight indicates the user is pointing at this image and wants it highlighted. executing is only relevent for button images; it is irrelevent and FALSE for pop-up menu entry images. guarded indicates a button image should be painted in a way so as to indicate it's guarded; NOT guarded indicates the button is not guarded or is armed; irrelevent and FALSE for pop-up menu entry images. Not called under DoSave, so please restore context's transformation upon exit; other context state variables may be changed (and of course you can't assume they have any particular value upon entry). A defaulted strike means to use the foreground color. The image used for this button is the first non-NIL one found along the following search path: the image argument to Instantiate, the image of the class being instantiated, the name of the viewer being instantiated, and the image of the first choice. If the viewerInfo.wh and ww are defaulted, aesthetic values will be chosen based on the image. Defaulting the wx and wy, with parent=NIL creates a "system" button appended after the most recent system button after the message window. Does not change size, even when image size changes. Redefines the class. Cedar trivia question #47: why is this procedure here? ΚT– "cedar" style˜code™K™/—K˜KšΟk œ#˜,K˜šΟn œœ œ˜#K˜K™ΚK˜Kšœœœ˜Kšœœ˜$Kšœ œ˜K˜Kšœœœ˜šœœ˜K™φ—K˜Kšž œœœ˜9Kšžœœœ˜7K˜šœ œœ˜šœ œœœ˜K™—Kšœ˜šœœ˜K™]—šœ/œœ˜;K™E—Kšœœœ˜Kšœ œœ˜Kšœœ˜Kšœœ˜K˜—K˜š œœœ0œœ˜UKšœ~Οcœ Ÿ`™ιK˜KšŸ¦™¦—K™Kšœ œœœ˜"šœœœ˜šœœœ˜ KšœJ™J—šœœ˜ K™­—šœ˜Kšœš™š—K˜K˜Kšœν™ν—K˜šœœœœ˜%K™—K˜Kšœœœ˜šœœœ˜Kšœ œ˜Kšžœ ˜ Kšœœœ˜K˜—K˜šœœœbœ˜{Kš Οeœn  œŽ  œI  œ_ œU  œ­™Ϊ—K˜Kš ž œœœœœœ˜fK˜Kšœ œœ˜'šœœœ˜!Kšœœ˜ K˜K˜Kšœ ˜K˜—K˜K˜Kšœ%˜%Kšœ œ˜!K˜Kšœœœ˜!šœœœŸœœœŸ œœœŸ œœœ?œ˜ΆK™5—K˜šž œœHœœœœ œœœ˜©KšŸuœ‡Ÿœ ŸΩ™ζ—K˜šœœœ˜Kšœ ˜ Kšœœœ˜Kšœ ˜ Kšœ˜K˜—K˜Kšžœœœ˜BK˜šžœœ'œœ˜BK™3—K˜šž œœ!˜2K™—K˜šžœœœœœœœ˜