1 /*
2 * Motif
3 *
4 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5 *
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
16 * details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25 /************************************************************
26 * INCLUDE FILES
27 ************************************************************/
28 #include <Xm/Xm.h>
29 #include <stdio.h>
30 #include <Xm/ButtonBoxP.h>
31 #include <Xm/ExtP.h>
32 #include <Xm/TraitP.h>
33 #include <Xm/TakesDefT.h>
34 #include <Xm/VaSimpleP.h>
35 #include "XmI.h"
36
37 /************************************************************
38 * TYPEDEFS AND DEFINES
39 ************************************************************/
40
41 #define SUPERCLASS ((ConstraintWidgetClass) &xmManagerClassRec)
42
43 /************************************************************
44 * MACROS
45 ************************************************************/
46
47 #define IsHorizontal(x) (XmButtonBox_orientation((x)) == XmHORIZONTAL)
48 #define MarginH(x) (XmButtonBox_margin_height((x)))
49 #define MarginW(x) (XmButtonBox_margin_width((x)))
50 #define FillOption(x) (XmButtonBox_fill_option((x)))
51 #define EqualSize(x) (XmButtonBox_equal_size((x)))
52
53 /************************************************************
54 * EXTERNAL DECLARATIONS
55 ************************************************************/
56
57 /************************************************************
58 * STATIC FUNCTION DECLARATIONS
59 ************************************************************/
60
61 static void Initialize(Widget, Widget, ArgList, Cardinal *);
62 static void ClassInitialize(void);
63
64 static void ClassPartInitialize(WidgetClass w_class) ;
65
66 static void InsertChild(Widget);
67 static void Resize(Widget), ChangeManaged(Widget);
68 static void ConstraintInitialize(Widget, Widget, ArgList, Cardinal *);
69
70 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
71 static Boolean ConstraintSetValues(Widget, Widget,
72 Widget, ArgList, Cardinal *);
73 static Boolean CvtStringToFillOption(Display *, XrmValuePtr, Cardinal *,
74 XrmValuePtr, XrmValuePtr);
75
76 static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *,
77 XtWidgetGeometry *);
78 static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *,
79 XtWidgetGeometry *);
80
81 static XtGeometryResult TryNewLayout(Widget, Mask *, Boolean);
82 static Cardinal CalcChildrenPrefSizes(XmButtonBoxWidget, Dimension *,
83 Dimension *, Dimension *);
84 static void LayoutChildren(Widget, Widget);
85 static void CalcChildSize(XmButtonBoxWidget, Widget, Dimension,
86 Dimension, Dimension, Cardinal,
87 Dimension *, Dimension *);
88
89 static void ButtonBoxSetDefaultShadow(Widget button) ;
90
91
92 /************************************************************
93 * STATIC DECLARATIONS
94 ************************************************************/
95
96 static XtResource resources[] =
97 {
98 {
99 XmNequalSize, XmCEqualSize, XmRBoolean,
100 sizeof(Boolean), XtOffsetOf(XmButtonBoxRec, button_box.equal_size),
101 XmRImmediate, (XtPointer) False
102 },
103
104 {
105 XmNfillOption, XmCFillOption, XmRXmFillOption,
106 sizeof(XmFillOption), XtOffsetOf(XmButtonBoxRec, button_box.fill_option),
107 XmRImmediate, (XtPointer) XmFillNone
108 },
109
110 {
111 XmNmarginHeight, XmCMargin, XmRVerticalDimension,
112 sizeof(Dimension), XtOffsetOf(XmButtonBoxRec, button_box.margin_height),
113 XmRImmediate, (XtPointer) 0
114 },
115
116 {
117 XmNmarginWidth, XmCMargin, XmRHorizontalDimension,
118 sizeof(Dimension), XtOffsetOf(XmButtonBoxRec, button_box.margin_width),
119 XmRImmediate, (XtPointer) 0
120 },
121
122 {
123 XmNorientation, XmCOrientation, XmROrientation,
124 sizeof(unsigned char), XtOffsetOf(XmButtonBoxRec, button_box.orientation),
125 XmRImmediate, (XtPointer)XmHORIZONTAL
126 },
127
128 {
129 XmNdefaultButton, XmCWidget, XmRWidget,
130 sizeof(Widget), XtOffsetOf(XmButtonBoxRec, button_box.default_button),
131 XmRImmediate, (XtPointer) NULL
132 }
133 };
134
135 static XmSyntheticResource get_resources[] =
136 {
137 {
138 XmNmarginHeight, sizeof(Dimension),
139 XtOffsetOf(XmButtonBoxRec, button_box.margin_height),
140 XmeFromVerticalPixels, (XmImportProc) XmeToVerticalPixels
141 },
142
143 {
144 XmNmarginWidth, sizeof(Dimension),
145 XtOffsetOf(XmButtonBoxRec, button_box.margin_width),
146 XmeFromHorizontalPixels, (XmImportProc) XmeToHorizontalPixels
147 }
148 };
149
150 static XtResource constraints[] =
151 {
152 {
153 "pri.vate1", "Pri.vate1", XmRDimension, sizeof(Dimension),
154 XtOffsetOf(XmBBoxConstraintsRec, bbox.pref_width),
155 XmRImmediate, (XtPointer) 0
156 },
157 {
158 "pri.vate2", "Pri.vate2", XmRAttachment, sizeof(Dimension),
159 XtOffsetOf(XmBBoxConstraintsRec, bbox.pref_height),
160 XmRImmediate, (XtPointer) 0
161 }
162 };
163
164 XmButtonBoxClassRec xmButtonBoxClassRec = {
165 {
166 /* core_class members */
167 /* superclass */ (WidgetClass)SUPERCLASS,
168 /* class_name */ "XmButtonBox",
169 /* widget_size */ sizeof(XmButtonBoxRec),
170 /* class_initialize */ ClassInitialize,
171 /* class_part_init */ ClassPartInitialize,
172 /* class_inited */ False,
173 /* initialize */ Initialize,
174 /* initialize_hook */ NULL,
175 /* realize */ XtInheritRealize,
176 /* actions */ NULL,
177
178
179 /* num_actions */ 0,
180 /* resources */ (XtResource*)resources,
181 /* num_resources */ XtNumber(resources),
182 /* xrm_class */ NULLQUARK,
183 /* compress_motion */ True,
184 /* compress_exposure */ True,
185 /* compress_enterleave*/ True,
186 /* visible_interest */ False,
187 /* destroy */ NULL,
188 /* resize */ Resize,
189 /* expose */ NULL,
190 /* set_values */ SetValues,
191 /* set_values_hook */ NULL,
192 /* set_values_almost */ XtInheritSetValuesAlmost,
193 /* get_values_hook */ NULL,
194 /* accept_focus */ NULL,
195 /* version */ XtVersion,
196 /* callback_private */ NULL,
197 /* tm_table */ XtInheritTranslations,
198 /* query_geometry */ (XtGeometryHandler) QueryGeometry,
199 /* display_accelerator*/ NULL,
200 /* extension */ NULL,
201 },
202 {
203 /* composite_class members */
204 /* geometry_manager */ GeometryManager,
205 /* change_managed */ ChangeManaged,
206 /* insert_child */ InsertChild,
207 /* delete_child */ XtInheritDeleteChild,
208 /* extension */ NULL,
209 },
210 { /* constraint_class fields */
211 /* resource list */ constraints,
212 /* num resources */ XtNumber(constraints),
213 /* constraint size */ sizeof(XmBBoxConstraintsRec),
214 /* init proc */ ConstraintInitialize,
215 /* destroy proc */ NULL,
216 /* set values proc */ ConstraintSetValues,
217 /* extension */ NULL,
218 },
219 { /* manager_class fields */
220 /* default translations */ XtInheritTranslations,
221 /* syn_resources */ get_resources,
222 /* num_syn_resources */ XtNumber(get_resources),
223 /* syn_cont_resources */ NULL,
224 /* num_syn_cont_resources */ 0,
225 /* parent_process */ XmInheritParentProcess,
226 /* extension */ NULL,
227 },
228 {
229 /* Row class members */
230 /* extension */ NULL,
231 }
232 };
233
234 WidgetClass xmButtonBoxWidgetClass = (WidgetClass)&xmButtonBoxClassRec;
235
236 /************************************************************
237 * STATIC CODE
238 ************************************************************/
239
240 /* Function Name: ClassInitialize
241 * Description: Called to initialize information specific
242 * to this widget class.
243 * Arguments: none.
244 * Returns: none.
245 */
246
247 /* ARGSUSED */
248 static void
ClassInitialize()249 ClassInitialize()
250 {
251 XmButtonBoxClassRec *wc = &xmButtonBoxClassRec;
252
253 XtSetTypeConverter(XmRString, XmRXmFillOption,
254 (XtTypeConverter) CvtStringToFillOption,
255 NULL, (Cardinal)0, XtCacheAll, (XtDestructor)NULL);
256 }
257
258
259 /****************************************************************/
260 static void
ClassPartInitialize(WidgetClass w_class)261 ClassPartInitialize(WidgetClass w_class )
262 {
263 XmButtonBoxWidgetClass bbClass
264 = (XmButtonBoxWidgetClass) w_class ;
265
266 /* this seems to do nothing.... why is it here? -rh
267 XmButtonBoxWidgetClass bbSuper
268 = (XmButtonBoxWidgetClass) w_class->core_class.superclass ;
269 */
270 _XmFastSubclassInit (w_class, XmBUTTONBOX_BIT);
271
272
273 /* Install the specifyrendertable trait for all subclasses */
274 /*
275 XmeTraitSet((XtPointer)w_class, XmQTspecifyRenderTable,
276 (XtPointer) &bulletinbSRT);
277 */
278 return ;
279 }
280
281
282 /****************************************************************/
283
284
285 /* Function Name: Initialize
286 * Description: Called to initialize information specific
287 * to this widget.
288 * Arguments: req - what was originally requested.
289 * new - what will be created (our superclasses have
290 * already mucked with this)
291 * args, num_args - The arguments passed to
292 * the creation call.
293 * Returns: none.
294 */
295
296 /* ARGSUSED */
Initialize(Widget req,Widget set,ArgList args,Cardinal * num_args)297 static void Initialize(Widget req, Widget set,
298 ArgList args, Cardinal * num_args)
299 {
300 /*
301 * This is here just in case no children are added before the
302 * widget is realized.
303 */
304
305 if (req->core.width == 0)
306 set->core.width = 1;
307
308 if (req->core.height == 0)
309 set->core.height = 1;
310 }
311
312 /* Function Name: ConstraintInitialize
313 * Description: Called to initialize information specific
314 * to this child widget.
315 * Arguments: req - what was originally requested.
316 * set - what will be created (our superclassed have
317 * already mucked with this)
318 * args, num_args - The arguments passed to
319 * the creation call.
320 * Returns: none.
321 */
322
323 /* ARGSUSED */
324 static void
ConstraintInitialize(Widget request,Widget set,ArgList args,Cardinal * num_args)325 ConstraintInitialize(Widget request, Widget set, ArgList args, Cardinal *num_args)
326 {
327 XmButtonBoxC_pref_width(set) = XmButtonBoxC_pref_height(set) = 0;
328 }
329
330 /* Function Name: ConstraintSetValues
331 * Description: Called when child widget data needs to be modified on-
332 * the-fly.
333 * Arguments: current - the current (old) widget values.
334 * request - before superclassed have changed things.
335 * set - what will acutally be the new values.
336 * args, num_args - the arguments in the list.
337 * Returns: none
338 */
339
340 /* ARGSUSED */
341 static Boolean
ConstraintSetValues(Widget current,Widget request,Widget set,ArgList args,Cardinal * num_args)342 ConstraintSetValues(Widget current, Widget request, Widget set,
343 ArgList args, Cardinal * num_args)
344 {
345 if ((XmButtonBoxC_pref_width(set) != set->core.width) ||
346 (XmButtonBoxC_pref_height(set) != set->core.height))
347 {
348 /*
349 * The desired height or width changed, this will
350 * tell the icon box to perform a new XtQueryGeom.
351 */
352
353 XmButtonBoxC_pref_width(set) = XmButtonBoxC_pref_height(set) = 0;
354 }
355
356 return(False);
357 }
358
359 /*
360 * Function Name: Resize
361 * Description: Called when this widget has been resized.
362 * Arguments: w - Button Box Widget to resize.
363 * Returns: none.
364 */
365
366 /*ARGSUSED */
367 static void
Resize(Widget w)368 Resize(Widget w)
369 {
370 LayoutChildren(w, NULL);
371 }
372
373 /* Function Name: QueryGeometry
374 * Description: Called when my parent wants to know my
375 * preferred size.
376 * Arguments: w - the widget to check.
377 * intended - parent imposed geometry.
378 * preferred - what I would like.
379 * Returns: status.
380 */
381
382 static XtGeometryResult
QueryGeometry(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * preferred)383 QueryGeometry(Widget w, XtWidgetGeometry *request,
384 XtWidgetGeometry *preferred)
385 {
386 XmButtonBoxWidget bbox = (XmButtonBoxWidget)w;
387 Dimension max_major, max_minor, child_major_total;
388
389 /*
390 * Calculate our desired size.
391 */
392
393 (void) CalcChildrenPrefSizes(bbox, &max_major,
394 &max_minor, &child_major_total);
395
396 if (IsHorizontal(bbox)) {
397 preferred->width = child_major_total + (2 * MarginW(bbox));
398 preferred->height = max_minor + (2 * MarginH(bbox));
399 }
400 else
401 {
402 preferred->width = max_minor + (2 * MarginW(bbox));
403 preferred->height = child_major_total + (2 * MarginH(bbox));
404 }
405
406 return(_XmHWQuery(w, request, preferred));
407 }
408
409 /* Function Name: GeometryManager
410 * Description: handles request from children for size changes.
411 * Arguments: child - the child to change.
412 * request - desired geometry of child.
413 * result - what will be allowed if almost.
414 * Returns: status.
415 */
416
417 /* ARGSUSED */
418 static XtGeometryResult
GeometryManager(Widget w,XtWidgetGeometry * request,XtWidgetGeometry * reply)419 GeometryManager(Widget w, XtWidgetGeometry *request,
420 XtWidgetGeometry *reply)
421 {
422 XmButtonBoxWidget bbox = (XmButtonBoxWidget)w->core.parent;
423 Mask mask = 0;
424 XtGeometryResult result;
425
426 /*
427 * Say no to any change in position.
428 */
429
430 if ( (request->request_mode & (CWX | CWY | CWBorderWidth)) &&
431 !(request->request_mode & (CWWidth | CWHeight)) )
432 {
433 return (XtGeometryNo);
434 }
435
436 if ( request->request_mode & (CWWidth | CWHeight) )
437 {
438 Dimension max_major, max_minor;
439 Dimension child_major, child_minor;
440 Dimension child_width, child_height;
441 Dimension child_major_total;
442
443 Cardinal num_managed;
444
445 /*
446 * Save the old size, and set the corresponding
447 * widget fields to the requested sizes.
448 */
449
450 Dimension old_width = XmButtonBoxC_pref_width(w);
451 Dimension old_height = XmButtonBoxC_pref_height(w);
452
453 if ( request->request_mode & CWWidth )
454 XmButtonBoxC_pref_width(w) = request->width;
455
456 if ( request->request_mode & CWHeight )
457 XmButtonBoxC_pref_height(w) = request->height;
458
459 /*
460 * See if everything fits with the new size.
461 */
462
463 (void) TryNewLayout((Widget)bbox, &mask,
464 (request->request_mode & XtCWQueryOnly));
465
466 num_managed = CalcChildrenPrefSizes(bbox, &max_major,
467 &max_minor, &child_major_total);
468
469 CalcChildSize(bbox, w, max_major, max_minor,
470 child_major_total, num_managed, &child_major,
471 &child_minor);
472
473 if (IsHorizontal(bbox)) {
474 child_height = child_minor;
475 child_width = child_major;
476 }
477 else {
478 child_height = child_major;
479 child_width = child_minor;
480 }
481
482 if ( (int)child_width >= (int)(2 * w->core.border_width) )
483 child_width -= (2 * w->core.border_width);
484
485 if ( (int)child_height >= (int)(2 * w->core.border_width) )
486 child_height -= (2 * w->core.border_width);
487
488 if (((child_width == XmButtonBoxC_pref_width(w)) ||
489 !(request->request_mode & CWWidth)) &&
490 ((child_height == XmButtonBoxC_pref_height(w)) ||
491 !(request->request_mode & CWHeight)))
492 {
493 result = XtGeometryYes;
494 }
495 else if ((child_width != w->core.width) ||
496 (child_height != w->core.height))
497 {
498 reply->request_mode = CWHeight | CWWidth;
499 reply->height = child_height;
500 reply->width = child_width;
501 result = XtGeometryAlmost;
502 }
503 else {
504 result = XtGeometryNo;
505 }
506
507 if ((request->request_mode & XtCWQueryOnly) ||
508 (result != XtGeometryYes))
509 {
510 XmButtonBoxC_pref_width(w) = old_width;
511 XmButtonBoxC_pref_height(w) = old_height;
512 }
513 else
514 LayoutChildren((Widget)bbox, w);
515
516 /*
517 * We didn't get what we wanted, our preferred
518 * size should be recomputed the next time we have
519 * a chance to ask it, given that we're rejecting
520 * its current geometry and that it may not agree
521 * with our Almost reply.
522 */
523
524 if (result != XtGeometryYes) {
525 if ( request->request_mode & CWWidth )
526 XmButtonBoxC_pref_width(w) = 0;
527
528 if ( request->request_mode & CWHeight )
529 XmButtonBoxC_pref_height(w) = 0;
530 }
531
532 return(result);
533 }
534
535 /*
536 * Stacking request only.
537 */
538
539 return (XtGeometryYes);
540 }
541
542
543 /* Function Name: ChangeManaged
544 * Description: when a management change has occurred.
545 * Arguments: w - the ButtonBox widget.
546 * Returns: none.
547 */
548
549 /* ARGSUSED */
550 static void
ChangeManaged(Widget w)551 ChangeManaged(Widget w)
552 {
553 Mask mask = 0;
554 /* CR03420 mask should be set accordingly */
555 if (w->core.width == 1) mask |= CWWidth;
556 if (w->core.height == 1) mask |= CWHeight;
557 if (mask) (void)TryNewLayout(w, &mask, False);
558 LayoutChildren(w, NULL);
559
560 /*
561 * for Motif navigation
562 */
563
564 XmeNavigChangeManaged(w);
565 }
566
567
568 /* Function Name: InsertChild
569 * Description: when a child widget is added.
570 * Arguments: w - the child widget
571 * Returns: none.
572 */
573
574 /* ARGSUSED */
575 static void
InsertChild(register Widget child)576 InsertChild(register Widget child)
577 {
578 Boolean is_button = False ;
579 XmButtonBoxWidget bb = (XmButtonBoxWidget) XtParent( child) ;
580 /*
581 * Check for non-widgets - ButtonBox doesn't support gadgets, for now ...
582 */
583
584 if (_XmGadgetWarning(child))
585 {
586 return;
587 }
588
589 /*
590 * Insert the child widget in the composite children list with the
591 * superclass insert_child routine.
592 */
593
594 /* (*SUPERCLASS->composite_class.insert_child)(w); */
595
596 /* Another process may be updating the superclass's data */
597 /* (This was missed for some reason... - scorch)
598 * use composite class insert proc to do all the dirty work
599 */
600 {
601 XtWidgetProc insert_child;
602 _XmProcessLock();
603 insert_child = ((XmManagerWidgetClass)xmManagerWidgetClass)->
604 composite_class.insert_child;
605 _XmProcessUnlock();
606 (*insert_child)(child);
607 }
608
609 if(XmeTraitGet((XtPointer)XtClass(child), XmQTtakesDefault))
610 {
611 is_button = TRUE ;
612
613 if( XmButtonBox_default_button( bb) )
614 {
615 /* Notify child that it has to be ready for default visual */
616 ButtonBoxSetDefaultShadow( child) ;
617 }
618 }
619
620 }
621
622
623 /* Function Name: SetValues
624 * Description: Called when some widget data needs to be modified on-
625 * the-fly.
626 * Arguments: current - the current (old) widget values.
627 * request - before superclassed have changed things.
628 * set - what will acutally be the new values.
629 * args, num_args - the arguments in the list.
630 * Returns: none
631 */
632
633 /* ARGSUSED */
634 static Boolean
SetValues(Widget current,Widget request,Widget set,ArgList args,Cardinal * num_args)635 SetValues(Widget current, Widget request, Widget set,
636 ArgList args, Cardinal * num_args)
637 {
638 XmButtonBoxWidget b_old = (XmButtonBoxWidget) current;
639 XmButtonBoxWidget b_set = (XmButtonBoxWidget) set;
640 Boolean newLayout = False;
641 Mask mask = 0; /* CR03420 */
642 if ( XmButtonBox_equal_size(b_set) != XmButtonBox_equal_size(b_old) ||
643 XmButtonBox_fill_option(b_set) != XmButtonBox_fill_option(b_old) ||
644 XmButtonBox_margin_height(b_set) != XmButtonBox_margin_height(b_old) ||
645 XmButtonBox_margin_width(b_set) != XmButtonBox_margin_width(b_old) ||
646 XmButtonBox_orientation(b_set) != XmButtonBox_orientation(b_old) )
647 {
648 newLayout = True;
649 }
650
651 if (set->core.width == 0)
652 { /* CR03420 */
653 set->core.width = 1; /* setting to 1 to prevent zero width */
654 mask |= CWWidth;
655 }
656 if (set->core.height == 0)
657 { /* CR03420 */
658 set->core.height = 1; /* setting to 1 to prevent zero height */
659 mask |= CWHeight;
660 }
661 if (mask) TryNewLayout((Widget)b_set, &mask, False);
662 if ( newLayout == True ) LayoutChildren((Widget)b_set, NULL);
663
664 return(False);
665 }
666
667 /************************************************************
668 * Type Converters.
669 ************************************************************/
670
671 /* Function Name: CvtStringToFillOption
672 * Description: Converts a string to a FillOption
673 * Arguments: dpy - the X Display.
674 * args, num_args - *** NOT USED ***
675 * fromVal - contains the string to convert.
676 * toVal - contains the converted node state.
677 * Returns:
678 */
679
680 /* ARGSUSED */
681 static Boolean
CvtStringToFillOption(Display * dpy,XrmValuePtr args,Cardinal * num_args,XrmValuePtr fromVal,XrmValuePtr toVal)682 CvtStringToFillOption(Display * dpy, XrmValuePtr args, Cardinal *num_args,
683 XrmValuePtr fromVal, XrmValuePtr toVal)
684 {
685 static XmFillOption option;
686 char lowerName[BUFSIZ];
687
688 XmCopyISOLatin1Lowered(lowerName, (char *)fromVal->addr);
689
690 if ( streq(lowerName, "none") || streq(lowerName,"fillnone") )
691 option = XmFillNone;
692 else if ( streq(lowerName, "major") || streq(lowerName, "fillmajor") )
693 option = XmFillMajor;
694 else if ( streq(lowerName, "minor") || streq(lowerName, "fillminor") )
695 option = XmFillMinor;
696 else if ( streq(lowerName, "all") || streq(lowerName, "fillall") )
697 option = XmFillAll;
698 else
699 {
700 XtDisplayStringConversionWarning(dpy, fromVal->addr, XmRXmFillOption);
701 return(False); /* Conversion failed. */
702 }
703
704 if ( toVal->addr == NULL )
705 {
706 toVal->size = sizeof(XmFillOption);
707 toVal->addr = (XtPointer)&option;
708 return(True);
709 }
710 else
711 {
712 toVal->size = sizeof(XmFillOption);
713 if ( toVal->size >= sizeof(XmFillOption) )
714 {
715 XmFillOption *state = (XmFillOption *)toVal->addr;
716
717 *state = option;
718 return(True);
719 }
720 else
721 {
722 return(False);
723 }
724 }
725 }
726
727 /************************************************************
728 * LOCAL CODE
729 ************************************************************/
730
731 /* Function Name: TryNewLayout
732 * Description: tries to do a layout within the current width
733 * and height. If that fails, it tries to resize and
734 * do it within the geometry given in preferred_size.
735 * Arguments: parent - the ButtonBox
736 * mask - request mask
737 * queryOnly - should this only query
738 * Returns: status.
739 */
740
741 /* ARGSUSED */
742 static XtGeometryResult
TryNewLayout(Widget parent,Mask * mask,Boolean queryOnly)743 TryNewLayout(Widget parent, Mask *mask,
744 Boolean queryOnly)
745 {
746 XmButtonBoxWidget bbox = (XmButtonBoxWidget)parent;
747 Dimension new_width, new_height;
748 Dimension max_major, max_minor, child_major_total;
749
750 /*
751 * Get the bounding width and height of all children.
752 */
753
754 (void) CalcChildrenPrefSizes(bbox, &max_major,
755 &max_minor, &child_major_total);
756
757 if (IsHorizontal(bbox))
758 {
759 new_width = child_major_total + 2 * MarginW(bbox);
760 new_height = max_minor + 2 * MarginH(bbox);
761 }
762 else
763 {
764 new_width = max_minor + 2 * MarginW(bbox);
765 new_height = child_major_total + 2 * MarginH(bbox);
766 }
767
768 /*
769 * Be sure that we are always at least one pixel high.
770 */
771
772 if (new_width == 0)
773 new_width = 1;
774 if (new_height == 0)
775 new_height = 1;
776
777 if ( new_width != parent->core.width || new_height != parent->core.height )
778 {
779 XtWidgetGeometry request, reply;
780 XtGeometryResult result;
781
782 request.width = new_width;
783 request.height = new_height;
784
785 reply.width = 0;
786 reply.height = 0;
787
788 request.request_mode = *mask; /* CR03420 */
789 if ( queryOnly )
790 {
791 request.request_mode |= XtCWQueryOnly;
792 }
793 result = XtMakeGeometryRequest(parent, &request, &reply);
794
795 if ( request.width == reply.width )
796 {
797 *mask |= CWWidth;
798 }
799 if ( request.height == reply.height )
800 {
801 *mask |= CWHeight;
802 }
803
804 if ( result == XtGeometryAlmost && !queryOnly )
805 {
806 result = XtMakeGeometryRequest(parent, &reply, &reply);
807 }
808
809 return(result);
810 }
811
812 *mask = CWWidth | CWHeight;
813 return(XtGeometryYes);
814 }
815
816
817 /* Function Name: LayoutChildren
818 * Description: Lays out the "child" widgets in the ButtonBox widget.
819 * Arguments: w - the ButtonBox widget.
820 * special_child - Treat this child special, actually
821 * set the new width and height instead
822 * of calling the Xt routine. This helps
823 * the geom mgr implement XtGeometryYes
824 * policy.
825 * Returns: none.
826 */
827
828 /* ARGSUSED */
829 static void
LayoutChildren(Widget w,Widget special_child)830 LayoutChildren(Widget w, Widget special_child)
831 {
832 XmButtonBoxWidget bbox = (XmButtonBoxWidget)w;
833 Widget *childp;
834
835 Dimension margin_major, margin_minor;
836 Dimension max_major, max_minor;
837 Dimension box_major, box_minor;
838 Dimension child_major, child_minor;
839 Dimension child_width, child_height;
840 Dimension child_major_total;
841
842 Position pos_minor;
843 Position pos_x, pos_y;
844
845 float pad = 0, pos_major;
846 Cardinal num_managed;
847
848 child_major = 0;
849 child_minor = 0;
850
851 if ( IsHorizontal(bbox) )
852 {
853 margin_major = MarginW(bbox);
854 margin_minor = MarginH(bbox);
855 box_major = bbox->core.width;
856 box_minor = bbox->core.height;
857 }
858 else
859 {
860 margin_major = MarginH(bbox);
861 margin_minor = MarginW(bbox);
862 box_major = bbox->core.height;
863 box_minor = bbox->core.width;
864 }
865 if ((int)box_major > (int)(2 * margin_major))
866 box_major -= 2 * margin_major;
867 else
868 box_major = 1;
869
870 if ((int)box_minor > (int)(2 * margin_minor))
871 box_minor -= 2 * margin_minor;
872 else
873 box_minor = 1;
874
875 num_managed = CalcChildrenPrefSizes(bbox, &max_major,
876 &max_minor, &child_major_total);
877
878 pad = 0.0;
879 pos_major = (float) margin_major;
880 if ((FillOption(bbox) == XmFillNone) || (FillOption(bbox) == XmFillMinor))
881 {
882 if ( box_major >= child_major_total ) {
883 pad = ((float) box_major -
884 (float) child_major_total) / ((float) num_managed + 1.0);
885 pos_major += pad;
886 }
887 }
888
889 ForAllChildren(bbox, childp) {
890 if ( !XtIsManaged(*childp) )
891 continue;
892
893 CalcChildSize(bbox, *childp, max_major, max_minor,
894 child_major_total, num_managed, &child_major,
895 &child_minor);
896
897 if ((FillOption(bbox) == XmFillNone) ||
898 (FillOption(bbox) == XmFillMajor))
899 {
900 pos_minor = (((int)(box_minor - child_minor)) /2) + margin_minor;
901 }
902 else
903 pos_minor = margin_minor;
904
905 if ( IsHorizontal(bbox) ) {
906 child_width = child_major;
907 child_height = child_minor;
908 if (LayoutIsRtoLM(bbox))
909 pos_x = box_major - (int) pos_major - child_width;
910 else
911 pos_x = (int) pos_major;
912 pos_y = pos_minor;
913 }
914 else {
915 pos_x = pos_minor;
916 pos_y = (int) pos_major;
917 child_width = child_minor;
918 child_height = child_major;
919 }
920
921 if ( (int)child_width >= (int)(2 * (*childp)->core.border_width) )
922 child_width -= (2 * (*childp)->core.border_width);
923
924 if ( (int)child_height >= (int)(2 * (*childp)->core.border_width) )
925 child_height -= (2 * (*childp)->core.border_width);
926
927 child_width = (child_width == 0) ? 1 : child_width;
928 child_height = (child_height == 0) ? 1 : child_height;
929
930 if (*childp == special_child) {
931 special_child->core.x = pos_x;
932 special_child->core.y = pos_y;
933 special_child->core.width = child_width;
934 special_child->core.height = child_height;
935 }
936 else {
937 _XmConfigureWidget(*childp, pos_x, pos_y, child_width,
938 child_height, (*childp)->core.border_width);
939 }
940
941 pos_major += (float) child_major + pad;
942 }
943 }
944
945 /* Function Name: CalcChildrenPrefSizes
946 * Description: Determines the total size in the major direction
947 * of all children of the ButtonBox, as well as the
948 * maximum value in both major and minor directions.
949 * Arguments: bbox - the ButtonBox parent.
950 * max_major - the maximum size of all the children
951 * in the major dimension.
952 * total - return location for the total size in the
953 * major direction.
954 * Returns: number of managed children.
955 */
956
957 /* ARGSUSED */
958 static Cardinal
CalcChildrenPrefSizes(XmButtonBoxWidget bbox,Dimension * max_major,Dimension * max_minor,Dimension * total)959 CalcChildrenPrefSizes(XmButtonBoxWidget bbox, Dimension *max_major,
960 Dimension *max_minor, Dimension *total)
961 {
962 Cardinal num_managed = 0;
963 Widget *childp;
964 XtWidgetGeometry geo;
965 Dimension *maj_dim, *minor_dim;
966 Boolean is_equal = EqualSize(bbox);
967
968 if ( IsHorizontal(bbox) )
969 {
970 maj_dim = &geo.width;
971 minor_dim = &geo.height;
972 }
973 else
974 {
975 maj_dim = &geo.height;
976 minor_dim = &geo.width;
977 }
978
979 *total = *max_major = *max_minor = 1;
980
981 ForAllChildren(bbox, childp) {
982
983 if ( !XtIsManaged(*childp) )
984 continue;
985
986 num_managed++;
987
988 if ((XmButtonBoxC_pref_width(*childp) == 0) ||
989 (XmButtonBoxC_pref_height(*childp) == 0))
990 {
991 XtQueryGeometry(*childp, NULL, &geo);
992 }
993 else
994 geo.border_width = (*childp)->core.border_width;
995
996 if (XmButtonBoxC_pref_width(*childp) == 0)
997 XmButtonBoxC_pref_width(*childp) = geo.width;
998 else
999 geo.width = XmButtonBoxC_pref_width(*childp);
1000
1001 if (XmButtonBoxC_pref_height(*childp) == 0)
1002 XmButtonBoxC_pref_height(*childp) = geo.height;
1003 else
1004 geo.height = XmButtonBoxC_pref_height(*childp);
1005
1006 ASSIGN_MAX(*max_major, *maj_dim + (2 * geo.border_width));
1007 ASSIGN_MAX(*max_minor, *minor_dim + (2 * geo.border_width));
1008
1009 if (!is_equal)
1010 *total += (*maj_dim + (2 * geo.border_width));
1011 }
1012
1013 if ( is_equal )
1014 *total = num_managed * (*max_major);
1015
1016 return(num_managed);
1017 }
1018
1019 /* Function Name: CalcChildSize
1020 * Description: Determines the size of a child
1021 * Arguments: bbox - the ButtonBox parent.
1022 * w - the child of interest.
1023 * max_major - the largest size allowed in the
1024 * major direction.
1025 * max_minor - the largest size allowed in the
1026 * minor direction.
1027 * child_major_total - total size of all children in the
1028 * major direction.
1029 * num_managed - number of managed children.
1030 * child_major - return location for child's base
1031 * major size.
1032 * child_minor - return location for child's base
1033 * minor size.
1034 * Returns: none.
1035 */
1036
1037 /* ARGSUSED */
1038 static void
CalcChildSize(XmButtonBoxWidget bbox,Widget w,Dimension max_major,Dimension max_minor,Dimension child_major_total,Cardinal num_managed,Dimension * child_major,Dimension * child_minor)1039 CalcChildSize(XmButtonBoxWidget bbox, Widget w, Dimension max_major,
1040 Dimension max_minor, Dimension child_major_total,
1041 Cardinal num_managed, Dimension *child_major,
1042 Dimension *child_minor)
1043 {
1044 XtWidgetGeometry geo;
1045 Dimension box_minor, box_major;
1046 Dimension margin_major, margin_minor;
1047
1048 if ((XmButtonBoxC_pref_width(w) == 0)||(XmButtonBoxC_pref_height(w) == 0))
1049 XtQueryGeometry(w, NULL, &geo);
1050 else
1051 geo.border_width = w->core.border_width;
1052
1053 if (XmButtonBoxC_pref_width(w) != 0)
1054 geo.width = XmButtonBoxC_pref_width(w);
1055
1056 if (XmButtonBoxC_pref_height(w) != 0)
1057 geo.height = XmButtonBoxC_pref_height(w);
1058
1059 if ( IsHorizontal(bbox) )
1060 {
1061 margin_major = MarginW(bbox);
1062 margin_minor = MarginH(bbox);
1063 box_major = bbox->core.width;
1064 box_minor = bbox->core.height;
1065 *child_major = geo.width;
1066 *child_minor = geo.height;
1067 }
1068 else
1069 {
1070 margin_major = MarginH(bbox);
1071 margin_minor = MarginW(bbox);
1072 box_major = bbox->core.height;
1073 box_minor = bbox->core.width;
1074 *child_major = geo.height;
1075 *child_minor = geo.width;
1076 }
1077 *child_major += (2 * geo.border_width);
1078 *child_minor += (2 * geo.border_width);
1079
1080 if ((int)box_major > (int)(2 * margin_major))
1081 box_major -= (2 * margin_major);
1082 else
1083 box_major = 1;
1084
1085 if ((int)box_minor > (int)(2 * margin_minor))
1086 box_minor -= (2 * margin_minor);
1087 else
1088 box_minor = 1;
1089
1090 if ( EqualSize(bbox) )
1091 {
1092 *child_major = max_major;
1093 *child_minor = max_minor;
1094 }
1095 if ( FillOption(bbox) == XmFillMajor || FillOption(bbox) == XmFillAll ||
1096 child_major_total > box_major )
1097 {
1098 *child_major = (Dimension)
1099 (((float)*child_major/(float)child_major_total) * box_major);
1100 }
1101 if ( FillOption(bbox) == XmFillMinor || FillOption(bbox) == XmFillAll ||
1102 *child_minor > box_minor )
1103 {
1104 *child_minor = box_minor;
1105 }
1106 }
1107
1108 /************************************************************
1109 *
1110 * Public functions
1111 *
1112 ************************************************************/
1113
1114 /* Function Name: XmCreateButtonBox
1115 * Description: Creation Routine for UIL and ADA.
1116 * Arguments: parent - the parent widget.
1117 * name - the name of the widget.
1118 * args, num_args - the number and list of args.
1119 * Returns: The created widget.
1120 */
1121
1122 Widget
XmCreateButtonBox(Widget parent,String name,ArgList args,Cardinal num_args)1123 XmCreateButtonBox(Widget parent, String name, ArgList args, Cardinal num_args)
1124 {
1125 return(XtCreateWidget(name,
1126 xmButtonBoxWidgetClass, parent, args, num_args));
1127 }
1128
1129 Widget
XmVaCreateButtonBox(Widget parent,char * name,...)1130 XmVaCreateButtonBox(
1131 Widget parent,
1132 char *name,
1133 ...)
1134 {
1135 register Widget w;
1136 va_list var;
1137 int count;
1138
1139 Va_start(var,name);
1140 count = XmeCountVaListSimple(var);
1141 va_end(var);
1142
1143
1144 Va_start(var, name);
1145 w = XmeVLCreateWidget(name,
1146 xmButtonBoxWidgetClass,
1147 parent, False,
1148 var, count);
1149 va_end(var);
1150 return w;
1151 }
1152
1153 Widget
XmVaCreateManagedButtonBox(Widget parent,char * name,...)1154 XmVaCreateManagedButtonBox(
1155 Widget parent,
1156 char *name,
1157 ...)
1158 {
1159 Widget w = NULL;
1160 va_list var;
1161 int count;
1162
1163 Va_start(var, name);
1164 count = XmeCountVaListSimple(var);
1165 va_end(var);
1166
1167 Va_start(var, name);
1168 w = XmeVLCreateWidget(name,
1169 xmButtonBoxWidgetClass,
1170 parent, True,
1171 var, count);
1172 va_end(var);
1173 return w;
1174 }
1175
1176 /****************************************************************/
1177 static void
ButtonBoxSetDefaultShadow(Widget button)1178 ButtonBoxSetDefaultShadow(Widget button)
1179 {
1180 XmTakesDefaultTrait trait_default ;
1181
1182 trait_default = (XmTakesDefaultTrait) XmeTraitGet((XtPointer)
1183 XtClass(button),
1184 XmQTtakesDefault) ;
1185 if (trait_default)
1186 trait_default->showAsDefault (button, XmDEFAULT_READY);
1187 }
1188