1 /* $XConsortium: Toggle.c,v 1.28 94/04/17 20:13:17 kaleb Exp $ */
5 Copyright (c) 1989, 1994 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Except as contained in this notice, the name of the X Consortium shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the X Consortium.
31 * Toggle.c - Toggle button widget
33 * Author: Chris D. Peterson
35 * kit@expo.lcs.mit.edu
37 * Date: January 12, 1989
43 #include <X11/IntrinsicP.h>
44 #include <X11/StringDefs.h>
45 #include <X11/Xaw/XawInit.h>
46 #include <X11/Xmu/Converters.h>
47 #include <X11/Xmu/Misc.h>
48 #include <X11/Xaw/ToggleP.h>
50 /****************************************************************
52 * Full class record constant
54 ****************************************************************/
59 * The order of toggle and notify are important, as the state has
60 * to be set when we call the notify proc.
63 static char defaultTranslations
[] =
64 "<EnterWindow>: highlight(Always) \n\
65 <LeaveWindow>: unhighlight() \n\
66 <Btn1Down>,<Btn1Up>: toggle() notify()";
68 #define offset(field) XtOffsetOf(ToggleRec, field)
70 static XtResource resources
[] = {
71 {XtNstate
, XtCState
, XtRBoolean
, sizeof(Boolean
),
72 offset(command
.set
), XtRString
, "off"},
73 {XtNradioGroup
, XtCWidget
, XtRWidget
, sizeof(Widget
),
74 offset(toggle
.widget
), XtRWidget
, (XtPointer
) NULL
},
75 {XtNradioData
, XtCRadioData
, XtRPointer
, sizeof(XtPointer
),
76 offset(toggle
.radio_data
), XtRPointer
, (XtPointer
) NULL
},
82 static void Toggle(), Initialize(), Notify(), ToggleSet();
83 static void ToggleDestroy(), ClassInit();
84 static Boolean
SetValues();
86 /* Functions for handling the Radio Group. */
88 static RadioGroup
* GetRadioGroup();
89 static void CreateRadioGroup(), AddToRadioGroup(), TurnOffRadioSiblings();
90 static void RemoveFromRadioGroup();
92 static XtActionsRec actionsList
[] =
99 #define SuperClass ((CommandWidgetClass)&commandClassRec)
101 ToggleClassRec toggleClassRec
= {
103 (WidgetClass
) SuperClass
, /* superclass */
104 "Toggle", /* class_name */
105 sizeof(ToggleRec
), /* size */
106 ClassInit
, /* class_initialize */
107 NULL
, /* class_part_initialize */
108 FALSE
, /* class_inited */
109 Initialize
, /* initialize */
110 NULL
, /* initialize_hook */
111 XtInheritRealize
, /* realize */
112 actionsList
, /* actions */
113 XtNumber(actionsList
), /* num_actions */
114 resources
, /* resources */
115 XtNumber(resources
), /* resource_count */
116 NULLQUARK
, /* xrm_class */
117 FALSE
, /* compress_motion */
118 TRUE
, /* compress_exposure */
119 TRUE
, /* compress_enterleave */
120 FALSE
, /* visible_interest */
122 XtInheritResize
, /* resize */
123 XtInheritExpose
, /* expose */
124 SetValues
, /* set_values */
125 NULL
, /* set_values_hook */
126 XtInheritSetValuesAlmost
, /* set_values_almost */
127 NULL
, /* get_values_hook */
128 NULL
, /* accept_focus */
129 XtVersion
, /* version */
130 NULL
, /* callback_private */
131 defaultTranslations
, /* tm_table */
132 XtInheritQueryGeometry
, /* query_geometry */
133 XtInheritDisplayAccelerator
, /* display_accelerator */
135 }, /* CoreClass fields initialization */
137 XtInheritChangeSensitive
/* change_sensitive */
138 }, /* SimpleClass fields initialization */
140 0 /* field not used */
141 }, /* LabelClass fields initialization */
143 0 /* field not used */
144 }, /* CommandClass fields initialization */
146 NULL
, /* Set Procedure. */
147 NULL
, /* Unset Procedure. */
148 NULL
/* extension. */
149 } /* ToggleClass fields initialization */
152 /* for public consumption */
153 WidgetClass toggleWidgetClass
= (WidgetClass
) &toggleClassRec
;
155 /****************************************************************
159 ****************************************************************/
164 XtActionList actions
;
165 Cardinal num_actions
;
167 ToggleWidgetClass
class = (ToggleWidgetClass
) toggleWidgetClass
;
168 static XtConvertArgRec parentCvtArgs
[] = {
169 {XtBaseOffset
, (XtPointer
)XtOffsetOf(WidgetRec
, core
.parent
),
173 XawInitializeWidgetSet();
174 XtSetTypeConverter(XtRString
, XtRWidget
, XmuNewCvtStringToWidget
,
175 parentCvtArgs
, XtNumber(parentCvtArgs
), XtCacheNone
,
178 * Find the set and unset actions in the command widget's action table.
181 XtGetActionList(commandWidgetClass
, &actions
, &num_actions
);
183 for (i
= 0 ; i
< num_actions
; i
++) {
184 if (streq(actions
[i
].string
, "set"))
185 class->toggle_class
.Set
= actions
[i
].proc
;
186 if (streq(actions
[i
].string
, "unset"))
187 class->toggle_class
.Unset
= actions
[i
].proc
;
189 if ( (class->toggle_class
.Set
!= NULL
) &&
190 (class->toggle_class
.Unset
!= NULL
) ) {
191 XtFree((char *) actions
);
196 /* We should never get here. */
197 XtError("Aborting, due to errors resolving bindings in the Toggle widget.");
201 static void Initialize(request
, new, args
, num_args
)
206 ToggleWidget tw
= (ToggleWidget
) new;
207 ToggleWidget tw_req
= (ToggleWidget
) request
;
209 tw
->toggle
.radio_group
= NULL
;
211 if (tw
->toggle
.radio_data
== NULL
)
212 tw
->toggle
.radio_data
= (XtPointer
) new->core
.name
;
214 if (tw
->toggle
.widget
!= NULL
) {
215 if ( GetRadioGroup(tw
->toggle
.widget
) == NULL
)
216 CreateRadioGroup(new, tw
->toggle
.widget
);
218 AddToRadioGroup( GetRadioGroup(tw
->toggle
.widget
), new);
220 XtAddCallback(new, XtNdestroyCallback
, ToggleDestroy
, (XtPointer
)NULL
);
223 * Command widget assumes that the widget is unset, so we only
224 * have to handle the case where it needs to be set.
226 * If this widget is in a radio group then it may cause another
227 * widget to be unset, thus calling the notify proceedure.
229 * I want to set the toggle if the user set the state to "On" in
230 * the resource group, reguardless of what my ancestors did.
233 if (tw_req
->command
.set
)
234 ToggleSet(new, (XEvent
*)NULL
, (String
*)NULL
, (Cardinal
*)0);
237 /************************************************************
241 ************************************************************/
245 ToggleSet(w
,event
,params
,num_params
)
248 String
*params
; /* unused */
249 Cardinal
*num_params
; /* unused */
251 ToggleWidgetClass
class = (ToggleWidgetClass
) w
->core
.widget_class
;
253 TurnOffRadioSiblings(w
);
254 class->toggle_class
.Set(w
, event
, NULL
, 0);
259 Toggle(w
,event
,params
,num_params
)
262 String
*params
; /* unused */
263 Cardinal
*num_params
; /* unused */
265 ToggleWidget tw
= (ToggleWidget
)w
;
266 ToggleWidgetClass
class = (ToggleWidgetClass
) w
->core
.widget_class
;
269 class->toggle_class
.Unset(w
, event
, NULL
, 0);
271 ToggleSet(w
, event
, params
, num_params
);
275 static void Notify(w
,event
,params
,num_params
)
278 String
*params
; /* unused */
279 Cardinal
*num_params
; /* unused */
281 ToggleWidget tw
= (ToggleWidget
) w
;
282 long antilint
= tw
->command
.set
;
284 XtCallCallbacks( w
, XtNcallback
, (XtPointer
) antilint
);
287 /************************************************************
289 * Set specified arguments into widget
291 ***********************************************************/
295 SetValues (current
, request
, new, args
, num_args
)
296 Widget current
, request
, new;
300 ToggleWidget oldtw
= (ToggleWidget
) current
;
301 ToggleWidget tw
= (ToggleWidget
) new;
302 ToggleWidget rtw
= (ToggleWidget
) request
;
304 if (oldtw
->toggle
.widget
!= tw
->toggle
.widget
)
305 XawToggleChangeRadioGroup(new, tw
->toggle
.widget
);
307 if (!tw
->core
.sensitive
&& oldtw
->core
.sensitive
&& rtw
->command
.set
)
308 tw
->command
.set
= True
;
310 if (oldtw
->command
.set
!= tw
->command
.set
) {
311 tw
->command
.set
= oldtw
->command
.set
;
312 Toggle(new, (XEvent
*)NULL
, (String
*)NULL
, (Cardinal
*)0);
317 /* Function Name: ToggleDestroy
318 * Description: Destroy Callback for toggle widget.
319 * Arguments: w - the toggle widget that is being destroyed.
320 * junk, grabage - not used.
326 ToggleDestroy(w
, junk
, garbage
)
328 XtPointer junk
, garbage
;
330 RemoveFromRadioGroup(w
);
333 /************************************************************
335 * Below are all the private procedures that handle
336 * radio toggle buttons.
338 ************************************************************/
340 /* Function Name: GetRadioGroup
341 * Description: Gets the radio group associated with a give toggle
343 * Arguments: w - the toggle widget who's radio group we are getting.
344 * Returns: the radio group associated with this toggle group.
351 ToggleWidget tw
= (ToggleWidget
) w
;
353 if (tw
== NULL
) return(NULL
);
354 return( tw
->toggle
.radio_group
);
357 /* Function Name: CreateRadioGroup
358 * Description: Creates a radio group. give two widgets.
359 * Arguments: w1, w2 - the toggle widgets to add to the radio group.
362 * NOTE: A pointer to the group is added to each widget's radio_group
367 CreateRadioGroup(w1
, w2
)
370 char error_buf
[BUFSIZ
];
371 ToggleWidget tw1
= (ToggleWidget
) w1
;
372 ToggleWidget tw2
= (ToggleWidget
) w2
;
374 if ( (tw1
->toggle
.radio_group
!= NULL
) || (tw2
->toggle
.radio_group
!= NULL
) ) {
375 (void) sprintf(error_buf
, "%s %s", "Toggle Widget Error - Attempting",
376 "to create a new toggle group, when one already exists.");
377 XtWarning(error_buf
);
380 AddToRadioGroup( (RadioGroup
*)NULL
, w1
);
381 AddToRadioGroup( GetRadioGroup(w1
), w2
);
384 /* Function Name: AddToRadioGroup
385 * Description: Adds a toggle to the radio group.
386 * Arguments: group - any element of the radio group the we are adding to.
387 * w - the new toggle widget to add to the group.
392 AddToRadioGroup(group
, w
)
396 ToggleWidget tw
= (ToggleWidget
) w
;
399 local
= (RadioGroup
*) XtMalloc( sizeof(RadioGroup
) );
401 tw
->toggle
.radio_group
= local
;
403 if (group
== NULL
) { /* Creating new group. */
409 local
->prev
= group
; /* Adding to previous group. */
410 if ((local
->next
= group
->next
) != NULL
)
411 local
->next
->prev
= local
;
415 /* Function Name: TurnOffRadioSiblings
416 * Description: Deactivates all radio siblings.
417 * Arguments: widget - a toggle widget.
422 TurnOffRadioSiblings(w
)
426 ToggleWidgetClass
class = (ToggleWidgetClass
) w
->core
.widget_class
;
428 if ( (group
= GetRadioGroup(w
)) == NULL
) /* Punt if there is no group */
431 /* Go to the top of the group. */
433 for ( ; group
->prev
!= NULL
; group
= group
->prev
);
435 while ( group
!= NULL
) {
436 ToggleWidget local_tog
= (ToggleWidget
) group
->widget
;
437 if ( local_tog
->command
.set
) {
438 class->toggle_class
.Unset(group
->widget
, NULL
, NULL
, 0);
439 Notify( group
->widget
, (XEvent
*)NULL
, (String
*)NULL
, (Cardinal
*)0);
445 /* Function Name: RemoveFromRadioGroup
446 * Description: Removes a toggle from a RadioGroup.
447 * Arguments: w - the toggle widget to remove.
452 RemoveFromRadioGroup(w
)
455 RadioGroup
* group
= GetRadioGroup(w
);
457 if (group
->prev
!= NULL
)
458 (group
->prev
)->next
= group
->next
;
459 if (group
->next
!= NULL
)
460 (group
->next
)->prev
= group
->prev
;
461 XtFree((char *) group
);
465 /************************************************************
469 ************************************************************/
471 /* Function Name: XawToggleChangeRadioGroup
472 * Description: Allows a toggle widget to change radio groups.
473 * Arguments: w - The toggle widget to change groups.
474 * radio_group - any widget in the new group.
479 #if NeedFunctionPrototypes
480 XawToggleChangeRadioGroup(Widget w
, Widget radio_group
)
482 XawToggleChangeRadioGroup(w
, radio_group
)
483 Widget w
, radio_group
;
486 ToggleWidget tw
= (ToggleWidget
) w
;
489 RemoveFromRadioGroup(w
);
492 * If the toggle that we are about to add is set then we will
493 * unset all toggles in the new radio group.
496 if ( tw
->command
.set
&& radio_group
!= NULL
)
497 XawToggleUnsetCurrent(radio_group
);
499 if (radio_group
!= NULL
)
500 if ((group
= GetRadioGroup(radio_group
)) == NULL
)
501 CreateRadioGroup(w
, radio_group
);
502 else AddToRadioGroup(group
, w
);
505 /* Function Name: XawToggleGetCurrent
506 * Description: Returns the RadioData associated with the toggle
507 * widget that is currently active in a toggle group.
508 * Arguments: w - any toggle widget in the toggle group.
509 * Returns: The XtNradioData associated with the toggle widget.
513 #if NeedFunctionPrototypes
514 XawToggleGetCurrent(Widget w
)
516 XawToggleGetCurrent(w
)
522 if ( (group
= GetRadioGroup(w
)) == NULL
) return(NULL
);
523 for ( ; group
->prev
!= NULL
; group
= group
->prev
);
525 while ( group
!= NULL
) {
526 ToggleWidget local_tog
= (ToggleWidget
) group
->widget
;
527 if ( local_tog
->command
.set
)
528 return( local_tog
->toggle
.radio_data
);
534 /* Function Name: XawToggleSetCurrent
535 * Description: Sets the Toggle widget associated with the
536 * radio_data specified.
537 * Arguments: radio_group - any toggle widget in the toggle group.
538 * radio_data - radio data of the toggle widget to set.
543 #if NeedFunctionPrototypes
544 XawToggleSetCurrent(Widget radio_group
, XtPointer radio_data
)
546 XawToggleSetCurrent(radio_group
, radio_data
)
548 XtPointer radio_data
;
552 ToggleWidget local_tog
;
554 /* Special case of no radio group. */
556 if ( (group
= GetRadioGroup(radio_group
)) == NULL
) {
557 local_tog
= (ToggleWidget
) radio_group
;
558 if ( (local_tog
->toggle
.radio_data
== radio_data
) )
559 if (!local_tog
->command
.set
) {
560 ToggleSet((Widget
) local_tog
, (XEvent
*)NULL
, (String
*)NULL
, (Cardinal
*)0);
561 Notify((Widget
) local_tog
, (XEvent
*)NULL
, (String
*)NULL
, (Cardinal
*)0);
567 * find top of radio_roup
570 for ( ; group
->prev
!= NULL
; group
= group
->prev
);
573 * search for matching radio data.
576 while ( group
!= NULL
) {
577 local_tog
= (ToggleWidget
) group
->widget
;
578 if ( (local_tog
->toggle
.radio_data
== radio_data
) ) {
579 if (!local_tog
->command
.set
) { /* if not already set. */
580 ToggleSet((Widget
) local_tog
, (XEvent
*)NULL
, (String
*)NULL
, (Cardinal
*)0);
581 Notify((Widget
) local_tog
, (XEvent
*)NULL
, (String
*)NULL
, (Cardinal
*)0);
583 return; /* found it, done */
589 /* Function Name: XawToggleUnsetCurrent
590 * Description: Unsets all Toggles in the radio_group specified.
591 * Arguments: radio_group - any toggle widget in the toggle group.
596 #if NeedFunctionPrototypes
597 XawToggleUnsetCurrent(Widget radio_group
)
599 XawToggleUnsetCurrent(radio_group
)
603 ToggleWidgetClass
class;
604 ToggleWidget local_tog
= (ToggleWidget
) radio_group
;
606 /* Special Case no radio group. */
608 if (local_tog
->command
.set
) {
609 class = (ToggleWidgetClass
) local_tog
->core
.widget_class
;
610 class->toggle_class
.Unset(radio_group
, NULL
, NULL
, 0);
611 Notify(radio_group
, (XEvent
*)NULL
, (String
*)NULL
, (Cardinal
*)0);
613 if ( GetRadioGroup(radio_group
) == NULL
) return;
614 TurnOffRadioSiblings(radio_group
);