[comp.windows.x] XView: Help w/ attaching client data

warsaw@cme.nist.gov (Barry A. Warsaw) (03/15/90)

I'm trying to attach client data to PANEL_LIST type panel items in
XView, but I can't quite figure out how to set and later retrieve the
data in the notify procedure.

I'm creating the PANEL_LIST item like this:

	list = xv_create(panel, PANEL_LIST,
		PANEL_LIST_DISPLAY_ROWS,	4,
		PANEL_LIST_WIDTH,       	xv_col(panel, 20),
		PANEL_NOTIFY_PROC,      	selected_from_list,
		PANEL_CHOOSE_ONE,       	TRUE,
		PANEL_CHOOSE_NONE,      	TRUE,
		NULL);

and putting items into this list later (in a function other than the
one that creates the list):

	xv_set(list,
		PANEL_LIST_INSERT,  	0,
		PANEL_LIST_STRING,  	0, string_name,
		PANEL_LIST_CLIENT_DATA,	0, integer_value,
		NULL);

This xv_set is embedded in a function that is called an unknown number
of times, so any number of entries could be in the list.  When a
particular entry is selected, the function selected_from_list is
called as the notify proc:

	void selected_from_list(item, op, event)
	Panel_item  	item;
	Panel_list_op	op;
	Event       	*event;
		{
		...
		}

The item passed to the notify proc is *not* the PANEL_LIST item, it is
the PANEL_MESSAGE item corresponding to the entry in the list that was
selected.  The problem is that the client data is set on the
PANEL_LIST item, not the PANEL_MESSAGE item so there is no way to get
the client data inside the notify proc, without maintaining a bunch of
global variables (which defeats the purpose of using client data or
key data anyway) and brute-forcing the solution.  The problem is
really that there is not enough information passed to the notify
procedure to accomplish the desired task. These are the relevent
issues as I see it:

1) In the notify proc we can't find the row number corresponding to
the PANEL_MESSAGE item selected so that we could do an xv_get(list,
PANEL_LIST_CLIENT_DATA, row).  We have to brute-force to find the row
number of the selected item.  Something like PANEL_LIST_ROW_SELECTED
on the PANEL_LIST would do the trick.

2) Can't find the total number of rows in the PANEL_LIST item, so we
don't bomb out "for" loops when brute-force searching for the message
item.  We'd have to keep a global variable for this.  Something like
PANEL_LIST_ROWS_N would be needed.

3) Also in the notify proc, we can't find the PANEL_LIST item which
contains the PANEL_MESSAGE item selected, forcing me to keep "list"
around as a global variable.  Something like PANEL_LIST_PARENT_LIST
would be appropriate here.

4) The client data set on the list via PANEL_LIST_CLIENT_DATA could be
placed on the item's PANEL_CLIENT_DATA attribute so that it can be
retrieved in the notify proc.

5) Really, the parameters passed to the notify procedure are not the
right ones.  Ideally it should be passed the PANEL_LIST item
containing the selection, the row number of the selected item and a
pointer to the event, much like PANEL_CHOICE notification.

Any help or pointers are appreciated, but I'm really not interested in
brute-force or global variable solutions, unless this is the only way
to accomplish my goal.  In that case, I'll send an RFE to Sun.

BTW, for the record, I'm using the XView library from expo, with
patches 1 & 2 installed, on a Sun3/160C SunOS 4.0.3, under MIT Xsun
server release 4 and TWM window manager.

Thanks in advance.

-Barry

NAME: Barry A. Warsaw                USMAIL: National Institute of Standards
TELE: (301) 975-3460                         and Technology (formerly NBS)
UUCP: {...}!uunet!cme-durer!warsaw           Rm. B-124, Bldg. 220
ARPA: warsaw@cme.nist.gov                    Gaithersburg, MD 20899

warsaw@cme.nist.gov (Barry A. Warsaw) (03/15/90)

>>>>> "Barry" == Barry A. Warsaw <cme!durer!warsaw> writes:

Barry> I'm trying to attach client data to PANEL_LIST type panel items
Barry> in XView, but I can't quite figure out how to set and later
Barry> retrieve the data in the notify procedure.

I spent some time scanning through the source (after all those years
of sunview hacking with no source, its a real treat to have the xview
source! Thanks, Sun) and came up with a few routines that help with
attaching and retrieving data on PANEL_LIST items.  These aren't the
best solutions (I still think the data should hang off of some
attribute, or the list item should be passed to the notify proc), but
they do the job...

Say you have a PANEL_LIST item created as such:

	list = xv_create(panel, PANEL_LIST,
		PANEL_NOTIFY_PROC,	my_list_notify_proc,
		...
		NULL);

