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 <X11/Xlib.h>
26 #include <stdio.h>
27 
28 #include "_xitk.h"
29 
enability(xitk_widget_t * w)30 static void enability(xitk_widget_t *w) {
31 
32   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
33 	   (w->type & WIDGET_GROUP_WIDGET))) {
34     doublebox_private_data_t *private_data = (doublebox_private_data_t *) w->private_data;
35 
36     if(w->enable == WIDGET_ENABLE) {
37       xitk_enable_widget(private_data->input_widget);
38       xitk_enable_widget(private_data->more_widget);
39       xitk_enable_widget(private_data->less_widget);
40     }
41     else {
42       xitk_disable_widget(private_data->input_widget);
43       xitk_disable_widget(private_data->more_widget);
44       xitk_disable_widget(private_data->less_widget);
45     }
46   }
47 }
48 
49 /*
50  *
51  */
notify_destroy(xitk_widget_t * w)52 static void notify_destroy(xitk_widget_t *w) {
53 
54   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
55 	   (w->type & WIDGET_GROUP_WIDGET))) {
56     doublebox_private_data_t *private_data = (doublebox_private_data_t *) w->private_data;
57 
58     XITK_FREE(private_data->skin_element_name);
59     XITK_FREE(private_data);
60   }
61 }
62 
63 /*
64  *
65  */
paint(xitk_widget_t * w)66 static void paint(xitk_widget_t *w) {
67 
68   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
69 	   (w->type & WIDGET_GROUP_WIDGET))) {
70     doublebox_private_data_t *private_data = (doublebox_private_data_t *) w->private_data;
71 
72     if(w->visible == 1) {
73       int bx, ih, iw;
74 
75       iw = xitk_get_widget_width(private_data->input_widget);
76       ih = xitk_get_widget_height(private_data->input_widget);
77       xitk_set_widget_pos(private_data->input_widget, w->x, w->y);
78       bx = w->x + iw;
79       xitk_set_widget_pos(private_data->more_widget, bx, w->y);
80       xitk_set_widget_pos(private_data->less_widget, bx, (w->y + (ih>>1)));
81 
82       xitk_show_widget(private_data->input_widget);
83       xitk_show_widget(private_data->more_widget);
84       xitk_show_widget(private_data->less_widget);
85     }
86     else {
87       xitk_hide_widget(private_data->input_widget);
88       xitk_hide_widget(private_data->more_widget);
89       xitk_hide_widget(private_data->less_widget);
90     }
91   }
92 }
93 
94 /*
95  *
96  */
notify_change_skin(xitk_widget_t * w,xitk_skin_config_t * skonfig)97 static void notify_change_skin(xitk_widget_t *w, xitk_skin_config_t *skonfig) {
98 
99   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
100 	   (w->type & WIDGET_GROUP_WIDGET))) {
101     doublebox_private_data_t *private_data = (doublebox_private_data_t *) w->private_data;
102 
103     if(private_data->skin_element_name) {
104       /*
105       int x, y;
106 
107       xitk_skin_lock(skonfig);
108 
109       // visibility && enability
110 
111       xitk_set_widget_pos(c, c->x, c->y);
112       xitk_get_widget_pos(private_data->label_widget, &x, &y);
113       x += xitk_get_widget_width(private_data->label_widget);
114 
115       (void) xitk_set_widget_pos(private_data->button_widget, x, y);
116 
117       xitk_skin_unlock(skonfig);
118       */
119     }
120   }
121 }
122 
tips_timeout(xitk_widget_t * w,unsigned long timeout)123 static void tips_timeout(xitk_widget_t *w, unsigned long timeout) {
124   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
125 	   (w->type & WIDGET_GROUP_WIDGET))) {
126     doublebox_private_data_t *private_data = (doublebox_private_data_t *) w->private_data;
127 
128     private_data->input_widget->tips_timeout = timeout;
129     private_data->more_widget->tips_timeout = timeout;
130     private_data->less_widget->tips_timeout = timeout;
131   }
132 }
133 
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)134 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
135   int retval = 0;
136 
137   switch(event->type) {
138   case WIDGET_EVENT_PAINT:
139     paint(w);
140     break;
141   case WIDGET_EVENT_CHANGE_SKIN:
142     notify_change_skin(w, event->skonfig);
143     break;
144   case WIDGET_EVENT_DESTROY:
145     notify_destroy(w);
146     break;
147   case WIDGET_EVENT_ENABLE:
148     enability(w);
149     break;
150   case WIDGET_EVENT_TIPS_TIMEOUT:
151     tips_timeout(w, event->tips_timeout);
152     break;
153   }
154 
155   return retval;
156 }
157 
158 /*
159  *
160  */
doublebox_change_value(xitk_widget_t * x,void * data,const char * string)161 static void doublebox_change_value(xitk_widget_t *x, void *data, const char *string) {
162   xitk_widget_t         *w = (xitk_widget_t *)data;
163 
164   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
165 	   (w->type & WIDGET_GROUP_WIDGET))) {
166     doublebox_private_data_t *private_data = (doublebox_private_data_t *)w->private_data;
167     char                      buf[256];
168 
169     private_data->value = strtod(string, NULL);
170 
171     memset(&buf, 0, sizeof(buf));
172     snprintf(buf, sizeof(buf), "%e", private_data->value);
173     xitk_inputtext_change_text(private_data->input_widget, buf);
174     if(private_data->force_value == 0)
175       if(private_data->callback)
176 	private_data->callback(w, private_data->userdata, private_data->value);
177   }
178 }
179 
180 /*
181  *
182  */
xitk_doublebox_set_value(xitk_widget_t * w,double value)183 void xitk_doublebox_set_value(xitk_widget_t *w, double value) {
184 
185   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
186 	   (w->type & WIDGET_GROUP_WIDGET))) {
187     doublebox_private_data_t *private_data = (doublebox_private_data_t *) w->private_data;
188     char                      buf[256];
189 
190     memset(&buf, 0, sizeof(buf));
191     snprintf(buf, sizeof(buf), "%e", value);
192     private_data->force_value = 1;
193     doublebox_change_value(NULL, (void*)w, buf);
194     private_data->force_value = 0;
195   }
196 }
197 
198 /*
199  *
200  */
xitk_doublebox_get_value(xitk_widget_t * w)201 double xitk_doublebox_get_value(xitk_widget_t *w) {
202 
203   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
204 	   (w->type & WIDGET_GROUP_WIDGET))) {
205     doublebox_private_data_t *private_data = (doublebox_private_data_t *)w->private_data;
206     const char               *strval;
207 
208     strval = xitk_inputtext_get_text(private_data->input_widget);
209     private_data->value = strtod(strval, NULL);
210 
211     return private_data->value;
212   }
213   return 0;
214 }
215 
216 /*
217  *
218  */
doublebox_stepdown(xitk_widget_t * x,void * data)219 static void doublebox_stepdown(xitk_widget_t *x, void *data) {
220   xitk_widget_t *w = (xitk_widget_t *) data;
221 
222   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
223 	   (w->type & WIDGET_GROUP_WIDGET))) {
224     doublebox_private_data_t *private_data = (doublebox_private_data_t *)w->private_data;
225 
226     private_data->value -= private_data->step;
227     xitk_doublebox_set_value(w, private_data->value);
228     if(private_data->callback)
229       private_data->callback(w, private_data->userdata, private_data->value);
230   }
231 }
232 
233 /*
234  *
235  */
doublebox_stepup(xitk_widget_t * x,void * data)236 static void doublebox_stepup(xitk_widget_t *x, void *data) {
237   xitk_widget_t *w = (xitk_widget_t *) data;
238 
239   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
240 	   (w->type & WIDGET_GROUP_WIDGET))) {
241     doublebox_private_data_t *private_data = (doublebox_private_data_t *)w->private_data;
242 
243     private_data->value += private_data->step;
244     xitk_doublebox_set_value(w, private_data->value);
245     if(private_data->callback)
246       private_data->callback(w, private_data->userdata, private_data->value);
247   }
248 }
249 
250 /*
251  *
252  */
xitk_doublebox_get_input_widget(xitk_widget_t * w)253 xitk_widget_t *xitk_doublebox_get_input_widget(xitk_widget_t *w) {
254 
255   if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_DOUBLEBOX) &&
256 	   (w->type & WIDGET_GROUP_WIDGET))) {
257     doublebox_private_data_t *private_data = (doublebox_private_data_t *)w->private_data;
258 
259     return private_data->input_widget;
260   }
261 
262   return NULL;
263 }
264 
265 /*
266  *
267  */
_xitk_doublebox_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_doublebox_widget_t * ib,char * skin_element_name,xitk_widget_t * mywidget,doublebox_private_data_t * private_data,int visible,int enable)268 static xitk_widget_t *_xitk_doublebox_create(xitk_widget_list_t *wl,
269 					  xitk_skin_config_t *skonfig,
270 					  xitk_doublebox_widget_t *ib, char *skin_element_name,
271 					  xitk_widget_t *mywidget,
272 					  doublebox_private_data_t *private_data,
273 					  int visible, int enable) {
274 
275   private_data->imlibdata                = ib->imlibdata;
276   private_data->skin_element_name        = (skin_element_name == NULL) ? NULL : strdup(skin_element_name);
277   private_data->parent_wlist             = ib->parent_wlist;
278   private_data->callback                 = ib->callback;
279   private_data->userdata                 = ib->userdata;
280   private_data->step                     = ib->step;
281   private_data->value                    = ib->value;
282   private_data->force_value              = 0;
283 
284   mywidget->private_data                 = private_data;
285 
286   mywidget->wl                           = wl;
287 
288   mywidget->enable                       = enable;
289   mywidget->running                      = 1;
290   mywidget->visible                      = visible;
291   mywidget->have_focus                   = FOCUS_LOST;
292 
293   mywidget->imlibdata                    = private_data->imlibdata;
294 
295   mywidget->type                         = WIDGET_GROUP | WIDGET_GROUP_WIDGET | WIDGET_GROUP_DOUBLEBOX;
296   mywidget->event                        = notify_event;
297   mywidget->tips_timeout                 = 0;
298   mywidget->tips_string                  = NULL;
299 
300   return mywidget;
301 }
302 
303 /*
304  *
305  */
xitk_noskin_doublebox_create(xitk_widget_list_t * wl,xitk_doublebox_widget_t * ib,int x,int y,int width,int height,xitk_widget_t ** iw,xitk_widget_t ** mw,xitk_widget_t ** lw)306 xitk_widget_t *xitk_noskin_doublebox_create(xitk_widget_list_t *wl,
307 					 xitk_doublebox_widget_t *ib,
308 					 int x, int y, int width, int height,
309 					 xitk_widget_t **iw, xitk_widget_t **mw, xitk_widget_t **lw) {
310   xitk_widget_t              *mywidget;
311   doublebox_private_data_t      *private_data;
312   xitk_button_widget_t        b;
313   xitk_inputtext_widget_t     inp;
314 
315   XITK_CHECK_CONSTITENCY(ib);
316 
317   mywidget = (xitk_widget_t *) xitk_xmalloc (sizeof(xitk_widget_t));
318 
319   XITK_WIDGET_INIT(&b, ib->imlibdata);
320   XITK_WIDGET_INIT(&inp, ib->imlibdata);
321 
322   private_data = (doublebox_private_data_t *) xitk_xmalloc(sizeof(doublebox_private_data_t));
323 
324   /* Create inputtext and buttons (not skinable) */
325   {
326     char          buf[256];
327     xitk_image_t *wimage;
328 
329     memset(&buf, 0, sizeof(buf));
330     snprintf(buf, sizeof(buf), "%e", ib->value);
331 
332     inp.skin_element_name = NULL;
333     inp.text              = buf;
334     inp.max_length        = 16;
335     inp.callback          = doublebox_change_value;
336     inp.userdata          = (void *)mywidget;
337     private_data->input_widget = xitk_noskin_inputtext_create (ib->parent_wlist, &inp,
338       x, y, (width - 10), height, "Black", "Black", DEFAULT_FONT_10);
339     xitk_dlist_add_tail (&ib->parent_wlist->list, &private_data->input_widget->node);
340     private_data->input_widget->type |= WIDGET_GROUP | WIDGET_GROUP_DOUBLEBOX;
341 
342     b.skin_element_name = NULL;
343     b.callback          = doublebox_stepup;
344     b.userdata          = (void *)mywidget;
345     private_data->more_widget = xitk_noskin_button_create (ib->parent_wlist, &b,
346       (x + width) - (height>>1), y, (height>>1), (height>>1));
347     xitk_dlist_add_tail (&ib->parent_wlist->list, &private_data->more_widget->node);
348     private_data->more_widget->type |= WIDGET_GROUP | WIDGET_GROUP_DOUBLEBOX;
349 
350     b.skin_element_name = NULL;
351     b.callback          = doublebox_stepdown;
352     b.userdata          = (void *)mywidget;
353     private_data->less_widget = xitk_noskin_button_create (ib->parent_wlist, &b,
354       (x + width) - (height>>1), (y + (height>>1)), (height>>1), (height>>1));
355     xitk_dlist_add_tail (&ib->parent_wlist->list, &private_data->less_widget->node);
356     private_data->less_widget->type |= WIDGET_GROUP | WIDGET_GROUP_DOUBLEBOX;
357 
358     /* Draw '+' and '-' in buttons */
359     wimage = xitk_get_widget_foreground_skin(private_data->more_widget);
360 
361     if(wimage)
362       draw_button_plus(ib->imlibdata, wimage);
363 
364     wimage = xitk_get_widget_foreground_skin(private_data->less_widget);
365 
366     if(wimage)
367       draw_button_minus(ib->imlibdata, wimage);
368 
369   }
370 
371   if(iw)
372     *iw = private_data->input_widget;
373   if(mw)
374     *mw = private_data->more_widget;
375   if(lw)
376     *lw = private_data->less_widget;
377 
378   mywidget->x = x;
379   mywidget->y = y;
380   mywidget->width = width;
381   mywidget->height = height;
382 
383   return _xitk_doublebox_create(wl, NULL, ib, NULL, mywidget, private_data, 0, 0);
384 }
385