HP OpenVMS Systems Documentation |
DECwindows Motif Guide to Application Programming
Chapter 3
|
DXmInitialize(); |
The DXmInitialize routine calls MrmRegisterClass for the widgets supplied by Digital. If you do not call DXmInitialize, you will see error messages similar to the following when you run your application:
X Toolkit Warning: Urm__WCI_LookupClassDescriptor: Couldn't find class descriptor for class xxxxxxx - MrmNOT_FOUND |
The sections that follow describe additional XmForm widget programming
hints. See the OSF/Motif Programmer's Reference for a complete description of the XmForm
widget.
3.2.1 Creating a Form Dialog Box with Children
One of the common uses of the XmForm widget is to anchor rows and columns of widgets so that their alignment does not change if the size of the XmForm widget changes. The UIL example shown in Example 3-1 implements such an XmForm widget.
Example 3-1 XmForm Dialog with Children---UIL Module |
---|
. . . object form_main : XmForm{ arguments { XmNdialogTitle = compound_string("XmForm"); XmNwidth = 400; XmNheight = 400; }; (1)controls { XmPushButton a_button; XmPushButton b_button; XmPushButton c_button; XmPushButton d_button; XmPushButton e_button; XmPushButton f_button; XmPushButton g_button; XmPushButton h_button; XmPushButton i_button; XmPushButton j_button; }; }; object (2)a_button : XmPushButton { arguments { XmNlabelString = compound_string("a button"); XmNtopAttachment = XmATTACH_FORM; XmNtopOffset = 25; XmNleftAttachment = XmATTACH_FORM; XmNleftOffset = 25; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object (3)b_button : XmPushButton { arguments { XmNlabelString = compound_string("b button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = a_button; XmNleftAttachment = XmATTACH_FORM; XmNleftOffset = 25; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object c_button : XmPushButton { arguments { XmNlabelString = compound_string("c button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = b_button; XmNleftAttachment = XmATTACH_FORM; XmNleftOffset = 25; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object d_button : XmPushButton { arguments { XmNlabelString = compound_string("d button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = c_button; XmNleftAttachment = XmATTACH_FORM; XmNleftOffset = 25; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object e_button : XmPushButton { arguments { XmNlabelString = compound_string("e button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = d_button; XmNleftAttachment = XmATTACH_FORM; XmNleftOffset = 25; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object (4)f_button : XmPushButton { arguments { XmNlabelString = compound_string("f button"); XmNtopAttachment = XmATTACH_FORM; XmNtopOffset = 25; XmNleftAttachment = XmATTACH_WIDGET; XmNleftOffset = 5; XmNleftWidget = a_button; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object (5)g_button : XmPushButton { arguments { XmNlabelString = compound_string("g button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = f_button; XmNleftAttachment = XmATTACH_WIDGET; XmNleftOffset = 5; XmNleftWidget = b_button; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object h_button : XmPushButton { arguments { XmNlabelString = compound_string("h button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = g_button; XmNleftAttachment = XmATTACH_WIDGET; XmNleftOffset = 5; XmNleftWidget = c_button; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object i_button : XmPushButton { arguments { XmNlabelString = compound_string("i button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = h_button; XmNleftAttachment = XmATTACH_WIDGET; XmNleftOffset = 5; XmNleftWidget = d_button; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object j_button : XmPushButton { arguments { XmNlabelString = compound_string("j button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = i_button; XmNleftAttachment = XmATTACH_WIDGET; XmNleftOffset = 5; XmNleftWidget = e_button; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; . . . |
object b_button : XmPushButton { arguments { XmNlabelString = compound_string("b button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = a_button; XmNleftAttachment = XmATTACH_OPPOSITE_WIDGET; XmNleftWidget = a_button; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; object c_button : XmPushButton { arguments { XmNlabelString = compound_string("b button"); XmNtopAttachment = XmATTACH_WIDGET; XmNtopOffset = 5; XmNtopWidget = b_button; XmNleftAttachment = XmATTACH_OPPOSITE_WIDGET; XmNleftWidget = a_button; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; }; }; |
The UIL module shown in Example 3-1 correctly aligns the XmPushButtons and maintains this relationship regardless of the size of the XmForm. However, this alignment would be broken if the XmPushButton widgets were of different sizes. For example, a long title in button b would push button g to the right.
If your application needs to align widgets of varying sizes, you can put the XmPushButtons into XmRowColumn widgets, which expand to fit the largest child. You then align the XmRowColumn widgets within an XmForm widget.
The UIL example shown in Example 3-2 implements an XmForm widget that has children of different sizes.
Example 3-2 Aligning Children of Different Sizes |
---|
. . . object form_main : XmForm{ arguments { XmNdialogTitle = compound_string("XmForm"); XmNwidth = 400; XmNheight = 400; }; (1)controls { XmRowColumn align_a; XmRowColumn align_b; }; }; object align_a : XmRowColumn { arguments { XmNunitType = XmPIXELS; (2)XmNtopAttachment = XmATTACH_FORM; XmNtopOffset = 25; XmNleftAttachment = XmATTACH_FORM; XmNleftOffset = 25; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; XmNorientation = XmVERTICAL; XmNborderWidth = 0; }; controls { XmPushButton a_button; XmPushButton b_button; XmPushButton c_button; XmPushButton d_button; XmPushButton e_button; }; }; object a_button : XmPushButton { arguments { XmNlabelString = compound_string("a button"); }; }; object b_button : XmPushButton { arguments { XmNlabelString = compound_string("b button"); }; }; object c_button : XmPushButton { arguments { XmNlabelString = compound_string("Long Button Title"); }; }; object d_button : XmPushButton { arguments { XmNlabelString = compound_string("d button"); }; }; object e_button : XmPushButton { arguments { XmNlabelString = compound_string("Long Button Title"); }; }; object align_b : XmRowColumn { arguments { XmNunitType = XmPIXELS; XmNtopAttachment = XmATTACH_FORM; XmNtopOffset = 25; (3)XmNleftAttachment = XmATTACH_WIDGET; XmNleftWidget = align_a; XmNleftOffset = 25; XmNbottomAttachment = XmATTACH_NONE; XmNrightAttachment = XmATTACH_NONE; XmNorientation = XmVERTICAL; XmNborderWidth = 0; }; controls { XmPushButton f_button; XmPushButton g_button; XmPushButton h_button; XmPushButton i_button; XmPushButton j_button; }; }; object f_button : XmPushButton { arguments { XmNlabelString = compound_string("f button"); }; }; object g_button : XmPushButton { arguments { XmNlabelString = compound_string("g button"); }; }; object h_button : XmPushButton { arguments { XmNlabelString = compound_string("h button"); }; }; object i_button : XmPushButton { arguments { XmNlabelString = compound_string("i button"); }; }; object j_button : XmPushButton { arguments { XmNlabelString = compound_string("j button"); }; }; . . . |
The XmForm widget lets you attach an edge of a widget to a position in the XmForm widget. Instead of specifying the position by its x- and y-coordinates, you specify the position as a fraction of the total dimension of the XmForm widget. This is called fractional positioning.
You specify this type of attachment by passing the attachment type constant XmNATTACH_POSITION as the value of the attachment type attribute and the numerator of the fractional position as the value of the attachment position attribute.
For example, the midpoint of the XmForm widget is one-half the distance between the two edges. To attach the left edge of a child widget to the midpoint of the XmForm widget, set the XmNleftAttachment attribute to XmNATTACH_POSITION and specify the numerator of 50 in the XmNleftPosition attribute. (The default denominator is 100.)
Note that you can also treat the XmNleftPosition argument as a percentage, where a value of 50 means 50%.
Note, however, that this aligns the left edge of the child widget with the midpoint of the XmForm widget; the child widget is not centered. To center the child widget at the midpoint, you can:
Example 3-3 and Example 3-4 show how to center child widgets by using offset values. The MrmNcreateCallback routine computes width and height offsets that center the XmPushButton widgets at their respective positions. These position and offset relationships are maintained regardless of any resizing operations performed on the XmForm widget.
Example 3-3 Centering Child Widgets at Positions in XmForm---UIL Module |
---|
. . . module form version = 'v1.0' names = case_sensitive procedure center_form (); object (1)form_main : XmForm{ arguments { XmNdialogTitle = compound_string("XmForm"); XmNwidth = 400; XmNheight = 400; }; controls { XmPushButton a_arrow; XmPushButton b_arrow; XmPushButton c_arrow; }; }; object a_arrow : XmPushButton { (2)arguments { XmNlabelString = compound_string("centered"); XmNtopAttachment = XmATTACH_POSITION; XmNtopPosition = 50; XmNbottomAttachment = XmATTACH_NONE; XmNleftAttachment = XmATTACH_POSITION; XmNleftPosition = 25; XmNrightAttachment = XmATTACH_NONE; }; callbacks { (3)MrmNcreateCallback = procedure center_form(); }; }; object b_arrow : XmPushButton { (4)arguments { XmNlabelString = compound_string("centered"); XmNtopAttachment = XmATTACH_POSITION; XmNtopPosition = 50; XmNbottomAttachment = XmATTACH_NONE; XmNleftAttachment = XmATTACH_POSITION; XmNleftPosition = 50; XmNrightAttachment = XmATTACH_NONE; }; callbacks { MrmNcreateCallback = procedure center_form(); }; }; object c_arrow : XmPushButton { (5)arguments { XmNlabelString = compound_string("centered"); XmNtopAttachment = XmATTACH_POSITION; XmNtopPosition = 50; XmNbottomAttachment = XmATTACH_NONE; XmNleftAttachment = XmATTACH_POSITION; XmNleftPosition = 75; XmNrightAttachment = XmATTACH_NONE; }; callbacks { MrmNcreateCallback = procedure center_form(); }; }; end module; . . . |
Example 3-4 Centering Child Widgets at Positions in XmForm---C Module |
---|
. . . #include <stdio> #include <Mrm/MrmAppl.h> #include <DXm/DXmCSText.h> Widget toplevel, form_w; static MrmHierarchy s_MrmHierarchy; static MrmType *dummy_class; static char *db_filename_vec[] = {"center_form.uid" }; /* Forward declarations */ static void center_form(); /* The names and addresses of things that Mrm has to bind. The names do * not have to be in alphabetical order. */ static MrmRegisterArg reglist[] = { {"center_form", (caddr_t) center_form} }; static int reglist_num = (sizeof reglist / sizeof reglist [0]); int main(argc, argv) unsigned int argc; char **argv; { XtAppContext app_context; MrmInitialize(); DXmInitialize(); toplevel = XtAppInitialize(&app_context, "example", NULL, 0, &argc, argv, NULL, NULL, 0); /* Open the UID files (the output of the UIL compiler) in the hierarchy*/ if (MrmOpenHierarchy(1, db_filename_vec, NULL, &s_MrmHierarchy) !=MrmSUCCESS) printf("can't open hierarchy"); MrmRegisterNames(reglist, reglist_num); if (MrmFetchWidget(s_MrmHierarchy, "form_main", toplevel, &form_w, &dummy_class) != MrmSUCCESS) printf("can't fetch widget"); XtManageChild(form_w); XtRealizeWidget(toplevel); XtAppMainLoop(app_context); } static void center_form(w, tag, reason) Widget w; int *tag; unsigned long *reason; { Arg arglist[10]; int ac; int calc_width = 0; int width_b = 0; int calc_height = 0; int height_b = 0; /* Get the button width and height*/ (1)ac = 0; XtSetArg(arglist[ac], XmNwidth, &width_b); ac++; XtSetArg(arglist[ac], XmNheight, &height_b); ac++; XtGetValues(w, arglist, ac); /* Calculate the button width and height */ (2)calc_width = width_b/2; calc_height = height_b/2; ac = 0; (3)XtSetArg (arglist[ac], XmNleftOffset, -calc_width); ac++; (4)XtSetArg (arglist[ac], XmNtopOffset, -calc_height); ac++; XtSetValues (w, arglist, ac); } . . . |
The Toolkit includes a routine, DXmFormSpaceButtonsEqually, that applications can call to set a variable number of push buttons in an XmForm widget so they are equally spaced and sized. DXmFormSpaceButtonsEqually determines the width of the XmForm widget and the number of XmPushButtons and then spaces and sizes the XmPushButtons accordingly.
You pass to DXmFormSpaceButtonsEqually the widget ID of the XmForm widget that contains the XmPushButtons, an array of the widget IDs of the XmPushButtons to be changed, and the number of XmPushButtons in the widget array.
You must specify the XmPushButton IDs in the order they appear in the XmForm widget; for example, OK, Apply, Reset, and Cancel. Additionally, the XmPushButtons must not have left and right attachments.
Example 3-5, the DXmFormSpaceButtonsEqually routine, is from the OpenVMS DECburger sample program. It spaces the OK, Apply, Reset, and Cancel push buttons in the XmFormDialog widget.
Example 3-5 Calling the DXmFormSpaceButtonsEqually Routine |
---|
. . . #define k_ok 6 /* NOTE: ok, apply, reset, cancel */ #define k_apply 7 /* must be sequential */ #define k_reset 8 #define k_cancel 9 . . . static void show_hide_proc(w, tag, reason) Widget w; int *tag; XmAnyCallbackStruct *reason; { if (XtIsManaged(widget_array[k_order_box])) XtUnmanageChild(widget_array[k_order_box]); else { start_watch(); XtManageChild(widget_array[k_order_box]); DXmFormSpaceButtonsEqually (widget_array[k_order_box], &widget_array[k_ok], 4); stop_watch(); } } |
Previous | Next | Contents | Index |