.\"remove .ig hn for full docs .de hi .ig eh .. .de eh .. .TH "" 3 "" "Version 3.0" "Free Widget Foundation" .SH NAME XfwfRowCol .SH DESCRIPTION The RowCol widget forces all its children into rows and columns. The children keep their preferred size, but the preferred position is ignored. Resources determine how many rows or columns their should be (or as many as will fit) and if the children should be layed out in rows or in columns. In both methods, the children are placed on a grid, the size of which is determined by the width (height) of the widest (tallest) child. The children can be aligned in several ways: they can be placed in the center of their grid cell or against the edges. This is controlled by a resource of type \fIAlignment\fP. .SS "Public variables" .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. XfwfRowCol Name Class Type Default XtNstoreByRow XtCStoreByRow Boolean True XtNrows XtCRows Int 0 XtNcolumns XtCColumns Int 0 XtNalignment XtCAlignment Alignment XfwfTopLeft XtNshrinkToFit XtCShrinkToFit Boolean False .TE .ps .TP .I "XtNstoreByRow" The child widgets can be layed out in rows (left to right) or in columns (top to bottom). The resource \fIstoreByRow\fP can be \fITrue\fP or \fIFalse\fP. \fITrue\fP means children are added to the right of the previous one until the row is full, like words are added to a text. \fIFalse\fP means children are added below the previous one, until the column is full. .hi .nf Boolean storeByRow = True .fi .eh .TP .I "XtNrows" The number of rows can be set with \fIrows\fP, or the number of columns can be set with \fIcolumns\fP. If both are non-zero, \fIrows\fP will be ignored. If \fIrows\fP is zero, there will be as many rows as needed. If \fIcolumns\fP is zero, there will be as many columns as needed. However, if both are zero, there will be as many columns as will fit in the current width of the RowCol widget. By default, both \fIrows\fP and \fIcolumns\fP are zero. .hi .nf int rows = 0 .fi .eh .TP .I "XtNcolumns" .hi .nf int columns = 0 .fi .eh .TP .I "XtNalignment" The area of the RowCol widget is partitioned into rectangular cells (a grid). The cells are just large enough to contain the widest and the tallest of the children. Within the cell, the children can be put in the top left corner (the default) or against one of the edges or in the center. This is set with the \fIalignment\fP resource. The type \fIAlignment\fP is defined in the ancestor class `Common'. .hi .nf Alignment alignment = XfwfTopLeft .fi .eh .TP .I "XtNshrinkToFit" The resource \fIshrinkToFit\fP determines how the size of the RowCol widget itself is computed. When it is \fIFalse\fP (default), the \fIlocation\fP resource is used to compute the widget's preferred size. When the value is \fITrue\fP, the preferred size is computed fromthe total width and height of the children. For example, when the widest child has a width of \fIw\fP and \fIcolumns > 0\fP, the preferred width will be \fIcolumns * w +\fP frame width. A similar computation is used for the height. If \fIcolumns > 0\fP, only the height is computed this way. If \fIcolumns = 0, rows > 0\fP, only the width is computed. .hi .nf Boolean shrinkToFit = False .fi .eh .TP .I "XtNframeType" The inherited resource \fIframeType\fP is given a default value of \fIXfwfSunken\fP, instead of the inherited default \fIXfwfRaised\fP. The frame width is set to a default of 2 pixels, instead of 0. .hi .nf frameType = XfwfSunken .fi .eh .TP .I "XtNframeWidth" .hi .nf frameWidth = 2 .fi .eh .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. XfwfBoard Name Class Type Default XtNabs_x XtCAbs_x Position 0 XtNrel_x XtCRel_x Float "0.0" XtNabs_y XtCAbs_y Position 0 XtNrel_y XtCRel_y Float "0.0" XtNabs_width XtCAbs_width Position 0 XtNrel_width XtCRel_width Float "1.0" XtNabs_height XtCAbs_height Position 0 XtNrel_height XtCRel_height Float "1.0" XtNhunit XtCHunit Float "1.0" XtNvunit XtCVunit Float "1.0" XtNlocation XtCLocation String NULL .TE .ps .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. XfwfFrame Name Class Type Default XtNcursor XtCCursor Cursor None XtNframeType XtCFrameType FrameType XfwfRaised XtNframeWidth XtCFrameWidth Dimension 0 XtNouterOffset XtCOuterOffset Dimension 0 XtNinnerOffset XtCInnerOffset Dimension 0 XtNshadowScheme XtCShadowScheme ShadowScheme XfwfAuto XtNtopShadowColor XtCTopShadowColor Pixel compute_topcolor XtNbottomShadowColor XtCBottomShadowColor Pixel compute_bottomcolor XtNtopShadowStipple XtCTopShadowStipple Bitmap NULL XtNbottomShadowStipple XtCBottomShadowStipple Bitmap NULL .TE .ps .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. XfwfCommon Name Class Type Default XtNtraversalOn XtCTraversalOn Boolean True XtNhighlightThickness XtCHighlightThickness Dimension 2 XtNhighlightColor XtCHighlightColor Pixel XtDefaultForeground XtNhighlightPixmap XtCHighlightPixmap Pixmap None XtNnextTop XtCNextTop Callback NULL XtNuserData XtCUserData Pointer NULL .TE .ps .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. Composite Name Class Type Default XtNchildren XtCChildren WidgetList NULL insertPosition XtCInsertPosition XTOrderProc NULL numChildren XtCNumChildren Cardinal 0 .TE .ps .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. Core Name Class Type Default XtNx XtCX Position 0 XtNy XtCY Position 0 XtNwidth XtCWidth Dimension 0 XtNheight XtCHeight Dimension 0 borderWidth XtCBorderWidth Dimension 0 XtNcolormap XtCColormap Colormap NULL XtNdepth XtCDepth Int 0 destroyCallback XtCDestroyCallback XTCallbackList NULL XtNsensitive XtCSensitive Boolean True XtNtm XtCTm XTTMRec NULL ancestorSensitive XtCAncestorSensitive Boolean False accelerators XtCAccelerators XTTranslations NULL borderColor XtCBorderColor Pixel 0 borderPixmap XtCBorderPixmap Pixmap NULL background XtCBackground Pixel 0 backgroundPixmap XtCBackgroundPixmap Pixmap NULL mappedWhenManaged XtCMappedWhenManaged Boolean True XtNscreen XtCScreen Screen * NULL .TE .ps .hi .SS "Private variables" The width of the widest and the height of the tallest child are kept in private variables, for quicker access. .nf Dimension max_width .fi .nf Dimension max_height .fi .hi .hi .SS "Methods" If a child becomes managed or unmanaged, the RowCol widget recomputes the positions of all managed children. That is done by a method \fIlayout\fP. In the process, the widget may ask its parent for a different size if \fIshrinkToFit = True\fP. .nf change_managed($) { $layout($, $shrinkToFit); } .fi The \fIlayout\fP function is responsible for moving the children to their positions in the grid. It is called from \fIchange_managed\fP, \fIgeometry_manager\fP and \fIresize\fP. The function first computes the maximum width and height of all the children, including their borders. Then it computes the number of rows and columns. All children are moved to their proper positions with the help of a utility function \fIalign_child\fP, which aligns a child widget to the grid. If \fIshrink = True\fP, the RowCol widget also asks its parent for a new width and/or height, depending on the resulting layout. .nf layout($, int shrink) { int nrows, ncols, i, nchild, n; Position left, top, x, y; Dimension width, height, w, h; Widget child; nchild = 0; $max_width = 0; $max_height = 0; for (i = 0; i < $num_children; i++) { child = $children[i]; if (! XtIsManaged(child)) continue; nchild++; $max_width = max($max_width, $child$width + 2*$child$border_width); $max_height = max($max_height, $child$height + 2*$child$border_width); } $compute_inside($, left, top, width, height); if ($columns != 0) { ncols = $columns; nrows = (nchild + ncols - 1)/ncols; } else if ($rows != 0) { nrows = $rows; ncols = (nchild + nrows - 1)/nrows; } else { ncols = $max_width != 0 ? width/$max_width : 1; if (ncols == 0) ncols = 1; nrows = (nchild + ncols - 1)/ncols; } x = left; y = top; n = 0; if ($storeByRow) { for (i = 0; i < $num_children; i++) { child = $children[i]; if (! XtIsManaged(child)) continue; align_child(child, x, y, $max_width, $max_height, $alignment); n++; if (n == ncols) { n = 0; x = left; y += $max_height; } else x += $max_width; } } else { for (i = 0; i < $num_children; i++) { child = $children[i]; if (! XtIsManaged(child)) continue; align_child(child, x, y, $max_width, $max_height, $alignment); n++; if (n == nrows) { n = 0; y = top; x += $max_width; } else y += $max_height; } } if (shrink) { w = 2*left + ncols * $max_width; h = 2*top + nrows * $max_height; if ($columns != 0) XtVaSetValues($, XtNwidth, w, XtNheight, h, NULL); else XtVaSetValues($, XtNheight, h, NULL); } } .fi When a child wants to change its size or border width, it calls its parent's \fIgeometry_manager\fP method (through a call to \fIXtMakeGeometryRequest\fP or \fIXtMakeResizeRequest\fP.) The RowCol widget always grants size changes to its children. The size change is carried out immediately and a new layout is computed. If a child requests a change of position, the request is denied. A request for a change in stacking order is ignored. .nf XtGeometryResult geometry_manager(Widget child, XtWidgetGeometry * request, XtWidgetGeometry * reply) { Dimension newwd, newht, newbd; if (request->request_mode (CWX | CWY)) return XtGeometryNo; if (request->request_mode XtCWQueryOnly) return XtGeometryYes; newwd = request->request_mode CWWidth ? request->width : $child$width; newht = request->request_mode CWHeight ? request->height : $child$height; newbd = request->request_mode CWBorderWidth ? request->border_width : $child$border_width; if (newwd == $child$width newht == $child$height newbd == $child$border_width) return XtGeometryNo; XtResizeWidget(child, newwd, newht, newbd); $layout($, $shrinkToFit); return XtGeometryDone; } .fi The \fIresize\fP method is called when the widget is resized. If the \fIrows\fP and \fIcolumns\fP resources are both zero, the children will have to be be re-aligned. In this case, there is no sense in asking the parent for a new size, so \fIlayout\fP is passed a value of \fIFalse\fP. .nf resize($) { if ($rows == 0 $columns == 0) $layout($, False); } .fi The initialize method sets the private variables, in this case only \fImax_width\fP and \fImax_height\fP. There is no need to check if the resources have sensible values. .nf initialize(Widget request, $, ArgList args, Cardinal * num_args) { $max_width = $max_height = 0; } .fi The RowCol widget needs to recompute the positions of the children when one of the resources changes. When the layout changes, the widget also needs to be redrawn, of course. The private variables are not dependent on the resources, so they don't need recomputing. .nf Boolean set_values(Widget old, Widget request, $, ArgList args, Cardinal * num_args) { Boolean need_layout = False; Boolean need_redisplay = False; if ($old$storeByRow != $storeByRow) need_layout = True; if ($old$rows != $rows) need_layout = True; if ($old$columns != $columns) need_layout = True; if ($old$alignment != $alignment) need_layout = True; if ($old$shrinkToFit != $shrinkToFit) need_layout = True; if (need_layout) { $layout($, $shrinkToFit); need_redisplay = True; } return need_redisplay; } .fi .hi .hi .SH "Utilities" .nf char rcsid[] = "$Header: RowCol.w,v 1.1 92/10/14 18:36:36 bert Exp $" .fi \fIalign_child\fP puts a widget in the proper position in the cell given by \fIcx\fP, \fIcy\fP, \fIwidth\fP and \fIheight\fP. .nf align_child($, int cx, int cy, int width, int height, Alignment alignment) { Position x, y; if (alignment XfwfLeft) x = cx; else if (alignment XfwfRight) x = cx + width - $width; else x = cx + (width - $width) / 2; if (alignment XfwfTop) y = cy; else if (alignment XfwfBottom) y = cy + height - $height; else y = cy + (height - $height) / 2; XtMoveWidget($, x, y); } .fi .hi