And later you add items to the list:

	xv_set(list,
		PANEL_LIST_INSERT,  	insert_index,
		PANEL_LIST_STRING,  	insert_index, string_name,
		PANEL_LIST_CLIENT_DATA,	insert_index, client_data,
		NULL);

When an item is selected, this function is called:

	void my_list_notify_proc(item, op, event)
	Panel_item  	item;
	Panel_list_op	op;
	Event       	*event;
		{
		int     	row = get_pli_row(item);
		Xv_opaque	client_data = get_pli_client_data(item);
		Panel_item	list = get_pli_parent_list(item);
		}

Here are the three useful routines:

	#include <xview_private/p_lst_impl.h> /* very important */

	int get_pli_row(item)
	Panel_item	item;
		{
		Panel_list_info	*pli;
		Row_info    	*row;
	
		pli = (Panel_list_info *) xv_get(item, PANEL_CLIENT_DATA);
	
		for (row = pli->rows; row; row = row->next)
			if (row->string_item == item) break;
	
		if (!row) return -1;
		return row->row;
		}


	Xv_opaque get_pli_client_data(item)
	Panel_item	item;
		{
		Panel_list_info	*pli;
	
		pli = (Panel_list_info *) xv_get(item, PANEL_CLIENT_DATA);
		return xv_get(pli->public_self, PANEL_LIST_CLIENT_DATA,
			get_pli_row(item));
		}


	Panel_item get_pli_parent_list(item)
	Panel_item	item;
		{
		Panel_list_info	*pli;
	
		pli = (Panel_list_info *) xv_get(item, PANEL_CLIENT_DATA);
		return pli->public_self;
		}


Barry> 1) In the notify proc we can't find the row number
Barry> corresponding to the PANEL_MESSAGE item selected so that we
Barry> could do an xv_get(list, PANEL_LIST_CLIENT_DATA, row).  We have
Barry> to brute-force to find the row number of the selected item.
Barry> Something like PANEL_LIST_ROW_SELECTED on the PANEL_LIST would
Barry> do the trick.

Still need to brute force it (see get_pli_row above), but you can cut
down on the number of globals needed by using some xview "secrets".

Barry> 2) Can't find the total number of rows in the PANEL_LIST item,
Barry> so we don't bomb out "for" loops when brute-force searching for
Barry> the message item.  We'd have to keep a global variable for
Barry> this.  Something like PANEL_LIST_ROWS_N would be needed.

Sorry, should have read TFM a little more closely, try attribute
PANEL_LIST_NROWS.

Barry> 3) Also in the notify proc, we can't find the PANEL_LIST item
Barry> which contains the PANEL_MESSAGE item selected, forcing me to
Barry> keep "list" around as a global variable.  Something like
Barry> PANEL_LIST_PARENT_LIST would be appropriate here.

See get_pli_parent_list above.

Barry> 4) The client data set on the list via PANEL_LIST_CLIENT_DATA
Barry> could be placed on the item's PANEL_CLIENT_DATA attribute so
Barry> that it can be retrieved in the notify proc.

I see why this can't be done, since xview uses the item's
PANEL_CLIENT_DATA attribute to store a structure of data pertaining to
the parent PANEL_LIST item.

Barry> 5) Really, the parameters passed to the notify procedure are
Barry> not the right ones.  Ideally it should be passed the PANEL_LIST
Barry> item containing the selection, the row number of the selected
Barry> item and a pointer to the event, much like PANEL_CHOICE
Barry> notification.

I still think this is the preferred way of notification since its
highly likely that the notification proc will need info about the
parent list.

Hope this helps...

-Barry

NAME: Barry A. Warsaw                USMAIL: National Institute of Standards
TELE: (301) 975-3460                         and Technology (formerly NBS)
UUCP: {...}!uunet!cme-durer!warsaw           Rm. B-124, Bldg. 220
ARPA: warsaw@cme.nist.gov                    Gaithersburg, MD 20899

hvr@kimba.Sun.COM (Heather Rose) (03/21/90)

In article <WARSAW.90Mar15105024@rtg.cme.nist.gov> warsaw@cme.nist.gov (Barry A. Warsaw) writes:
>
Barry,

You've certainly done your homework.  Sorry this was so difficult.  We've
enhanced the PANEL_LIST API in the next release to be much more obvious so
this kind of work around won't be necessary.

In the release this summer:

plist_notify(plist_item, string, client_data, op, event)

plist_item is the handle of the PANEL_LIST itself.
string and client_data is for the row being operated on.
op and event remain unchanged from Rev. 1.0.

__________________________________________________________________
Heather Rose
Window Systems Group                      internet:  hrose@sun.com
Sun Microsystems, Inc.                        uucp:  ...!sun!hrose