DECwindows Motif Guide to Application Programming


Previous Contents Index

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();         
                };                            
           };                                             
   .
   .
   .

  1. 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.
  2. The object declaration defines a pull-down menu named options_menu.
  3. 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.
  4. The object declaration defines a pop-up color mixing widget named main_color. The UIL keyword for the color mixing widget is DXmColorMixDialog.
  5. 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();     
}                                     
                     
   .
   .
   .

  1. Include the color mixing widget resource file.
  2. The color mixing widget is declared in the global data section because it is referenced by more than one routine within the module.
  3. The savecolor XColor data structure is declared in the global data section because it is referenced by more than one routine within the module.
  4. 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.
  5. Test to see if OpenVMS DECburger is displaying on a color system. DECburger implements the customize background color feature only for color systems.
  6. If DECburger is displaying on a color system, set the Options cascade button to be mapped when managed.
  7. 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.
  8. The create_color routine is called as a result of the activate callback for the Background Color push button.
  9. If the color mixing widget does not already exist, fetch it.
  10. 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.
  11. 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.
  12. Call the XtSetArg and XtSetValues routines to set the original colors for the color mixing widget.
  13. Save the original XmNbackground color of the main window widget in case you need to restore it.
  14. 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.
  15. 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);     
 
  } 
   .
   .
   .

  1. The ok_color callback routine is called as a result of a user pressing the OK push button.
  2. 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.
  3. 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.
  4. 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);                    
    
}             
 
   .
   .
   .

  1. Unmanage the color mixing widget.
  2. 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.
  3. 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);   
        } 
 
    }     
           
 
 
 
   .
   .
   .


Previous Next Contents Index