rick@pcrat.uucp (Rick Richardson) (08/08/90)
I want to create a Box (or RowColumn in Motif) widget that contains a bunch of Command (or PushButton in Motif) widgets. But with a twist. The labels on the buttons themselves take anywhere from 1-3 seconds apiece to compute, and are information that the user can read in and of themselves. The buttons represent pages of a document. As each button widget is created, I'd like to process events ala XtMainLoop, but only until I'm sure the newly created button has been displayed. Once the button is displayed, I need to continue parsing an input file until the next button is ready to be added and displayed. I want to do this displaying as each button is created so that the user has something to look at and think about rather than a dumb hourglass or Please Wait message. I've scoped out the pseudo code, as indicated below, but there are a few things I haven't figured out how to do, marked by ***'s. Does anybody have any ideas or pointers on how I can accomplish this? Is there some event I have to wait for that says that everything created so far has been displayed? What is it? main # main program { - box = XtCreateManagedWidget( ...Box..., toplevel, ... ) (and other widgets) - XtRealizeWidget(toplevel) - Now, process events until widgets are displayed **** How do I do this **** - call parse(document) - call regular XtMainLoop() } parse_ready # called from "parse", usually many times { - button[n++] = XtCreateManagedWidget( ...Command..., box, ... ) The 'label' on this button is information in itself. - XtRealizeWidget(button[n++]) *** is this correct? *** - Now, process events until this new button has been fully displayed. *** how do I do this *** - return back to parse(); } parse { While there are more pages to process { - format the page (somewhat CPU intensive) - call parse_ready } } -Rick -- Rick Richardson - PC Research, Inc., uunet!pcrat!rick, (201) 389-8963
swick@ATHENA.MIT.EDU (Ralph Swick) (08/08/90)
- Now, process events until widgets are displayed
**** How do I do this ****
You process events with a loop consisting of
while (XtAppPending(...)) {
...
XtAppNextEvent(...);
...
XtDispatchEvent(...);
...
}
(this is precisely XtAppMainLoop, substituting XtAppPending
for True). You might find it desirable to call XFlush before
the loop in some circumstances, or even XSync just before
XtAppPending to insure that the client and server queues are
completely emptied before continuing.
But have you considered using "work procedures"?
See XtAppAddWorkProc().
swick@ATHENA.MIT.EDU (Ralph Swick) (08/08/90)
The "guts" does the work and is orders of magnitude larger** (in any significant application). Keeping the "guts" clean, comprehensible, and maintainable is what is most important in my mind. I certainly don't disagree with this! :-) Nor do I have any argument with your general observations about work procs. They're a very simplistic attempt to ameliorate a problem whose proper solution really needs lower-level OS suport. (So let's get better OS's :-)
rlh2@ukc.ac.uk (Richard Hesketh) (08/09/90)
In article <1990Aug8.025339.3419@pcrat.uucp> rick@pcrat.uucp (Rick Richardson) writes: >I want to create a Box (or RowColumn in Motif) widget that contains > - Now, process events until widgets are displayed > **** How do I do this **** I thought of a routine that would wait for a particular event. Here's the routine. It works for me (I've tried waiting for various events). I'd like to know if I've missed anything. Specifically will this routine break the Intrinsics when a translation table has been set on this widget .. and what about grabs? Boolean XukcWaitForWidgetEvent(widget, eventmask, type) Widget widget; long eventmask; int type; { XEvent ev; long oldmask; XWindowAttributes atts; if (!XGetWindowAttributes(XtDisplay(widget), XtWindow(widget), &atts)) return (FALSE); /* Help! .. failed X request */ oldmask = atts.your_event_mask; XSelectInput(XtDisplay(widget), XtWindow(widget), oldmask | eventmask); while (1) { if (XtAppPeekEvent(XtWidgetToApplicationContext(widget), &ev) && (ev.type == type) && (ev.xany.window == XtWindow(widget))) break; XtAppNextEvent(XtWidgetToApplicationContext(widget), &ev); XtDispatchEvent(&ev); } if (!(oldmask & eventmask)) /* eat up this event if the widget didn't select for it */ XtAppNextEvent(XtWidgetToApplicationContext(widget), &ev); XSelectInput(XtDisplay(widget), XtWindow(widget), oldmask); return (TRUE); } Richard Hesketh : @nsfnet-relay.ac.uk:rlh2@ukc.ac.uk : rlh2@ukc.ac.uk ..!mcsun!ukc!rlh2 --- Computing Lab., University of Kent at Canterbury, Canterbury, Kent, CT2 7NF, United Kingdom. Tel: +44 227 764000 ext 7620/3682
rick@pcrat.uucp (Rick Richardson) (08/09/90)
Thanks to all who mailed me concerning "Incremental Display of Widget
Tree". There were several answers that included using expose event
callbacks and waiting in a modified XtAppMainLoop for particular events.
However, the simplest solution came from Ralph Swick, and does the
trick for my application:
XFlush(TheDisplay);
for(;;)
{
XEvent event;
XSync(TheDisplay, 0);
if (!XtAppPending(Context))
break;
XtAppNextEvent(Context, &event);
XtDispatchEvent(&event);
}
-Rick
--
Rick Richardson - PC Research, Inc., uunet!pcrat!rick, (201) 389-8963
swick@ATHENA.MIT.EDU (Ralph Swick) (08/10/90)
You fleshed-out my pseudo-code just fine, but the performance can be improved considerably with an inner loop: for(;;) { XEvent event; while (XtAppPending(Context)) { XtAppNextEvent(Context, &event); XtDispatchEvent(&event); } XSync(TheDisplay, 0); if (!XtAppPending(Context)) break; } -Ralph