1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           xitCreTopDia
4 --
5 --  Project:          xit  - X Internal Toolkit
6 --  System:           xit  - X Internal Toolkit
7 --    Subsystem:      <>
8 --    Function block: <>
9 --
10 --  Description:
11 --    Manages a toplevel dialog with at most 4 buttons. Enter and Return
12 --    are used as activate keys (if a default button is defined).
13 --
14 --  Filename:         xitCreTopDia.c
15 --
16 --  Authors:          Roger Larsson, Ulrika Bornetun
17 --  Creation date:    1991-10-20
18 --
19 --
20 --  (C) Copyright Ulrika Bornetun, Roger Larsson (1995)
21 --      All rights reserved
22 --
23 --  Permission to use, copy, modify, and distribute this software and its
24 --  documentation for any purpose and without fee is hereby granted,
25 --  provided that the above copyright notice appear in all copies. Ulrika
26 --  Bornetun and Roger Larsson make no representations about the usability
27 --  of this software for any purpose. It is provided "as is" without express
28 --  or implied warranty.
29 ----------------------------------------------------------------------------*/
30 
31 /* SCCS module identifier. */
32 static char SCCSID[] = "@(#) Module: xitCreTopDia.c, Version: 1.1, Date: 95/02/18 15:10:27";
33 
34 
35 /*----------------------------------------------------------------------------
36 --  Include files
37 ----------------------------------------------------------------------------*/
38 
39 #include <stdio.h>
40 #include <string.h>
41 
42 #include <X11/Intrinsic.h>
43 #include <X11/Shell.h>
44 
45 #include <Xm/Xm.h>
46 #include <Xm/Form.h>
47 #include <Xm/RowColumn.h>
48 #include <Xm/Separator.h>
49 
50 #include "System.h"
51 #include "xitTools.h"
52 
53 
54 /*----------------------------------------------------------------------------
55 --  Macro definitions
56 ----------------------------------------------------------------------------*/
57 
58 #define DEFAULT_TIGHTNESS  5
59 
60 
61 /*----------------------------------------------------------------------------
62 --  Type declarations
63 ----------------------------------------------------------------------------*/
64 
65 /* Structure to hold the min. sizes of the shell. */
66 typedef struct {
67   Dimension  min_width;
68   Dimension  min_height;
69 } MIN_SIZE, *MIN_SIZE_REF;
70 
71 
72 /*----------------------------------------------------------------------------
73 --  Global definitions
74 ----------------------------------------------------------------------------*/
75 
76 
77 /*----------------------------------------------------------------------------
78 --  Function prototypes
79 ----------------------------------------------------------------------------*/
80 
81 static void
82   destroySizeDataCB( Widget               widget,
83                      MIN_SIZE_REF         size_ref,
84                      XmAnyCallbackStruct  *call_data );
85 
86 static void
87   removeCB( Widget               widget,
88             Widget               toplevel_widget,
89             XmAnyCallbackStruct  *call_data );
90 
91 
92 
93 /*----------------------------------------------------------------------------
94 --  Functions
95 ----------------------------------------------------------------------------*/
96 
97 Widget
xitCreateToplevelDialog(Widget parent,char * name,int default_button_no,int tightness,XIT_ACTION_AREA_ITEM * actions,int num_actions)98   xitCreateToplevelDialog( Widget                parent,
99                            char                  *name,
100                            int                   default_button_no,
101                            int                   tightness,
102                            XIT_ACTION_AREA_ITEM  *actions,
103                            int                   num_actions )
104 {
105 
106   /* Variables. */
107   int         index;
108   int         extra_offset = 0;
109   char        buffer[ 50 ];
110   Arg         args[ 20 ];
111   Cardinal    n;
112   Dimension   height;
113   Dimension   width;
114   Dimension   max_height = 0;
115   Dimension   max_width  = 0;
116   Widget      baseFo;
117   Widget      ho1Sp = NULL;
118   Widget      shellTl;
119   Widget      widget;
120   Widget      workFo;
121 
122   static XIT_PUSH_STRUCT action_bu_def[] = {
123     { "", "", "", True, NULL },
124   };
125 
126 
127   /* Code. */
128 
129   if( tightness < 1 )
130     tightness = DEFAULT_TIGHTNESS;
131 
132 
133   /* Create a toplevel shell, our base widget. */
134   n = 0;
135   XtSetArg( args[ n ], XmNallowShellResize, True ); n++;
136   shellTl = XtCreatePopupShell( name, topLevelShellWidgetClass,
137                                 parent, args, n );
138 
139 
140   /* Create a form in the shell. */
141   sprintf( buffer, "%sBase", name );
142 
143   n = 0;
144   XtSetArg( args[ n ], XmNskipAdjust,   True );  n++;
145 
146   if( num_actions > 1 ) {
147     XtSetArg( args[ n ], XmNfractionBase, tightness * num_actions - 1 ); n++;
148   }
149   baseFo = XmCreateForm( shellTl, buffer, args, n );
150 
151 
152   /* Work area form. */
153   sprintf( buffer, "%sFo", name );
154 
155   n = 0;
156   workFo = XmCreateForm( baseFo, buffer, args, n );
157 
158   XtManageChild( workFo );
159 
160 
161   /* Separator. */
162   if( num_actions > 0 ) {
163     n = 0;
164     sprintf( buffer, "%sSp", name );
165     XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL );  n++;
166     ho1Sp = XmCreateSeparator( baseFo, buffer, args, n );
167 
168     XtManageChild( ho1Sp );
169   }
170 
171   /* Attachments. */
172   if( num_actions > 0 ) {
173     xitAttachWidget( workFo,
174                      XmATTACH_FORM, NULL, XmATTACH_FORM,   NULL,
175                      XmATTACH_FORM, NULL, XmATTACH_WIDGET, ho1Sp );
176     xitAttachWidget( ho1Sp,
177                      XmATTACH_NONE, NULL, XmATTACH_FORM, NULL,
178                      XmATTACH_FORM, NULL, XmATTACH_FORM, NULL );
179   } else {
180     xitAttachWidget( workFo,
181                      XmATTACH_FORM, NULL, XmATTACH_FORM, NULL,
182                      XmATTACH_FORM, NULL, XmATTACH_FORM, NULL );
183   }
184 
185   /* Create the action buttons. */
186   for( index = 0; index < num_actions; index++ ) {
187 
188     /* Create the action button and set resources. */
189     sprintf( buffer, "Bu%d", index + 1 );
190 
191     action_bu_def[ 0 ].title = actions[ index ].label;
192     action_bu_def[ 0 ].name  = buffer;
193     widget = xitCreatePushButton( baseFo, &action_bu_def[ 0 ] );
194 
195     n = 0;
196 
197     if( index == 0 ) {
198       XtSetArg( args[ n ], XmNleftAttachment, XmATTACH_FORM ); n++;
199       XtSetArg( args[ n ], XmNleftOffset,     5             ); n++;
200     } else {
201       XtSetArg( args[ n ], XmNleftAttachment, XmATTACH_POSITION ); n++;
202     }
203 
204     XtSetArg( args[ n ], XmNleftPosition,     tightness * index ); n++;
205 
206     XtSetArg( args[ n ], XmNtopAttachment,    XmATTACH_WIDGET   ); n++;
207     XtSetArg( args[ n ], XmNtopWidget,        ho1Sp             ); n++;
208     XtSetArg( args[ n ], XmNbottomAttachment, XmATTACH_FORM     ); n++;
209 
210     if( index != num_actions - 1 ) {
211       XtSetArg( args[ n ], XmNrightAttachment, XmATTACH_POSITION );  n++;
212     } else {
213       XtSetArg( args[ n ], XmNrightAttachment, XmATTACH_FORM ); n++;
214       XtSetArg( args[ n ], XmNrightOffset,     5             ); n++;
215     }
216 
217     XtSetArg( args[ n ], XmNrightPosition,
218               tightness * index + (tightness - 1) );  n++;
219 
220     if( default_button_no - 1 == index ) {
221       XtSetArg( args[ n ], XmNshowAsDefault, True );  n++;
222       XtSetArg( args[ n ], XmNtopOffset,    5 ); n++;
223       XtSetArg( args[ n ], XmNbottomOffset, 5 ); n++;
224     } else {
225       XtSetArg( args[ n ], XmNtopOffset,    5 + extra_offset ); n++;
226       XtSetArg( args[ n ], XmNbottomOffset, 5 + extra_offset ); n++;
227     }
228 
229 
230     /* Fake button? */
231     if( actions[ index ].label == NULL ) {
232       XtSetArg( args[ n ], XmNmappedWhenManaged, False ); n++;
233     }
234 
235     XtSetValues( widget, args, n );
236 
237     XtManageChild( widget );
238 
239 
240     /* Callback and callback data. */
241     if( actions[ index ].callback != NULL )
242       XtAddCallback( widget, XmNactivateCallback,
243                      actions[ index ].callback, actions[ index ].data );
244     else
245       XtAddCallback( widget, XmNactivateCallback,
246                      (XtCallbackProc) removeCB, (XtPointer) shellTl );
247 
248 
249     /* Search the max height and width of the widgets in the action area. */
250     n = 0;
251     XtSetArg( args[ n ], XmNheight, &height ); n++;
252     XtSetArg( args[ n ], XmNwidth,  &width  ); n++;
253     XtGetValues( widget, args, n );
254 
255     if( height > max_height )
256       max_height = height;
257 
258     if( width > max_width )
259       max_width = width;
260 
261     /* Activate the default button widget? */
262     if( default_button_no - 1 == index ) {
263       n = 0;
264       XtSetArg( args[ n ], XmNdefaultButton, widget ); n++;
265       XtSetValues( baseFo, args, n );
266     }
267 
268   } /* loop */
269 
270 
271   /* The separator should be above the action buttons. */
272   height = max_height + 2 * 5;
273 
274   if( num_actions > 0 ) {
275     n = 0;
276     XtSetArg( args[ n ], XmNbottomOffset, height ); n++;
277     XtSetValues( ho1Sp, args, n );
278   }
279 
280   XtManageChild( baseFo );
281 
282 
283   /* Save the min width and height. */
284   {
285     MIN_SIZE_REF  size_ref;
286 
287     size_ref = SysNew( MIN_SIZE );
288 
289     if( num_actions > 0 ) {
290       size_ref -> min_width  = max_width * num_actions +
291                                (num_actions * 3 + 1) * 5;
292       size_ref -> min_height = max_height + 2 * 5 + 5;
293     } else {
294       size_ref -> min_width  = 10;
295       size_ref -> min_height = 10;
296     }
297 
298     /* Save as userdata to the baseFo. */
299     n = 0;
300     XtSetArg( args[ n ], XmNuserData, (void *) size_ref ); n++;
301     XtSetValues( baseFo, args, n );
302 
303     /* Make sure we can release the userdata. */
304     XtAddCallback( baseFo, XmNdestroyCallback,
305                    (XtCallbackProc) destroySizeDataCB, (XtPointer) size_ref );
306 
307   } /* block */
308 
309 
310   /* To enable default accelerators, use a fake menu. */
311   if( default_button_no > 0 && num_actions > 0 ) {
312 
313     Widget  menuBr;
314     Widget  menuCs;
315     Widget  menuPd;
316     Widget  menuBu1;
317 
318     static XIT_MENU_BUTTON_STRUCT menu_casc[] = {
319       { "", "",  NULL, "", True,  False, False },
320     };
321 
322     static XIT_CASCADE_STRUCT menu_pane[] = {
323       { "", "", "" },
324     };
325 
326     n = 0;
327     XtSetArg( args[ n ], XmNmappedWhenManaged, False ); n++;
328     menuBr  = XmCreateMenuBar(         baseFo, "",     args, n );
329     menuPd  = XmCreatePulldownMenu(    menuBr, "",     args, n );
330     menuCs  = xitCreateCascadeButton(  menuBr, menuPd, &menu_pane[ 0 ] );
331     menuBu1 = xitCreateMenuPushButton( menuPd, &menu_casc[ 0 ] );
332 
333     XtManageChild( menuBr  );
334     XtManageChild( menuCs  );
335     XtManageChild( menuBu1 );
336 
337     n = 0;
338     XtSetArg( args[ n ], XmNaccelerator, "<Key>KP_Enter:" );  n++;
339     XtSetValues( menuBu1, args, n );
340 
341   } /* if */
342 
343 
344   return( shellTl );
345 
346 } /* xitCreateToplevelDialog */
347 
348 
349 /*----------------------------------------------------------------------*/
350 
351 void
xitSetSizeToplevelDialog(Widget toplevel,Boolean tight)352   xitSetSizeToplevelDialog( Widget   toplevel,
353                             Boolean  tight )
354 {
355 
356   /* Variables. */
357   Boolean       ok;
358   int           index;
359   char          buffer[ 100 ];
360   char          *geometry;
361   char          *name;
362   void          *user_data;
363   Arg           args[ 10 ];
364   Cardinal      n;
365   Cardinal      num_children;
366   Dimension     height;
367   Dimension     user_height = 0;
368   Dimension     user_width  = 0;
369   Dimension     width;
370   Position      x;
371   Position      y;
372   WidgetList    children;
373   Widget        tempW;
374   MIN_SIZE_REF  min_size_ref;
375 
376 
377   /* Code. */
378 
379   /* Get the name of the toplevel widget. */
380   name = xitGetWidgetName( toplevel );
381   if( name == NULL )
382     return;
383 
384 
385   /* When we realize the toplevel form, all geometries are calculated. */
386   XtRealizeWidget( toplevel );
387 
388   n = 0;
389   XtSetArg( args[ n ], XmNwidth,  &width ); n++;
390   XtSetArg( args[ n ], XmNheight, &height ); n++;
391   XtGetValues( toplevel, args, n );
392 
393 
394   /* If we have a geometry size specified, do nothing. */
395   n = 0;
396   XtSetArg( args[ n ], XmNgeometry, &geometry ); n++;
397   XtGetValues( toplevel, args, n );
398 
399   if( geometry != NULL && strpbrk( geometry, "xX" ) != NULL )
400     return;
401 
402   /* Find the max height and width of the form. */
403   sprintf( buffer, "%sBase.%sFo", name, name );
404 
405   tempW = XtNameToWidget( toplevel, buffer );
406   if( tempW == NULL )
407     return;
408 
409   ok = xitGetChildren( tempW, &num_children, &children );
410   if( ! ok )
411     return;
412 
413   for( index = 0; index < num_children; index++ ) {
414     n = 0;
415     XtSetArg( args[ n ], XmNx,      &x ); n++;
416     XtSetArg( args[ n ], XmNy,      &y ); n++;
417     XtSetArg( args[ n ], XmNwidth,  &width ); n++;
418     XtSetArg( args[ n ], XmNheight, &height ); n++;
419     XtGetValues( *(children + index ), args, n );
420 
421     if( x + width > user_width )
422       user_width = x + width;
423 
424     if( y + height > user_height )
425       user_height = y + height;
426   }
427 
428   if( ! tight ) {
429     user_height = user_height + 10;
430     user_width  = user_width  + 10;
431   }
432 
433   /* Min sizes saved as user data in widget nameBase. */
434   sprintf( buffer, "%sBase", name );
435 
436   tempW = XtNameToWidget( toplevel, buffer );
437   n = 0;
438   XtSetArg( args[ n ], XmNuserData, &user_data ); n++;
439   XtGetValues( tempW, args, n );
440 
441   min_size_ref = (MIN_SIZE_REF) user_data;
442 
443 
444   /* Set the min sizes of the shell. */
445   if( user_width > min_size_ref -> min_width )
446     width = user_width;
447   else
448     width = min_size_ref -> min_width;
449 
450   height = min_size_ref -> min_height + user_height;
451 
452 
453   /* Let the form tell how big it wants to be. */
454   sprintf( buffer, "%sBase", name );
455 
456   tempW = XtNameToWidget( toplevel, buffer );
457   n = 0;
458   XtSetArg( args[ n ], XmNwidth,  width ); n++;
459   XtSetArg( args[ n ], XmNheight, height ); n++;
460   XtSetValues( tempW, args, n );
461 
462 
463   SysFree( name );
464 
465 
466   return;
467 
468 } /* xitSetSizeToplevelDialog */
469 
470 
471 /*----------------------------------------------------------------------*/
472 
473 static void
destroySizeDataCB(Widget widget,MIN_SIZE_REF size_ref,XmAnyCallbackStruct * call_data)474   destroySizeDataCB( Widget               widget,
475                      MIN_SIZE_REF         size_ref,
476                      XmAnyCallbackStruct  *call_data )
477 {
478 
479   /* Code. */
480 
481   SysFree( size_ref );
482 
483 
484   return;
485 
486 } /* destroySizeDataCB */
487 
488 
489 /*----------------------------------------------------------------------*/
490 
491 static void
removeCB(Widget widget,Widget toplevel_widget,XmAnyCallbackStruct * call_data)492   removeCB( Widget               widget,
493             Widget               toplevel_widget,
494             XmAnyCallbackStruct  *call_data )
495 {
496 
497   /* Code. */
498 
499   XtDestroyWidget( toplevel_widget );
500 
501   return;
502 
503 } /* removeCB */
504 
505 
506