2 static char Xrcsid
[] = "$XConsortium: Toggle.c,v 1.15 89/12/11 15:22:59 kit Exp $";
6 * Copyright 1989 Massachusetts Institute of Technology
8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that
11 * copyright notice and this permission notice appear in supporting
12 * documentation, and that the name of M.I.T. not be used in advertising or
13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. M.I.T. makes no representations about the
15 * suitability of this software for any purpose. It is provided "as is"
16 * without express or implied warranty.
18 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
20 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 * Toggle.c - Toggle button widget
30 * Author: Chris D. Peterson
32 * kit@expo.lcs.mit.edu
34 * Date: January 12, 1989
40 #include <X11/IntrinsicP.h>
41 #include <X11/StringDefs.h>
43 #include <./Xaw3_1XawInit.h>
44 #include <X11/Xmu/Misc.h>
45 #include <./Xaw3_1ToggleP.h>
47 /****************************************************************
49 * Full class record constant
51 ****************************************************************/
55 /* This is a hack, see the comments in ClassInit(). */
57 extern XtActionList xaw_command_actions_list
;
60 * The order of toggle and notify are important, as the state has
61 * to be set when we call the notify proc.
64 static char defaultTranslations
[] =
65 "<EnterWindow>: highlight(Always) \n\
66 <LeaveWindow>: unhighlight() \n\
67 <Btn1Down>,<Btn1Up>: toggle() notify()";
69 #define offset(field) XtOffset(ToggleWidget, field)
71 static XtResource resources
[] = {
72 {XtNstate
, XtCState
, XtRBoolean
, sizeof(Boolean
),
73 offset(command
.set
), XtRString
, "off"},
74 {XtNradioGroup
, XtCWidget
, XtRWidget
, sizeof(Widget
),
75 offset(toggle
.widget
), XtRWidget
, (caddr_t
) NULL
},
76 {XtNradioData
, XtCRadioData
, XtRPointer
, sizeof(caddr_t
),
77 offset(toggle
.radio_data
), XtRPointer
, (caddr_t
) NULL
},
82 /* Action proceedures retrieved from the command widget */
84 static void Toggle(), Initialize(), Notify(), ToggleSet();
85 static void ToggleDestroy(), ClassInit();
86 static Boolean
SetValues();
88 /* Functions for handling the Radio Group. */
90 static RadioGroup
* GetRadioGroup();
91 static void CreateRadioGroup(), AddToRadioGroup(), TurnOffRadioSiblings();
92 static void RemoveFromRadioGroup();
94 static XtActionsRec actionsList
[] =
101 #define SuperClass ((CommandWidgetClass)&commandClassRec)
103 ToggleClassRec toggleClassRec
= {
105 (WidgetClass
) SuperClass
, /* superclass */
106 "Toggle", /* class_name */
107 sizeof(ToggleRec
), /* size */
108 ClassInit
, /* class_initialize */
109 NULL
, /* class_part_initialize */
110 FALSE
, /* class_inited */
111 Initialize
, /* initialize */
112 NULL
, /* initialize_hook */
113 XtInheritRealize
, /* realize */
114 actionsList
, /* actions */
115 XtNumber(actionsList
), /* num_actions */
116 resources
, /* resources */
117 XtNumber(resources
), /* resource_count */
118 NULLQUARK
, /* xrm_class */
119 FALSE
, /* compress_motion */
120 TRUE
, /* compress_exposure */
121 TRUE
, /* compress_enterleave */
122 FALSE
, /* visible_interest */
124 XtInheritResize
, /* resize */
125 XtInheritExpose
, /* expose */
126 SetValues
, /* set_values */
127 NULL
, /* set_values_hook */
128 XtInheritSetValuesAlmost
, /* set_values_almost */
129 NULL
, /* get_values_hook */
130 NULL
, /* accept_focus */
131 XtVersion
, /* version */
132 NULL
, /* callback_private */
133 defaultTranslations
, /* tm_table */
134 XtInheritQueryGeometry
, /* query_geometry */
135 XtInheritDisplayAccelerator
, /* display_accelerator */
137 }, /* CoreClass fields initialization */
139 XtInheritChangeSensitive
/* change_sensitive */
140 }, /* SimpleClass fields initialization */
142 0 /* field not used */
143 }, /* LabelClass fields initialization */
145 0 /* field not used */
146 }, /* CommmandClass fields initialization */
148 NULL
, /* Set Proceedure. */
149 NULL
, /* Unset Proceedure. */
150 NULL
/* extension. */
151 } /* ToggleClass fields initialization */
154 /* for public consumption */
155 WidgetClass toggleWidgetClass
= (WidgetClass
) &toggleClassRec
;
157 /****************************************************************
161 ****************************************************************/
166 XtActionList actions
;
168 ToggleWidgetClass
class = (ToggleWidgetClass
) toggleWidgetClass
;
170 XawInitializeWidgetSet();
172 /* actions = SuperClass->core_class.actions; */
174 /* The actions table should really be retrieved from the toggle widget's
175 * Superclass, but this information is munged by the R3 intrinsics so the
176 * I have hacked the Athena command widget to export its action table
177 * as a global variable.
179 * Chris D. Peterson 12/28/88.
182 actions
= xaw_command_actions_list
;
185 * Find the set and unset actions in the command widget's action table.
188 for (i
= 0 ; i
< SuperClass
->core_class
.num_actions
; i
++) {
189 if (streq(actions
[i
].string
, "set"))
190 class->toggle_class
.Set
= actions
[i
].proc
;
191 if (streq(actions
[i
].string
, "unset"))
192 class->toggle_class
.Unset
= actions
[i
].proc
;
194 if ( (class->toggle_class
.Set
!= NULL
) &&
195 (class->toggle_class
.Unset
!= NULL
) ) return;
198 /* We should never get here. */
199 if (class->toggle_class
.Set
== NULL
)
201 "Toggle could not find action Proceedure Set() in the Command Widget.");
202 if (class->toggle_class
.Unset
== NULL
)
204 "Toggle could not find action Proceedure Unset() in the Command Widget.");
205 XtError("Aborting, due to errors in Toggle widget.");
208 static void Initialize(request
, new)
211 ToggleWidget tw
= (ToggleWidget
) new;
212 ToggleWidget tw_req
= (ToggleWidget
) request
;
214 tw
->toggle
.radio_group
= NULL
;
216 if (tw
->toggle
.radio_data
== NULL
)
217 tw
->toggle
.radio_data
= (caddr_t
) new->core
.name
;
219 if (tw
->toggle
.widget
!= NULL
) {
220 if ( GetRadioGroup(tw
->toggle
.widget
) == NULL
)
221 CreateRadioGroup(new, tw
->toggle
.widget
);
223 AddToRadioGroup( GetRadioGroup(tw
->toggle
.widget
), new);
225 XtAddCallback(new, XtNdestroyCallback
, ToggleDestroy
, NULL
);
228 * Command widget assumes that the widget is unset, so we only
229 * have to handle the case where it needs to be set.
231 * If this widget is in a radio group then it may cause another
232 * widget to be unset, thus calling the notify proceedure.
234 * I want to set the toggle if the user set the state to "On" in
235 * the resource group, reguardless of what my ancestors did.
238 if (tw_req
->command
.set
)
239 ToggleSet(new, NULL
, NULL
, 0);
242 /************************************************************
246 ************************************************************/
250 ToggleSet(w
,event
,params
,num_params
)
253 String
*params
; /* unused */
254 Cardinal
*num_params
; /* unused */
256 ToggleWidgetClass
class = (ToggleWidgetClass
) w
->core
.widget_class
;
258 TurnOffRadioSiblings(w
);
259 class->toggle_class
.Set(w
, event
, NULL
, 0);
264 Toggle(w
,event
,params
,num_params
)
267 String
*params
; /* unused */
268 Cardinal
*num_params
; /* unused */
270 ToggleWidget tw
= (ToggleWidget
)w
;
271 ToggleWidgetClass
class = (ToggleWidgetClass
) w
->core
.widget_class
;
274 class->toggle_class
.Unset(w
, event
, NULL
, 0);
276 ToggleSet(w
, event
, params
, num_params
);
280 static void Notify(w
,event
,params
,num_params
)
283 String
*params
; /* unused */
284 Cardinal
*num_params
; /* unused */
286 ToggleWidget tw
= (ToggleWidget
) w
;
287 XtCallCallbacks(w
, XtNcallback
, tw
->command
.set
);
290 /************************************************************
292 * Set specified arguments into widget
294 ***********************************************************/
298 SetValues (current
, request
, new)
299 Widget current
, request
, new;
301 ToggleWidget oldtw
= (ToggleWidget
) current
;
302 ToggleWidget tw
= (ToggleWidget
) new;
304 if (oldtw
->toggle
.widget
!= tw
->toggle
.widget
)
305 XawToggleChangeRadioGroup(new, tw
->toggle
.widget
);
307 if (oldtw
->command
.set
!= tw
->command
.set
) {
308 tw
->command
.set
= oldtw
->command
.set
;
309 Toggle(new, NULL
, NULL
, 0); /* Does a redisplay. */
314 /* Function Name: ToggleDestroy
315 * Description: Destroy Callback for toggle widget.
316 * Arguments: w - the toggle widget that is being destroyed.
317 * junk, grabage - not used.
323 ToggleDestroy(w
, junk
, garbage
)
325 caddr_t junk
, garbage
;
327 RemoveFromRadioGroup(w
);
330 /************************************************************
332 * Below are all the private proceedures that handle
333 * radio toggle buttons.
335 ************************************************************/
337 /* Function Name: GetRadioGroup
338 * Description: Gets the radio group associated with a give toggle
340 * Arguments: w - the toggle widget who's radio group we are getting.
341 * Returns: the radio group associated with this toggle group.
348 ToggleWidget tw
= (ToggleWidget
) w
;
350 if (tw
== NULL
) return(NULL
);
351 return( tw
->toggle
.radio_group
);
354 /* Function Name: CreateRadioGroup
355 * Description: Creates a radio group. give two widgets.
356 * Arguments: w1, w2 - the toggle widgets to add to the radio group.
359 * NOTE: A pointer to the group is added to each widget's radio_group
364 CreateRadioGroup(w1
, w2
)
367 char error_buf
[BUFSIZ
];
368 ToggleWidget tw1
= (ToggleWidget
) w1
;
369 ToggleWidget tw2
= (ToggleWidget
) w2
;
371 if ( (tw1
->toggle
.radio_group
!= NULL
) || (tw2
->toggle
.radio_group
!= NULL
) ) {
372 sprintf(error_buf
, "%s %s", "Toggle Widget Error - Attempting",
373 "to create a new toggle group, when one already exists.");
374 XtWarning(error_buf
);
377 AddToRadioGroup( NULL
, w1
);
378 AddToRadioGroup( GetRadioGroup(w1
), w2
);
381 /* Function Name: AddToRadioGroup
382 * Description: Adds a toggle to the radio group.
383 * Arguments: group - any element of the radio group the we are adding to.
384 * w - the new toggle widget to add to the group.
389 AddToRadioGroup(group
, w
)
393 ToggleWidget tw
= (ToggleWidget
) w
;
396 local
= (RadioGroup
*) XtMalloc( sizeof(RadioGroup
) );
398 tw
->toggle
.radio_group
= local
;
400 if (group
== NULL
) { /* Creating new group. */
406 local
->prev
= group
; /* Adding to previous group. */
407 if ((local
->next
= group
->next
) != NULL
)
408 local
->next
->prev
= local
;
412 /* Function Name: TurnOffRadioSiblings
413 * Description: Deactivates all radio siblings.
414 * Arguments: widget - a toggle widget.
419 TurnOffRadioSiblings(w
)
423 ToggleWidgetClass
class = (ToggleWidgetClass
) w
->core
.widget_class
;
425 if ( (group
= GetRadioGroup(w
)) == NULL
) /* Punt if there is no group */
428 /* Go to the top of the group. */
430 for ( ; group
->prev
!= NULL
; group
= group
->prev
);
432 while ( group
!= NULL
) {
433 ToggleWidget local_tog
= (ToggleWidget
) group
->widget
;
434 if ( local_tog
->command
.set
) {
435 class->toggle_class
.Unset(group
->widget
, NULL
, NULL
, 0);
436 Notify( group
->widget
, NULL
, NULL
, 0);
442 /* Function Name: RemoveFromRadioGroup
443 * Description: Removes a toggle from a RadioGroup.
444 * Arguments: w - the toggle widget to remove.
449 RemoveFromRadioGroup(w
)
452 RadioGroup
* group
= GetRadioGroup(w
);
454 if (group
->prev
!= NULL
)
455 (group
->prev
)->next
= group
->next
;
456 if (group
->next
!= NULL
)
457 (group
->next
)->prev
= group
->prev
;
462 /************************************************************
466 ************************************************************/
468 /* Function Name: XawToggleChangeRadioGroup
469 * Description: Allows a toggle widget to change radio groups.
470 * Arguments: w - The toggle widget to change groups.
471 * radio_group - any widget in the new group.
476 XawToggleChangeRadioGroup(w
, radio_group
)
477 Widget w
, radio_group
;
479 ToggleWidget tw
= (ToggleWidget
) w
;
481 RemoveFromRadioGroup(w
);
484 * If the toggle that we are about to add is set then we will
485 * unset all toggles in the new radio group.
488 if ( tw
->command
.set
&& radio_group
!= NULL
)
489 XawToggleUnsetCurrent(radio_group
);
490 AddToRadioGroup( GetRadioGroup(radio_group
), w
);
493 /* Function Name: XawToggleGetCurrent
494 * Description: Returns the RadioData associated with the toggle
495 * widget that is currently active in a toggle group.
496 * Arguments: w - any toggle widget in the toggle group.
497 * Returns: The XtNradioData associated with the toggle widget.
501 XawToggleGetCurrent(w
)
506 if ( (group
= GetRadioGroup(w
)) == NULL
) return(NULL
);
507 for ( ; group
->prev
!= NULL
; group
= group
->prev
);
509 while ( group
!= NULL
) {
510 ToggleWidget local_tog
= (ToggleWidget
) group
->widget
;
511 if ( local_tog
->command
.set
)
512 return( local_tog
->toggle
.radio_data
);
518 /* Function Name: XawToggleSetCurrent
519 * Description: Sets the Toggle widget associated with the
520 * radio_data specified.
521 * Arguments: radio_group - any toggle widget in the toggle group.
522 * radio_data - radio data of the toggle widget to set.
527 XawToggleSetCurrent(radio_group
, radio_data
)
532 ToggleWidget local_tog
;
534 /* Special case case of no radio group. */
536 if ( (group
= GetRadioGroup(radio_group
)) == NULL
) {
537 local_tog
= (ToggleWidget
) radio_group
;
538 if ( (local_tog
->toggle
.radio_data
== radio_data
) )
539 if (!local_tog
->command
.set
) {
540 ToggleSet((Widget
) local_tog
, NULL
, NULL
, 0);
541 Notify((Widget
) local_tog
, NULL
, NULL
, 0);
547 * find top of radio_roup
550 for ( ; group
->prev
!= NULL
; group
= group
->prev
);
553 * search for matching radio data.
556 while ( group
!= NULL
) {
557 local_tog
= (ToggleWidget
) group
->widget
;
558 if ( (local_tog
->toggle
.radio_data
== radio_data
) ) {
559 if (!local_tog
->command
.set
) { /* if not already set. */
560 ToggleSet((Widget
) local_tog
, NULL
, NULL
, 0);
561 Notify((Widget
) local_tog
, NULL
, NULL
, 0);
563 return; /* found it, done */
569 /* Function Name: XawToggleUnsetCurrent
570 * Description: Unsets all Toggles in the radio_group specified.
571 * Arguments: radio_group - any toggle widget in the toggle group.
576 XawToggleUnsetCurrent(radio_group
)
579 ToggleWidgetClass
class;
580 ToggleWidget local_tog
= (ToggleWidget
) radio_group
;
582 /* Special Case no radio group. */
584 if (local_tog
->command
.set
) {
585 class = (ToggleWidgetClass
) local_tog
->core
.widget_class
;
586 class->toggle_class
.Unset(radio_group
, NULL
, NULL
, 0);
587 Notify(radio_group
, NULL
, NULL
, 0);
589 if ( GetRadioGroup(radio_group
) == NULL
) return;
590 TurnOffRadioSiblings(radio_group
);