Re: XForms: Menu/Callback Question...

Steve Lamont (spl@szechuan.ucsd.edu)
Mon, 6 Apr 98 18:05:59 PDT

# To subscribers of the xforms list from spl@szechuan.ucsd.edu (Steve Lamont) :

> Is it possible to bind a callback to a menu item? Right now I set a
> callback in fdesign for the menu itself and do a switch

Yes, sort of, although IMHO the API lacks the kind of generality I'd
like. The "%f" option or the fl_set_pup_itemcb() function will allow
you to set callbacks for menu items. However, all that's passed to
the callback is the item number, which makes it difficult to pass any
sort of context to the callback without having to resort to global
variables.

I've gone to the extent of writing my own menu handling function:

/*
* invoke_menu( object,
* label, handler, data, greyed, box_state, ... )
*/

void invoke_menu( FL_OBJECT *obj, char *label, ... )

{

FL_FORM *form = OBJFORM(obj);
va_list list;
int i;
int n = 1;
int on[256];
void (*handler_list[256])( FL_OBJECT *obj, void *data );
void *data[256];
Window parent = FL_ObjWin( obj );
int menu_id = fl_newpup( parent );
char menu_text[80];
static int check_box[3] = { FL_PUP_NONE, FL_PUP_BOX, FL_PUP_CHECK };
int pup_chosen;
Window root;
int x;
int y;
int width;
int height;
int border_width;
int depth;

XGetGeometry( fl_get_display(), FL_ObjWin( obj ),
&root, &x, &y, &width, &height, &border_width, &depth );

va_start( list, label );

sprintf( menu_text, "%s%%t", obj->label );
fl_addtopup( menu_id, menu_text );
do {

handler_list[n] = va_arg( list, void *);
data[n] = va_arg( list, void *);
on[n] = FL_PUP_NONE;
on[n] |= !va_arg( list, Logical ) ? FL_PUP_GRAY : 0;
on[n] |= check_box[va_arg( list, Logical )];

fl_addtopup( menu_id, label );

n++;

} while ( label = va_arg( list, char *) );

va_end( list );

for ( i = 0; i < n; i++ )
fl_setpup_mode( menu_id, i, on[i] );

fl_setpup_position( obj->x + form->x,
obj->y + form->y + obj->bw * 2 + obj->h );
fl_setpup_shadow( menu_id, True );

pup_chosen = fl_dopup( menu_id );
fl_freepup( menu_id );

if ( pup_chosen > 0 )
(*handler_list[pup_chosen])( obj, data[pup_chosen] );

}

It is invoked like

invoke_menu( menu_obj,
"item 1", handler_1, some_data_ptr, 1, 0,
"item 2", handler_2, other_data_ptr, 0, 0,
NULL );

The first item will call the callback `handler_1' with data
`some_data_ptr'. It will be active and there will be no check box.
The second itme calls `handler_2' with `other_data_ptr', however in
this invocation it is turned off and greyed out.

Since I like to construct my menus on the fly this scheme works well
for me.

spl
_________________________________________________
To unsubscribe, send the message "unsubscribe" to
xforms-request@bob.usuf2.usuhs.mil or see
http://bob.usuf2.usuhs.mil/mailserv/xforms.html
XForms Home Page: http://bragg.phys.uwm.edu/xforms
List Archive: http://bob.usuf2.usuhs.mil/mailserv/list-archives/