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.