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