[comp.windows.x] XView scrolling list usage

straw@cam.nist.gov (Mike Strawbridge) (11/20/90)

A couple questions about using Scrolling Lists in XView.

I would like to change the all the list's string items by passing to xv_set
one attribute/value pair with a value argument such as a pointer to an array
of pointers to char.  Can I do this or do I have to know how many items are
in the list and pass each string in a separate argument?

Also what effect does setting the attribute PANEL_LIST_NROWS supposed to have?
If I have 20 items and set the value to 10, it appears to have no effect.

I ask these two questions because I would like to use XView scrolling lists
where the contents of the list and the number of items in the list change
often.  I would like to dynamically change the string values and the number
of items in the list. Are scrolling lists intended for this use or are they
really meant to be rather static ...  that is, initialized once and used
with those values only.

Maybe better questions are ...
   Should I use a different XView object?
   Should I forget XView and go with OLIT or something else?

-----------------------------------------------------------------------
NAME:   Michael Strawbridge                     TELE: (301) 975-3852
USMAIL: National Institute of Standards         ARPA: straw@cam.nist.gov
                and Technology                  UUCP: uunet!cme-durer!straw
        Rm. B-146, Bldg. 225
        Gaithersburg, MD  20899

cflatter@ZIA.AOC.NRAO.EDU (Chris Flatters) (11/20/90)

Mike Strawbridge writes:
> I would like to change the all the list's string items by passing to xv_set
> one attribute/value pair with a value argument such as a pointer to an array
> of pointers to char.  Can I do this or do I have to know how many items are
> in the list and pass each string in a separate argument?

The PANEL_LIST_STRINGS attribute does exactly what you want.  Used with
xv_create or xv_set it takes a NULL terminated list of strings in an array
of char* and sets each item in the scrolling list to the corresponding
entry in the array, discarding any previous contents (see pages 155ff in
the XView programmers manual).

> Also what effect does setting the attribute PANEL_LIST_NROWS supposed
> to have? If I have 20 items and set the value to 10, it appears to have
> no effect.

PANEL_LIST_NROWS is only valid as an argument to xv_get.  It returns the
current number of rows in the scrolling list.  PANEL_LIST_NROWS is updated
automatically when you insert or delete items from the list.

> I ask these two questions because I would like to use XView scrolling lists
> where the contents of the list and the number of items in the list change
> often.  I would like to dynamically change the string values and the number
> of items in the list. Are scrolling lists intended for this use or are they
> really meant to be rather static ...  that is, initialized once and used
> with those values only.

Scrolling lists are intended to be dynamic:

	" - Use an exclusive scrolling list in lieu of an exclusive
            setting when there are too many choices to fit in the
            available space, when the number of choices varies as the
            application runs, or when you want users to be able to
            edit the list."
		OPEN LOOK GUI Application Style Guidelines, p217

	" - Use a nonexclusive scrolling list in place of non-exclusive
	    settings when the number of choices is very large or varies
	    dynamically."
		ibid, p217

	" - Do not use menus for situations in which the number of items
            is not fixed and can grow extremely large.  Use a scrollable
            region --- either a pane or a scrolling list --- instead.
          - Use a scrolling region instead of a menu when users can
            edit the list of items."
		ibid, p142

And so on.  The style guide contains a lot of good advice on where (and where
not) to use each particular OPEN LOOK UI element.  I would rate it as an
essential reference if you are programming using any OPEN LOOK toolkit.
Both the style guide and the XView programming manual come with OpenWindows. 
If you just pulled XView off the net the publication details are:

OPEN LOOK Graphical User Interface Application Style Guidelines,
   by Sun Microsystems, Inc., 
   Addison-Wesley Publishing Company, Inc, 1990
   ISBN 0-201-52364-7, $24.95

XView Programming Manual (2nd Edn.),
   by Dan Heller,
   O'Reilly & Associates, Inc., 1990
   ISBN 0-937175-52-8, (no price marked on cover).

			Chris Flatters

straw@cam.nist.gov (Mike Strawbridge) (11/20/90)

Thanks for your reply to my article. But maybe I was not clear enough on
my first question.

>> I would like to change the all the list's string items by passing to xv_set
>> one attribute/value pair with a value argument such as a pointer to an array
>> of pointers to char.  Can I do this or do I have to know how many items are
>> in the list and pass each string in a separate argument?
>
>The PANEL_LIST_STRINGS attribute does exactly what you want.  Used with
>xv_create or xv_set it takes a NULL terminated list of strings in an array
>of char* and sets each item in the scrolling list to the corresponding
>entry in the array, discarding any previous contents (see pages 155ff in
>the XView programmers manual).

