 |
DECwindows Motif Guide to Application
Programming
6.7.1 Creating a Color Mixing Widget---UIL Example
Example 6-2 creates the options menu entry and color mixing widget
used in the OpenVMS DECburger example program. The example defines a
color mixing widget that uses the default color display subwidget and
the default color mixer subwidget.
Example 6-2 Creating a Color Mixing
Widget---UIL Example |
.
.
.
! The options pull-down entry and its associated pull-down menu.
object
options_menu_entry : XmCascadeButton {
arguments {
XmNlabelString = k_options_label_text;
XmNmnemonic = keysym("O");
(1)XmNmappedWhenManaged = false;
};
controls {
XmPulldownMenu options_menu;
};
callbacks {
MrmNcreateCallback = procedure create_proc (k_options_pdme);
XmNhelpCallback = procedure sens_help_proc(k_options_help);
};
};
(2)object
options_menu : XmPulldownMenu {
controls {
XmPushButton m_options_control_button;
};
callbacks {
MrmNcreateCallback = procedure create_proc (k_options_menu);
XmNhelpCallback = procedure sens_help_proc(k_options_help);
};
};
(3)object
m_options_control_button : XmPushButton {
arguments
{
XmNlabelString = k_options_color_label_text;
XmNmnemonic = keysym("C");
};
callbacks {
MrmNcreateCallback = procedure create_proc (k_create_options);
XmNactivateCallback = procedure activate_proc (k_create_options);
XmNhelpCallback = procedure sens_help_proc(k_options_help);
};
};
(4)object main_color : DXmColorMixDialog
{
arguments
{
XmNdialogTitle = "DECburger: Background Color";
DXmNmainLabel = compound_string("Colormix Example");
};
(5)callbacks
{
XmNhelpCallback = procedure sens_help_proc(k_options_help);
XmNcancelCallback = procedure cancel_color_proc();
XmNokCallback = procedure ok_color_proc();
XmNapplyCallback = procedure apply_color_proc();
};
};
.
.
.
|
- The object declaration defines a cascade
button named options_menu_entry. The
XmNmappedWhenManaged resource is set to false because
OpenVMS DECburger uses the Options menu entry only on color systems.
- The object declaration defines a pull-down
menu named options_menu.
- The options_menu pull-down menu controls the
Background Color push button. The create_color routine is called as a
result of the activate callback for this push button.
- The object declaration defines a pop-up
color mixing widget named main_color. The UIL keyword for the color
mixing widget is DXmColorMixDialog.
- The callbacks list section of the UIL object
declaration assigns values to each of the primary callbacks performed
by the color mixing widget.
Example 6-3 shows the C source code associated with the UIL module.
Example 6-3 C Source Code for Creating a
Color Mixing Widget with UIL |
.
.
.
(1)#include <DXm/DXmColor.h>
.
.
.
/*
* Global data
*/
static Cursor watch = NULL;
static Widget
toplevel_widget = (Widget)NULL, /* Root widget ID of the application */
main_window_widget = (Widget)NULL, /* Root widget ID of main MRM fetch */
widget_array[MAX_WIDGETS], /* Place to keep all other widget IDs */
main_help_widget = (Widget)NULL, /* Primary help widget */
help_widget[MAX_WIDGETS], /* Array of help widgets */
help_array[MAX_WIDGETS], /* Array of help widgets for Toolkit */
print_widget = (Widget)NULL, /* Print widget */
(2)color_widget = (Widget)NULL; /* Color Mix widget */
static Screen *the_screen; /* Pointer to screen data*/
static Display *the_display; /* Pointer to display data */
(3)static XColor savecolor;
.
.
.
/*
* Forward declarations
*/
static void s_error();
static void get_something();
static void set_something();
static void activate_proc();
static void create_proc();
static void list_proc();
static void exit_proc();
static void pull_proc();
static void scale_proc();
static void show_hide_proc();
static void show_label_proc();
static void toggle_proc();
static void create_help();
static void tracking_help();
static void sens_help_proc();
static void help_system_proc();
static void create_print();
static void activate_print();
(4)static void create_color();
static void ok_color_proc();
static void apply_color_proc();
static void cancel_color_proc();
static void xmstring_append();
static void start_watch();
static void stop_watch();
.
.
.
/* The names and addresses of things that Mrm has to bind. The names do
* not have to be in alphabetical order. */
static MrmRegisterArg reglist[] = {
{"activate_proc", (caddr_t) activate_proc},
{"create_proc", (caddr_t) create_proc},
{"list_proc", (caddr_t) list_proc},
{"pull_proc", (caddr_t) pull_proc},
{"exit_proc", (caddr_t) exit_proc},
{"scale_proc", (caddr_t) scale_proc},
{"show_hide_proc", (caddr_t) show_hide_proc},
{"show_label_proc", (caddr_t) show_label_proc},
{"toggle_proc", (caddr_t) toggle_proc},
{"sens_help_proc", (caddr_t) sens_help_proc},
{"help_system_proc", (caddr_t) help_system_proc},
{"cancel_color_proc", (caddr_t) cancel_color_proc},
{"apply_color_proc", (caddr_t) apply_color_proc},
{"ok_color_proc", (caddr_t) ok_color_proc}
};
.
.
.
/* If it's a color display, map customize color menu entry */
(5)if ((XDefaultVisualOfScreen(the_screen))->class == TrueColor
|| (XDefaultVisualOfScreen(the_screen))->class == PseudoColor
|| (XDefaultVisualOfScreen(the_screen))->class == DirectColor
|| (XDefaultVisualOfScreen(the_screen))->class == StaticColor)
(6)XtSetMappedWhenManaged(widget_array[k_options_pdme], TRUE);
.
.
.
/*
* One-time initialization of application data structures.
*/
static int init_application()
{
int k;
int a = i;
/* Initialize the application data structures. */
for (k = 0; k < MAX_WIDGETS; k++)
widget_array[k] = NULL;
for (k = 0; k < NUM_BOOLEAN; k++)
toggle_array[k] = FALSE;
/* Initialize CS help widgets. */
for (a = 0; a < MAX_WIDGETS; a++)
help_widget[a] = NULL;
/* Initialize help widgets for Toolkit creation. */
for (a = 0; a < MAX_WIDGETS; a++)
help_array[a] = NULL;
/* Initialize print widgets. */
print_widget = NULL;
/* Initialize color mix widget. */
(7)color_widget = NULL;
.
.
.
/*
* All push buttons in this application call back to this routine. We
* use the tag to tell us what widget it is, then react accordingly.
*/
static void activate_proc(w, tag, reason)
Widget w;
int *tag;
XmAnyCallbackStruct *reason;
{
int widget_num = *tag; /* Convert tag to widget number. */
int a, value;
XmString topic;
switch (widget_num) {
case k_nyi:
/* The user activated a 'not yet implemented' push button. Send
* the user a message. */
if (widget_array[k_nyi] == NULL) {
/* The first time, fetch from the data base. */
if (MrmFetchWidget(s_MrmHierarchy, "nyi", toplevel_widget,
&widget_array[k_nyi], &dummy_class) != MrmSUCCESS) {
s_error("can't fetch nyi widget");
}
}
/* Put up the message box saying 'not yet implemented'. */
XtManageChild(widget_array[k_nyi]);
break;
.
.
.
(8)case k_create_options:
create_color();
break;
default:
break;
}
}
.
.
.
/* Color Mixing Widget Creation */
static void create_color()
{
XColor newcolor;
unsigned int ac;
Arg arglist[10];
start_watch();
(9)if (!color_widget) {
if (MrmFetchWidget (s_MrmHierarchy, "main_color", toplevel_widget,
&color_widget, &dummy_class) != MrmSUCCESS)
s_error ("can't fetch color mix widget");
(10)XtSetArg(arglist[0], XmNbackground, &newcolor.pixel);
XtGetValues(main_window_widget, arglist, 1);
(11)XQueryColor(the_display,
XDefaultColormapOfScreen(the_screen), &newcolor);
(12)ac = 0;
XtSetArg (arglist[ac], DXmNorigRedValue, newcolor.red); ac++;
XtSetArg (arglist[ac], DXmNorigGreenValue, newcolor.green); ac++;
XtSetArg (arglist[ac], DXmNorigBlueValue, newcolor.blue); ac++;
XtSetValues(color_widget, arglist, ac);
(13)savecolor.red = newcolor.red;
savecolor.green = newcolor.green;
savecolor.blue = newcolor.blue;
savecolor.pixel = newcolor.pixel;
} else {
(14)XtSetArg(arglist[0], XmNbackground, &savecolor.pixel);
XtGetValues(main_window_widget, arglist, 1);
XQueryColor(the_display,
XDefaultColormapOfScreen(the_screen), &savecolor);
}
(15)XtManageChild(color_widget);
stop_watch();
}
.
.
.
|
- Include the color mixing widget resource
file.
- The color mixing widget is declared in the
global data section because it is referenced by more than one routine
within the module.
- The savecolor XColor data structure is
declared in the global data section because it is referenced by more
than one routine within the module.
- Forward declaration to the color mixing
routines.
When a user presses the OK, Apply, or Cancel push button,
the color mixing widget performs a callback to your application. The
ok, apply, and cancel callback routines are provided for this purpose.
- Test to see if OpenVMS DECburger is
displaying on a color system. DECburger implements the customize
background color feature only for color systems.
- If DECburger is displaying on a color
system, set the Options cascade button to be mapped when managed.
- Make sure that the color mixing widget
starts with a null value. The create_color routine tests to see if the
color mixing widgets exists. Initializing the widget to NULL makes sure
that it does not contain invalid data.
- The create_color routine is called as a
result of the activate callback for the Background Color push button.
- If the color mixing widget does not already
exist, fetch it.
- When the color mixing widget is first
managed, the original color of the Color Display Subwidget should match
the color of the object to be changed, in this case the main window
widget. Therefore, the example calls the XtSetArg and XtGetValues
intrinsic routines to get the background color of the main window
widget and store it in the newcolor.pixel pixel field.
- The example then calls the Xlib XQueryColor
routine to get the RGB values associated with the pixel value in
newcolor.pixel. The XQueryColor routine fills in the
red, green, and blue fields of the newcolor data
structure.
This implementation allows the application to determine
the initial color for the Color Display Subwidget at run time.
Note
The only way to set the DXmNorigRedValue,
DXmNorigGreenValue, and
DXmNorigBlueValue resources through UIL is to use hard
coded RGB values.
This practice is not recommended because there is no way to guarantee
that the hard coded RGB values will match the actual color of the
object to be changed.
|
- Call the XtSetArg and XtSetValues routines
to set the original colors for the color mixing widget.
- Save the original XmNbackground color of the
main window widget in case you need to restore it.
- If the color mixing widget already exists,
get the current XmNbackground pixel value for the main window widget,
and then call XQueryColor to get the associated RGB values. The
savecolor.red, savecolor.green, and
savecolor.blue fields store the RGB values in case you
need to restore them.
- Manage the color mixing widget. The color
mixing widget callbacks update the color mixing widget as needed.
6.7.2 Color Mixing Widget---OK Callback
The OpenVMS DECburger OK callback routine is shown in Example 6-4.
Example 6-4 Color Mixing Widget---OK
Callback |
.
.
.
/* Color Mix OK Callback */
(1)static void ok_color_proc(widget_id, tag, reason)
Widget widget_id;
int *tag;
DXmColorMixCallbackStruct *reason;
{
int ac;
Arg arglist[10];
XColor newcolor;
(2)newcolor.red = reason->newred;
newcolor.green = reason->newgrn;
newcolor.blue = reason->newblu;
(3)if (XAllocColor(the_display,
XDefaultColormapOfScreen(the_screen), &newcolor)) {
(4)ac = 0;
XtSetArg (arglist[ac], XmNbackground, newcolor.pixel);ac++;
XtSetValues(widget_array[k_total_order], arglist, ac);
XtSetValues(main_window_widget, arglist, ac);
}
else
s_error ("can't allocate color cell");
XtUnmanageChild(color_widget);
ac = 0;
XtSetArg (arglist[ac], DXmNorigRedValue, newcolor.red);ac++;
XtSetArg (arglist[ac], DXmNorigGreenValue, newcolor.green);ac++;
XtSetArg (arglist[ac], DXmNorigBlueValue, newcolor.blue);ac++;
XtSetValues(color_widget, arglist, ac);
}
.
.
.
|
- The ok_color callback routine is called as a
result of a user pressing the OK push button.
- The red, green, and blue members of the
newcolor data structure are initialized to the RGB values selected by
the user and returned by the color mixing widget in the
reason argument.
- Allocate a color cell entry. You pass the
Xlib XAllocColor routine the display identifier and color map to use,
and a pointer to an XColor data structure. XAllocColor fills in the
XColor.pixel member with the RGB value determined by
the red, green, and blue RGB values of the data structure.
- Set the background
attribute of the k_total_order widget, which is the XmScrolledList
widget child of the main window widget. The k_total_order widget is on
top of the main window widget in the window hierarchy. Therefore, the
background color of this widget must match the background color of the
main window widget.
Set the background attribute
of the main window widget.
6.7.3 Color Mixing Widget---Apply Callback
The OpenVMS DECburger apply callback routine is shown in Example 6-5.
The apply callback is similar to the OK callback with the exception
that the apply callback does not update or unmanage the color mixing
widget.
Example 6-5 Color Mixing Widget---Apply
Callback |
.
.
.
/* Color Mix Apply Callback */
static void apply_color_proc(widget_id, tag, reason)
Widget widget_id;
int *tag;
DXmColorMixCallbackStruct *reason;
{
int ac;
Arg arglist[10];
XColor newcolor;
newcolor.red = reason->newred;
newcolor.green = reason->newgrn;
newcolor.blue = reason->newblu;
if (XAllocColor(the_display,
XDefaultColormapOfScreen(the_screen), &newcolor)) {
ac = 0;
XtSetArg (arglist[ac], XmNbackground, newcolor.pixel);ac++;
XtSetValues(widget_array[k_total_order], arglist, ac);
XtSetValues(main_window_widget, arglist, ac);
}
else
s_error ("can't allocate color cell");
}
.
.
.
|
6.7.4 Color Mixing Widget---Cancel Callback
The OpenVMS DECburger cancel callback routine is shown in
Example 6-6. The cancel callback unmanages the color mixing widget
and restores the main window widget to the state it was in when it was
last managed. The Cancel callback removes any changes the user might
have made by clicking the Apply push button.
Example 6-6 Color Mixing Widget---Cancel
Callback |
.
.
.
/* Color Mix Cancel Callback */
static void cancel_color_proc(widget_id, tag, reason)
Widget widget_id;
int *tag;
DXmColorMixCallbackStruct *reason;
{
int ac;
Arg arglist[10];
(1)XtUnmanageChild(color_widget);
(2)ac = 0;
XtSetArg (arglist[ac], XmNbackground, savecolor.pixel);ac++;
XtSetValues(widget_array[k_total_order], arglist, ac);
(3)XtSetValues(main_window_widget, arglist, ac);
}
.
.
.
|
- Unmanage the color mixing widget.
- Restore the k_total_order widget to the
state it was in when it was last managed. The k_total_order widget is
on top of the main window widget in the window hierarchy. Therefore,
the background color of this widget must match the background color of
the main window widget.
- Restore the main window widget to the state
it was in when it was last managed.
6.7.5 Creating a Color Mixing Widget---Toolkit Example
The code section shown in Example 6-7 can be used to set the
background color of the OpenVMS DECburger example program main window.
Example 6-7 Creating a Color Mixing
Widget---Toolkit Example |
.
.
.
/* Color Mix Widget Creation */
static void create_color()
{
unsigned int ac;
Arg arglist[10];
XtCallbackRec ok_callback_arg[2];
XtCallbackRec apply_callback_arg[2];
XtCallbackRec cancel_callback_arg[2];
XColor newcolor;
Arg al[1];
(1)if (!color_widget) {
apply_callback_arg[0].callback = apply_color_proc;
apply_callback_arg[0].closure = 0;
apply_callback_arg[1].callback = NULL;
apply_callback_arg[1].closure = NULL;
cancel_callback_arg[0].callback = cancel_color_proc;
cancel_callback_arg[0].closure = 0;
cancel_callback_arg[1].callback = NULL;
cancel_callback_arg[1].closure = NULL;
ok_callback_arg[0].callback = ok_color_proc;
ok_callback_arg[0].closure = 0;
ok_callback_arg[1].callback = NULL;
ok_callback_arg[1].closure = NULL;
(2)XtSetArg(al[0], XmNbackground, &newcolor.pixel);
XtGetValues(main_window_widget, al, 1);
(3)XQueryColor(the_display,
XDefaultColormapOfScreen(the_screen), &newcolor);
(4)ac = 0;
XtSetArg (arglist[ac], XmNcancelCallback, cancel_callback_arg);ac++;
XtSetArg (arglist[ac], XmNokCallback, ok_callback_arg); ac++;
XtSetArg (arglist[ac], XmNapplyCallback, apply_callback_arg); ac++;
XtSetArg (arglist[ac], DXmNorigRedValue, newcolor.red); ac++;
XtSetArg (arglist[ac], DXmNorigGreenValue, newcolor.green); ac++;
XtSetArg (arglist[ac], DXmNorigBlueValue, newcolor.blue); ac++;
XtSetArg (arglist[ac], DXmNcolorModel, DXmColorModelPicker); ac++;
(5)color_widget = DXmCreateColorMixDialog (toplevel_widget,
"Color Mix Widget",
arglist, ac);
(6)savecolor.red = newcolor.red;
savecolor.green = newcolor.green;
savecolor.blue = newcolor.blue;
savecolor.pixel = newcolor.pixel;
(7)XtManageChild(color_widget);
return;
}
else {
ac = 0;
(8)XtSetArg(arglist[ac], XmNbackground, &savecolor.pixel);
XtGetValues(main_window_widget, arglist, 1);
XQueryColor(the_display,
XDefaultColormapOfScreen(the_screen), &savecolor);
(9)XtManageChild(color_widget);
}
}
.
.
.
|
|