1
2 #include "WINGsP.h"
3
4 typedef struct W_Button {
5 W_Class widgetClass;
6 WMView *view;
7
8 char *caption;
9
10 char *altCaption;
11
12 WMFont *font;
13
14 WMColor *textColor;
15 WMColor *altTextColor;
16 WMColor *disTextColor;
17
18 W_Pixmap *image;
19 W_Pixmap *altImage;
20 W_Pixmap *tsImage;
21
22 W_Pixmap *dimage;
23
24 void *clientData;
25 WMAction *action;
26
27 int tag;
28
29 int groupIndex;
30
31 float periodicDelay;
32 float periodicInterval;
33
34 WMHandlerID *timer; /* for continuous mode */
35
36 struct {
37 WMButtonType type:4;
38 WMImagePosition imagePosition:4;
39 WMAlignment alignment:2;
40
41 unsigned int selected:2;
42
43 unsigned int enabled:1;
44
45 unsigned int dimsWhenDisabled:1;
46
47 unsigned int bordered:1;
48
49 unsigned int springLoaded:1;
50
51 unsigned int pushIn:1; /* change relief while pushed */
52
53 unsigned int pushLight:1; /* highlight while pushed */
54
55 unsigned int pushChange:1; /* change caption while pushed */
56
57 unsigned int stateLight:1; /* state indicated by highlight */
58
59 unsigned int stateChange:1; /* state indicated by caption change */
60
61 unsigned int statePush:1; /* state indicated by relief */
62
63 unsigned int continuous:1; /* continually perform action */
64
65 unsigned int prevSelected:1;
66
67 unsigned int pushed:1;
68
69 unsigned int wasPushed:1;
70
71 unsigned int redrawPending:1;
72
73 unsigned int addedObserver:1;
74 } flags;
75 } Button;
76
77 #define DEFAULT_BUTTON_WIDTH 60
78 #define DEFAULT_BUTTON_HEIGHT 24
79 #define DEFAULT_BUTTON_ALIGNMENT WACenter
80 #define DEFAULT_BUTTON_IS_BORDERED True
81
82 #define DEFAULT_RADIO_WIDTH 100
83 #define DEFAULT_RADIO_HEIGHT 20
84 #define DEFAULT_RADIO_ALIGNMENT WALeft
85 #define DEFAULT_RADIO_IMAGE_POSITION WIPLeft
86 #define DEFAULT_RADIO_TEXT "Radio"
87
88 #define DEFAULT_SWITCH_WIDTH 100
89 #define DEFAULT_SWITCH_HEIGHT 20
90 #define DEFAULT_SWITCH_ALIGNMENT WALeft
91 #define DEFAULT_SWITCH_IMAGE_POSITION WIPLeft
92 #define DEFAULT_SWITCH_TEXT "Switch"
93
94 static void destroyButton(Button * bPtr);
95 static void paintButton(Button * bPtr);
96
97 static void handleEvents(XEvent * event, void *data);
98 static void handleActionEvents(XEvent * event, void *data);
99
100 static char *WMPushedRadioNotification = "WMPushedRadioNotification";
101
102
WMCreateCustomButton(WMWidget * parent,int behaviourMask)103 WMButton *WMCreateCustomButton(WMWidget * parent, int behaviourMask)
104 {
105 Button *bPtr;
106
107 bPtr = wmalloc(sizeof(Button));
108
109 bPtr->widgetClass = WC_Button;
110
111 bPtr->view = W_CreateView(W_VIEW(parent));
112 if (!bPtr->view) {
113 wfree(bPtr);
114 return NULL;
115 }
116 bPtr->view->self = bPtr;
117
118 bPtr->flags.type = 0;
119
120 bPtr->flags.springLoaded = (behaviourMask & WBBSpringLoadedMask) != 0;
121 bPtr->flags.pushIn = (behaviourMask & WBBPushInMask) != 0;
122 bPtr->flags.pushChange = (behaviourMask & WBBPushChangeMask) != 0;
123 bPtr->flags.pushLight = (behaviourMask & WBBPushLightMask) != 0;
124 bPtr->flags.stateLight = (behaviourMask & WBBStateLightMask) != 0;
125 bPtr->flags.stateChange = (behaviourMask & WBBStateChangeMask) != 0;
126 bPtr->flags.statePush = (behaviourMask & WBBStatePushMask) != 0;
127
128 W_ResizeView(bPtr->view, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT);
129 bPtr->flags.alignment = DEFAULT_BUTTON_ALIGNMENT;
130 bPtr->flags.bordered = DEFAULT_BUTTON_IS_BORDERED;
131
132 bPtr->flags.enabled = 1;
133 bPtr->flags.dimsWhenDisabled = 1;
134
135 WMCreateEventHandler(bPtr->view, ExposureMask | StructureNotifyMask, handleEvents, bPtr);
136
137 WMCreateEventHandler(bPtr->view, ButtonPressMask | ButtonReleaseMask
138 | EnterWindowMask | LeaveWindowMask, handleActionEvents, bPtr);
139
140 W_ResizeView(bPtr->view, DEFAULT_BUTTON_WIDTH, DEFAULT_BUTTON_HEIGHT);
141 bPtr->flags.alignment = DEFAULT_BUTTON_ALIGNMENT;
142 bPtr->flags.bordered = DEFAULT_BUTTON_IS_BORDERED;
143
144 return bPtr;
145 }
146
WMCreateButton(WMWidget * parent,WMButtonType type)147 WMButton *WMCreateButton(WMWidget * parent, WMButtonType type)
148 {
149 W_Screen *scrPtr = W_VIEW(parent)->screen;
150 Button *bPtr;
151
152 switch (type) {
153 case WBTMomentaryPush:
154 bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask | WBBPushInMask | WBBPushLightMask);
155 break;
156
157 case WBTMomentaryChange:
158 bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask | WBBPushChangeMask);
159 break;
160
161 case WBTPushOnPushOff:
162 bPtr = WMCreateCustomButton(parent, WBBPushInMask | WBBStatePushMask | WBBStateLightMask);
163 break;
164
165 case WBTToggle:
166 bPtr = WMCreateCustomButton(parent, WBBPushInMask | WBBStateChangeMask | WBBStatePushMask);
167 break;
168
169 case WBTOnOff:
170 bPtr = WMCreateCustomButton(parent, WBBStateLightMask);
171 break;
172
173 case WBTSwitch:
174 bPtr = WMCreateCustomButton(parent, WBBStateChangeMask);
175 bPtr->flags.bordered = 0;
176 bPtr->image = WMRetainPixmap(scrPtr->checkButtonImageOff);
177 bPtr->altImage = WMRetainPixmap(scrPtr->checkButtonImageOn);
178 break;
179
180 case WBTRadio:
181 bPtr = WMCreateCustomButton(parent, WBBStateChangeMask);
182 bPtr->flags.bordered = 0;
183 bPtr->image = WMRetainPixmap(scrPtr->radioButtonImageOff);
184 bPtr->altImage = WMRetainPixmap(scrPtr->radioButtonImageOn);
185 break;
186
187 case WBTTriState:
188 bPtr = WMCreateCustomButton(parent, WBBStateChangeMask);
189 bPtr->flags.bordered = 0;
190 bPtr->image = WMRetainPixmap(scrPtr->tristateButtonImageOff);
191 bPtr->altImage = WMRetainPixmap(scrPtr->tristateButtonImageOn);
192 bPtr->tsImage = WMRetainPixmap(scrPtr->tristateButtonImageTri);
193 break;
194
195 default:
196 case WBTMomentaryLight:
197 bPtr = WMCreateCustomButton(parent, WBBSpringLoadedMask | WBBPushLightMask);
198 bPtr->flags.bordered = 1;
199 break;
200 }
201
202 bPtr->flags.type = type;
203
204 if (type == WBTRadio) {
205 W_ResizeView(bPtr->view, DEFAULT_RADIO_WIDTH, DEFAULT_RADIO_HEIGHT);
206 WMSetButtonText(bPtr, DEFAULT_RADIO_TEXT);
207 bPtr->flags.alignment = DEFAULT_RADIO_ALIGNMENT;
208 bPtr->flags.imagePosition = DEFAULT_RADIO_IMAGE_POSITION;
209 } else if (type == WBTSwitch || type == WBTTriState) {
210 W_ResizeView(bPtr->view, DEFAULT_SWITCH_WIDTH, DEFAULT_SWITCH_HEIGHT);
211 WMSetButtonText(bPtr, DEFAULT_SWITCH_TEXT);
212 bPtr->flags.alignment = DEFAULT_SWITCH_ALIGNMENT;
213 bPtr->flags.imagePosition = DEFAULT_SWITCH_IMAGE_POSITION;
214 }
215
216 return bPtr;
217 }
218
updateDisabledMask(WMButton * bPtr)219 static void updateDisabledMask(WMButton * bPtr)
220 {
221 WMScreen *scr = WMWidgetScreen(bPtr);
222 Display *dpy = scr->display;
223
224 if (bPtr->image) {
225 XGCValues gcv;
226
227 if (bPtr->dimage->mask) {
228 XFreePixmap(dpy, bPtr->dimage->mask);
229 bPtr->dimage->mask = None;
230 }
231
232 if (bPtr->flags.dimsWhenDisabled) {
233 bPtr->dimage->mask = XCreatePixmap(dpy, scr->stipple,
234 bPtr->dimage->width, bPtr->dimage->height, 1);
235
236 XSetForeground(dpy, scr->monoGC, 0);
237 XFillRectangle(dpy, bPtr->dimage->mask, scr->monoGC, 0, 0,
238 bPtr->dimage->width, bPtr->dimage->height);
239
240 gcv.foreground = 1;
241 gcv.background = 0;
242 gcv.stipple = scr->stipple;
243 gcv.fill_style = FillStippled;
244 gcv.clip_mask = bPtr->image->mask;
245 gcv.clip_x_origin = 0;
246 gcv.clip_y_origin = 0;
247
248 XChangeGC(dpy, scr->monoGC, GCForeground | GCBackground | GCStipple
249 | GCFillStyle | GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
250
251 XFillRectangle(dpy, bPtr->dimage->mask, scr->monoGC, 0, 0,
252 bPtr->dimage->width, bPtr->dimage->height);
253
254 gcv.fill_style = FillSolid;
255 gcv.clip_mask = None;
256 XChangeGC(dpy, scr->monoGC, GCFillStyle | GCClipMask, &gcv);
257 }
258 }
259 }
260
WMSetButtonImageDefault(WMButton * bPtr)261 void WMSetButtonImageDefault(WMButton * bPtr)
262 {
263 WMSetButtonImage(bPtr, WMWidgetScreen(bPtr)->buttonArrow);
264 WMSetButtonAltImage(bPtr, WMWidgetScreen(bPtr)->pushedButtonArrow);
265 }
266
WMSetButtonImage(WMButton * bPtr,WMPixmap * image)267 void WMSetButtonImage(WMButton * bPtr, WMPixmap * image)
268 {
269 if (bPtr->image != NULL)
270 WMReleasePixmap(bPtr->image);
271 bPtr->image = WMRetainPixmap(image);
272
273 if (bPtr->dimage) {
274 bPtr->dimage->pixmap = None;
275 WMReleasePixmap(bPtr->dimage);
276 bPtr->dimage = NULL;
277 }
278
279 if (image) {
280 bPtr->dimage = WMCreatePixmapFromXPixmaps(WMWidgetScreen(bPtr),
281 image->pixmap, None,
282 image->width, image->height, image->depth);
283 updateDisabledMask(bPtr);
284 }
285
286 if (bPtr->view->flags.realized) {
287 paintButton(bPtr);
288 }
289 }
290
WMSetButtonAltImage(WMButton * bPtr,WMPixmap * image)291 void WMSetButtonAltImage(WMButton * bPtr, WMPixmap * image)
292 {
293 if (bPtr->altImage != NULL)
294 WMReleasePixmap(bPtr->altImage);
295 bPtr->altImage = WMRetainPixmap(image);
296
297 if (bPtr->view->flags.realized) {
298 paintButton(bPtr);
299 }
300 }
301
WMSetButtonImagePosition(WMButton * bPtr,WMImagePosition position)302 void WMSetButtonImagePosition(WMButton * bPtr, WMImagePosition position)
303 {
304 bPtr->flags.imagePosition = position;
305
306 if (bPtr->view->flags.realized) {
307 paintButton(bPtr);
308 }
309 }
310
WMSetButtonTextAlignment(WMButton * bPtr,WMAlignment alignment)311 void WMSetButtonTextAlignment(WMButton * bPtr, WMAlignment alignment)
312 {
313 bPtr->flags.alignment = alignment;
314
315 if (bPtr->view->flags.realized) {
316 paintButton(bPtr);
317 }
318 }
319
WMSetButtonText(WMButton * bPtr,const char * text)320 void WMSetButtonText(WMButton * bPtr, const char *text)
321 {
322 if (bPtr->caption)
323 wfree(bPtr->caption);
324
325 if (text != NULL) {
326 bPtr->caption = wstrdup(text);
327 } else {
328 bPtr->caption = NULL;
329 }
330
331 if (bPtr->view->flags.realized) {
332 paintButton(bPtr);
333 }
334 }
335
WMGetButtonText(WMButton * bPtr)336 const char *WMGetButtonText(WMButton *bPtr)
337 {
338 return bPtr->caption;
339 }
340
WMSetButtonAltText(WMButton * bPtr,const char * text)341 void WMSetButtonAltText(WMButton * bPtr, const char *text)
342 {
343 if (bPtr->altCaption)
344 wfree(bPtr->altCaption);
345
346 if (text != NULL) {
347 bPtr->altCaption = wstrdup(text);
348 } else {
349 bPtr->altCaption = NULL;
350 }
351
352 if (bPtr->view->flags.realized) {
353 paintButton(bPtr);
354 }
355 }
356
WMSetButtonTextColor(WMButton * bPtr,WMColor * color)357 void WMSetButtonTextColor(WMButton * bPtr, WMColor * color)
358 {
359 if (bPtr->textColor)
360 WMReleaseColor(bPtr->textColor);
361
362 bPtr->textColor = WMRetainColor(color);
363 }
364
WMSetButtonAltTextColor(WMButton * bPtr,WMColor * color)365 void WMSetButtonAltTextColor(WMButton * bPtr, WMColor * color)
366 {
367 if (bPtr->altTextColor)
368 WMReleaseColor(bPtr->altTextColor);
369
370 bPtr->altTextColor = WMRetainColor(color);
371 }
372
WMSetButtonDisabledTextColor(WMButton * bPtr,WMColor * color)373 void WMSetButtonDisabledTextColor(WMButton * bPtr, WMColor * color)
374 {
375 if (bPtr->disTextColor)
376 WMReleaseColor(bPtr->disTextColor);
377
378 bPtr->disTextColor = WMRetainColor(color);
379 }
380
WMSetButtonSelected(WMButton * bPtr,int isSelected)381 void WMSetButtonSelected(WMButton * bPtr, int isSelected)
382 {
383 if ((bPtr->flags.type == WBTTriState) && (isSelected < 0))
384 bPtr->flags.selected = 2;
385 else
386 bPtr->flags.selected = isSelected ? 1 : 0;
387
388 if (bPtr->view->flags.realized) {
389 paintButton(bPtr);
390 }
391 if (bPtr->groupIndex > 0)
392 WMPostNotificationName(WMPushedRadioNotification, bPtr, NULL);
393 }
394
WMGetButtonSelected(WMButton * bPtr)395 int WMGetButtonSelected(WMButton * bPtr)
396 {
397 CHECK_CLASS(bPtr, WC_Button);
398
399 if ((bPtr->flags.type == WBTTriState) && (bPtr->flags.selected == 2))
400 return -1;
401
402 return bPtr->flags.selected;
403 }
404
WMSetButtonBordered(WMButton * bPtr,int isBordered)405 void WMSetButtonBordered(WMButton * bPtr, int isBordered)
406 {
407 bPtr->flags.bordered = isBordered;
408
409 if (bPtr->view->flags.realized) {
410 paintButton(bPtr);
411 }
412 }
413
WMSetButtonFont(WMButton * bPtr,WMFont * font)414 void WMSetButtonFont(WMButton * bPtr, WMFont * font)
415 {
416 if (bPtr->font)
417 WMReleaseFont(bPtr->font);
418
419 bPtr->font = WMRetainFont(font);
420 }
421
WMSetButtonEnabled(WMButton * bPtr,Bool flag)422 void WMSetButtonEnabled(WMButton * bPtr, Bool flag)
423 {
424 bPtr->flags.enabled = ((flag == 0) ? 0 : 1);
425
426 if (bPtr->view->flags.mapped) {
427 paintButton(bPtr);
428 }
429 }
430
WMGetButtonEnabled(WMButton * bPtr)431 int WMGetButtonEnabled(WMButton * bPtr)
432 {
433 CHECK_CLASS(bPtr, WC_Button);
434
435 return bPtr->flags.enabled;
436 }
437
WMSetButtonImageDimsWhenDisabled(WMButton * bPtr,Bool flag)438 void WMSetButtonImageDimsWhenDisabled(WMButton * bPtr, Bool flag)
439 {
440 bPtr->flags.dimsWhenDisabled = ((flag == 0) ? 0 : 1);
441
442 updateDisabledMask(bPtr);
443 }
444
WMSetButtonTag(WMButton * bPtr,int tag)445 void WMSetButtonTag(WMButton * bPtr, int tag)
446 {
447 bPtr->tag = tag;
448 }
449
WMPerformButtonClick(WMButton * bPtr)450 void WMPerformButtonClick(WMButton * bPtr)
451 {
452 CHECK_CLASS(bPtr, WC_Button);
453
454 if (!bPtr->flags.enabled)
455 return;
456
457 bPtr->flags.pushed = 1;
458 bPtr->flags.selected = 1;
459
460 if (bPtr->view->flags.mapped) {
461 paintButton(bPtr);
462 XFlush(WMScreenDisplay(WMWidgetScreen(bPtr)));
463 wusleep(20000);
464 }
465
466 bPtr->flags.pushed = 0;
467
468 if (bPtr->groupIndex > 0) {
469 WMPostNotificationName(WMPushedRadioNotification, bPtr, NULL);
470 }
471
472 if (bPtr->action)
473 (*bPtr->action) (bPtr, bPtr->clientData);
474
475 if (bPtr->view->flags.mapped)
476 paintButton(bPtr);
477 }
478
WMSetButtonAction(WMButton * bPtr,WMAction * action,void * clientData)479 void WMSetButtonAction(WMButton * bPtr, WMAction * action, void *clientData)
480 {
481 CHECK_CLASS(bPtr, WC_Button);
482
483 bPtr->action = action;
484
485 bPtr->clientData = clientData;
486 }
487
radioPushObserver(void * observerData,WMNotification * notification)488 static void radioPushObserver(void *observerData, WMNotification * notification)
489 {
490 WMButton *bPtr = (WMButton *) observerData;
491 WMButton *pushedButton = (WMButton *) WMGetNotificationObject(notification);
492
493 if (bPtr != pushedButton && pushedButton->groupIndex == bPtr->groupIndex && bPtr->groupIndex != 0) {
494 if (bPtr->flags.selected) {
495 bPtr->flags.selected = 0;
496 paintButton(bPtr);
497 }
498 }
499 }
500
WMGroupButtons(WMButton * bPtr,WMButton * newMember)501 void WMGroupButtons(WMButton * bPtr, WMButton * newMember)
502 {
503 static int tagIndex = 0;
504
505 CHECK_CLASS(bPtr, WC_Button);
506 CHECK_CLASS(newMember, WC_Button);
507
508 if (!bPtr->flags.addedObserver) {
509 WMAddNotificationObserver(radioPushObserver, bPtr, WMPushedRadioNotification, NULL);
510 bPtr->flags.addedObserver = 1;
511 }
512 if (!newMember->flags.addedObserver) {
513 WMAddNotificationObserver(radioPushObserver, newMember, WMPushedRadioNotification, NULL);
514 newMember->flags.addedObserver = 1;
515 }
516
517 if (bPtr->groupIndex == 0) {
518 bPtr->groupIndex = ++tagIndex;
519 }
520 newMember->groupIndex = bPtr->groupIndex;
521 }
522
WMSetButtonContinuous(WMButton * bPtr,Bool flag)523 void WMSetButtonContinuous(WMButton * bPtr, Bool flag)
524 {
525 bPtr->flags.continuous = ((flag == 0) ? 0 : 1);
526 if (bPtr->timer) {
527 WMDeleteTimerHandler(bPtr->timer);
528 bPtr->timer = NULL;
529 }
530 }
531
WMSetButtonPeriodicDelay(WMButton * bPtr,float delay,float interval)532 void WMSetButtonPeriodicDelay(WMButton * bPtr, float delay, float interval)
533 {
534 bPtr->periodicInterval = interval;
535 bPtr->periodicDelay = delay;
536 }
537
paintButton(Button * bPtr)538 static void paintButton(Button * bPtr)
539 {
540 W_Screen *scrPtr = bPtr->view->screen;
541 WMReliefType relief;
542 int offset;
543 char *caption;
544 WMPixmap *image;
545 WMColor *textColor;
546 WMColor *backColor;
547
548 backColor = NULL;
549 caption = bPtr->caption;
550
551 if (bPtr->flags.enabled) {
552 textColor = (bPtr->textColor != NULL ? bPtr->textColor : scrPtr->black);
553 } else {
554 textColor = (bPtr->disTextColor != NULL ? bPtr->disTextColor : scrPtr->darkGray);
555 }
556
557 if (bPtr->flags.enabled || !bPtr->dimage)
558 image = bPtr->image;
559 else
560 image = bPtr->dimage;
561 offset = 0;
562 if (bPtr->flags.bordered)
563 relief = WRRaised;
564 else
565 relief = WRFlat;
566
567 if (bPtr->flags.selected) {
568 if (bPtr->flags.stateLight) {
569 backColor = scrPtr->white;
570 textColor = scrPtr->black;
571 }
572
573 if (bPtr->flags.stateChange) {
574 if (bPtr->altCaption)
575 caption = bPtr->altCaption;
576 if (bPtr->flags.selected == 2)
577 image = bPtr->tsImage;
578 else if (bPtr->altImage)
579 image = bPtr->altImage;
580 if (bPtr->altTextColor)
581 textColor = bPtr->altTextColor;
582 }
583
584 if (bPtr->flags.statePush && bPtr->flags.bordered) {
585 relief = WRSunken;
586 offset = 1;
587 }
588 }
589
590 if (bPtr->flags.pushed) {
591 if (bPtr->flags.pushIn) {
592 relief = WRPushed;
593 offset = 1;
594 }
595 if (bPtr->flags.pushLight) {
596 backColor = scrPtr->white;
597 textColor = scrPtr->black;
598 }
599
600 if (bPtr->flags.pushChange) {
601 if (bPtr->altCaption)
602 caption = bPtr->altCaption;
603 if (bPtr->altImage)
604 image = bPtr->altImage;
605 if (bPtr->altTextColor)
606 textColor = bPtr->altTextColor;
607 }
608 }
609
610 W_PaintTextAndImage(bPtr->view, True, textColor,
611 (bPtr->font != NULL ? bPtr->font : scrPtr->normalFont),
612 relief, caption, bPtr->flags.alignment, image,
613 bPtr->flags.imagePosition, backColor, offset);
614 }
615
handleEvents(XEvent * event,void * data)616 static void handleEvents(XEvent * event, void *data)
617 {
618 Button *bPtr = (Button *) data;
619
620 CHECK_CLASS(data, WC_Button);
621
622 switch (event->type) {
623 case Expose:
624 if (event->xexpose.count != 0)
625 break;
626 paintButton(bPtr);
627 break;
628
629 case DestroyNotify:
630 destroyButton(bPtr);
631 break;
632 }
633 }
634
autoRepeat(void * data)635 static void autoRepeat(void *data)
636 {
637 Button *bPtr = (Button *) data;
638
639 if (bPtr->action && bPtr->flags.pushed)
640 (*bPtr->action) (bPtr, bPtr->clientData);
641
642 bPtr->timer = WMAddTimerHandler((int)(bPtr->periodicInterval * 1000), autoRepeat, bPtr);
643 }
644
handleActionEvents(XEvent * event,void * data)645 static void handleActionEvents(XEvent * event, void *data)
646 {
647 Button *bPtr = (Button *) data;
648 int doclick = 0, dopaint = 0;
649
650 CHECK_CLASS(data, WC_Button);
651
652 if (!bPtr->flags.enabled)
653 return;
654
655 switch (event->type) {
656 case EnterNotify:
657 if (bPtr->groupIndex == 0) {
658 bPtr->flags.pushed = bPtr->flags.wasPushed;
659 if (bPtr->flags.pushed) {
660 bPtr->flags.selected = !bPtr->flags.prevSelected;
661 dopaint = 1;
662 }
663 }
664 break;
665
666 case LeaveNotify:
667 if (bPtr->groupIndex == 0) {
668 bPtr->flags.wasPushed = bPtr->flags.pushed;
669 if (bPtr->flags.pushed) {
670 bPtr->flags.selected = bPtr->flags.prevSelected;
671 dopaint = 1;
672 }
673 bPtr->flags.pushed = 0;
674 }
675 break;
676
677 case ButtonPress:
678 if (event->xbutton.button == Button1) {
679 static const unsigned int next_state[4] = { [0] = 1, [1] = 2, [2] = 0 };
680
681 bPtr->flags.prevSelected = bPtr->flags.selected;
682 bPtr->flags.wasPushed = 0;
683 bPtr->flags.pushed = 1;
684 if (bPtr->groupIndex > 0) {
685 bPtr->flags.selected = 1;
686 dopaint = 1;
687 break;
688 }
689 if (bPtr->flags.type == WBTTriState)
690 bPtr->flags.selected = next_state[bPtr->flags.selected];
691 else
692 bPtr->flags.selected = !bPtr->flags.selected;
693 dopaint = 1;
694
695 if (bPtr->flags.continuous && !bPtr->timer) {
696 bPtr->timer = WMAddTimerHandler((int)(bPtr->periodicDelay * 1000),
697 autoRepeat, bPtr);
698 }
699 }
700 break;
701
702 case ButtonRelease:
703 if (event->xbutton.button == Button1) {
704 if (bPtr->flags.pushed) {
705 if (bPtr->groupIndex == 0 || (bPtr->flags.selected && bPtr->groupIndex > 0))
706 doclick = 1;
707 dopaint = 1;
708 if (bPtr->flags.springLoaded) {
709 bPtr->flags.selected = bPtr->flags.prevSelected;
710 }
711 }
712 bPtr->flags.pushed = 0;
713 }
714 if (bPtr->timer) {
715 WMDeleteTimerHandler(bPtr->timer);
716 bPtr->timer = NULL;
717 }
718 break;
719 }
720
721 if (dopaint)
722 paintButton(bPtr);
723
724 if (doclick) {
725 if (bPtr->flags.selected && bPtr->groupIndex > 0) {
726 WMPostNotificationName(WMPushedRadioNotification, bPtr, NULL);
727 }
728
729 if (bPtr->action)
730 (*bPtr->action) (bPtr, bPtr->clientData);
731 }
732 }
733
destroyButton(Button * bPtr)734 static void destroyButton(Button * bPtr)
735 {
736 if (bPtr->flags.addedObserver) {
737 WMRemoveNotificationObserver(bPtr);
738 }
739
740 if (bPtr->timer)
741 WMDeleteTimerHandler(bPtr->timer);
742
743 if (bPtr->font)
744 WMReleaseFont(bPtr->font);
745
746 if (bPtr->caption)
747 wfree(bPtr->caption);
748
749 if (bPtr->altCaption)
750 wfree(bPtr->altCaption);
751
752 if (bPtr->textColor)
753 WMReleaseColor(bPtr->textColor);
754
755 if (bPtr->altTextColor)
756 WMReleaseColor(bPtr->altTextColor);
757
758 if (bPtr->disTextColor)
759 WMReleaseColor(bPtr->disTextColor);
760
761 if (bPtr->image)
762 WMReleasePixmap(bPtr->image);
763
764 if (bPtr->dimage) {
765 /* yuck.. kluge */
766 bPtr->dimage->pixmap = None;
767
768 WMReleasePixmap(bPtr->dimage);
769 }
770 if (bPtr->altImage)
771 WMReleasePixmap(bPtr->altImage);
772
773 if (bPtr->tsImage)
774 WMReleasePixmap(bPtr->tsImage);
775
776 wfree(bPtr);
777 }
778