[comp.windows.x] probs with popup windows

chapman@lll-lcc.UUCP (Carol Chapman) (05/05/89)

Well, I am still struggling along, trying to find a way for my program to
get a mere 10 bytes of input from a user.  If any of you can offer
advice or send me samples of code using popup windows, I'd appreciate it.
My latest idea is to have a dialog widget within a popup shell.  It is
defined as follows: 

num_args = 0;
XtSetArg(args[num_args], XtNallowShellResize, TRUE); num_args++;
popup_shell = XtCreatePopupShell("Popup Shell", transientShellWidgetClass,
	                         toplevel, args, num_args);
num_args = 0;  /* reinitialize */
barcode = (char *) calloc(STR_LEN, sizeof(char));
XtSetArg(args[num_args], XtNborderWidth, 4); num_args++;
XtSetArg(args[num_args], XtNlabel, "Enter a barcode:  "); num_args++;
XtSetArg(args[num_args], XtNvalue, barcode); num_args++;
input_dialog = XtCreateManagedWidget("Input Dialog", dialogWidgetClass,
	                             popup_shell, args, num_args);

/* create an OK button for the popup window */
num_args = 0;  /* reinitialize */
XtSetArg(args[num_args], XtNfont, fontb_info); num_args++;
ok_button = XtCreateManagedWidget("OK", commandWidgetClass, input_dialog,
	                          args, num_args);
XtAddCallback(ok_button, XtNcallback, check_barcode, NULL);

/* create a cancel button for the popup window */
cancel_button = XtCreateManagedWidget("Cancel", commandWidgetClass,
                                      input_dialog, args, num_args);
XtAddCallback(cancel_button, XtNcallback, cancel_action, NULL);

Looks simple, right?  My program sets up a large vpaned window with
buttons in one pane.  If a user selects the Display button, a routine
named display() is called, the first line of which is
XtPopup(popup_shell, XtGrabExclusive);  At this point, I want a
popup window to appear and get a barcode.  Within the popup window, if
the user selects the Cancel button, I want the program to simply
remove the popup window and return to the main vpaned window.  Within the 
popup window, if the user selects the OK button, I want the program to
remove the popup window and check the validity of the barcode that the
user typed.  If it is invalid, I want the popup window to reappear, so
the process can be repeated.  If the barcode is valid, I want the
program to continue on its merry way in the display() routine.

I'm having great difficulty getting things to work as stated above.
In my latest rendition, the popup window appears but with no text in it, and my
program keeps running with garbage for the barcode.  When it finishes,
*then* text appears in the popup window asking me for a barcode!  If I
give it a barcode, it calls the check_barcode routine like I want
it to, but when that finishes, it never returns to the point where
XtPopup was originally called.  Isn't it supposed to return to that point?

A few other minor questions:  Is there a way to set the font for the
text entered by the user in the dialog widget (XtNvalue)?  Am I
correct to be using XtGrabExclusive as an argument to XtPopup?  If I
use XtNvalue with the dialog widget, then I don't need
XtGetValueDialogString, correct?

If you can help, I thank you muchly!
carol chapman

-- 
-------------------------------------------------------------------------------
Livermore Lab            (chapman@lll-crg.llnl.gov or chapman@lll-lcc.llnl.gov)
P.O. Box 808, L-153      Tel. (415) 423-7876
Livermore, CA  94550     "Never own anything that you have to FEED or PAINT." 

argv%eureka@Sun.COM (Dan Heller) (05/05/89)

In article <2461@lll-lcc.UUCP> chapman@lll-lcc.UUCP (Carol Chapman) writes:
>Well, I am still struggling along, trying to find a way for my program to
>get a mere 10 bytes of input from a user.  If any of you can offer
>advice or send me samples of code using popup windows, I'd appreciate it.

This is perhaps the most commonly asked question that people send "me",
so when I posted my WidgetWrap code to comp.sources.x, I made sure to include
a sample program which does just what you are talking about.  It is a very
simple program that demonstrates the widgetwrap code (which is much easier
to use and read than the XtSetArg() calls riddled throughout toolkit programs).
The sample application uses a simple yes/no dialog box ...

This code is also available via ftp from expo.lcs.mit.edu in the contrib
directory.  I have yet to have questions from someone who can't figure out
this stuff, so maybe it will be equally helpful to you.
    dan  <argv@sun.com>

kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) (05/05/89)

> My latest idea is to have a dialog widget within a popup shell...

Who's latest idea? :-) :-)

> I'm having great difficulty getting things to work as stated above.

It sounds like you are having problems with your program flow.  What you
need to do is:

1) When this user selects display popup the dialog widget, and then return from
   the routine.

This will return you to XtMainLoop() which will process events and
popup the dialog widget.

