Toggle.c

Go to the documentation of this file.
00001 /* $XConsortium: Toggle.c,v 1.28 94/04/17 20:13:17 kaleb Exp $ */
00002 
00003 /*
00004 
00005 Copyright (c) 1989, 1994  X Consortium
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00020 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023 
00024 Except as contained in this notice, the name of the X Consortium shall not be
00025 used in advertising or otherwise to promote the sale, use or other dealings
00026 in this Software without prior written authorization from the X Consortium.
00027 
00028  */
00029 
00030 /*
00031  * Toggle.c - Toggle button widget
00032  *
00033  * Author: Chris D. Peterson
00034  *         MIT X Consortium 
00035  *         kit@expo.lcs.mit.edu
00036  *  
00037  * Date:   January 12, 1989
00038  *
00039  */
00040 
00041 #include <stdio.h>
00042 
00043 #include <X11/IntrinsicP.h>
00044 #include <X11/StringDefs.h>
00045 #include <X11/Xaw3d/XawInit.h>
00046 #include <X11/Xmu/Converters.h>
00047 #include <X11/Xmu/Misc.h>
00048 #include <X11/Xaw3d/ToggleP.h>
00049 
00050 /****************************************************************
00051  *
00052  * Full class record constant
00053  *
00054  ****************************************************************/
00055 
00056 /* Private Data */
00057 
00058 /* 
00059  * The order of toggle and notify are important, as the state has
00060  * to be set when we call the notify proc.
00061  */
00062 
00063 static char defaultTranslations[] =
00064     "<EnterWindow>:         highlight(Always)   \n\
00065      <LeaveWindow>:         unhighlight()       \n\
00066      <Btn1Down>,<Btn1Up>:   toggle() notify()";
00067 
00068 #define offset(field) XtOffsetOf(ToggleRec, field)
00069 
00070 static XtResource resources[] = { 
00071    {XtNstate, XtCState, XtRBoolean, sizeof(Boolean), 
00072       offset(command.set), XtRString, "off"},
00073    {XtNradioGroup, XtCWidget, XtRWidget, sizeof(Widget), 
00074       offset(toggle.widget), XtRWidget, (XtPointer) NULL },
00075    {XtNradioData, XtCRadioData, XtRPointer, sizeof(XtPointer), 
00076       offset(toggle.radio_data), XtRPointer, (XtPointer) NULL },
00077 };
00078 
00079 #undef offset
00080 
00081 
00082 static void Toggle(), Initialize(), Notify(), ToggleSet();
00083 static void ToggleDestroy(), ClassInit();
00084 static Boolean SetValues();
00085 
00086 /* Functions for handling the Radio Group. */
00087 
00088 static RadioGroup * GetRadioGroup();
00089 static void CreateRadioGroup(), AddToRadioGroup(), TurnOffRadioSiblings();
00090 static void RemoveFromRadioGroup();
00091 
00092 static XtActionsRec actionsList[] =
00093 {
00094   {"toggle",            Toggle},
00095   {"notify",            Notify},
00096   {"set",               ToggleSet},
00097 };
00098 
00099 #define SuperClass ((CommandWidgetClass)&commandClassRec)
00100 
00101 ToggleClassRec toggleClassRec = {
00102   {
00103     (WidgetClass) SuperClass,           /* superclass             */    
00104     "Toggle",                           /* class_name             */
00105     sizeof(ToggleRec),                  /* size                   */
00106     ClassInit,                          /* class_initialize       */
00107     NULL,                               /* class_part_initialize  */
00108     FALSE,                              /* class_inited           */
00109     Initialize,                         /* initialize             */
00110     NULL,                               /* initialize_hook        */
00111     XtInheritRealize,                   /* realize                */
00112     actionsList,                        /* actions                */
00113     XtNumber(actionsList),              /* num_actions            */
00114     resources,                          /* resources              */
00115     XtNumber(resources),                /* resource_count         */
00116     NULLQUARK,                          /* xrm_class              */
00117     FALSE,                              /* compress_motion        */
00118     TRUE,                               /* compress_exposure      */
00119     TRUE,                               /* compress_enterleave    */
00120     FALSE,                              /* visible_interest       */
00121     NULL,                               /* destroy                */
00122     XtInheritResize,                    /* resize                 */
00123     XtInheritExpose,                    /* expose                 */
00124     SetValues,                          /* set_values             */
00125     NULL,                               /* set_values_hook        */
00126     XtInheritSetValuesAlmost,           /* set_values_almost      */
00127     NULL,                               /* get_values_hook        */
00128     NULL,                               /* accept_focus           */
00129     XtVersion,                          /* version                */
00130     NULL,                               /* callback_private       */
00131     defaultTranslations,                /* tm_table               */
00132     XtInheritQueryGeometry,             /* query_geometry         */
00133     XtInheritDisplayAccelerator,        /* display_accelerator    */
00134     NULL                                /* extension              */
00135   },  /* CoreClass fields initialization */
00136   {
00137     XtInheritChangeSensitive            /* change_sensitive       */ 
00138   },  /* SimpleClass fields initialization */
00139   {
00140     XtInheritXaw3dShadowDraw            /* shadowdraw          */
00141   },  /* ThreeDClass fields initialization */
00142   {
00143     0                                     /* field not used    */
00144   },  /* LabelClass fields initialization */
00145   {
00146     0                                     /* field not used    */
00147   },  /* CommandClass fields initialization */
00148   {
00149       NULL,                             /* Set Procedure. */
00150       NULL,                             /* Unset Procedure. */
00151       NULL                              /* extension. */
00152   }  /* ToggleClass fields initialization */
00153 };
00154 
00155   /* for public consumption */
00156 WidgetClass toggleWidgetClass = (WidgetClass) &toggleClassRec;
00157 
00158 /****************************************************************
00159  *
00160  * Private Procedures
00161  *
00162  ****************************************************************/
00163 
00164 static void
00165 ClassInit()
00166 {
00167   XtActionList actions;
00168   Cardinal num_actions;
00169   Cardinal i;
00170   ToggleWidgetClass class = (ToggleWidgetClass) toggleWidgetClass;
00171   static XtConvertArgRec parentCvtArgs[] = {
00172       {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent),
00173            sizeof(Widget)}
00174   };
00175 
00176   XawInitializeWidgetSet();
00177   XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget,
00178                      parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone,
00179                      (XtDestructor)NULL);
00180 /* 
00181  * Find the set and unset actions in the command widget's action table. 
00182  */
00183 
00184   XtGetActionList(commandWidgetClass, &actions, &num_actions);
00185 
00186   for (i = 0 ; i < num_actions ; i++) {
00187     if (streq(actions[i].string, "set"))
00188         class->toggle_class.Set = actions[i].proc;
00189     if (streq(actions[i].string, "unset")) 
00190         class->toggle_class.Unset = actions[i].proc;
00191 
00192     if ( (class->toggle_class.Set != NULL) &&
00193          (class->toggle_class.Unset != NULL) ) {
00194         XtFree((char *) actions);
00195         return;
00196     }
00197   }  
00198 
00199 /* We should never get here. */
00200   XtError("Aborting, due to errors resolving bindings in the Toggle widget.");
00201 }
00202 
00203 /*ARGSUSED*/
00204 static void Initialize(request, new, args, num_args)
00205  Widget request, new;
00206  ArgList args;
00207  Cardinal *num_args;
00208 {
00209     ToggleWidget tw = (ToggleWidget) new;
00210     ToggleWidget tw_req = (ToggleWidget) request;
00211 
00212     tw->toggle.radio_group = NULL;
00213 
00214     if (tw->toggle.radio_data == NULL) 
00215       tw->toggle.radio_data = (XtPointer) new->core.name;
00216 
00217     if (tw->toggle.widget != NULL) {
00218       if ( GetRadioGroup(tw->toggle.widget) == NULL) 
00219         CreateRadioGroup(new, tw->toggle.widget);
00220       else
00221         AddToRadioGroup( GetRadioGroup(tw->toggle.widget), new);
00222     }      
00223     XtAddCallback(new, XtNdestroyCallback, ToggleDestroy, (XtPointer)NULL);
00224 
00225 /*
00226  * Command widget assumes that the widget is unset, so we only 
00227  * have to handle the case where it needs to be set.
00228  *
00229  * If this widget is in a radio group then it may cause another
00230  * widget to be unset, thus calling the notify proceedure.
00231  *
00232  * I want to set the toggle if the user set the state to "On" in 
00233  * the resource group, reguardless of what my ancestors did.
00234  */
00235 
00236     if (tw_req->command.set)
00237       ToggleSet(new, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
00238 }
00239 
00240 /************************************************************
00241  *
00242  *  Action Procedures
00243  *
00244  ************************************************************/
00245 
00246 /* ARGSUSED */
00247 static void 
00248 ToggleSet(w,event,params,num_params)
00249 Widget w;
00250 XEvent *event;
00251 String *params;         /* unused */
00252 Cardinal *num_params;   /* unused */
00253 {
00254     ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
00255 
00256     TurnOffRadioSiblings(w);
00257     class->toggle_class.Set(w, event, NULL, 0);
00258 }
00259 
00260 /* ARGSUSED */
00261 static void 
00262 Toggle(w,event,params,num_params)
00263 Widget w;
00264 XEvent *event;
00265 String *params;         /* unused */
00266 Cardinal *num_params;   /* unused */
00267 {
00268   ToggleWidget tw = (ToggleWidget)w;
00269   ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
00270 
00271   if (tw->command.set) 
00272     class->toggle_class.Unset(w, event, NULL, 0);
00273   else 
00274     ToggleSet(w, event, params, num_params);
00275 }
00276 
00277 /* ARGSUSED */
00278 static void Notify(w,event,params,num_params)
00279 Widget w;
00280 XEvent *event;
00281 String *params;         /* unused */
00282 Cardinal *num_params;   /* unused */
00283 {
00284   ToggleWidget tw = (ToggleWidget) w;
00285   long antilint = tw->command.set;
00286 
00287   XtCallCallbacks( w, XtNcallback, (XtPointer) antilint );
00288 }
00289 
00290 /************************************************************
00291  *
00292  * Set specified arguments into widget
00293  *
00294  ***********************************************************/
00295 
00296 /* ARGSUSED */
00297 static Boolean 
00298 SetValues (current, request, new, args, num_args)
00299 Widget current, request, new;
00300 ArgList args;
00301 Cardinal *num_args;
00302 {
00303     ToggleWidget oldtw = (ToggleWidget) current;
00304     ToggleWidget tw = (ToggleWidget) new;
00305     ToggleWidget rtw = (ToggleWidget) request;
00306 
00307     if (oldtw->toggle.widget != tw->toggle.widget)
00308       XawToggleChangeRadioGroup(new, tw->toggle.widget);
00309 
00310     if (!tw->core.sensitive && oldtw->core.sensitive && rtw->command.set)
00311         tw->command.set = True;
00312 
00313     if (oldtw->command.set != tw->command.set) {
00314         tw->command.set = oldtw->command.set;
00315         Toggle(new, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
00316     }
00317     return(FALSE);
00318 }
00319 
00320 /*      Function Name: ToggleDestroy
00321  *      Description: Destroy Callback for toggle widget.
00322  *      Arguments: w - the toggle widget that is being destroyed.
00323  *                 junk, grabage - not used.
00324  *      Returns: none.
00325  */
00326 
00327 /* ARGSUSED */
00328 static void
00329 ToggleDestroy(w, junk, garbage)
00330 Widget w;
00331 XtPointer junk, garbage;
00332 {
00333   RemoveFromRadioGroup(w);
00334 }
00335 
00336 /************************************************************
00337  *
00338  * Below are all the private procedures that handle 
00339  * radio toggle buttons.
00340  *
00341  ************************************************************/
00342 
00343 /*      Function Name: GetRadioGroup
00344  *      Description: Gets the radio group associated with a give toggle
00345  *                   widget.
00346  *      Arguments: w - the toggle widget who's radio group we are getting.
00347  *      Returns: the radio group associated with this toggle group.
00348  */
00349 
00350 static RadioGroup *
00351 GetRadioGroup(w)
00352 Widget w;
00353 {
00354   ToggleWidget tw = (ToggleWidget) w;
00355 
00356   if (tw == NULL) return(NULL);
00357   return( tw->toggle.radio_group );
00358 }
00359 
00360 /*      Function Name: CreateRadioGroup
00361  *      Description: Creates a radio group. give two widgets.
00362  *      Arguments: w1, w2 - the toggle widgets to add to the radio group.
00363  *      Returns: none.
00364  * 
00365  *      NOTE:  A pointer to the group is added to each widget's radio_group
00366  *             field.
00367  */
00368 
00369 static void
00370 CreateRadioGroup(w1, w2)
00371 Widget w1, w2;
00372 {
00373   char error_buf[BUFSIZ];
00374   ToggleWidget tw1 = (ToggleWidget) w1;
00375   ToggleWidget tw2 = (ToggleWidget) w2;
00376 
00377   if ( (tw1->toggle.radio_group != NULL) || (tw2->toggle.radio_group != NULL) ) {
00378     (void) sprintf(error_buf, "%s %s", "Toggle Widget Error - Attempting",
00379             "to create a new toggle group, when one already exists.");
00380     XtWarning(error_buf);
00381   }
00382 
00383   AddToRadioGroup( (RadioGroup *)NULL, w1 );
00384   AddToRadioGroup( GetRadioGroup(w1), w2 );
00385 }
00386 
00387 /*      Function Name: AddToRadioGroup
00388  *      Description: Adds a toggle to the radio group.
00389  *      Arguments: group - any element of the radio group the we are adding to.
00390  *                 w - the new toggle widget to add to the group.
00391  *      Returns: none.
00392  */
00393 
00394 static void
00395 AddToRadioGroup(group, w)
00396 RadioGroup * group;
00397 Widget w;
00398 {
00399   ToggleWidget tw = (ToggleWidget) w;
00400   RadioGroup * local;
00401 
00402   local = (RadioGroup *) XtMalloc( sizeof(RadioGroup) );
00403   local->widget = w;
00404   tw->toggle.radio_group = local;
00405 
00406   if (group == NULL) {          /* Creating new group. */
00407     group = local;
00408     group->next = NULL;
00409     group->prev = NULL;
00410     return;
00411   }
00412   local->prev = group;          /* Adding to previous group. */
00413   if ((local->next = group->next) != NULL)
00414       local->next->prev = local;
00415   group->next = local;
00416 }
00417 
00418 /*      Function Name: TurnOffRadioSiblings
00419  *      Description: Deactivates all radio siblings.
00420  *      Arguments: widget - a toggle widget.
00421  *      Returns: none.
00422  */
00423 
00424 static void
00425 TurnOffRadioSiblings(w)
00426 Widget w;
00427 {
00428   RadioGroup * group;
00429   ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class;
00430 
00431   if ( (group = GetRadioGroup(w)) == NULL)  /* Punt if there is no group */
00432     return;
00433 
00434   /* Go to the top of the group. */
00435 
00436   for ( ; group->prev != NULL ; group = group->prev );
00437 
00438   while ( group != NULL ) {
00439     ToggleWidget local_tog = (ToggleWidget) group->widget;
00440     if ( local_tog->command.set ) {
00441       class->toggle_class.Unset(group->widget, NULL, NULL, 0);
00442       Notify( group->widget, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
00443     }
00444     group = group->next;
00445   }
00446 }
00447 
00448 /*      Function Name: RemoveFromRadioGroup
00449  *      Description: Removes a toggle from a RadioGroup.
00450  *      Arguments: w - the toggle widget to remove.
00451  *      Returns: none.
00452  */
00453 
00454 static void
00455 RemoveFromRadioGroup(w)
00456 Widget w;
00457 {
00458   RadioGroup * group = GetRadioGroup(w);
00459   if (group != NULL) {
00460     if (group->prev != NULL)
00461       (group->prev)->next = group->next;
00462     if (group->next != NULL)
00463       (group->next)->prev = group->prev;
00464     XtFree((char *) group);
00465   }
00466 }
00467 
00468 /************************************************************
00469  *
00470  * Public Routines
00471  *
00472  ************************************************************/
00473    
00474 /*      Function Name: XawToggleChangeRadioGroup
00475  *      Description: Allows a toggle widget to change radio groups.
00476  *      Arguments: w - The toggle widget to change groups.
00477  *                 radio_group - any widget in the new group.
00478  *      Returns: none.
00479  */
00480 
00481 void
00482 #if NeedFunctionPrototypes
00483 XawToggleChangeRadioGroup(Widget w, Widget radio_group)
00484 #else
00485 XawToggleChangeRadioGroup(w, radio_group)
00486 Widget w, radio_group;
00487 #endif
00488 {
00489   ToggleWidget tw = (ToggleWidget) w;
00490   RadioGroup * group;
00491 
00492   RemoveFromRadioGroup(w);
00493 
00494 /*
00495  * If the toggle that we are about to add is set then we will 
00496  * unset all toggles in the new radio group.
00497  */
00498 
00499   if ( tw->command.set && radio_group != NULL )
00500     XawToggleUnsetCurrent(radio_group);
00501 
00502   if (radio_group != NULL)
00503       if ((group = GetRadioGroup(radio_group)) == NULL)
00504           CreateRadioGroup(w, radio_group);
00505       else AddToRadioGroup(group, w);
00506 }
00507 
00508 /*      Function Name: XawToggleGetCurrent
00509  *      Description: Returns the RadioData associated with the toggle
00510  *                   widget that is currently active in a toggle group.
00511  *      Arguments: w - any toggle widget in the toggle group.
00512  *      Returns: The XtNradioData associated with the toggle widget.
00513  */
00514 
00515 XtPointer
00516 #if NeedFunctionPrototypes
00517 XawToggleGetCurrent(Widget w)
00518 #else
00519 XawToggleGetCurrent(w)
00520 Widget w;
00521 #endif
00522 {
00523   RadioGroup * group;
00524 
00525   if ( (group = GetRadioGroup(w)) == NULL) return(NULL);
00526   for ( ; group->prev != NULL ; group = group->prev);
00527 
00528   while ( group != NULL ) {
00529     ToggleWidget local_tog = (ToggleWidget) group->widget;
00530     if ( local_tog->command.set )
00531       return( local_tog->toggle.radio_data );
00532     group = group->next;
00533   }
00534   return(NULL);
00535 }
00536 
00537 /*      Function Name: XawToggleSetCurrent
00538  *      Description: Sets the Toggle widget associated with the
00539  *                   radio_data specified.
00540  *      Arguments: radio_group - any toggle widget in the toggle group.
00541  *                 radio_data - radio data of the toggle widget to set.
00542  *      Returns: none.
00543  */
00544 
00545 void
00546 #if NeedFunctionPrototypes
00547 XawToggleSetCurrent(Widget radio_group, XtPointer radio_data)
00548 #else
00549 XawToggleSetCurrent(radio_group, radio_data)
00550 Widget radio_group;
00551 XtPointer radio_data;
00552 #endif
00553 {
00554   RadioGroup * group;
00555   ToggleWidget local_tog; 
00556 
00557 /* Special case of no radio group. */
00558 
00559   if ( (group = GetRadioGroup(radio_group)) == NULL) {
00560     local_tog = (ToggleWidget) radio_group;
00561     if ( (local_tog->toggle.radio_data == radio_data) )     
00562       if (!local_tog->command.set) {
00563         ToggleSet((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
00564         Notify((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
00565       }
00566     return;
00567   }
00568 
00569 /*
00570  * find top of radio_roup 
00571  */
00572 
00573   for ( ; group->prev != NULL ; group = group->prev);
00574 
00575 /*
00576  * search for matching radio data.
00577  */
00578 
00579   while ( group != NULL ) {
00580     local_tog = (ToggleWidget) group->widget;
00581     if ( (local_tog->toggle.radio_data == radio_data) ) {
00582       if (!local_tog->command.set) { /* if not already set. */
00583         ToggleSet((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
00584         Notify((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
00585       }
00586       return;                   /* found it, done */
00587     }
00588     group = group->next;
00589   }
00590 }
00591  
00592 /*      Function Name: XawToggleUnsetCurrent
00593  *      Description: Unsets all Toggles in the radio_group specified.
00594  *      Arguments: radio_group - any toggle widget in the toggle group.
00595  *      Returns: none.
00596  */
00597 
00598 void
00599 #if NeedFunctionPrototypes
00600 XawToggleUnsetCurrent(Widget radio_group)
00601 #else
00602 XawToggleUnsetCurrent(radio_group)
00603 Widget radio_group;
00604 #endif
00605 {
00606   ToggleWidgetClass class;
00607   ToggleWidget local_tog = (ToggleWidget) radio_group;
00608 
00609   /* Special Case no radio group. */
00610 
00611   if (local_tog->command.set) {
00612     class = (ToggleWidgetClass) local_tog->core.widget_class;
00613     class->toggle_class.Unset(radio_group, NULL, NULL, 0);
00614     Notify(radio_group, (XEvent *)NULL, (String *)NULL, (Cardinal *)0);
00615   }
00616   if ( GetRadioGroup(radio_group) == NULL) return;
00617   TurnOffRadioSiblings(radio_group);
00618 }
00619 

Generated on Sun Mar 4 15:03:55 2007 for Scilab [trunk] by  doxygen 1.5.1