1 /***************************************************************************/
2 /* 	This code is part of X-toolkit widget library called Nws 	   */
3 /*	Copyright (c) 1997,1998,1999 Ondrejicka Stefan			   */
4 /*	(ondrej@idata.sk)						   */
5 /*	Distributed under GPL 2 or later				   */
6 /***************************************************************************/
7 
8 #include <X11/IntrinsicP.h>
9 #include <X11/StringDefs.h>
10 #include <X11/Xlib.h>
11 
12 #include "MwSButtonP.h"
13 #include "MwNws.h"
14 
15 #define offset(field) XtOffsetOf(MwSButtonRec,sButton.field)
16 
17 static XtResource resources [] = {
18 	{
19 	 XtNcallback ,
20 	 XtCCallback ,
21 	 XtRCallback ,
22 	 sizeof(XtCallbackList) ,
23 	 offset(activate) ,
24 	 XtRCallback ,
25 	 (XtPointer) NULL
26 	},
27  	{
28 	 XtNswitch ,
29 	 XtCSwitch ,
30 	 XtRCallback ,
31 	 sizeof(XtCallbackList) ,
32 	 offset(switchcb) ,
33 	 XtRCallback ,
34 	 (XtPointer) NULL
35 	},
36         {
37          XtNbuttonMode,
38          XtCButtonMode,
39          XtRButtonMode,
40          sizeof(int),
41          offset(mode),
42          XtRImmediate,
43          (XtPointer) XtCnormalMode,
44         },
45 	{
46 	 XtNinitDelay,
47 	 XtCInitDelay,
48 	 XtRCardinal,
49 	 sizeof(Cardinal),
50 	 offset(init_delay),
51 	 XtRImmediate,
52 	(XtPointer)500,
53 	},
54 	{
55 	 XtNrepeatDelay,
56 	 XtCRepeatDelay,
57 	 XtRCardinal,
58 	 sizeof(Cardinal),
59 	 offset(repeat_delay),
60 	 XtRImmediate,
61 	 (XtPointer)100,
62 	},
63 	{
64 	 XtNhighlight_on_enter ,
65 	 XtCHighlight_on_enter ,
66 	 XtRBoolean ,
67 	 sizeof(Boolean) ,
68 	 XtOffsetOf(MwSButtonRec,base.highlight_on_enter) ,
69 	 XtRImmediate ,
70 	 (XtPointer) True
71 	},
72 	{
73 	 XtNbox_type ,
74 	 XtCBox_type ,
75 	 XtRBox_type ,
76 	 sizeof(int) ,
77 	 XtOffsetOf(MwSButtonRec,base.box_type) ,
78 	 XtRImmediate ,
79 	 (XtPointer) XtCup_box
80 	},
81 	{
82 	 XtNon ,
83 	 XtCOn ,
84 	 XtRBoolean ,
85 	 sizeof(Boolean) ,
86 	 offset(on) ,
87 	 XtRImmediate ,
88 	 (XtPointer) False
89 	},
90 };
91 
92 #undef offset
93 
94 static void ClassInitialize(void);
95 static void Initialize (Widget, Widget, ArgList, Cardinal *);
96 
97 static void deactivate_t (Widget, XEvent *, String *, Cardinal *);
98 static void activate_t (Widget, XEvent *, String *, Cardinal *);
99 static void KBactivate (Widget, XEvent *, String *, Cardinal *);
100 static void timerCB (XtPointer, XtIntervalId *);
101 static void Enter_Leave (Widget, XEvent *, String *, Cardinal *);
102 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
103 
104 static XtActionsRec action [] = {
105         {"activate",activate_t},
106         {"deactivate",deactivate_t},
107         {"KBactivate",KBactivate},
108 	{"enter_leave",Enter_Leave},
109 };
110 
111 static char trans_tab [] =
112         "\
113 	 <FocusIn>: focusIn()\n\
114 	 <FocusOut>: focusOut()\n\
115 	 ~Shift<Key>Tab: traverseForward()\n\
116 	 Shift<Key>Tab: traverseBackward()\n\
117 	 <Key>Return: KBactivate()\n\
118 	 <Key>space: KBactivate()\n\
119          <Btn1Down>: hide_help() activate() \n\
120 	 <Btn1Up>: deactivate() \n\
121 	 <Enter>: enter_leave() highlight() show_help() \n\
122 	 <Leave>: enter_leave() unhighlight() hide_help() \n\
123 	 <BtnDown>: hide_help() \n\
124 	 <KeyDown>: hide_help() \n\
125 	";
126 
127 MwSButtonClassRec mwSButtonClassRec = {
128 /* core */
129    {
130     /* superclass            */ (WidgetClass) &mwBaseClassRec,
131     /* class_name            */ "MwSButton",
132     /* widget_size           */ sizeof(MwSButtonRec),
133     /* class_initialize      */ ClassInitialize,
134     /* class_part_initialize */ NULL,
135     /* class_inited          */ FALSE,
136     /* initialize            */ (XtInitProc) Initialize,
137     /* initialize_hook       */ NULL,
138     /* realize               */ XtInheritRealize,
139     /* actions               */ action,
140     /* num_actions           */ XtNumber(action),
141     /* resources             */ resources,
142     /* num_resources         */ XtNumber(resources),
143     /* xrm_class             */ NULLQUARK,
144     /* compress_motion       */ TRUE,
145     /* compress_exposure     */ TRUE,
146     /* compress_enterleave   */ TRUE,
147     /* visible_interest      */ FALSE,
148     /* destroy               */ NULL,
149     /* resize                */ XtInheritResize,
150     /* expose                */ XtInheritExpose,
151     /* set_values            */ SetValues,
152     /* set_values_hook       */ NULL,
153     /* set_values_almost     */ XtInheritSetValuesAlmost,
154     /* get_values_hook       */ NULL,
155     /* accept_focus          */ XtInheritAcceptFocus,
156     /* version               */ XtVersion,
157     /* callback_private      */ NULL,
158     /* tm_table              */ trans_tab,
159     /* query_geometry        */ XtInheritQueryGeometry,
160     /* display_accelerator   */ XtInheritDisplayAccelerator,
161     /* extension             */ NULL
162    },
163 /* base */
164    {
165     /* get_internal_dimension  */ XtInheritGetInternalDimension,
166     /* set_internal_dimension  */ XtInheritSetInternalDimension,
167     /* highlight	       */ XtInheritHighlight,
168     /* unhighlight	       */ XtInheritUnhighlight,
169     /* highlightBorder	       */ XtInheritHighlightBorder,
170     /* unhighlightBorder       */ XtInheritUnhighlightBorder,
171    },
172 /* sButton */
173    {
174     /* empty                 */ 0
175    }
176 };
177 
178 WidgetClass mwSButtonWidgetClass = (WidgetClass) & mwSButtonClassRec;
179 
ClassInitialize(void)180 static void ClassInitialize(void)
181 {
182 	_InitializeWidgetSet();
183 
184 	XtSetTypeConverter(XtRString, XtRButtonMode, cvtStringToButtonMode,
185 		NULL, 0, XtCacheNone, NULL);
186 }
187 
Initialize(Widget req_widget,Widget new_widget,ArgList args,Cardinal * num_args)188 static void Initialize(Widget req_widget, Widget new_widget,
189 		ArgList args, Cardinal *num_args)
190 {
191 	MwSButtonWidget nw = (MwSButtonWidget) new_widget;
192 
193 	if (nw->sButton.mode == XtCtoggleMode)
194 	{
195 		if (nw->sButton.on)
196 		{
197 			nw->sButton.pressed = True;
198 			nw->base.box_type =  XtCdown_box;
199 		}
200 		else
201 		{
202 			nw->sButton.pressed = False;
203 			nw->base.box_type =  XtCup_box;
204 		}
205 	}
206 	else nw->sButton.pressed = False;
207 }
208 
SetValues(Widget current,Widget request,Widget new_widget,ArgList args,Cardinal * num_args)209 static Boolean SetValues(Widget current, Widget request, Widget new_widget,
210 		ArgList args, Cardinal *num_args)
211 {
212 	MwSButtonWidget nw = (MwSButtonWidget) new_widget;
213 	MwSButtonWidget cw = (MwSButtonWidget) current;
214 	Boolean redraw = False;
215 
216 	if (nw->sButton.mode == XtCtoggleMode && (cw->sButton.on != nw->sButton.on ||
217 	    cw->sButton.mode != nw->sButton.mode))
218 	{
219 		if (nw->sButton.on)
220 			nw->base.box_type = XtCdown_box;
221 		else
222 			nw->base.box_type = XtCup_box;
223 
224 		redraw = True;
225 	}
226 
227 	return redraw;
228 }
229 
KBactivate(Widget sw,XEvent * event,String * params,Cardinal * num_params)230 static void KBactivate(Widget sw, XEvent *event,
231 		String *params, Cardinal *num_params)
232 {
233 	MwSButtonWidget w = (MwSButtonWidget)sw;
234 	if (w->sButton.mode == XtCtoggleMode)
235 	{
236  		w->sButton.on = !w->sButton.on;
237 
238 		if (w->sButton.on)
239 		{
240 			XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
241 		}
242 		else
243 		{
244 			XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
245 		}
246 
247 		XtCallCallbackList((Widget)w , w->sButton.switchcb , NULL);
248 	}
249 	else
250 	{
251 		XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
252 
253 		XtCallCallbackList((Widget)w, w->sButton.activate, NULL);
254 
255 		XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
256 	}
257 }
258 
Enter_Leave(Widget sw,XEvent * event,String * params,Cardinal * num_params)259 static void Enter_Leave (Widget sw, XEvent *event,
260 		String *params, Cardinal *num_params)
261 {
262 	MwSButtonWidget w = (MwSButtonWidget)sw;
263 	if (w->sButton.mode == XtCcyclicMode) return;
264 
265 	if (w->sButton.mode == XtCnormalMode)
266 	{
267 		if ( (w->sButton.pressed) &&
268 		     (event->type == LeaveNotify))
269 		{
270 			XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
271 
272 			w->sButton.pressed = False;
273 		}
274 		else if ((event->type == EnterNotify) &&
275 			 (event->xcrossing.state & Button1Mask))
276 		{
277 			w->sButton.pressed = True;
278 
279 			XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
280 		}
281 	}
282 	else
283 	{
284 		if ((w->sButton.pressed) &&
285 		     (event->type == LeaveNotify))
286 		{
287 			if (w->sButton.on)
288 			{
289 				XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
290 			}
291 			else
292 			{
293 				XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
294 			}
295 
296 			w->sButton.pressed = False;
297 		}
298 		else if ((event->type == EnterNotify) &&
299 			 (event->xcrossing.state & Button1Mask))
300 		{
301 			if (w->sButton.on)
302 			{
303 				XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
304 			}
305 			else
306 			{
307 				XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
308 			}
309 			w->sButton.pressed = True;
310 		}
311 	}
312 }
313 
activate_t(Widget sw,XEvent * event,String * params,Cardinal * num_params)314 static void activate_t(Widget sw , XEvent *event ,
315 		String *params , Cardinal *num_params)
316 {
317 	MwSButtonWidget w = (MwSButtonWidget)sw;
318 	if (w->sButton.mode == XtCcyclicMode)
319 	{
320 		XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
321 
322 		XtCallCallbackList((Widget)w, w->sButton.activate, NULL);
323 
324 		w->sButton.timer = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)w),
325 					w->sButton.init_delay, timerCB, w);
326        	}
327        	else if (w->sButton.mode == XtCnormalMode)
328        	{
329 		w->sButton.pressed = True;
330 
331 		XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
332        	}
333        	else if (w->sButton.mode == XtCtoggleMode)
334        	{
335 		if (w->sButton.on)
336 		{
337 			XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
338 		}
339 		else
340 		{
341 			XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
342 		}
343 	       	w->sButton.pressed = True;
344        	}
345 }
346 
347 
deactivate_t(Widget sw,XEvent * event,String * params,Cardinal * num_params)348 static void deactivate_t(Widget sw , XEvent *event ,
349 		String *params , Cardinal *num_params)
350 {
351 	MwSButtonWidget w = (MwSButtonWidget)sw;
352 	if (w->sButton.mode == XtCcyclicMode)
353 	{
354 		XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
355 
356 		XtRemoveTimeOut(w->sButton.timer);
357 	}
358 	else  if (w->sButton.mode == XtCnormalMode)
359 	{
360 		XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
361 
362 		XFlush(XtDisplay((Widget)w));
363 
364 		if (w->sButton.pressed)
365 			XtCallCallbackList((Widget)w,w->sButton.activate, NULL);
366 
367 		w->sButton.pressed = False;
368 	}
369        	else if (w->sButton.mode == XtCtoggleMode)
370        	{
371        		if (w->sButton.pressed)
372        		{
373 			w->sButton.on = !w->sButton.on;
374 
375 			if (w->sButton.on)
376 			{
377 	       			w->sButton.pressed = False;
378 				XtVaSetValues((Widget)w , XtNbox_type , XtCdown_box , NULL);
379 			}
380 			else
381 			{
382 		       		w->sButton.pressed = False;
383 				XtVaSetValues((Widget)w , XtNbox_type , XtCup_box , NULL);
384 			}
385 
386 			XtCallCallbackList((Widget)w , w->sButton.switchcb , NULL);
387 
388 		}
389        	}
390 }
391 
392 
timerCB(XtPointer client_data,XtIntervalId * timer)393 static void timerCB(XtPointer client_data, XtIntervalId *timer)
394 {
395 	MwSButtonWidget w = (MwSButtonWidget) client_data;
396 
397 
398 	XtCallCallbackList((Widget) w, w->sButton.activate, NULL);
399 
400 
401 	w->sButton.timer = XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)w),
402 				w->sButton.repeat_delay, timerCB, w);
403 }
404