[comp.windows.x] can callbacks map widgets in realized parents?

y2@DINORAH.WUSTL.EDU (Yeong-Yeong Liu) (08/03/88)

I have a widget tree that looks like this:
	Widget	toplevel,
		     frame,
		          mainwidget,
		               text,
			       auxtext;	/* each indentation is a
					   generation lower */

"text" and "auxtext" are siblings and their contents (subwidgets)
may change from time to time.  They hold most of the activities of
my application.  Here is what I want to do:
	1. In main(), create and realize an initial display using 
	   Restart() function. Multiple choices go to callbacks.
	   (I had no problem)
	2. execute appropriate callback depending on user's choice
	   (the callback was indeed properly invoked).  In one of
	   the callbacks, I did:
		i) retrieve main_width,main_height,main_x and main_y by
		   XtGetValues(mainwidget,...);
		ii) XtDestroy(mainwidget);	/* wipe out mainwidget
						   and its children */
		iii) recreate mainwidget with old x,y,width,height.
		iv) create text, auxtext, their children and their
		    children's callbacks
		v) XtRealizeWidget(mainwidget);
		(steps ii thru v are in function InitialPage())
	3. back in main(), return to XtMainLoop() and wait for something
	   to happen appropriate to the widgets created in step 2 iv

I ran into following problems:

	* after step 2 iii), the dump statement tells me the mainwidget
	  recreated has height of 1 and y position of 780, which is
	  approximately the opposite of the two parameters I put in.
	  This is minor but seems strange.
	* in step 2 iv) I must set widget geometry (x,y,width,height)
	  in args or I'll get "integer out of range" in X_CreateWidget
	  from Server. Is this required ? Why would I be able to
	  create widget in step 1 (before any of the widgets is realized)
	  without setting geometry ?
	* after completion of step 2 v), program apparently goes
	  to XtMainLoop(), but it didn't display any of the widgets
	  created in step 2 (didn't map mainwidget).
	* If I replace Restart in main program with InitialPage, less
	  the final XtRealizeWidget(mainwidget), then all widgets
	  created by InitialPage are visible. It looks like it depends
	  on if the parent has been realized or not.  Is this really so??
	  Or have I missed something?  Has anyone else created widgets
	  after the parent has been realized?

Here is my main program:
------------------------
	.
	.
	Widget	frame,mainwidget,text,auxtext;
	int main_width,main_height,main_x,main_y;
	.
	main()
	{
	.
	.
	XtGetApplicationResources(toplevel,(caddr_t)NULL,resources,
				  XtNumber(resources),NULL,0);
	.
	.
	frame = XtCreateWidget("rtp", vPanedWidgetClass, toplevel, args, n);
	CreateMainWidget();	/* create (managed) mainwidget (dimension
				   set according to DisplayWidth etc. for
				   DefaultScreen) */
	Restart();	/* setup (initial) multiple choice in "text",
			   message in "auxtext" (all subwidgets are
			   managed) */
	XtManageChild(frame);
	XtRealizeWidget(toplevel);
	XtMainLoop();
}

Here is the subroutine (which does step 2 ii to 2 v) called by callbacks
------------------------------------------------------------------------
void InitialPage()
  {
  Widget funcky,panel;
  Arg	args[6];
  int	i,n,width,height,wdth,hght,horiz=0;

  /* destroy mainwidget and its children, then recreate mainwidget again */
  XtDestroyWidget(mainwidget);
  CreateMainWidget();
  
  /* create a shell for text */
  n = 0;
  XtSetArg(args[n],XtNwidth,main_width);
  n ++;
  XtSetArg(args[n],XtNheight,main_height/3);
  n ++;
  XtSetArg(args[n],XtNborderWidth,0);
  n ++;
  XtSetArg(args[n],XtNx,0);
  n ++;
  XtSetArg(args[n],XtNy,0);
  n ++;
  text = XtCreateManagedWidget("text",formWidgetClass,
			       mainwidget,args,n);

  /* create another shell for text help */
  XtSetArg(args[n-1],XtNy,main_height/3);
  XtSetArg(args[n],XtNfromVert,text);
  n ++;
  auxtext = XtCreateManagedWidget("auxtext",formWidgetClass,
				  mainwidget,args,n);

  /* create a shell for multiple choice */
  XtSetArg(args[n-1],XtNfromVert,auxtext);
  XtSetArg(args[n-2],XtNy,main_height * 2 / 3);
  funcky = XtCreateWidget("mainwidget",formWidgetClass,
				mainwidget,args,n);

  /* create multiple choices inside funcky */
  panel = MenuPage(funcky,"funcky",funcalls,funcdata,horiz,frame,
		   txplanActionsTableCount,txplanActionsTable,
		   nfuncky,txplanTranslations,
		   &wdth,&hght);

  /* reposition function keys to the bottom of the mainwidget */
  XtMoveWidget(funcky,0,main_height - hght);
  
  /* manage and realize all children */
  XtManageChild(funcky);
  XtRealizeWidget(mainwidget);

  }

Any help will be highly appreciated. Thanks.

Y Liu
	{uunet...}!wucs1!dinorah!y2	or
	wucs1.wustl.edu!dinorah!y2	or
	y2@dinorah.wustl.edu		or
	314-362-2950

swick@ATHENA.MIT.EDU (Ralph R. Swick) (08/03/88)

The answer to your subject question is yes, but the scenario you
describe is a lot more complicated.  Remember that geometry negotiation
behaves very differently before and after a widget (branch) is realized.

When a widget hierarchy is created and managed before any of its
ancestors have been realized, then geometries are effectively
calculated from the inside out.  This allows each parent's layout
routine to be called exactly once and have full information on 
the desires of it's children.  Once the hierarchy has been
realized, however, the parent must react to each individual change
in it's managed set of children and must negotiate any changes
in it's own geometry with it's parent.  Thus, geometries of realized
hierarchies are effectively calculated from the outside in.

One technique that will work well when you want to create and destroy
branches of a realized tree is to leave the uppermost node of the
branch unmanaged until the remainder of the branch has been created
(and managed).  You can then set the uppermost node to be managed,
which will also cause the entire branch to be realized.  You may
also want some way to inform the parent of the new branch not to
perform a re-layout operation between the time you destroy the
old branch and manage the new one.  Some composite widgets will
support this (deferring a re-layout) and some won't.  The better
one probably will.