I would like to change the contents of the list with one call to xv_set().
And since my lists will have differing number of items, I was looking for a
way to do this without knowing at compile time how many items are in the
list.

For example, something like
	char *strings[] = { "string1", "string2", "string3", NULL };


	xv_set(panel,
	    PANEL_LIST_STRINGS, strings,
	    NULL);

instead of 
	xv_set(panel,
	    PANEL_LIST_STRINGS, "string1", "string2", "string3", NULL,
	    NULL);

With the first form, changing the strings in a dynamic scrolling list is
much easier. With the second form I have to know at compile time how many
items are in the list. Is something like the first form possible?

Alternatively if the second form is all that is available, I could put an
xv_set(panel, PANEL_LIST_STRING, ...) into a loop and set each string
individually, but I see this as uncool. It takes a little longer and the
display is updated for each xv_set() causing it to blink wildly.

mike

-----------------------------------------------------------------------
NAME:   Michael Strawbridge             	TELE: (301) 975-3852
USMAIL: National Institute of Standards 	ARPA: straw@cam.nist.gov
		and Technology            	UUCP: uunet!cme-durer!straw
        Rm. B-146, Bldg. 225
        Gaithersburg, MD  20899

denault@galileo.ifa.hawaii.edu (Tony Denault) (11/21/90)

>
>I would like to change the contents of the list with one call to xv_set().
>And since my lists will have differing number of items, I was looking for a
>way to do this without knowing at compile time how many items are in the
>list.
>

Many months ago I posted a request similar to your. I want to
be able to update a scroll list quickly. Using the xv_set() calls
to delete and insert items in the list was too slow, because 
xview redraws the panel item on each xv_set() call.

Someone posted a solution ( author unknown, sorry I lost the orginal file )
which I use to set the contents of the scrolling list using an argv-style 
array of strings. I am posting this function.

/*----------------------------------------------------------------------------
 * scrolling_list_update:
 *
 *   Given a scrolling list and an argv-style array of strings,
 *   update the contents of the scrolling list.
 *----------------------------------------------------------------------------
 */
void scrolling_list_update(list, argc, argv)
Xv_opaque   list;
int      argc;
char      **argv;
{
   register int   i, j;
   char      **avlist;
   int      rows = xv_get(list, PANEL_LIST_NROWS);
 
   /*
    * Copy the string information to an avlist.
    */
   if (argc > 0) {
      /*
       * Allocate memory for the list and fill it in.
       */
      avlist = (char **) malloc((argc + 3) * sizeof (char *));
      avlist[0] = (char *) PANEL_LIST_STRINGS;
      for (i = 0; i < argc; i++)
         avlist[i + 1] = argv[i];
      avlist[++i] = (char *) NULL;   /* NULL-terminate strings */
      avlist[++i] = (char *) NULL;   /* NULL-terminate avlist */

      /*
       * Set the scrolling list and free the avlist.
       */
      xv_set(list, ATTR_LIST, avlist, NULL);
      free((char *) avlist);
   }
   /*
    * This should not be necessary, but ... clear any entries
    * in excess of the new entries.
    */
   if (rows > argc) {
      /*
       * Set up an avlist with PANEL_LIST_DELETE,index pairs. The
       * panel entries are deleted from bottom (high index) to
       * top (low index) which might reduce copying of entries.
       */
      avlist = (char **) malloc(((rows-argc)*2+1) * sizeof (char *));
      for (j = 0, i = rows - 1; i >= argc; i--) {
         avlist[j++] = (char *) PANEL_LIST_DELETE;
         avlist[j++] = (char *) i;
      }
      avlist[j] = (char *) NULL;   /* NULL-terminate avlist */

      /*
       * Delete the excess entries and free the avlist.
       */
      xv_set(list, ATTR_LIST, avlist, NULL);
      free((char *) avlist);
   }
}


/------------------------------------------------------------------------\
| Tony Denault, Institute for Astronomy,  | denault@uhifa.ifa.hawaii.edu |
| 2680 Woodlawn Drive, Honolulu, HI 96789 |               (808) 956-6097 |
\------------------------------------------------------------------------/
--
/------------------------------------------------------------------------\
| Tony Denault, Institute for Astronomy,  | denault@uhifa.ifa.hawaii.edu |
| 2680 Woodlawn Drive, Honolulu, HI 96789 |               (808) 956-6097 |
\------------------------------------------------------------------------/