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.