\input wbuildmac.tex
\Class{XfwfPullDown}
 A PullDown button looks like a normal button, but when it is clicked
or pressed, a menu drops down. The menu can be specified in two ways:
as a string or as a widget. If a string is given, it must be in the
correct syntax for the EzMenu(3) widget and a widget will be created
automatically. If a widget is given instead, it must be a widget that
is able to pop up: in other words: a Shell widget or a subclass of
Shell.

The most likely application of this widget is as a menu in a menu bar.
A menu bar can be created, e.g., with a RowCol widget and a number of
PullDown buttons.

By default, the {\tt activateCallback} that is inherited from Button is
still called, but as soon as the button is first pressed, not only
after a click. Most applications will not need this callback.



\Publicvars
\Table{XfwfPullDown}
XtNpopup&XtCPopup&Widget &NULL \cr
XtNmenu&XtCMenu&String &NULL \cr
XtNmenuCursor&XtCMenuCursor&Cursor &"arrow"\cr
\endTable
\Section
\Publicvar{XtNpopup}
 Two resources determine the menu. The {\tt popup} resource can be
pointed at the widget that should pop up when the button is pressed,
but when the {\tt popup} resource is NULL, the menu will be created
>from the {\tt menu} resource. If the {\tt popup} resource is set, it must
be set to a widget that is (a subclass of) a Shell widget.



\HCode
\Code
Widget  popup = NULL \endCode
\endHCode


\Section
\Publicvar{XtNmenu}
 When {\tt popup} is {\tt NULL}, the widget will be created from the
textual description in {\tt menu}. For the syntax of this string, see the
EzMenu(3).



\HCode
\Code
String  menu = NULL \endCode
\endHCode


\Section
\Publicvar{XtNmenuCursor}
 The cursor shape that is used in the menu can be set with the
{\tt menuCursor} resource. By default it is an arrow pointing to the upper
right.



\HCode
\Code
Cursor  menuCursor = {\langle}String{\rangle}"arrow"\endCode
\endHCode


\Section
\Publicvar{XtNframeWidth}
 Since the most likely place for this type of button will be in a
menubar, the default frame width is reset to zero.



\HCode
\Code
 frameWidth = 0 \endCode
\endHCode


\Section
\Publicvar{XtNshrinkToFit}
 The {\tt shrinkToFit} resource is set to a new default of {\tt True}.



\HCode
\Code
 shrinkToFit = True \endCode
\endHCode


\End\Table{XfwfButton}
XtNactivateCallback&XtCActivateCallback&Callback&NULL \cr
\endTable
\Table{XfwfLabel}
XtNlabel&XtCLabel&String &NULL \cr
XtNfont&XtCFont&FontStruct&XtDefaultFont \cr
XtNforeground&XtCForeground&Pixel &XtDefaultForeground \cr
XtNalignment&XtCAlignment&Alignment &0 \cr
XtNmargin&XtCMargin&Int &2 \cr
XtNshrinkToFit&XtCShrinkToFit&Boolean &False \cr
\endTable
\Table{XfwfBoard}
XtNcursor&XtCCursor&Cursor &None \cr
XtNabs{\underline}x&XtCAbs{\underline}x&Int &0 \cr
XtNrel{\underline}x&XtCRel{\underline}x&Float &"0.0"\cr
XtNabs{\underline}y&XtCAbs{\underline}y&Int &0 \cr
XtNrel{\underline}y&XtCRel{\underline}y&Float &"0.0"\cr
XtNabs{\underline}width&XtCAbs{\underline}width&Int &0 \cr
XtNrel{\underline}width&XtCRel{\underline}width&Float &"1.0"\cr
XtNabs{\underline}height&XtCAbs{\underline}height&Int &0 \cr
XtNrel{\underline}height&XtCRel{\underline}height&Float &"1.0"\cr
XtNhunit&XtCHunit&Int &1 \cr
XtNvunit&XtCVunit&Int &1 \cr
XtNlocation&XtCLocation&String &NULL \cr
\endTable
\Table{XfwfFrame}
XtNframeType&XtCFrameType&FrameType &XfwfRaised \cr
XtNframeWidth&XtCFrameWidth&Dimension &0 \cr
XtNframeOffset&XtCFrameOffset&Dimension &0 \cr
XtNshadowScheme&XtCShadowScheme&ShadowScheme &XfwfAuto \cr
XtNlightColor&XtCLightColor&Pixel &XtDefaultBackground \cr
XtNdarkColor&XtCDarkColor&Pixel &XtDefaultForeground \cr
XtNlightStipple&XtCLightStipple&Bitmap &NULL \cr
XtNdarkStipple&XtCDarkStipple&Bitmap &NULL \cr
\endTable
\Table{XfwfCommon}
XtNhighlighted&XtCHighlighted&Boolean &False \cr
XtNselected&XtCSelected&Boolean &False \cr
XtNtext&XtCText&String &NULL \cr
XtNhandlers&XtCHandlers&Program *&NULL \cr
\endTable
\Table{Composite}
XtNchildren&XtCChildren&WidgetList &NULL \cr
insertPosition&XtCInsertPosition&XTOrderProc &NULL \cr
numChildren&XtCNumChildren&Cardinal &0 \cr
\endTable
\Table{Core}
XtNx&XtCX&Position &0 \cr
XtNy&XtCY&Position &0 \cr
XtNwidth&XtCWidth&Dimension &0 \cr
XtNheight&XtCHeight&Dimension &0 \cr
borderWidth&XtCBorderWidth&Dimension &0 \cr
XtNcolormap&XtCColormap&Colormap &NULL \cr
XtNdepth&XtCDepth&Int &0 \cr
destroyCallback&XtCDestroyCallback&XTCallbackList &NULL \cr
XtNsensitive&XtCSensitive&Boolean &True \cr
XtNtranslations&XtCTranslations&XTTranslations &NULL \cr
ancestorSensitive&XtCAncestorSensitive&Boolean &False \cr
accelerators&XtCAccelerators&XTTranslations &NULL \cr
borderColor&XtCBorderColor&Pixel &0 \cr
borderPixmap&XtCBorderPixmap&Pixmap &NULL \cr
background&XtCBackground&Pixel &0 \cr
backgroundPixmap&XtCBackgroundPixmap&Pixmap &NULL \cr
mappedWhenManaged&XtCMappedWhenManaged&Boolean &True \cr
XtNscreen&XtCScreen&Screen *&NULL \cr
\endTable
\Translations
\Section
 When the left mouse button is pressed, the {\tt activate} action is
