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 #include <math.h>
27 
28 #include "_xitk.h"
29 
30 #ifndef M_PI
31 #define M_PI 3.14159265358979323846
32 #endif
33 
34 /*
35  *
36  */
slider_update_value(xitk_widget_t * w,float value)37 static void slider_update_value(xitk_widget_t *w, float value) {
38   slider_private_data_t *private_data = (slider_private_data_t *) w->private_data;
39   float                  range;
40 
41   if(value < private_data->lower)
42     private_data->value = private_data->lower;
43   else if(value > private_data->upper)
44     private_data->value = private_data->upper;
45   else
46     private_data->value = value;
47 
48   range = (private_data->upper + -private_data->lower);
49 
50   private_data->percentage = (private_data->value + -private_data->lower) / range;
51   private_data->angle = 7.*M_PI/6. - (private_data->value - private_data->lower) *
52     4.*M_PI/3. / (private_data->upper - private_data->lower);
53 
54 }
55 
56 /*
57  *
58  */
slider_update_minmax(xitk_widget_t * w,float min,float max)59 static void slider_update_minmax(xitk_widget_t *w, float min, float max) {
60   slider_private_data_t *private_data = (slider_private_data_t *) w->private_data;
61 
62   if(min > max) {
63     XITK_WARNING("%s@%d: slider min value > max value !\n", __FILE__, __LINE__);
64     return;
65   }
66 
67   private_data->upper = (min == max) ? max + 1 : max;
68   private_data->lower = min;
69   slider_update_value(w, private_data->value);
70 }
71 
72 /*
73  *
74  */
slider_update(xitk_widget_t * w,int x,int y)75 static void slider_update(xitk_widget_t *w, int x, int y) {
76   slider_private_data_t *private_data = (slider_private_data_t *) w->private_data;
77 
78   if(private_data->sType == XITK_RSLIDER) {
79     int   xc, yc;
80     float old_value;
81 
82     xc = private_data->bg_skin->width / 2;
83     yc = private_data->bg_skin->height / 2;
84 
85     old_value = private_data->value;
86     private_data->angle = atan2(yc - y, x - xc);
87 
88     if(private_data->angle < -M_PI / 2.)
89       private_data->angle += 2 * M_PI;
90 
91     if(private_data->angle < -M_PI / 6)
92       private_data->angle = -M_PI / 6;
93 
94     if(private_data->angle > 7. * M_PI / 6.)
95       private_data->angle = 7. * M_PI / 6.;
96 
97     private_data->value = private_data->lower + (7. * M_PI / 6 - private_data->angle) *
98       (private_data->upper - private_data->lower) / (4. * M_PI / 3.);
99 
100     if(private_data->value != old_value) {
101       float new_value;
102 
103       new_value = private_data->value;
104 
105       if(new_value < private_data->lower)
106 	new_value = private_data->lower;
107 
108       if(new_value > private_data->upper)
109 	new_value = private_data->upper;
110 
111       slider_update_value(w, new_value);
112 
113     }
114   }
115   else {
116     float width, height;
117     float old_value, new_value = 0.0;
118 
119     old_value = private_data->value;
120 
121     width = (float)private_data->bg_skin->width;
122     height = (float)private_data->bg_skin->height;
123 
124     if(private_data->paddle_cover_bg == 1) {
125 
126       if(x < 0)
127 	x = 0;
128       if(x > width)
129 	x = width;
130 
131       if(y < 0)
132 	y = 0;
133       if(y > height)
134 	y = height;
135 
136       if(private_data->sType == XITK_HSLIDER)
137 	new_value = (x * .01) / (width * .01);
138       else if(private_data->sType == XITK_VSLIDER)
139 	new_value = ((height - y) * .01) / (height * .01);
140 
141     }
142     else {
143       int pwidth, pheight;
144 
145       pwidth = private_data->button_width;
146       pheight = private_data->paddle_skin->height;
147 
148       if(private_data->sType == XITK_HSLIDER) {
149 	x -= pwidth >> 1;
150 
151 	if(x < 0)
152 	  x = 0;
153 	if(x > (width - pwidth))
154 	  x = width - pwidth;
155 
156 	if(y < 0)
157 	  y = 0;
158 	if(y > height)
159 	  y = height;
160 
161       }
162       else { /* XITK_VSLIDER */
163 
164 	if(x < 0)
165 	  x = 0;
166 	if(x > width)
167 	  x = width;
168 
169 	y += pheight >> 1;
170 
171 	if(y < 0)
172 	  y = 0;
173 	if(y > (height + pheight))
174 	  y = height + pheight ;
175       }
176 
177       if(private_data->sType == XITK_HSLIDER)
178 	new_value = (x * .01) / ((width - pwidth) * .01);
179       else if(private_data->sType == XITK_VSLIDER)
180 	new_value = ((height - y) * .01) / ((height - pheight) * .01);
181     }
182 
183     private_data->value = private_data->lower +
184       (new_value * (private_data->upper - private_data->lower));
185 
186     if(private_data->value != old_value) {
187       float new_value;
188 
189       new_value = private_data->value;
190 
191       if (new_value < private_data->lower)
192 	new_value = private_data->lower;
193 
194       if (new_value > private_data->upper)
195 	new_value = private_data->upper;
196 
197       slider_update_value(w, new_value);
198     }
199   }
200 }
201 
202 /*
203  *
204  */
notify_destroy(xitk_widget_t * w)205 static void notify_destroy(xitk_widget_t *w) {
206   slider_private_data_t *private_data;
207 
208   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
209     private_data = (slider_private_data_t *) w->private_data;
210 
211     if(!private_data->skin_element_name) {
212       xitk_image_free_image(private_data->imlibdata, &(private_data->paddle_skin));
213       xitk_image_free_image(private_data->imlibdata, &(private_data->bg_skin));
214     }
215 
216     XITK_FREE(private_data->skin_element_name);
217     XITK_FREE(private_data);
218   }
219 }
220 
221 /*
222  *
223  */
get_skin(xitk_widget_t * w,int sk)224 static xitk_image_t *get_skin(xitk_widget_t *w, int sk) {
225   slider_private_data_t *private_data;
226 
227   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
228 
229     private_data = (slider_private_data_t *) w->private_data;
230 
231     if(sk == FOREGROUND_SKIN && private_data->paddle_skin) {
232       return private_data->paddle_skin;
233     }
234     else if(sk == BACKGROUND_SKIN && private_data->bg_skin) {
235       return private_data->bg_skin;
236     }
237   }
238 
239   return NULL;
240 }
241 
242 /*
243  *
244  */
notify_inside(xitk_widget_t * w,int x,int y)245 static int notify_inside(xitk_widget_t *w, int x, int y) {
246   slider_private_data_t *private_data;
247 
248   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
249 
250     private_data = (slider_private_data_t *) w->private_data;
251 
252     if(w->visible == 1) {
253       xitk_image_t *skin;
254 
255       if(private_data->paddle_cover_bg == 1)
256 	skin = private_data->paddle_skin;
257       else
258 	skin = private_data->bg_skin;
259 
260       if(skin->mask)
261 	return xitk_is_cursor_out_mask(private_data->imlibdata->x.disp, w, skin->mask->pixmap, x, y);
262     }
263     else
264       return 0;
265   }
266 
267   return 1;
268 }
269 
270 /*
271  * Draw widget
272  */
paint_slider(xitk_widget_t * w)273 static void paint_slider(xitk_widget_t *w) {
274   int                     button_width, button_height;
275   slider_private_data_t  *private_data;
276   GC                      bgc, pgc;
277   xitk_image_t           *bg;
278   xitk_image_t           *paddle;
279 
280   if(w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER) && w->visible == 1)) {
281     int    x, y, srcx1, srcx2, destx1, srcy1, srcy2, desty1;
282     int    xcenter, ycenter;
283     int    paddle_width;
284     int    paddle_height;
285     double angle;
286 
287     private_data = (slider_private_data_t *) w->private_data;
288     bg = (xitk_image_t *) private_data->bg_skin;
289     paddle = (xitk_image_t *) private_data->paddle_skin;
290 
291     x = y = srcx1 = srcx2 = destx1 = srcy1 = srcy2 = desty1 = 0;
292 
293     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
294     bgc = XCreateGC(private_data->imlibdata->x.disp, bg->image->pixmap, None, None);
295     XCopyGC(private_data->imlibdata->x.disp, w->wl->gc, (1 << GCLastBit) - 1, bgc);
296     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
297 
298     if(bg->mask) {
299       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
300       XSetClipOrigin(private_data->imlibdata->x.disp, bgc, w->x, w->y);
301       XSetClipMask(private_data->imlibdata->x.disp, bgc, bg->mask->pixmap);
302       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
303     }
304 
305     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
306     XCopyArea(private_data->imlibdata->x.disp, bg->image->pixmap, w->wl->win, bgc, 0, 0,
307 	      bg->width, bg->height, w->x, w->y);
308 
309     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
310 
311     if(w->enable == WIDGET_ENABLE) {
312 
313       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
314       pgc = XCreateGC(private_data->imlibdata->x.disp, paddle->image->pixmap, None, None);
315       XCopyGC(private_data->imlibdata->x.disp, w->wl->gc, (1 << GCLastBit) - 1, pgc);
316       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
317 
318       if(private_data->sType == XITK_RSLIDER) {
319 
320 	button_width = private_data->bg_skin->width;
321 	button_height = private_data->bg_skin->height;
322 
323 	xcenter       = (bg->width /2) + w->x;
324 	ycenter       = (bg->width /2) + w->y;
325 	paddle_width  = paddle->width / 3;
326 	paddle_height = paddle->height;
327 	angle         = private_data->angle;
328 
329 	if(angle < M_PI / -2)
330 	  angle = angle + M_PI * 2;
331 
332 	x = (int) (0.5 + xcenter + private_data->radius * cos(angle)) - (paddle_width / 2);
333 	y = (int) (0.5 + ycenter - private_data->radius * sin(angle)) - (paddle_height / 2);
334 
335 	srcx1 = 0;
336 
337 	if((private_data->focus == FOCUS_RECEIVED) || (private_data->focus == FOCUS_MOUSE_IN)) {
338 	  srcx1 += paddle_width;
339 	  if(private_data->bClicked)
340 	    srcx1 += paddle_width;
341 	}
342 
343 	srcy1 = 0;
344 	srcx2 = paddle_width;
345 	srcy2 = paddle_height;
346 	destx1 = x;
347 	desty1 = y;
348 
349       }
350       else {
351 	int   dir_area;
352 	float tmp;
353 
354 	button_width = private_data->button_width;
355 	button_height = paddle->height;
356 
357 	dir_area = (float)(private_data->sType == XITK_HSLIDER) ?
358 	  w->width - button_width : w->height - button_height;
359 
360 	tmp = (dir_area * .01) * (private_data->percentage * 100.0);
361 
362 	if(private_data->sType == XITK_HSLIDER) {
363 	  x = rint(w->x + tmp);
364 	  y = w->y;
365 	}
366 	else if(private_data->sType == XITK_VSLIDER) {
367 	  x = w->x;
368 	  y = rint(w->y + private_data->bg_skin->height - button_height - tmp);
369 	}
370 
371 	if(private_data->paddle_cover_bg == 1) {
372 	  int pixpos;
373 	  int direction;
374 
375 	  x = w->x;
376 	  y = w->y;
377 
378 	  direction = (private_data->sType == XITK_HSLIDER) ?
379 	    private_data->bg_skin->width : private_data->bg_skin->height;
380 
381 	  pixpos = (int)private_data->value /
382 	    ((private_data->upper - private_data->lower) / direction);
383 
384 	  if(private_data->sType == XITK_VSLIDER) {
385 	    pixpos = button_height - pixpos;
386 	    srcx1  = 0;
387 	    srcy1  = pixpos;
388 	    srcx2  = button_width;
389 	    srcy2  = paddle->height - pixpos;
390 	    destx1 = w->x;
391 	    desty1 = w->y + pixpos;
392 	  }
393 	  else if(private_data->sType == XITK_HSLIDER) {
394 	    srcx1  = 0;
395 	    srcy1  = 0;
396 	    srcx2  = pixpos;
397 	    srcy2  = paddle->height;
398 	    destx1 = w->x;
399 	    desty1 = w->y;
400 	  }
401 	}
402 	else {
403 	  srcy1  = 0;
404 	  srcx2  = button_width;
405 	  srcy2  = paddle->height;
406 	  destx1 = x;
407 	  desty1 = y;
408 	}
409 
410 	if((private_data->focus == FOCUS_RECEIVED) || (private_data->focus == FOCUS_MOUSE_IN)) {
411 	  if(private_data->bClicked)
412 	    srcx1 = 2*button_width;
413 	  else
414 	    srcx1 = button_width;
415 	}
416 
417       }
418 
419       if(paddle->mask) {
420         XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
421 	XSetClipOrigin(private_data->imlibdata->x.disp, pgc, x, y);
422 	XSetClipMask(private_data->imlibdata->x.disp, pgc, paddle->mask->pixmap);
423         XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
424       }
425 
426       XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
427       XCopyArea(private_data->imlibdata->x.disp, paddle->image->pixmap, w->wl->win, pgc,
428 		srcx1, srcy1, srcx2, srcy2, destx1, desty1);
429       XFreeGC(private_data->imlibdata->x.disp, pgc);
430       XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
431     }
432 
433     XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
434     XFreeGC(private_data->imlibdata->x.disp, bgc);
435     XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
436   }
437 
438 }
439 
440 /*
441  *
442  */
notify_change_skin(xitk_widget_t * w,xitk_skin_config_t * skonfig)443 static void notify_change_skin(xitk_widget_t *w, xitk_skin_config_t *skonfig) {
444   slider_private_data_t *private_data;
445 
446   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
447 
448     private_data = (slider_private_data_t *) w->private_data;
449 
450     if(private_data->skin_element_name) {
451 
452       xitk_skin_lock(skonfig);
453 
454       private_data->paddle_skin     = xitk_skin_get_image(skonfig, xitk_skin_get_slider_skin_filename(skonfig, private_data->skin_element_name));
455       private_data->button_width    = private_data->paddle_skin->width / 3;
456       private_data->bg_skin         = xitk_skin_get_image(skonfig, xitk_skin_get_skin_filename(skonfig, private_data->skin_element_name));
457       private_data->sType = xitk_skin_get_slider_type(skonfig, private_data->skin_element_name);
458       private_data->paddle_cover_bg = 0;
459 
460       if(private_data->sType == XITK_HSLIDER) {
461 	if(private_data->button_width == private_data->bg_skin->width)
462 	  private_data->paddle_cover_bg = 1;
463       }
464       else if(private_data->sType == XITK_VSLIDER) {
465 	if(private_data->paddle_skin->height == private_data->bg_skin->height)
466 	  private_data->paddle_cover_bg = 1;
467       }
468 
469       private_data->radius = xitk_skin_get_slider_radius(skonfig, private_data->skin_element_name);
470 
471       w->x       = xitk_skin_get_coord_x(skonfig, private_data->skin_element_name);
472       w->y       = xitk_skin_get_coord_y(skonfig, private_data->skin_element_name);
473       w->width   = private_data->bg_skin->width;
474       w->height  = private_data->bg_skin->height;
475       w->visible = (xitk_skin_get_visibility(skonfig, private_data->skin_element_name)) ? 1 : -1;
476       w->enable  = xitk_skin_get_enability(skonfig, private_data->skin_element_name);
477 
478       xitk_skin_unlock(skonfig);
479 
480       xitk_set_widget_pos(w, w->x, w->y);
481     }
482   }
483 }
484 
485 /*
486  * Got click
487  */
notify_click_slider(xitk_widget_t * w,int button,int bUp,int x,int y)488 static int notify_click_slider(xitk_widget_t *w, int button, int bUp, int x, int y) {
489   slider_private_data_t *private_data;
490   int                    ret = 0;
491 
492   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
493     if(button == Button1) {
494       private_data = (slider_private_data_t *) w->private_data;
495 
496       if(private_data->focus == FOCUS_RECEIVED) {
497 	int old_value = (int) private_data->value;
498 
499 	slider_update(w, (x - w->x), (y - w->y));
500 
501 	if(private_data->bClicked == bUp)
502 	  private_data->bClicked = !bUp;
503 
504 	if(bUp == 0) {
505 
506 	  if(old_value != ((int) private_data->value))
507 	    slider_update_value(w, private_data->value);
508 
509 	  paint_slider(w);
510 
511 	  /*
512 	   * Exec motion callback function (if available)
513 	   */
514 	  if(old_value != ((int) private_data->value)) {
515 	    if(private_data->motion_callback)
516 	      private_data->motion_callback(private_data->sWidget,
517 					    private_data->motion_userdata,
518 					    (int) private_data->value);
519 	  }
520 
521 	}
522 	else if(bUp == 1) {
523 	  private_data->bClicked = 0;
524 
525 	  slider_update_value(w, private_data->value);
526 	  paint_slider(w);
527 
528 	  if(private_data->callback) {
529 	    private_data->callback(private_data->sWidget,
530 				   private_data->userdata,
531 				   (int) private_data->value);
532 	  }
533 	}
534       }
535       ret = 1;
536     }
537   }
538 
539   return ret;
540 }
541 
542 /*
543  * Got focus
544  */
notify_focus_slider(xitk_widget_t * w,int focus)545 static int notify_focus_slider(xitk_widget_t *w, int focus) {
546   slider_private_data_t *private_data;
547 
548   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
549     private_data = (slider_private_data_t *) w->private_data;
550     if(!private_data->bClicked)
551       private_data->focus = focus;
552   }
553 
554   return 1;
555 }
556 
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)557 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
558   int retval = 0;
559 
560   switch(event->type) {
561   case WIDGET_EVENT_PAINT:
562     paint_slider(w);
563     break;
564   case WIDGET_EVENT_CLICK:
565     result->value = notify_click_slider(w, event->button,
566 					event->button_pressed, event->x, event->y);
567     retval = 1;
568     break;
569   case WIDGET_EVENT_FOCUS:
570     notify_focus_slider(w, event->focus);
571     break;
572   case WIDGET_EVENT_INSIDE:
573     result->value = notify_inside(w, event->x, event->y);
574     retval = 1;
575     break;
576   case WIDGET_EVENT_CHANGE_SKIN:
577     notify_change_skin(w, event->skonfig);
578     break;
579   case WIDGET_EVENT_DESTROY:
580     notify_destroy(w);
581     break;
582   case WIDGET_EVENT_GET_SKIN:
583     if(result) {
584       result->image = get_skin(w, event->skin_layer);
585       retval = 1;
586     }
587     break;
588   }
589 
590   return retval;
591 }
592 
593 /*
594  * Increment position
595  */
xitk_slider_make_step(xitk_widget_t * w)596 void xitk_slider_make_step(xitk_widget_t *w) {
597   slider_private_data_t *private_data;
598 
599   if (w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
600     private_data = (slider_private_data_t *) w->private_data;
601     if(!private_data->bClicked) {
602       if(((xitk_slider_get_pos(w)) + private_data->step) <= (xitk_slider_get_max(w)))
603 	xitk_slider_set_pos(w, xitk_slider_get_pos(w) + private_data->step);
604     }
605   }
606 
607 }
608 
609 /*
610  * Decrement position
611  */
xitk_slider_make_backstep(xitk_widget_t * w)612 void xitk_slider_make_backstep(xitk_widget_t *w) {
613   slider_private_data_t *private_data;
614 
615   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
616     private_data = (slider_private_data_t *) w->private_data;
617     if(!private_data->bClicked) {
618       if(((xitk_slider_get_pos(w)) - private_data->step) >= (xitk_slider_get_min(w)))
619 	xitk_slider_set_pos(w, xitk_slider_get_pos(w) - private_data->step);
620     }
621 
622   }
623 
624 }
625 
626 /*
627  * Set value MIN.
628  */
xitk_slider_set_min(xitk_widget_t * w,int min)629 void xitk_slider_set_min(xitk_widget_t *w, int min) {
630   slider_private_data_t *private_data;
631 
632   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
633     private_data = (slider_private_data_t *) w->private_data;
634     slider_update_minmax(w, (float)((min == private_data->upper)
635 				    ? min - 1 : min), private_data->upper);
636   }
637 }
638 
639 /*
640  * Return the MIN value
641  */
xitk_slider_get_min(xitk_widget_t * w)642 int xitk_slider_get_min(xitk_widget_t *w) {
643   slider_private_data_t *private_data;
644 
645   if((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER) {
646     private_data = (slider_private_data_t *) w->private_data;
647     return (int) private_data->lower;
648   }
649 
650   return -1;
651 }
652 
653 /*
654  * Return the MAX value
655  */
xitk_slider_get_max(xitk_widget_t * w)656 int xitk_slider_get_max(xitk_widget_t *w) {
657   slider_private_data_t *private_data;
658 
659   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
660     private_data = (slider_private_data_t *) w->private_data;
661     return (int) private_data->upper;
662   }
663 
664   return -1;
665 }
666 
667 /*
668  * Set value MAX
669  */
xitk_slider_set_max(xitk_widget_t * w,int max)670 void xitk_slider_set_max(xitk_widget_t *w, int max) {
671   slider_private_data_t *private_data;
672 
673   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
674     private_data = (slider_private_data_t *) w->private_data;
675     slider_update_minmax(w, private_data->lower, (float)((max == private_data->lower)
676 							 ? max + 1 : max));
677   }
678 }
679 
680 /*
681  * Set pos to 0 and redraw the widget.
682  */
xitk_slider_reset(xitk_widget_t * w)683 void xitk_slider_reset(xitk_widget_t *w) {
684   slider_private_data_t *private_data;
685 
686   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
687     private_data = (slider_private_data_t *) w->private_data;
688     slider_update_value(w, 0.0);
689     private_data->bClicked = 0;
690     paint_slider(w);
691   }
692 }
693 
694 /*
695  * Set pos to max and redraw the widget.
696  */
xitk_slider_set_to_max(xitk_widget_t * w)697 void xitk_slider_set_to_max(xitk_widget_t *w) {
698   slider_private_data_t *private_data;
699 
700   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
701     private_data = (slider_private_data_t *) w->private_data;
702     if(!private_data->bClicked) {
703       slider_update_value(w, private_data->upper);
704       paint_slider(w);
705     }
706   }
707 }
708 
709 /*
710  * Return current position.
711  */
xitk_slider_get_pos(xitk_widget_t * w)712 int xitk_slider_get_pos(xitk_widget_t *w) {
713   slider_private_data_t *private_data;
714 
715   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
716     private_data = (slider_private_data_t *) w->private_data;
717     return (int) private_data->value;
718   }
719 
720   return -1;
721 }
722 
723 /*
724  * Set position.
725  */
xitk_slider_set_pos(xitk_widget_t * w,int pos)726 void xitk_slider_set_pos(xitk_widget_t *w, int pos) {
727   slider_private_data_t *private_data;
728 
729   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
730     float value = (float) pos;
731 
732     private_data = (slider_private_data_t *) w->private_data;
733 
734     if(!private_data->bClicked) {
735       if(value >= private_data->lower && value <= private_data->upper) {
736 	slider_update_value(w, value);
737 	paint_slider(w);
738       }
739     }
740 
741   }
742 }
743 
744 /*
745  * Call callback for current position
746  */
xitk_slider_callback_exec(xitk_widget_t * w)747 void xitk_slider_callback_exec(xitk_widget_t *w) {
748   slider_private_data_t *private_data;
749 
750   if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_SLIDER)) {
751     private_data = (slider_private_data_t *) w->private_data;
752 
753     if(private_data->callback) {
754       private_data->callback(private_data->sWidget,
755 			     private_data->userdata,
756 			     (int) private_data->value);
757     }
758     else {
759 
760       if(private_data->motion_callback) {
761 	private_data->motion_callback(private_data->sWidget,
762 				      private_data->motion_userdata,
763 				      (int) private_data->value);
764       }
765 
766     }
767   }
768 }
769 
770 /*
771  * Create the widget
772  */
_xitk_slider_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_slider_widget_t * s,int x,int y,const char * skin_element_name,xitk_image_t * bg_skin,xitk_image_t * pad_skin,int stype,int radius,int visible,int enable)773 static xitk_widget_t *_xitk_slider_create(xitk_widget_list_t *wl,
774 					  xitk_skin_config_t *skonfig, xitk_slider_widget_t *s,
775 					  int x, int y, const char *skin_element_name,
776 					  xitk_image_t *bg_skin, xitk_image_t *pad_skin,
777 					  int stype, int radius, int visible, int enable) {
778   xitk_widget_t           *mywidget;
779   slider_private_data_t   *private_data;
780 
781   mywidget = (xitk_widget_t *) xitk_xmalloc (sizeof(xitk_widget_t));
782 
783   private_data = (slider_private_data_t *) xitk_xmalloc (sizeof (slider_private_data_t));
784 
785   private_data->imlibdata                = s->imlibdata;
786   private_data->skin_element_name        = (skin_element_name == NULL) ? NULL : strdup(s->skin_element_name);
787 
788   private_data->sWidget                  = mywidget;
789   private_data->sType                    = stype;
790   private_data->bClicked                 = 0;
791   private_data->focus                    = FOCUS_LOST;
792 
793   private_data->angle                    = 0.0;
794 
795   private_data->upper                    = (float)((s->min == s->max) ? s->max + 1 : s->max);
796   private_data->lower                    = (float)s->min;
797 
798   private_data->value                    = 0.0;
799   private_data->percentage               = 0.0;
800   private_data->radius                   = radius;
801 
802   private_data->step                     = s->step;
803 
804   private_data->paddle_skin              = pad_skin;
805   private_data->button_width             = private_data->paddle_skin->width / 3;
806 
807   private_data->bg_skin                  = bg_skin;
808 
809   private_data->paddle_cover_bg          = 0;
810   if(private_data->sType == XITK_HSLIDER) {
811     if(private_data->button_width == private_data->bg_skin->width)
812       private_data->paddle_cover_bg = 1;
813   }
814   else if(private_data->sType == XITK_VSLIDER) {
815     if(private_data->paddle_skin->height == private_data->bg_skin->height)
816       private_data->paddle_cover_bg = 1;
817   }
818 
819   private_data->motion_callback          = s->motion_callback;
820   private_data->motion_userdata          = s->motion_userdata;
821   private_data->callback                 = s->callback;
822   private_data->userdata                 = s->userdata;
823 
824   mywidget->private_data                 = private_data;
825 
826   mywidget->wl                           = wl;
827 
828   mywidget->enable                       = enable;
829   mywidget->running                      = 1;
830   mywidget->visible                      = visible;
831   mywidget->have_focus                   = FOCUS_LOST;
832   mywidget->imlibdata                    = private_data->imlibdata;
833   mywidget->x                            = x;
834   mywidget->y                            = y;
835   mywidget->width                        = private_data->bg_skin->width;
836   mywidget->height                       = private_data->bg_skin->height;
837   mywidget->type                         = WIDGET_TYPE_SLIDER | WIDGET_FOCUSABLE | WIDGET_CLICKABLE | WIDGET_KEYABLE;
838   mywidget->event                        = notify_event;
839   mywidget->tips_timeout                 = 0;
840   mywidget->tips_string                  = NULL;
841 
842   return mywidget;
843 }
844 
845 /*
846  * Create the widget
847  */
xitk_slider_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_slider_widget_t * s)848 xitk_widget_t *xitk_slider_create(xitk_widget_list_t *wl,
849 				  xitk_skin_config_t *skonfig, xitk_slider_widget_t *s) {
850 
851   XITK_CHECK_CONSTITENCY(s);
852 
853   return _xitk_slider_create(wl, skonfig, s,
854 			     (xitk_skin_get_coord_x(skonfig, s->skin_element_name)),
855 			     (xitk_skin_get_coord_y(skonfig, s->skin_element_name)),
856 			     s->skin_element_name,
857 			     (xitk_skin_get_image(skonfig,
858 						  xitk_skin_get_skin_filename(skonfig, s->skin_element_name))),
859 			     (xitk_skin_get_image(skonfig,
860 						  xitk_skin_get_slider_skin_filename(skonfig, s->skin_element_name))),
861 			     (xitk_skin_get_slider_type(skonfig, s->skin_element_name)),
862 			     (xitk_skin_get_slider_radius(skonfig, s->skin_element_name)),
863 			     ((xitk_skin_get_visibility(skonfig, s->skin_element_name)) ? 1 : -1),
864 			     (xitk_skin_get_enability(skonfig, s->skin_element_name)));
865 }
866 
867 /*
868  * Create the widget (not skined).
869  */
xitk_noskin_slider_create(xitk_widget_list_t * wl,xitk_slider_widget_t * s,int x,int y,int width,int height,int type)870 xitk_widget_t *xitk_noskin_slider_create(xitk_widget_list_t *wl,
871 					 xitk_slider_widget_t *s,
872 					 int x, int y, int width, int height, int type) {
873   xitk_image_t   *b, *p;
874   int             radius;
875 
876   XITK_CHECK_CONSTITENCY(s);
877 
878   if(type == XITK_VSLIDER)
879     p = xitk_image_create_image(s->imlibdata, width * 3, height / 5);
880   else if(type == XITK_HSLIDER)
881     p = xitk_image_create_image(s->imlibdata, (width / 5) * 3, height);
882   else if(type == XITK_RSLIDER) {
883     int w;
884 
885     w = ((((width + height) >> 1) >> 1) / 10) * 3;
886     p = xitk_image_create_image(s->imlibdata, (w * 3), w);
887   }
888   else
889     XITK_DIE("Slider type unhandled.\n");
890 
891   xitk_image_add_mask(s->imlibdata, p);
892   if(type == XITK_VSLIDER)
893     draw_paddle_three_state_vertical(s->imlibdata, p);
894   else if(type == XITK_HSLIDER)
895     draw_paddle_three_state_horizontal(s->imlibdata, p);
896   else if(type == XITK_RSLIDER) {
897     draw_paddle_rotate(s->imlibdata, p);
898   }
899 
900   b = xitk_image_create_image(s->imlibdata, width, height);
901   xitk_image_add_mask(s->imlibdata, b);
902   if((type == XITK_HSLIDER) || (type == XITK_VSLIDER))
903     draw_inner(s->imlibdata, b->image, width, height);
904   else if(type == XITK_RSLIDER) {
905     draw_rotate_button(s->imlibdata, b);
906   }
907 
908   radius = (b->height >> 1) - (p->height);
909 
910   return _xitk_slider_create(wl,NULL, s, x, y, NULL, b, p, type, radius, 0, 0);
911 }
912