1 /*---------------------------------------------------------------------------- 2 -- 3 -- Module: XmUbArrowLabel 4 -- 5 -- Project: XmUb - Ulle's Motif widgets 6 -- System: 7 -- Subsystem: <> 8 -- Function block: <> 9 -- 10 -- Description: 11 -- This is the implementation of the widget. 12 -- 13 -- Filename: XmUbArrLab.c 14 -- 15 -- Authors: Roger Larsson, Ulrika Bornetun 16 -- Creation date: 1992-04-28 17 -- 18 -- 19 -- (C) Copyright Ulrika Bornetun, Roger Larsson (1995) 20 -- All rights reserved 21 -- 22 -- Permission to use, copy, modify, and distribute this software and its 23 -- documentation for any purpose and without fee is hereby granted, 24 -- provided that the above copyright notice appear in all copies. Ulrika 25 -- Bornetun and Roger Larsson make no representations about the usability 26 -- of this software for any purpose. It is provided "as is" without express 27 -- or implied warranty. 28 ----------------------------------------------------------------------------*/ 29 30 /* SCCS module identifier. */ 31 static char SCCSID[] = "@(#) Module: XmUbArrLab.c, Version: 1.1, Date: 95/02/18 15:10:06"; 32 33 34 /*---------------------------------------------------------------------------- 35 -- Include files 36 ----------------------------------------------------------------------------*/ 37 38 #include <stdio.h> 39 #include <string.h> 40 #include <X11/Intrinsic.h> 41 #include <X11/StringDefs.h> 42 #include <Xm/XmP.h> 43 44 #include <Xm/Label.h> 45 #include <Xm/ArrowB.h> 46 47 /* Private widget header file. */ 48 #include "XmUbArrLabP.h" 49 50 /*---------------------------------------------------------------------------- 51 -- Macro definitions 52 ----------------------------------------------------------------------------*/ 53 54 #ifdef MAX 55 #undef MAX 56 #endif 57 58 #ifdef MIN 59 #undef MIN 60 #endif 61 62 #define MAX( x, y ) ( ( x ) > ( y ) ? ( x ) : ( y ) ) 63 #define MIN( x, y ) ( ( x ) < ( y ) ? ( x ) : ( y ) ) 64 65 #define XmUbAL_CHILD_ERROR -1 66 67 /* Resource converters. */ 68 #define XmRarrowPlacement "ArrowPlacement" 69 70 71 /*---------------------------------------------------------------------------- 72 -- Type declarations 73 ----------------------------------------------------------------------------*/ 74 75 typedef struct { 76 77 Dimension width; 78 Dimension height; 79 Position x; 80 Position y; 81 82 } KidDimensionRec; 83 84 /*---------------------------------------------------------------------------- 85 -- Global definitions 86 ----------------------------------------------------------------------------*/ 87 88 /* Internal Motif functions (how do we know about this....?) */ 89 extern void 90 _XmBackgroundColorDefault(); 91 92 93 /* The arrow label resource list. */ 94 static XtResource resources[] = { 95 { 96 XmNactivateCallback, 97 XmCCallback, 98 XmRCallback, sizeof( XtCallbackList ), 99 XtOffset( XmUbArrowLabelWidget, al.activate_callback ), 100 XmRCallback, 101 NULL 102 }, 103 { 104 XmNlabelString, 105 XmCXmString, 106 XmRXmString, sizeof( XmString ), 107 XtOffset( XmUbArrowLabelWidget, al.label_string ), 108 XtRImmediate, 109 (XtPointer) NULL 110 }, 111 { 112 XmNmarginHeight, 113 XmCMarginHeight, 114 XtRDimension, sizeof( Dimension ), 115 XtOffset( XmUbArrowLabelWidget, al.margin_height ), 116 XtRImmediate, 117 (XtPointer) 0 118 }, 119 { 120 XmNmarginWidth, 121 XmCMarginWidth, 122 XtRDimension, sizeof( Dimension ), 123 XtOffset( XmUbArrowLabelWidget, al.margin_width ), 124 XtRImmediate, 125 (XtPointer) 0 126 }, 127 { 128 XmUbNalArrowOrientation, 129 XmCOrientation, 130 XmROrientation, sizeof( unsigned char ), 131 XtOffset( XmUbArrowLabelWidget, al.arrow_orientation ), 132 XmRImmediate, 133 (XtPointer) XmHORIZONTAL 134 }, 135 { 136 XmUbNalArrowPlacement, 137 XmUbCAlArrowPlacement, 138 XmRarrowPlacement, sizeof( arrowPlacement ), 139 XtOffset( XmUbArrowLabelWidget, al.arrow_placement ), 140 XmRImmediate, 141 (XtPointer) XmUbARROWS_SPREAD_OUT 142 }, 143 { 144 XmNspacing, 145 XmCSpacing, 146 XtRDimension, sizeof( Dimension ), 147 XtOffset( XmUbArrowLabelWidget, al.spacing ), 148 XtRImmediate, 149 (XtPointer) 2 150 }, 151 { 152 XmUbNalRecomputeHeight, 153 XmUbCAlRecomputeHeight, 154 XtRBoolean, sizeof( Boolean ), 155 XtOffset( XmUbArrowLabelWidget, al.recompute_height ), 156 XtRImmediate, 157 (XtPointer) True 158 }, 159 { 160 XmUbNalRecomputeWidth, 161 XmUbCAlRecomputeWidth, 162 XtRBoolean, sizeof( Boolean ), 163 XtOffset( XmUbArrowLabelWidget, al.recompute_width ), 164 XtRImmediate, 165 (XtPointer) True 166 }, 167 168 }; /* resources */ 169 170 171 /*---------------------------------------------------------------------------- 172 -- Function prototypes 173 ----------------------------------------------------------------------------*/ 174 175 /* Class methods. */ 176 static void 177 ClassInitialize(); 178 179 static void 180 ChangeManaged( Widget widget ); 181 182 static void 183 DeleteChild( Widget widget ); 184 185 static void 186 Destroy( Widget widget ); 187 188 static XtGeometryResult 189 GeometryManager( Widget widget, 190 XtWidgetGeometry *request, 191 XtWidgetGeometry *reply ); 192 193 static void 194 Initialize( Widget treq, 195 Widget tnew, 196 ArgList args, 197 Cardinal *num_args ); 198 199 static void 200 InsertChild( Widget widget ); 201 202 static XtGeometryResult 203 QueryGeometry( Widget widget, 204 XtWidgetGeometry *proposed, 205 XtWidgetGeometry *answer ); 206 207 static void 208 Resize( Widget widget ); 209 210 static Boolean 211 SetValues( Widget current, 212 Widget request, 213 Widget new, 214 ArgList args, 215 Cardinal *num_args ); 216 217 218 /* Internal functions. */ 219 220 221 static void 222 ArrowButtonActivatedCB( Widget arrow_button, 223 XmUbArrowLabelWidget al, 224 XmArrowButtonCallbackStruct *call_data ); 225 226 /* If not in the child list, returns XmUbMD_CHILD_ERROR. */ 227 static int 228 ChildIndex( XmUbArrowLabelWidget al, 229 Widget child ); 230 231 static void 232 ConvertToArrowPlacement( XrmValue *args, 233 Cardinal *num_args, 234 XrmValue *from, 235 XrmValue *to ); 236 237 238 static void 239 CreateInternalWidgets( XmUbArrowLabelWidget al ); 240 241 /* The sizes array must have been processed by GetChildPrefSizes 242 before DoLayout is called. */ 243 static void 244 DoLayout( XmUbArrowLabelWidget al, 245 KidDimensionRec sizes[] ); 246 247 /* Fills in the width and height fields in the kids dimension recs. */ 248 static void 249 GetChildPrefSizes( XmUbArrowLabelWidget al, 250 Widget initiator, 251 XtWidgetGeometry *request, 252 KidDimensionRec sizes[] ); 253 254 255 /* The sizes array must have been prepared by GetChildPrefSizes before this 256 function is called. */ 257 static void 258 GetOwnPreferredSize( XmUbArrowLabelWidget al, 259 KidDimensionRec sizes[], 260 Dimension *pref_width, 261 Dimension *pref_height ); 262 263 static void 264 GetValuesHook( Widget w, 265 ArgList args, 266 Cardinal *num_args ); 267 268 static void 269 KidsPreferredGeometry( Widget kid, 270 Widget initiator, 271 XtWidgetGeometry *request, 272 XtWidgetGeometry *desired ); 273 274 /* ResizeIfNeeded fills in the sizes array. Does not have to be initialized. */ 275 static Boolean 276 ResizeIfNeeded( XmUbArrowLabelWidget al, 277 KidDimensionRec sizes[] ); 278 279 static void 280 WarningNoResourceChange( XmUbArrowLabelWidget al, 281 String resource ); 282 283 /*---------------------------------------------------------------------------- 284 -- Initialization of the class record. 285 ----------------------------------------------------------------------------*/ 286 287 /* This initialization has to be done after the methods have been declared. */ 288 XmUbArrowLabelClassRec xmUbArrowLabelClassRec = { 289 290 { /* Core class fields. */ 291 /* superclass */ (WidgetClass) &xmManagerClassRec, 292 /* class_name */ "XmUbArrowLabel", 293 /* widget_size */ sizeof( XmUbArrowLabelRec ), 294 /* class_initialize */ ClassInitialize, 295 /* class_part_initialize */ NULL, 296 /* class_inited */ False, 297 /* initialize */ Initialize, 298 /* initialize_hook */ NULL, 299 /* realize */ XtInheritRealize, 300 /* actions */ NULL, 301 /* num_actions */ 0, 302 /* resources */ resources, 303 /* num_resources */ XtNumber( resources ), 304 /* xrm_class */ NULLQUARK, 305 /* compress_motion */ True, 306 /* compress_exposure */ True, 307 /* compress_enterleave */ True, 308 /* visible_interest */ False, 309 /* destroy */ Destroy, 310 /* resize */ Resize, 311 /* expose */ NULL, 312 /* set_values */ SetValues, 313 /* set_values_hook */ NULL, 314 /* set_values_almost */ XtInheritSetValuesAlmost, 315 /* get_values_hook */ GetValuesHook, 316 /* accept_focus */ NULL, 317 /* version */ XtVersion, 318 /* callback_private */ NULL, 319 /* tm_table */ NULL, 320 /* query_geometry */ QueryGeometry, 321 /* display_accelerator */ XtInheritDisplayAccelerator, 322 /* extension */ NULL 323 }, 324 { /* Composite class part. */ 325 /* geometry_manager */ GeometryManager, 326 /* change_managed */ ChangeManaged, 327 /* insert_child */ InsertChild, 328 /* delete_child */ DeleteChild, 329 /* extension */ NULL 330 }, 331 { /* Constraint class fields. */ 332 /* subresources */ NULL, 333 /* subresource_count */ 0, 334 /* constraint_size */ sizeof( 335 XmUbArrowLabelConstraintsRec ), 336 /* initialize */ NULL, 337 /* destroy */ NULL, 338 /* set_values */ NULL, 339 /* extension */ NULL 340 }, 341 { /* XmManager class part. */ 342 /* translations */ NULL, 343 /* get_resources */ NULL, 344 /* num_get_resources */ 0, 345 /* get_constraint_resources */ NULL, 346 /* num_get_constraint_resources */ 0, 347 /* extension */ NULL 348 }, 349 { /* Arrow label class part. */ 350 /* extension */ NULL 351 }, 352 353 }; 354 355 356 /* Class record pointer. */ 357 WidgetClass 358 xmUbArrowLabelWidgetClass = (WidgetClass) &xmUbArrowLabelClassRec; 359 360 361 362 /*---------------------------------------------------------------------------- 363 -- Functions 364 ----------------------------------------------------------------------------*/ 365 366 367 static void ArrowButtonActivatedCB(Widget arrow_button,XmUbArrowLabelWidget al,XmArrowButtonCallbackStruct * call_data)368 ArrowButtonActivatedCB( Widget arrow_button, 369 XmUbArrowLabelWidget al, 370 XmArrowButtonCallbackStruct *call_data ) 371 { 372 /* Variables. */ 373 XmUbArrowLabelCallbackStruct cb; 374 int child_index; 375 376 /* Code. */ 377 378 /* Find out if it was the forwards or backwards button that was pressed. */ 379 child_index = ChildIndex( al, arrow_button ); 380 381 switch( child_index ){ 382 383 case XmUbAL_CHILD_BACK_ARROW: 384 cb.reason = XmUbCR_BACK_ARROW_ACTIVATED; 385 break; 386 387 case XmUbAL_CHILD_FORWARD_ARROW: 388 cb.reason = XmUbCR_FORWARD_ARROW_ACTIVATED; 389 break; 390 391 default: 392 /* Something is wrong. */ 393 return; 394 } 395 396 cb.event = call_data -> event; 397 cb.child = arrow_button; 398 399 /* Invoke the callbacks. */ 400 XtCallCallbackList( (Widget) al, al -> al.activate_callback, 401 (XtPointer) &cb ); 402 403 404 return; 405 406 } /* ArrowButtonActivatedCB */ 407 408 409 /*----------------------------------------------------------------------*/ 410 411 static void ClassInitialize()412 ClassInitialize() 413 { 414 /* Code. */ 415 416 /* Register type converters. */ 417 XtAddConverter( XmRString, XmRarrowPlacement, 418 ConvertToArrowPlacement, NULL, 0 ); 419 420 return; 421 422 } /* ClassInitialize */ 423 424 425 /*----------------------------------------------------------------------*/ 426 427 static void ChangeManaged(Widget widget)428 ChangeManaged( Widget widget ) 429 { 430 /* Variables. */ 431 Boolean layout_done; 432 KidDimensionRec kids_sizes[ NO_INTERNAL_CHILDREN ]; 433 XmUbArrowLabelWidget al; 434 435 436 /* Code. */ 437 438 al = (XmUbArrowLabelWidget) widget; 439 440 /* ResizeIfNeeded checks the size of all children and resizes the widget. */ 441 layout_done = ResizeIfNeeded( al, kids_sizes ); 442 443 /* Do the layout. */ 444 if( !layout_done ) 445 DoLayout( al, kids_sizes ); 446 447 448 return; 449 450 } /* ChangeManaged */ 451 452 453 /*----------------------------------------------------------------------*/ 454 455 static int ChildIndex(XmUbArrowLabelWidget al,Widget child)456 ChildIndex( XmUbArrowLabelWidget al, 457 Widget child ) 458 { 459 /* Variables. */ 460 int index; 461 462 /* Code. */ 463 464 for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){ 465 466 if( al -> al.internal_children[ index ] == child ) 467 return index; 468 469 } /* for */ 470 471 472 /* Specified child not found. */ 473 return XmUbAL_CHILD_ERROR; 474 475 } /* ChildIndex */ 476 477 478 /*----------------------------------------------------------------------*/ 479 480 static void ConvertToArrowPlacement(XrmValue * args,Cardinal * num_args,XrmValue * from,XrmValue * to)481 ConvertToArrowPlacement( XrmValue *args, 482 Cardinal *num_args, 483 XrmValue *from, 484 XrmValue *to ) 485 { 486 487 /* Variables. */ 488 static arrowPlacement conv_arrow_placement; 489 490 491 /* Code. */ 492 493 if( *num_args != 0 ) 494 XtWarningMsg( "wrongParameters", "ConvertToArrowPlacement", 495 "XtToolkitError", "Conversion needs no extra arguments", 496 (String *) NULL, (Cardinal *) NULL ); 497 498 if( strcmp( (char *) from -> addr, "ARROWS_LEFT" ) == 0 ) 499 conv_arrow_placement = XmUbARROWS_LEFT; 500 501 else if( strcmp( (char *) from -> addr, "ARROWS_SPREAD_OUT" ) == 0 ) 502 conv_arrow_placement = XmUbARROWS_SPREAD_OUT; 503 504 else if( strcmp( (char *) from -> addr, "ARROWS_RIGHT" ) == 0 ) 505 conv_arrow_placement = XmUbARROWS_RIGHT; 506 507 else { 508 XtWarningMsg( "wrongParameters", "ConvertToArrowPlacement", 509 "XtToolkitError", "Cannot convert to type arrowPlacement", 510 (String *) NULL, (Cardinal *) 0 ); 511 conv_arrow_placement = XmUbARROWS_SPREAD_OUT; 512 } 513 514 ( *to ).size = sizeof( arrowPlacement ); 515 ( *to ).addr = (XtPointer) &conv_arrow_placement; 516 517 518 return; 519 520 } /* ConvertToArrowPlacement */ 521 522 523 /*----------------------------------------------------------------------*/ 524 525 static void CreateInternalWidgets(XmUbArrowLabelWidget al)526 CreateInternalWidgets( XmUbArrowLabelWidget al ) 527 { 528 /* Variables. */ 529 Arg args[ 5 ]; 530 Cardinal n; 531 char *name_buffer; 532 String wname; 533 534 /* Code. */ 535 536 /* Get the name of the "parent" widget. */ 537 wname = XtName( (Widget)al ); 538 539 name_buffer = XtMalloc( strlen( wname ) + 4 ); 540 541 /* The two arrow buttons. */ 542 /* Backwards button. */ 543 sprintf( name_buffer, "%sBa", wname ); 544 n = 0; 545 if( al -> al.arrow_orientation == XmHORIZONTAL ){ 546 XtSetArg( args[ n ], XmNarrowDirection, XmARROW_LEFT ); n++; 547 } else { 548 XtSetArg( args[ n ], XmNarrowDirection, XmARROW_UP ); n++; 549 } 550 551 al -> al.internal_children[ XmUbAL_CHILD_BACK_ARROW ] = 552 XmCreateArrowButton( (Widget) al, name_buffer, args, n ); 553 554 XtAddCallback( al -> al.internal_children[ XmUbAL_CHILD_BACK_ARROW ], 555 XmNactivateCallback, 556 (XtCallbackProc) ArrowButtonActivatedCB, (XtPointer) al ); 557 558 /* Forward button. */ 559 sprintf( name_buffer, "%sFa", wname ); 560 n = 0; 561 if( al -> al.arrow_orientation == XmHORIZONTAL ){ 562 XtSetArg( args[ n ], XmNarrowDirection, XmARROW_RIGHT ); n++; 563 } else { 564 XtSetArg( args[ n ], XmNarrowDirection, XmARROW_DOWN ); n++; 565 } 566 567 al -> al.internal_children[ XmUbAL_CHILD_FORWARD_ARROW ] = 568 XmCreateArrowButton( (Widget) al, name_buffer, args, n ); 569 570 XtAddCallback( al -> al.internal_children[ XmUbAL_CHILD_FORWARD_ARROW ], 571 XmNactivateCallback, 572 (XtCallbackProc) ArrowButtonActivatedCB, (XtPointer) al ); 573 574 /* The label. */ 575 sprintf( name_buffer, "%sLb", wname ); 576 577 n = 0; 578 if( al -> al.label_string != NULL ){ 579 XtSetArg( args[ n ], XmNlabelString, al -> al.label_string ); n++; 580 } 581 582 al -> al.internal_children[ XmUbAL_CHILD_LABEL ] = 583 XmCreateLabel( (Widget) al, name_buffer, args, n ); 584 585 586 XtManageChildren( al -> al.internal_children, NO_INTERNAL_CHILDREN ); 587 588 XtFree( name_buffer ); 589 590 591 return; 592 593 } /* CreateInternalWidgets */ 594 595 596 /*----------------------------------------------------------------------*/ 597 598 static void DeleteChild(Widget widget)599 DeleteChild( Widget widget ) 600 { 601 602 /* Variables. */ 603 int index; 604 XmUbArrowLabelWidget al; 605 606 /* Code. */ 607 608 al = (XmUbArrowLabelWidget) XtParent( widget ); 609 610 /* Clear the internal reference. */ 611 for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){ 612 if( al -> al.internal_children[ index ] == widget ){ 613 al -> al.internal_children[ index ] = NULL; 614 break; 615 } 616 } 617 618 /* Perform the actual operation */ 619 (* ( (CompositeWidgetClass) (xmUbArrowLabelWidgetClass -> 620 core_class.superclass) ) -> composite_class.delete_child ) ( widget ); 621 622 623 return; 624 625 } /* DeleteChild */ 626 627 628 /*----------------------------------------------------------------------*/ 629 630 static void Destroy(Widget widget)631 Destroy( Widget widget ) 632 { 633 /* Variables. */ 634 XmUbArrowLabelWidget al; 635 636 /* Code. */ 637 638 al = (XmUbArrowLabelWidget) widget; 639 640 /* Free copied XmStrings. */ 641 if( al -> al.label_string != NULL ) 642 XmStringFree( al -> al.label_string ); 643 644 /* Remove callbacks. */ 645 XtRemoveAllCallbacks( widget, XmNactivateCallback ); 646 647 648 return; 649 650 } /* Destroy */ 651 652 653 /*----------------------------------------------------------------------*/ 654 655 static void DoLayout(XmUbArrowLabelWidget al,KidDimensionRec sizes[])656 DoLayout( XmUbArrowLabelWidget al, 657 KidDimensionRec sizes[] ) 658 { 659 /* Variables. */ 660 int index; 661 Widget kid; 662 Dimension max_height; 663 Dimension offset; 664 665 /* Code. */ 666 667 /* Let the arrows keep their sizes, and let the label size shrink and 668 grow. */ 669 670 /* Start by calculating the label's width. */ 671 offset = sizes[ XmUbAL_CHILD_BACK_ARROW ].width + 672 sizes[ XmUbAL_CHILD_FORWARD_ARROW ].width + 673 2 * al -> al.margin_width + 2 * al -> al.spacing; 674 675 if( offset > al -> core.width ) 676 sizes[ XmUbAL_CHILD_LABEL ].width = 1; 677 else 678 sizes[ XmUbAL_CHILD_LABEL ].width = al -> core.width - offset; 679 680 /* The widgets may keep their heights. */ 681 682 /* The placement resource decides the x position. */ 683 switch( al -> al.arrow_placement ){ 684 685 case XmUbARROWS_LEFT: 686 sizes[ XmUbAL_CHILD_BACK_ARROW ].x = (Position) al -> al.margin_width; 687 688 sizes[ XmUbAL_CHILD_FORWARD_ARROW ].x = 689 sizes[ XmUbAL_CHILD_BACK_ARROW ].x + 690 (Position) sizes[ XmUbAL_CHILD_BACK_ARROW ].width + 691 (Position) al -> al.spacing; 692 693 sizes[ XmUbAL_CHILD_LABEL ].x = sizes[ XmUbAL_CHILD_FORWARD_ARROW ].x + 694 (Position) sizes[ XmUbAL_CHILD_FORWARD_ARROW ].width + 695 (Position) al -> al.spacing; 696 697 break; 698 699 case XmUbARROWS_RIGHT: 700 sizes[ XmUbAL_CHILD_LABEL ].x = (Position) al -> al.margin_width; 701 702 sizes[ XmUbAL_CHILD_BACK_ARROW ].x = sizes[ XmUbAL_CHILD_LABEL ].x + 703 (Position) sizes[ XmUbAL_CHILD_LABEL ].width + 704 (Position) al -> al.spacing; 705 706 sizes[ XmUbAL_CHILD_FORWARD_ARROW ].x = 707 sizes[ XmUbAL_CHILD_BACK_ARROW ].x + 708 (Position) sizes[ XmUbAL_CHILD_BACK_ARROW ].width + 709 (Position) al -> al.spacing; 710 711 break; 712 713 case XmUbARROWS_SPREAD_OUT: 714 sizes[ XmUbAL_CHILD_BACK_ARROW ].x = (Position) al -> al.margin_width; 715 716 sizes[ XmUbAL_CHILD_LABEL ].x = sizes[ XmUbAL_CHILD_BACK_ARROW ].x + 717 (Position) sizes[ XmUbAL_CHILD_BACK_ARROW ].width + 718 (Position) al -> al.spacing; 719 720 sizes[ XmUbAL_CHILD_FORWARD_ARROW ].x = sizes[ XmUbAL_CHILD_LABEL ].x + 721 (Position) sizes[ XmUbAL_CHILD_LABEL ].width + 722 (Position) al -> al.spacing; 723 724 break; 725 726 } /* switch */ 727 728 729 /* Vertical positions. */ 730 max_height = 0; 731 for( index = XmUbAL_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ){ 732 if( sizes[ index ].height > max_height ) 733 max_height = sizes[ index ].height; 734 } 735 736 for( index = XmUbAL_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ) 737 sizes[ index ].y = (Position) ( max_height - sizes[ index ].height ) / 2; 738 739 /* Configure the children. */ 740 /* All positions and dimensions are now in the sizes array. */ 741 for( index = XmUbAL_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ){ 742 743 kid = al -> al.internal_children[ index ]; 744 745 if( ( kid != NULL ) && XtIsManaged( kid ) ) 746 XtConfigureWidget( kid, sizes[ index ].x, sizes[ index ].y, 747 sizes[ index ].width, sizes[ index ].height, 748 kid -> core.border_width ); 749 } 750 751 752 return; 753 754 } /* DoLayout */ 755 756 757 /*----------------------------------------------------------------------*/ 758 759 static XtGeometryResult GeometryManager(Widget widget,XtWidgetGeometry * request,XtWidgetGeometry * reply)760 GeometryManager( Widget widget, 761 XtWidgetGeometry *request, 762 XtWidgetGeometry *reply ) 763 { 764 765 XmUbArrowLabelWidget al; 766 XtWidgetGeometry own_request; 767 Dimension old_width, old_height; 768 Dimension pref_height; 769 Dimension pref_width; 770 KidDimensionRec kids_sizes[ NO_INTERNAL_CHILDREN ]; 771 XtGeometryResult result; 772 773 /* Code. */ 774 775 al = (XmUbArrowLabelWidget) XtParent( widget ); 776 777 /* Find out how big the widget would be if the resize were allowed. */ 778 GetChildPrefSizes( al, NULL, request, kids_sizes ); 779 GetOwnPreferredSize( al, kids_sizes, &pref_width, &pref_height ); 780 781 /* If no change in dimensions, allow the request. */ 782 if( ( pref_width == al -> core.width ) && 783 ( pref_height == al -> core.height )){ 784 DoLayout( al, kids_sizes ); 785 return XtGeometryYes; 786 } 787 788 /* We must ask our parent to resize us. */ 789 own_request.request_mode = CWWidth | CWHeight; 790 own_request.width = pref_width; 791 own_request.height = pref_height; 792 793 /* Save dimensions. */ 794 old_width = al -> core.width; 795 old_height = al -> core.height; 796 797 al -> al.resize_called = False; 798 799 /* We are not interested in any compromise geometry. */ 800 result = XtMakeGeometryRequest( (Widget) al, &own_request, NULL ); 801 802 /* Reset to old dimensions if request not granted. */ 803 if( result != XtGeometryYes ){ 804 al -> core.width = old_width; 805 al -> core.height = old_height; 806 807 } else { 808 if( !al -> al.resize_called ) 809 Resize( (Widget) al ); 810 } 811 812 /* !!!!!!!!!!!!!!!!!!!!!! */ 813 /* Always grant child's request. */ 814 return XtGeometryYes; 815 816 } /* GeometryManager */ 817 818 819 /*----------------------------------------------------------------------*/ 820 821 static void GetChildPrefSizes(XmUbArrowLabelWidget al,Widget initiator,XtWidgetGeometry * request,KidDimensionRec sizes[])822 GetChildPrefSizes( XmUbArrowLabelWidget al, 823 Widget initiator, 824 XtWidgetGeometry *request, 825 KidDimensionRec sizes[] ) 826 { 827 /* Variables. */ 828 XtWidgetGeometry desired; 829 int index; 830 Widget kid; 831 832 /* Code. */ 833 834 /* Initialize. */ 835 for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){ 836 sizes[ index ].width = 0; 837 sizes[ index ].height = 0; 838 sizes[ index ].x = 0; 839 sizes[ index ].y = 0; 840 } 841 842 /* Get the preferred sizes for the children. */ 843 for( index = XmUbAL_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ){ 844 845 kid = al -> al.internal_children[ index ]; 846 847 if( ( kid != NULL ) && XtIsManaged( kid ) ){ 848 849 KidsPreferredGeometry( kid, initiator, request, &desired ); 850 851 sizes[ index ].width = desired.width; 852 sizes[ index ].height = desired.height; 853 854 } 855 856 } /* for */ 857 858 859 return; 860 861 } /* GetChildPrefSizes */ 862 863 864 /*----------------------------------------------------------------------*/ 865 866 static void GetOwnPreferredSize(XmUbArrowLabelWidget al,KidDimensionRec sizes[],Dimension * pref_width,Dimension * pref_height)867 GetOwnPreferredSize( XmUbArrowLabelWidget al, 868 KidDimensionRec sizes[], 869 Dimension *pref_width, 870 Dimension *pref_height ) 871 { 872 /* Code. */ 873 874 /* All layouts arrange the widgets horizontally, so calculating the 875 preferred size is simple. */ 876 877 *pref_width = sizes[ XmUbAL_CHILD_BACK_ARROW ].width + 878 sizes[ XmUbAL_CHILD_FORWARD_ARROW ].width + 879 sizes[ XmUbAL_CHILD_LABEL ].width + 880 2 * al -> al.margin_width + 881 2 * al -> al.spacing; 882 883 *pref_height = MAX( sizes[ XmUbAL_CHILD_LABEL ].height, 884 MAX( sizes[ XmUbAL_CHILD_BACK_ARROW ].height, 885 sizes[ XmUbAL_CHILD_FORWARD_ARROW ].height ) ) + 886 2 * al -> al.margin_height; 887 888 return; 889 890 } /* GetOwnPreferredSize */ 891 892 893 /*----------------------------------------------------------------------*/ 894 895 static void GetValuesHook(Widget w,ArgList args,Cardinal * num_args)896 GetValuesHook( Widget w, 897 ArgList args, 898 Cardinal *num_args ) 899 { 900 /* Variables. */ 901 int index; 902 XmUbArrowLabelWidget al; 903 904 /* Code. */ 905 906 al = (XmUbArrowLabelWidget) w; 907 908 /* Copy the XmStrings. */ 909 for( index = 0; index < *num_args; index ++ ){ 910 911 if( strcmp( args[ index ].name, XmNlabelString ) == 0 ){ 912 * ( XmString *) ( args[ index ].value ) = 913 XmStringCopy( al -> al.label_string ); 914 915 } 916 } 917 918 919 return; 920 921 } /* GetValuesHook */ 922 923 924 /*----------------------------------------------------------------------*/ 925 926 static void Initialize(Widget treq,Widget tnew,ArgList args,Cardinal * num_args)927 Initialize( Widget treq, 928 Widget tnew, 929 ArgList args, 930 Cardinal *num_args ) 931 { 932 /* Variables. */ 933 int index; 934 KidDimensionRec kids_sizes[ NO_INTERNAL_CHILDREN ]; 935 XmUbArrowLabelWidget new; 936 Dimension pref_height; 937 Dimension pref_width; 938 XmString xm; 939 940 /* Code. */ 941 942 new = (XmUbArrowLabelWidget) tnew; 943 944 /* Initialize private fields. */ 945 /* Nullify all widget ids. */ 946 for( index = XmUbAL_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ) 947 new -> al.internal_children[ index ] = NULL; 948 949 /* Start size if none supplied. */ 950 if( new -> core.width == 0 ) 951 new -> core.width = 300; 952 else 953 new -> al.recompute_width = False; 954 955 if( new -> core.height == 0 ) 956 new -> core.height = 100; 957 else 958 new -> al.recompute_height = False; 959 960 /* Copy XmStrings. */ 961 if( new -> al.label_string != NULL ){ 962 xm = XmStringCopy( new -> al.label_string ); 963 new -> al.label_string = xm; 964 } 965 966 967 /* Create the internal widgets. */ 968 new -> al.internal_widgets_created = False; 969 970 CreateInternalWidgets( new ); 971 972 new -> al.internal_widgets_created = True; 973 974 /* Set the desired size of the widget. */ 975 GetChildPrefSizes( new, NULL, NULL, kids_sizes ); 976 GetOwnPreferredSize( new, kids_sizes, &pref_width, &pref_height ); 977 978 new -> core.width = pref_width; 979 new -> core.height = pref_height; 980 981 DoLayout( new, kids_sizes ); 982 983 984 return; 985 986 } /* Initialize */ 987 988 989 /*----------------------------------------------------------------------*/ 990 991 static void InsertChild(Widget widget)992 InsertChild( Widget widget ) 993 { 994 995 /* Variables. */ 996 Cardinal num_params; 997 String params[ 1 ]; 998 XmUbArrowLabelWidget al; 999 1000 /* Code. */ 1001 1002 al = (XmUbArrowLabelWidget) XtParent( widget ); 1003 1004 /* We do not allow the application to create children. */ 1005 if( al -> al.internal_widgets_created ){ 1006 1007 params[ 0 ] = XtClass( (Widget) al ) -> core_class.class_name; 1008 num_params = 1; 1009 XtAppErrorMsg( XtWidgetToApplicationContext( widget ), 1010 "childError", "number", "WidgetError", 1011 "Applications cannot add children to %s widgets.", 1012 params, &num_params ); 1013 } 1014 1015 /* This is an internal child. Adding it is OK. */ 1016 (* ( (CompositeWidgetClass) (xmUbArrowLabelWidgetClass -> 1017 core_class.superclass) ) -> composite_class.insert_child ) ( widget ); 1018 1019 1020 return; 1021 1022 } /* InsertChild */ 1023 1024 1025 /*----------------------------------------------------------------------*/ 1026 1027 static void KidsPreferredGeometry(Widget kid,Widget initiator,XtWidgetGeometry * request,XtWidgetGeometry * desired)1028 KidsPreferredGeometry( Widget kid, 1029 Widget initiator, 1030 XtWidgetGeometry *request, 1031 XtWidgetGeometry *desired ) 1032 { 1033 1034 /* Code. */ 1035 1036 if( ( kid == initiator ) && ( request != NULL ) ){ 1037 /* The initiator should not be queried. */ 1038 if( request -> request_mode & CWWidth ) 1039 desired -> width = request -> width; 1040 else 1041 desired -> width = (Dimension) kid -> core.width; 1042 1043 if( request -> request_mode & CWHeight ) 1044 desired -> height = request -> height; 1045 else 1046 desired -> height = (Dimension) kid -> core.height; 1047 1048 } else 1049 (void) XtQueryGeometry( kid, NULL, desired ); 1050 1051 1052 return; 1053 1054 } /* KidsPreferredGeometry */ 1055 1056 1057 /*----------------------------------------------------------------------*/ 1058 1059 static void Resize(Widget widget)1060 Resize( Widget widget ) 1061 { 1062 /* Variables. */ 1063 KidDimensionRec kids_sizes[ NO_INTERNAL_CHILDREN ]; 1064 XmUbArrowLabelWidget al; 1065 1066 /* Code. */ 1067 1068 al = (XmUbArrowLabelWidget) widget; 1069 1070 al -> al.resize_called = True; 1071 1072 /* We have to get the preferred size of the children before we organize 1073 the layout. */ 1074 GetChildPrefSizes( al, NULL, NULL, kids_sizes ); 1075 DoLayout( al, kids_sizes ); 1076 1077 1078 return; 1079 1080 } /* Resize */ 1081 1082 1083 /*----------------------------------------------------------------------*/ 1084 1085 static Boolean ResizeIfNeeded(XmUbArrowLabelWidget al,KidDimensionRec sizes[])1086 ResizeIfNeeded( XmUbArrowLabelWidget al, 1087 KidDimensionRec sizes[] ) 1088 { 1089 1090 /* Variables. */ 1091 Boolean layout_done; 1092 Dimension pref_height; 1093 Dimension pref_width; 1094 XtWidgetGeometry request; 1095 XtGeometryResult result; 1096 1097 /* Code. */ 1098 1099 /* Initialize. */ 1100 layout_done = False; 1101 1102 /* Get the preferred dimensions of the widget. */ 1103 GetChildPrefSizes( al, NULL, NULL, sizes ); 1104 GetOwnPreferredSize( al, sizes, &pref_width, &pref_height ); 1105 1106 /* If we want the same dimensions, no resizing is needed. */ 1107 if(( pref_width == al -> core.width ) && 1108 ( pref_height == al -> core.height )) 1109 return False; 1110 1111 /* Dimensions are different. Try to resize. */ 1112 request.request_mode = CWWidth | CWHeight; 1113 1114 request.width = pref_width; 1115 request.height = pref_height; 1116 1117 al -> al.resize_called = False; 1118 1119 do { 1120 1121 result = XtMakeGeometryRequest( (Widget) al, &request, &request ); 1122 1123 } while( result == XtGeometryAlmost ); 1124 1125 if( result == XtGeometryNo ) 1126 return False; 1127 1128 /* Resize done. Core fields have already been updated. */ 1129 return( al -> al.resize_called ); 1130 1131 } /* ResizeIfNeeded */ 1132 1133 1134 /*----------------------------------------------------------------------*/ 1135 1136 static XtGeometryResult QueryGeometry(Widget widget,XtWidgetGeometry * proposed,XtWidgetGeometry * answer)1137 QueryGeometry( Widget widget, 1138 XtWidgetGeometry *proposed, 1139 XtWidgetGeometry *answer ) 1140 { 1141 1142 KidDimensionRec kids_sizes[ NO_INTERNAL_CHILDREN ]; 1143 XmUbArrowLabelWidget al; 1144 Dimension pref_height; 1145 Dimension pref_width; 1146 1147 /* Code. */ 1148 1149 al = (XmUbArrowLabelWidget) widget; 1150 1151 /* Get dimensions that we *really* want. */ 1152 GetChildPrefSizes( al, NULL, NULL, kids_sizes ); 1153 GetOwnPreferredSize( al, kids_sizes, &pref_width, &pref_height ); 1154 1155 answer -> request_mode = CWWidth | CWHeight; 1156 answer -> width = pref_width; 1157 answer -> height = pref_height; 1158 1159 1160 if( proposed == NULL ){ 1161 /* This is a query for the requested geometry. */ 1162 1163 if(( answer -> height == (int) al -> core.height ) && 1164 ( answer -> width == (int) al -> core.width )) 1165 return XtGeometryNo; 1166 else 1167 return XtGeometryAlmost; 1168 } 1169 1170 /* The parent supplied a geometry suggestion. */ 1171 if(( answer -> height == proposed -> height ) && 1172 ( answer -> width == proposed -> width )) 1173 return XtGeometryYes; 1174 1175 if( ( proposed -> height <= 1 ) || 1176 ( proposed -> width <= 1 ) ) 1177 /* That's too small ! */ 1178 return XtGeometryNo; 1179 1180 1181 /* Only a compromise left. */ 1182 return XtGeometryAlmost; 1183 1184 } /* QueryGeometry */ 1185 1186 1187 /*----------------------------------------------------------------------*/ 1188 1189 static Boolean SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * num_args)1190 SetValues( Widget current, 1191 Widget request, 1192 Widget new, 1193 ArgList args, 1194 Cardinal *num_args ) 1195 { 1196 #ifdef Differs 1197 #undef Differs 1198 #endif 1199 1200 #define Differs( field ) ( curW -> field != newW -> field ) 1201 1202 /* Variables. */ 1203 XmUbArrowLabelWidget curW; 1204 Arg local_args[ 4 ]; 1205 Cardinal n; 1206 XmUbArrowLabelWidget newW; 1207 Boolean visual_changed = False; 1208 XmString xm; 1209 1210 /* Code. */ 1211 1212 curW = (XmUbArrowLabelWidget) current; 1213 newW = (XmUbArrowLabelWidget) new; 1214 1215 /* Width and height. */ 1216 /* Resizing is handled higher up. */ 1217 1218 if( Differs( al.recompute_width ) && newW -> al.recompute_width ) 1219 visual_changed = True; 1220 else if( Differs( core.width ) ) 1221 newW -> al.recompute_width = False; 1222 1223 if( Differs( al.recompute_height ) && newW -> al.recompute_height ) 1224 visual_changed = True; 1225 else if( Differs( core.height ) ) 1226 newW -> al.recompute_height = False; 1227 1228 /* Margins and spacings. */ 1229 if( Differs( al.margin_width ) || 1230 Differs( al.margin_height ) || 1231 Differs( al.spacing ) ) 1232 visual_changed = True; 1233 1234 /* These resources may only be set at creation. */ 1235 if( Differs( al.arrow_orientation ) ){ 1236 WarningNoResourceChange( newW, "XmUbNalArrowOrientation" ); 1237 newW -> al.arrow_orientation = curW -> al.arrow_orientation; 1238 } 1239 if( Differs( al.arrow_placement ) ){ 1240 WarningNoResourceChange( newW, "XmUbNalArrowPlacement" ); 1241 newW -> al.arrow_placement = curW -> al.arrow_placement; 1242 } 1243 1244 /* These resources affect child widgets. */ 1245 if( Differs( al.label_string ) || 1246 Differs( manager.foreground ) || 1247 Differs( core.background_pixel ) ){ 1248 1249 n = 0; 1250 if( Differs( manager.foreground ) ){ 1251 XtSetArg( local_args[ n ], XmNforeground, 1252 newW -> manager.foreground ); n++; 1253 } 1254 if( Differs( core.background_pixel ) ){ 1255 XtSetArg( local_args[ n ], XmNbackground, 1256 newW -> core.background_pixel ); n++; 1257 } 1258 1259 if( n != 0 ){ 1260 XtSetValues( newW -> al.internal_children[ XmUbAL_CHILD_BACK_ARROW ], 1261 local_args, n ); 1262 XtSetValues( newW -> al.internal_children[ XmUbAL_CHILD_FORWARD_ARROW ], 1263 local_args, n ); 1264 } 1265 1266 /* The label is also affected by a label string change. */ 1267 if( Differs( al.label_string ) ){ 1268 if( curW -> al.label_string != NULL ) 1269 XmStringFree( curW -> al.label_string ); 1270 1271 if( newW -> al.label_string != NULL ){ 1272 xm = XmStringCopy( newW -> al.label_string ); 1273 newW -> al.label_string = xm; 1274 } 1275 1276 XtSetArg( local_args[ n ], XmNlabelString, 1277 newW -> al.label_string ); n++; 1278 } 1279 1280 if( n != 0 ) 1281 XtSetValues( newW -> al.internal_children[ XmUbAL_CHILD_LABEL ], 1282 local_args, n ); 1283 } 1284 1285 1286 if( visual_changed ){ 1287 1288 KidDimensionRec kids_sizes[ NO_INTERNAL_CHILDREN ]; 1289 Boolean resized; 1290 1291 /* Code. */ 1292 1293 resized = ResizeIfNeeded( newW, kids_sizes ); 1294 1295 /* If the widget was resized, the layout has already been done. */ 1296 if( !resized ) 1297 DoLayout( newW, kids_sizes ); 1298 1299 } 1300 1301 return( visual_changed ); 1302 1303 #undef Differs 1304 1305 } /* SetValues */ 1306 1307 1308 /*----------------------------------------------------------------------*/ 1309 1310 static void WarningNoResourceChange(XmUbArrowLabelWidget al,String resource)1311 WarningNoResourceChange( XmUbArrowLabelWidget al, 1312 String resource ) 1313 { 1314 /* Variables. */ 1315 Cardinal num_params; 1316 String params[ 2 ]; 1317 1318 /* Code. */ 1319 1320 params[ 0 ] = resource; 1321 params[ 1 ] = XtClass( al ) -> core_class.class_name; 1322 num_params = 2; 1323 XtAppWarningMsg( XtWidgetToApplicationContext( (Widget) al ), 1324 "resourceError", "setValues", "WidgetError", 1325 "Resource %s may not be changed in %s widgets.", 1326 params, &num_params ); 1327 1328 return; 1329 1330 } /* WarningNoResourceChange */ 1331 1332 1333 /*----------------------------------------------------------------------*/ 1334 1335 Widget XmUbCreateArrowLabel(Widget parent,String name,ArgList arglist,Cardinal argcount)1336 XmUbCreateArrowLabel( Widget parent, 1337 String name, 1338 ArgList arglist, 1339 Cardinal argcount ) 1340 { 1341 1342 /* Code. */ 1343 1344 return XtCreateWidget( name, xmUbArrowLabelWidgetClass, 1345 parent, arglist, argcount ); 1346 1347 } /* XmUbCreateArrowLabel */ 1348 1349 1350 /*----------------------------------------------------------------------*/ 1351 1352 Widget XmUbArrowLabelGetChild(Widget widget,int child)1353 XmUbArrowLabelGetChild( Widget widget, 1354 int child ) 1355 { 1356 /* Variables. */ 1357 XmUbArrowLabelWidget al; 1358 1359 /* Code. */ 1360 1361 al = (XmUbArrowLabelWidget) widget; 1362 1363 1364 return( al -> al.internal_children[ child ] ); 1365 1366 } /* XmUbArrowLabelGetChild */ 1367