[comp.windows.x] Widgetization Made EZ

meo@stiatl.UUCP (Miles O'Neal) (11/01/88)

Currently, programming using the Athena Widget set is kind of a pain.
For even the simplest widget, there are usually several declarations to
be made, including the resource database, to be made, and 1 or more
routines that must be called to actually setup the Widget.

This quickly results in large source files, or many source files that
do very little, or something equally obnoxious.

As an initial attempt to solve this problem, I have started using macros
for the "standard" widgets within any given project. By standard widgets
I mean similar items based on the same Widget. As an example, I have an
application with a "control panel" that requires a number of similar
Command widgets; the primary differences between these buttons are the
label and the Widget ID. But I also may need similar buttons
with more differences; so the simple case just expands to an invocation
of the general case macro. The actual parameters which would be used are,
of course, based on one's needs. The macros, and sample calls, follow.

/*------------------------start of code -------------------------------*/

/*
   Copyright 1988 Sales Technologies, Inc. All rights reserved.

   Author : Miles O'Neal

   This code may be freely redistributed for any purpose as long
   as this copyright notice is included, and due credit is given
   in this or any copy of the original code, as well as any derived
   works and supporting documentation, and so long as neither the
   author's name nor Sales Technologies' name is used in any
   advertising or publicity related to anything related to this
   or any derivations thereof.
   
   This works for me when I use it, and should work with any X11r2
   package (and hopefully later versions), if used in a similar manner,
   but I won't guarantee it lest the lawyers get upset. No warranties
   implied or expressed. Use only as directed. Do not expose to
   direct sunlight. Mileage may vary.
*/

/*
   the following macros are defined in an include file, and reference
   constants from that include file; other than this, they are complete.
*/

/*
   define & realize a control panel button widget

   DEF_CPB (W, L)
      W     -  Widget ID
      WL    -  Widget label
*/
#define DEF_CPB(W, WL) \
      DEF_BUTTON (W, B_HEIGHT, B_WIDTH, WL, XtJustifyCenter, \
         B_BORDER_WIDTH, button_pressed, WL, commandWidgetClass, \
         button_box) \

/*
   define & realize a button widget
   the widget is set insensitive if the label is empty

   DEF_BUTTON (W, AH, AW, L, AJ, ABW, CBN, CLI, WC, WP)
      W     -  Widget ID
      AH    -  Widget height
      AW    -  Widget width
      L     -  Widget label
      AJ    -  Widget justify
      ABW   -  Widget borderWidth
      CBN   -  callback name
      CLI   -  callback client data (also Widget name)
      WC    -  Widget class
      WP    -  Widget parent (Widget)
*/
#define DEF_BUTTON(W, AH, AW, L, AJ, ABW, CBN, CLI, WC, WP) \
{ \
   static XtCallbackRec ButtonCallbacks [] = { \
      {CBN, (caddr_t) CLI}, \
      {NULL, NULL} \
   }; \
   static Arg ButtonArgs [] = { \
      {XtNheight, (XtArgVal) (AH)}, \
      {XtNwidth, (XtArgVal) (AW)}, \
      {XtNlabel, (XtArgVal) L}, \
      {XtNjustify, (XtArgVal) AJ}, \
      {XtNborderWidth, (XtArgVal) (ABW)}, \
      {XtNcallback, (XtArgVal) ButtonCallbacks}, \
      {XtNsensitive, (XtArgVal) ((sizeof (L) == 1)?(FALSE):(TRUE))}, \
   }; \
   W = (Widget) XtCreateManagedWidget(CLI, WC, WP, ButtonArgs, \
      XtNumber (ButtonArgs)); \
}



/*
   the following are examples of usages of the above macros.

   edit_status_button_pressed is a callback function declared
   earlier in this same file
*/

make_button_box_buttons (parent)

Widget parent;
{
   static Widget b1, b2, b3;

   DEF_BUTTON (b1, B_HEIGHT, B_WIDTH, EDIT_STATUS, XtJustifyCenter,
      B_BORDER_WIDTH, edit_status_button_pressed, EDIT_STATUS,
      commandWidgetClass, button_box);
   DEF_CPB (b2, UNDO);
   DEF_CPB (b3, EXIT);
}

/*------------------------- end of code -------------------------------*/


While this is certainly not the optimum solution to the problem,
it has let me get a lot of work done quickly, greatly reduces the
size of the source file, and allows mods to a generic widget type
to be made easily.

In particular, for the application I am currently developing, adding
one of the widgets defined as above has gone from about 5 - 10 minutes
editing time to about 30 seconds. The total source file size has been
cut from several thousand lines to less than 400.

As my Fearless Leader says, "macros are our friends."

The scope rules allow reuse of the variable names, while the
static declarations keep the variables around after the block
is exited.

Another thing I do is declare the Widget statically inside the macro block
when I know I don't need to reference it externally.

I have similar macros for Label widgets, Prompt Widgets, Desk (stupid
Box) Widgets, etc.

Please feel free to critique this in news or via email. If there is
enough interest, I could post related tips.