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 static void tabs_arrange(xitk_widget_t *);
31
32 /*
33 *
34 */
enability(xitk_widget_t * w)35 static void enability(xitk_widget_t *w) {
36
37 if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_TABS) &&
38 (w->type & WIDGET_GROUP_WIDGET))) {
39 tabs_private_data_t *private_data = (tabs_private_data_t *) w->private_data;
40 int i;
41
42 if(w->enable == WIDGET_ENABLE) {
43 xitk_enable_and_show_widget(private_data->left);
44 xitk_enable_and_show_widget(private_data->right);
45 for(i = 0; i < private_data->num_entries; i++)
46 xitk_enable_widget(private_data->tabs[i]);
47 }
48 else {
49 xitk_disable_widget(private_data->left);
50 xitk_disable_widget(private_data->right);
51 for(i = 0; i < private_data->num_entries; i++) {
52 xitk_disable_widget(private_data->tabs[i]);
53 }
54 }
55 }
56 }
57
notify_destroy(xitk_widget_t * w)58 static void notify_destroy(xitk_widget_t *w) {
59 tabs_private_data_t *private_data;
60
61 if(w && (((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_TABS) &&
62 (w->type & WIDGET_GROUP_WIDGET))) {
63 int i;
64
65 private_data = (tabs_private_data_t *) w->private_data;
66
67 for(i = 0; i <= private_data->num_entries; i++)
68 XITK_FREE(private_data->bt[i]);
69
70 XITK_FREE(private_data->skin_element_name);
71 XITK_FREE(private_data);
72 }
73 }
74
75 /*
76 *
77 */
tabs_arrange(xitk_widget_t * w)78 static void tabs_arrange(xitk_widget_t *w) {
79 tabs_private_data_t *private_data;
80
81 if(w && ((((w->type & WIDGET_GROUP_MASK) & WIDGET_GROUP_TABS) &&
82 (w->type & WIDGET_GROUP_WIDGET)) && w->visible == 1)) {
83 int i = 0, width, x;
84
85 private_data = (tabs_private_data_t*) w->private_data;
86
87 if(private_data->offset != private_data->old_offset) {
88
89 for(i = 0; i < private_data->num_entries; i++)
90 xitk_hide_widget(private_data->tabs[i]);
91
92 i = private_data->offset;
93 width = 0;
94 x = private_data->x;
95
96 do {
97 if((width + xitk_get_widget_width(private_data->tabs[i])) <= private_data->width - 40) {
98 xitk_set_widget_pos(private_data->tabs[i], x, private_data->y);
99 width += xitk_get_widget_width(private_data->tabs[i]);
100 x += xitk_get_widget_width(private_data->tabs[i]);
101 xitk_show_widget(private_data->tabs[i]);
102 }
103 else
104 break;
105
106 i++;
107
108 } while((i < private_data->num_entries) && (width < (private_data->width - 40)));
109 private_data->gap_widthstart = width;
110 }
111 /*
112 * Fill gap
113 */
114 if((((private_data->width - 40) - private_data->gap_widthstart) * 3) > 0) {
115 xitk_image_t *p;
116 GC gc;
117 XGCValues gcv;
118
119 p = xitk_image_create_image(private_data->imlibdata,
120 ((private_data->width - 40) - private_data->gap_widthstart) * 3,
121 private_data->bheight>>1);
122
123 if(p) {
124 gcv.graphics_exposures = False;
125
126 draw_flat(private_data->imlibdata, p->image, p->width, p->height);
127
128 XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
129 gc = XCreateGC(private_data->imlibdata->x.disp,
130 p->image->pixmap, GCGraphicsExposures, &gcv);
131 XCopyArea(private_data->imlibdata->x.disp,
132 p->image->pixmap, private_data->parent_wlist->win, gc,
133 0, 0, p->width/3, p->height,
134 private_data->x + private_data->gap_widthstart, private_data->y);
135 XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
136
137 draw_tab(private_data->imlibdata, p);
138
139 XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
140 XCopyArea(private_data->imlibdata->x.disp,
141 p->image->pixmap, private_data->parent_wlist->win, gc,
142 0, 0, p->width/3, p->height,
143 private_data->x + private_data->gap_widthstart, private_data->y + p->height);
144 XFreeGC(private_data->imlibdata->x.disp, gc);
145 XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
146
147 xitk_image_free_image(private_data->imlibdata, &p);
148 }
149 }
150
151 if(private_data->offset != private_data->old_offset) {
152 if(i < private_data->num_entries)
153 xitk_start_widget(private_data->right);
154 else
155 xitk_stop_widget(private_data->right);
156
157 if(private_data->offset == 0)
158 xitk_stop_widget(private_data->left);
159 else
160 xitk_start_widget(private_data->left);
161 }
162
163 private_data->old_offset = private_data->offset;
164 }
165 }
166
167 /*
168 *
169 */
paint(xitk_widget_t * w)170 static void paint(xitk_widget_t *w) {
171
172 if(w && (((w->type & WIDGET_GROUP_MASK) == WIDGET_GROUP_TABS) &&
173 (w->type & WIDGET_GROUP_WIDGET))) {
174
175 if(w->visible == 1) {
176 tabs_arrange(w);
177 }
178 }
179 }
180
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)181 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
182 int retval = 0;
183
184 switch(event->type) {
185 case WIDGET_EVENT_PAINT:
186 paint(w);
187 break;
188 case WIDGET_EVENT_DESTROY:
189 notify_destroy(w);
190 break;
191 case WIDGET_EVENT_ENABLE:
192 enability(w);
193 break;
194 }
195
196 return retval;
197 }
198
199 /*
200 *
201 */
tabs_select(xitk_widget_t * w,void * data,int select)202 static void tabs_select(xitk_widget_t *w, void *data, int select) {
203 tabs_private_data_t *private_data = (tabs_private_data_t*) ((btnlist_t*)data)->itemlist->private_data;
204
205 if(select) {
206 private_data->old_selected = private_data->selected;
207 private_data->selected = (int)((btnlist_t*)data)->sel;
208
209 xitk_labelbutton_set_state(private_data->tabs[private_data->old_selected], 0);
210
211
212 // tabs_arrange(private_data->widget);
213 if(private_data->callback)
214 private_data->callback(private_data->widget, private_data->userdata, private_data->selected);
215 }
216 else {
217 xitk_labelbutton_set_state(private_data->tabs[private_data->selected], 1);
218 }
219
220 }
221
222 /*
223 *
224 */
tabs_select_prev(xitk_widget_t * w,void * data)225 static void tabs_select_prev(xitk_widget_t *w, void *data) {
226 xitk_widget_t *t = (xitk_widget_t *)data;
227 tabs_private_data_t *private_data = (tabs_private_data_t*)t->private_data;
228
229 if(private_data->offset > 0) {
230 private_data->old_offset = private_data->offset;
231 private_data->offset--;
232 tabs_arrange(private_data->widget);
233 }
234 }
235
236 /*
237 *
238 */
tabs_select_next(xitk_widget_t * w,void * data)239 static void tabs_select_next(xitk_widget_t *w, void *data) {
240 xitk_widget_t *t = (xitk_widget_t *)data;
241 tabs_private_data_t *private_data = (tabs_private_data_t*)t->private_data;
242
243 if(private_data->offset < (private_data->num_entries - 1)) {
244 private_data->old_offset = private_data->offset;
245 private_data->offset++;
246 tabs_arrange(private_data->widget);
247 }
248 }
249
250 /*
251 *
252 */
xitk_tabs_set_current_selected(xitk_widget_t * w,int select)253 void xitk_tabs_set_current_selected(xitk_widget_t *w, int select) {
254 tabs_private_data_t *private_data;
255
256 if(!w)
257 XITK_WARNING("%s(): widget is NULL\n", __FUNCTION__);
258
259 if(w && (((w->type & WIDGET_GROUP_MASK) == WIDGET_GROUP_TABS) &&
260 (w->type & WIDGET_GROUP_WIDGET))) {
261
262 private_data = (tabs_private_data_t*)w->private_data;
263
264 if(select <= private_data->num_entries) {
265 private_data->old_selected = private_data->selected;
266 private_data->selected = select;
267 tabs_arrange(w);
268 }
269
270 }
271 }
272
273 /*
274 *
275 */
xitk_tabs_get_current_selected(xitk_widget_t * w)276 int xitk_tabs_get_current_selected(xitk_widget_t *w) {
277 tabs_private_data_t *private_data;
278
279 if(!w) {
280 XITK_WARNING("%s(): widget is NULL\n", __FUNCTION__);
281 return -1;
282 }
283
284 if(((w->type & WIDGET_GROUP_MASK) == WIDGET_GROUP_TABS) &&
285 (w->type & WIDGET_GROUP_WIDGET)) {
286
287 private_data = (tabs_private_data_t*)w->private_data;
288 return (private_data->selected);
289 }
290
291
292 return -1;
293 }
294
295 /*
296 *
297 */
xitk_tabs_get_current_tab_selected(xitk_widget_t * w)298 const char *xitk_tabs_get_current_tab_selected(xitk_widget_t *w) {
299 tabs_private_data_t *private_data;
300
301 if(!w) {
302 XITK_WARNING("%s(): widget is NULL\n", __FUNCTION__);
303 return NULL;
304 }
305
306 if(((w->type & WIDGET_GROUP_MASK) == WIDGET_GROUP_TABS) &&
307 (w->type & WIDGET_GROUP_WIDGET)) {
308
309 private_data = (tabs_private_data_t*)w->private_data;
310 return ((xitk_labelbutton_get_label(private_data->tabs[private_data->selected])));
311 }
312
313 return NULL;
314 }
315
316 /*
317 *
318 */
xitk_noskin_tabs_create(xitk_widget_list_t * wl,xitk_tabs_widget_t * t,int x,int y,int width,const char * fontname)319 xitk_widget_t *xitk_noskin_tabs_create(xitk_widget_list_t *wl,
320 xitk_tabs_widget_t *t,
321 int x, int y, int width,
322 const char *fontname) {
323 xitk_widget_t *mywidget;
324 tabs_private_data_t *private_data;
325
326 XITK_CHECK_CONSTITENCY(t);
327
328 if((t->entries == NULL) || (t->num_entries == 0))
329 XITK_DIE("%s(): entries should be non NULL.\n", __FUNCTION__);
330
331 mywidget = (xitk_widget_t *) xitk_xmalloc(sizeof(xitk_widget_t));
332 private_data = (tabs_private_data_t *) xitk_xmalloc(sizeof(tabs_private_data_t));
333
334 private_data->imlibdata = t->imlibdata;
335 private_data->widget = mywidget;
336
337 private_data->entries = t->entries;
338 private_data->num_entries = t->num_entries;
339
340 private_data->parent_wlist = t->parent_wlist;
341
342 private_data->x = x;
343 private_data->y = y;
344 private_data->width = width;
345
346 private_data->callback = t->callback;
347 private_data->userdata = t->userdata;
348
349 private_data->skin_element_name = (t->skin_element_name == NULL) ? NULL : strdup(t->skin_element_name);
350
351 {
352 xitk_font_t *fs;
353 int fwidth, fheight, i;
354 xitk_labelbutton_widget_t lb;
355 xitk_button_widget_t b;
356 int xx = x;
357
358 fs = xitk_font_load_font(t->imlibdata->x.disp, fontname);
359
360 xitk_font_set_font(fs, t->parent_wlist->gc);
361 fheight = xitk_font_get_string_height(fs, " ");
362
363 XITK_WIDGET_INIT(&lb, t->imlibdata);
364 XITK_WIDGET_INIT(&b, t->imlibdata);
365
366 private_data->bheight = fheight + 18;
367
368 for(i = 0; i < t->num_entries; i++) {
369
370 private_data->bt[i] = (btnlist_t *) xitk_xmalloc(sizeof(btnlist_t));
371 private_data->bt[i]->itemlist = mywidget;
372 private_data->bt[i]->sel = i;
373
374 fwidth = xitk_font_get_string_length(fs, t->entries[i]);
375
376 lb.skin_element_name = NULL;
377 lb.button_type = RADIO_BUTTON;
378 lb.align = ALIGN_CENTER;
379 lb.label = t->entries[i];
380 lb.callback = NULL;
381 lb.state_callback = tabs_select;
382 lb.userdata = (void *) (private_data->bt[i]);
383 private_data->tabs[i] = xitk_noskin_labelbutton_create (t->parent_wlist, &lb, xx, y, fwidth + 20,
384 private_data->bheight, "Black", "Black", "Black", fontname);
385 xitk_dlist_add_tail (&t->parent_wlist->list, &private_data->tabs[i]->node);
386 private_data->tabs[i]->type |= WIDGET_GROUP | WIDGET_GROUP_TABS;
387 xx += fwidth + 20;
388
389 xitk_hide_widget(private_data->tabs[i]);
390 draw_tab(t->imlibdata, (xitk_get_widget_foreground_skin(private_data->tabs[i])));
391
392 }
393
394 /*
395 Add left/rigth arrows
396 */
397 {
398 xitk_image_t *wimage;
399
400 b.skin_element_name = NULL;
401 b.callback = tabs_select_prev;
402 b.userdata = (void *)mywidget;
403 private_data->left = xitk_noskin_button_create (t->parent_wlist, &b, (private_data->x + width) - 40,
404 (y-1) + (private_data->bheight - 20), 20, 20);
405 xitk_dlist_add_tail (&t->parent_wlist->list, &private_data->left->node);
406 private_data->left->type |= WIDGET_GROUP | WIDGET_GROUP_TABS;
407
408 wimage = xitk_get_widget_foreground_skin(private_data->left);
409 if(wimage)
410 draw_arrow_left(t->imlibdata, wimage);
411
412 xx += 20;
413 b.skin_element_name = NULL;
414 b.callback = tabs_select_next;
415 b.userdata = (void *)mywidget;
416 private_data->right = xitk_noskin_button_create (t->parent_wlist, &b, (private_data->x + width) - 20,
417 (y-1) + (private_data->bheight - 20), 20, 20);
418 xitk_dlist_add_tail (&t->parent_wlist->list, &private_data->right->node);
419 private_data->right->type |= WIDGET_GROUP | WIDGET_GROUP_TABS;
420
421 wimage = xitk_get_widget_foreground_skin(private_data->right);
422 if(wimage)
423 draw_arrow_right(t->imlibdata, wimage);
424
425 }
426
427 private_data->old_selected = private_data->selected = 0;
428 private_data->offset = 0;
429 private_data->old_offset = -2;
430
431 xitk_font_unload_font(fs);
432 }
433
434 mywidget->private_data = private_data;
435
436 mywidget->wl = wl;
437
438 mywidget->enable = 1;
439 mywidget->running = 0;
440 mywidget->visible = 0;
441
442 mywidget->have_focus = FOCUS_LOST;
443 mywidget->imlibdata = private_data->imlibdata;
444 mywidget->x = mywidget->y = 0;
445 mywidget->width = private_data->width;
446 mywidget->height = private_data->bheight;
447 mywidget->type = WIDGET_GROUP | WIDGET_GROUP_WIDGET | WIDGET_GROUP_TABS;
448 mywidget->event = notify_event;
449 mywidget->tips_timeout = 0;
450 mywidget->tips_string = NULL;
451
452 xitk_labelbutton_set_state(private_data->tabs[private_data->selected], 1);
453
454 return mywidget;
455 }
456