From: lee@sq.sq.com (Liam R. E. Quin)
Subject: Re: In Search of a Better Scrolling List
Organization: SoftQuad Inc., Toronto, Canada
Date: Sat, 25 Jul 92 03:30:07 GMT

gast@midway.uchicago.edu writes:
>Does anybody out the know of any Openlook widgets (in XView or OLit,
>preferably XView) that can handle scrolling columns of data. 

I looked at the XView 3 source and decided it'd take me maybe a week or
so to get a working, tested, documented multi-coumn list widget, with
where
	xv_set(MyList, 
	    PANEL_LIST_STRING, 23 "Col1\tCol2\tCol3"
	    NULL
	);
would do the obvious thing.  I don't have a week spare.

But I think you are looking at having columns that can be individually
selected.

I can think of two fairly easy ways of doing this in XView...
(1) use text fields and a scrollable panel
    This might not be very OPEN LOOK-ish, beware..

(2) have several scrolling lists, and hide the scroll-bars (use
	xv_get(List, PANEL_LIST_SCROLLBAR) to get a handle to the scroll bars,
    and set XV_SHOW to false and PANEL_INACTIVE to true),
    put your own scroll-bar on, and then create your own scroll bar to the
    right of them all, and use
	notify_interpose_event_func(MyScrollBar, MyScrollFunc, NOTIFY_SAFE);
    as illustrated on p. 261 of the O'Reily XView 3 manual.
    Your notify function will have to scroll the individual lists.
    I spent a few minutes on this and didn't get very far, though - I'll
    append what I did to this message & maybe someone can fix it.

    It might be easier simply to retain the right-most scroll-bar;
    creaing scrollbars in XView is a black art, to say the least.

If you want to create a large number of fields (several hundred, say) you
might find it easier to use olgx directly onto a canvas, or to use OLIT
gadgets, since creating large numbers of objects can be slow.


Here's a program that nearly works.  Faults:
* the invisible scrol-bars still work (an XView bug?)
* sometimes redrawing makes the scollbars all scroll!

Lee
Liam Quin, lee@sq.com, SoftQuad, Toronto, 416 239-4801
the barefoot programmer

/* cc -g -c pscroll.c
 * cc -o pscroll pscroll.o -lxview -lolgx -lX11
 */

#include <assert.h>
#include <xview/xview.h>
#include <xview/frame.h>
#include <xview/panel.h>
#include <xview/scrollbar.h>
#include <xview/notify.h>

#define N_LISTS 6

Xv_opaque Lists[N_LISTS];
Scrollbar s;

static int ValidEvent = 0;

Notify_func
sc_func(client, event, sbar, type) /* p. 261 */
    Notify_client client;
    Event *event;
    Scrollbar *sbar;
    Notify_event_type type;
{
    if (event_id(event) == SCROLLBAR_REQUEST) {
	int i;
	int Where;

fprintf(stderr, "right scroll event %d\n", __LINE__);
	Where = (int) xv_get(sbar, SCROLLBAR_VIEW_START);

	for (i = 0; i < N_LISTS - 1; i++) {
	    Scrollbar s ;
	    Notify_client c;

	    s = (Scrollbar) xv_get(Lists[i], PANEL_LIST_SCROLLBAR);
	    c = (Notify_client) xv_get(s, SCROLLBAR_NOTIFY_CLIENT);
fprintf(stderr, "Scroll %d %c [0x%x] to %d\n", i, c, s, Where);
	    ValidEvent++;
	    xv_set(s, SCROLLBAR_VIEW_START, Where);
	    ValidEvent--;
	}
    } else {
fprintf(stderr, "not scroll event %d\n", __LINE__);
    }
    return notify_next_event_func(client, event, sbar, type);
}

Notify_func
Other_Scroll(client, event, sbar, type)
    Notify_client client;
    Event *event;
    Scrollbar *sbar;
    Notify_event_type type;
{
    static int InMeAlready = 0;
    Notify_event n;

    if (InMeAlready > 1) {
	fprintf(stderr, "OtherScroll recursion limit reached\n");
	return NOTIFY_DONE;
    }

    ++InMeAlready;

    if (event_id(event) != SCROLLBAR_REQUEST) {
fprintf(stderr, "non-scroll event %d\n", __LINE__);
	n = notify_next_event_func(client, event, sbar, type);
	--InMeAlready;
	return n;
    } else if (ValidEvent) {
fprintf(stderr, "valid scroll event %d\n", __LINE__);
	n = notify_next_event_func(client, event, sbar, type);
	--InMeAlready;
	return n;
    } else {
fprintf(stderr, "INVALID scroll event %d ignored\n", __LINE__);
	--InMeAlready;
	return NOTIFY_DONE;
    }
}

main(argc, argv)
    int argc;
    char *argv[];
{
    Frame f;
    Panel p ;
    int i;
    int x = 10;

    xv_init(XV_INIT_ARGS, argc, argv, NULL);

    f = (Frame) xv_create(NULL, FRAME, NULL);

    p = (Panel) xv_create(f, PANEL,
	PANEL_LAYOUT, PANEL_HORIZONTAL,
	NULL
    );

    for (i = 0; i < N_LISTS; i++) {
	Scrollbar tmp_s;

	Lists[i] = xv_create(p,
	    PANEL_LIST,
	    XV_X, x,
	    PANEL_LIST_STRINGS,
		"a", "b", "c", "d", "e", "f", "g", "h", "i",
		"j", "k", "l", "m", "n", "o", "p", "q",
		NULL,
	    PANEL_LIST_DISPLAY_ROWS, 6,
	    NULL
	);

	x += (int) xv_get(Lists[i], XV_WIDTH);

	tmp_s = (Scrollbar) xv_get(Lists[i], PANEL_LIST_SCROLLBAR);

	assert(tmp_s != 0);

	if (i + 1 < N_LISTS) {
	    xv_set(tmp_s,
		XV_SHOW, FALSE,
		NULL
	    );
	}

    }
    s = (Scrollbar) xv_get(Lists[5], PANEL_LIST_SCROLLBAR);
    assert(s != 0);
    notify_interpose_event_func(
	/* tmp_s, */
	xv_get(s, SCROLLBAR_NOTIFY_CLIENT),
	sc_func,
	NOTIFY_SAFE
    );

    window_fit(p);
    window_fit(f);
fprintf(stderr, "%d\n", __LINE__);
    xv_main_loop(f);
}
Newsgroups: comp.windows.open-look