.\"remove .ig hn for full docs .de hi .ig eh .. .de eh .. .TH "" 3 "" "Version 3.0" "Free Widget Foundation" .SH NAME XfwfGroup .SH DESCRIPTION The Group widget is a subclass of RowCol, which means that it arranges its children in rows and columns. (See the RowCol widget for the resources that influence the layout.) The Group widget adds two things to the capabilities already present in RowCol, namely a label in the upper left hand corner and the ability to make a number of Toggle buttons act as radio buttons. The label is a short, one line piece of text, that is displayed over the border in the top left corner. The border is interupted at that point. Since this works best with `ledged' or `chiseled' border types, the default border is \fIXfwfChiseled\fP. The special support for radio buttons works as follows: when a child is added the Group widget checks if it is of class \fIXfwfToggle\fP or a subclass thereof. If so, the Group widget installs a callback in it. When the toggle button is then activated, the Group widget determines which other buttons need to be turned off. All toggle buttons are given an implicit number. The first one to be added is number 0. There are three selection styles, settable through the \fIselectionStyle\fP resource: 1) `single' (\fIXfwfSingleSelection\fP) means that at most one of the toggle buttons may be on, but it is possible that they are all off. When one of the buttons is turned on, all others are turned off automatically. The resource \fIselection\fP holds the number of the button that is on, or -1 if they are all off. 2) `one' (\fIXfwfOneSelection\fP) means that at all times exactly one button is turned on. It is not possible to turn buttons off, except by toggling another one to on. The resource \fIselection\fP holds the number of the button that is currently on. 3) `multi' or `multiple' (\fIXfwfMultipleSelection\fP) means that any number of buttons may be on. No buttons are turned off automatically. The resource \fIselection\fP has one bit set for each button that is on. Thus, if buttons 1, 4 and 5 are on, the value of \fIselection\fP is (1<<1 + 1<<4 + 1<<5 =) 0x62. Note that this limits the number of buttons that is recorded in \fIselection\fP to the first 32. It is still possible to have more buttons, but the application will then have to use callbacks or other means to keep track of the toggle buttons. 4) `none' (\fIXfwfNoSelection\fP) turns off any special handling of toggle buttons. The value of the \fIselection\fP resource is undefined. Applications may of course install callbacks on the toggle buttons, but a simpler way is to attach to the \fIactivateCallback\fP of the Group widget itself, or use no callback at all and simply inspect the \fIselection\fP resource when needed. It is recommended that application visually differentiate between selection styles. One way would be to use different graphics in the toggle buttons, e.g., the Motif convention that radiobuttons have an empty or colored diamond, and non-exclusive toggles a square. Suitable icons are already defined by the Common widget. .SS "Public variables" .ps-2 .TS center box; cBsss lB|lB|lB|lB l|l|l|l. XfwfGroup Name Class Type Default XtNlabel XtCLabel String NULL XtNfont XtCFont FontStruct XtDefaultFont XtNforeground XtCForeground Pixel XtDefaultForeground XtNselectionStyle XtCSelectionStyle SelectionType XfwfSingleSelection XtNselection XtCSelection Long 0 XtNactivate XtCActivate Callback NULL .TE .ps .TP .I "XtNlabel" The label must be a single line. It is displayed superimposed on the frame, in the upper lefthand corner. Currently, it must be simple string in a single font. .hi .nf String label = NULL .fi .eh .TP .I "XtNfont" The font for the label is set with \fIfont\fP. .hi .nf XFontStruct * font = XtDefaultFont .fi .eh .TP .I "XtNforeground" The foreground color is the color used to draw the text. .hi .nf Pixel foreground = XtDefaultForeground .fi .eh .TP .I "XtNselectionStyle" The \fIselectionStyle\fP resource determines how the Group widget treats the child widgets that are of class \fIXfwfToggle\fP or a subclass thereof. The possible values are \fIXfwfNoSelection\fP, \fIXfwfSingleSelection\fP (default), \fIXfwfOneSelection\fP and \fIXfwfMultipleSelection\fP. The meaning is as explained above. There is a converter from strings, that recognizes the strings `no', `none', `single', `one', `multi', and `multiple', in upper or lower case. .hi .nf SelectionType selectionStyle = XfwfSingleSelection .fi .eh .TP .I "XtNselection" The resource \fIselection\fP holds the state of the toggle buttons (if any). If \fIselectionType = XfwfSingleSelection\fP or \fIXfwfOneSelection\fP, it holds the number of the buttons that is currently on, or -1 if they are all off. If \fIselectionType = XfwfMultipleSelection\fP, it is a bitmap with one bit set for each button that is on. (See the introduction above for more information.) The value can also be set (e.g., through \fIXtSetValues\fP); the result is that the corresponding toggle buttons will be turned on or off. .hi .nf long selection = 0 .fi .eh .TP .I "XtNactivate" The callback \fIactivate\fP can be used by applications that want to be informed of any change to the state of the toggle buttons as soon as it happens. Other applications can simply use \fIXtGetValues\fP to get the value of the \fIselection\fP resource. The callback will be called with the value of \fIselection\fP as \fIcall_data\fP argument. .hi .nf XtCallbackList activate = NULL .fi .eh .TP .I "XtNframeType" The default border type is different from that of its superclass RowCol. It is set to \fIXfwfChiseled\fP because that is the conventional border type around radio buttons, and because it looks better when there is a label superimposed on it. .hi .nf FrameType frameType = XfwfChiseled .fi .eh .TP .I "XtNinnerOffset" The default value for \fIinnerOffset\fP is set to 3 pixels, which makes it a little bit more likely that the descenders of the label will stay visible. .hi .nf innerOffset = 3 .fi .eh .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 .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 .SS "Exports" The \fISelectionType\fP type is exported to the public header file. .nf .B type SelectionType = enum { XfwfNoSelection, XfwfSingleSelection, XfwfOneSelection, XfwfMultipleSelection } .fi .hi .SH "Importss" .nf .B incl .fi .nf .B incl .fi .nf .B incl .fi .nf .B incl .fi .hi .hi .SS "Private variables" The GC is used for the text. .nf GC textgc .fi The private variable \fItoggle_ord\fP holds the number that will be assigned to the next child that is a toggle button. The first toggle will be number 0. .nf Cardinal toggle_ord .fi .hi .hi .SS "Methods" The type converter from String to SelectionType is installed here. .nf class_initialize() { XtAddConverter(XtRString, XtRLong, XmuCvtStringToLong, NULL, 0); XtSetTypeConverter(XtRLong, XtRString, XfwfCvtLongToString, NULL, 0, XtCacheNone, NULL); XtSetTypeConverter(XtRString, XtRSelectionType, cvtStringToSelectionType, NULL, 0, XtCacheNone, NULL); XtSetTypeConverter(XtRSelectionType, XtRString, cvtSelectionTypeToString, NULL, 0, XtCacheNone, NULL); } .fi The \fIinitialize\fP method initializes the private variables. .nf initialize(Widget request, $, ArgList args, Cardinal * num_args) { $toggle_ord = 0; $textgc = NULL; make_textgc($); if ($selectionStyle == XfwfOneSelection $selection == -1L) { XtWarning ("Illegal combination of selectionStyle and selection resources"); $selection = 0; } } .fi The \fIset_values\fP method has to deal with changes in \fIlabel\fP, \fIfont\fP, \fIselectionType\fP or \fIselection\fP. A change in \fIselection\fP or \fIselectionType\fP means that all toggle buttons must be set to on or off according to the new values. .nf Boolean set_values(Widget old, Widget request, $, ArgList args, Cardinal * num_args) { Boolean need_redraw = False; if ($old$label != $label) { XtFree($old$label); $label = XtNewString($label); need_redraw = True; } if ($font != $old$font) { make_textgc($); if ($label != NULL) need_redraw = True; } if ($old$selection != $selection || $old$selectionStyle != $selectionStyle) { if ($selectionStyle == XfwfOneSelection $selection == -1L) $selection = 0; set_toggles($); } return need_redraw; } .fi The \fIexpose\fP method first calls the \fIexpose\fP method of its superclass -- which basically just draws the frame -- and then adds the label to it. .nf expose($, XEvent * event, Region region) { Dimension w, h; Position x, y; if (! XtIsRealized($)) return; #expose($, event, region); $compute_inside($, x, y, w, h); XDrawImageString(XtDisplay($), XtWindow($), $textgc, x + 3, y - $innerOffset, $label, strlen($label)); } .fi When a child is added, the Group widget checks to see if it is a Toggle button. If it is, and the \fIselectionStyle\fP resource is not \fIXfwfNoSelection\fP, then the toggle button is assigned a number and two callbacks are installed in it. The callbacks' task is to record any changes in the state of the togle button in the Group widget's \fIselection\fP resource and also to make sure that no more and no fewer buttons are turned on then is allowed by the \fIselectionStyle\fP. It doesn't matter whether the new child is managed or not: any child that is (a subclass of) an XfwfToggle button gets two callbacks and a number. The \fIon\fP resource of the new child is also set in accordance with the current value of the Group's \fIselection\fP resource. .nf insert_child(Widget child) { #insert_child(child); if ($selectionStyle != XfwfNoSelection XtIsSubclass(child, xfwfToggleWidgetClass)) { XtAddCallback(child, XtNonCallback, on_cb, (XtPointer) $toggle_ord); XtAddCallback(child, XtNoffCallback, off_cb, (XtPointer) $toggle_ord); switch ($selectionStyle) { case XfwfOneSelection: case XfwfSingleSelection: XtVaSetValues(child, XtNon, $toggle_ord == $selection, NULL); break; case XfwfMultipleSelection: XtVaSetValues(child, XtNon, ($selection (1L<<$toggle_ord)) != 0, NULL); break; default: ; } $toggle_ord++; } } .fi .hi .hi .SH "Utilities" The \fImake_textgc\fP routine creates the GC for the text. .nf make_textgc($) { XtGCMask mask; XGCValues values; if ($textgc != NULL) XtReleaseGC($, $textgc); values.background = $background_pixel; values.foreground = $foreground; values.font = $font->fid; mask = GCFont | GCBackground | GCForeground; $textgc = XtGetGC($, mask, values); } .fi The task of the \fIon_cb\fP callback function is to record the changed state of the toggle button and maybe turn off other toggle buttons. When the new value of \fIselection\fP is computed, the \fIactivate\fP callbacks are called. .nf on_cb(Widget toggle, XtPointer client_data, XtPointer call_data) { Widget $ = XtParent(toggle); Cardinal toggle_ord = (Cardinal) client_data; Cardinal t, i, bits = sizeof($selection) * 8; switch ($selectionStyle) { case XfwfMultipleSelection: if (toggle_ord < bits) $selection |= 1L << toggle_ord; break; case XfwfSingleSelection: case XfwfOneSelection: if ($selection != -1L) for (t = 0, i = 0; i < $num_children; i++) if (XtIsSubclass($children[i], xfwfToggleWidgetClass)) { if ($selection == t) { XtVaSetValues($children[i], XtNon, False, NULL); break; } t++; } $selection = toggle_ord; break; default: ; } XtCallCallbackList($, $activate, (XtPointer) $selection); } .fi The task of the \fIoff_cb\fP callback function is to update the \fIselection\fP resource and check if turning off the toggle button is allowed. If the \fIselectionStyle\fP is \fIXfwfOneSelection\fP, toggles cannot be turned off, except by turning on another one. .nf off_cb(Widget toggle, XtPointer client_data, XtPointer call_data) { Widget $ = XtParent(toggle); Cardinal toggle_ord = (Cardinal) client_data; Cardinal t, i, bits = sizeof($selection) * 8; switch ($selectionStyle) { case XfwfOneSelection: XtVaSetValues(toggle, XtNon, True, NULL); /* Undo */ break; case XfwfSingleSelection: $selection = -1L; /* Nothing selected */ break; case XfwfMultipleSelection: if (toggle_ord < bits) $selection = ~(1L << toggle_ord); break; default: ; } XtCallCallbackList($, $activate, (XtPointer) $selection); } .fi The function \fIset_toggles\fP is used when the \fIselection\fP resource or the \fIselectionStyle\fP resource changes. It inspects all child widgets in turn and turns toggles on or off according to the values of these two resources. .nf set_toggles($) { Cardinal i, t; for (t = 0, i = 0; i < $num_children; i++) if (XtIsSubclass($children[i], xfwfToggleWidgetClass)) { switch ($selectionStyle) { case XfwfNoSelection: break; case XfwfSingleSelection: case XfwfOneSelection: XtVaSetValues($children[i], XtNon, t == $selection, NULL); break; case XfwfMultipleSelection: XtVaSetValues($children[i], XtNon, ($selection (1L<addr != NULL) { if (to->size < sizeof(type)) { to->size = sizeof(type); return False; } *(type*)(to->addr) = (value); } else { static type static_val; static_val = (value); to->addr = (XtPointer)static_val; } to->size = sizeof(type); return True; }while (0 ) .nf Boolean cvtStringToSelectionType(Display * display, XrmValuePtr args, Cardinal * num_args, XrmValuePtr from, XrmValuePtr to, XtPointer * converter_data) { String s = (String) from->addr; if (*num_args != 0) XtAppErrorMsg(XtDisplayToApplicationContext(display), "cvtStringToSelectionType", "wrongParameters", "XtToolkitError", "String to SelectionType conversion needs no arguments", (String*) NULL, (Cardinal*) NULL); if (XmuCompareISOLatin1(s, "no") == 0) done(SelectionType, XfwfNoSelection); if (XmuCompareISOLatin1(s, "none") == 0) done(SelectionType, XfwfNoSelection); if (XmuCompareISOLatin1(s, "single") == 0) done(SelectionType, XfwfSingleSelection); if (XmuCompareISOLatin1(s, "one") == 0) done(SelectionType, XfwfOneSelection); if (XmuCompareISOLatin1(s, "multi") == 0) done(SelectionType, XfwfMultipleSelection); if (XmuCompareISOLatin1(s, "multiple") == 0) done(SelectionType, XfwfMultipleSelection); XtDisplayStringConversionWarning(display, s, XtRSelectionType); done(SelectionType, XfwfSingleSelection); } .fi A converter in the opposite direction. .nf Boolean cvtSelectionTypeToString(Display * display, XrmValuePtr args, Cardinal * num_args, XrmValuePtr from, XrmValuePtr to, XtPointer * converter_data) { char s[30]; if (*num_args != 0) XtAppErrorMsg(XtDisplayToApplicationContext(display), "cvtStringToSelectionStyle", "wrongParameters", "XtToolkitError", "String to SelectionStyle conversion needs no arguments", (String*) NULL, (Cardinal*) NULL); switch (*((SelectionType*) from->addr)) { case XfwfNoSelection: done(String, "none"); case XfwfSingleSelection: done(String, "single"); case XfwfOneSelection: done(String, "one"); case XfwfMultipleSelection: done(String, "multiple"); } XtDisplayStringConversionWarning(display, s, XtRSelectionType); done(String, "none"); } .fi .hi