1 /*
2  * Copyright (C) 2000-2019 the xine project
3  *
4  * This file is part of xine, a unix video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <stdio.h>
26 
27 #include "_xitk.h"
28 
29 /*
30  *
31  */
notify_destroy(xitk_widget_t * w)32 static void notify_destroy(xitk_widget_t *w) {
33   checkbox_private_data_t *private_data;
34 
35   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
36     private_data = (checkbox_private_data_t *) w->private_data;
37 
38     if(!private_data->skin_element_name)
39       xitk_image_free_image(private_data->imlibdata, &(private_data->skin));
40 
41     XITK_FREE(private_data->skin_element_name);
42     XITK_FREE(private_data);
43   }
44 }
45 
46 /*
47  *
48  */
get_skin(xitk_widget_t * w,int sk)49 static xitk_image_t *get_skin(xitk_widget_t *w, int sk) {
50   checkbox_private_data_t *private_data;
51 
52   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
53     private_data = (checkbox_private_data_t *) w->private_data;
54 
55     if(sk == FOREGROUND_SKIN && private_data->skin) {
56       return private_data->skin;
57     }
58   }
59 
60   return NULL;
61 }
62 
63 /*
64  *
65  */
notify_inside(xitk_widget_t * w,int x,int y)66 static int notify_inside(xitk_widget_t *w, int x, int y) {
67   checkbox_private_data_t *private_data;
68 
69   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
70     private_data = (checkbox_private_data_t *) w->private_data;
71 
72     if(w->visible == 1) {
73       xitk_image_t *skin = private_data->skin;
74 
75       if(skin->mask)
76 	return xitk_is_cursor_out_mask(private_data->imlibdata->x.disp, w, skin->mask->pixmap, x, y);
77     }
78     else
79       return 0;
80   }
81 
82   return 1;
83 }
84 
85 /*
86  *
87  */
paint_checkbox(xitk_widget_t * w)88 static void paint_checkbox (xitk_widget_t *w) {
89   checkbox_private_data_t *private_data;
90   GC                       lgc;
91   int                      checkbox_width;
92   xitk_image_t            *skin;
93 
94   if(w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX) && w->visible == 1)) {
95     private_data = (checkbox_private_data_t *) w->private_data;
96 
97     skin           = private_data->skin;
98     checkbox_width = skin->width / 3;
99 
100     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
101     lgc = XCreateGC(private_data->imlibdata->x.disp, w->wl->win, None, None);
102     XCopyGC(private_data->imlibdata->x.disp, w->wl->gc, (1 << GCLastBit) - 1, lgc);
103     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
104 
105     if (skin->mask) {
106       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
107       XSetClipOrigin(private_data->imlibdata->x.disp, lgc, w->x, w->y);
108       XSetClipMask(private_data->imlibdata->x.disp, lgc, skin->mask->pixmap);
109       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
110     }
111 
112     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
113     if ((private_data->focus == FOCUS_RECEIVED) || (private_data->focus == FOCUS_MOUSE_IN)) {
114       if (private_data->cClicked || private_data->cState) { // focused, clicked or checked
115 	XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
116 		   w->wl->win, lgc, 2*checkbox_width, 0,
117 		   checkbox_width, skin->height, w->x, w->y);
118       }
119       else { // focused, unchecked
120 	XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
121 		   w->wl->win, lgc, checkbox_width, 0,
122 		   checkbox_width, skin->height, w->x, w->y);
123       }
124     }
125     else {
126       if(private_data->cState) { // unfocused, checked
127 	XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap,
128 		   w->wl->win, lgc, 2*checkbox_width, 0,
129 		   checkbox_width, skin->height, w->x, w->y);
130       }
131       else { // unfocused, unchecked
132 	XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap, w->wl->win, lgc, 0, 0,
133 		   checkbox_width, skin->height, w->x, w->y);
134       }
135     }
136     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
137 
138     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
139     XFreeGC(private_data->imlibdata->x.disp, lgc);
140     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
141   }
142 
143 }
144 
145 /*
146  *
147  */
notify_click_checkbox(xitk_widget_t * w,int button,int cUp,int x,int y)148 static int notify_click_checkbox (xitk_widget_t *w, int button, int cUp, int x, int y) {
149   checkbox_private_data_t *private_data;
150   int                      ret = 0;
151 
152   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
153     if(button == Button1) {
154       private_data = (checkbox_private_data_t *) w->private_data;
155 
156       private_data->cClicked = !cUp;
157       if (cUp && (private_data->focus == FOCUS_RECEIVED)) {
158 	private_data->cState = !private_data->cState;
159 
160 	if(private_data->callback) {
161 	  private_data->callback(private_data->cWidget,
162 				 private_data->userdata,
163 				 private_data->cState);
164 	}
165       }
166 
167       paint_checkbox(w);
168       ret = 1;
169     }
170   }
171 
172   return ret;
173 }
174 
175 /*
176  *
177  */
notify_focus_checkbox(xitk_widget_t * w,int focus)178 static int notify_focus_checkbox (xitk_widget_t *w, int focus) {
179   checkbox_private_data_t *private_data;
180 
181   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
182     private_data = (checkbox_private_data_t *) w->private_data;
183     private_data->focus = focus;
184   }
185   return 1;
186 }
187 
188 /*
189  *
190  */
notify_change_skin(xitk_widget_t * w,xitk_skin_config_t * skonfig)191 static void notify_change_skin(xitk_widget_t *w, xitk_skin_config_t *skonfig) {
192   checkbox_private_data_t *private_data;
193 
194   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
195     private_data = (checkbox_private_data_t *) w->private_data;
196 
197     if(private_data->skin_element_name) {
198       xitk_skin_lock(skonfig);
199       private_data->skin = xitk_skin_get_image(skonfig,
200 					       xitk_skin_get_skin_filename(skonfig, private_data->skin_element_name));
201       w->x               = xitk_skin_get_coord_x(skonfig, private_data->skin_element_name);
202       w->y               = xitk_skin_get_coord_y(skonfig, private_data->skin_element_name);
203       w->width           = private_data->skin->width/3;
204       w->height          = private_data->skin->height;
205       w->visible         = (xitk_skin_get_visibility(skonfig, private_data->skin_element_name)) ? 1: -1;
206       w->enable          = xitk_skin_get_enability(skonfig, private_data->skin_element_name);
207 
208       xitk_skin_unlock(skonfig);
209 
210       xitk_set_widget_pos(w, w->x, w->y);
211     }
212   }
213 }
214 
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)215 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
216   int retval = 0;
217 
218   switch(event->type) {
219   case WIDGET_EVENT_PAINT:
220     paint_checkbox(w);
221     break;
222   case WIDGET_EVENT_CLICK:
223     result->value = notify_click_checkbox(w, event->button,
224 					  event->button_pressed, event->x, event->y);
225     retval = 1;
226     break;
227   case WIDGET_EVENT_FOCUS:
228     notify_focus_checkbox(w, event->focus);
229     break;
230   case WIDGET_EVENT_INSIDE:
231     result->value = notify_inside(w, event->x, event->y);
232     retval = 1;
233     break;
234   case WIDGET_EVENT_CHANGE_SKIN:
235     notify_change_skin(w, event->skonfig);
236     break;
237   case WIDGET_EVENT_DESTROY:
238     notify_destroy(w);
239     break;
240   case WIDGET_EVENT_GET_SKIN:
241     if(result) {
242       result->image = get_skin(w, event->skin_layer);
243       retval = 1;
244     }
245     break;
246   }
247 
248   return retval;
249 }
250 
xitk_checkbox_callback_exec(xitk_widget_t * w)251 void xitk_checkbox_callback_exec(xitk_widget_t *w) {
252   checkbox_private_data_t *private_data;
253 
254   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
255     private_data = (checkbox_private_data_t *) w->private_data;
256 
257     if(private_data->callback) {
258       private_data->callback(private_data->cWidget,
259 			     private_data->userdata,
260 			     private_data->cState);
261     }
262   }
263 }
264 
265 /*
266  *
267  */
xitk_checkbox_get_state(xitk_widget_t * w)268 int xitk_checkbox_get_state(xitk_widget_t *w) {
269   checkbox_private_data_t *private_data;
270 
271   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
272     private_data = (checkbox_private_data_t *) w->private_data;
273     return private_data->cState;
274   }
275 
276   return 0;
277 }
278 
279 /*
280  *
281  */
xitk_checkbox_set_state(xitk_widget_t * w,int state)282 void xitk_checkbox_set_state(xitk_widget_t *w, int state) {
283   checkbox_private_data_t *private_data;
284   int                      clk, focus;
285 
286   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_CHECKBOX)) {
287     private_data = (checkbox_private_data_t *) w->private_data;
288 
289     if(xitk_checkbox_get_state(w) != state) {
290 
291       focus = private_data->focus;
292       clk = private_data->cClicked;
293 
294       private_data->focus = FOCUS_RECEIVED;
295       private_data->cClicked = 1;
296       private_data->cState = state;
297 
298       paint_checkbox(w);
299 
300       private_data->focus = focus;
301       private_data->cClicked = clk;
302 
303       paint_checkbox(w);
304     }
305   }
306 
307 }
308 
309 /*
310  *
311  */
_xitk_checkbox_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_checkbox_widget_t * cb,int x,int y,const char * skin_element_name,xitk_image_t * skin,int visible,int enable)312 static xitk_widget_t *_xitk_checkbox_create(xitk_widget_list_t *wl,
313 					    xitk_skin_config_t *skonfig,
314 					    xitk_checkbox_widget_t *cb, int x, int y,
315                                             const char *skin_element_name, xitk_image_t *skin,
316 					    int visible, int enable) {
317   xitk_widget_t *mywidget;
318   checkbox_private_data_t *private_data;
319 
320   mywidget = (xitk_widget_t *) xitk_xmalloc (sizeof(xitk_widget_t));
321 
322   private_data = (checkbox_private_data_t *)
323     xitk_xmalloc (sizeof (checkbox_private_data_t));
324 
325   private_data->imlibdata         = cb->imlibdata;
326   private_data->skin_element_name = (skin_element_name == NULL) ? NULL : strdup(cb->skin_element_name);
327 
328   private_data->cWidget           = mywidget;
329   private_data->cClicked          = 0;
330   private_data->cState            = 0;
331   private_data->focus             = FOCUS_LOST;
332 
333   private_data->skin              = skin;
334   private_data->callback          = cb->callback;
335   private_data->userdata          = cb->userdata;
336 
337   mywidget->private_data          = private_data;
338 
339   mywidget->wl                    = wl;
340 
341   mywidget->enable                = enable;
342   mywidget->running               = 1;
343   mywidget->visible               = visible;
344   mywidget->have_focus            = FOCUS_LOST;
345   mywidget->imlibdata             = private_data->imlibdata;
346   mywidget->x                     = x;
347   mywidget->y                     = y;
348   mywidget->width                 = private_data->skin->width/3;
349   mywidget->height                = private_data->skin->height;
350   mywidget->type                  = WIDGET_TYPE_CHECKBOX | WIDGET_CLICKABLE | WIDGET_FOCUSABLE | WIDGET_KEYABLE;
351   mywidget->event                 = notify_event;
352   mywidget->tips_timeout          = 0;
353   mywidget->tips_string           = NULL;
354 
355   return mywidget;
356 }
357 
358 /*
359  *
360  */
xitk_checkbox_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_checkbox_widget_t * cb)361 xitk_widget_t *xitk_checkbox_create (xitk_widget_list_t *wl,
362 				     xitk_skin_config_t *skonfig, xitk_checkbox_widget_t *cb) {
363 
364   XITK_CHECK_CONSTITENCY(cb);
365 
366   return _xitk_checkbox_create(wl, skonfig, cb,
367 			       (xitk_skin_get_coord_x(skonfig, cb->skin_element_name)),
368 			       (xitk_skin_get_coord_y(skonfig, cb->skin_element_name)),
369 			       cb->skin_element_name,
370 			       (xitk_skin_get_image(skonfig,
371 						    xitk_skin_get_skin_filename(skonfig, cb->skin_element_name))),
372 			       (xitk_skin_get_visibility(skonfig, cb->skin_element_name)) ? 1 : -1,
373 			       xitk_skin_get_enability(skonfig, cb->skin_element_name));
374 
375 }
376 
377 /*
378  *
379  */
xitk_noskin_checkbox_create(xitk_widget_list_t * wl,xitk_checkbox_widget_t * cb,int x,int y,int width,int height)380 xitk_widget_t *xitk_noskin_checkbox_create(xitk_widget_list_t *wl,
381 					   xitk_checkbox_widget_t *cb,
382 					   int x, int y, int width, int height) {
383   xitk_image_t  *i;
384 
385   XITK_CHECK_CONSTITENCY(cb);
386 
387   i = xitk_image_create_image(cb->imlibdata, width * 3, height);
388   draw_checkbox_check(cb->imlibdata, i);
389 
390   return _xitk_checkbox_create(wl, NULL, cb, x, y, NULL, i, 0, 0);
391 }
392