/* * Motif Tools Library, Version 3.1 * $Id: LayoutBox.c,v 1.1.1.1 2001/07/18 11:06:02 root Exp $ * * Written by David Flanagan. * Copyright (c) 1992-2001 by David Flanagan. * All Rights Reserved. See the file COPYRIGHT for details. * This is open source software. See the file LICENSE for details. * There is no warranty for this software. See NO_WARRANTY for details. * * $Log: LayoutBox.c,v $ * Revision 1.1.1.1 2001/07/18 11:06:02 root * Initial checkin. * * Revision 1.2 2001/06/12 16:25:28 andre * *** empty log message *** * * */ #include #include #define offset(field) XtOffsetOf(XmtLayoutBoxRec, layout_box.field) static XtResource resources[] = { {XmtNorientation, XmCOrientation, XmROrientation, sizeof(unsigned char), offset(orientation), XtRImmediate, (XtPointer)XmHORIZONTAL}, {XmtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), offset(background), XtRImmediate, (XtPointer) -1}, {XmtNequal, XmtCEqual, XtRBoolean, sizeof(Boolean), offset(equal), XtRImmediate, (XtPointer)False}, {XmtNspaceType, XmtCSpaceType, XmtRXmtLayoutSpaceType, sizeof(unsigned char), offset(space_type), XtRImmediate, (XtPointer)XmtLayoutSpaceNone}, {XmtNspace, XmtCSpace, XtRDimension, sizeof(Dimension), offset(space), XtRImmediate, (XtPointer) 0}, {XmtNspaceStretch, XmtCSpaceStretch, XtRDimension, sizeof(Dimension), offset(space_stretch), XtRImmediate, (XtPointer) 1}, {XmtNitemStretch, XmtCItemStretch, XtRDimension, sizeof(Dimension), offset(item_stretch), XtRImmediate, (XtPointer) 1}, }; #undef offset #if NeedFunctionPrototypes static void Initialize(Widget, Widget, ArgList, Cardinal *); static void Destroy(Widget); static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *); static void Resize(Widget); static void Redisplay(Widget, XEvent *, Region); static XtGeometryResult QueryGeometry(Widget, XtWidgetGeometry *, XtWidgetGeometry *); #else static void Initialize(); static void Destroy(); static Boolean SetValues(); static void Resize(); static void Redisplay(); static XtGeometryResult QueryGeometry(); #endif #define superclass (&xmtLayoutGadgetClassRec) externaldef(xmtlayoutboxclassrec) XmtLayoutBoxClassRec xmtLayoutBoxClassRec = { { /* rect_class fields */ /* superclass */ (WidgetClass)superclass, /* class_name */ "XmtLayoutBox", /* widget_size */ sizeof(XmtLayoutBoxRec), /* class_initialize */ NULL, /* class_part_initialize*/ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* rect1 */ NULL, /* rect2 */ NULL, /* rect3 */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* rect4 */ FALSE, /* rect5 */ FALSE, /* rect6 */ FALSE, /* rect7 */ FALSE, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* rect9 */ NULL, /* version */ XtVersion, /* callback_offsets */ NULL, /* rect10 */ NULL, /* query_geometry */ QueryGeometry, /* rect11 */ NULL, /* extension */ NULL }, { /* XmtLayoutGadget field */ /* change_font */ NULL }, { /* XmtLayoutBox fields */ /* extension */ NULL } }; externaldef(xmtlayoutboxgadgetclass) WidgetClass xmtLayoutBoxGadgetClass = (WidgetClass) &xmtLayoutBoxClassRec; /* ARGSUSED */ #if NeedFunctionPrototypes static void Initialize(Widget request, Widget init, ArgList arglist, Cardinal *num_args) #else static void Initialize(request, init, arglist, num_args) Widget request; Widget init; ArgList arglist; Cardinal *num_args; #endif { XmtLayoutBoxGadget lb = (XmtLayoutBoxGadget)init; if (lb->layout_box.orientation == XmHORIZONTAL) Constraint(init, type) = XmtLayoutRow; else Constraint(init, type) = XmtLayoutCol; if (lb->layout_box.background != (Pixel)-1) { XGCValues gcv; gcv.foreground = lb->layout_box.background; lb->layout_box.gc = XtGetGC(init, GCForeground, &gcv); } else lb->layout_box.gc = NULL; } #if NeedFunctionPrototypes static void Destroy(Widget w) #else static void Destroy(w) Widget w; #endif { XmtLayoutBoxGadget lb = (XmtLayoutBoxGadget)w; Widget child; if (lb->layout_box.gc) XtReleaseGC(w, lb->layout_box.gc); /* * we destroy anything within this box. This seems as reasonable * a thing to do as moving those widgets elsewhere. Except if * the entire Layout is being destroyed, in which case we can * skip this. */ if (!(XtParent(w))->core.being_destroyed) ForEachItem(lb, child) XtDestroyWidget(child); } /* ARGSUSED */ #if NeedFunctionPrototypes static Boolean SetValues(Widget current, Widget request, Widget set, ArgList arglist, Cardinal *num_args) #else static Boolean SetValues(current, request, set, arglist, num_args) Widget current; Widget request; Widget set; ArgList arglist; Cardinal *num_args; #endif { XmtLayoutBoxGadget cg = (XmtLayoutBoxGadget) current; XmtLayoutBoxGadget sg = (XmtLayoutBoxGadget) set; Boolean redisplay = False; Boolean relayout = False; if (sg->layout_box.background != cg->layout_box.background) { XGCValues gcv; if (sg->layout_box.gc) XtReleaseGC(set, sg->layout_box.gc); if (sg->layout_box.background != -1) { gcv.foreground = sg->layout_box.background; sg->layout_box.gc = XtGetGC(set, GCForeground, &gcv); } else sg->layout_box.gc = NULL; redisplay = True; } if (sg->layout_box.orientation != cg->layout_box.orientation) { if ((sg->layout_box.orientation != XmHORIZONTAL) && (sg->layout_box.orientation != XmVERTICAL)) sg->layout_box.orientation = cg->layout_box.orientation; else relayout = True; } if ((sg->layout_box.space != cg->layout_box.space) || (sg->layout_box.space_type != cg->layout_box.space_type) || (sg->layout_box.space_stretch!=cg->layout_box.space_stretch) || (sg->layout_box.item_stretch != cg->layout_box.item_stretch) || (sg->layout_box.equal != cg->layout_box.equal)) relayout = True; if (relayout) _XmtLayoutChildren((XmtLayoutWidget)XtParent(set), True); return redisplay | relayout; } /* * The story with margins and frames and captions: * Any child (including boxes) of an XmtLayout widget can have a * frame and/or a caption and/or a margin. * The XmtLayout widget will draw the frames and captions appropriately. * The size of the frame, caption and margin are not included in any child's * core x,y,width, and height fields. This includes boxes. * The children should not include the frame, caption or margin when * calculating their preferred size. * The frame, caption and margin *are* included when doing stretching * and shrinking calculations. * The frame, caption and margin are not included when adjusting the * size of children in an "equal" row or column. * If the programmer specifies a size for the child, then that size * does not include any frame or caption or margin. * The frame and caption are inside the margin. */ #if NeedFunctionPrototypes static void HorizontalMargins(XmtLayoutWidget lw, Widget child, int *total, int *left) #else static void HorizontalMargins(lw, child, total, left) XmtLayoutWidget lw; Widget child; int *total; int *left; #endif { XmtLayoutConstraintsPart *cc = LayoutConstraintsRec(child); int caption = 0; Boolean left_caption = False; XmtLayoutFrameType frame_type; XmtLayoutFramePosition frame_position; int frame = 0; *total = 2*cc->margin_width; *left = cc->margin_width; if (cc->caption) { if ((cc->caption_position == XmtLayoutLeft) || (cc->caption_position == XmtLayoutRight)) { caption = cc->caption_width + cc->caption_margin; *total += caption; if (cc->caption_position == XmtLayoutLeft) { left_caption = True; *left += caption; } } } /* if there is no frame, we're done */ if ((cc->frame_type == XmtLayoutFrameNone) && !lw->layout.debug_layout) return; /* get the frame args. If debug_layout is set, force fixed values */ if (lw->layout.debug_layout) { frame_type = XmtLayoutFrameBox; frame_position = XmtLayoutFrameOutside; frame = 6; } else { frame_type = cc->frame_type; frame_position = cc->frame_position; frame = cc->frame_margin + cc->frame_thickness; } if (frame_type == XmtLayoutFrameBox) { if (!left_caption || (frame_position!=XmtLayoutFrameThrough)) *left += frame; else if (frame > caption) *left += frame - caption; *total += frame; if (!caption || (frame_position != XmtLayoutFrameThrough)) *total += frame; else if (frame > caption) *total += frame - caption; } else if (frame_type == XmtLayoutFrameLeft) { if (!left_caption || (frame_position != XmtLayoutFrameThrough)) { *left += frame; *total += frame; } else if (frame > caption) { *left += frame - caption; *total += frame - caption; } } else if (frame_type == XmtLayoutFrameRight) { if (!caption || left_caption || (frame_position != XmtLayoutFrameThrough)) *total += frame; else if (frame > caption) *total += frame - caption; } } #if NeedFunctionPrototypes static void VerticalMargins(XmtLayoutWidget lw, Widget child, int *total, int *top) #else static void VerticalMargins(lw, child, total, top) XmtLayoutWidget lw; Widget child; int *total; int *top; #endif { XmtLayoutConstraintsPart *cc = LayoutConstraintsRec(child); int caption = 0; Boolean top_caption = False; XmtLayoutFrameType frame_type; XmtLayoutFramePosition frame_position; int frame = 0; *total = 2*cc->margin_height; *top = cc->margin_height; if (cc->caption) { if ((cc->caption_position == XmtLayoutTop) || (cc->caption_position == XmtLayoutBottom)) { caption = cc->caption_height + cc->caption_margin; *total += caption; if (cc->caption_position == XmtLayoutTop) { top_caption = True; *top += caption; } } } /* if there is no frame, we're done */ if ((cc->frame_type == XmtLayoutFrameNone) && !lw->layout.debug_layout) return; /* get the frame args. If debug_layout is set, force fixed values */ if (lw->layout.debug_layout) { frame_type = XmtLayoutFrameBox; frame_position = XmtLayoutFrameOutside; frame = 6; } else { frame_type = cc->frame_type; frame_position = cc->frame_position; frame = cc->frame_margin + cc->frame_thickness; } if (frame_type == XmtLayoutFrameBox) { if (!top_caption || (frame_position != XmtLayoutFrameThrough)) *top += frame; else if (frame > caption) *top += frame - caption; *total += frame; if (!caption || (frame_position != XmtLayoutFrameThrough)) *total += frame; else if (frame > caption) *total += frame - caption; } else if (frame_type == XmtLayoutFrameTop) { if (!top_caption || (frame_position != XmtLayoutFrameThrough)) { *top += frame; *total += frame; } else if (frame > caption) { *top += frame - caption; *total += frame - caption; } } else if (frame_type == XmtLayoutFrameBottom) { if (!caption || top_caption || (frame_position != XmtLayoutFrameThrough)) *total += frame; else if (frame > caption) *total += frame - caption; } } #if NeedFunctionPrototypes static void HideHomelessChildren(Widget w) #else static void HideHomelessChildren(w) Widget w; #endif { XmtLayoutBoxGadget lb = (XmtLayoutBoxGadget)w; Widget child; XmtLayoutConstraintsPart *cc; /* child constraints */ /* * If this box is already positioned outside of the window, * then it and its descendants are already hidden. */ if ((w->core.x + w->core.width < 0) && (w->core.y + w->core.height < 0)) return; /* * Otherwise, we've got to move this box and everything it * contains (recursively) out of the window. */ XmtSetRectObj(w); XtMoveWidget(w, -w->core.width-20, -w->core.height-20); XmtUnsetRectObj(w); ForEachItem(lb, child) { cc = LayoutConstraintsRec(child); /* * If the child is itself a container, then recurse on it, * to hide its contents. */ if ((cc->type == XmtLayoutRow) || (cc->type == XmtLayoutCol)) HideHomelessChildren(child); /* * hide the child. We do this differently depending on whether * the child is an XmtLayoutGadget or not. */ if (cc->type == XmtLayoutChild) XtMoveWidget(child, -child->core.width-20, -child->core.height-20); else { XmtSetRectObj(child); XtMoveWidget(child, -child->core.width-20, -child->core.height-20); XmtUnsetRectObj(child); } } } #if NeedFunctionPrototypes static void Resize(Widget w) #else static void Resize(w) Widget w; #endif { XmtLayoutWidget lw = (XmtLayoutWidget)XtParent(w); XmtLayoutBoxGadget lb = (XmtLayoutBoxGadget)w; XmtLayoutConstraintsPart *c = LayoutConstraintsRec(w); XmtLayoutConstraintsPart *cc; /* child constraints */ Boolean row; int extra_space; int child_num; Widget child; double factor; /* "glue set ratio" */ Boolean stretch = True; int major_start, minor_start; /* instead of x, y */ int major_length, minor_length; /* instead of width, height */ int cx, cy; /* child x, y */ int cw, ch; /* child w, h */ int *cmajor0, *cminor0; /* addresses of child major & minor coord */ int *cmajorlen, *cminorlen; /* addresses of child dimensions */ int next; int margin_width, margin_height, top_margin, left_margin; int *major_margin, *minor_margin; int space_stretch; int total_space, space, interval = 0; if (!XtIsManaged(w)) return; if (lb->layout_box.orientation == XmHORIZONTAL) row = True; else row = False; if (row) { major_start = w->core.x; minor_start = w->core.y; major_length = w->core.width; minor_length = w->core.height; cmajor0 = &cx; cminor0 = &cy; cmajorlen = &cw; cminorlen = &ch; major_margin = &margin_width; minor_margin = &margin_height; } else { major_start = w->core.y; minor_start = w->core.x; major_length = w->core.height; minor_length = w->core.width; cmajor0 = &cy; cminor0 = &cx; cmajorlen = &ch; cminorlen = &cw; major_margin = &margin_height; minor_margin = &margin_width; } if (major_length <= 0) major_length = 1; if (minor_length <= 0) minor_length = 1; if (row) extra_space = major_length - c->pref_w; else extra_space = major_length - c->pref_h; /* * figure out stretch or shrink factor. * The total_stretch figure includes the stretchiness of the spaces, * if any. */ if (extra_space > 0) { if (lb->layout_box.total_stretch == 0) factor = 0.0; else factor = extra_space/(double)lb->layout_box.total_stretch; stretch = True; } else if (extra_space < 0) { if (lb->layout_box.total_shrink == 0) factor = 0.0; else factor = -extra_space/(double)lb->layout_box.total_shrink; stretch = False; } else factor = 0.0; /* compute the size of the interval for Interval or Tabbed spacing */ if (lb->layout_box.space_type == XmtLayoutSpaceInterval) interval = major_length / ((int)lb->layout_box.num_items+1); else if ((lb->layout_box.space_type == XmtLayoutSpaceLTabbed) || (lb->layout_box.space_type == XmtLayoutSpaceCTabbed) || (lb->layout_box.space_type == XmtLayoutSpaceRTabbed)){ if (lb->layout_box.num_items <= 1) interval = major_length; else interval = major_length / ((int)lb->layout_box.num_items); } /* compute the size of the internal spaces, if any */ if ((lb->layout_box.space_type == XmtLayoutSpaceEven) || (lb->layout_box.space_type == XmtLayoutSpaceLREven)) { space = lb->layout_box.space; if (stretch) { int num_spaces; if (lb->layout_box.space_type == XmtLayoutSpaceEven) num_spaces = lb->layout_box.num_items + 1; else { num_spaces = lb->layout_box.num_items - 1; if (num_spaces <= 0) num_spaces = 1; } if ((lb->layout_box.item_stretch == 0) || (lb->layout_box.total_stretch == 0)) { /* in this case, all the stretchiness goes to the spaces */ space += extra_space/num_spaces; } else { /* otherwise, spaces only get some of the extra space */ space_stretch = lb->layout_box.total_stretch * (int) lb->layout_box.space_stretch / ((int) (lb->layout_box.space_stretch + lb->layout_box.item_stretch)); /* rounding works better when we compute it this way */ total_space = space * num_spaces + space_stretch * factor; space = total_space / num_spaces; } } } else space = 0; /* compute the major position of the first child */ *cmajor0 = major_start; if (lb->layout_box.space_type == XmtLayoutSpaceEven) *cmajor0 += space; /* loop through all items in the box */ child_num = 0; ForEachItem(lb, child) { cc = LayoutConstraintsRec(child); /* * If this is an unmanaged child, we don't have to lay it out. * With the exception, however, that if it is an unmanaged row * or column, we've got to make sure that the contents of that * row or column are hidden. */ if (!XtIsManaged(child)) { if ((cc->type == XmtLayoutRow) || (cc->type == XmtLayoutCol)) HideHomelessChildren(child); continue; } child_num++; /* Get basic child size and add margins */ HorizontalMargins(lw, child, &margin_width, &left_margin); VerticalMargins(lw, child, &margin_height, &top_margin); cw = cc->pref_w + margin_width; ch = cc->pref_h + margin_height; /* if the box is "Equal", adjust major size of most children */ if (lb->layout_box.equal) { if ((cc->type != XmtLayoutSpace) && (cc->type != XmtLayoutHSep) && (cc->type != XmtLayoutVSep)) *cmajorlen = lb->layout_box.equal_size + *major_margin; } /* * stretch or shrink the child's width as needed. * but don't stretch if we've explictly given all stretchiness to * the spaces. */ if (factor != 0.0) { if (stretch) { if (lb->layout_box.item_stretch != 0) *cmajorlen += (int)(cc->stretchability * factor); } else { *cmajorlen -= (int)(cc->shrinkability * factor); } } /* * And never shrink to less than the size of the margins, * because otherwise the child will have a negative size. */ if (*cmajorlen <= *major_margin) *cmajorlen = *major_margin+1; /* set the minor coordinate depending on justification */ switch(cc->justification) { case XmtLayoutCentered: *cminor0 = minor_start + (minor_length - *cminorlen)/2; break; case XmtLayoutFlushLeft: *cminor0 = minor_start; break; case XmtLayoutFlushRight: *cminor0 = minor_start + minor_length - *cminorlen; break; case XmtLayoutFilled: *cminor0 = minor_start; *cminorlen = minor_length; break; } /* * But don't let the minor size be less than the size of the margins, * because otherwise the child will have a negative size. */ if (*cminorlen <= *minor_margin) *cminorlen = *minor_margin+1; /* * for Interval spacing, center the child around the interval. * for Tabbed spacing, position appropriately to the "tab stop". * for LCR spacing, left, center or right justify the child. * for other kinds, remember the starting point of next child. */ if (lb->layout_box.space_type == XmtLayoutSpaceInterval) *cmajor0 = major_start + interval * child_num - *cmajorlen/2; else if (lb->layout_box.space_type == XmtLayoutSpaceLTabbed) *cmajor0 = major_start + interval * (child_num-1); else if (lb->layout_box.space_type == XmtLayoutSpaceCTabbed) *cmajor0 = major_start + interval * child_num - interval/2 - *cmajorlen/2; else if (lb->layout_box.space_type == XmtLayoutSpaceRTabbed) *cmajor0 = major_start + interval * child_num - *cmajorlen; else if (lb->layout_box.space_type == XmtLayoutSpaceLCR) { /* first child is already handled */ if (child_num == 2) *cmajor0 = major_start + (major_length - *cmajorlen)/2; else if (child_num == 3) *cmajor0 = major_start + major_length - *cmajorlen; } /* * figure out where this child ends, * so we know where the next begins (for some space types) */ next = *cmajor0 + *cmajorlen; /* indent by the size of the margins, frame and captions */ cx += left_margin; cy += top_margin; cw -= margin_width; ch -= margin_height; /* set the child size and location */ if (XmtIsLayoutGadget(child)) { /* * fake out _XmConfigureObject: * 1) make the XmtLayoutGadget look like a RectObj, briefly. * 2) if this is a box, make sure this is not a no-op * by setting the child's width to something other than cw. */ XmtSetRectObj(child); if (XtClass(child) == xmtLayoutBoxGadgetClass) child->core.width = 0; _XmtConfigureObject(child, cx, cy, cw, ch, child->core.border_width); XmtUnsetRectObj(child); } else _XmtConfigureObject(child, cx, cy, cw, ch, child->core.border_width); /* set starting position for next child for space types that care */ *cmajor0 = next + space; } } /* ARGSUSED */ #if NeedFunctionPrototypes static XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply) #else static XtGeometryResult QueryGeometry(w, request, reply) Widget w; XtWidgetGeometry *request; XtWidgetGeometry *reply; #endif { XmtLayoutBoxGadget lb = (XmtLayoutBoxGadget) w; XmtLayoutWidget lw = (XmtLayoutWidget) XtParent(w); XmtLayoutConstraintsPart *cc; int total_width, total_height; int total_stretch, total_shrink; int max_width, max_height; int equal_width, equal_height; int total_equal_width, total_equal_height; int width, height; int margin_width, margin_height, top_margin, left_margin; int num_items; XtWidgetGeometry geometry; Widget child; total_width = total_height = 0; total_stretch = total_shrink = 0; equal_width = equal_height = total_equal_width = total_equal_height = 0; max_width = max_height = 0; num_items = 0; /* figure out the size of each child */ ForEachItem(lb, child) { /* * For each managed child: * figure out the basic size w/o margins. This may be a hardcoded * or a preferred size, or it may be the caption size. * if this is an "equal" box * compute the maximum marginless size * compute the total size of non-spaces and non-separators. * add the margins in * compute the total and maxmimum sizes with margins * compute the total stretchability and shrinkability */ if (!XtIsManaged(child)) continue; num_items++; cc = LayoutConstraintsRec(child); /* * Figure out the basic size of the child without margins. * This is either the preferred size of the child, or the * sizes specified on the layoutWidth and layoutHeight resources. * In either case, this basic size may have to be adjusted if it * is too small for the specified caption. */ /* * ask the child its preferred size, unless it will be overridden * by resources and the child is not a box we need to recursively * measure. */ if ((cc->width == 0) || (cc->height == 0) || (cc->type==XmtLayoutRow) || (cc->type==XmtLayoutCol)) XtQueryGeometry(child, NULL, &geometry); /* override widget's preferences with resources, if specified */ if (cc->width) width = cc->width; else width = geometry.width; if (cc->height) height = cc->height; else height = geometry.height; /* * if a top or bottom caption is wider than this width, or a * left or right caption is taller than this height, increase * the basic size to match. */ if (cc->caption) { if ((cc->caption_position == XmtLayoutTop) || (cc->caption_position == XmtLayoutBottom)) { if (cc->caption_width > width) width = cc->caption_width; } else { /* caption on the right or left */ if (cc->caption_height > height) height = cc->caption_height; } } /* remember this basic preferred or specified size */ cc->pref_w = width; cc->pref_h = height; /* handle rows or columns that are "equal" */ if (lb->layout_box.equal) { /* get maximum marginless sizes */ if (width > equal_width) equal_width = width; if (height > equal_height) equal_height = height; /* compute the total size of non-spaces and separators */ if ((cc->type != XmtLayoutSpace) && (cc->type != XmtLayoutHSep) && (cc->type != XmtLayoutVSep)) { total_equal_width += width; total_equal_height += height; } } /* compute the margins, and add them in */ HorizontalMargins(lw, child, &margin_width, &left_margin); VerticalMargins(lw, child, &margin_height, &top_margin); width += margin_width; height += margin_height; /* compute total and maximum sizes */ total_width += width; total_height += height; if (max_width < width) max_width = width; if (max_height < height) max_height = height; /* compute total stretch and shrink */ total_stretch += cc->stretchability; total_shrink += cc->shrinkability; } /* * if the row or column has the Equal flag set, go back through * the children and recompute the box width or height. * Note that spaces and separators aren't affected. */ if (lb->layout_box.equal) { if (lb->layout_box.orientation == XmHORIZONTAL) total_width -= total_equal_width; else total_height -= total_equal_height; ForEachItem(lb, child) { if (!XtIsManaged(child)) continue; cc = LayoutConstraintsRec(child); if ((cc->type != XmtLayoutSpace) && (cc->type != XmtLayoutHSep) && (cc->type != XmtLayoutVSep)) { if (lb->layout_box.orientation == XmHORIZONTAL) total_width += equal_width; else total_height += equal_height; } } } /* check for <= 3 children with LCR spacing */ if ((lb->layout_box.space_type == XmtLayoutSpaceLCR) && (num_items > 3)) { lb->layout_box.space_type = XmtLayoutSpaceLREven; XmtWarningMsg("XmtLayout", "lcr", "Widget '%s':\n\tSpace type is LCR, but number of childre is > 3.\n\tUsing LREven instead.", XtName((Widget)lw)); } /* adjust sizes depending on space model */ if ((lb->layout_box.space_type == XmtLayoutSpaceEven) || (lb->layout_box.space_type == XmtLayoutSpaceInterval)) { total_width += lb->layout_box.space * (num_items + 1); total_height += lb->layout_box.space * (num_items + 1); } else if ((lb->layout_box.space_type == XmtLayoutSpaceLREven) || (lb->layout_box.space_type == XmtLayoutSpaceLCR)) { total_width += lb->layout_box.space * (num_items - 1); total_height += lb->layout_box.space * (num_items - 1); } else if ((lb->layout_box.space_type == XmtLayoutSpaceLTabbed) || (lb->layout_box.space_type == XmtLayoutSpaceCTabbed) || (lb->layout_box.space_type == XmtLayoutSpaceRTabbed)) { total_width += lb->layout_box.space * num_items; total_height += lb->layout_box.space * num_items; } /* adjust the total_stretch to account for the spaces */ if (lb->layout_box.space_type != XmtLayoutSpaceNone) { if (lb->layout_box.item_stretch == 0) total_stretch = INFINITY; else total_stretch = total_stretch + total_stretch * (int)lb->layout_box.space_stretch / (int)lb->layout_box.item_stretch; } /* record information that we'll need when we lay this box out */ lb->layout_box.total_stretch = total_stretch; lb->layout_box.total_shrink = total_shrink; if (lb->layout_box.orientation == XmHORIZONTAL) lb->layout_box.equal_size = equal_width; else lb->layout_box.equal_size = equal_height; lb->layout_box.num_items = num_items; /* reply to the geometry query */ reply->request_mode = CWWidth | CWHeight; if (lb->layout_box.orientation == XmHORIZONTAL) { reply->width = total_width; reply->height = max_height; } else { reply->width = max_width; reply->height = total_height; } return XtGeometryYes; } #if NeedFunctionPrototypes static void Redisplay(Widget w, XEvent *event, Region region) #else static void Redisplay(w, event, region) Widget w; XEvent *event; Region region; #endif { XmtLayoutBoxGadget lb = (XmtLayoutBoxGadget) w; XmtLayoutWidget lw = (XmtLayoutWidget)XtParent(w); Widget child; XRectangle rect; Boolean filled = False; if (lw->core.window == None) return; if (lb->layout_box.gc != NULL) { XFillRectangle(lw->core.screen->display, lw->core.window, lb->layout_box.gc, lb->rectangle.x, lb->rectangle.y, lb->rectangle.width, lb->rectangle.height); if (region) { rect.x = lb->rectangle.x; rect.y = lb->rectangle.y; rect.width = lb->rectangle.width; rect.height = lb->rectangle.height; XUnionRectWithRegion(&rect, region, region); } filled = True; } ForEachItem(lb, child) { if (XmtIsLayoutGadget(child) && XtIsManaged(child)) { if (!region || filled || XRectInRegion(region, child->core.x, child->core.y, child->core.width, child->core.height)) _XmtRedisplayGadget(child, event, region); } } } #if NeedFunctionPrototypes Widget XmtCreateLayoutBox(Widget parent, String name, ArgList arglist, Cardinal num_args) #else Widget XmtCreateLayoutBox(parent, name, arglist, num_args) Widget parent; String name; ArgList arglist; Cardinal num_args; #endif { return XtCreateWidget(name, xmtLayoutBoxGadgetClass, parent, arglist, num_args); } #if NeedFunctionPrototypes Widget XmtCreateLayoutRow(Widget parent, String name, ArgList arglist, Cardinal num_args) #else Widget XmtCreateLayoutRow(parent, name, arglist, num_args) Widget parent; String name; ArgList arglist; Cardinal num_args; #endif { Widget w; w = XtVaCreateWidget(name, xmtLayoutBoxGadgetClass, parent, XmtNorientation, XmHORIZONTAL, NULL); XtSetValues(w, arglist, num_args); return w; } #if NeedFunctionPrototypes Widget XmtCreateLayoutCol(Widget parent, String name, ArgList arglist, Cardinal num_args) #else Widget XmtCreateLayoutCol(parent, name, arglist, num_args) Widget parent; String name; ArgList arglist; Cardinal num_args; #endif { Widget w; w = XtVaCreateWidget(name, xmtLayoutBoxGadgetClass, parent, XmtNorientation, XmVERTICAL, NULL); XtSetValues(w, arglist, num_args); return w; }