called, which calls the {\tt activateCallback} routines, and the menu is
popped up. The rest of the interaction is presumably done by the menu
widget, which is also responsible for popping itself down again.

It is important that the {\tt activate} action is called {\em after} the
menu is popped up, since the MenuBar widget uses this callback to
change the active grab that is started by {\tt XtMenuPopup}.



\Code
{\langle}Btn1Down{\rangle}: position{\underline}menu() XtMenuPopup({\underline}menu) activate() \endCode


\Section


\Code
Button1{\langle}Enter{\rangle}: position{\underline}menu() XtMenuPopup({\underline}menu) activate() \endCode


\End\Actions
\Section
\Action{note} {\tt note} is for debugging only.



\HCode
\Code
void note({\dollar}, XEvent* event, String* params, Cardinal* num{\underline}params)
{\lbrace}
    static String Xeventname[] = {\lbrace}
	"", "", "KeyPress", "KeyRelease",
	"ButtonPress", "ButtonRelease", "MotionNotify", "EnterNotify",
	"LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose",
	"GraphicsExpose", "NoExpose", "VisisbilityNotify", "CreateNotify",
	"DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
	"ReparentNotify", "ConfigureNotify", "ConfigureRequest",
	"GravityNotify", "ResizeRequest", "CirculateNotify",
	"CirculateRequest", "PropertyNotify", "SelectionClear",
	"SelectionRequest", "SelectionNotify", "ColormapNotify",
	"ClientMessage", "MappingNotify", {\rbrace};
    (void) fprintf(stderr, "{\percent}s received {\percent}s{\backslash}n",
		   XtName({\dollar}), Xeventname[event-{\rangle}type]);
{\rbrace}\endCode
\endHCode


\Section
\Action{position{\underline}menu} The {\tt position{\underline}menu} action computes the coordinates of the menu, such
that it will appear directly below the button.



\HCode
\Code
void position{\underline}menu({\dollar}, XEvent* event, String* params, Cardinal* num{\underline}params)
{\lbrace}
    Position x, y;

    if ({\dollar}popup != NULL) {\lbrace}
	XtTranslateCoords({\dollar}, 0, {\dollar}height, {\ampersand}x, {\ampersand}y);
	XtMoveWidget({\dollar}popup, x, y);
    {\rbrace}
{\rbrace}\endCode
\endHCode


\End\Imports
\Section


\Code
{\incl} {\langle}Xfwf/EzMenu.h{\rangle}\endCode


\Section


\Code
{\incl} {\langle}stdio.h{\rangle}\endCode


\End\Methods
\Section
 Both the {\tt initialize} and {\tt set{\underline}values} methods need to create a new
menu widget, if the {\tt menu} resource is set and the {\tt popup} resource
is not. A utility function is used to do the actual work. If both
{\tt popup} and {\tt menu} are set, {\tt popup} is used and {\tt menu} is
ignored.



\Code
initialize(Widget  request, {\dollar}, ArgList  args, Cardinal * num{\underline}args)
{\lbrace}
    if ({\dollar}popup == NULL {\ampersand}{\ampersand} {\dollar}menu != NULL)
	create{\underline}menu({\dollar});
{\rbrace}\endCode


\Section
 {\tt set{\underline}values} is similar. Changes in these resources never cause a
redraw, so the method always returns {\tt False}.



\Code
Boolean  set{\underline}values(Widget  old, Widget  request, {\dollar}, ArgList  args, Cardinal * num{\underline}args)
{\lbrace}
    if ({\dollar}old{\dollar}popup != {\dollar}popup)
	XtDestroyWidget({\dollar}old{\dollar}popup);
    else if ({\dollar}old{\dollar}menu != {\dollar}menu)
	create{\underline}menu({\dollar});
    if ({\dollar}old{\dollar}menuCursor != {\dollar}menuCursor)
	if ({\dollar}popup) XtVaSetValues({\dollar}popup, XtNcursor, {\dollar}menuCursor, NULL);
    return False;
{\rbrace}\endCode


\End\Utilities
\Section
 The {\tt create{\underline}menu} routine is used to create an instance of an EzMenu
(an easy-to-use version of the Athena simple menu).



\Code
create{\underline}menu({\dollar})
{\lbrace}
    if ({\dollar}popup) XtDestroyWidget({\dollar}popup);
    {\dollar}popup = XtVaCreatePopupShell("{\underline}menu", xfwfEzMenuWidgetClass, {\dollar},
				  XtNmenu, {\dollar}menu,
				  XtNcursor, {\dollar}menuCursor, NULL);
{\rbrace}\endCode


\End\bye
