[comp.soft-sys.andrew] moving menu items

bill@allegra.tempo.nj.att.com (Bill Schell) (10/04/90)

I'm having a small problem getting the menus for a view object I'm
writing to look the way I want.

My view is a subclass of aptv.   On the front-most menu card, I'm getting
"Save", "Switch File" and "Delete Window" menu selections from a parent
view.  I would like to move "Save" and "Switch File" to the "File" card
and "Delete Window" to the "Window" card (the front menu card is getting
too crowded).
I would also like to remove selections like  "Preview" from the "File" card as 

they don't make sense in my context.

I'm using the "bind" interface to menus and I don't see any clear way to do it.
I'm sure someone else out there has had this problem?

Thanks very much,

Bill Schell
AT&T Bell Labs, Murray Hill, NJ
bill@allegra.att.com
[An Andrew ToolKit view (a raster image) was included here, but could
not be displayed.]

nsb@THUMPER.BELLCORE.COM (Nathaniel Borenstein) (10/08/90)

I would think that you could do this using menulist_ChainAfterML to
chain your menus together in the right order.    You create your own
bind structure entries with NULL values  as appropriate to override the
ones you're getting automatically.  

For an example of this -- albeit one that is embedded in a lot of other
stuff -- look at how the sendmessage window gets rid of some of the
extra style menus.  The source is in atkams/messages/lib/sendaux.c,
around line 541 you can see where things like "Enumerate" get overridden.

Hope that helps.  Good luck.  -- Nathaniel

gk5g+@andrew.cmu.edu (Gary Keim) (10/11/90)

Excerpts from misc: 3-Oct-90 moving menu items Bill Schell@allegra.temp (743+1)

> My view is a subclass of aptv.   On the front-most menu card, I'm getting
> "Save", "Switch File" and "Delete Window" menu selections from a parent
> view.  I would like to move "Save" and "Switch File" to the "File" card
> and "Delete Window" to the "Window" card (the front menu card is getting
> too crowded).

Did you figure this out yet?  There are two steps: (1) override those
items that you want removed or moved-to-other-cards, (2) create bind
entries for those items to be moved-to-other-cards.  

The First Part

This is what Nathaniel was referring to in his message.  Just create
bind entries for those items to be moved or removed that have the same,
exact menu-string as the bind entries that you want to override. Provide
NULL values for the other bind entry fields.

The Second Part

To create bind entries for those items that you want to move to other
cards, you have to provide a routine that will be called when that item
is chosen.  How do you do that when the item you're overriding is in
another module.  Well,  first you have to load the class that you're
overriding because to get a handle on the the original call-back routine
you must make a proctable lookup.  Let's have an example:  You want to
move 'Save' to the 'File' menu card.  Let's call your aptv override foo.
 In foo__InitializeClass you make a call to 

class_Load("frame");

because the 'Save' menu item comes from the frame class.  Here is the
bind entry for 'Save' as it looks in andrew/atk/frame/framecmd.c:

    {"frame-save-file", "\030\023", 0,   "Save~20", 0,
    frame_BufferMenus, (void (*)()) frame_SaveFile, "Saves buffer
    into its current file."},

You create a bind entry like this:

    {"foo-save-file", "\030\023", 0,   "File, Save~20", 0,
    frame_BufferMenus , (void (*)()) foo_SaveFile, "Saves buffer
    into its current file."},

The only missing piece is foo_SaveFile.  Where does that come from? 
Well, this is why you load frame in foo_InitializeClass.  You must do a
lookup of the proctable entry of the name frame-save-file.  Here's how:

static void foo_SaveFile();

boolean
foo__InitializeClass( ClassID )
	struct classheader *ClassID;
{
	struct proctable_Entry *saveProcEnt = NULL;

	class_Load("frame");
	if(saveProcEnt = proctable_Lookup("frame-save-file")) {
		foo_SaveFile = proctable_GetFunction(saveProcEnt);
	}
	else {
		printf("foo: couldn't lookup proctable entry frame-save-file.\n");
		return(FALSE);
	}
	return(TRUE);
}

How does that sound?  If you have any problems just send e-mail.

Gary Keim
ATK Group

gk5g+@andrew.cmu.edu (Gary Keim) (10/11/90)

There is a small problem with my solution to the problem of moving menu
items to different cards.  I directed that you get a handle on the
original call-back routine via a proctable lookup, and then use that
routine in the overriding bind entry.  This is incorrect because then
that routine (foo_SaveFile, really frame_SaveFile) will be called with
(struct foo *) as the first argument when it expects a (struct frame *).
 So you must define your own routine to be used in the overriding bind
entry, and in that routine you must get your frame pointer from self. 
Then make the original call-back that you looked-up in
foo_InitializeClass, with the proper argument. So, here is the real code:


static void frame_SaveFile(), foo_SaveFile();
static boolean FindMyFrame();
#define Parent(v) ((v)->header.view.parent)

static void
foo_SaveFile( self, rock )
struct foo *self;
long rock;
{
	struct frame *frame = NULL;

	if(frame = frame_Enumerate(FindMyFrame,foo_GetIM(self)))
		frame_SaveFile(frame,rock);
	else
		printf("foo: could not find frame.\n");
}

static boolean
FindMyFrame( frame, im )
struct frame *frame;
long im;
{
	return((struct view*) im == Parent(frame));
}

static struct bind_Description fooBindings[]={

{"foo-save-file", "\030\023", 0,   "File, Save~20", 0, frame_BufferMenus
, (void (*)()) foo_SaveFile, "Saves buffer into its current file."},

}

boolean
foo__InitializeClass( ClassID )
	struct classheader *ClassID;
{
	struct proctable_Entry *saveProcEnt = NULL;

	class_Load("frame");
	if(saveProcEnt = proctable_Lookup("frame-save-file")) {
		frame_SaveFile = proctable_GetFunction(saveProcEnt);
	}
	else {
		printf("foo: couldn't lookup proctable entry frame-save-file.\n");
		return(FALSE);
	}
	return(TRUE);
}


Have Fun.

Gary Keim
ATK Group