Search the FAQ Archives

3 - A - B - C - D - E - F - G - H - I - J - K - L - M
N - O - P - Q - R - S - T - U - V - W - X - Y - Z
faqs.org - Internet FAQ Archives

Motif FAQ (Part 5 of 9)
Section - 128) How can I center a widget in a form?

( Part1 - Part2 - Part3 - Part4 - Part5 - Part6 - Part7 - Part8 - Part9 - Single Page )
[ Usenet FAQs | Web FAQs | Documents | RFC Index | Schools ]


Top Document: Motif FAQ (Part 5 of 9)
Previous Document: 127) Why don't labels in a Form resize when the label is changed?
Next Document: 129) How do I line up two columns of widgets of different types? I
See reader questions & answers on this topic! - Help others by sharing your knowledge
[Last modified: Nov 96]

Answer: One of Motif's trickier questions.  The problems are that: Form gives
no support for centering, only for edge attachments, and the widget must stay
in the center if the form or the widget is resized.  Just looking at
horizontal centering (vertical is similar) some solutions are:

 a.  Use the table widget instead of Form.  A hack free solution is from Dan
     Heller:

     /* Written by Dan Heller.  Copyright 1991, O'Reilly && Associates.
     * This program is freely distributable without licensing fees and
     * is provided without guarantee or warranty expressed or implied.
     * This program is -not- in the public domain.  This program is
     * taken from the Motif Programming Manual, O'Reilly Volume 6.
     */

     /* corners.c -- demonstrate widget layout management for a
     * BulletinBoard widget.  There are four widgets each labeled
     * top-left, top-right, bottom-left and bottom-right.  Their
     * positions in the bulletin board correspond to their names.
     * Only when the widget is resized does the geometry management
     * kick in and position the children in their correct locations.
     */
     #include <Xm/BulletinB.h>
     #include <Xm/PushBG.h>

     char *corners[] = {
     "Top-Left", "Top-Right", "Bottom-Left", "Bottom-Right",
     };

     static void resize();

     main(argc, argv)
     int argc;
     char *argv[];
     {
     Widget toplevel, bboard;
     XtAppContext app;
     XtActionsRec rec;
     int i;

     /* Initialize toolkit and create toplevel shell */
     toplevel = XtVaAppInitialize(&app, "Demos", NULL, 0,
     &argc, argv, NULL, NULL);

     /* Create your standard BulletinBoard widget */
     bboard = XtVaCreateManagedWidget("bboard",
     xmBulletinBoardWidgetClass, toplevel, NULL);

     /* Set up a translation table that captures "Resize" events
     * (also called ConfigureNotify or Configure events).  If the
     * event is generated, call the function resize().
     */
     rec.string = "resize";
     rec.proc = resize;
     XtAppAddActions(app, &rec, 1);

     /******** WARNING! Next statement is questionable in 1996. See
     ******** "Can you reuse the return value from XtParseTranslationTable?"
     ******** If someone corrects this code, send it to kenton@nojunk.rahul.net
     ********/

     XtOverrideTranslations(bboard,
     XtParseTranslationTable("<Configure>: resize()"));

     /* Create children of the dialog -- a PushButton in each corner. */
     for (i = 0; i < XtNumber(corners); i++)
     XtVaCreateManagedWidget(corners[i],
         xmPushButtonGadgetClass, bboard, NULL);

     XtRealizeWidget(toplevel);
     XtAppMainLoop(app);
     }

     /* resize(), the routine that is automatically called by Xt upon the
     * delivery of a Configure event.  This happens whenever the widget
     * gets resized.
     */
     static void
     resize(w, event, args, num_args)
     CompositeWidget w;   /* The widget (BulletinBoard) that got resized */
     XConfigureEvent *event;  /* The event struct associated with the event */
     String args[]; /* unused */
     int *num_args; /* unused */
     {
     WidgetList children;
     int width = event->width;
     int height = event->height;
     Dimension w_width, w_height;
     short margin_w, margin_h;

     /* get handle to BulletinBoard's children and marginal spacing */
     XtVaGetValues(w,
     XmNchildren, &children,
     XmNmarginWidth, &margin_w,
     XmNmarginHeight, &margin_h,
     NULL);

     /* place the top left widget */
     XtVaSetValues(children[0],
     XmNx, margin_w,
     XmNy, margin_h,
     NULL);

     /* top right */
     XtVaGetValues(children[1], XmNwidth, &w_width, NULL);

     /* To Center a widget in the middle of the BulletinBoard (or Form),
     * simply call:
     *   XtVaSetValues(widget,
       XmNx,    (width - w_width)/2,
       XmNy,    (height - w_height)/2,
       NULL);
     * and return.
     */
     XtVaSetValues(children[1],
     XmNx, width - margin_w - w_width,
     XmNy, margin_h,
     NULL);

     /* bottom left */
     XtVaGetValues(children[2], XmNheight, &w_height, NULL);
     XtVaSetValues(children[2],
     XmNx, margin_w,
     XmNy, height - margin_h - w_height,
     NULL);

     /* bottom right */
     XtVaGetValues(children[3],
     XmNheight, &w_height,
     XmNwidth, &w_width,
     NULL);
     XtVaSetValues(children[3],
     XmNx, width - margin_w - w_width,
     XmNy, height - margin_h - w_height,
     NULL);
     }

 b.  No uil solution has been suggested, because of the widget size problem.

 c.  Cameron Hayne (hayne@crim.ca) suggests another solution:

     Attach the widget with XmATTACH_POSITION but offset it by half of its
     width.  You will likely have to create the widget first and then query it
     to find out its width. Thus the following function is useful - you can
     call it immediately after the widget is created.

     void    center_it(Widget wgt)
     {
     Dimension       width;
     XtVaGetValues(wgt, XmNwidth, &width, NULL);
     XtVaSetValues(wgt, XmNleftAttachment, XmATTACH_POSITION,
                     XmNleftPosition, 50,  /* assumes fractionBase is 100 */
                     XmNleftOffset, -width/2, NULL);
     }

     The idea is: get the size of the widget and then offset it by half that
     much from position 50.  The above function will likely only work for
     primitive widgets if you call it immediately after the widget is created.
     For manager widgets you will likely have to wait to call the center_it()
     function until after the widget has been realized since it is only then
     that a manager widget's size is finally determined.  (Refer to discussion
     by Daniel Dardailler "Application's Geometry Management Advanced
     Guidelines" in this FAQ.)

User Contributions:

Comment about this article, ask questions, or add new information about this topic:




Top Document: Motif FAQ (Part 5 of 9)
Previous Document: 127) Why don't labels in a Form resize when the label is changed?
Next Document: 129) How do I line up two columns of widgets of different types? I

Part1 - Part2 - Part3 - Part4 - Part5 - Part6 - Part7 - Part8 - Part9 - Single Page

[ Usenet FAQs | Web FAQs | Documents | RFC Index ]

Send corrections/additions to the FAQ Maintainer:
kenton@rahul.net (Ken Lee)





Last Update March 27 2014 @ 02:11 PM