2) If cancel is selected then just popdown the dialog, and then exit.
   This will cause no other action (the desired behavior.

3) If "okay" was selected then check the barcode.
   a) If it is okay then call your computation routine right here in the
      okay proc.

   b) If is it not okay then print an error message and force the user to 
      try again (or whatever.


It is important to remember that no event processing will happen when
the program is actually in a callback or action routine, all event processing
and window operations take place when the program is in the XtMainLoop() 
fuinction.  It is important to spend as little time away from this routine
as possible, as no events will be processed while you are off doing something
else.  This includes both user interactions and window refreshes.

> A few other minor questions:  Is there a way to set the font for the
> text entered by the user in the dialog widget (XtNvalue)?

The name of the dialog widgets value entry widget is documented as: "value"
Thus you can use a resource specification of the following:

*<dialog name>*value.Font:		<font_name>

If you really want to hard code the font name into the program (very bad
practice IMHO) you can use XtNameToWidget() to get the widget id of the the
value widget and then do a XtSetValues().

>  Am I correct to be using XtGrabExclusive as an argument to XtPopup?

It depends upon the behavior that you desire,  XtGrabExclusive will lock out
event processing in the rest of your application while the grab is active
(as long as the menu is up).

> If I use XtNvalue with the dialog widget, then I don't need
> XtGetValueDialogString, correct?

Nope, you should use XtGetValueDialogString(), as the dialog value is
copied internally.  It is not clear that this is the right behavior, but
it seems too late to break things.

tim@brspyr1.BRS.Com (Tim Northrup) (05/06/89)

From article <2461@lll-lcc.UUCP>, by chapman@lll-lcc.UUCP (Carol Chapman):
>
> program keeps running with garbage for the barcode.  When it finishes,
> *then* text appears in the popup window asking me for a barcode!  If I
> give it a barcode, it calls the check_barcode routine like I want
> it to, but when that finishes, it never returns to the point where
> XtPopup was originally called.  Isn't it supposed to return to that point?

This is where you went wrong (I recently hit the same problem).

XtPopup() returns after the popup window is established, not after you
return from any selection in the popup.  In the case you describe, after
calling XtPopup(), you should return;  All after-selection processing
gets done by the callback routines.

Using your example, this is a rough idea of what you want:

	void DoThatPopup () {
		XtPopup(popup_shell);	/* popup the dialog box */
					/* cannot process barcode yet!!! */
		return;			/* return to main loop */
		}

	void check_barcode () {

		<check validity of the barcode entered>

		if (<barcode is valid>) {
			XtPopdown(popup_shell);		/* all is well */
			<process valid barcode now>
			}
		return;			/* return with or without popup */
		}

	void cancel_action () {
		XtPopdown(popup_shell);		/* remove popup */
		return;				/* return to main loop */
		}

Hope this helps.
"It works for me." -- Hunter.
-- 
Tim Northrup      		  +------------------------------------------+
+---------------------------------+         GEnie:  T.Northrup               |
UUCP: uunet!crdgw1!brspyr1!tim    |   Air Warrior:  "Duke"                   |
ARPA: tim@brspyr1.BRS.Com	  +------------------------------------------+

argv%eureka@Sun.COM (Dan Heller) (05/08/89)

I thought I followed up to this before; maybe it didn't get thru.

In article kit@EXPO.LCS.MIT.EDU (Chris D. Peterson) writes:
> > I'm having great difficulty getting things to work as stated above.
> It sounds like you are having problems with your program flow.  What you
> need to do is:
> 
> 1) When this user selects display popup the dialog widget, and then return from
>    the routine.
> 
> This will return you to XtMainLoop() which will process events and
> popup the dialog widget.

You shouldn't *have* to return to the top level.  This might change
the flow of the program or function significantly.  It is perfectly
reasonable to want to "freeze" the program and interact with the
user immediately.  Obviously, this easily handled by inserting a
synthetic XtMainLoop() in the function which does the popup and is
prompting for request to return (see prompt.c in WidgetWrap source).

> It is important to remember that no event processing will happen when
> the program is actually in a callback or action routine, all event processing
> and window operations take place when the program is in the XtMainLoop() 

In the general sense this is true, but it doesn't have to be; the user
should be able to loop himself as exemplified in the above paragraph.

As I said, prompt.c shows an example of this, but it also raises and
interesting question which was discussed several months ago, but nothing
was resolved.  Is XtNextEvent and XtDispatchEvent reentrant?  Experimentation
on various machines renders no particular problems with it.  Inspection of
the source doesn't show any particular problems with it (so long as you aren't
reentrant as a result of servicing a signal of some kind that interrupted the
intrinsics at an undesireable place).

Paul Ascente once answered "kind of" meaning (based on my understanding of
what he said at the time) that you may call XtNextEvent and XtDispatch...
as long as "you are careful" -- that is, don't set your -own- timer (e.g.
you're not using XtAddTimeOut) and suddenly call Xt{Next,Dispatch}Event
and expect it to work.  If you understand the toolkit intrinsics, you can
figure out when is a reasonable time to call your own such routine (again,
I refer you back to prompt.c).

    dan  <argv@sun.com>