1 // widget-helper.c
2 // LiVES
3 // (c) G. Finch 2012 - 2020 <salsaman+lives@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING or www.gnu.org for licensing details
6
7 #define NEED_DEF_WIDGET_OPTS
8
9 #include "main.h"
10
11 // The idea here is to replace toolkit specific functions with generic ones
12
13 // TODO - replace as much code in the other files with these functions as possible
14
15 // TODO - add for other toolkits, e.g. qt
16
17 // static defns
18
19 #define EV_LIM 64
20
21 static void set_child_colour_internal(LiVESWidget *, livespointer set_allx);
22 static void set_child_alt_colour_internal(LiVESWidget *, livespointer set_allx);
23 static boolean governor_loop(livespointer data) GNU_RETURNS_TWICE;
24 static void async_sig_handler(livespointer instance, livespointer data);
25
26 typedef void (*bifunc)(livespointer, livespointer);
27 typedef boolean(*trifunc)(livespointer, livespointer, livespointer);
28 static void sigdata_free(livespointer, LiVESWidgetClosure *);
29
30 static boolean show_css = FALSE;
31
32 #ifdef GUI_GTK
33 boolean set_css_value_direct(LiVESWidget *, LiVESWidgetState state, const char *selector,
34 const char *detail, const char *value);
35 #endif
36
37 #define NSLEEP_TIME 500
38
39 /// internal data keys
40 #define STD_KEY "_wh_is_standard"
41 #define BACCL_GROUP_KEY "_wh_baccl_group"
42 #define BACCL_ACCL_KEY "_wh_baccl_accl"
43 #define TTIPS_KEY "_wh_lives_tooltips"
44 #define TTIPS_OVERRIDE_KEY "_wh_lives_tooltips_override"
45 #define TTIPS_HIDE_KEY "_wh_lives_tooltips_hide"
46 #define HAS_TTIPS_IMAGE_KEY "_wh_has_ttips_image"
47 #define TTIPS_IMAGE_KEY "_wh_ttips_image"
48 #define WARN_IMAGE_KEY "_wh_warn_image"
49 #define SHOWALL_OVERRIDE_KEY "_wh_lives_showall_override"
50 #define SHOWHIDE_CONTROLLER_KEY "_wh_lives_showhide_controller"
51 #define ROWS_KEY "_wh_rows"
52 #define COLS_KEY "_wh_cols"
53 #define CDEF_KEY "_wh_current_default"
54 #define DEFBUTTON_KEY "_wh_default_button"
55 #define DEFOVERRIDE_KEY "_wh_default_override"
56 #define EXP_LIST_KEY "_wh_expansion_list"
57 #define LROW_KEY "_wh_layout_row"
58 #define EXPANSION_KEY "_wh_expansion"
59 #define JUST_KEY "_wh_justification"
60 #define WADDED_KEY "_wh_widgets_added"
61 #define NWIDTH_KEY "_wh_normal_width"
62 #define FBUTT_KEY "_wh_first_button"
63 #define ISLOCKED_KEY "_wh_is_locked"
64 #define CBUTTON_KEY "_wh_cbutton"
65 #define SPRED_KEY "_wh_sp_red"
66 #define SPGREEN_KEY "_wh_sp_green"
67 #define SPBLUE_KEY "_wh_sp_blue"
68 #define SPALPHA_KEY "_wh_sp_alpha"
69 #define THEME_KEY "_wh_theme"
70
71 #define SBUTT_SURFACE_KEY "_sbutt_surf"
72 #define SBUTT_TXT_KEY "_sbutt_txt"
73 #define SBUTT_LAYOUT_KEY "_sbutt_layout"
74 #define SBUTT_LW_KEY "_sbutt_lw"
75 #define SBUTT_LH_KEY "_sbutt_lh"
76 #define SBUTT_PIXBUF_KEY "_sbutt_pixbuf"
77 #define SBUTT_FORCEIMG_KEY "_sbutt_forceimg"
78 #define SBUTT_FAKEDEF_KEY "_sbutt_fakedef"
79
80 static LiVESWindow *modalw = NULL;
81
82 #if 0
83 weed_plant_t *LiVESWidgetObject_to_weed_plant(LiVESWidgetObject *o) {
84 int nprops;
85 GParamSpec **pspec;
86 GObjectClass oclass;
87 weed_plant_t *plant;
88
89 if (!o || !G_IS_OBJECT(o)) return NULL;
90
91 plant = weed_plant_new(WEED_PLANT_LIVES);
92 weed_set_int_value(plant, WEED_LEAF_LIVES_SUBTYPE, LIVES_WEED_SUBTYPE_WIDGET);
93
94 oclass = G_OBJECT_GET_CLASS(o);
95
96 // get all the properties
97 pspec = g_object_class_list_properties(oclass, &nprops);
98 // also g_object_interface_list_properties
99
100 if (nprops > 0) {
101 GType gtype;
102 weed_plant_t **params = (weed_plant_t **)lives_malloc(nprops * sizeof(weed_plant_t *));
103 for (i = 0; i < nprops; i++) {
104 // check pspec[i]->flags (G_PARAM_READABLE, G_PARAM_WRITABLE...)
105 // if (!G_PARAM_EXPLICIT_NOTIFY), we can hook to the notify signal to shadow it
106 //
107
108 params[i] = weed_plant_new(WEED_PLANT_PARAMETER);
109 weed_set_string_value(params[i], WEED_LEAF_NAME, g_param_spec_get_name(pspec[i]));
110 gtype = G_PARAM_SPEC_VALUE_TYPE(pspec[i]);
111 switch (gtype) {
112 case G_TYPE_STRING:
113 case G_TYPE_CHAR:
114 case G_TYPE_UCHAR:
115 // WEED_SEED_STRING
116 break;
117 case G_TYPE_FLOAT:
118 case G_TYPE_DOUBLE:
119 // WEED_SEED_DOUBLE
120 break;
121 case G_TYPE_INT:
122 case G_TYPE_FLAGS:
123 case G_TYPE_ENUM:
124 case G_TYPE_UINT: {
125 int ival;
126 g_object_get(o, name, &ival, NULL);
127 //g_object_set(o, name, ival, NULL);
128 weed_set_int_value(params[i], WEED_LEAF_VALUE, ival);
129 break;
130 }
131 case G_TYPE_BOOLEAN:
132 // WEED_SEED_BOOLEAN
133 break;
134 case G_TYPE_INT64:
135 case G_TYPE_UINT64:
136 case G_TYPE_LONG:
137 case G_TYPE_ULONG:
138 // WEED_SEED_INT64
139 break;
140 case G_TYPE_POINTER:
141 // WEED_SEED_VOIDPTR
142 break;
143 default:
144 break;
145 }
146 }
147 params[num_params] = NULL;
148 weed_set_plantptr_array(plant, WEED_LEAF_IN_PARAMETERS, nprops, params);
149 }
150 }
151 #endif
152
153
is_standard_widget(LiVESWidget * widget)154 WIDGET_HELPER_GLOBAL_INLINE boolean is_standard_widget(LiVESWidget *widget) {
155 livespointer val;
156 if (!(val = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), STD_KEY))) return FALSE;
157 return (LIVES_POINTER_TO_INT(val));
158 }
159
set_standard_widget(LiVESWidget * widget,boolean is)160 WIDGET_HELPER_LOCAL_INLINE void set_standard_widget(LiVESWidget *widget, boolean is) {
161 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget), STD_KEY, LIVES_INT_TO_POINTER(is));
162 }
163
164
edit_state_cb(LiVESWidgetObject * object,livespointer pspec,livespointer user_data)165 static void edit_state_cb(LiVESWidgetObject *object, livespointer pspec, livespointer user_data) {
166 LiVESWidget *entry = LIVES_WIDGET(object);
167 if (lives_entry_get_editable(LIVES_ENTRY(object))) {
168 lives_widget_apply_theme3(entry, LIVES_WIDGET_STATE_NORMAL);
169 } else {
170 lives_widget_apply_theme2(entry, LIVES_WIDGET_STATE_NORMAL, TRUE);
171 }
172 }
173
174
175 #if !GTK_CHECK_VERSION(3, 16, 0)
widget_state_cb(LiVESWidgetObject * object,livespointer pspec,livespointer user_data)176 static boolean widget_state_cb(LiVESWidgetObject *object, livespointer pspec, livespointer user_data) {
177 // This callback is here because:
178 //
179 // a) cannot alter the text colour of a button after the initial draw of a button
180 // this is because it doesnt have a proper label widget
181 // we can only change the background colour, so here we change the border colour via updating the parent container
182
183 // note: if we need a button with changable text colour we must use a toolbar button instead !
184 //
185 // b) CSS appears broken in gtk+ 3.18.9 and possibly other versions, preventing seeting of colours for
186 // non-default states (e.g. insensitive)
187 // thus we need to set a callback to listen to "sensitive" changes, and update the colours in response
188 //
189 // c) it is also easier just to set the CSS colours when the widget state changes than to figure out ahead of time
190 // what the colours should be for each state. Hopefully it doesn't add too much overhead listening for sensitivity
191 // changes and then updating the CSS manually.
192 //
193 LiVESWidget *widget = (LiVESWidget *)object;
194 LiVESWidgetState state;
195 int woat = widget_opts.apply_theme;
196
197 if (LIVES_IS_PLAYING || !mainw->is_ready) return FALSE;
198
199 widget_opts.apply_theme = 1;
200
201 state = lives_widget_get_state(widget);
202
203 if (LIVES_IS_TOOL_BUTTON(widget)) {
204 LiVESWidget *label;
205 LiVESWidget *icon = gtk_tool_button_get_icon_widget(LIVES_TOOL_BUTTON(widget));
206 if (icon) {
207 // if we have an icon (no label) just update the border
208 lives_tool_button_set_border_color(widget, state, &palette->menu_and_bars);
209 widget_opts.apply_theme = woat;
210 return FALSE;
211 }
212 label = gtk_tool_button_get_label_widget(LIVES_TOOL_BUTTON(widget));
213 if (label) {
214 float dimval;
215 LiVESWidgetColor dimmed_fg;
216 LiVESList *list, *olist;
217 // if we have a label we CAN set the text colours for TOOL_buttons
218 // as well as the outline colour
219 if (!lives_widget_is_sensitive(widget)) {
220 dimval = (0.2 * 65535.);
221 lives_widget_color_copy(&dimmed_fg, &palette->normal_fore);
222 lives_widget_color_mix(&dimmed_fg, &palette->normal_back, (float)dimval / 65535.);
223 lives_tool_button_set_border_color(widget, state, &dimmed_fg);
224 lives_widget_apply_theme_dimmed2(label, state, BUTTON_DIM_VAL);
225 } else {
226 dimval = (0.6 * 65535.);
227 lives_widget_color_copy(&dimmed_fg, &palette->normal_fore);
228 lives_widget_color_mix(&dimmed_fg, &palette->normal_back, (float)dimval / 65535.);
229 lives_tool_button_set_border_color(widget, state, &dimmed_fg);
230 lives_widget_apply_theme2(label, state, TRUE);
231 }
232 // menutoolbuttons will also have an arrow
233 // since CSS selectors are borked we have to find it by brute force
234 olist = list = lives_container_get_children(LIVES_CONTAINER(widget));
235 while (list) {
236 widget = (LiVESWidget *)list->data;
237 if (LIVES_IS_VBOX(widget)) {
238 lives_widget_set_bg_color(widget, state, &palette->menu_and_bars);
239 }
240 list = list->next;
241 }
242 lives_list_free(olist);
243 widget_opts.apply_theme = woat;
244 return FALSE;
245 }
246 }
247
248 if (LIVES_IS_LABEL(widget)) {
249 // other widgets get dimmed text
250 int themetype = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), THEME_KEY));
251 if (themetype == 2) {
252 if (!lives_widget_is_sensitive(widget)) {
253 set_child_dimmed_colour2(widget, BUTTON_DIM_VAL); // insens, themecols 1, child only
254 } else set_child_alt_colour(widget, TRUE);
255 } else {
256 if (!lives_widget_is_sensitive(widget)) {
257 set_child_dimmed_colour(widget, BUTTON_DIM_VAL); // insens, themecols 1, child only
258 } else set_child_colour(widget, TRUE);
259 }
260 }
261
262 if (LIVES_IS_ENTRY(widget) || LIVES_IS_COMBO(widget)) {
263 // other widgets get dimmed text
264 if (!lives_widget_is_sensitive(widget)) {
265 set_child_dimmed_colour2(widget, BUTTON_DIM_VAL); // insens, themecols 1, child only
266 lives_widget_apply_theme_dimmed2(widget, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
267 } else {
268 if (LIVES_IS_ENTRY(widget) && !LIVES_IS_SPIN_BUTTON(widget))
269 edit_state_cb(LIVES_WIDGET_OBJECT(widget), NULL, NULL);
270 else {
271 if (LIVES_IS_COMBO(widget)) {
272 LiVESWidget *entry = lives_combo_get_entry(LIVES_COMBO(widget));
273 lives_widget_apply_theme2(entry, LIVES_WIDGET_STATE_NORMAL, TRUE);
274 lives_widget_apply_theme2(widget, LIVES_WIDGET_STATE_NORMAL, TRUE);
275 } else set_child_colour(widget, TRUE);
276 }
277 }
278 }
279 widget_opts.apply_theme = woat;
280 return FALSE;
281 }
282 #endif
283
284
lives_widget_object_set_data_auto(LiVESWidgetObject * obj,const char * key,livespointer data)285 WIDGET_HELPER_GLOBAL_INLINE void lives_widget_object_set_data_auto(LiVESWidgetObject *obj, const char *key, livespointer data) {
286 lives_widget_object_set_data_full(obj, key, data, lives_free);
287 }
288
289 /// needed because lives_list_free() is a macro
lives_list_free_cb(livespointer list)290 static void lives_list_free_cb(livespointer list) {lives_list_free((LiVESList *)list);}
291
lives_widget_object_set_data_list(LiVESWidgetObject * obj,const char * key,LiVESList * list)292 WIDGET_HELPER_GLOBAL_INLINE void lives_widget_object_set_data_list(LiVESWidgetObject *obj, const char *key, LiVESList *list) {
293 lives_widget_object_set_data_full(obj, key, list, lives_list_free_cb);
294 }
295
lives_widget_object_unref_cb(livespointer obj)296 static void lives_widget_object_unref_cb(livespointer obj) {lives_widget_object_unref((LiVESWidgetObject *)obj);}
297
lives_widget_object_set_data_widget_object(LiVESWidgetObject * obj,const char * key,livespointer other)298 WIDGET_HELPER_GLOBAL_INLINE void lives_widget_object_set_data_widget_object(LiVESWidgetObject *obj, const char *key,
299 livespointer other) {
300 lives_widget_object_set_data_full(obj, key, other, lives_widget_object_unref_cb);
301 }
302
303
304 // basic functions
305
306 ////////////////////////////////////////////////////
307 //lives_painter functions
308
lives_painter_create_from_surface(lives_painter_surface_t * target)309 WIDGET_HELPER_GLOBAL_INLINE lives_painter_t *lives_painter_create_from_surface(lives_painter_surface_t *target) {
310 lives_painter_t *cr = NULL;
311 #ifdef LIVES_PAINTER_IS_CAIRO
312 cr = cairo_create(target);
313 #endif
314 #ifdef PAINTER_QPAINTER
315 cr = new lives_painter_t(target);
316 #endif
317 return cr;
318 }
319
320
lives_painter_set_source_pixbuf(lives_painter_t * cr,const LiVESPixbuf * pixbuf,double pixbuf_x,double pixbuf_y)321 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_set_source_pixbuf(lives_painter_t *cr, const LiVESPixbuf *pixbuf,
322 double pixbuf_x,
323 double pixbuf_y) {
324 // blit pixbuf to cairo at x,y
325 #ifdef LIVES_PAINTER_IS_CAIRO
326 gdk_cairo_set_source_pixbuf(cr, pixbuf, pixbuf_x, pixbuf_y);
327 return TRUE;
328 #endif
329 #ifdef PAINTER_QPAINTER
330 QPointF qp(pixbuf_x, pixbuf_y);
331 const QImage *qi = (const QImage *)pixbuf;
332 cr->drawImage(qp, *qi);
333 return TRUE;
334 #endif
335 return FALSE;
336 }
337
338
lives_painter_set_source_surface(lives_painter_t * cr,lives_painter_surface_t * surface,double x,double y)339 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_set_source_surface(lives_painter_t *cr, lives_painter_surface_t *surface,
340 double x,
341 double y) {
342 #ifdef LIVES_PAINTER_IS_CAIRO
343 cairo_set_source_surface(cr, surface, x, y);
344 return TRUE;
345 #endif
346 #ifdef PAINTER_QPAINTER
347 QPointF qp(x, y);
348 cr->drawImage(qp, *surface);
349 return TRUE;
350 #endif
351 return FALSE;
352 }
353
354
lives_painter_paint(lives_painter_t * cr)355 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_paint(lives_painter_t *cr) {
356 #ifdef LIVES_PAINTER_IS_CAIRO
357 cairo_paint(cr);
358 return TRUE;
359 #endif
360 #ifdef PAINTER_QPAINTER
361 return TRUE;
362 #endif
363 return FALSE;
364 }
365
366
lives_painter_fill(lives_painter_t * cr)367 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_fill(lives_painter_t *cr) {
368 #ifdef LIVES_PAINTER_IS_CAIRO
369 cairo_fill(cr);
370 return TRUE;
371 #endif
372 #ifdef PAINTER_QPAINTER
373 cr->fillPath(*(cr->p), cr->pen.color());
374 delete cr->p;
375 cr->p = new QPainterPath;
376 return TRUE;
377 #endif
378 return FALSE;
379 }
380
381
lives_painter_stroke(lives_painter_t * cr)382 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_stroke(lives_painter_t *cr) {
383 #ifdef LIVES_PAINTER_IS_CAIRO
384 cairo_stroke(cr);
385 return TRUE;
386 #endif
387 #ifdef PAINTER_QPAINTER
388 cr->strokePath(*(cr->p), cr->pen);
389 delete cr->p;
390 cr->p = new QPainterPath;
391 return TRUE;
392 #endif
393 return FALSE;
394 }
395
396
lives_painter_clip(lives_painter_t * cr)397 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_clip(lives_painter_t *cr) {
398 #ifdef LIVES_PAINTER_IS_CAIRO
399 cairo_clip(cr);
400 return TRUE;
401 #endif
402 #ifdef PAINTER_QPAINTER
403 cr->setClipPath(*(cr->p), Qt::IntersectClip);
404 delete cr->p;
405 cr->p = new QPainterPath;
406 return TRUE;
407 #endif
408 return FALSE;
409 }
410
411
lives_painter_destroy(lives_painter_t * cr)412 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_destroy(lives_painter_t *cr) {
413 #ifdef LIVES_PAINTER_IS_CAIRO
414 cairo_destroy(cr);
415 return TRUE;
416 #endif
417 #ifdef PAINTER_QPAINTER
418 cr->end();
419 delete cr;
420 return TRUE;
421 #endif
422 return FALSE;
423 }
424
425
lives_painter_render_background(LiVESWidget * widget,lives_painter_t * cr,double x,double y,double width,double height)426 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_render_background(LiVESWidget *widget, lives_painter_t *cr, double x,
427 double y, double width, double height) {
428 #ifdef LIVES_PAINTER_IS_CAIRO
429 if (widget == mainw->play_image && mainw->multitrack) {
430 if (prefs->dev_show_dabg)
431 lives_painter_set_source_rgb_from_lives_widget_color(cr, &palette->dark_orange);
432 else
433 lives_painter_set_source_rgb_from_lives_widget_color(cr, &palette->black);
434 } else {
435 if (LIVES_IS_PLAYING && mainw->faded) {
436 if (prefs->dev_show_dabg)
437 lives_painter_set_source_rgb_from_lives_widget_color(cr, &palette->light_green);
438 else
439 lives_painter_set_source_rgb_from_lives_widget_color(cr, &palette->fade_colour);
440 } else {
441 if (prefs->dev_show_dabg)
442 lives_painter_set_source_rgb_from_lives_widget_color(cr, &palette->dark_red);
443 else
444 lives_painter_set_source_rgb_from_lives_widget_color(cr, &palette->normal_back);
445 }
446 }
447 lives_painter_rectangle(cr, x, y, width, height);
448 lives_painter_fill(cr);
449 lives_widget_queue_draw(widget);
450 return TRUE;
451 #endif /// painter cairo
452 return FALSE;
453 }
454
455
456
lives_painter_surface_destroy(lives_painter_surface_t * surf)457 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_surface_destroy(lives_painter_surface_t *surf) {
458 #ifdef LIVES_PAINTER_IS_CAIRO
459 cairo_surface_destroy(surf);
460 return TRUE;
461 #endif
462 #ifdef PAINTER_QPAINTER
463 surf->dec_refcount();
464 return TRUE;
465 #endif
466 return FALSE;
467 }
468
469
lives_painter_surface_reference(lives_painter_surface_t * surf)470 WIDGET_HELPER_GLOBAL_INLINE lives_painter_surface_t *lives_painter_surface_reference(lives_painter_surface_t *surf) {
471 #ifdef LIVES_PAINTER_IS_CAIRO
472 return cairo_surface_reference(surf);
473 #endif
474 return NULL;
475 }
476
477
lives_painter_new_path(lives_painter_t * cr)478 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_new_path(lives_painter_t *cr) {
479 #ifdef LIVES_PAINTER_IS_CAIRO
480 cairo_new_path(cr);
481 return TRUE;
482 #endif
483 #ifdef PAINTER_QPAINTER
484 delete cr->p;
485 cr->p = new QPainterPath;
486 return TRUE;
487 #endif
488 return FALSE;
489 }
490
491
lives_painter_translate(lives_painter_t * cr,double x,double y)492 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_translate(lives_painter_t *cr, double x, double y) {
493 #ifdef LIVES_PAINTER_IS_CAIRO
494 cairo_translate(cr, x, y);
495 return TRUE;
496 #endif
497 #ifdef PAINTER_QPAINTER
498 QTransform qt;
499 qt.translate(x, y);
500 cr->setTransform(qt, true);
501 return TRUE;
502 #endif
503 return FALSE;
504 }
505
506
lives_painter_set_line_width(lives_painter_t * cr,double width)507 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_set_line_width(lives_painter_t *cr, double width) {
508 #ifdef LIVES_PAINTER_IS_CAIRO
509 cairo_set_line_width(cr, width);
510 return TRUE;
511 #endif
512 #ifdef PAINTER_QPAINTER
513 cr->pen.setWidthF(width);
514 return TRUE;
515 #endif
516 return FALSE;
517 }
518
519
lives_painter_move_to(lives_painter_t * cr,double x,double y)520 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_move_to(lives_painter_t *cr, double x, double y) {
521 #ifdef LIVES_PAINTER_IS_CAIRO
522 cairo_move_to(cr, x, y);
523 return TRUE;
524 #endif
525 #ifdef PAINTER_QPAINTER
526 cr->p->moveTo(x, y);
527 return TRUE;
528 #endif
529 return FALSE;
530 }
531
532
lives_painter_line_to(lives_painter_t * cr,double x,double y)533 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_line_to(lives_painter_t *cr, double x, double y) {
534 #ifdef LIVES_PAINTER_IS_CAIRO
535 cairo_line_to(cr, x, y);
536 return TRUE;
537 #endif
538 #ifdef PAINTER_QPAINTER
539 cr->p->lineTo(x, y);
540 return TRUE;
541 #endif
542 return FALSE;
543 }
544
545
lives_painter_close_path(lives_painter_t * cr)546 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_close_path(lives_painter_t *cr) {
547 #ifdef LIVES_PAINTER_IS_CAIRO
548 cairo_close_path(cr);
549 return TRUE;
550 #endif
551 return FALSE;
552 }
553
554
lives_painter_rectangle(lives_painter_t * cr,double x,double y,double width,double height)555 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_rectangle(lives_painter_t *cr, double x, double y, double width,
556 double height) {
557 #ifdef LIVES_PAINTER_IS_CAIRO
558 cairo_rectangle(cr, x, y, width, height);
559 return TRUE;
560 #endif
561 #ifdef PAINTER_QPAINTER
562 cr->p->addRect(x, y, width, height);
563 return TRUE;
564 #endif
565 return FALSE;
566 }
567
568
lives_painter_arc(lives_painter_t * cr,double xc,double yc,double radius,double angle1,double angle2)569 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_arc(lives_painter_t *cr, double xc, double yc, double radius, double angle1,
570 double angle2) {
571 #ifdef LIVES_PAINTER_IS_CAIRO
572 cairo_arc(cr, xc, yc, radius, angle1, angle2);
573 return TRUE;
574 #endif
575 #ifdef PAINTER_QPAINTER
576 double l = xc - radius;
577 double t = yc - radius;
578 double w = radius * 2, h = w;
579 angle1 = angle1 / M_PI * 180.;
580 angle2 = angle2 / M_PI * 180.;
581 cr->p->arcTo(l, t, w, h, angle1, angle2 - angle1);
582 return TRUE;
583 #endif
584 return FALSE;
585 }
586
587
lives_painter_set_operator(lives_painter_t * cr,lives_painter_operator_t op)588 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_set_operator(lives_painter_t *cr, lives_painter_operator_t op) {
589 // if op was not LIVES_PAINTER_OPERATOR_DEFAULT, and FALSE is returned, then the operation failed,
590 // and op was set to the default
591 #ifdef LIVES_PAINTER_IS_CAIRO
592 cairo_set_operator(cr, op);
593 if (op == LIVES_PAINTER_OPERATOR_UNKNOWN) return FALSE;
594 return TRUE;
595 #endif
596 #ifdef PAINTER_QPAINTER
597 cr->setCompositionMode(op);
598 return TRUE;
599 #endif
600 return FALSE;
601 }
602
603
lives_painter_set_source_rgb(lives_painter_t * cr,double red,double green,double blue)604 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_set_source_rgb(lives_painter_t *cr, double red, double green, double blue) {
605 // r,g,b values 0.0 -> 1.0
606 #ifdef LIVES_PAINTER_IS_CAIRO
607 cairo_set_source_rgb(cr, red, green, blue);
608 return TRUE;
609 #endif
610 #ifdef PAINTER_QPAINTER
611 QColor qc(red * 255., green * 255., blue * 255.);
612 cr->pen.setColor(qc);
613 return TRUE;
614 #endif
615 return FALSE;
616 }
617
618
lives_painter_set_source_rgba(lives_painter_t * cr,double red,double green,double blue,double alpha)619 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_set_source_rgba(lives_painter_t *cr, double red, double green, double blue,
620 double alpha) {
621 // r,g,b,a values 0.0 -> 1.0
622 #ifdef LIVES_PAINTER_IS_CAIRO
623 cairo_set_source_rgba(cr, red, green, blue, alpha);
624 return TRUE;
625 #endif
626 #ifdef PAINTER_QPAINTER
627 QColor qc(red * 255., green * 255., blue * 255., alpha * 255.);
628 cr->pen.setColor(qc);
629 return TRUE;
630 #endif
631 return FALSE;
632 }
633
634
lives_painter_set_fill_rule(lives_painter_t * cr,lives_painter_fill_rule_t fill_rule)635 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_set_fill_rule(lives_painter_t *cr, lives_painter_fill_rule_t fill_rule) {
636 #ifdef LIVES_PAINTER_IS_CAIRO
637 cairo_set_fill_rule(cr, fill_rule);
638 return TRUE;
639 #endif
640 #ifdef PAINTER_QPAINTER
641 cr->p->setFillRule(fill_rule);
642 return TRUE;
643 #endif
644 return FALSE;
645 }
646
647
lives_painter_surface_flush(lives_painter_surface_t * surf)648 WIDGET_HELPER_GLOBAL_INLINE boolean lives_painter_surface_flush(lives_painter_surface_t *surf) {
649 #ifdef LIVES_PAINTER_IS_CAIRO
650 cairo_surface_flush(surf);
651 return TRUE;
652 #endif
653 #ifdef PAINTER_QPAINTER
654 return TRUE;
655 #endif
656 return FALSE;
657 }
658
659
lives_painter_image_surface_create_for_data(uint8_t * data,lives_painter_format_t format,int width,int height,int stride)660 WIDGET_HELPER_GLOBAL_INLINE lives_painter_surface_t *lives_painter_image_surface_create_for_data(uint8_t *data,
661 lives_painter_format_t format,
662 int width, int height, int stride) {
663 lives_painter_surface_t *surf = NULL;
664 #ifdef LIVES_PAINTER_IS_CAIRO
665 surf = cairo_image_surface_create_for_data(data, format, width, height, stride);
666 #endif
667 #ifdef PAINTER_QPAINTER
668 surf = new lives_painter_surface_t(data, format, width, height, stride);
669 #endif
670 return surf;
671 }
672
673
lives_painter_image_surface_create(lives_painter_format_t format,int width,int height)674 WIDGET_HELPER_GLOBAL_INLINE lives_painter_surface_t *lives_painter_image_surface_create(lives_painter_format_t format,
675 int width,
676 int height) {
677 lives_painter_surface_t *surf = NULL;
678 #ifdef LIVES_PAINTER_IS_CAIRO
679 surf = cairo_image_surface_create(format, width, height);
680 #endif
681 #ifdef PAINTER_QPAINTER
682 surf = new lives_painter_surface_t(width, height, format);
683 #endif
684 return surf;
685 }
686
687
688 WIDGET_HELPER_GLOBAL_INLINE lives_painter_surface_t
lives_xwindow_create_similar_surface(LiVESXWindow * window,lives_painter_content_t cont,int width,int height)689 *lives_xwindow_create_similar_surface(LiVESXWindow *window, lives_painter_content_t cont,
690 int width, int height) {
691 lives_painter_surface_t *surf = gdk_window_create_similar_surface(window, cont, width, height);
692 lives_painter_t *cr = lives_painter_create_from_surface(surf);
693 lives_painter_set_source_rgb(cr, 0., 0., 0.);
694 lives_painter_paint(cr);
695 lives_painter_destroy(cr);
696 return surf;
697 }
698
699
lives_widget_create_painter_surface(LiVESWidget * widget)700 WIDGET_HELPER_GLOBAL_INLINE lives_painter_surface_t *lives_widget_create_painter_surface(LiVESWidget *widget) {
701 if (widget)
702 return lives_xwindow_create_similar_surface(lives_widget_get_xwindow(widget),
703 LIVES_PAINTER_CONTENT_COLOR,
704 lives_widget_get_allocation_width(widget),
705 lives_widget_get_allocation_height(widget));
706 return NULL;
707 }
708
709 ////////////////////////// painter info funcs
710
lives_painter_get_target(lives_painter_t * cr)711 WIDGET_HELPER_GLOBAL_INLINE lives_painter_surface_t *lives_painter_get_target(lives_painter_t *cr) {
712 lives_painter_surface_t *surf = NULL;
713 #ifdef LIVES_PAINTER_IS_CAIRO
714 surf = cairo_get_target(cr);
715 #endif
716 #ifdef PAINTER_QPAINTER
717 surf = cr->target;
718 #endif
719 return surf;
720 }
721
722
lives_painter_format_stride_for_width(lives_painter_format_t form,int width)723 WIDGET_HELPER_GLOBAL_INLINE int lives_painter_format_stride_for_width(lives_painter_format_t form, int width) {
724 int stride = -1;
725 #ifdef LIVES_PAINTER_IS_CAIRO
726 stride = cairo_format_stride_for_width(form, width);
727 #endif
728 #ifdef PAINTER_QPAINTER
729 stride = width * 4; //TODO !!
730 #endif
731 return stride;
732 }
733
734
lives_painter_image_surface_get_data(lives_painter_surface_t * surf)735 WIDGET_HELPER_GLOBAL_INLINE uint8_t *lives_painter_image_surface_get_data(lives_painter_surface_t *surf) {
736 uint8_t *data = NULL;
737 #ifdef LIVES_PAINTER_IS_CAIRO
738 data = cairo_image_surface_get_data(surf);
739 #endif
740 #ifdef PAINTER_QPAINTER
741 data = (uint8_t *)surf->bits();
742 #endif
743 return data;
744 }
745
746
lives_painter_image_surface_get_width(lives_painter_surface_t * surf)747 WIDGET_HELPER_GLOBAL_INLINE int lives_painter_image_surface_get_width(lives_painter_surface_t *surf) {
748 int width = 0;
749 #ifdef LIVES_PAINTER_IS_CAIRO
750 width = cairo_image_surface_get_width(surf);
751 #endif
752 #ifdef PAINTER_QPAINTER
753 width = ((QImage *)surf)->width();
754 #endif
755 return width;
756 }
757
758
lives_painter_image_surface_get_height(lives_painter_surface_t * surf)759 WIDGET_HELPER_GLOBAL_INLINE int lives_painter_image_surface_get_height(lives_painter_surface_t *surf) {
760 int height = 0;
761 #ifdef LIVES_PAINTER_IS_CAIRO
762 height = cairo_image_surface_get_height(surf);
763 #endif
764 #ifdef PAINTER_QPAINTER
765 height = ((QImage *)surf)->height();
766 #endif
767 return height;
768 }
769
770
lives_painter_image_surface_get_stride(lives_painter_surface_t * surf)771 WIDGET_HELPER_GLOBAL_INLINE int lives_painter_image_surface_get_stride(lives_painter_surface_t *surf) {
772 int stride = 0;
773 #ifdef LIVES_PAINTER_IS_CAIRO
774 stride = cairo_image_surface_get_stride(surf);
775 #endif
776 #ifdef PAINTER_QPAINTER
777 stride = ((QImage *)surf)->bytesPerLine();
778 #endif
779 return stride;
780 }
781
782
lives_painter_image_surface_get_format(lives_painter_surface_t * surf)783 WIDGET_HELPER_GLOBAL_INLINE lives_painter_format_t lives_painter_image_surface_get_format(lives_painter_surface_t *surf) {
784 lives_painter_format_t format = (lives_painter_format_t)0;
785 #ifdef LIVES_PAINTER_IS_CAIRO
786 format = cairo_image_surface_get_format(surf);
787 #endif
788 #ifdef PAINTER_QPAINTER
789 format = ((QImage *)surf)->format();
790 #endif
791 return format;
792 }
793
794
795 ////////////////////////////////////////////////////////
796
lives_widget_object_ref(livespointer object)797 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_ref(livespointer object) {
798 #ifdef GUI_GTK
799 if (LIVES_IS_WIDGET_OBJECT(object)) g_object_ref(object);
800 else {
801 LIVES_WARN("Ref of non-object");
802 break_me("ref of nomobj");
803 return FALSE;
804 }
805 return TRUE;
806 #endif
807 #ifdef GUI_QT
808 static_cast<LiVESWidgetObject *>(object)->inc_refcount();
809 return TRUE;
810 #endif
811 return FALSE;
812 }
813
814
lives_widget_object_unref(livespointer object)815 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_unref(livespointer object) {
816 #ifdef GUI_GTK
817 if (LIVES_IS_WIDGET_OBJECT(object)) g_object_unref(object);
818 else {
819 LIVES_WARN("Unref of non-object");
820 break_me("unref of nonobj");
821 return FALSE;
822 }
823 return TRUE;
824 #endif
825 #ifdef GUI_QT
826 static_cast<LiVESWidgetObject *>(object)->dec_refcount();
827 return TRUE;
828 #endif
829 return FALSE;
830 }
831
832
833 #ifdef GUI_GTK
834 #if GTK_CHECK_VERSION(3, 0, 0)
lives_widget_object_ref_sink(livespointer object)835 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_ref_sink(livespointer object) {
836 if (!LIVES_IS_WIDGET_OBJECT(object)) {
837 LIVES_WARN("Ref_sink of non-object");
838 break_me("ref sink of nonobj");
839 return FALSE;
840 }
841 g_object_ref_sink(object);
842 return TRUE;
843 }
844 #else
lives_widget_object_ref_sink(livespointer object)845 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_ref_sink(livespointer object) {
846 GtkObject *gtkobject;
847 if (!LIVES_IS_WIDGET_OBJECT(object)) {
848 LIVES_WARN("Ref_sink of non-object");
849 return FALSE;
850 }
851 gtkobject = (GtkObject *)object;
852 gtk_object_sink(gtkobject);
853 return TRUE;
854 }
855 #endif
856 #endif
857
858 #ifdef GUI_QT
lives_widget_object_ref_sink(livespointer object)859 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_object_ref_sink(livespointer object) {
860 static_cast<LiVESWidgetObject *>(object)->ref_sink();
861 return TRUE;
862 }
863 #endif
864
865 /// signal handling
866
867 typedef struct {
868 livespointer instance;
869 lives_funcptr_t callback;
870 livespointer user_data;
871 volatile boolean swapped;
872 unsigned long funcid;
873 char *detsig;
874 boolean is_timer;
875 boolean added;
876 lives_proc_thread_t proc;
877 } lives_sigdata_t;
878
879 static LiVESList *active_sigdets = NULL;
880
async_notify_redirect_handler(LiVESWidgetObject * object,livespointer pspec,livespointer user_data)881 static void async_notify_redirect_handler(LiVESWidgetObject *object, livespointer pspec,
882 livespointer user_data) {
883 /// async shim to convert "notify::xxx" to some other signal
884 async_sig_handler(object, user_data);
885 }
886
notify_redirect_handler(LiVESWidgetObject * object,livespointer pspec,livespointer user_data)887 static void notify_redirect_handler(LiVESWidgetObject *object, livespointer pspec,
888 livespointer user_data) {
889 /// shim to convert "notify::xxx" to some other signal
890 lives_sigdata_t *sigdata = (lives_sigdata_t *)user_data;
891 LiVESWidget *widget = (LiVESWidget *)object;
892 if (!sigdata->swapped)
893 (*((bifunc)sigdata->callback))(widget, sigdata->user_data);
894 else
895 (*((bifunc)sigdata->callback))(sigdata->user_data, widget);
896 }
897
lives_signal_connect_sync(livespointer instance,const char * detailed_signal,LiVESGuiCallback c_handler,livespointer data,LiVESConnectFlags flags)898 unsigned long lives_signal_connect_sync(livespointer instance, const char *detailed_signal,
899 LiVESGuiCallback c_handler, livespointer data,
900 LiVESConnectFlags flags) {
901 unsigned long func_id;
902 #if LIVES_HAS_SWITCH_WIDGET
903 if (LIVES_IS_WIDGET(instance) && LIVES_IS_SWITCH(LIVES_WIDGET(instance))
904 && !strcmp(detailed_signal, LIVES_WIDGET_TOGGLED_SIGNAL)) {
905 /// to make switch and checkbutton interchangeable,
906 /// we substitue the "toggled" signal for a switch with "notify::active"
907 /// and then redirect it back to the desired callback
908 lives_sigdata_t *sigdata = lives_calloc(1, sizeof(lives_sigdata_t));
909 sigdata->instance = instance;
910 sigdata->callback = (lives_funcptr_t)c_handler;
911 sigdata->user_data = data;
912 sigdata->swapped = (flags & LIVES_CONNECT_SWAPPED) ? TRUE : FALSE;
913 sigdata->detsig = lives_strdup(LIVES_WIDGET_TOGGLED_SIGNAL);
914 sigdata->funcid = g_signal_connect_data(instance, LIVES_WIDGET_NOTIFY_SIGNAL "active",
915 LIVES_GUI_CALLBACK(notify_redirect_handler),
916 sigdata, sigdata_free, (flags & LIVES_CONNECT_AFTER));
917 active_sigdets = lives_list_prepend(active_sigdets, (livespointer)sigdata);
918 return sigdata->funcid;
919 }
920 #endif
921 if (!flags)
922 func_id = g_signal_connect(instance, detailed_signal, c_handler, data);
923 else {
924 if (flags & LIVES_CONNECT_AFTER)
925 func_id = g_signal_connect_after(instance, detailed_signal, c_handler, data);
926 else
927 func_id = g_signal_connect_swapped(instance, detailed_signal, c_handler, data);
928 }
929 return func_id;
930 }
931
932
lives_signal_handler_block(livespointer instance,unsigned long handler_id)933 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_block(livespointer instance, unsigned long handler_id) {
934 #ifdef GUI_GTK
935 g_signal_handler_block(instance, handler_id);
936 return TRUE;
937 #endif
938 #ifdef GUI_QT
939 LiVESWidgetObject *obj = static_cast<LiVESWidgetObject *>(instance);
940 obj->block_signal(handler_id);
941 return TRUE;
942 #endif
943 return FALSE;
944 }
945
946
lives_signal_handler_unblock(livespointer instance,unsigned long handler_id)947 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_unblock(livespointer instance, unsigned long handler_id) {
948 #ifdef GUI_GTK
949 g_signal_handler_unblock(instance, handler_id);
950 return TRUE;
951 #endif
952 #ifdef GUI_QT
953 LiVESWidgetObject *obj = static_cast<LiVESWidgetObject *>(instance);
954 obj->unblock_signal(handler_id);
955 return TRUE;
956 #endif
957 return FALSE;
958 }
959
960
lives_signal_handler_disconnect(livespointer instance,unsigned long handler_id)961 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handler_disconnect(livespointer instance, unsigned long handler_id) {
962 #ifdef GUI_GTK
963 g_signal_handler_disconnect(instance, handler_id);
964 return TRUE;
965 #endif
966 #ifdef GUI_QT
967 LiVESWidgetObject *obj = static_cast<LiVESWidgetObject *>(instance);
968 obj->disconnect_signal(handler_id);
969 return TRUE;
970 #endif
971 return FALSE;
972 }
973
974
lives_signal_stop_emission_by_name(livespointer instance,const char * detailed_signal)975 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_stop_emission_by_name(livespointer instance, const char *detailed_signal) {
976 #ifdef GUI_GTK
977 g_signal_stop_emission_by_name(instance, detailed_signal);
978 return TRUE;
979 #endif
980 return FALSE;
981 }
982
983
984 static volatile boolean gov_running = FALSE;
985 static volatile LiVESResponseType dlgresp = LIVES_RESPONSE_NONE;
986 static volatile boolean was_dest = FALSE;
987 static volatile lives_proc_thread_t lpttorun = NULL;
988 static volatile void *lpt_result = NULL;
989 static volatile void *lpt_retval = NULL;
990
sigdata_free(livespointer data,LiVESWidgetClosure * cl)991 static void sigdata_free(livespointer data, LiVESWidgetClosure *cl) {
992 lives_sigdata_t *sigdata = (lives_sigdata_t *)data;
993 if (cl) active_sigdets = lives_list_remove(active_sigdets, sigdata);
994
995 //if (sigdata->proc) weed_plant_free(sigdata->proc);
996
997 if (sigdata->detsig) lives_free(sigdata->detsig);
998 lives_free(sigdata);
999 }
1000
1001 static boolean timer_running = FALSE;
1002
1003 static LiVESList *task_list = NULL;
1004
tasks_running(void)1005 static lives_sigdata_t *tasks_running(void) {
1006 LiVESList *list;
1007 lives_sigdata_t *sigdata;
1008 list = task_list;
1009 if (!list) return NULL;
1010 sigdata = (lives_sigdata_t *)list->data;
1011 if (lives_proc_thread_check(sigdata->proc)) {
1012 task_list = task_list->next;
1013 if (task_list) task_list->prev = NULL;
1014 list->next = NULL;
1015 list->data = NULL;
1016 lives_list_free(list);
1017 if (!task_list) return sigdata;
1018 if (sigdata->proc) lives_proc_thread_dontcare(sigdata->proc);
1019 sigdata_free(sigdata, NULL);
1020 }
1021 return NULL;
1022 }
1023
governor_loop(livespointer data)1024 static boolean governor_loop(livespointer data) {
1025 volatile boolean clutch;
1026 static boolean lpt_recurse = FALSE;
1027 static boolean lpt_recurse2 = FALSE;
1028 boolean is_timer = FALSE;
1029 lives_sigdata_t *sigdata = NULL;
1030 lives_sigdata_t *new_sigdata = (lives_sigdata_t *)data;
1031 /// this loop runs in the main thread while callbacks are being run in bg.
1032 reloop:
1033
1034 if (g_main_depth() > 1) {
1035 mainw->clutch = TRUE;
1036 return TRUE;
1037 }
1038 if (mainw->is_exiting) return FALSE;
1039
1040 if (lpt_recurse2) return TRUE;
1041
1042 if (!new_sigdata) {
1043 // here we ar either re-entering as an idlefunc, or we are in a timer and looped back
1044 if (lpttorun) {
1045 // check if there is a foreground task to run
1046 lpt_recurse2 = TRUE;
1047 lpt_result = fg_run_func(lpttorun, (void *)lpt_retval);
1048 if (!is_timer) {
1049 lpttorun = NULL;
1050 lpt_recurse2 = FALSE;
1051 if (!lpt_recurse) {
1052 return FALSE;
1053 } else {
1054 //gov_running = FALSE;
1055 lpt_recurse = FALSE;
1056 return TRUE;
1057 }
1058 }
1059 /* if (!lpttorun) */
1060 /* while (lives_widget_context_iteration(NULL, FALSE)); */
1061 lpttorun = NULL;
1062 lpt_recurse = FALSE;
1063 lpt_recurse2 = FALSE;
1064 }
1065
1066 if (timer_running) {
1067 mainw->clutch = FALSE;
1068 return TRUE;
1069 }
1070 }
1071
1072 // this is a shared variable which can be reset to interrupt us
1073 mainw->clutch = TRUE;
1074
1075 if (!new_sigdata || !lives_proc_thread_check(new_sigdata->proc)) {
1076 // either we rentered as an idle, or reloop for timer, or adding a new task
1077
1078 // sigdata will be set if the last task on the stack completed
1079 if (!(sigdata = tasks_running()) || new_sigdata) {
1080 // either a task is still running, or else we are adding a new one
1081
1082 if (sigdata && new_sigdata) {
1083 // handle the case where the last task finished, and we need to add a new one
1084 if (sigdata->is_timer) {
1085 // this is complicated, We need to return to caller so it can exit with correct value
1086 // but we need to return to run the new task
1087 lives_idle_add_simple(governor_loop, new_sigdata);
1088 return FALSE;
1089 }
1090 }
1091 // signal that ww are in the loop
1092 gov_running = TRUE;
1093
1094 if (new_sigdata) {
1095 // push a new task to the stack
1096 // signal bg that it can start now...
1097 lives_proc_thread_sync_ready(new_sigdata->proc);
1098 task_list = lives_list_prepend(task_list, new_sigdata);
1099 new_sigdata = NULL;
1100 goto reloop;
1101 }
1102
1103 clutch = mainw->clutch;
1104 while (task_list && !lpttorun && clutch && !mainw->is_exiting && !(sigdata = tasks_running())) {
1105 // while any signal handler is running in the bg, we just loop here until either:
1106 // the task completes, the task wants to run a main loop cycle, or the app exits
1107 lives_nanosleep(NSLEEP_TIME);
1108 /* if (lives_proc_thread_signalled(sigdata->proc)) { */
1109 /* g_print("Thread %lu received signal %d\n", lives_proc_thread_signalled_idx(sigdata->proc), */
1110 /* lives_proc_thread_signalled(sigdata->proc)); */
1111 /* } */
1112 //sched_yield();
1113 clutch = mainw->clutch;
1114 }
1115 }
1116 }
1117 //else sigdata = new_sigdata;
1118
1119 if (mainw->is_exiting) return FALSE; // app exit
1120
1121 if (!task_list && !lpttorun && !sigdata) {
1122 gov_running = FALSE;
1123 return FALSE;
1124 }
1125
1126 if (lpttorun || (!mainw->clutch && !sigdata)) {
1127 int count = 0;
1128 // a thread wants to wiggle the widgets...
1129 if (task_list) sigdata = (lives_sigdata_t *)lives_list_last(task_list)->data;
1130 if (sigdata && sigdata->is_timer) {
1131 // this is also complicated. We are running in a timer and we need to run mainloop
1132 is_timer = TRUE;
1133 /* if (!lpttorun) */
1134 while (!lives_proc_thread_check(sigdata->proc) && lives_widget_context_iteration(NULL, FALSE));
1135 sigdata = NULL;
1136 goto reloop;
1137 }
1138 if (lpttorun) lpt_recurse = TRUE;
1139 while (count++ < EV_LIM && !(sigdata && lives_proc_thread_check(sigdata->proc))
1140 && lives_widget_context_iteration(NULL, FALSE));
1141 lives_idle_add_simple(governor_loop, NULL);
1142 gov_running = FALSE;
1143 return FALSE;
1144 }
1145
1146 /// something else might have removed the clutch, so check again
1147 if (!lives_proc_thread_check(sigdata->proc)) goto reloop;
1148
1149 /// something else might have removed the clutch, so check again
1150 //if (!lives_proc_thread_check(sigdata->proc)) goto reloop;
1151 //if (!(sigdata = tasks_running())) goto reloop;
1152
1153 // bg handler finished
1154 gov_running = FALSE;
1155 // if a timer, set sigdata->swapped
1156 if (sigdata->is_timer) {
1157 if (sigdata) sigdata->swapped = TRUE;
1158 /// timer handler will free sigdata
1159 } else {
1160 lives_proc_thread_dontcare(sigdata->proc);
1161 sigdata_free(sigdata, NULL);
1162 }
1163 return FALSE;
1164 }
1165
1166
async_sig_handler(livespointer instance,livespointer data)1167 static void async_sig_handler(livespointer instance, livespointer data) {
1168 lives_thread_attr_t attr = LIVES_THRDATTR_WAIT_SYNC;
1169 lives_sigdata_t *sigdata = lives_calloc(1, sizeof(lives_sigdata_t));
1170 lives_memcpy(sigdata, data, sizeof(lives_sigdata_t));
1171 sigdata->detsig = NULL;
1172
1173 // possible values: [gtk+] gdk_frame_clock_paint_idle
1174 // GDK X11 Event source (:0.0)
1175 // [gio] complete_in_idle_cb
1176 // null
1177 // g_print("SOURCE is %s\n", g_source_get_name(g_main_current_source()));
1178 if (sigdata->instance != instance) return;
1179
1180 /* ctx = lives_widget_context_get_thread_default(); */
1181 /* if (!gov_running && (!ctx || ctx == lives_widget_context_default())) { */
1182
1183 //mainw->clutch = TRUE;
1184 if (sigdata->swapped) {
1185 sigdata->proc = lives_proc_thread_create(attr, (lives_funcptr_t)sigdata->callback, -1, "vv", sigdata->user_data, instance);
1186 } else {
1187 sigdata->proc = lives_proc_thread_create(attr, (lives_funcptr_t)sigdata->callback, -1, "vv", instance, sigdata->user_data);
1188 }
1189 governor_loop(sigdata);
1190 }
1191
1192
async_sig_handler3(livespointer instance,livespointer extra,livespointer data)1193 static void async_sig_handler3(livespointer instance, livespointer extra, livespointer data) {
1194 lives_sigdata_t *sigdata = lives_calloc(1, sizeof(lives_sigdata_t));
1195 lives_thread_attr_t attr = LIVES_THRDATTR_WAIT_SYNC;
1196 lives_memcpy(sigdata, data, sizeof(lives_sigdata_t));
1197 sigdata->detsig = NULL;
1198 if (sigdata->swapped)
1199 sigdata->proc = lives_proc_thread_create(attr, sigdata->callback, -1, "vvv", sigdata->user_data,
1200 extra, instance);
1201 else
1202 sigdata->proc = lives_proc_thread_create(attr, sigdata->callback, -1, "vvv", instance, extra,
1203 sigdata->user_data);
1204 governor_loop((livespointer)sigdata);
1205 }
1206
1207
async_timer_handler(livespointer data)1208 static boolean async_timer_handler(livespointer data) {
1209 if (mainw->is_exiting) return FALSE;
1210 else {
1211 lives_sigdata_t *sigdata = lives_calloc(1, sizeof(lives_sigdata_t));
1212 lives_memcpy(sigdata, data, sizeof(lives_sigdata_t));
1213 sigdata->detsig = NULL;
1214 sigdata->is_timer = TRUE;
1215 //g_print("SOURCE is %s\n", g_source_get_name(g_main_current_source())); // NULL for timer, GIdleSource for idle
1216 //g_print("hndling %p %s %p\n", sigdata, sigdata->detsig, (void *)sigdata->detsig);
1217
1218 if (!sigdata->added) {
1219 lives_thread_attr_t attr = LIVES_THRDATTR_WAIT_SYNC;
1220 mainw->clutch = FALSE;
1221 sigdata->swapped = FALSE;
1222 sigdata->proc = lives_proc_thread_create(attr, (lives_funcptr_t)sigdata->callback, WEED_SEED_BOOLEAN,
1223 "v", sigdata->user_data);
1224 }
1225
1226 while (1) {
1227 int count = 0;
1228 if (!governor_loop(sigdata->added ? NULL : (livespointer)sigdata)) {
1229 if (sigdata->proc) lives_proc_thread_dontcare(sigdata->proc);
1230 sigdata_free(sigdata, NULL);
1231 break;
1232 }
1233 sigdata->added = TRUE;
1234 if (sigdata->swapped) {
1235 // task finished
1236 // get bool result and return
1237 boolean res = lives_proc_thread_join_boolean(sigdata->proc);
1238 if (sigdata->proc) weed_plant_free(sigdata->proc);
1239 sigdata_free(sigdata, NULL);
1240 return res;
1241 }
1242 timer_running = TRUE;
1243 while (count++ < EV_LIM && !mainw->is_exiting && lives_widget_context_pending(NULL)) {
1244 //while (lives_widget_context_iteration(NULL, FALSE)) {
1245 //LiVESXEvent *ev = lives_widgets_get_current_event();
1246 //if (ev) g_print("ev was %d\n", ev->type);
1247 //else g_print("NULL event\n");
1248 lives_widget_context_iteration(NULL, FALSE);
1249 //lives_nanosleep(NSLEEP_TIME);
1250 }
1251 timer_running = FALSE;
1252 }
1253 }
1254 return FALSE;
1255 }
1256
1257
lives_signal_connect_async(livespointer instance,const char * detailed_signal,LiVESGuiCallback c_handler,livespointer data,LiVESConnectFlags flags)1258 unsigned long lives_signal_connect_async(livespointer instance, const char *detailed_signal, LiVESGuiCallback c_handler,
1259 livespointer data, LiVESConnectFlags flags) {
1260 static size_t notilen = -1;
1261 lives_sigdata_t *sigdata;
1262 uint32_t nvals;
1263 GSignalQuery sigq;
1264
1265 #if LIVES_HAS_SWITCH_WIDGET
1266 boolean swtog = FALSE;
1267 if (LIVES_IS_WIDGET(instance) && LIVES_IS_SWITCH(LIVES_WIDGET(instance))
1268 && !strcmp(detailed_signal, LIVES_WIDGET_TOGGLED_SIGNAL)) swtog = TRUE;
1269 else {
1270 #endif
1271
1272 if (notilen == -1) notilen = lives_strlen(LIVES_WIDGET_NOTIFY_SIGNAL);
1273 if (!lives_strncmp(detailed_signal, LIVES_WIDGET_NOTIFY_SIGNAL, notilen)) {
1274 return lives_signal_connect_sync(instance, detailed_signal, c_handler, data, flags);
1275 }
1276
1277 g_signal_query(g_signal_lookup(detailed_signal, G_OBJECT_TYPE(instance)), &sigq);
1278 if (sigq.return_type != 4) {
1279 return lives_signal_connect_sync(instance, detailed_signal, c_handler, data, flags);
1280 }
1281
1282 nvals = sigq.n_params + 2; // add instance, user_data
1283
1284 if (nvals != 2 && nvals != 3) {
1285 return lives_signal_connect_sync(instance, detailed_signal, c_handler, data, flags);
1286 }
1287
1288 #if LIVES_HAS_SWITCH_WIDGET
1289 }
1290 #endif
1291
1292 sigdata = (lives_sigdata_t *)lives_calloc(1, sizeof(lives_sigdata_t));
1293 sigdata->instance = instance;
1294 sigdata->callback = (lives_funcptr_t)c_handler;
1295 sigdata->user_data = data;
1296 sigdata->swapped = (flags & LIVES_CONNECT_SWAPPED) ? TRUE : FALSE;
1297 active_sigdets = lives_list_prepend(active_sigdets, (livespointer)sigdata);
1298
1299 #if LIVES_HAS_SWITCH_WIDGET
1300 if (swtog) {
1301 /// to make switch and checkbutton interchangeable,
1302 /// we substitue the "toggled" signal for a switch with "notify::active"
1303 /// and then redirect it back to the desired callback
1304 sigdata->detsig = lives_strdup(LIVES_WIDGET_TOGGLED_SIGNAL);
1305 sigdata->funcid = g_signal_connect_data(instance, LIVES_WIDGET_NOTIFY_SIGNAL "active",
1306 LIVES_GUI_CALLBACK(async_notify_redirect_handler),
1307 sigdata, sigdata_free, (flags & LIVES_CONNECT_AFTER));
1308 return sigdata->funcid;
1309 }
1310 #endif
1311
1312 sigdata->detsig = lives_strdup(detailed_signal);
1313
1314 if (nvals == 2) {
1315 sigdata->funcid = g_signal_connect_data(instance, detailed_signal,
1316 LIVES_GUI_CALLBACK(async_sig_handler),
1317 sigdata, sigdata_free, (flags & LIVES_CONNECT_AFTER));
1318 } else {
1319 sigdata->funcid = g_signal_connect_data(instance, detailed_signal,
1320 LIVES_GUI_CALLBACK(async_sig_handler3),
1321 sigdata, sigdata_free, (flags & LIVES_CONNECT_AFTER));
1322 }
1323 return sigdata->funcid;
1324 }
1325
find_sigdata(livespointer instance,LiVESGuiCallback func,livespointer data)1326 static lives_sigdata_t *find_sigdata(livespointer instance, LiVESGuiCallback func, livespointer data) {
1327 LiVESList *list = active_sigdets;
1328 for (; list; list = list->next) {
1329 lives_sigdata_t *sigdata = (lives_sigdata_t *)list->data;
1330 if (sigdata->instance == instance && sigdata->callback == (lives_funcptr_t)func
1331 && sigdata->user_data == data) return sigdata;
1332 }
1333 return NULL;
1334 }
1335
lives_signal_handlers_sync_disconnect_by_func(livespointer instance,LiVESGuiCallback func,livespointer data)1336 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_sync_disconnect_by_func(livespointer instance,
1337 LiVESGuiCallback func, livespointer data) {
1338 #ifdef GUI_GTK
1339 #if LIVES_HAS_SWITCH_WIDGET
1340 if (LIVES_IS_WIDGET(instance) && LIVES_IS_SWITCH(LIVES_WIDGET(instance))) {
1341 /// to make switch and checkbutton interchangeable,
1342 /// we substitue the "toggled" signal for a switch with "notify::active"
1343 /// and then redirect it back to the desired callback
1344 lives_sigdata_t *sigdata = find_sigdata(instance, LIVES_GUI_CALLBACK(func), data);
1345 if (sigdata) {
1346 g_signal_handler_disconnect(instance, sigdata->funcid);
1347 return TRUE;
1348 }
1349 }
1350 #endif
1351 g_signal_handlers_disconnect_by_func(instance, func, data);
1352 return TRUE;
1353 #endif
1354 return FALSE;
1355 }
1356
lives_signal_handlers_sync_block_by_func(livespointer instance,LiVESGuiCallback func,livespointer data)1357 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_sync_block_by_func(livespointer instance,
1358 LiVESGuiCallback func, livespointer data) {
1359 #ifdef GUI_GTK
1360 #if LIVES_HAS_SWITCH_WIDGET
1361 if (LIVES_IS_WIDGET(instance) && LIVES_IS_SWITCH(LIVES_WIDGET(instance))) {
1362 /// to make switch and checkbutton interchangeable,
1363 /// we substitue the "toggled" signal for a switch with "notify::active"
1364 /// and then redirect it back to the desired callback
1365 lives_sigdata_t *sigdata = find_sigdata(instance, LIVES_GUI_CALLBACK(func), data);
1366 if (sigdata) {
1367 g_signal_handler_block(instance, sigdata->funcid);
1368 return TRUE;
1369 }
1370 }
1371 #endif
1372 g_signal_handlers_block_by_func(instance, func, data);
1373 return TRUE;
1374 #endif
1375 return FALSE;
1376 }
1377
lives_signal_handlers_sync_unblock_by_func(livespointer instance,LiVESGuiCallback func,livespointer data)1378 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_sync_unblock_by_func(livespointer instance,
1379 LiVESGuiCallback func, livespointer data) {
1380 #ifdef GUI_GTK
1381 #if LIVES_HAS_SWITCH_WIDGET
1382 if (LIVES_IS_WIDGET(instance) && LIVES_IS_SWITCH(LIVES_WIDGET(instance))) {
1383 /// to make switch and checkbutton interchangeable,
1384 /// we substitue the "toggled" signal for a switch with "notify::active"
1385 /// and then redirect it back to the desired callback
1386 lives_sigdata_t *sigdata = find_sigdata(instance, LIVES_GUI_CALLBACK(func), data);
1387 if (sigdata) {
1388 g_signal_handler_unblock(instance, sigdata->funcid);
1389 return TRUE;
1390 }
1391 }
1392 #endif
1393 g_signal_handlers_unblock_by_func(instance, func, data);
1394 return TRUE;
1395 #endif
1396 return FALSE;
1397 }
1398
lives_signal_handlers_disconnect_by_func(livespointer instance,LiVESGuiCallback func,livespointer data)1399 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_disconnect_by_func(livespointer instance,
1400 LiVESGuiCallback func, livespointer data) {
1401 #if LIVES_HAS_SWITCH_WIDGET
1402 if (LIVES_IS_WIDGET(instance) && LIVES_IS_SWITCH(LIVES_WIDGET(instance))) {
1403 return lives_signal_handlers_sync_disconnect_by_func(instance, func, data);
1404 } else {
1405 #endif
1406 lives_sigdata_t *sigdata = find_sigdata(instance, LIVES_GUI_CALLBACK(func), data);
1407 if (sigdata) {
1408 lives_signal_handler_disconnect(instance, sigdata->funcid);
1409 return TRUE;
1410 }
1411 return lives_signal_handlers_sync_disconnect_by_func(instance, func, data);
1412 #if LIVES_HAS_SWITCH_WIDGET
1413 }
1414 #endif
1415 }
1416
lives_signal_handlers_block_by_func(livespointer instance,LiVESGuiCallback func,livespointer data)1417 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_block_by_func(livespointer instance,
1418 LiVESGuiCallback func, livespointer data) {
1419 #if LIVES_HAS_SWITCH_WIDGET
1420 if (LIVES_IS_WIDGET(instance) && LIVES_IS_SWITCH(LIVES_WIDGET(instance))) {
1421 return lives_signal_handlers_sync_block_by_func(instance, func, data);
1422 } else {
1423 #endif
1424 lives_sigdata_t *sigdata = find_sigdata(instance, LIVES_GUI_CALLBACK(func), data);
1425 if (sigdata) {
1426 lives_signal_handler_block(instance, sigdata->funcid);
1427 return TRUE;
1428 }
1429 return lives_signal_handlers_sync_block_by_func(instance, func, data);
1430 #if LIVES_HAS_SWITCH_WIDGET
1431 }
1432 #endif
1433 }
1434
lives_signal_handlers_unblock_by_func(livespointer instance,LiVESGuiCallback func,livespointer data)1435 WIDGET_HELPER_GLOBAL_INLINE boolean lives_signal_handlers_unblock_by_func(livespointer instance,
1436 LiVESGuiCallback func, livespointer data) {
1437 #if LIVES_HAS_SWITCH_WIDGET
1438 if (LIVES_IS_WIDGET(instance) && LIVES_IS_SWITCH(LIVES_WIDGET(instance))) {
1439 return lives_signal_handlers_sync_unblock_by_func(instance, func, data);
1440 } else {
1441 #endif
1442 lives_sigdata_t *sigdata = find_sigdata(instance, LIVES_GUI_CALLBACK(func), data);
1443 if (sigdata) {
1444 lives_signal_handler_unblock(instance, sigdata->funcid);
1445 return TRUE;
1446 }
1447 return lives_signal_handlers_sync_unblock_by_func(instance, func, data);
1448 #if LIVES_HAS_SWITCH_WIDGET
1449 }
1450 #endif
1451 }
1452
1453
lives_grab_add(LiVESWidget * widget)1454 WIDGET_HELPER_GLOBAL_INLINE boolean lives_grab_add(LiVESWidget *widget) {
1455 #ifdef GUI_GTK
1456 gtk_grab_add(widget);
1457 return TRUE;
1458 #endif
1459 return FALSE;
1460 }
1461
lives_grab_remove(LiVESWidget * widget)1462 WIDGET_HELPER_GLOBAL_INLINE boolean lives_grab_remove(LiVESWidget *widget) {
1463 #ifdef GUI_GTK
1464 gtk_grab_remove(widget);
1465 return TRUE;
1466 #endif
1467 return FALSE;
1468 }
1469
1470
_lives_widget_set_sensitive_cb(LiVESWidget * w,void * pstate)1471 static void _lives_widget_set_sensitive_cb(LiVESWidget *w, void *pstate) {
1472 boolean state = (boolean)LIVES_POINTER_TO_INT(pstate);
1473 lives_widget_set_sensitive(w, state);
1474 }
1475
1476
lives_widget_set_sensitive(LiVESWidget * widget,boolean state)1477 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_sensitive(LiVESWidget *widget, boolean state) {
1478 if (!GTK_IS_WIDGET(widget)) break_me("non widget in set_sensitive");
1479 #ifdef GUI_GTK
1480 gtk_widget_set_sensitive(widget, state);
1481 #ifdef GTK_SUBMENU_SENS_BUG
1482 if (GTK_IS_MENU_ITEM(widget)) {
1483 LiVESWidget *sub = lives_menu_item_get_submenu(LIVES_MENU_ITEM(widget));
1484 if (sub) {
1485 lives_container_foreach(LIVES_CONTAINER(sub), _lives_widget_set_sensitive_cb,
1486 LIVES_INT_TO_POINTER(state));
1487 gtk_widget_set_sensitive(sub, state);
1488 }
1489 }
1490 #endif
1491 return TRUE;
1492 #endif
1493 return FALSE;
1494 }
1495
1496
lives_widget_get_sensitive(LiVESWidget * widget)1497 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_sensitive(LiVESWidget *widget) {
1498 #ifdef GUI_GTK
1499 return gtk_widget_get_sensitive(widget);
1500 #endif
1501 return FALSE;
1502 }
1503
1504
lives_widget_show(LiVESWidget * widget)1505 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show(LiVESWidget *widget) {
1506 #ifdef GUI_GTK
1507 gtk_widget_show(widget);
1508 return TRUE;
1509 #endif
1510 return FALSE;
1511 }
1512
1513
lives_widget_hide(LiVESWidget * widget)1514 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_hide(LiVESWidget *widget) {
1515 #ifdef GUI_GTK
1516 gtk_widget_hide(widget);
1517 return TRUE;
1518 #endif
1519 return FALSE;
1520 }
1521
1522
lives_widget_show_all(LiVESWidget * widget)1523 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all(LiVESWidget *widget) {
1524 #ifdef GUI_GTK
1525 gtk_widget_show_all(widget);
1526
1527 // recommended to center the window again after adding all its widgets
1528 if (LIVES_IS_DIALOG(widget) && mainw->mgeom) lives_window_center(LIVES_WINDOW(widget));
1529
1530 return TRUE;
1531 #endif
1532 return FALSE;
1533 }
1534
lives_widget_show_all_from_bg(LiVESWidget * widget)1535 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all_from_bg(LiVESWidget *widget) {
1536 // run in main thread as it seems to give a smoother result
1537 boolean ret;
1538 main_thread_execute((lives_funcptr_t)lives_widget_show_all, WEED_SEED_BOOLEAN, &ret, "v", widget);
1539 return ret;
1540 //return lives_widget_show_all(widget);
1541 }
1542
1543
lives_widget_show_now(LiVESWidget * widget)1544 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_now(LiVESWidget *widget) {
1545 #ifdef GUI_GTK
1546 gtk_widget_show_now(widget);
1547 return TRUE;
1548 #endif
1549 return FALSE;
1550 }
1551
1552
lives_widget_destroy(LiVESWidget * widget)1553 LIVES_GLOBAL_INLINE boolean lives_widget_destroy(LiVESWidget *widget) {
1554 #ifdef GUI_GTK
1555 if (GTK_IS_WIDGET(widget))
1556 gtk_widget_destroy(widget);
1557 return TRUE;
1558 #endif
1559 return FALSE;
1560 }
1561
1562
_lives_widget_destroy(LiVESWidget * widget)1563 WIDGET_HELPER_LOCAL_INLINE boolean _lives_widget_destroy(LiVESWidget *widget) {
1564 /* boolean ret; */
1565 /* main_thread_execute((lives_funcptr_t)_lives_widget_destroy, WEED_SEED_BOOLEAN, &ret, "v", widget); */
1566 /* return ret; */
1567 return lives_widget_destroy(widget);
1568 }
1569
1570
lives_widget_realize(LiVESWidget * widget)1571 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_realize(LiVESWidget *widget) {
1572 #ifdef GUI_GTK
1573 gtk_widget_realize(widget);
1574 return TRUE;
1575 #endif
1576 return FALSE;
1577 }
1578
1579
lives_widget_queue_draw(LiVESWidget * widget)1580 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_draw(LiVESWidget *widget) {
1581 #ifdef GUI_GTK
1582 if (!GTK_IS_WIDGET(widget)) {
1583 LIVES_WARN("Draw queue invalid widget");
1584 return FALSE;
1585 }
1586 gtk_widget_queue_draw(widget);
1587 return TRUE;
1588 #endif
1589 return FALSE;
1590 }
1591
1592
lives_widget_queue_draw_area(LiVESWidget * widget,int x,int y,int width,int height)1593 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_draw_area(LiVESWidget *widget, int x, int y, int width, int height) {
1594 #ifdef GUI_GTK
1595 #if GTK_CHECK_VERSION(3, 0, 0)
1596 gtk_widget_queue_draw_area(widget, x, y, width, height);
1597 #else
1598 gtk_widget_queue_draw(widget);
1599 #endif
1600 #endif
1601 return FALSE;
1602 }
1603
1604
lives_widget_queue_resize(LiVESWidget * widget)1605 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_resize(LiVESWidget *widget) {
1606 #ifdef GUI_GTK
1607 gtk_widget_queue_resize(widget);
1608 return TRUE;
1609 #endif
1610 return FALSE;
1611 }
1612
1613
lives_widget_set_size_request(LiVESWidget * widget,int width,int height)1614 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_size_request(LiVESWidget *widget, int width, int height) {
1615 #ifdef GUI_GTK
1616 if (LIVES_IS_WINDOW(widget)) lives_window_resize(LIVES_WINDOW(widget), width, height);
1617 else gtk_widget_set_size_request(widget, width, height);
1618 return TRUE;
1619 #endif
1620 return FALSE;
1621 }
1622
1623
lives_widget_set_minimum_size(LiVESWidget * widget,int width,int height)1624 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_minimum_size(LiVESWidget *widget, int width, int height) {
1625 #ifdef GUI_GTK
1626 GdkGeometry geom;
1627 GdkWindowHints mask;
1628 GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
1629 if (GTK_IS_WINDOW(toplevel)) {
1630 geom.min_width = width;
1631 geom.min_height = height;
1632 mask = GDK_HINT_MIN_SIZE;
1633 gtk_window_set_geometry_hints(GTK_WINDOW(toplevel), widget, &geom, mask);
1634 return TRUE;
1635 }
1636 #endif
1637 return FALSE;
1638 }
1639
1640
lives_widget_set_maximum_size(LiVESWidget * widget,int width,int height)1641 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_maximum_size(LiVESWidget *widget, int width, int height) {
1642 #ifdef GUI_GTK
1643 GdkGeometry geom;
1644 GdkWindowHints mask;
1645 GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
1646 if (GTK_IS_WINDOW(toplevel)) {
1647 geom.max_width = width;
1648 geom.max_height = height;
1649 mask = GDK_HINT_MAX_SIZE;
1650 gtk_window_set_geometry_hints(GTK_WINDOW(toplevel), widget, &geom, mask);
1651 return TRUE;
1652 }
1653 #endif
1654 return FALSE;
1655 }
1656
1657
lives_widget_process_updates(LiVESWidget * widget)1658 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_process_updates(LiVESWidget *widget) {
1659 #ifdef GUI_GTK
1660 LiVESWidgetContext *ctx = lives_widget_context_get_thread_default();
1661 LiVESWindow *win, *modalold = modalw;
1662 boolean was_modal = TRUE;
1663 if (!ctx || ctx == lives_widget_context_default()) return TRUE;
1664
1665 if (LIVES_IS_WINDOW(widget)) win = (LiVESWindow *)widget;
1666 else if (LIVES_IS_WIDGET(widget))
1667 win = lives_widget_get_window(widget);
1668 else return FALSE;
1669 if (win && LIVES_IS_WINDOW(win)) {
1670 was_modal = lives_window_get_modal(win);
1671 if (!was_modal) lives_window_set_modal(win, TRUE);
1672 }
1673
1674 if (gov_running) {
1675 mainw->clutch = FALSE;
1676 if (!mainw->is_exiting) {
1677 while (!mainw->clutch) {
1678 lives_nanosleep(NSLEEP_TIME);
1679 }
1680 }
1681 }
1682
1683 if (!was_modal) {
1684 lives_window_set_modal(win, FALSE);
1685 if (modalold) lives_window_set_modal(modalold, TRUE);
1686 }
1687 return TRUE;
1688 #endif
1689 return FALSE;
1690 }
1691
1692
lives_xwindow_get_origin(LiVESXWindow * xwin,int * posx,int * posy)1693 WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_get_origin(LiVESXWindow *xwin, int *posx, int *posy) {
1694 #ifdef GUI_GTK
1695 gdk_window_get_origin(xwin, posx, posy);
1696 return TRUE;
1697 #endif
1698 return FALSE;
1699 }
1700
1701
lives_xwindow_get_frame_extents(LiVESXWindow * xwin,lives_rect_t * rect)1702 WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_get_frame_extents(LiVESXWindow *xwin, lives_rect_t *rect) {
1703 #ifdef GUI_GTK
1704 gdk_window_get_frame_extents(xwin, (GdkRectangle *)rect);
1705 return TRUE;
1706 #endif
1707 return FALSE;
1708 }
1709
1710
lives_xwindow_invalidate_rect(LiVESXWindow * window,lives_rect_t * rect,boolean inv_childs)1711 WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_invalidate_rect(LiVESXWindow *window, lives_rect_t *rect,
1712 boolean inv_childs) {
1713 #ifdef GUI_GTK
1714 gdk_window_invalidate_rect(window, (const GdkRectangle *)rect, inv_childs);
1715 return TRUE;
1716 #endif
1717 return FALSE;
1718 }
1719
1720
lives_widget_reparent(LiVESWidget * widget,LiVESWidget * new_parent)1721 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_reparent(LiVESWidget *widget, LiVESWidget *new_parent) {
1722 #ifdef GUI_GTK
1723 #if GTK_CHECK_VERSION(3, 14, 0)
1724 GtkWidget *parent = gtk_widget_get_parent(widget);
1725 g_object_ref(widget);
1726 if (parent) {
1727 gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget);
1728 }
1729 gtk_container_add(GTK_CONTAINER(new_parent), widget);
1730 g_object_unref(widget);
1731 #else
1732 gtk_widget_reparent(widget, new_parent);
1733 #endif
1734 return TRUE;
1735 #endif
1736 return FALSE;
1737 }
1738
1739
lives_widget_is_ancestor(LiVESWidget * widget,LiVESWidget * ancestor)1740 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_is_ancestor(LiVESWidget *widget, LiVESWidget *ancestor) {
1741 #ifdef GUI_GTK
1742 return gtk_widget_is_ancestor(widget, ancestor);
1743 #endif
1744 return FALSE;
1745 }
1746
1747
lives_widget_set_app_paintable(LiVESWidget * widget,boolean paintable)1748 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_app_paintable(LiVESWidget *widget, boolean paintable) {
1749 #ifdef GUI_GTK
1750 gtk_widget_set_app_paintable(widget, paintable);
1751 return TRUE;
1752 #endif
1753 return FALSE;
1754 }
1755
1756
lives_widget_set_opacity(LiVESWidget * widget,double opacity)1757 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_opacity(LiVESWidget *widget, double opacity) {
1758 #ifdef GUI_GTK
1759 #if GTK_CHECK_VERSION(3, 8, 0)
1760 if (capable->wm_caps.is_composited) {
1761 gtk_widget_set_opacity(widget, opacity);
1762 }
1763 return TRUE;
1764 #endif
1765 if (opacity == 0.) lives_widget_hide(widget);
1766 if (opacity == 1.) lives_widget_show(widget);
1767 #endif
1768 return FALSE;
1769 }
1770
1771
_lives_dialog_run(LiVESDialog * dialog)1772 static LiVESResponseType _lives_dialog_run(LiVESDialog *dialog) {
1773 #ifdef GUI_GTK
1774 LiVESResponseType resp;
1775 lives_widget_show_all(LIVES_WIDGET(dialog));
1776 resp = gtk_dialog_run(dialog);
1777 return resp;
1778 #endif
1779 return LIVES_RESPONSE_INVALID;
1780 }
1781
1782
lives_dialog_run(LiVESDialog * dialog)1783 WIDGET_HELPER_GLOBAL_INLINE LiVESResponseType lives_dialog_run(LiVESDialog *dialog) {
1784 LiVESResponseType resp;
1785 main_thread_execute((lives_funcptr_t)_lives_dialog_run, WEED_SEED_INT, &resp, "v", dialog);
1786 return resp;
1787 }
1788
1789
lives_fg_run(lives_proc_thread_t lpt,void * retval)1790 void *lives_fg_run(lives_proc_thread_t lpt, void *retval) {
1791 void *ret = NULL;
1792 boolean waitgov = FALSE;
1793 #ifdef GUI_GTK
1794 LiVESWidgetContext *ctx = lives_widget_context_get_thread_default();
1795 if (!ctx || ctx == lives_widget_context_default()) {
1796 // run direct
1797 ret = fg_run_func(lpt, retval);
1798 } else {
1799 lpttorun = lpt;
1800 lpt_retval = (volatile void *)retval;
1801 if (!gov_running) {
1802 lives_idle_add_simple(governor_loop, NULL);
1803 while (!gov_running) {
1804 lives_nanosleep(NSLEEP_TIME);
1805 }
1806 } else {
1807 waitgov = TRUE;
1808 mainw->clutch = FALSE;
1809 }
1810 while (lpttorun || (waitgov && !mainw->clutch)) {
1811 lives_nanosleep(NSLEEP_TIME);
1812 }
1813 ret = (void *)lpt_result;
1814 }
1815 #endif
1816 return ret;
1817 }
1818
1819
lives_dialog_response(LiVESDialog * dialog,int response)1820 WIDGET_HELPER_GLOBAL_INLINE boolean lives_dialog_response(LiVESDialog *dialog, int response) {
1821 #ifdef GUI_GTK
1822 gtk_dialog_response(dialog, response);
1823 return TRUE;
1824 #endif
1825 return FALSE;
1826 }
1827
1828
lives_dialog_get_response_for_widget(LiVESDialog * dialog,LiVESWidget * widget)1829 WIDGET_HELPER_GLOBAL_INLINE int lives_dialog_get_response_for_widget(LiVESDialog *dialog, LiVESWidget *widget) {
1830 #ifdef GUI_GTK
1831 return gtk_dialog_get_response_for_widget(dialog, widget);
1832 #endif
1833 return LIVES_RESPONSE_NONE;
1834 }
1835
1836
1837 #if GTK_CHECK_VERSION(3, 16, 0)
1838
1839 #define RND_STRLEN 12
1840 #define RND_STR_PREFIX "XXX"
1841
make_random_string(const char * prefix)1842 static char *make_random_string(const char *prefix) {
1843 // give each widget a random name so we can style it individually
1844 char *str;
1845 size_t psize = strlen(prefix);
1846 size_t rsize = RND_STRLEN << 1;
1847 register int i;
1848
1849 if (psize > RND_STRLEN) return NULL;
1850
1851 str = (char *)lives_malloc(rsize);
1852 lives_snprintf(str, psize + 1, "%s", prefix);
1853
1854 rsize--;
1855
1856 for (i = psize; i < rsize; i++) str[i] = ((lives_random() & 15) + 65);
1857 str[rsize] = 0;
1858 return str;
1859 }
1860 #endif
1861
1862
1863 #ifdef GUI_GTK
1864 #if GTK_CHECK_VERSION(3, 16, 0)
1865 //#define ORD_NAMES
1866
set_css_value_for_state_flag(LiVESWidget * widget,LiVESWidgetState state,const char * xselector,const char * detail,const char * value)1867 static boolean set_css_value_for_state_flag(LiVESWidget *widget, LiVESWidgetState state, const char *xselector,
1868 const char *detail, const char *value) {
1869 GtkCssProvider *provider;
1870 GtkStyleContext *ctx;
1871 char *widget_name, *wname, *selector;
1872 char *css_string;
1873 char *state_str, *selstr;
1874 #ifdef ORD_NAMES
1875 static int widnum = 1;
1876 int brk_widnum = 3128;
1877 #endif
1878 if (!widget) {
1879 int numtok = get_token_count(xselector, ' ') ;
1880 if (numtok > 1) {
1881 char **array = lives_strsplit(xselector, " ", 2);
1882 widget_name = lives_strdup(array[0]);
1883 selector = lives_strdup(array[1]);
1884 lives_strfreev(array);
1885 } else {
1886 widget_name = lives_strdup(xselector);
1887 selector = lives_strdup("");
1888 }
1889 provider = gtk_css_provider_new();
1890
1891 // setting context provider for screen is VERY slow, so this should be used sparingly
1892 gtk_style_context_add_provider_for_screen(mainw->mgeom[widget_opts.monitor].screen, GTK_STYLE_PROVIDER
1893 (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 10000);
1894 } else {
1895 if (!LIVES_IS_WIDGET(widget)) return FALSE;
1896 selector = (char *)xselector;
1897
1898 ctx = gtk_widget_get_style_context(widget);
1899 provider = gtk_css_provider_new();
1900 gtk_style_context_add_provider(ctx, GTK_STYLE_PROVIDER
1901 (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 10000);
1902
1903 widget_name = lives_strdup(gtk_widget_get_name(widget));
1904
1905 if (!widget_name || (strncmp(widget_name, RND_STR_PREFIX, strlen(RND_STR_PREFIX)))) {
1906 lives_freep((void **)&widget_name);
1907 #ifdef ORD_NAMES
1908 widget_name = lives_strdup_printf("%s-%d", RND_STR_PREFIX, ++widnum);
1909 #else
1910 widget_name = make_random_string(RND_STR_PREFIX);
1911 #endif
1912 gtk_widget_set_name(widget, widget_name);
1913 #ifdef ORD_NAMES
1914 if (widnum == brk_widnum) break_me("widnum");
1915 #endif
1916 }
1917 }
1918
1919 #ifdef GTK_TEXT_VIEW_CSS_BUG
1920 if (widget && GTK_IS_TEXT_VIEW(widget)) {
1921 lives_freep((void **)&widget_name);
1922 widget_name = lives_strdup("GtkTextView");
1923 } else {
1924 #endif
1925 switch (state) {
1926 // TODO: gtk+ 3.x can set multiple states
1927 case GTK_STATE_FLAG_ACTIVE:
1928 state_str = ":active";
1929 break;
1930 case GTK_STATE_FLAG_FOCUSED:
1931 #if GTK_CHECK_VERSION(3, 18, 0)
1932 state_str = ":focus";
1933 #endif
1934 break;
1935 case GTK_STATE_FLAG_PRELIGHT:
1936 #if GTK_CHECK_VERSION(3, 18, 0)
1937 state_str = ":hover";
1938 #else
1939 state_str = ":prelight";
1940 #endif
1941 break;
1942 case GTK_STATE_FLAG_SELECTED:
1943 state_str = ":selected";
1944 break;
1945 case GTK_STATE_FLAG_CHECKED:
1946 state_str = ":checked";
1947 break;
1948 case GTK_STATE_FLAG_INCONSISTENT:
1949 #if GTK_CHECK_VERSION(3, 18, 0)
1950 state_str = ":indeterminate";
1951 #endif
1952 break;
1953 case GTK_STATE_FLAG_BACKDROP:
1954 #if GTK_CHECK_VERSION(3, 18, 0)
1955 state_str = ":backdrop";
1956 #endif
1957 break;
1958 case GTK_STATE_FLAG_INSENSITIVE:
1959 #if GTK_CHECK_VERSION(3, 24, 0)
1960 state_str = ":disabled";
1961 #else
1962 state_str = ":insensitive";
1963 #endif
1964 break;
1965 default:
1966 state_str = "";
1967 }
1968 if (widget) {
1969 // special tweaks
1970 if (!selector) {
1971 if (GTK_IS_FRAME(widget)) {
1972 if (selector != xselector) lives_free(selector);
1973 selector = lives_strdup("label");
1974 } else if (GTK_IS_TEXT_VIEW(widget)) {
1975 if (selector != xselector) lives_free(selector);
1976 selector = lives_strdup("text");
1977 }
1978 if (GTK_IS_SPIN_BUTTON(widget)) {
1979 if (selector != xselector) lives_free(selector);
1980 selector = lives_strdup("*");
1981 }
1982 }
1983 }
1984
1985 if (!selector || !(*selector)) selstr = lives_strdup("");
1986 else selstr = lives_strdup_printf(" %s", selector);
1987 if (widget) {
1988 #if GTK_CHECK_VERSION(3, 24, 0)
1989 wname = lives_strdup_printf("#%s%s%s", widget_name, state_str, selstr);
1990 #else
1991 wname = lives_strdup_printf("#%s%s%s", widget_name, selstr, state_str);
1992 #endif
1993 } else {
1994 wname = lives_strdup_printf("%s%s%s", widget_name, selstr, state_str);
1995 }
1996 lives_free(selstr);
1997 if (selector && selector != xselector) lives_free(selector);
1998
1999 #ifdef GTK_TEXT_VIEW_CSS_BUG
2000 }
2001 #endif
2002
2003 lives_free(widget_name);
2004 css_string = g_strdup_printf(" %s {\n %s: %s;}\n", wname, detail, value);
2005
2006 if (show_css) g_print("running CSS %s\n", css_string);
2007
2008 #if GTK_CHECK_VERSION(4, 0, 0)
2009 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider),
2010 css_string, -1);
2011 #else
2012 gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider),
2013 css_string, -1, NULL);
2014 #endif
2015 lives_free(wname);
2016 lives_free(css_string);
2017 lives_widget_object_unref(provider);
2018 return TRUE;
2019 }
2020
2021
set_css_value(LiVESWidget * widget,LiVESWidgetState state,const char * detail,const char * value)2022 boolean set_css_value(LiVESWidget *widget, LiVESWidgetState state, const char *detail, const char *value) {
2023 if (state == GTK_STATE_FLAG_NORMAL) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_NORMAL, NULL, detail, value);
2024 if (state & GTK_STATE_FLAG_ACTIVE) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_ACTIVE, NULL, detail, value);
2025 if (state & GTK_STATE_FLAG_PRELIGHT) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_PRELIGHT, NULL, detail, value);
2026 if (state & GTK_STATE_FLAG_SELECTED) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_SELECTED, NULL, detail, value);
2027 if (state & GTK_STATE_FLAG_INSENSITIVE) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_INSENSITIVE, NULL, detail, value);
2028 if (state & GTK_STATE_FLAG_INCONSISTENT) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_INCONSISTENT, NULL, detail, value);
2029 if (state & GTK_STATE_FLAG_FOCUSED) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_FOCUSED, NULL, detail, value);
2030 if (state & GTK_STATE_FLAG_BACKDROP) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_BACKDROP, NULL, detail, value);
2031 if (state & GTK_STATE_FLAG_CHECKED) set_css_value_for_state_flag(widget, GTK_STATE_FLAG_CHECKED, NULL, detail, value);
2032 return TRUE;
2033 }
2034 #endif
2035 #endif
2036
2037
2038 #ifdef GUI_GTK
set_css_value_direct(LiVESWidget * widget,LiVESWidgetState state,const char * selector,const char * detail,const char * value)2039 boolean set_css_value_direct(LiVESWidget *widget, LiVESWidgetState state, const char *selector, const char *detail,
2040 const char *value) {
2041 #if GTK_CHECK_VERSION(3, 16, 0)
2042
2043 #if !GTK_CHECK_VERSION(3, 24, 0)
2044 if (!lives_strcmp(detail, "min-width")
2045 || !lives_strcmp(detail, "min-height")
2046 || !lives_strcmp(detail, "caret-color"))
2047 return FALSE;
2048 #endif
2049 return set_css_value_for_state_flag(widget, state, selector, detail, value);
2050 #endif
2051 return FALSE;
2052 }
2053 #endif
2054
2055
lives_widget_set_bg_color(LiVESWidget * widget,LiVESWidgetState state,const LiVESWidgetColor * color)2056 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_bg_color(LiVESWidget *widget, LiVESWidgetState state,
2057 const LiVESWidgetColor *color) {
2058 #ifdef GUI_GTK
2059 #if GTK_CHECK_VERSION(3, 0, 0)
2060 #if GTK_CHECK_VERSION(3, 16, 0)
2061 char *colref = gdk_rgba_to_string(color);
2062 boolean retb = set_css_value(widget, state, "background-color", colref);
2063 if (retb) retb = lives_widget_set_base_color(widget, state, color);
2064 lives_free(colref);
2065 return retb;
2066 #else
2067 gtk_widget_override_background_color(widget, state, color);
2068 #endif
2069 #else
2070 gtk_widget_modify_bg(widget, state, color);
2071 gtk_widget_modify_base(widget, state, color);
2072 #endif
2073 return TRUE;
2074 #endif
2075 return FALSE;
2076 }
2077
2078
lives_widget_set_fg_color(LiVESWidget * widget,LiVESWidgetState state,const LiVESWidgetColor * color)2079 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_fg_color(LiVESWidget *widget, LiVESWidgetState state,
2080 const LiVESWidgetColor *color) {
2081 #ifdef GUI_GTK
2082 #if GTK_CHECK_VERSION(3, 0, 0)
2083 #if GTK_CHECK_VERSION(3, 16, 0)
2084 char *colref = gdk_rgba_to_string(color);
2085 boolean retb = set_css_value(widget, state, "color", colref);
2086 lives_free(colref);
2087 return retb;
2088 #else
2089 gtk_widget_override_color(widget, state, color);
2090 #endif
2091 #else
2092 gtk_widget_modify_text(widget, state, color);
2093 gtk_widget_modify_fg(widget, state, color);
2094 #endif
2095 return TRUE;
2096 #endif
2097 return FALSE;
2098 }
2099
2100
lives_widget_set_text_color(LiVESWidget * widget,LiVESWidgetState state,const LiVESWidgetColor * color)2101 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_text_color(LiVESWidget *widget, LiVESWidgetState state,
2102 const LiVESWidgetColor *color) {
2103 #ifdef GUI_GTK
2104 #if GTK_CHECK_VERSION(3, 0, 0)
2105 #if GTK_CHECK_VERSION(3, 16, 0)
2106 char *colref = gdk_rgba_to_string(color);
2107 boolean retb = set_css_value(widget, state, "color", colref);
2108 lives_free(colref);
2109 return retb;
2110 #else
2111 gtk_widget_override_color(widget, state, color);
2112 #endif
2113 #else
2114 gtk_widget_modify_text(widget, state, color);
2115 #endif
2116 return TRUE;
2117 #endif
2118 #ifdef GUI_QT
2119 widget->set_text_color(state, color);
2120 return TRUE;
2121 #endif
2122 return FALSE;
2123 }
2124
2125
lives_widget_set_base_color(LiVESWidget * widget,LiVESWidgetState state,const LiVESWidgetColor * color)2126 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_base_color(LiVESWidget *widget, LiVESWidgetState state,
2127 const LiVESWidgetColor *color) {
2128 #ifdef GUI_GTK
2129 #if GTK_CHECK_VERSION(3, 0, 0)
2130 #if GTK_CHECK_VERSION(3, 16, 0)
2131 char *colref = gdk_rgba_to_string(color);
2132 boolean retb = set_css_value(widget, state, "background", colref);
2133 lives_free(colref);
2134 return retb;
2135 #else
2136 gtk_widget_override_color(widget, state, color);
2137 #endif
2138 #else
2139 gtk_widget_modify_base(widget, state, color);
2140 #endif
2141 return TRUE;
2142 #endif
2143 #ifdef GUI_QT
2144 widget->set_base_color(state, color);
2145 return TRUE;
2146 #endif
2147 return FALSE;
2148 }
2149
2150
lives_widget_set_outline_color(LiVESWidget * widget,LiVESWidgetState state,const LiVESWidgetColor * color)2151 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_outline_color(LiVESWidget *widget, LiVESWidgetState state,
2152 const LiVESWidgetColor *color) {
2153 #ifdef GUI_GTK
2154 #if GTK_CHECK_VERSION(3, 16, 0)
2155 char *colref = gdk_rgba_to_string(color);
2156 boolean retb = set_css_value(widget, state, "outline-color", colref);
2157 lives_free(colref);
2158 return retb;
2159 #endif
2160 #endif
2161 return FALSE;
2162 }
2163
2164
lives_widget_set_border_color(LiVESWidget * widget,LiVESWidgetState state,const LiVESWidgetColor * color)2165 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_border_color(LiVESWidget *widget, LiVESWidgetState state,
2166 const LiVESWidgetColor *color) {
2167 #ifdef GUI_GTK
2168 #if GTK_CHECK_VERSION(3, 16, 0)
2169 char *colref = gdk_rgba_to_string(color);
2170 boolean retb = set_css_value(widget, state, "border-color", colref);
2171 lives_free(colref);
2172 return retb;
2173 #endif
2174 #endif
2175 return FALSE;
2176 }
2177
2178
lives_widget_set_text_size(LiVESWidget * widget,LiVESWidgetState state,const char * size)2179 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_text_size(LiVESWidget *widget, LiVESWidgetState state,
2180 const char *size) {
2181 #ifdef GUI_GTK
2182 #if GTK_CHECK_VERSION(3, 16, 0)
2183 boolean retb = set_css_value(widget, state, "font-size", size);
2184 return retb;
2185 #endif
2186 #endif
2187 return FALSE;
2188 }
2189
2190
lives_widget_get_fg_state_color(LiVESWidget * widget,LiVESWidgetState state,LiVESWidgetColor * color)2191 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_fg_state_color(LiVESWidget *widget, LiVESWidgetState state,
2192 LiVESWidgetColor *color) {
2193 #ifdef GUI_GTK
2194 #if GTK_CHECK_VERSION(3, 0, 0)
2195 #if GTK_CHECK_VERSION(4, 0, 0)
2196 gtk_style_context_get_color(gtk_widget_get_style_context(widget), color);
2197 #else
2198 gtk_style_context_get_color(gtk_widget_get_style_context(widget), lives_widget_get_state(widget), color);
2199 #endif
2200 #else
2201 lives_widget_color_copy(color, >k_widget_get_style(widget)->fg[LIVES_WIDGET_STATE_NORMAL]);
2202 #endif
2203 return TRUE;
2204 #endif
2205 #ifdef GUI_QT
2206 lives_widget_color_copy(color, widget->get_fg_color(state));
2207 return TRUE;
2208 #endif
2209 return FALSE;
2210 }
2211
2212
lives_widget_get_bg_state_color(LiVESWidget * widget,LiVESWidgetState state,LiVESWidgetColor * color)2213 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_bg_state_color(LiVESWidget *widget, LiVESWidgetState state,
2214 LiVESWidgetColor *color) {
2215 #ifdef GUI_GTK
2216 #if GTK_CHECK_VERSION(3, 0, 0)
2217 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2218 gtk_style_context_get_background_color(gtk_widget_get_style_context(widget), lives_widget_get_state(widget), color);
2219 G_GNUC_END_IGNORE_DEPRECATIONS
2220 #else
2221 lives_widget_color_copy(color, >k_widget_get_style(widget)->bg[LIVES_WIDGET_STATE_NORMAL]);
2222 #endif
2223 return TRUE;
2224 #endif
2225 #ifdef GUI_QT
2226 lives_widget_color_copy(color, widget->get_bg_color(state));
2227 return TRUE;
2228 #endif
2229 return FALSE;
2230 }
2231
2232
lives_widget_color_equal(LiVESWidgetColor * c1,const LiVESWidgetColor * c2)2233 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_color_equal(LiVESWidgetColor *c1, const LiVESWidgetColor *c2) {
2234 #ifdef GUI_GTK
2235 #if LIVES_WIDGET_COLOR_HAS_ALPHA
2236 if (c1->alpha != c2->alpha) return FALSE;
2237 #endif
2238 if (c1->red != c2->red || c1->green != c2->green || c1->blue != c2->blue) return FALSE;
2239 return TRUE;
2240 #endif
2241 return FALSE;
2242 }
2243
2244
lives_widget_color_mix(LiVESWidgetColor * c1,const LiVESWidgetColor * c2,float mixval)2245 boolean lives_widget_color_mix(LiVESWidgetColor *c1, const LiVESWidgetColor *c2, float mixval) {
2246 // c1 = mixval * c1 + (1. - mixval) * c2
2247 if (mixval < 0. || mixval > 1. || !c1 || !c2) return FALSE;
2248 #ifdef GUI_GTK
2249 c1->red = (float)c1->red * mixval + (float)c2->red * (1. - mixval);
2250 c1->green = (float)c1->green * mixval + (float)c2->green * (1. - mixval);
2251 c1->blue = (float)c1->blue * mixval + (float)c2->blue * (1. - mixval);
2252 return TRUE;
2253 #endif
2254 return FALSE;
2255 }
2256
2257
lives_widget_color_copy(LiVESWidgetColor * c1,const LiVESWidgetColor * c2)2258 WIDGET_HELPER_GLOBAL_INLINE LiVESWidgetColor *lives_widget_color_copy(LiVESWidgetColor *c1, const LiVESWidgetColor *c2) {
2259 // if c1 is NULL, create a new copy of c2, otherwise copy c2 -> c1
2260 LiVESWidgetColor *c0 = NULL;
2261 #ifdef GUI_GTK
2262 if (c1) {
2263 c1->red = c2->red;
2264 c1->green = c2->green;
2265 c1->blue = c2->blue;
2266 #if GTK_CHECK_VERSION(3, 0, 0)
2267 c1->alpha = c2->alpha;
2268 #else
2269 c1->pixel = c2->pixel;
2270 #endif
2271 } else {
2272 #if GTK_CHECK_VERSION(3, 0, 0)
2273 c0 = gdk_rgba_copy(c2);
2274 #else
2275 c0 = gdk_color_copy(c2);
2276 #endif
2277 }
2278 #endif
2279
2280 return c0;
2281 }
2282
2283
lives_event_box_new(void)2284 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_event_box_new(void) {
2285 LiVESWidget *eventbox = NULL;
2286 #ifdef GUI_GTK
2287 eventbox = gtk_event_box_new();
2288 #endif
2289 #ifdef GUI_QT
2290 eventbox = new LiVESEventBox;
2291 #endif
2292 return eventbox;
2293 }
2294
2295
lives_event_box_set_above_child(LiVESEventBox * ebox,boolean set)2296 WIDGET_HELPER_GLOBAL_INLINE boolean lives_event_box_set_above_child(LiVESEventBox *ebox, boolean set) {
2297 #ifdef GUI_GTK
2298 gtk_event_box_set_above_child(ebox, set);
2299 return TRUE;
2300 #endif
2301 #ifdef GUI_QT
2302 return TRUE;
2303 #endif
2304 return FALSE;
2305 }
2306
2307
lives_image_new(void)2308 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_image_new(void) {
2309 LiVESWidget *image = NULL;
2310 #ifdef GUI_GTK
2311 image = gtk_image_new();
2312 #endif
2313 #ifdef GUI_QT
2314 image = new LiVESImage;
2315 #endif
2316 return image;
2317 }
2318
2319
get_real_size_from_icon_size(LiVESIconSize size)2320 WIDGET_HELPER_LOCAL_INLINE int get_real_size_from_icon_size(LiVESIconSize size) {
2321 switch (size) {
2322 case LIVES_ICON_SIZE_SMALL_TOOLBAR:
2323 case LIVES_ICON_SIZE_BUTTON:
2324 case LIVES_ICON_SIZE_MENU:
2325 return 16;
2326 case LIVES_ICON_SIZE_LARGE_TOOLBAR:
2327 return 24;
2328 case LIVES_ICON_SIZE_DND:
2329 return 32;
2330 case LIVES_ICON_SIZE_DIALOG:
2331 return 48;
2332 default:
2333 break;
2334 }
2335 return -1;
2336 }
2337
2338
lives_pixbuf_new_from_stock_at_size(const char * stock_id,LiVESIconSize size,int x,int y)2339 LiVESPixbuf *lives_pixbuf_new_from_stock_at_size(const char *stock_id, LiVESIconSize size, int x, int y) {
2340 LiVESPixbuf *pixbuf = NULL;
2341 LiVESWidget *image = NULL;
2342 if (size == LIVES_ICON_SIZE_CUSTOM) {
2343 if (x == y) {
2344 if (x == get_real_size_from_icon_size(LIVES_ICON_SIZE_MENU)) size = LIVES_ICON_SIZE_MENU;
2345 if (x == get_real_size_from_icon_size(LIVES_ICON_SIZE_SMALL_TOOLBAR))
2346 size = LIVES_ICON_SIZE_SMALL_TOOLBAR;
2347 if (x == get_real_size_from_icon_size(LIVES_ICON_SIZE_LARGE_TOOLBAR))
2348 size = LIVES_ICON_SIZE_LARGE_TOOLBAR;
2349 if (x == get_real_size_from_icon_size(LIVES_ICON_SIZE_BUTTON)) size = LIVES_ICON_SIZE_BUTTON;
2350 if (x == get_real_size_from_icon_size(LIVES_ICON_SIZE_DND)) size = LIVES_ICON_SIZE_DND;
2351 if (x == get_real_size_from_icon_size(LIVES_ICON_SIZE_DIALOG)) size = LIVES_ICON_SIZE_DIALOG;
2352 }
2353 }
2354
2355 if (size != LIVES_ICON_SIZE_CUSTOM) {
2356 if (lives_has_icon(widget_opts.icon_theme, stock_id, size)) {
2357 #if GTK_CHECK_VERSION(3, 10, 0)
2358 pixbuf = gtk_icon_theme_load_icon((LiVESIconTheme *)widget_opts.icon_theme, stock_id,
2359 get_real_size_from_icon_size(size),
2360 GTK_ICON_LOOKUP_FORCE_SIZE, NULL);
2361 return pixbuf;
2362 #else
2363 image = gtk_image_new_from_stock(stock_id, size);
2364 #endif
2365 }
2366 if (image) return lives_image_get_pixbuf(LIVES_IMAGE(image));
2367 }
2368
2369 // custom size, or failed at specified size
2370 // try all sizes to see if we get one
2371 if (!image) {
2372 if (lives_has_icon(widget_opts.icon_theme, stock_id, LIVES_ICON_SIZE_DIALOG)) {
2373 size = LIVES_ICON_SIZE_DIALOG;
2374 } else if (lives_has_icon(widget_opts.icon_theme, stock_id, LIVES_ICON_SIZE_DND)) {
2375 size = LIVES_ICON_SIZE_DND;
2376 } else if (lives_has_icon(widget_opts.icon_theme, stock_id, LIVES_ICON_SIZE_LARGE_TOOLBAR)) {
2377 size = LIVES_ICON_SIZE_LARGE_TOOLBAR;
2378 } else if (lives_has_icon(widget_opts.icon_theme, stock_id, LIVES_ICON_SIZE_SMALL_TOOLBAR)) {
2379 size = LIVES_ICON_SIZE_SMALL_TOOLBAR;
2380 } else if (lives_has_icon(widget_opts.icon_theme, stock_id, LIVES_ICON_SIZE_BUTTON)) {
2381 size = LIVES_ICON_SIZE_BUTTON;
2382 } else if (lives_has_icon(widget_opts.icon_theme, stock_id, LIVES_ICON_SIZE_MENU)) {
2383 size = LIVES_ICON_SIZE_MENU;
2384 } else return NULL;
2385
2386 #if GTK_CHECK_VERSION(3, 10, 0)
2387 pixbuf = gtk_icon_theme_load_icon((LiVESIconTheme *)widget_opts.icon_theme, stock_id,
2388 get_real_size_from_icon_size(size),
2389 GTK_ICON_LOOKUP_FORCE_SIZE, NULL);
2390 return pixbuf;
2391 #else
2392 image = gtk_image_new_from_stock(stock_id, size);
2393 #endif
2394 if (!image) return NULL;
2395 pixbuf = lives_image_get_pixbuf(LIVES_IMAGE(image));
2396 }
2397 return pixbuf;
2398 }
2399
2400
lives_image_new_from_stock_at_size(const char * stock_id,LiVESIconSize size,int x,int y)2401 LiVESWidget *lives_image_new_from_stock_at_size(const char *stock_id, LiVESIconSize size, int x, int y) {
2402 LiVESWidget *image = NULL;
2403 LiVESPixbuf *pixbuf = lives_pixbuf_new_from_stock_at_size(stock_id, size, x, y);
2404 if (pixbuf) {
2405 image = lives_image_new_from_pixbuf(pixbuf);
2406 lives_widget_object_unref(pixbuf);
2407 }
2408 return image;
2409 }
2410
2411
lives_image_new_from_stock(const char * stock_id,LiVESIconSize size)2412 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_image_new_from_stock(const char *stock_id,
2413 LiVESIconSize size) {
2414 return lives_image_new_from_stock_at_size(stock_id, size, get_real_size_from_icon_size(size),
2415 get_real_size_from_icon_size(size));
2416 }
2417
2418
lives_image_new_from_file(const char * filename)2419 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_image_new_from_file(const char *filename) {
2420 LiVESWidget *image = NULL;
2421 #ifdef GUI_GTK
2422 image = gtk_image_new_from_file(filename);
2423 #endif
2424 return image;
2425 }
2426
2427
lives_image_new_from_pixbuf(LiVESPixbuf * pixbuf)2428 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_image_new_from_pixbuf(LiVESPixbuf *pixbuf) {
2429 LiVESWidget *image = NULL;
2430 #ifdef GUI_GTK
2431 image = gtk_image_new_from_pixbuf(pixbuf);
2432 #endif
2433 #ifdef GUI_QT
2434 image = new LiVESImage(static_cast<QImage *>(pixbuf));
2435 #endif
2436 return image;
2437 }
2438
2439
lives_image_set_from_pixbuf(LiVESImage * image,LiVESPixbuf * pixbuf)2440 WIDGET_HELPER_GLOBAL_INLINE boolean lives_image_set_from_pixbuf(LiVESImage *image, LiVESPixbuf *pixbuf) {
2441 #ifdef GUI_GTK
2442 gtk_image_set_from_pixbuf(image, pixbuf);
2443 return TRUE;
2444 #endif
2445 #ifdef GUI_QT
2446 *(static_cast<QImage *>(image)) = pixbuf->copy(0, 0, (static_cast<QImage *>(pixbuf))->width(),
2447 (static_cast<QImage *>(pixbuf))->height());
2448 return TRUE;
2449 #endif
2450 return FALSE;
2451 }
2452
2453
lives_image_get_pixbuf(LiVESImage * image)2454 WIDGET_HELPER_GLOBAL_INLINE LiVESPixbuf *lives_image_get_pixbuf(LiVESImage *image) {
2455 LiVESPixbuf *pixbuf = NULL;
2456 #ifdef GUI_GTK
2457 pixbuf = gtk_image_get_pixbuf(image);
2458 #endif
2459 #ifdef GUI_QT
2460 pixbuf = new LiVESPixbuf(image);
2461 #endif
2462 return pixbuf;
2463 }
2464
2465
lives_color_parse(const char * spec,LiVESWidgetColor * color)2466 WIDGET_HELPER_GLOBAL_INLINE boolean lives_color_parse(const char *spec, LiVESWidgetColor *color) {
2467 boolean retval = FALSE;
2468 #ifdef GUI_GTK
2469 #if GTK_CHECK_VERSION(3, 0, 0)
2470 retval = gdk_rgba_parse(color, spec);
2471 #else
2472 retval = gdk_color_parse(spec, color);
2473 #endif
2474 #endif
2475 return retval;
2476 }
2477
2478
lives_dialog_get_content_area(LiVESDialog * dialog)2479 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_dialog_get_content_area(LiVESDialog *dialog) {
2480 #ifdef GUI_GTK
2481
2482 #if GTK_CHECK_VERSION(2, 14, 0)
2483 return gtk_dialog_get_content_area(LIVES_DIALOG(dialog));
2484 #else
2485 return LIVES_DIALOG(dialog)->vbox;
2486 #endif
2487 #endif
2488 #ifdef GUI_QT
2489 return dialog->get_content_area();
2490 #endif
2491 return NULL;
2492 }
2493
2494
lives_dialog_get_action_area(LiVESDialog * dialog)2495 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_dialog_get_action_area(LiVESDialog *dialog) {
2496 #ifdef GUI_GTK
2497 #if GTK_CHECK_VERSION(2, 14, 0)
2498 #ifdef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2499 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
2500 #endif
2501 return gtk_dialog_get_action_area(LIVES_DIALOG(dialog));
2502 #ifdef G_GNUC_END_IGNORE_DEPRECATIONS
2503 G_GNUC_END_IGNORE_DEPRECATIONS
2504 #endif
2505 #else
2506 return LIVES_DIALOG(dialog)->vbox;
2507 #endif
2508 #endif
2509 #ifdef GUI_QT
2510 return dialog->get_action_area();
2511 #endif
2512 return NULL;
2513 }
2514
2515
lives_widget_set_margin_left(LiVESWidget * widget,int margin)2516 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_margin_left(LiVESWidget *widget, int margin) {
2517 #ifdef GUI_GTK
2518 #if GTK_CHECK_VERSION(3, 0, 0)
2519 #if GTK_CHECK_VERSION(3, 12, 0)
2520 gtk_widget_set_margin_start(widget, margin);
2521 #else
2522 gtk_widget_set_margin_left(widget, margin);
2523 #endif
2524 return TRUE;
2525 #endif
2526 #endif
2527 return FALSE;
2528 }
2529
2530
lives_widget_set_margin_right(LiVESWidget * widget,int margin)2531 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_margin_right(LiVESWidget *widget, int margin) {
2532 #ifdef GUI_GTK
2533 #if GTK_CHECK_VERSION(3, 0, 0)
2534 #if GTK_CHECK_VERSION(3, 12, 0)
2535 gtk_widget_set_margin_end(widget, margin);
2536 #else
2537 gtk_widget_set_margin_right(widget, margin);
2538 #endif
2539 return TRUE;
2540 #endif
2541 #endif
2542 return FALSE;
2543 }
2544
2545
lives_widget_set_margin_top(LiVESWidget * widget,int margin)2546 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_margin_top(LiVESWidget *widget, int margin) {
2547 #ifdef GUI_GTK
2548 #if GTK_CHECK_VERSION(3, 0, 0)
2549 gtk_widget_set_margin_top(widget, margin);
2550 return TRUE;
2551 #endif
2552 #endif
2553 return FALSE;
2554 }
2555
2556
lives_widget_set_margin_bottom(LiVESWidget * widget,int margin)2557 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_margin_bottom(LiVESWidget *widget, int margin) {
2558 #ifdef GUI_GTK
2559 #if GTK_CHECK_VERSION(3, 0, 0)
2560 gtk_widget_set_margin_bottom(widget, margin);
2561 return TRUE;
2562 #endif
2563 #endif
2564 return FALSE;
2565 }
2566
2567
lives_widget_set_margin(LiVESWidget * widget,int margin)2568 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_margin(LiVESWidget *widget, int margin) {
2569 #ifdef GUI_GTK
2570 #if GTK_CHECK_VERSION(3, 0, 0)
2571 lives_widget_set_margin_bottom(widget, margin);
2572 lives_widget_set_margin_top(widget, margin);
2573 lives_widget_set_margin_left(widget, margin);
2574 lives_widget_set_margin_right(widget, margin);
2575 return TRUE;
2576 #endif
2577 #endif
2578 return FALSE;
2579 }
2580
2581
lives_widget_set_padding(LiVESWidget * widget,int padding)2582 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_padding(LiVESWidget *widget, int padding) {
2583 #ifdef GUI_GTK
2584 #if GTK_CHECK_VERSION(3, 16, 0)
2585 char *wpx = lives_strdup_printf("%dpx", padding);
2586 set_css_value_direct(widget, LIVES_WIDGET_STATE_NORMAL, "", "padding", wpx);
2587 lives_free(wpx);
2588 return TRUE;
2589 #endif
2590 #endif
2591 return FALSE;
2592 }
2593
2594
2595
lives_dialog_add_action_widget(LiVESDialog * dialog,LiVESWidget * widget,int response)2596 WIDGET_HELPER_GLOBAL_INLINE boolean lives_dialog_add_action_widget(LiVESDialog *dialog, LiVESWidget *widget, int response) {
2597 // TODO: use lives_dialog_add_button, lives_dialog_add_button_from_stock
2598 #ifdef GUI_GTK
2599 #if GTK_CHECK_VERSION(3, 0, 0)
2600 lives_widget_set_margin_left(widget, widget_opts.packing_width / 2);
2601 lives_widget_set_margin_right(widget, widget_opts.packing_width / 2);
2602 #endif
2603 gtk_dialog_add_action_widget(dialog, widget, response);
2604 gtk_box_set_spacing(LIVES_BOX(lives_widget_get_parent(widget)), widget_opts.packing_width * 4);
2605 return TRUE;
2606 #endif
2607 return FALSE;
2608 }
2609
2610
lives_window_new(LiVESWindowType wintype)2611 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_window_new(LiVESWindowType wintype) {
2612 LiVESWidget *window = NULL;
2613 #ifdef GUI_GTK
2614 window = gtk_window_new(wintype);
2615 #endif
2616 return window;
2617 }
2618
2619
lives_window_set_title(LiVESWindow * window,const char * title)2620 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_title(LiVESWindow *window, const char *title) {
2621 #ifdef GUI_GTK
2622 char *ntitle;
2623 if (*widget_opts.title_prefix) {
2624 ntitle = lives_strdup_printf("%s%s", widget_opts.title_prefix, title);
2625 } else ntitle = lives_strdup(title);
2626 gtk_window_set_title(window, ntitle);
2627 lives_free(ntitle);
2628 return TRUE;
2629 #endif
2630 return FALSE;
2631 }
2632
2633
lives_window_set_transient_for(LiVESWindow * window,LiVESWindow * parent)2634 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_transient_for(LiVESWindow *window, LiVESWindow *parent) {
2635 #ifdef GUI_GTK
2636 gtk_window_set_transient_for(window, parent);
2637 return TRUE;
2638 #endif
2639 return FALSE;
2640 }
2641
2642
modunmap(LiVESWindow * win,livespointer data)2643 static void modunmap(LiVESWindow *win, livespointer data) {if (win == modalw) modalw = NULL;}
moddest(LiVESWindow * win,livespointer data)2644 static void moddest(LiVESWindow *win, livespointer data) {if (win == modalw) modalw = NULL;}
moddelete(LiVESWindow * win,LiVESXEvent * event,livespointer data)2645 static boolean moddelete(LiVESWindow *win, LiVESXEvent *event, livespointer data) {
2646 if (win == modalw) modalw = NULL;
2647 return TRUE;
2648 }
2649
lives_window_set_modal(LiVESWindow * window,boolean modal)2650 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_modal(LiVESWindow *window, boolean modal) {
2651 if (window == modalw) {
2652 lives_signal_handlers_sync_disconnect_by_func(LIVES_GUI_OBJECT(modalw), LIVES_GUI_CALLBACK(moddest), NULL);
2653 lives_signal_handlers_sync_disconnect_by_func(LIVES_GUI_OBJECT(modalw), LIVES_GUI_CALLBACK(moddelete), NULL);
2654 lives_signal_handlers_sync_disconnect_by_func(LIVES_GUI_OBJECT(modalw), LIVES_GUI_CALLBACK(modunmap), NULL);
2655 modalw = NULL;
2656 }
2657 if (modal) {
2658 lives_signal_sync_connect(window, LIVES_WIDGET_DELETE_EVENT,
2659 LIVES_GUI_CALLBACK(moddelete), NULL);
2660 lives_signal_sync_connect(window, LIVES_WIDGET_DESTROY_SIGNAL,
2661 LIVES_GUI_CALLBACK(moddest), NULL);
2662 lives_signal_sync_connect(window, LIVES_WIDGET_UNMAP_SIGNAL,
2663 LIVES_GUI_CALLBACK(modunmap), NULL);
2664 modalw = window;
2665 }
2666 #ifdef GUI_GTK
2667 gtk_window_set_modal(window, modal);
2668 return TRUE;
2669 #endif
2670 return FALSE;
2671 }
2672
2673
lives_window_get_modal(LiVESWindow * window)2674 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_get_modal(LiVESWindow *window) {
2675 #ifdef GUI_GTK
2676 return gtk_window_get_modal(window);
2677 #endif
2678 return FALSE;
2679 }
2680
2681
lives_window_set_deletable(LiVESWindow * window,boolean deletable)2682 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_deletable(LiVESWindow *window, boolean deletable) {
2683 #ifdef GUI_GTK
2684 gtk_window_set_deletable(window, deletable);
2685 return TRUE;
2686 #endif
2687 return FALSE;
2688 }
2689
2690
lives_window_set_resizable(LiVESWindow * window,boolean resizable)2691 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_resizable(LiVESWindow *window, boolean resizable) {
2692 #ifdef GUI_GTK
2693 gtk_window_set_resizable(window, resizable);
2694 return TRUE;
2695 #endif
2696 return FALSE;
2697 }
2698
2699
lives_window_set_keep_below(LiVESWindow * window,boolean set)2700 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_keep_below(LiVESWindow *window, boolean set) {
2701 #ifdef GUI_GTK
2702 gtk_window_set_keep_below(window, set);
2703 return TRUE;
2704 #endif
2705 return FALSE;
2706 }
2707
2708
lives_window_set_keep_above(LiVESWindow * window,boolean set)2709 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_keep_above(LiVESWindow *window, boolean set) {
2710 #ifdef GUI_GTK
2711 gtk_window_set_keep_above(window, set);
2712 return TRUE;
2713 #endif
2714 return FALSE;
2715 }
2716
2717
lives_window_set_decorated(LiVESWindow * window,boolean set)2718 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_decorated(LiVESWindow *window, boolean set) {
2719 #ifdef GUI_GTK
2720 gtk_window_set_decorated(window, set);
2721 return TRUE;
2722 #endif
2723 return FALSE;
2724 }
2725
2726
lives_window_set_auto_startup_notification(boolean set)2727 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_auto_startup_notification(boolean set) {
2728 #ifdef GUI_GTK
2729 gtk_window_set_auto_startup_notification(set);
2730 return TRUE;
2731 #endif
2732 #ifdef GUI_QT
2733 // TODO
2734 #endif
2735
2736 return FALSE;
2737 }
2738
2739
2740 /* WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_screen(LiVESWindow *window, LiVESXScreen *screen) { */
2741 /* if (LIVES_IS_WINDOW(window)) { */
2742 /* #ifdef GUI_GTK */
2743 /* gtk_window_set_screen(window, screen); */
2744 /* return TRUE; */
2745 /* #endif */
2746 /* } */
2747 /* return FALSE; */
2748 /* } */
2749
2750
lives_window_set_monitor(LiVESWindow * window,int monnum)2751 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_monitor(LiVESWindow *window, int monnum) {
2752 #ifdef GUI_GTK
2753 if (LIVES_IS_WINDOW(window)) {
2754 #if !GTK_CHECK_VERSION(3, 20, 0)
2755 gtk_window_set_screen(window, mainw->mgeom[monnum].screen);
2756 #else
2757 gtk_window_fullscreen_on_monitor(window, mainw->mgeom[monnum].screen, monnum);
2758 gtk_window_unfullscreen(window);
2759 #endif
2760 return TRUE;
2761 }
2762 #endif
2763 return FALSE;
2764 }
2765
2766
lives_window_set_default_size(LiVESWindow * window,int width,int height)2767 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_default_size(LiVESWindow *window, int width, int height) {
2768 #ifdef GUI_GTK
2769 gtk_window_set_default_size(window, width, height);
2770 return TRUE;
2771 #endif
2772 #ifdef GUI_QT
2773 if (LIVES_IS_WINDOW(window)) {
2774 window->resize(width, height);
2775 }
2776 return TRUE;
2777 #endif
2778 return FALSE;
2779 }
2780
2781
lives_window_get_title(LiVESWindow * window)2782 WIDGET_HELPER_GLOBAL_INLINE const char *lives_window_get_title(LiVESWindow *window) {
2783 #ifdef GUI_GTK
2784 return gtk_window_get_title(window);
2785 #endif
2786 #ifdef GUI_QT
2787 return (const char *)window->windowTitle().toUtf8().constData();
2788 #endif
2789 return NULL;
2790 }
2791
2792
lives_window_move(LiVESWindow * window,int x,int y)2793 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_move(LiVESWindow *window, int x, int y) {
2794 #ifdef GUI_GTK
2795 gtk_window_move(window, x, y);
2796 return TRUE;
2797 #endif
2798 return FALSE;
2799 }
2800
2801
lives_widget_get_position(LiVESWidget * widget,int * x,int * y)2802 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_position(LiVESWidget *widget, int *x, int *y) {
2803 #ifdef GUI_GTK
2804 GdkWindow *window = lives_widget_get_xwindow(widget);
2805 if (x) *x = 0;
2806 if (y) *y = 0;
2807 if (GDK_IS_WINDOW(window))
2808 gdk_window_get_position(window, x, y);
2809 return TRUE;
2810 #endif
2811 return FALSE;
2812 }
2813
2814
lives_window_get_position(LiVESWindow * window,int * x,int * y)2815 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_get_position(LiVESWindow *window, int *x, int *y) {
2816 #ifdef GUI_GTK
2817 gtk_window_get_position(window, x, y);
2818 return TRUE;
2819 #endif
2820 return FALSE;
2821 }
2822
2823
lives_window_set_position(LiVESWindow * window,LiVESWindowPosition pos)2824 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_position(LiVESWindow *window, LiVESWindowPosition pos) {
2825 #ifdef GUI_GTK
2826 gtk_window_set_position(window, pos);
2827 return TRUE;
2828 #endif
2829 return FALSE;
2830 }
2831
2832
lives_window_set_hide_titlebar_when_maximized(LiVESWindow * window,boolean setting)2833 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_hide_titlebar_when_maximized(LiVESWindow *window, boolean setting) {
2834 #ifdef GUI_GTK
2835 #if GTK_CHECK_VERSION(3, 4, 0)
2836 gtk_window_set_hide_titlebar_when_maximized(window, setting);
2837 #endif
2838 return TRUE;
2839 #endif
2840 #ifdef GUI_QT
2841 // TODO
2842 #endif
2843 return FALSE;
2844 }
2845
2846
lives_window_resize(LiVESWindow * window,int width,int height)2847 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_resize(LiVESWindow *window, int width, int height) {
2848 #ifdef GUI_GTK
2849 gtk_window_resize(window, width, height);
2850 gtk_widget_set_size_request(GTK_WIDGET(window), width, height);
2851 return TRUE;
2852 #endif
2853 // TODO
2854 return FALSE;
2855 }
2856
2857
lives_window_present(LiVESWindow * window)2858 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_present(LiVESWindow *window) {
2859 #ifdef GUI_GTK
2860 gtk_window_present(window);
2861 return TRUE;
2862 #endif
2863 #ifdef GUI_QT
2864 window->raise();
2865 return TRUE;
2866 #endif
2867 return FALSE;
2868 }
2869
2870
lives_window_fullscreen(LiVESWindow * window)2871 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_fullscreen(LiVESWindow *window) {
2872 #ifdef GUI_GTK
2873 gtk_window_fullscreen(window);
2874 return TRUE;
2875 #endif
2876 return FALSE;
2877 }
2878
2879
lives_window_unfullscreen(LiVESWindow * window)2880 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_unfullscreen(LiVESWindow *window) {
2881 #ifdef GUI_GTK
2882 gtk_window_unfullscreen(window);
2883 return TRUE;
2884 #endif
2885 return FALSE;
2886 }
2887
2888
lives_window_maximize(LiVESWindow * window)2889 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_maximize(LiVESWindow *window) {
2890 #ifdef GUI_GTK
2891 gtk_window_maximize(window);
2892 return TRUE;
2893 #endif
2894 return FALSE;
2895 }
2896
2897
lives_window_unmaximize(LiVESWindow * window)2898 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_unmaximize(LiVESWindow *window) {
2899 #ifdef GUI_GTK
2900 gtk_window_unmaximize(window);
2901 return TRUE;
2902 #endif
2903 return FALSE;
2904 }
2905
2906
lives_window_get_focus(LiVESWindow * window)2907 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_window_get_focus(LiVESWindow *window) {
2908 #ifdef GUI_GTK
2909 return gtk_window_get_focus(window);
2910 #endif
2911 return NULL;
2912 }
2913
2914
lives_accel_group_new(void)2915 WIDGET_HELPER_GLOBAL_INLINE LiVESAccelGroup *lives_accel_group_new(void) {
2916 LiVESAccelGroup *group = NULL;
2917 #ifdef GUI_GTK
2918 group = gtk_accel_group_new();
2919 #endif
2920 #ifdef GUI_QT
2921 group = new LiVESAccelGroup;
2922 #endif
2923 return group;
2924 }
2925
2926
lives_accel_group_connect(LiVESAccelGroup * group,uint32_t key,LiVESXModifierType mod,LiVESAccelFlags flags,LiVESWidgetClosure * closure)2927 WIDGET_HELPER_GLOBAL_INLINE boolean lives_accel_group_connect(LiVESAccelGroup *group, uint32_t key, LiVESXModifierType mod,
2928 LiVESAccelFlags flags, LiVESWidgetClosure *closure) {
2929 #ifdef GUI_GTK
2930 gtk_accel_group_connect(group, key, mod, flags, closure);
2931 return TRUE;
2932 #endif
2933 #ifdef GUI_QT
2934 group->connect(key, mod, flags, closure);
2935 return FALSE;
2936 #endif
2937 }
2938
2939
lives_accel_group_disconnect(LiVESAccelGroup * group,LiVESWidgetClosure * closure)2940 WIDGET_HELPER_GLOBAL_INLINE boolean lives_accel_group_disconnect(LiVESAccelGroup *group, LiVESWidgetClosure *closure) {
2941 #ifdef GUI_GTK
2942 gtk_accel_group_disconnect(group, closure);
2943 return TRUE;
2944 #endif
2945 #ifdef GUI_QT
2946 group->disconnect(closure);
2947 return TRUE;
2948 #endif
2949 return FALSE;
2950 }
2951
2952
lives_widget_add_accelerator(LiVESWidget * widget,const char * accel_signal,LiVESAccelGroup * accel_group,uint32_t accel_key,LiVESXModifierType accel_mods,LiVESAccelFlags accel_flags)2953 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_add_accelerator(LiVESWidget *widget, const char *accel_signal,
2954 LiVESAccelGroup *accel_group,
2955 uint32_t accel_key, LiVESXModifierType accel_mods, LiVESAccelFlags accel_flags) {
2956 #ifdef GUI_GTK
2957 gtk_widget_add_accelerator(widget, accel_signal, accel_group, accel_key, accel_mods, accel_flags);
2958 return TRUE;
2959 #endif
2960 #ifdef GUI_QT
2961 widget->add_accel(accel_signal, accel_group, accel_key, accel_mods, accel_flags);
2962 return TRUE;
2963 #endif
2964 return FALSE;
2965 }
2966
2967
lives_window_add_accel_group(LiVESWindow * window,LiVESAccelGroup * group)2968 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_add_accel_group(LiVESWindow *window, LiVESAccelGroup *group) {
2969 #ifdef GUI_GTK
2970 gtk_window_add_accel_group(window, group);
2971 return TRUE;
2972 #endif
2973 #ifdef GUI_QT
2974 window->add_accel_group(group);
2975 return TRUE;
2976 #endif
2977 return FALSE;
2978 }
2979
2980
lives_widget_has_focus(LiVESWidget * widget)2981 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_has_focus(LiVESWidget *widget) {
2982 /// physical
2983 #ifdef GUI_GTK
2984 return gtk_widget_has_focus(widget);
2985 #endif
2986 return FALSE;
2987 }
2988
2989
lives_widget_is_focus(LiVESWidget * widget)2990 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_is_focus(LiVESWidget *widget) {
2991 /// logical
2992 #ifdef GUI_GTK
2993 return gtk_widget_is_focus(widget);
2994 #endif
2995 return FALSE;
2996 }
2997
2998
lives_widget_has_default(LiVESWidget * widget)2999 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_has_default(LiVESWidget *widget) {
3000 #ifdef GUI_GTK
3001 return gtk_widget_has_default(widget);
3002 #endif
3003 return FALSE;
3004 }
3005
3006
lives_window_remove_accel_group(LiVESWindow * window,LiVESAccelGroup * group)3007 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_remove_accel_group(LiVESWindow *window, LiVESAccelGroup *group) {
3008 #ifdef GUI_GTK
3009 gtk_window_remove_accel_group(window, group);
3010 return TRUE;
3011 #endif
3012 #ifdef GUI_QT
3013 window->remove_accel_group(group);
3014 return TRUE;
3015 #endif
3016 return FALSE;
3017 }
3018
3019
lives_menu_set_accel_group(LiVESMenu * menu,LiVESAccelGroup * group)3020 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_set_accel_group(LiVESMenu *menu, LiVESAccelGroup *group) {
3021 #ifdef GUI_GTK
3022 gtk_menu_set_accel_group(menu, group);
3023 return TRUE;
3024 #endif
3025 #ifdef GUI_QT
3026 menu->add_accel_group(group);
3027 return TRUE;
3028 #endif
3029 return FALSE;
3030 }
3031
3032
lives_accel_groups_activate(LiVESWidgetObject * object,uint32_t key,LiVESXModifierType mod)3033 WIDGET_HELPER_GLOBAL_INLINE boolean lives_accel_groups_activate(LiVESWidgetObject *object, uint32_t key,
3034 LiVESXModifierType mod) {
3035 #ifdef GUI_GTK
3036 gtk_accel_groups_activate(object, key, mod);
3037 return TRUE;
3038 #endif
3039 #ifdef GUI_QT
3040 object->activate_accel(key, mod);
3041 return TRUE;
3042 #endif
3043 return FALSE;
3044 }
3045
3046
lives_pixbuf_new(boolean has_alpha,int width,int height)3047 WIDGET_HELPER_GLOBAL_INLINE LiVESPixbuf *lives_pixbuf_new(boolean has_alpha, int width, int height) {
3048 #ifdef GUI_GTK
3049 // alpha fmt is RGBA post mult
3050 return gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, width, height);
3051 #endif
3052 return NULL;
3053 }
3054
3055
lives_pixbuf_copy(LiVESPixbuf * orig)3056 WIDGET_HELPER_GLOBAL_INLINE LiVESPixbuf *lives_pixbuf_copy(LiVESPixbuf *orig) {
3057 #ifdef GUI_GTK
3058 // alpha fmt is RGBA post mult
3059 return gdk_pixbuf_copy(orig);
3060 #endif
3061 return NULL;
3062 }
3063
3064
lives_pixbuf_new_from_data(const unsigned char * buf,boolean has_alpha,int width,int height,int rowstride,LiVESPixbufDestroyNotify lives_free_buffer_fn,livespointer destroy_fn_data)3065 WIDGET_HELPER_GLOBAL_INLINE LiVESPixbuf *lives_pixbuf_new_from_data(const unsigned char *buf, boolean has_alpha, int width,
3066 int height,
3067 int rowstride, LiVESPixbufDestroyNotify lives_free_buffer_fn,
3068 livespointer destroy_fn_data) {
3069 #ifdef GUI_GTK
3070 return gdk_pixbuf_new_from_data((const guchar *)buf, GDK_COLORSPACE_RGB, has_alpha, 8, width, height, rowstride,
3071 lives_free_buffer_fn,
3072 destroy_fn_data);
3073 #endif
3074 return NULL;
3075 }
3076
3077
lives_pixbuf_new_from_file(const char * filename,LiVESError ** error)3078 WIDGET_HELPER_GLOBAL_INLINE LiVESPixbuf *lives_pixbuf_new_from_file(const char *filename, LiVESError **error) {
3079 #ifdef GUI_GTK
3080 return gdk_pixbuf_new_from_file(filename, error);
3081 #endif
3082 return NULL;
3083 }
3084
3085
lives_pixbuf_new_from_file_at_scale(const char * filename,int width,int height,boolean preserve_aspect_ratio,LiVESError ** error)3086 WIDGET_HELPER_GLOBAL_INLINE LiVESPixbuf *lives_pixbuf_new_from_file_at_scale(const char *filename, int width, int height,
3087 boolean preserve_aspect_ratio,
3088 LiVESError **error) {
3089 #ifdef GUI_GTK
3090 return gdk_pixbuf_new_from_file_at_scale(filename, width, height, preserve_aspect_ratio, error);
3091 #endif
3092 return NULL;
3093 }
3094
3095
lives_pixbuf_get_rowstride(const LiVESPixbuf * pixbuf)3096 WIDGET_HELPER_GLOBAL_INLINE int lives_pixbuf_get_rowstride(const LiVESPixbuf *pixbuf) {
3097 #ifdef GUI_GTK
3098 return gdk_pixbuf_get_rowstride(pixbuf);
3099 #endif
3100
3101 #ifdef GUI_QT
3102 return (dynamic_cast<const QImage *>(pixbuf))->bytesPerLine();
3103 #endif
3104 }
3105
3106
lives_pixbuf_get_width(const LiVESPixbuf * pixbuf)3107 WIDGET_HELPER_GLOBAL_INLINE int lives_pixbuf_get_width(const LiVESPixbuf *pixbuf) {
3108 #ifdef GUI_GTK
3109 return gdk_pixbuf_get_width(pixbuf);
3110 #endif
3111
3112 #ifdef GUI_QT
3113 return (dynamic_cast<const QImage *>(pixbuf))->width();
3114 #endif
3115 }
3116
3117
lives_pixbuf_get_height(const LiVESPixbuf * pixbuf)3118 WIDGET_HELPER_GLOBAL_INLINE int lives_pixbuf_get_height(const LiVESPixbuf *pixbuf) {
3119 #ifdef GUI_GTK
3120 return gdk_pixbuf_get_height(pixbuf);
3121 #endif
3122
3123 #ifdef GUI_QT
3124 return (dynamic_cast<const QImage *>(pixbuf))->height();
3125 #endif
3126 }
3127
3128
lives_pixbuf_get_n_channels(const LiVESPixbuf * pixbuf)3129 WIDGET_HELPER_GLOBAL_INLINE int lives_pixbuf_get_n_channels(const LiVESPixbuf *pixbuf) {
3130 #ifdef GUI_GTK
3131 return gdk_pixbuf_get_n_channels(pixbuf);
3132 #endif
3133
3134 #ifdef GUI_QT
3135 return (dynamic_cast<const QImage *>(pixbuf))->depth() >> 3;
3136 #endif
3137 }
3138
3139
lives_pixbuf_get_pixels(const LiVESPixbuf * pixbuf)3140 WIDGET_HELPER_GLOBAL_INLINE unsigned char *lives_pixbuf_get_pixels(const LiVESPixbuf *pixbuf) {
3141 #ifdef GUI_GTK
3142 return gdk_pixbuf_get_pixels(pixbuf);
3143 #endif
3144
3145 #ifdef GUI_QT
3146 return (uchar *)(dynamic_cast<const QImage *>(pixbuf))->bits();
3147 #endif
3148 }
3149
3150
lives_pixbuf_get_pixels_readonly(const LiVESPixbuf * pixbuf)3151 WIDGET_HELPER_GLOBAL_INLINE const unsigned char *lives_pixbuf_get_pixels_readonly(const LiVESPixbuf *pixbuf) {
3152 #ifdef GUI_GTK
3153 return (const guchar *)gdk_pixbuf_get_pixels(pixbuf);
3154 #endif
3155
3156 #ifdef GUI_QT
3157 return (const uchar *)(dynamic_cast<const QImage *>(pixbuf))->bits();
3158 #endif
3159 }
3160
3161
lives_pixbuf_get_has_alpha(const LiVESPixbuf * pixbuf)3162 WIDGET_HELPER_GLOBAL_INLINE boolean lives_pixbuf_get_has_alpha(const LiVESPixbuf *pixbuf) {
3163 #ifdef GUI_GTK
3164 return gdk_pixbuf_get_has_alpha(pixbuf);
3165 #endif
3166
3167 #ifdef GUI_QT
3168 return (dynamic_cast<const QImage *>(pixbuf))->hasAlphaChannel();
3169 #endif
3170 }
3171
3172
lives_pixbuf_scale_simple(const LiVESPixbuf * src,int dest_width,int dest_height,LiVESInterpType interp_type)3173 WIDGET_HELPER_GLOBAL_INLINE LiVESPixbuf *lives_pixbuf_scale_simple(const LiVESPixbuf *src, int dest_width, int dest_height,
3174 LiVESInterpType interp_type) {
3175 #ifdef GUI_GTK
3176 return gdk_pixbuf_scale_simple(src, dest_width, dest_height, interp_type);
3177 #endif
3178 return NULL;
3179 }
3180
3181
lives_pixbuf_saturate_and_pixelate(const LiVESPixbuf * src,LiVESPixbuf * dest,float saturation,boolean pixilate)3182 WIDGET_HELPER_GLOBAL_INLINE boolean lives_pixbuf_saturate_and_pixelate(const LiVESPixbuf *src, LiVESPixbuf *dest,
3183 float saturation,
3184 boolean pixilate) {
3185 #ifdef GUI_GTK
3186 gdk_pixbuf_saturate_and_pixelate(src, dest, saturation, pixilate);
3187 return TRUE;
3188 #endif
3189 #ifdef GUI_QT
3190 // TODO
3191 #endif
3192 return FALSE;
3193 }
3194
3195
lives_adjustment_new(double value,double lower,double upper,double step_increment,double page_increment,double page_size)3196 WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment *lives_adjustment_new(double value, double lower, double upper,
3197 double step_increment, double page_increment, double page_size) {
3198 LiVESAdjustment *adj = NULL;
3199 #ifdef GUI_GTK
3200 #if GTK_CHECK_VERSION(3, 0, 0)
3201 adj = gtk_adjustment_new(value, lower, upper, step_increment, page_increment, page_size);
3202 #else
3203 adj = GTK_ADJUSTMENT(gtk_adjustment_new(value, lower, upper, step_increment, page_increment, page_size));
3204 #endif
3205 #endif
3206 #ifdef GUI_QT
3207 adj = new LiVESAdjustment(value, lower, upper, step_increment, page_increment, page_size);
3208 #endif
3209 return adj;
3210 }
3211
3212
lives_box_set_homogeneous(LiVESBox * box,boolean homogenous)3213 WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_set_homogeneous(LiVESBox *box, boolean homogenous) {
3214 #ifdef GUI_GTK
3215 gtk_box_set_homogeneous(box, homogenous);
3216 return TRUE;
3217 #endif
3218 #ifdef GUI_QT
3219 // TODO
3220 #endif
3221 return FALSE;
3222 }
3223
3224
lives_box_reorder_child(LiVESBox * box,LiVESWidget * child,int pos)3225 WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_reorder_child(LiVESBox *box, LiVESWidget *child, int pos) {
3226 #ifdef GUI_GTK
3227 gtk_box_reorder_child(box, child, pos);
3228 return TRUE;
3229 #endif
3230 return FALSE;
3231 }
3232
3233
lives_box_set_child_packing(LiVESBox * box,LiVESWidget * child,boolean expand,boolean fill,uint32_t padding,LiVESPackType pack_type)3234 LIVES_GLOBAL_INLINE boolean lives_box_set_child_packing(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill,
3235 uint32_t padding, LiVESPackType pack_type) {
3236 #ifdef GUI_GTK
3237 gtk_box_set_child_packing(box, child, expand, fill, padding, pack_type);
3238 return TRUE;
3239 #endif
3240 return FALSE;
3241 }
3242
3243
lives_box_set_spacing(LiVESBox * box,int spacing)3244 WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_set_spacing(LiVESBox *box, int spacing) {
3245 #ifdef GUI_GTK
3246 gtk_box_set_spacing(box, spacing);
3247 return TRUE;
3248 #endif
3249 return FALSE;
3250 }
3251
3252
lives_hbox_new(boolean homogeneous,int spacing)3253 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_hbox_new(boolean homogeneous, int spacing) {
3254 LiVESWidget *hbox = NULL;
3255 #ifdef GUI_GTK
3256 #if GTK_CHECK_VERSION(3, 0, 0)
3257 hbox = gtk_box_new(LIVES_ORIENTATION_HORIZONTAL, spacing);
3258 lives_box_set_homogeneous(LIVES_BOX(hbox), homogeneous);
3259 #else
3260 hbox = gtk_hbox_new(homogeneous, spacing);
3261 #endif
3262 #endif
3263 return hbox;
3264 }
3265
3266
lives_vbox_new(boolean homogeneous,int spacing)3267 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_vbox_new(boolean homogeneous, int spacing) {
3268 LiVESWidget *vbox = NULL;
3269 #ifdef GUI_GTK
3270 #if GTK_CHECK_VERSION(3, 0, 0)
3271 vbox = gtk_box_new(LIVES_ORIENTATION_VERTICAL, spacing);
3272 lives_box_set_homogeneous(LIVES_BOX(vbox), homogeneous);
3273 #else
3274 vbox = gtk_vbox_new(homogeneous, spacing);
3275 #endif
3276 #endif
3277 return vbox;
3278 }
3279
3280
lives_box_pack_start(LiVESBox * box,LiVESWidget * child,boolean expand,boolean fill,uint32_t padding)3281 WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_start(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill,
3282 uint32_t padding) {
3283 #ifdef GUI_GTK
3284 gtk_box_pack_start(box, child, expand, fill, padding);
3285 return TRUE;
3286 #endif
3287 return FALSE;
3288 }
3289
3290
lives_box_pack_end(LiVESBox * box,LiVESWidget * child,boolean expand,boolean fill,uint32_t padding)3291 WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_end(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill,
3292 uint32_t padding) {
3293 #ifdef GUI_GTK
3294 gtk_box_pack_end(box, child, expand, fill, padding);
3295 return TRUE;
3296 #endif
3297 return FALSE;
3298 }
3299
3300
lives_hseparator_new(void)3301 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_hseparator_new(void) {
3302 LiVESWidget *hsep = NULL;
3303 #ifdef GUI_GTK
3304 #if GTK_CHECK_VERSION(3, 0, 0)
3305 hsep = gtk_separator_new(LIVES_ORIENTATION_HORIZONTAL);
3306 #else
3307 hsep = gtk_hseparator_new();
3308 #endif
3309 lives_widget_set_size_request(hsep, -1, 1);
3310 #endif
3311 return hsep;
3312 }
3313
3314
lives_vseparator_new(void)3315 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_vseparator_new(void) {
3316 LiVESWidget *vsep = NULL;
3317 #ifdef GUI_GTK
3318 #if GTK_CHECK_VERSION(3, 0, 0)
3319 vsep = gtk_separator_new(LIVES_ORIENTATION_VERTICAL);
3320 #else
3321 vsep = gtk_vseparator_new();
3322 #endif
3323 lives_widget_set_size_request(vsep, 1, -1);
3324 #endif
3325 return vsep;
3326 }
3327
3328
lives_hbutton_box_new(void)3329 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_hbutton_box_new(void) {
3330 LiVESWidget *bbox = NULL;
3331 #ifdef GUI_GTK
3332 #if GTK_CHECK_VERSION(3, 0, 0)
3333 bbox = gtk_button_box_new(LIVES_ORIENTATION_HORIZONTAL);
3334 #else
3335 bbox = gtk_hbutton_box_new();
3336 #endif
3337 #endif
3338 return bbox;
3339 }
3340
3341
lives_vbutton_box_new(void)3342 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_vbutton_box_new(void) {
3343 LiVESWidget *bbox = NULL;
3344 #ifdef GUI_GTK
3345 #if GTK_CHECK_VERSION(3, 0, 0)
3346 bbox = gtk_button_box_new(LIVES_ORIENTATION_VERTICAL);
3347 #else
3348 bbox = gtk_vbutton_box_new();
3349 #endif
3350 #endif
3351 return bbox;
3352 }
3353
3354
lives_button_box_set_layout(LiVESButtonBox * bbox,LiVESButtonBoxStyle bstyle)3355 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_box_set_layout(LiVESButtonBox *bbox, LiVESButtonBoxStyle bstyle) {
3356 #ifdef GUI_GTK
3357 #if !GTK_CHECK_VERSION(3, 12, 0)
3358 if (bstyle == LIVES_BUTTONBOX_EXPAND) {
3359 gtk_box_set_homogeneous(GTK_BOX(bbox), TRUE);
3360 gtk_box_set_spacing(GTK_BOX(bbox), 0);
3361 return TRUE;
3362 }
3363 #endif
3364 gtk_button_box_set_layout(bbox, bstyle);
3365 return TRUE;
3366 #endif
3367 return FALSE;
3368 }
3369
3370
3371 WIDGET_HELPER_GLOBAL_INLINE
lives_button_box_set_child_non_homogeneous(LiVESButtonBox * bbox,LiVESWidget * child,boolean set)3372 boolean lives_button_box_set_child_non_homogeneous(LiVESButtonBox *bbox, LiVESWidget *child, boolean set) {
3373 #ifdef GUI_GTK
3374 #if GTK_CHECK_VERSION(3, 2, 0)
3375 gtk_button_box_set_child_non_homogeneous(bbox, child, set);
3376 return TRUE;
3377 #endif
3378 #endif
3379 return FALSE;
3380 }
3381
3382
lives_vscale_new(LiVESAdjustment * adj)3383 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_vscale_new(LiVESAdjustment *adj) {
3384 LiVESWidget *vscale = NULL;
3385 #ifdef GUI_GTK
3386 #if GTK_CHECK_VERSION(3, 0, 0)
3387 vscale = gtk_scale_new(LIVES_ORIENTATION_VERTICAL, adj);
3388 #else
3389 vscale = gtk_vscale_new(adj);
3390 #endif
3391 #endif
3392 #ifdef GUI_QT
3393 vscale = new LiVESScale(LIVES_ORIENTATION_VERTICAL, adj);
3394 #endif
3395 return vscale;
3396 }
3397
3398
lives_hpaned_new(void)3399 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_hpaned_new(void) {
3400 LiVESWidget *hpaned = NULL;
3401 #ifdef GUI_GTK
3402 #if GTK_CHECK_VERSION(3, 0, 0)
3403 hpaned = gtk_paned_new(LIVES_ORIENTATION_HORIZONTAL);
3404 #else
3405 hpaned = gtk_hpaned_new();
3406 #endif
3407 #endif
3408 return hpaned;
3409 }
3410
3411
lives_vpaned_new(void)3412 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_vpaned_new(void) {
3413 LiVESWidget *vpaned = NULL;
3414 #ifdef GUI_GTK
3415 #if GTK_CHECK_VERSION(3, 0, 0)
3416 vpaned = gtk_paned_new(LIVES_ORIENTATION_VERTICAL);
3417 #else
3418 vpaned = gtk_vpaned_new();
3419 #endif
3420 #endif
3421 return vpaned;
3422 }
3423
3424
lives_hscrollbar_new(LiVESAdjustment * adj)3425 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_hscrollbar_new(LiVESAdjustment *adj) {
3426 LiVESWidget *hscrollbar = NULL;
3427 #ifdef GUI_GTK
3428 #if GTK_CHECK_VERSION(3, 0, 0)
3429 hscrollbar = gtk_scrollbar_new(LIVES_ORIENTATION_HORIZONTAL, adj);
3430 #else
3431 hscrollbar = gtk_hscrollbar_new(adj);
3432 #endif
3433 #endif
3434 #ifdef GUI_QT
3435 hscrollbar = new LiVESScrollbar(LIVES_ORIENTATION_HORIZONTAL, adj);
3436 #endif
3437 return hscrollbar;
3438 }
3439
3440
lives_vscrollbar_new(LiVESAdjustment * adj)3441 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_vscrollbar_new(LiVESAdjustment *adj) {
3442 LiVESWidget *vscrollbar = NULL;
3443 #ifdef GUI_GTK
3444 #if GTK_CHECK_VERSION(3, 0, 0)
3445 vscrollbar = gtk_scrollbar_new(LIVES_ORIENTATION_VERTICAL, adj);
3446 #else
3447 vscrollbar = gtk_vscrollbar_new(adj);
3448 #endif
3449 #endif
3450 #ifdef GUI_QT
3451 vscrollbar = new LiVESScrollbar(LIVES_ORIENTATION_VERTICAL, adj);
3452 #endif
3453 return vscrollbar;
3454 }
3455
3456
lives_label_new(const char * text)3457 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_label_new(const char *text) {
3458 LiVESWidget *label = NULL;
3459 #ifdef GUI_GTK
3460 label = gtk_label_new(text);
3461 gtk_label_set_use_underline(LIVES_LABEL(label), widget_opts.mnemonic_label);
3462 gtk_label_set_justify(LIVES_LABEL(label), widget_opts.justify);
3463 gtk_label_set_line_wrap(LIVES_LABEL(label), widget_opts.line_wrap);
3464 #endif
3465 return label;
3466 }
3467
3468
lives_arrow_new(LiVESArrowType arrow_type,LiVESShadowType shadow_type)3469 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_arrow_new(LiVESArrowType arrow_type, LiVESShadowType shadow_type) {
3470 LiVESWidget *arrow = NULL;
3471 #ifdef GUI_GTK
3472 #if GTK_CHECK_VERSION(3, 12, 0)
3473 const char *format = "<b>%s</b>";
3474 char *markup;
3475 char *str;
3476
3477 switch (arrow_type) {
3478 case LIVES_ARROW_DOWN:
3479 str = "v";
3480 break;
3481 case LIVES_ARROW_LEFT:
3482 str = "<";
3483 break;
3484 case LIVES_ARROW_RIGHT:
3485 str = ">";
3486 break;
3487 default:
3488 return arrow;
3489 }
3490
3491 arrow = gtk_label_new("");
3492 markup = g_markup_printf_escaped(format, str);
3493 gtk_label_set_markup(GTK_LABEL(arrow), markup);
3494 lives_free(markup);
3495
3496 #else
3497 arrow = gtk_arrow_new(arrow_type, shadow_type);
3498 #endif
3499 #endif
3500 return arrow;
3501 }
3502
3503
lives_widget_set_halign(LiVESWidget * widget,LiVESAlign align)3504 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_halign(LiVESWidget *widget, LiVESAlign align) {
3505 #ifdef GUI_GTK
3506 #if GTK_CHECK_VERSION(3, 0, 0)
3507 if (LIVES_IS_LABEL(widget)) {
3508 if (align == LIVES_ALIGN_START) gtk_label_set_xalign(LIVES_LABEL(widget), 0.);
3509 if (align == LIVES_ALIGN_CENTER) gtk_label_set_xalign(LIVES_LABEL(widget), 0.5);
3510 if (align == LIVES_ALIGN_END) gtk_label_set_xalign(LIVES_LABEL(widget), 1.);
3511 } else gtk_widget_set_halign(widget, align);
3512 #else
3513 if (LIVES_IS_LABEL(widget)) {
3514 float xalign, yalign;
3515 gtk_misc_get_alignment(GTK_MISC(widget), &xalign, &yalign);
3516 switch (align) {
3517 case LIVES_ALIGN_START:
3518 gtk_misc_set_alignment(GTK_MISC(widget), 0., yalign);
3519 break;
3520 case LIVES_ALIGN_END:
3521 gtk_misc_set_alignment(GTK_MISC(widget), 1., yalign);
3522 break;
3523 case LIVES_ALIGN_CENTER:
3524 gtk_misc_set_alignment(GTK_MISC(widget), 0.5, yalign);
3525 break;
3526 default:
3527 return FALSE;
3528 }
3529 return TRUE;
3530 }
3531 #endif
3532 #endif
3533 return FALSE;
3534 }
3535
3536
lives_widget_set_valign(LiVESWidget * widget,LiVESAlign align)3537 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_valign(LiVESWidget *widget, LiVESAlign align) {
3538 #ifdef GUI_GTK
3539 #if GTK_CHECK_VERSION(3, 0, 0)
3540 gtk_widget_set_valign(widget, align);
3541 #else
3542 if (!LIVES_IS_LABEL(widget)) return FALSE;
3543 else {
3544 float xalign, yalign;
3545 gtk_misc_get_alignment(GTK_MISC(widget), &xalign, &yalign);
3546 switch (align) {
3547 case LIVES_ALIGN_START:
3548 gtk_misc_set_alignment(GTK_MISC(widget), xalign, 0.);
3549 break;
3550 case LIVES_ALIGN_END:
3551 gtk_misc_set_alignment(GTK_MISC(widget), xalign, 1.);
3552 break;
3553 case LIVES_ALIGN_CENTER:
3554 gtk_misc_set_alignment(GTK_MISC(widget), xalign, 0.5);
3555 break;
3556 default:
3557 return FALSE;
3558 }
3559 }
3560 #endif
3561 return TRUE;
3562 #endif
3563 return FALSE;
3564 }
3565
3566
lives_alignment_new(float xalign,float yalign,float xscale,float yscale)3567 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_alignment_new(float xalign, float yalign, float xscale, float yscale) {
3568 LiVESWidget *alignment = NULL;
3569 #ifdef GUI_GTK
3570 #if GTK_CHECK_VERSION(3, 0, 0)
3571 alignment = gtk_aspect_frame_new(NULL, xalign, yalign, xscale / yscale, TRUE);
3572 lives_frame_set_shadow_type(LIVES_FRAME(alignment), LIVES_SHADOW_NONE);
3573 #else
3574 alignment = gtk_alignment_new(xalign, yalign, xscale, yscale);
3575 #endif
3576 #endif
3577 #ifdef GUI_QT
3578 alignment = new LiVESAlignment(xalign, yalign, xscale, yscale);
3579 #endif
3580 return alignment;
3581 }
3582
3583
lives_alignment_set(LiVESWidget * alignment,float xalign,float yalign,float xscale,float yscale)3584 WIDGET_HELPER_GLOBAL_INLINE boolean lives_alignment_set(LiVESWidget *alignment, float xalign, float yalign, float xscale,
3585 float yscale) {
3586 #ifdef GUI_GTK
3587 #if GTK_CHECK_VERSION(3, 0, 0)
3588 gtk_aspect_frame_set(GTK_ASPECT_FRAME(alignment), xalign, yalign, xscale / yscale, TRUE);
3589 #else
3590 gtk_alignment_set(LIVES_ALIGNMENT(alignment), xalign, yalign, xscale, yscale);
3591 #endif
3592 return TRUE;
3593 #endif
3594 #ifdef GUI_QT
3595 alignment->set_alignment(xalign, yalign, xscale, yscale);
3596 return TRUE;
3597 #endif
3598 return FALSE;
3599 }
3600
3601
lives_expander_new(const char * label)3602 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_expander_new(const char *label) {
3603 LiVESWidget *expander = NULL;
3604 #ifdef GUI_GTK
3605 if (!widget_opts.mnemonic_label) expander = gtk_expander_new(label);
3606 else expander = gtk_expander_new_with_mnemonic(label);
3607 #if GTK_CHECK_VERSION(3, 2, 0)
3608 gtk_expander_set_resize_toplevel(GTK_EXPANDER(expander), TRUE);
3609 #endif
3610 #endif
3611 return expander;
3612 }
3613
3614
lives_expander_get_label_widget(LiVESExpander * expander)3615 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_expander_get_label_widget(LiVESExpander *expander) {
3616 LiVESWidget *widget = NULL;
3617 #ifdef GUI_GTK
3618 widget = gtk_expander_get_label_widget(expander);
3619 #endif
3620 return widget;
3621 }
3622
3623
lives_expander_set_use_markup(LiVESExpander * expander,boolean val)3624 WIDGET_HELPER_GLOBAL_INLINE boolean lives_expander_set_use_markup(LiVESExpander *expander, boolean val) {
3625 #ifdef GUI_GTK
3626 gtk_expander_set_use_markup(expander, val);
3627 return TRUE;
3628 #endif
3629 return FALSE;
3630 }
3631
3632
lives_expander_set_expanded(LiVESExpander * expander,boolean val)3633 WIDGET_HELPER_GLOBAL_INLINE boolean lives_expander_set_expanded(LiVESExpander *expander, boolean val) {
3634 #ifdef GUI_GTK
3635 gtk_expander_set_expanded(expander, val);
3636 return TRUE;
3637 #endif
3638 return FALSE;
3639 }
3640
3641
lives_expander_set_label(LiVESExpander * expander,const char * text)3642 WIDGET_HELPER_GLOBAL_INLINE boolean lives_expander_set_label(LiVESExpander *expander, const char *text) {
3643
3644 #ifdef GUI_GTK
3645 char *labeltext = lives_strdup_printf("<big>%s</big>", text);
3646 gtk_expander_set_label(expander, labeltext);
3647 lives_free(labeltext);
3648 return TRUE;
3649 #endif
3650 return FALSE;
3651 }
3652
3653
lives_expander_get_expanded(LiVESExpander * expander)3654 WIDGET_HELPER_GLOBAL_INLINE boolean lives_expander_get_expanded(LiVESExpander *expander) {
3655 #ifdef GUI_GTK
3656 return gtk_expander_get_expanded(expander);
3657 #endif
3658 return FALSE;
3659 }
3660
3661
lives_label_set_width_chars(LiVESLabel * label,int nchars)3662 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_width_chars(LiVESLabel *label, int nchars) {
3663 #ifdef GUI_GTK
3664 gtk_label_set_width_chars(label, nchars);
3665 gtk_label_set_max_width_chars(label, nchars);
3666 return TRUE;
3667 #endif
3668 return FALSE;
3669 }
3670
3671
lives_label_set_line_wrap(LiVESLabel * label,boolean set)3672 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_line_wrap(LiVESLabel *label, boolean set) {
3673 #ifdef GUI_GTK
3674 gtk_label_set_line_wrap(label, set);
3675 return TRUE;
3676 #endif
3677 return FALSE;
3678 }
3679
lives_label_set_line_wrap_mode(LiVESLabel * label,LingoWrapMode mode)3680 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_line_wrap_mode(LiVESLabel *label, LingoWrapMode mode) {
3681 #ifdef GUI_GTK
3682 gtk_label_set_line_wrap_mode(label, mode);
3683 return TRUE;
3684 #endif
3685 return FALSE;
3686 }
3687
lives_label_seT_lines(LiVESLabel * label,int nlines)3688 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_seT_lines(LiVESLabel *label, int nlines) {
3689 #ifdef GUI_GTK
3690 gtk_label_set_lines(label, nlines);
3691 return TRUE;
3692 #endif
3693 return FALSE;
3694 }
3695
lives_label_set_ellipsize(LiVESLabel * label,LiVESEllipsizeMode mode)3696 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_ellipsize(LiVESLabel *label, LiVESEllipsizeMode mode) {
3697 #ifdef GUI_GTK
3698 gtk_label_set_ellipsize(label, mode);
3699 return TRUE;
3700 #endif
3701 return FALSE;
3702 }
3703
lives_label_set_halignment(LiVESLabel * label,float xalign)3704 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_halignment(LiVESLabel *label, float xalign) {
3705 #ifdef GUI_GTK
3706 #if GTK_CHECK_VERSION(3, 16, 0)
3707 gtk_label_set_xalign(label, xalign);
3708 #else
3709 if (xalign == 0.)
3710 lives_widget_set_halign(LIVES_WIDGET(label), LIVES_ALIGN_START);
3711 else if (xalign == 1.)
3712 lives_widget_set_halign(LIVES_WIDGET(label), LIVES_ALIGN_END);
3713 else
3714 lives_widget_set_halign(LIVES_WIDGET(label), LIVES_ALIGN_CENTER);
3715 #endif
3716 return TRUE;
3717 #endif
3718 #ifdef GUI_QT
3719 QRect qr = (static_cast<QFrame *>(label))->contentsRect();
3720 int pixels = (float)qr.width() * xalign;
3721 label->setIndent(pixels);
3722 #endif
3723 return FALSE;
3724 }
3725
3726
lives_combo_new(void)3727 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_combo_new(void) {
3728 LiVESWidget *combo = NULL;
3729 #ifdef GUI_GTK
3730 #if GTK_CHECK_VERSION(2, 24, 0)
3731 combo = gtk_combo_box_new_with_entry();
3732 #else
3733 combo = gtk_combo_box_entry_new_text();
3734 #endif
3735 #endif
3736 #ifdef GUI_QT
3737 combo = new LiVESCombo;
3738 #endif
3739 return combo;
3740 }
3741
3742
lives_combo_new_with_model(LiVESTreeModel * model)3743 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_combo_new_with_model(LiVESTreeModel *model) {
3744 LiVESWidget *combo = NULL;
3745 #ifdef GUI_GTK
3746 #if GTK_CHECK_VERSION(2, 24, 0)
3747 combo = gtk_combo_box_new_with_model_and_entry(model);
3748 #else
3749 combo = gtk_combo_box_entry_new();
3750 gtk_combo_box_set_model(GTK_COMBO_BOX(combo), model);
3751 #endif
3752 #endif
3753 #ifdef GUI_QT
3754 combo = new LiVESCombo;
3755 QComboBox *qcombo = dynamic_cast<QComboBox *>(combo);
3756 qcombo->setModel(model->to_qsimodel());
3757 if (model->get_qtree_widget()) qcombo->setView(model->get_qtree_widget());
3758 #endif
3759 return combo;
3760 }
3761
3762
lives_combo_get_model(LiVESCombo * combo)3763 WIDGET_HELPER_GLOBAL_INLINE LiVESTreeModel *lives_combo_get_model(LiVESCombo *combo) {
3764 LiVESTreeModel *model = NULL;
3765 #ifdef GUI_GTK
3766 model = gtk_combo_box_get_model(combo);
3767 #endif
3768 return model;
3769 }
3770
3771
lives_combo_set_model(LiVESCombo * combo,LiVESTreeModel * model)3772 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_model(LiVESCombo *combo, LiVESTreeModel *model) {
3773 #ifdef GUI_GTK
3774 gtk_combo_box_set_model(combo, model);
3775 return TRUE;
3776 #endif
3777 return FALSE;
3778 }
3779
3780
lives_combo_popup(LiVESCombo * combo)3781 void lives_combo_popup(LiVESCombo *combo) {
3782 // used in callback, so no inline
3783 #ifdef GUI_GTK
3784 gtk_combo_box_popup(combo);
3785 #endif
3786 }
3787
3788
lives_combo_set_focus_on_click(LiVESCombo * combo,boolean state)3789 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_focus_on_click(LiVESCombo *combo, boolean state) {
3790 #ifdef GUI_GTK
3791 #if GTK_CHECK_VERSION(3, 20, 0)
3792 gtk_widget_set_focus_on_click(GTK_WIDGET(combo), state);
3793 #else
3794 gtk_combo_box_set_focus_on_click(combo, state);
3795 #endif
3796 return TRUE;
3797 #endif
3798 return FALSE;
3799 }
3800
3801
lives_combo_append_text(LiVESCombo * combo,const char * text)3802 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_append_text(LiVESCombo *combo, const char *text) {
3803 #ifdef GUI_GTK
3804 LiVESTreeModel *tmodel = lives_combo_get_model(combo);
3805 if (!GTK_IS_LIST_STORE(tmodel)) return FALSE;
3806 else {
3807 LiVESTreeIter iter;
3808 LiVESListStore *lstore = GTK_LIST_STORE(tmodel);
3809 gtk_list_store_append(lstore, &iter); /* Acquire an iterator */
3810 lives_tree_store_set(GTK_TREE_STORE(lstore), &iter, 0, text, -1);
3811 }
3812
3813 /* #if GTK_CHECK_VERSION(2, 24, 0) */
3814 /* gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), text); */
3815 /* #else */
3816 /* gtk_combo_box_append_text(GTK_COMBO_BOX(combo), text); */
3817 /* #endif */
3818 return TRUE;
3819 #endif
3820 return FALSE;
3821 }
3822
3823
lives_combo_prepend_text(LiVESCombo * combo,const char * text)3824 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_prepend_text(LiVESCombo *combo, const char *text) {
3825 #ifdef GUI_GTK
3826 LiVESTreeModel *tmodel = lives_combo_get_model(combo);
3827 if (!GTK_IS_LIST_STORE(tmodel)) return FALSE;
3828 else {
3829 LiVESTreeIter iter;
3830 LiVESListStore *lstore = GTK_LIST_STORE(tmodel);
3831 gtk_list_store_prepend(lstore, &iter); /* Acquire an iterator */
3832 lives_tree_store_set(GTK_TREE_STORE(lstore), &iter, 0, text, -1);
3833 }
3834 return TRUE;
3835 #endif
3836 return FALSE;
3837 }
3838
3839
lives_combo_remove_all_text(LiVESCombo * combo)3840 boolean lives_combo_remove_all_text(LiVESCombo *combo) {
3841 #ifdef GUI_GTK
3842 LiVESTreeModel *tmodel = lives_combo_get_model(combo);
3843 if (GTK_IS_TREE_STORE(tmodel)) {
3844 LiVESTreeStore *tstore = GTK_TREE_STORE(tmodel);
3845 gtk_tree_store_clear(tstore);
3846 } else if (GTK_IS_LIST_STORE(tmodel)) {
3847 LiVESListStore *lstore = GTK_LIST_STORE(tmodel);
3848 /// block CHANGED signal else it gets called for EVERY SINGLE removed element !
3849 //uint32_t sigid = g_signal_lookup(LIVES_WIDGET_CHANGED_SIGNAL, GTK_TYPE_COMBO_BOX);
3850 // does NOT WORK ! bug in glib / gtk ?
3851 //g_signal_handlers_block_matched(combo, G_SIGNAL_MATCH_ID, sigid, 0, NULL, NULL, NULL);
3852 gtk_list_store_clear(lstore);
3853 //g_signal_handlers_unblock_matched(combo, G_SIGNAL_MATCH_ID, sigid, 0, NULL, NULL, NULL);
3854 }
3855 return TRUE;
3856 #endif
3857 return FALSE;
3858 }
3859
3860
lives_combo_set_entry_text_column(LiVESCombo * combo,int column)3861 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_entry_text_column(LiVESCombo *combo, int column) {
3862 #ifdef GUI_GTK
3863 #if GTK_CHECK_VERSION(2, 24, 0)
3864 gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(combo), column);
3865 #else
3866 gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(combo), column);
3867 #endif
3868 return TRUE;
3869 #endif
3870 return FALSE;
3871 }
3872
3873
lives_combo_get_active_text(LiVESCombo * combo)3874 WIDGET_HELPER_GLOBAL_INLINE const char *lives_combo_get_active_text(LiVESCombo *combo) {
3875 // return value should be freed
3876 #ifdef GUI_GTK
3877 return lives_entry_get_text(LIVES_ENTRY(lives_bin_get_child(LIVES_BIN(combo))));
3878 #endif
3879 return NULL;
3880 }
3881
3882
lives_combo_set_active_index(LiVESCombo * combo,int index)3883 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_index(LiVESCombo *combo, int index) {
3884 #ifdef GUI_GTK
3885 gtk_combo_box_set_active(combo, index);
3886 return TRUE;
3887 #endif
3888 return FALSE;
3889 }
3890
3891
lives_combo_set_active_iter(LiVESCombo * combo,LiVESTreeIter * iter)3892 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_iter(LiVESCombo *combo, LiVESTreeIter *iter) {
3893 #ifdef GUI_GTK
3894 gtk_combo_box_set_active_iter(combo, iter);
3895 return TRUE;
3896 #endif
3897 return FALSE;
3898 }
3899
3900
lives_combo_get_active_iter(LiVESCombo * combo,LiVESTreeIter * iter)3901 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_get_active_iter(LiVESCombo *combo, LiVESTreeIter *iter) {
3902 #ifdef GUI_GTK
3903 return gtk_combo_box_get_active_iter(combo, iter);
3904 #endif
3905 return FALSE;
3906 }
3907
3908
lives_combo_get_active_index(LiVESCombo * combo)3909 WIDGET_HELPER_GLOBAL_INLINE int lives_combo_get_active_index(LiVESCombo *combo) {
3910 #ifdef GUI_GTK
3911 LiVESTreeModel *tmodel = lives_combo_get_model(combo);
3912 if (GTK_IS_TREE_STORE(tmodel)) {
3913 int count = 0;
3914 LiVESTreeIter iter, iter1, iter2;
3915 if (!lives_combo_get_active_iter(combo, &iter)) return -1;
3916 if (gtk_tree_model_iter_children(tmodel, &iter1, NULL)) {
3917 if (gtk_tree_model_iter_children(tmodel, &iter2, &iter1)) {
3918 while (1) {
3919 if (iter2.stamp == iter.stamp) return count;
3920 count++;
3921 if (!gtk_tree_model_iter_next(tmodel, &iter2)) break;
3922 }
3923 }
3924 }
3925 }
3926 return gtk_combo_box_get_active(combo);
3927 #endif
3928 return -1;
3929 }
3930
3931
lives_text_view_new(void)3932 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_text_view_new(void) {
3933 LiVESWidget *tview = NULL;
3934 #ifdef GUI_GTK
3935 tview = gtk_text_view_new();
3936 #endif
3937 return tview;
3938 }
3939
3940
lives_text_view_new_with_buffer(LiVESTextBuffer * tbuff)3941 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_text_view_new_with_buffer(LiVESTextBuffer *tbuff) {
3942 LiVESWidget *tview = NULL;
3943 #ifdef GUI_GTK
3944 tview = gtk_text_view_new_with_buffer(tbuff);
3945 #endif
3946 return tview;
3947 }
3948
3949
lives_text_view_get_buffer(LiVESTextView * tview)3950 WIDGET_HELPER_GLOBAL_INLINE LiVESTextBuffer *lives_text_view_get_buffer(LiVESTextView *tview) {
3951 LiVESTextBuffer *tbuff = NULL;
3952 #ifdef GUI_GTK
3953 tbuff = gtk_text_view_get_buffer(tview);
3954 #endif
3955 return tbuff;
3956 }
3957
3958
lives_text_view_set_editable(LiVESTextView * tview,boolean setting)3959 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_editable(LiVESTextView *tview, boolean setting) {
3960 #ifdef GUI_GTK
3961 gtk_text_view_set_editable(tview, setting);
3962 return TRUE;
3963 #endif
3964 return FALSE;
3965 }
3966
3967
lives_text_view_set_accepts_tab(LiVESTextView * tview,boolean setting)3968 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_accepts_tab(LiVESTextView *tview, boolean setting) {
3969 #ifdef GUI_GTK
3970 gtk_text_view_set_accepts_tab(tview, setting);
3971 return TRUE;
3972 #endif
3973 return FALSE;
3974 }
3975
3976
lives_text_view_set_cursor_visible(LiVESTextView * tview,boolean setting)3977 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_cursor_visible(LiVESTextView *tview, boolean setting) {
3978 #ifdef GUI_GTK
3979 gtk_text_view_set_cursor_visible(tview, setting);
3980 return TRUE;
3981 #endif
3982 return FALSE;
3983 }
3984
3985
lives_text_view_set_wrap_mode(LiVESTextView * tview,LiVESWrapMode wrapmode)3986 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_wrap_mode(LiVESTextView *tview, LiVESWrapMode wrapmode) {
3987 #ifdef GUI_GTK
3988 gtk_text_view_set_wrap_mode(tview, wrapmode);
3989 return TRUE;
3990 #endif
3991 return FALSE;
3992 }
3993
3994
lives_text_view_set_justification(LiVESTextView * tview,LiVESJustification justify)3995 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_justification(LiVESTextView *tview, LiVESJustification justify) {
3996 #ifdef GUI_GTK
3997 gtk_text_view_set_justification(tview, justify);
3998 return TRUE;
3999 #endif
4000 return FALSE;
4001 }
4002
4003
lives_text_view_set_top_margin(LiVESTextView * tview,int margin)4004 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_top_margin(LiVESTextView *tview, int margin) {
4005 #ifdef GUI_GTK
4006 #if GTK_CHECK_VERSION(3, 18, 0)
4007 gtk_text_view_set_top_margin(tview, margin);
4008 return TRUE;
4009 #endif
4010 #endif
4011 return FALSE;
4012 }
4013
4014
lives_text_view_set_bottom_margin(LiVESTextView * tview,int margin)4015 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_view_set_bottom_margin(LiVESTextView *tview, int margin) {
4016 #ifdef GUI_GTK
4017 #if GTK_CHECK_VERSION(3, 18, 0)
4018 gtk_text_view_set_bottom_margin(tview, margin);
4019 return TRUE;
4020 #endif
4021 #endif
4022 return FALSE;
4023 }
4024
4025
lives_text_buffer_new(void)4026 WIDGET_HELPER_GLOBAL_INLINE LiVESTextBuffer *lives_text_buffer_new(void) {
4027 LiVESTextBuffer *tbuff = NULL;
4028 #ifdef GUI_GTK
4029 tbuff = gtk_text_buffer_new(NULL);
4030 #endif
4031 return tbuff;
4032 }
4033
4034
lives_text_buffer_insert(LiVESTextBuffer * tbuff,LiVESTextIter * iter,const char * text,int len)4035 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_insert(LiVESTextBuffer *tbuff, LiVESTextIter *iter, const char *text,
4036 int len) {
4037 #ifdef GUI_GTK
4038 gtk_text_buffer_insert(tbuff, iter, text, len);
4039 return TRUE;
4040 #endif
4041 return FALSE;
4042 }
4043
4044
lives_text_buffer_insert_at_cursor(LiVESTextBuffer * tbuff,const char * text,int len)4045 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_insert_at_cursor(LiVESTextBuffer *tbuff, const char *text, int len) {
4046 #ifdef GUI_GTK
4047 gtk_text_buffer_insert_at_cursor(tbuff, text, len);
4048 return TRUE;
4049 #endif
4050 return FALSE;
4051 }
4052
4053
lives_text_buffer_set_text(LiVESTextBuffer * tbuff,const char * text,int len)4054 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_set_text(LiVESTextBuffer *tbuff, const char *text, int len) {
4055 #ifdef GUI_GTK
4056 gtk_text_buffer_set_text(tbuff, text, len);
4057 return TRUE;
4058 #endif
4059 return FALSE;
4060 }
4061
4062
lives_text_buffer_get_text(LiVESTextBuffer * tbuff,LiVESTextIter * start,LiVESTextIter * end,boolean inc_hidden_chars)4063 WIDGET_HELPER_GLOBAL_INLINE char *lives_text_buffer_get_text(LiVESTextBuffer *tbuff, LiVESTextIter *start, LiVESTextIter *end,
4064 boolean inc_hidden_chars) {
4065 #ifdef GUI_GTK
4066 return gtk_text_buffer_get_text(tbuff, start, end, inc_hidden_chars);
4067 #endif
4068 return NULL;
4069 }
4070
4071
lives_text_buffer_get_all_text(LiVESTextBuffer * tbuff)4072 WIDGET_HELPER_GLOBAL_INLINE char *lives_text_buffer_get_all_text(LiVESTextBuffer *tbuff) {
4073 LiVESTextIter s, e;
4074 lives_text_buffer_get_start_iter(tbuff, &s);
4075 lives_text_buffer_get_end_iter(tbuff, &e);
4076 return lives_text_buffer_get_text(tbuff, &s, &e, FALSE);
4077 }
4078
4079
lives_text_buffer_get_start_iter(LiVESTextBuffer * tbuff,LiVESTextIter * iter)4080 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_get_start_iter(LiVESTextBuffer *tbuff, LiVESTextIter *iter) {
4081 #ifdef GUI_GTK
4082 gtk_text_buffer_get_start_iter(tbuff, iter);
4083 return TRUE;
4084 #endif
4085 return FALSE;
4086 }
4087
4088
lives_text_buffer_get_end_iter(LiVESTextBuffer * tbuff,LiVESTextIter * iter)4089 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_get_end_iter(LiVESTextBuffer *tbuff, LiVESTextIter *iter) {
4090 #ifdef GUI_GTK
4091 gtk_text_buffer_get_end_iter(tbuff, iter);
4092 return TRUE;
4093 #endif
4094 return FALSE;
4095 }
4096
4097
lives_text_buffer_place_cursor(LiVESTextBuffer * tbuff,LiVESTextIter * iter)4098 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_place_cursor(LiVESTextBuffer *tbuff, LiVESTextIter *iter) {
4099 #ifdef GUI_GTK
4100 gtk_text_buffer_place_cursor(tbuff, iter);
4101 return TRUE;
4102 #endif
4103 return FALSE;
4104 }
4105
4106
lives_text_buffer_create_mark(LiVESTextBuffer * tbuff,const char * mark_name,const LiVESTextIter * where,boolean left_gravity)4107 WIDGET_HELPER_GLOBAL_INLINE LiVESTextMark *lives_text_buffer_create_mark(LiVESTextBuffer *tbuff, const char *mark_name,
4108 const LiVESTextIter *where, boolean left_gravity) {
4109 LiVESTextMark *tmark;
4110 #ifdef GUI_GTK
4111 tmark = gtk_text_buffer_create_mark(tbuff, mark_name, where, left_gravity);
4112 #endif
4113 return tmark;
4114 }
4115
4116
lives_text_buffer_delete_mark(LiVESTextBuffer * tbuff,LiVESTextMark * mark)4117 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_delete_mark(LiVESTextBuffer *tbuff, LiVESTextMark *mark) {
4118 #ifdef GUI_GTK
4119 gtk_text_buffer_delete_mark(tbuff, mark);
4120 return TRUE;
4121 #endif
4122 return FALSE;
4123 }
4124
4125
lives_text_buffer_delete(LiVESTextBuffer * tbuff,LiVESTextIter * start,LiVESTextIter * end)4126 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_delete(LiVESTextBuffer *tbuff, LiVESTextIter *start, LiVESTextIter *end) {
4127 #ifdef GUI_GTK
4128 gtk_text_buffer_delete(tbuff, start, end);
4129 return TRUE;
4130 #endif
4131 #ifdef GUI_QT
4132 QTextCursor qtc = QTextCursor(tbuff);
4133 qtc.setPosition(*start);
4134 qtc.setPosition(*end, QTextCursor::KeepAnchor);
4135 qtc.removeSelectedText();
4136 return TRUE;
4137 #endif
4138 return FALSE;
4139 }
4140
4141
lives_text_buffer_get_iter_at_mark(LiVESTextBuffer * tbuff,LiVESTextIter * iter,LiVESTextMark * mark)4142 WIDGET_HELPER_GLOBAL_INLINE boolean lives_text_buffer_get_iter_at_mark(LiVESTextBuffer *tbuff, LiVESTextIter *iter,
4143 LiVESTextMark *mark) {
4144 #ifdef GUI_GTK
4145 gtk_text_buffer_get_iter_at_mark(tbuff, iter, mark);
4146 return TRUE;
4147 #endif
4148 return FALSE;
4149 }
4150
4151
lives_dialog_new(void)4152 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_dialog_new(void) {
4153 LiVESWidget *dialog = NULL;
4154 #ifdef GUI_GTK
4155 dialog = gtk_dialog_new();
4156 #endif
4157 return dialog;
4158 }
4159
4160
lives_button_new(void)4161 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_button_new(void) {
4162 LiVESWidget *button = NULL;
4163 #ifdef GUI_GTK
4164 button = gtk_button_new();
4165 gtk_button_set_use_underline(GTK_BUTTON(button), widget_opts.mnemonic_label);
4166 #endif
4167 return button;
4168 }
4169
4170
lives_button_new_with_label(const char * label)4171 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_button_new_with_label(const char *label) {
4172 LiVESWidget *button = NULL;
4173 #ifdef GUI_GTK
4174 button = lives_button_new();
4175 lives_button_set_label(LIVES_BUTTON(button), label);
4176 #endif
4177 return button;
4178 }
4179
4180
lives_button_set_image_from_stock(LiVESButton * button,const char * stock_id)4181 LIVES_GLOBAL_INLINE boolean lives_button_set_image_from_stock(LiVESButton *button,
4182 const char *stock_id) {
4183 /// tweaks for better icons
4184 if (!strcmp(stock_id, LIVES_STOCK_YES)) stock_id = LIVES_STOCK_APPLY;
4185 if (!strcmp(stock_id, LIVES_STOCK_NO)) stock_id = LIVES_STOCK_STOP;
4186
4187 if (!strcmp(stock_id, LIVES_STOCK_OK)) stock_id = LIVES_STOCK_APPLY;
4188 if (!strcmp(stock_id, LIVES_STOCK_CANCEL)) stock_id = LIVES_STOCK_STOP;
4189
4190 if (!is_standard_widget(LIVES_WIDGET(button))) {
4191 if (stock_id && (widget_opts.show_button_images
4192 || !strcmp(stock_id, LIVES_STOCK_ADD)
4193 || !strcmp(stock_id, LIVES_STOCK_REMOVE)
4194 )) {
4195 LiVESWidget *image = gtk_image_new_from_icon_name(stock_id, LIVES_ICON_SIZE_BUTTON);
4196 if (LIVES_IS_IMAGE(image)) gtk_button_set_image(LIVES_BUTTON(button), image);
4197 else return FALSE;
4198 }
4199 }
4200
4201 #ifdef USE_SPECIAL_BUTTONS
4202 else {
4203 if (stock_id) {
4204 LiVESPixbuf *pixbuf = lives_pixbuf_new_from_stock_at_size(stock_id, LIVES_ICON_SIZE_BUTTON, 0, 0);
4205 if (LIVES_IS_PIXBUF(pixbuf))
4206 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(button), SBUTT_PIXBUF_KEY, (livespointer)pixbuf);
4207 else return FALSE;
4208 }
4209 }
4210 #endif
4211 return TRUE;
4212 }
4213
4214
lives_standard_button_new_from_stock(const char * stock_id,const char * label,int width,int height)4215 LiVESWidget *lives_standard_button_new_from_stock(const char *stock_id, const char *label, int width, int height) {
4216 LiVESWidget *button = NULL;
4217
4218 #if GTK_CHECK_VERSION(3, 10, 0)
4219 do {
4220 if (!stock_id) {
4221 button = lives_standard_button_new(width, height);
4222 break;
4223 }
4224 if (!strcmp(stock_id, LIVES_STOCK_LABEL_CANCEL)) stock_id = LIVES_STOCK_CANCEL;
4225 if (!strcmp(stock_id, LIVES_STOCK_LABEL_OK)) stock_id = LIVES_STOCK_OK;
4226
4227 // gtk 3.10 + -> we need to set the text ourselves
4228 if (!strcmp(stock_id, LIVES_STOCK_APPLY)) {
4229 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_APPLY, width, height);
4230 break;
4231 }
4232 if (!strcmp(stock_id, LIVES_STOCK_OK)) {
4233 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_OK, width, height);
4234 break;
4235 }
4236 if (!strcmp(stock_id, LIVES_STOCK_CANCEL)) {
4237 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_CANCEL, width, height);
4238 break;
4239 }
4240 if (!strcmp(stock_id, LIVES_STOCK_YES)) {
4241 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_YES, width, height);
4242 break;
4243 }
4244 if (!strcmp(stock_id, LIVES_STOCK_NO)) {
4245 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_NO, width, height);
4246 break;
4247 }
4248 if (!strcmp(stock_id, LIVES_STOCK_CLOSE)) {
4249 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_CLOSE, width, height);
4250 break;
4251 }
4252 if (!strcmp(stock_id, LIVES_STOCK_REVERT_TO_SAVED)) {
4253 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_REVERT, width, height);
4254 break;
4255 }
4256 if (!strcmp(stock_id, LIVES_STOCK_REFRESH)) {
4257 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_REFRESH, width, height);
4258 break;
4259 }
4260 if (!strcmp(stock_id, LIVES_STOCK_DELETE)) {
4261 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_DELETE, width, height);
4262 break;
4263 }
4264 if (!strcmp(stock_id, LIVES_STOCK_SAVE)) {
4265 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_SAVE, width, height);
4266 break;
4267 }
4268 if (!strcmp(stock_id, LIVES_STOCK_SAVE_AS)) {
4269 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_SAVE_AS, width, height);
4270 break;
4271 }
4272 if (!strcmp(stock_id, LIVES_STOCK_OPEN)) {
4273 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_OPEN, width, height);
4274 break;
4275 }
4276 if (!strcmp(stock_id, LIVES_STOCK_SELECT_ALL)) {
4277 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_SELECT_ALL, width, height);
4278 break;
4279 }
4280 if (!strcmp(stock_id, LIVES_STOCK_QUIT)) {
4281 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_QUIT, width, height);
4282 break;
4283 }
4284 if (!strcmp(stock_id, LIVES_STOCK_GO_FORWARD)) {
4285 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_GO_FORWARD, width, height);
4286 break;
4287 }
4288 if (!strcmp(stock_id, LIVES_STOCK_MEDIA_FORWARD)) {
4289 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_MEDIA_FORWARD, width, height);
4290 break;
4291 }
4292 if (!strcmp(stock_id, LIVES_STOCK_MEDIA_REWIND)) {
4293 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_MEDIA_REWIND, width, height);
4294 break;
4295 }
4296 if (!strcmp(stock_id, LIVES_STOCK_MEDIA_STOP)) {
4297 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_MEDIA_STOP, width, height);
4298 break;
4299 }
4300 if (!strcmp(stock_id, LIVES_STOCK_MEDIA_PLAY)) {
4301 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_MEDIA_PLAY, width, height);
4302 break;
4303 }
4304 if (!strcmp(stock_id, LIVES_STOCK_MEDIA_PAUSE)) {
4305 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_MEDIA_PAUSE, width, height);
4306 break;
4307 }
4308 if (!strcmp(stock_id, LIVES_STOCK_MEDIA_RECORD)) {
4309 button = lives_standard_button_new_with_label(LIVES_STOCK_LABEL_MEDIA_RECORD, width, height);
4310 break;
4311 }
4312 // text not known
4313 button = lives_standard_button_new(width, height);
4314 } while (FALSE);
4315
4316 if (stock_id) lives_button_set_image_from_stock(LIVES_BUTTON(button), stock_id);
4317
4318 #else
4319 // < 3.10
4320 button = gtk_button_new_from_stock(stock_id);
4321 #endif
4322
4323 if (!LIVES_IS_BUTTON(button)) {
4324 char *msg = lives_strdup_printf("Unable to find button with stock_id: %s", stock_id);
4325 LIVES_WARN(msg);
4326 lives_free(msg);
4327 button = lives_standard_button_new(width, height);
4328 }
4329
4330 #ifdef GUI_GTK
4331 #if GTK_CHECK_VERSION(3, 6, 0)
4332 //gtk_button_set_always_show_image(GTK_BUTTON(button), widget_opts.show_button_images);
4333 #endif
4334 if (label)
4335 lives_standard_button_set_label(LIVES_BUTTON(button), label);
4336 #endif
4337
4338 lives_widget_set_can_focus_and_default(button);
4339 lives_widget_apply_theme(button, LIVES_WIDGET_STATE_NORMAL);
4340 return button;
4341 }
4342
4343
4344
lives_button_set_label(LiVESButton * button,const char * label)4345 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_set_label(LiVESButton *button, const char *label) {
4346 #ifdef USE_SPECIAL_BUTTONS
4347 if (is_standard_widget(LIVES_WIDGET(button))) return lives_standard_button_set_label(button, label);
4348 #endif
4349 #ifdef GUI_GTK
4350 gtk_button_set_label(button, label);
4351 return TRUE;
4352 #endif
4353 return FALSE;
4354 }
4355
4356
lives_button_get_label(LiVESButton * button)4357 WIDGET_HELPER_GLOBAL_INLINE const char *lives_button_get_label(LiVESButton *button) {
4358 #ifdef USE_SPECIAL_BUTTONS
4359 if (is_standard_widget(LIVES_WIDGET(button))) return lives_standard_button_get_label(button);
4360 #endif
4361 #ifdef GUI_GTK
4362 return gtk_button_get_label(button);
4363 #endif
4364 return NULL;
4365 }
4366
4367
lives_button_clicked(LiVESButton * button)4368 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_clicked(LiVESButton *button) {
4369 #ifdef GUI_GTK
4370 gtk_button_clicked(button);
4371 return TRUE;
4372 #endif
4373 return FALSE;
4374 }
4375
4376
lives_button_set_relief(LiVESButton * button,LiVESReliefStyle rstyle)4377 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_set_relief(LiVESButton *button, LiVESReliefStyle rstyle) {
4378 #ifdef GUI_GTK
4379 gtk_button_set_relief(button, rstyle);
4380 return TRUE;
4381 #endif
4382 return FALSE;
4383 }
4384
4385
lives_button_set_image(LiVESButton * button,LiVESWidget * image)4386 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_set_image(LiVESButton *button, LiVESWidget *image) {
4387 #ifdef GUI_GTK
4388 gtk_button_set_image(button, image);
4389 return TRUE;
4390 #endif
4391 return FALSE;
4392 }
4393
4394
lives_widget_set_focus_on_click(LiVESWidget * widget,boolean focus)4395 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_focus_on_click(LiVESWidget *widget, boolean focus) {
4396 #ifdef GUI_GTK
4397 #if GTK_CHECK_VERSION(3, 20, 0)
4398 gtk_widget_set_focus_on_click(widget, focus);
4399 #else
4400 if (!LIVES_IS_BUTTON(widget)) return FALSE;
4401 gtk_button_set_focus_on_click(LIVES_BUTTON(widget), focus);
4402 #endif
4403 return TRUE;
4404 #endif
4405 return FALSE;
4406 }
4407
4408
lives_button_set_focus_on_click(LiVESButton * button,boolean focus)4409 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_set_focus_on_click(LiVESButton *button, boolean focus) {
4410 return lives_widget_set_focus_on_click(LIVES_WIDGET(button), focus);
4411 }
4412
4413
lives_paned_get_position(LiVESPaned * paned)4414 WIDGET_HELPER_GLOBAL_INLINE int lives_paned_get_position(LiVESPaned *paned) {
4415 #ifdef GUI_GTK
4416 return gtk_paned_get_position(paned);
4417 #endif
4418 return -1;
4419 }
4420
4421
lives_paned_set_position(LiVESPaned * paned,int pos)4422 WIDGET_HELPER_GLOBAL_INLINE boolean lives_paned_set_position(LiVESPaned *paned, int pos) {
4423 // call this only after adding widgets
4424 #ifdef GUI_GTK
4425 gtk_paned_set_position(paned, pos);
4426 return TRUE;
4427 #endif
4428 return FALSE;
4429 }
4430
4431
lives_paned_pack(int where,LiVESPaned * paned,LiVESWidget * child,boolean resize,boolean shrink)4432 WIDGET_HELPER_GLOBAL_INLINE boolean lives_paned_pack(int where, LiVESPaned *paned, LiVESWidget *child, boolean resize,
4433 boolean shrink) {
4434 #ifdef GUI_GTK
4435 if (where == 1) gtk_paned_pack1(paned, child, resize, shrink);
4436 else gtk_paned_pack2(paned, child, resize, shrink);
4437 return TRUE;
4438 #endif
4439 #ifdef GUI_QT
4440 paned->insertWidget(where - 1, child);
4441 return TRUE;
4442 #endif
4443 return FALSE;
4444 }
4445
4446
lives_drawing_area_new(void)4447 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_drawing_area_new(void) {
4448 LiVESWidget *darea = NULL;
4449 #ifdef GUI_GTK
4450 darea = gtk_drawing_area_new();
4451 #endif
4452 #ifdef GUI_QT
4453 darea = new LiVESDrawingArea;
4454 #endif
4455 return darea;
4456 }
4457
4458
lives_event_get_time(LiVESXEvent * event)4459 WIDGET_HELPER_GLOBAL_INLINE int lives_event_get_time(LiVESXEvent *event) {
4460 #ifdef GUI_GTK
4461 return gdk_event_get_time(event);
4462 #endif
4463 #ifdef GUI_QT
4464 // TODO
4465 LiVESXEventButton *xevent = (LiVESXEventButton *)event;
4466 return xevent->time;
4467 #endif
4468 return 0;
4469 }
4470
4471
lives_toggle_button_get_active(LiVESToggleButton * button)4472 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_get_active(LiVESToggleButton *button) {
4473 #ifdef GUI_GTK
4474 #if LIVES_HAS_SWITCH_WIDGET
4475 if (LIVES_IS_SWITCH(button)) return gtk_switch_get_active(LIVES_SWITCH(button));
4476 #endif
4477 return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
4478 #endif
4479 return FALSE;
4480 }
4481
4482
lives_toggle_button_set_active(LiVESToggleButton * button,boolean active)4483 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_set_active(LiVESToggleButton *button, boolean active) {
4484 #ifdef GUI_GTK
4485 #if LIVES_HAS_SWITCH_WIDGET
4486 if (LIVES_IS_SWITCH(button)) lives_switch_set_active(LIVES_SWITCH(button), active);
4487 else
4488 #endif
4489 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), active);
4490 return TRUE;
4491 #endif
4492 return FALSE;
4493 }
4494
4495
lives_toggle_button_set_mode(LiVESToggleButton * button,boolean drawind)4496 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_set_mode(LiVESToggleButton *button, boolean drawind) {
4497 #ifdef GUI_GTK
4498 #if LIVES_HAS_SWITCH_WIDGET
4499 if (!LIVES_IS_SWITCH(button))
4500 #endif
4501 gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(button), drawind);
4502 return TRUE;
4503 #endif
4504 return FALSE;
4505 }
4506
4507
lives_toggle_tool_button_new(void)4508 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_toggle_tool_button_new(void) {
4509 LiVESWidget *button = NULL;
4510 #ifdef GUI_GTK
4511 button = LIVES_WIDGET(gtk_toggle_tool_button_new());
4512 #endif
4513 return button;
4514 }
4515
4516
lives_toggle_tool_button_get_active(LiVESToggleToolButton * button)4517 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_tool_button_get_active(LiVESToggleToolButton *button) {
4518 #ifdef GUI_GTK
4519 return gtk_toggle_tool_button_get_active(button);
4520 #endif
4521 return FALSE;
4522 }
4523
4524
lives_toggle_tool_button_set_active(LiVESToggleToolButton * button,boolean active)4525 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_tool_button_set_active(LiVESToggleToolButton *button, boolean active) {
4526 #ifdef GUI_GTK
4527 gtk_toggle_tool_button_set_active(button, active);
4528 return TRUE;
4529 #endif
4530 return FALSE;
4531 }
4532
4533
lives_radio_button_new(LiVESSList * group)4534 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_radio_button_new(LiVESSList *group) {
4535 LiVESWidget *button = NULL;
4536 #ifdef GUI_GTK
4537 button = gtk_radio_button_new(group);
4538 #endif
4539 return button;
4540 }
4541
4542
lives_switch_new(void)4543 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_switch_new(void) {
4544 LiVESWidget *swtch = NULL;
4545 #if LIVES_HAS_SWITCH_WIDGET
4546 swtch = gtk_switch_new();
4547 #endif
4548 return swtch;
4549 }
4550
lives_switch_get_active(LiVESSwitch * swtch)4551 WIDGET_HELPER_GLOBAL_INLINE boolean lives_switch_get_active(LiVESSwitch *swtch) {
4552 #if LIVES_HAS_SWITCH_WIDGET
4553 return gtk_switch_get_active(swtch);
4554 #endif
4555 return FALSE;
4556 }
4557
lives_switch_set_active(LiVESSwitch * swtch,boolean active)4558 WIDGET_HELPER_GLOBAL_INLINE boolean lives_switch_set_active(LiVESSwitch *swtch, boolean active) {
4559 #if LIVES_HAS_SWITCH_WIDGET
4560 gtk_switch_set_active(swtch, active);
4561 return TRUE;
4562 #endif
4563 return FALSE;
4564 }
4565
4566
lives_spinner_new(void)4567 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_spinner_new(void) {
4568 LiVESWidget *spinner = NULL;
4569 #if LIVES_HAS_SPINNER_WIDGET
4570 spinner = gtk_spinner_new();
4571 #endif
4572 return spinner;
4573 }
4574
lives_spinner_start(LiVESSpinner * spinner)4575 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spinner_start(LiVESSpinner *spinner) {
4576 if (spinner) {
4577 #if LIVES_HAS_SPINNER_WIDGET
4578 gtk_spinner_start(GTK_SPINNER(spinner));
4579 return TRUE;
4580 #endif
4581 }
4582 return FALSE;
4583 }
4584
4585
lives_spinner_stop(LiVESSpinner * spinner)4586 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spinner_stop(LiVESSpinner *spinner) {
4587 if (spinner) {
4588 #if LIVES_HAS_SPINNER_WIDGET
4589 gtk_spinner_stop(GTK_SPINNER(spinner));
4590 return TRUE;
4591 #endif
4592 }
4593 return FALSE;
4594 }
4595
4596
lives_check_button_new(void)4597 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_check_button_new(void) {
4598 LiVESWidget *button = NULL;
4599 #ifdef GUI_GTK
4600 button = gtk_check_button_new();
4601 #endif
4602 return button;
4603 }
4604
4605
lives_check_button_new_with_label(const char * label)4606 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_check_button_new_with_label(const char *label) {
4607 LiVESWidget *button = NULL;
4608 #ifdef GUI_GTK
4609 button = gtk_check_button_new_with_label(label);
4610 #endif
4611 return button;
4612 }
4613
4614
make_ttips_image_for(LiVESWidget * widget,const char * text)4615 static LiVESWidget *make_ttips_image_for(LiVESWidget *widget, const char *text) {
4616 LiVESWidget *ttips_image = lives_image_new_from_stock("livestock-help-info",
4617 widget_opts.icon_size);
4618 if (ttips_image) {
4619 #if GTK_CHECK_VERSION(3, 16, 0)
4620 if (widget_opts.apply_theme) {
4621 set_css_value_direct(ttips_image, LIVES_WIDGET_STATE_NORMAL, "", "opacity", "0.75");
4622 set_css_value_direct(ttips_image, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
4623 }
4624 #endif
4625 lives_widget_set_no_show_all(ttips_image, TRUE);
4626 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ttips_image), TTIPS_IMAGE_KEY, ttips_image);
4627 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ttips_image), TTIPS_HIDE_KEY, ttips_image);
4628 if (text) lives_widget_set_tooltip_text(ttips_image, text);
4629 else {
4630 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(ttips_image),
4631 SHOWALL_OVERRIDE_KEY, LIVES_INT_TO_POINTER(TRUE));
4632 }
4633 lives_widget_set_show_hide_with(widget, ttips_image);
4634 lives_widget_set_sensitive_with(widget, ttips_image);
4635 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget), HAS_TTIPS_IMAGE_KEY, ttips_image);
4636 }
4637 return ttips_image;
4638 }
4639
4640
lives_widget_set_tooltip_text(LiVESWidget * widget,const char * tip_text)4641 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_widget_set_tooltip_text(LiVESWidget *widget, const char *tip_text) {
4642 LiVESWidget *img_tips = NULL;
4643 boolean ttips_override = FALSE;
4644 const char *ttext = tip_text;
4645
4646 if (!widget) return NULL;
4647
4648 if (tip_text && *tip_text == '#' && !lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
4649 TTIPS_IMAGE_KEY)) {
4650 if (!(img_tips = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), HAS_TTIPS_IMAGE_KEY))) {
4651 img_tips = make_ttips_image_for(widget, ++ttext);
4652 if (img_tips) widget = img_tips;
4653 } else lives_widget_set_tooltip_text(img_tips, ++ttext);
4654 }
4655 if (!img_tips) {
4656 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), TTIPS_OVERRIDE_KEY))
4657 ttips_override = TRUE;
4658 if (!prefs->show_tooltips && !ttips_override) {
4659 if (tip_text) {
4660 lives_widget_object_set_data_auto(LIVES_WIDGET_OBJECT(widget), TTIPS_KEY,
4661 (livespointer)(lives_strdup(ttext)));
4662 } else {
4663 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget), TTIPS_KEY, NULL);
4664 }
4665 if (!lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
4666 TTIPS_IMAGE_KEY)) {
4667 if (!lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
4668 HAS_TTIPS_IMAGE_KEY)) {
4669 img_tips = make_ttips_image_for(widget, NULL);
4670 return img_tips;
4671 }
4672 }
4673 return NULL;
4674 }
4675 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
4676 TTIPS_IMAGE_KEY)) {
4677 if (ttext) {
4678 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
4679 SHOWALL_OVERRIDE_KEY)) {
4680 LiVESWidget *cntrl;
4681 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget),
4682 SHOWALL_OVERRIDE_KEY, NULL);
4683 if ((cntrl = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
4684 SHOWHIDE_CONTROLLER_KEY))) {
4685 if (lives_widget_is_visible(cntrl)) lives_widget_show_all(widget);
4686 }
4687 }
4688 } else {
4689 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget),
4690 SHOWALL_OVERRIDE_KEY, widget);
4691 lives_widget_hide(widget);
4692 }
4693 } else {
4694 if (!lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), HAS_TTIPS_IMAGE_KEY)) {
4695 img_tips = make_ttips_image_for(widget, NULL);
4696 }
4697 }
4698 }
4699 #ifdef GUI_GTK
4700 #if GTK_CHECK_VERSION(2, 12, 0)
4701 gtk_widget_set_tooltip_text(widget, ttext);
4702 #else
4703 GtkTooltips *tips;
4704 tips = gtk_tooltips_new();
4705 gtk_tooltips_set_tip(tips, widget, ttext, NULL);
4706 #endif
4707 #endif
4708 return img_tips;
4709 }
4710
4711
lives_widget_grab_focus(LiVESWidget * widget)4712 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_grab_focus(LiVESWidget *widget) {
4713 #ifdef GUI_GTK
4714 gtk_widget_set_can_focus(widget, TRUE);
4715 gtk_widget_grab_focus(widget);
4716 return TRUE;
4717 #endif
4718 return FALSE;
4719 }
4720
4721
lives_widget_grab_default(LiVESWidget * widget)4722 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_grab_default(LiVESWidget *widget) {
4723 #ifdef GUI_GTK
4724 gtk_widget_grab_default(widget);
4725 return TRUE;
4726 #endif
4727 return FALSE;
4728 }
4729
4730
lives_radio_button_get_group(LiVESRadioButton * rbutton)4731 WIDGET_HELPER_GLOBAL_INLINE LiVESSList *lives_radio_button_get_group(LiVESRadioButton *rbutton) {
4732 #ifdef GUI_GTK
4733 return gtk_radio_button_get_group(rbutton);
4734 #endif
4735 return NULL;
4736 }
4737
4738
lives_widget_get_parent(LiVESWidget * widget)4739 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_widget_get_parent(LiVESWidget *widget) {
4740 #ifdef GUI_GTK
4741 return gtk_widget_get_parent(widget);
4742 #endif
4743 #ifdef GUI_QT
4744 return widget->get_parent();
4745 #endif
4746 return NULL;
4747 }
4748
4749
lives_widget_get_toplevel(LiVESWidget * widget)4750 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_widget_get_toplevel(LiVESWidget *widget) {
4751 #ifdef GUI_GTK
4752 if (!GTK_IS_WIDGET(widget)) return NULL;
4753 return gtk_widget_get_toplevel(widget);
4754 #endif
4755 return NULL;
4756 }
4757
4758
lives_widget_get_xwindow(LiVESWidget * widget)4759 WIDGET_HELPER_GLOBAL_INLINE LiVESXWindow *lives_widget_get_xwindow(LiVESWidget *widget) {
4760 #ifdef GUI_GTK
4761 #if GTK_CHECK_VERSION(2, 12, 0)
4762 return gtk_widget_get_window(widget);
4763 #else
4764 return GDK_WINDOW(widget->window);
4765 #endif
4766 #endif
4767 return NULL;
4768 }
4769
4770
lives_widget_get_window(LiVESWidget * widget)4771 WIDGET_HELPER_GLOBAL_INLINE LiVESWindow *lives_widget_get_window(LiVESWidget *widget) {
4772 #ifdef GUI_GTK
4773 LiVESWidget *window = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
4774 if (GTK_IS_WINDOW(window)) return (LiVESWindow *)window;
4775 #endif
4776 return NULL;
4777 }
4778
4779
lives_xwindow_set_keep_above(LiVESXWindow * xwin,boolean setting)4780 WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_set_keep_above(LiVESXWindow *xwin, boolean setting) {
4781 #ifdef GUI_GTK
4782 gdk_window_set_keep_above(xwin, setting);
4783 return TRUE;
4784 #endif
4785 return FALSE;
4786 }
4787
4788
lives_widget_set_can_focus(LiVESWidget * widget,boolean state)4789 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_can_focus(LiVESWidget *widget, boolean state) {
4790 #ifdef GUI_GTK
4791 #if GTK_CHECK_VERSION(2, 18, 0)
4792 gtk_widget_set_can_focus(widget, state);
4793 #else
4794 if (state)
4795 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_FOCUS);
4796 else
4797 GTK_WIDGET_UNSET_FLAGS(widget, GTK_CAN_FOCUS);
4798 #endif
4799 return TRUE;
4800 #endif
4801 return FALSE;
4802 }
4803
4804
lives_widget_set_can_default(LiVESWidget * widget,boolean state)4805 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_can_default(LiVESWidget *widget, boolean state) {
4806 #ifdef GUI_GTK
4807 #if GTK_CHECK_VERSION(2, 18, 0)
4808 gtk_widget_set_can_default(widget, state);
4809 #else
4810 if (state)
4811 GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
4812 else
4813 GTK_WIDGET_UNSET_FLAGS(widget, GTK_CAN_DEFAULT);
4814 #endif
4815 return TRUE;
4816 #endif
4817 return FALSE;
4818 }
4819
4820
lives_widget_add_events(LiVESWidget * widget,int events)4821 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_add_events(LiVESWidget *widget, int events) {
4822 #ifdef GUI_GTK
4823 gtk_widget_add_events(widget, events);
4824 return TRUE;
4825 #endif
4826 return FALSE;
4827 }
4828
4829
lives_widget_set_events(LiVESWidget * widget,int events)4830 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_events(LiVESWidget *widget, int events) {
4831 #ifdef GUI_GTK
4832 gtk_widget_set_events(widget, events);
4833 return TRUE;
4834 #endif
4835 #ifdef GUI_QT
4836 widget->set_events(events);
4837 return TRUE;
4838 #endif
4839 return FALSE;
4840 }
4841
4842
lives_widget_remove_accelerator(LiVESWidget * widget,LiVESAccelGroup * acgroup,uint32_t accel_key,LiVESXModifierType accel_mods)4843 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_remove_accelerator(LiVESWidget *widget, LiVESAccelGroup *acgroup,
4844 uint32_t accel_key, LiVESXModifierType accel_mods) {
4845 #ifdef GUI_GTK
4846 return gtk_widget_remove_accelerator(widget, acgroup, accel_key, accel_mods);
4847 #endif
4848 #ifdef GUI_QT
4849 return (static_cast<LiVESWidgetObject *>(widget))->remove_accels(acgroup, accel_key, accel_mods);
4850 #endif
4851 return FALSE;
4852 }
4853
4854
lives_widget_get_preferred_size(LiVESWidget * widget,LiVESRequisition * min_size,LiVESRequisition * nat_size)4855 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_preferred_size(LiVESWidget *widget, LiVESRequisition *min_size,
4856 LiVESRequisition *nat_size) {
4857 // for GTK 4.x we will use widget::measure()
4858 #ifdef GUI_GTK
4859 #if GTK_CHECK_VERSION(3, 0, 0)
4860 gtk_widget_get_preferred_size(widget, min_size, nat_size);
4861 return TRUE;
4862 #endif
4863 #endif
4864 return FALSE;
4865 }
4866
4867
lives_widget_set_no_show_all(LiVESWidget * widget,boolean set)4868 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_no_show_all(LiVESWidget *widget, boolean set) {
4869 #ifdef GUI_GTK
4870 gtk_widget_set_no_show_all(widget, set);
4871 return TRUE;
4872 #endif
4873 return FALSE;
4874 }
4875
4876
lives_widget_get_no_show_all(LiVESWidget * widget)4877 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_no_show_all(LiVESWidget *widget) {
4878 #ifdef GUI_GTK
4879 return gtk_widget_get_no_show_all(widget);
4880 #endif
4881 return FALSE;
4882 }
4883
4884
lives_widget_is_sensitive(LiVESWidget * widget)4885 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_is_sensitive(LiVESWidget *widget) {
4886 // return TRUE is widget + parent is sensitive
4887 #ifdef GUI_GTK
4888 #if GTK_CHECK_VERSION(2, 18, 0)
4889 return gtk_widget_is_sensitive(widget);
4890 #else
4891 return GTK_WIDGET_IS_SENSITIVE(widget);
4892 #endif
4893 #endif
4894 #ifdef GUI_QT
4895 return widget->isEnabled();
4896 #endif
4897 return FALSE;
4898 }
4899
4900
lives_widget_is_visible(LiVESWidget * widget)4901 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_is_visible(LiVESWidget *widget) {
4902 #ifdef GUI_GTK
4903 #if GTK_CHECK_VERSION(2, 18, 0)
4904 return gtk_widget_get_visible(widget);
4905 #else
4906 return GTK_WIDGET_VISIBLE(widget);
4907 #endif
4908 #endif
4909 #ifdef GUI_QT
4910 return widget->isVisible();
4911 #endif
4912 return FALSE;
4913 }
4914
4915
lives_widget_is_realized(LiVESWidget * widget)4916 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_is_realized(LiVESWidget *widget) {
4917 // used for giw widgets
4918 #ifdef GUI_GTK
4919 #if GTK_CHECK_VERSION(2, 18, 0)
4920 return gtk_widget_get_realized(widget);
4921 #else
4922 return GTK_WIDGET_REALIZED(widget);
4923 #endif
4924 #endif
4925 return FALSE;
4926 }
4927
4928
lives_container_add(LiVESContainer * container,LiVESWidget * widget)4929 WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_add(LiVESContainer *container, LiVESWidget *widget) {
4930 #ifdef GUI_GTK
4931 gtk_container_add(container, widget);
4932 return TRUE;
4933 #endif
4934 return FALSE;
4935 }
4936
4937
lives_container_remove(LiVESContainer * container,LiVESWidget * widget)4938 WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_remove(LiVESContainer *container, LiVESWidget *widget) {
4939 #ifdef GUI_GTK
4940 gtk_container_remove(container, widget);
4941 return TRUE;
4942 #endif
4943 return FALSE;
4944 }
4945
4946
lives_container_set_border_width(LiVESContainer * container,uint32_t width)4947 WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_set_border_width(LiVESContainer *container, uint32_t width) {
4948 // sets border OUTSIDE container
4949 #ifdef GUI_GTK
4950 gtk_container_set_border_width(container, width);
4951 return TRUE;
4952 #endif
4953 return FALSE;
4954 }
4955
4956
lives_container_foreach(LiVESContainer * cont,LiVESWidgetCallback callback,livespointer cb_data)4957 WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_foreach(LiVESContainer *cont, LiVESWidgetCallback callback,
4958 livespointer cb_data) {
4959 // excludes internal children
4960 #ifdef GUI_GTK
4961 gtk_container_foreach(cont, callback, cb_data);
4962 return TRUE;
4963 #endif
4964 return FALSE;
4965 }
4966
4967
lives_container_forall(LiVESContainer * cont,LiVESWidgetCallback callback,livespointer cb_data)4968 WIDGET_HELPER_LOCAL_INLINE boolean lives_container_forall(LiVESContainer *cont, LiVESWidgetCallback callback,
4969 livespointer cb_data) {
4970 // includes internal children
4971 #ifdef GUI_GTK
4972 gtk_container_forall(cont, callback, cb_data);
4973 return TRUE;
4974 #endif
4975 return FALSE;
4976 }
4977
4978
lives_container_get_children(LiVESContainer * cont)4979 WIDGET_HELPER_GLOBAL_INLINE LiVESList *lives_container_get_children(LiVESContainer *cont) {
4980 LiVESList *children = NULL;
4981 #ifdef GUI_GTK
4982 children = gtk_container_get_children(cont);
4983 #endif
4984 return children;
4985 }
4986
4987
lives_container_set_focus_child(LiVESContainer * cont,LiVESWidget * child)4988 WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_set_focus_child(LiVESContainer *cont, LiVESWidget *child) {
4989 #ifdef GUI_GTK
4990 gtk_container_set_focus_child(cont, child);
4991 return TRUE;
4992 #endif
4993 return FALSE;
4994 }
4995
4996
lives_container_get_focus_child(LiVESContainer * cont)4997 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_container_get_focus_child(LiVESContainer *cont) {
4998 #ifdef GUI_GTK
4999 return gtk_container_get_focus_child(cont);
5000 #endif
5001 return NULL;
5002 }
5003
5004
lives_progress_bar_new(void)5005 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_progress_bar_new(void) {
5006 LiVESWidget *pbar = NULL;
5007 #ifdef GUI_GTK
5008 pbar = gtk_progress_bar_new();
5009 #endif
5010 return pbar;
5011 }
5012
5013
lives_progress_bar_set_fraction(LiVESProgressBar * pbar,double fraction)5014 WIDGET_HELPER_GLOBAL_INLINE boolean lives_progress_bar_set_fraction(LiVESProgressBar *pbar, double fraction) {
5015 #ifdef GUI_GTK
5016 #ifdef PROGBAR_IS_ENTRY
5017 if (palette->style & STYLE_1) {
5018 lives_widget_set_sensitive(LIVES_WIDGET(pbar), FALSE);
5019 }
5020 gtk_entry_set_progress_fraction(pbar, fraction);
5021 if (is_standard_widget(LIVES_WIDGET(pbar)) && widget_opts.apply_theme) {
5022 set_css_value_direct(LIVES_WIDGET(pbar), LIVES_WIDGET_STATE_NORMAL, "progress",
5023 "border-width", "0px");
5024 }
5025 #else
5026 gtk_progress_bar_set_fraction(pbar, fraction);
5027 #endif
5028 return TRUE;
5029 #endif
5030 return FALSE;
5031 }
5032
5033
lives_progress_bar_set_pulse_step(LiVESProgressBar * pbar,double fraction)5034 WIDGET_HELPER_GLOBAL_INLINE boolean lives_progress_bar_set_pulse_step(LiVESProgressBar *pbar, double fraction) {
5035 #ifdef GUI_GTK
5036 #ifdef PROGBAR_IS_ENTRY
5037 gtk_entry_set_progress_pulse_step(pbar, fraction);
5038 #else
5039 gtk_progress_bar_set_pulse_step(pbar, fraction);
5040 #endif
5041 return TRUE;
5042 #endif
5043 return FALSE;
5044 }
5045
5046
lives_progress_bar_pulse(LiVESProgressBar * pbar)5047 WIDGET_HELPER_GLOBAL_INLINE boolean lives_progress_bar_pulse(LiVESProgressBar *pbar) {
5048 #ifdef GUI_GTK
5049 #ifdef PROGBAR_IS_ENTRY
5050 if (palette->style & STYLE_1) {
5051 lives_widget_set_sensitive(LIVES_WIDGET(pbar), TRUE);
5052 }
5053 gtk_entry_progress_pulse(pbar);
5054 if (is_standard_widget(LIVES_WIDGET(pbar)) && widget_opts.apply_theme) {
5055 char *tmp = lives_strdup_printf("%dpx", widget_opts.css_min_height);
5056 set_css_value_direct(LIVES_WIDGET(pbar), LIVES_WIDGET_STATE_NORMAL, "progress",
5057 "border-top-width", tmp);
5058 set_css_value_direct(LIVES_WIDGET(pbar), LIVES_WIDGET_STATE_NORMAL, "progress",
5059 "border-bottom-width", tmp);
5060 lives_free(tmp);
5061 }
5062 #else
5063 gtk_progress_bar_pulse(pbar);
5064 #endif
5065 return TRUE;
5066 #endif
5067 return FALSE;
5068 }
5069
5070
lives_spin_button_new(LiVESAdjustment * adj,double climb_rate,uint32_t digits)5071 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_spin_button_new(LiVESAdjustment *adj, double climb_rate, uint32_t digits) {
5072 LiVESWidget *sbutton = NULL;
5073 #ifdef GUI_GTK
5074 sbutton = gtk_spin_button_new(adj, climb_rate, digits);
5075 #endif
5076 #ifdef GUI_QT
5077 sbutton = new LiVESSpinButton(adj, climb_rate, digits);
5078 #endif
5079 return sbutton;
5080 }
5081
5082
lives_spin_button_get_value(LiVESSpinButton * button)5083 WIDGET_HELPER_GLOBAL_INLINE double lives_spin_button_get_value(LiVESSpinButton *button) {
5084 #ifdef GUI_GTK
5085 return gtk_spin_button_get_value(button);
5086 #endif
5087 return 0.;
5088 }
5089
5090
lives_spin_button_get_value_as_int(LiVESSpinButton * button)5091 WIDGET_HELPER_GLOBAL_INLINE int lives_spin_button_get_value_as_int(LiVESSpinButton *button) {
5092 #ifdef GUI_GTK
5093 return gtk_spin_button_get_value_as_int(button);
5094 #endif
5095 return 0.;
5096 }
5097
5098
lives_spin_button_get_adjustment(LiVESSpinButton * button)5099 WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment *lives_spin_button_get_adjustment(LiVESSpinButton *button) {
5100 LiVESAdjustment *adj = NULL;
5101 #ifdef GUI_GTK
5102 adj = gtk_spin_button_get_adjustment(button);
5103 #endif
5104 #ifdef GUI_QT
5105 adj = button->get_adj();
5106 #endif
5107 return adj;
5108 }
5109
5110
lives_spin_button_set_adjustment(LiVESSpinButton * button,LiVESAdjustment * adj)5111 WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment *lives_spin_button_set_adjustment(LiVESSpinButton *button, LiVESAdjustment *adj) {
5112 #ifdef GUI_GTK
5113 gtk_spin_button_set_adjustment(button, adj);
5114 #endif
5115 return adj;
5116 }
5117
5118
lives_spin_button_set_value(LiVESSpinButton * button,double value)5119 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_value(LiVESSpinButton *button, double value) {
5120 if (is_standard_widget(LIVES_WIDGET(button))) value = lives_spin_button_get_snapval(button, value);
5121 #ifdef GUI_GTK
5122 gtk_spin_button_set_value(button, value);
5123 return TRUE;
5124 #endif
5125 return FALSE;
5126 }
5127
5128
lives_spin_button_set_range(LiVESSpinButton * button,double min,double max)5129 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_range(LiVESSpinButton *button, double min, double max) {
5130 #ifdef GUI_GTK
5131 gtk_spin_button_set_range(button, min, max);
5132 return TRUE;
5133 #endif
5134 return FALSE;
5135 }
5136
5137
lives_spin_button_set_wrap(LiVESSpinButton * button,boolean wrap)5138 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_wrap(LiVESSpinButton *button, boolean wrap) {
5139 #ifdef GUI_GTK
5140 gtk_spin_button_set_wrap(button, wrap);
5141 return TRUE;
5142 #endif
5143 return FALSE;
5144 }
5145
5146
lives_spin_button_set_snap_to_ticks(LiVESSpinButton * button,boolean snap)5147 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_snap_to_ticks(LiVESSpinButton *button, boolean snap) {
5148 #ifdef GUI_GTK
5149 gtk_spin_button_set_snap_to_ticks(button, snap);
5150 return TRUE;
5151 #endif
5152 return FALSE;
5153 }
5154
5155
lives_spin_button_set_digits(LiVESSpinButton * button,uint32_t digits)5156 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_digits(LiVESSpinButton *button, uint32_t digits) {
5157 #ifdef GUI_GTK
5158 gtk_spin_button_set_digits(button, digits);
5159 return TRUE;
5160 #endif
5161 return FALSE;
5162 }
5163
5164
lives_spin_button_update(LiVESSpinButton * button)5165 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_update(LiVESSpinButton *button) {
5166 #ifdef GUI_GTK
5167 gtk_spin_button_update(button);
5168 return TRUE;
5169 #endif
5170 return FALSE;
5171 }
5172
5173
lives_tool_button_new(LiVESWidget * icon_widget,const char * label)5174 WIDGET_HELPER_GLOBAL_INLINE LiVESToolItem *lives_tool_button_new(LiVESWidget *icon_widget, const char *label) {
5175 LiVESToolItem *button = NULL;
5176 #ifdef GUI_GTK
5177 button = gtk_tool_button_new(icon_widget, label);
5178 #endif
5179 return button;
5180 }
5181
5182
lives_tool_item_new(void)5183 WIDGET_HELPER_GLOBAL_INLINE LiVESToolItem *lives_tool_item_new(void) {
5184 LiVESToolItem *item = NULL;
5185 #ifdef GUI_GTK
5186 item = gtk_tool_item_new();
5187 #endif
5188 return item;
5189 }
5190
5191
lives_separator_tool_item_new(void)5192 WIDGET_HELPER_GLOBAL_INLINE LiVESToolItem *lives_separator_tool_item_new(void) {
5193 LiVESToolItem *item = NULL;
5194 #ifdef GUI_GTK
5195 item = gtk_separator_tool_item_new();
5196 #endif
5197 return item;
5198 }
5199
5200
lives_tool_button_set_icon_widget(LiVESToolButton * button,LiVESWidget * icon)5201 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tool_button_set_icon_widget(LiVESToolButton *button, LiVESWidget *icon) {
5202 #ifdef GUI_GTK
5203 gtk_tool_button_set_icon_widget(button, icon);
5204 return TRUE;
5205 #endif
5206 return FALSE;
5207 }
5208
5209
lives_tool_button_get_icon_widget(LiVESToolButton * button)5210 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_tool_button_get_icon_widget(LiVESToolButton *button) {
5211 #ifdef GUI_GTK
5212 return gtk_tool_button_get_icon_widget(button);
5213 #endif
5214 return NULL;
5215 }
5216
5217
lives_tool_button_set_label_widget(LiVESToolButton * button,LiVESWidget * label)5218 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tool_button_set_label_widget(LiVESToolButton *button, LiVESWidget *label) {
5219 #ifdef GUI_GTK
5220 gtk_tool_button_set_label_widget(button, label);
5221 return TRUE;
5222 #endif
5223 return FALSE;
5224 }
5225
5226
lives_tool_button_get_label_widget(LiVESToolButton * button)5227 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_tool_button_get_label_widget(LiVESToolButton *button) {
5228 #ifdef GUI_GTK
5229 return gtk_tool_button_get_label_widget(button);
5230 #endif
5231 return NULL;
5232 }
5233
5234
lives_tool_button_set_use_underline(LiVESToolButton * button,boolean use_underline)5235 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tool_button_set_use_underline(LiVESToolButton *button, boolean use_underline) {
5236 #ifdef GUI_GTK
5237 gtk_tool_button_set_use_underline(button, use_underline);
5238 return TRUE;
5239 #endif
5240 return FALSE;
5241 }
5242
5243
lives_ruler_set_range(LiVESRuler * ruler,double lower,double upper,double position,double max_size)5244 WIDGET_HELPER_GLOBAL_INLINE boolean lives_ruler_set_range(LiVESRuler *ruler, double lower, double upper, double position,
5245 double max_size) {
5246 #ifdef GUI_GTK
5247 #if GTK_CHECK_VERSION(3, 0, 0)
5248 gtk_range_set_range(GTK_RANGE(ruler), lower, upper);
5249 gtk_range_set_value(GTK_RANGE(ruler), position);
5250 #else
5251 gtk_ruler_set_range(ruler, lower, upper, position, max_size);
5252 return TRUE;
5253 #endif
5254 return FALSE;
5255 #endif
5256 }
5257
5258
lives_message_dialog_new(LiVESWindow * parent,LiVESDialogFlags flags,LiVESMessageType type,LiVESButtonsType buttons,const char * msg_fmt,...)5259 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_message_dialog_new(LiVESWindow *parent, LiVESDialogFlags flags,
5260 LiVESMessageType type,
5261 LiVESButtonsType buttons, const char *msg_fmt, ...) {
5262 LiVESWidget *mdial = NULL;
5263 #ifdef GUI_GTK
5264 mdial = gtk_message_dialog_new(parent, flags | GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, msg_fmt, NULL);
5265 #endif
5266 if (mdial && mainw && mainw->mgeom) lives_window_set_monitor(LIVES_WINDOW(mdial),
5267 widget_opts.monitor);
5268 return mdial;
5269 }
5270
5271
lives_ruler_get_value(LiVESRuler * ruler)5272 WIDGET_HELPER_GLOBAL_INLINE double lives_ruler_get_value(LiVESRuler *ruler) {
5273 #ifdef GUI_GTK
5274 #if GTK_CHECK_VERSION(3, 0, 0)
5275 return gtk_range_get_value(GTK_RANGE(ruler));
5276 #else
5277 return ruler->position;
5278 #endif
5279 #endif
5280 return 0.;
5281 }
5282
5283
lives_ruler_set_value(LiVESRuler * ruler,double value)5284 WIDGET_HELPER_GLOBAL_INLINE double lives_ruler_set_value(LiVESRuler *ruler, double value) {
5285 #ifdef GUI_GTK
5286 #if GTK_CHECK_VERSION(3, 0, 0)
5287 gtk_range_set_value(GTK_RANGE(ruler), value);
5288 #else
5289 ruler->position = value;
5290 #endif
5291 #endif
5292 return value;
5293 }
5294
5295
lives_ruler_set_upper(LiVESRuler * ruler,double value)5296 WIDGET_HELPER_GLOBAL_INLINE double lives_ruler_set_upper(LiVESRuler *ruler, double value) {
5297 #ifdef GUI_GTK
5298 #if GTK_CHECK_VERSION(3, 0, 0)
5299 #ifdef ENABLE_GIW_3
5300 if (GIW_IS_TIMELINE(ruler)) {
5301 LiVESAdjustment *adj = giw_timeline_get_adjustment(GIW_TIMELINE(ruler));
5302 double lower = lives_adjustment_get_lower(adj);
5303 giw_timeline_set_range(GIW_TIMELINE(ruler), lower, value, giw_timeline_get_max_size(GIW_TIMELINE(ruler)));
5304 } else
5305 #endif
5306 gtk_adjustment_set_upper(gtk_range_get_adjustment(GTK_RANGE(ruler)), value);
5307 #else
5308 ruler->upper = value;
5309 #endif
5310 #endif
5311 return value;
5312 }
5313
5314
lives_ruler_set_lower(LiVESRuler * ruler,double value)5315 WIDGET_HELPER_GLOBAL_INLINE double lives_ruler_set_lower(LiVESRuler *ruler, double value) {
5316 #ifdef GUI_GTK
5317 #if GTK_CHECK_VERSION(3, 0, 0)
5318 #ifdef ENABLE_GIW_3
5319 if (GIW_IS_TIMELINE(ruler)) {
5320 LiVESAdjustment *adj = giw_timeline_get_adjustment(GIW_TIMELINE(ruler));
5321 double upper = lives_adjustment_get_upper(adj);
5322 giw_timeline_set_range(GIW_TIMELINE(ruler), value, upper, giw_timeline_get_max_size(GIW_TIMELINE(ruler)));
5323 } else
5324 #endif
5325 gtk_adjustment_set_lower(gtk_range_get_adjustment(GTK_RANGE(ruler)), value);
5326 #else
5327 ruler->lower = value;
5328 #endif
5329 #endif
5330 return value;
5331 }
5332
5333
lives_cell_renderer_text_new(void)5334 WIDGET_HELPER_GLOBAL_INLINE LiVESCellRenderer *lives_cell_renderer_text_new(void) {
5335 LiVESCellRenderer *renderer = NULL;
5336 #ifdef GUI_GTK
5337 renderer = gtk_cell_renderer_text_new();
5338 #endif
5339 return renderer;
5340 }
5341
5342
lives_cell_renderer_spin_new(void)5343 WIDGET_HELPER_GLOBAL_INLINE LiVESCellRenderer *lives_cell_renderer_spin_new(void) {
5344 LiVESCellRenderer *renderer = NULL;
5345 #ifdef GUI_GTK
5346 #if GTK_CHECK_VERSION(2, 10, 0)
5347 renderer = gtk_cell_renderer_spin_new();
5348 #endif
5349 #endif
5350 return renderer;
5351 }
5352
5353
lives_cell_renderer_toggle_new(void)5354 WIDGET_HELPER_GLOBAL_INLINE LiVESCellRenderer *lives_cell_renderer_toggle_new(void) {
5355 LiVESCellRenderer *renderer = NULL;
5356 #ifdef GUI_GTK
5357 renderer = gtk_cell_renderer_toggle_new();
5358 #endif
5359 return renderer;
5360 }
5361
5362
lives_cell_renderer_pixbuf_new(void)5363 WIDGET_HELPER_GLOBAL_INLINE LiVESCellRenderer *lives_cell_renderer_pixbuf_new(void) {
5364 LiVESCellRenderer *renderer = NULL;
5365 #ifdef GUI_GTK
5366 renderer = gtk_cell_renderer_pixbuf_new();
5367 #endif
5368 return renderer;
5369 }
5370
5371
lives_toolbar_new(void)5372 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_toolbar_new(void) {
5373 LiVESWidget *toolbar = NULL;
5374 #ifdef GUI_GTK
5375 toolbar = gtk_toolbar_new();
5376 #endif
5377 return toolbar;
5378 }
5379
5380
lives_toolbar_insert(LiVESToolbar * toolbar,LiVESToolItem * item,int pos)5381 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toolbar_insert(LiVESToolbar *toolbar, LiVESToolItem *item, int pos) {
5382 #ifdef GUI_GTK
5383 gtk_toolbar_insert(toolbar, item, pos);
5384 return TRUE;
5385 #endif
5386 return FALSE;
5387 }
5388
5389
lives_toolbar_set_show_arrow(LiVESToolbar * toolbar,boolean show)5390 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toolbar_set_show_arrow(LiVESToolbar *toolbar, boolean show) {
5391 #ifdef GUI_GTK
5392 gtk_toolbar_set_show_arrow(toolbar, show);
5393 return TRUE;
5394 #endif
5395 return FALSE;
5396 }
5397
5398
lives_toolbar_get_icon_size(LiVESToolbar * toolbar)5399 WIDGET_HELPER_GLOBAL_INLINE LiVESIconSize lives_toolbar_get_icon_size(LiVESToolbar *toolbar) {
5400 #ifdef GUI_GTK
5401 return gtk_toolbar_get_icon_size(toolbar);
5402 #endif
5403 return LIVES_ICON_SIZE_INVALID;
5404 }
5405
5406
lives_toolbar_set_icon_size(LiVESToolbar * toolbar,LiVESIconSize icon_size)5407 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toolbar_set_icon_size(LiVESToolbar *toolbar, LiVESIconSize icon_size) {
5408 #ifdef GUI_GTK
5409 gtk_toolbar_set_icon_size(toolbar, icon_size);
5410 return TRUE;
5411 #endif
5412 return FALSE;
5413 }
5414
5415
lives_toolbar_set_style(LiVESToolbar * toolbar,LiVESToolbarStyle style)5416 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toolbar_set_style(LiVESToolbar *toolbar, LiVESToolbarStyle style) {
5417 #ifdef GUI_GTK
5418 gtk_toolbar_set_style(toolbar, style);
5419 return TRUE;
5420 #endif
5421 return FALSE;
5422 }
5423
5424
lives_widget_get_allocation_x(LiVESWidget * widget)5425 WIDGET_HELPER_GLOBAL_INLINE int lives_widget_get_allocation_x(LiVESWidget *widget) {
5426 int x = 0;
5427 #ifdef GUI_GTK
5428 #if GTK_CHECK_VERSION(2, 18, 0)
5429 GtkAllocation alloc;
5430 gtk_widget_get_allocation(widget, &alloc);
5431 x = alloc.x;
5432 #else
5433 x = widget->allocation.x;
5434 #endif
5435 #endif
5436 return x;
5437 }
5438
5439
lives_widget_get_allocation_y(LiVESWidget * widget)5440 WIDGET_HELPER_GLOBAL_INLINE int lives_widget_get_allocation_y(LiVESWidget *widget) {
5441 int y = 0;
5442 #ifdef GUI_GTK
5443 #if GTK_CHECK_VERSION(2, 18, 0)
5444 GtkAllocation alloc;
5445 gtk_widget_get_allocation(widget, &alloc);
5446 y = alloc.y;
5447 #else
5448 y = widget->allocation.y;
5449 #endif
5450 #endif
5451 return y;
5452 }
5453
5454
lives_widget_get_allocation_width(LiVESWidget * widget)5455 WIDGET_HELPER_GLOBAL_INLINE int lives_widget_get_allocation_width(LiVESWidget *widget) {
5456 int width = 0;
5457 #ifdef GUI_GTK
5458 #if GTK_CHECK_VERSION(2, 18, 0)
5459 GtkAllocation alloc;
5460 gtk_widget_get_allocation(widget, &alloc);
5461 width = alloc.width;
5462 #else
5463 width = widget->allocation.width;
5464 #endif
5465 #endif
5466 return width;
5467 }
5468
5469
lives_widget_get_allocation_height(LiVESWidget * widget)5470 WIDGET_HELPER_GLOBAL_INLINE int lives_widget_get_allocation_height(LiVESWidget *widget) {
5471 int height = 0;
5472 #ifdef GUI_GTK
5473 #if GTK_CHECK_VERSION(2, 18, 0)
5474 GtkAllocation alloc;
5475 gtk_widget_get_allocation(widget, &alloc);
5476 height = alloc.height;
5477 #else
5478 height = widget->allocation.height;
5479 #endif
5480 #endif
5481 return height;
5482 }
5483
5484
lives_widget_set_state(LiVESWidget * widget,LiVESWidgetState state)5485 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_state(LiVESWidget *widget, LiVESWidgetState state) {
5486 #ifdef GUI_GTK
5487 #if GTK_CHECK_VERSION(3, 0, 0)
5488 gtk_widget_set_state_flags(widget, state, TRUE);
5489 #else
5490 gtk_widget_set_state(widget, state);
5491 #endif
5492 return TRUE;
5493 #endif
5494 return FALSE;
5495 }
5496
5497
lives_widget_get_state(LiVESWidget * widget)5498 WIDGET_HELPER_GLOBAL_INLINE LiVESWidgetState lives_widget_get_state(LiVESWidget *widget) {
5499 #ifdef GUI_GTK
5500 #if GTK_CHECK_VERSION(3, 0, 0)
5501 return gtk_widget_get_state_flags(widget);
5502 #else
5503 #if GTK_CHECK_VERSION(2, 18, 0)
5504 return gtk_widget_get_state(widget);
5505 #else
5506 return GTK_WIDGET_STATE(widget);
5507 #endif
5508 #endif
5509 #endif
5510 return (LiVESWidgetState)0;
5511 }
5512
5513
lives_bin_get_child(LiVESBin * bin)5514 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_bin_get_child(LiVESBin *bin) {
5515 LiVESWidget *child = NULL;
5516 #ifdef GUI_GTK
5517 child = gtk_bin_get_child(bin);
5518 #endif
5519 return child;
5520 }
5521
5522
lives_adjustment_get_upper(LiVESAdjustment * adj)5523 WIDGET_HELPER_GLOBAL_INLINE double lives_adjustment_get_upper(LiVESAdjustment *adj) {
5524 double upper = 0.;
5525 #ifdef GUI_GTK
5526 #if GTK_CHECK_VERSION(2, 14, 0)
5527 upper = gtk_adjustment_get_upper(adj);
5528 #else
5529 upper = adj->upper;
5530 #endif
5531 #endif
5532 return upper;
5533 }
5534
5535
lives_adjustment_get_lower(LiVESAdjustment * adj)5536 WIDGET_HELPER_GLOBAL_INLINE double lives_adjustment_get_lower(LiVESAdjustment *adj) {
5537 double lower = 0.;
5538 #ifdef GUI_GTK
5539 #if GTK_CHECK_VERSION(2, 14, 0)
5540 lower = gtk_adjustment_get_lower(adj);
5541 #else
5542 lower = adj->lower;
5543 #endif
5544 #endif
5545 return lower;
5546 }
5547
5548
lives_adjustment_get_page_size(LiVESAdjustment * adj)5549 WIDGET_HELPER_GLOBAL_INLINE double lives_adjustment_get_page_size(LiVESAdjustment *adj) {
5550 double page_size = 0.;
5551 #ifdef GUI_GTK
5552 #if GTK_CHECK_VERSION(2, 14, 0)
5553 page_size = gtk_adjustment_get_page_size(adj);
5554 #else
5555 page_size = adj->page_size;
5556 #endif
5557 #endif
5558 return page_size;
5559 }
5560
5561
lives_adjustment_get_step_increment(LiVESAdjustment * adj)5562 WIDGET_HELPER_GLOBAL_INLINE double lives_adjustment_get_step_increment(LiVESAdjustment *adj) {
5563 double step_increment = 0.;
5564 #ifdef GUI_GTK
5565 #if GTK_CHECK_VERSION(2, 14, 0)
5566 step_increment = gtk_adjustment_get_step_increment(adj);
5567 #else
5568 step_increment = adj->step_increment;
5569 #endif
5570 #endif
5571 return step_increment;
5572 }
5573
5574
lives_adjustment_get_value(LiVESAdjustment * adj)5575 WIDGET_HELPER_GLOBAL_INLINE double lives_adjustment_get_value(LiVESAdjustment *adj) {
5576 double value = 0.;
5577 #ifdef GUI_GTK
5578 value = gtk_adjustment_get_value(adj);
5579 #endif
5580 return value;
5581 }
5582
5583
lives_adjustment_set_upper(LiVESAdjustment * adj,double upper)5584 WIDGET_HELPER_GLOBAL_INLINE boolean lives_adjustment_set_upper(LiVESAdjustment *adj, double upper) {
5585 #ifdef GUI_GTK
5586 #if GTK_CHECK_VERSION(2, 14, 0)
5587 gtk_adjustment_set_upper(adj, upper);
5588 #else
5589 adj->upper = upper;
5590 #endif
5591 return TRUE;
5592 #endif
5593 return FALSE;
5594 }
5595
5596
lives_adjustment_set_lower(LiVESAdjustment * adj,double lower)5597 WIDGET_HELPER_GLOBAL_INLINE boolean lives_adjustment_set_lower(LiVESAdjustment *adj, double lower) {
5598 #ifdef GUI_GTK
5599 #if GTK_CHECK_VERSION(2, 14, 0)
5600 gtk_adjustment_set_lower(adj, lower);
5601 #else
5602 adj->lower = lower;
5603 #endif
5604 return TRUE;
5605 #endif
5606 return FALSE;
5607 }
5608
5609
lives_adjustment_set_page_size(LiVESAdjustment * adj,double page_size)5610 WIDGET_HELPER_GLOBAL_INLINE boolean lives_adjustment_set_page_size(LiVESAdjustment *adj, double page_size) {
5611 #ifdef GUI_GTK
5612 #if GTK_CHECK_VERSION(2, 14, 0)
5613 gtk_adjustment_set_page_size(adj, page_size);
5614 #else
5615 adj->page_size = page_size;
5616 #endif
5617 return TRUE;
5618 #endif
5619 return FALSE;
5620 }
5621
5622
lives_adjustment_set_step_increment(LiVESAdjustment * adj,double step_increment)5623 WIDGET_HELPER_GLOBAL_INLINE boolean lives_adjustment_set_step_increment(LiVESAdjustment *adj, double step_increment) {
5624 #ifdef GUI_GTK
5625 #if GTK_CHECK_VERSION(2, 14, 0)
5626 gtk_adjustment_set_step_increment(adj, step_increment);
5627 #else
5628 adj->step_increment = step_increment;
5629 #endif
5630 return TRUE;
5631 #endif
5632 return FALSE;
5633 }
5634
5635
lives_adjustment_set_value(LiVESAdjustment * adj,double value)5636 WIDGET_HELPER_GLOBAL_INLINE boolean lives_adjustment_set_value(LiVESAdjustment *adj, double value) {
5637 #ifdef GUI_GTK
5638 gtk_adjustment_set_value(adj, value);
5639 return TRUE;
5640 #endif
5641 return FALSE;
5642 }
5643
5644
lives_adjustment_clamp_page(LiVESAdjustment * adj,double lower,double upper)5645 WIDGET_HELPER_GLOBAL_INLINE boolean lives_adjustment_clamp_page(LiVESAdjustment *adj, double lower, double upper) {
5646 #ifdef GUI_GTK
5647 gtk_adjustment_clamp_page(adj, lower, upper);
5648 return TRUE;
5649 #endif
5650 return FALSE;
5651 }
5652
5653
lives_range_get_adjustment(LiVESRange * range)5654 WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment *lives_range_get_adjustment(LiVESRange *range) {
5655 LiVESAdjustment *adj = NULL;
5656 #ifdef GUI_GTK
5657 adj = gtk_range_get_adjustment(range);
5658 #endif
5659 return adj;
5660 }
5661
5662
lives_range_set_value(LiVESRange * range,double value)5663 WIDGET_HELPER_GLOBAL_INLINE boolean lives_range_set_value(LiVESRange *range, double value) {
5664 #ifdef GUI_GTK
5665 gtk_range_set_value(range, value);
5666 return TRUE;
5667 #endif
5668 return FALSE;
5669 }
5670
5671
lives_range_set_range(LiVESRange * range,double min,double max)5672 WIDGET_HELPER_GLOBAL_INLINE boolean lives_range_set_range(LiVESRange *range, double min, double max) {
5673 #ifdef GUI_GTK
5674 gtk_range_set_range(range, min, max);
5675 return TRUE;
5676 #endif
5677 return FALSE;
5678 }
5679
5680
lives_range_set_increments(LiVESRange * range,double step,double page)5681 WIDGET_HELPER_GLOBAL_INLINE boolean lives_range_set_increments(LiVESRange *range, double step, double page) {
5682 #ifdef GUI_GTK
5683 gtk_range_set_increments(range, step, page);
5684 return TRUE;
5685 #endif
5686 return FALSE;
5687 }
5688
5689
lives_range_set_inverted(LiVESRange * range,boolean invert)5690 WIDGET_HELPER_GLOBAL_INLINE boolean lives_range_set_inverted(LiVESRange *range, boolean invert) {
5691 #ifdef GUI_GTK
5692 gtk_range_set_inverted(range, invert);
5693 return TRUE;
5694 #endif
5695 return FALSE;
5696 }
5697
5698
lives_range_get_value(LiVESRange * range)5699 WIDGET_HELPER_GLOBAL_INLINE double lives_range_get_value(LiVESRange *range) {
5700 double value = 0.;
5701 #ifdef GUI_GTK
5702 value = gtk_range_get_value(range);
5703 #endif
5704 return value;
5705 }
5706
5707
lives_tree_model_get(LiVESTreeModel * tmod,LiVESTreeIter * titer,...)5708 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_get(LiVESTreeModel *tmod, LiVESTreeIter *titer, ...) {
5709 boolean res = FALSE;
5710 va_list argList;
5711 va_start(argList, titer);
5712 #ifdef GUI_GTK
5713 gtk_tree_model_get_valist(tmod, titer, argList);
5714 res = TRUE;
5715 #endif
5716 va_end(argList);
5717 return res;
5718 }
5719
5720
lives_tree_model_get_iter(LiVESTreeModel * tmod,LiVESTreeIter * titer,LiVESTreePath * tpath)5721 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_get_iter(LiVESTreeModel *tmod, LiVESTreeIter *titer,
5722 LiVESTreePath *tpath) {
5723 #ifdef GUI_GTK
5724 return gtk_tree_model_get_iter(tmod, titer, tpath);
5725 #endif
5726 return FALSE;
5727 }
5728
5729
lives_tree_model_get_iter_first(LiVESTreeModel * tmod,LiVESTreeIter * titer)5730 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_get_iter_first(LiVESTreeModel *tmod, LiVESTreeIter *titer) {
5731 #ifdef GUI_GTK
5732 return gtk_tree_model_get_iter_first(tmod, titer);
5733 #endif
5734 return FALSE;
5735 }
5736
5737
lives_tree_model_get_path(LiVESTreeModel * tmod,LiVESTreeIter * titer)5738 WIDGET_HELPER_GLOBAL_INLINE LiVESTreePath *lives_tree_model_get_path(LiVESTreeModel *tmod, LiVESTreeIter *titer) {
5739 LiVESTreePath *tpath = NULL;
5740 #ifdef GUI_GTK
5741 tpath = gtk_tree_model_get_path(tmod, titer);
5742 #endif
5743 return tpath;
5744 }
5745
5746
lives_tree_model_iter_children(LiVESTreeModel * tmod,LiVESTreeIter * titer,LiVESTreeIter * parent)5747 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_iter_children(LiVESTreeModel *tmod, LiVESTreeIter *titer,
5748 LiVESTreeIter *parent) {
5749 #ifdef GUI_GTK
5750 return gtk_tree_model_iter_children(tmod, titer, parent);
5751 #endif
5752 return FALSE;
5753 }
5754
5755
lives_tree_model_iter_n_children(LiVESTreeModel * tmod,LiVESTreeIter * titer)5756 WIDGET_HELPER_GLOBAL_INLINE int lives_tree_model_iter_n_children(LiVESTreeModel *tmod, LiVESTreeIter *titer) {
5757 #ifdef GUI_GTK
5758 return gtk_tree_model_iter_n_children(tmod, titer);
5759 #endif
5760 return 0;
5761 }
5762
5763
lives_tree_model_iter_next(LiVESTreeModel * tmod,LiVESTreeIter * titer)5764 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_model_iter_next(LiVESTreeModel *tmod, LiVESTreeIter *titer) {
5765 #ifdef GUI_GTK
5766 return gtk_tree_model_iter_next(tmod, titer);
5767 #endif
5768 return FALSE;
5769 }
5770
5771
lives_tree_path_free(LiVESTreePath * tpath)5772 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_path_free(LiVESTreePath *tpath) {
5773 #ifdef GUI_GTK
5774 gtk_tree_path_free(tpath);
5775 return TRUE;
5776 #endif
5777 return FALSE;
5778 }
5779
5780
lives_tree_path_new_from_string(const char * path)5781 WIDGET_HELPER_GLOBAL_INLINE LiVESTreePath *lives_tree_path_new_from_string(const char *path) {
5782 LiVESTreePath *tpath = NULL;
5783 #ifdef GUI_GTK
5784 tpath = gtk_tree_path_new_from_string(path);
5785 #endif
5786 return tpath;
5787 }
5788
5789
lives_tree_path_get_depth(LiVESTreePath * tpath)5790 WIDGET_HELPER_GLOBAL_INLINE int lives_tree_path_get_depth(LiVESTreePath *tpath) {
5791 int depth = -1;
5792 #ifdef GUI_GTK
5793 depth = gtk_tree_path_get_depth(tpath);
5794 #endif
5795 return depth;
5796 }
5797
5798
lives_tree_path_get_indices(LiVESTreePath * tpath)5799 WIDGET_HELPER_GLOBAL_INLINE int *lives_tree_path_get_indices(LiVESTreePath *tpath) {
5800 int *indices = NULL;
5801 #ifdef GUI_GTK
5802 indices = gtk_tree_path_get_indices(tpath);
5803 #endif
5804 return indices;
5805 }
5806
5807
lives_tree_store_new(int ncols,...)5808 WIDGET_HELPER_GLOBAL_INLINE LiVESTreeStore *lives_tree_store_new(int ncols, ...) {
5809 LiVESTreeStore *tstore = NULL;
5810 va_list argList;
5811 va_start(argList, ncols);
5812 #ifdef GUI_GTK
5813 if (ncols > 0) {
5814 GType types[ncols];
5815 register int i;
5816 for (i = 0; i < ncols; i++) {
5817 types[i] = va_arg(argList, long unsigned int);
5818 }
5819 tstore = gtk_tree_store_newv(ncols, types);
5820 }
5821 // supposedly speeds things up a bit...
5822 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(tstore),
5823 GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
5824 GTK_SORT_ASCENDING);
5825 #endif
5826 va_end(argList);
5827 return tstore;
5828 }
5829
5830
lives_tree_store_append(LiVESTreeStore * tstore,LiVESTreeIter * titer,LiVESTreeIter * parent)5831 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_store_append(LiVESTreeStore *tstore, LiVESTreeIter *titer,
5832 LiVESTreeIter *parent) {
5833 #ifdef GUI_GTK
5834 gtk_tree_store_append(tstore, titer, parent);
5835 return TRUE;
5836 #endif
5837 return FALSE;
5838 }
5839
5840
lives_tree_store_prepend(LiVESTreeStore * tstore,LiVESTreeIter * titer,LiVESTreeIter * parent)5841 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_store_prepend(LiVESTreeStore *tstore, LiVESTreeIter *titer,
5842 LiVESTreeIter *parent) {
5843 #ifdef GUI_GTK
5844 gtk_tree_store_prepend(tstore, titer, parent);
5845 return TRUE;
5846 #endif
5847 return FALSE;
5848 }
5849
5850
lives_tree_store_set(LiVESTreeStore * tstore,LiVESTreeIter * titer,...)5851 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_store_set(LiVESTreeStore *tstore, LiVESTreeIter *titer, ...) {
5852 boolean res = FALSE;
5853 va_list argList;
5854 va_start(argList, titer);
5855 #ifdef GUI_GTK
5856 gtk_tree_store_set_valist(tstore, titer, argList);
5857 res = TRUE;
5858 #endif
5859 va_end(argList);
5860 return res;
5861 }
5862
5863
lives_tree_view_new_with_model(LiVESTreeModel * tmod)5864 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_tree_view_new_with_model(LiVESTreeModel *tmod) {
5865 LiVESWidget *tview = NULL;
5866 #ifdef GUI_GTK
5867 tview = gtk_tree_view_new_with_model(tmod);
5868 #endif
5869 return tview;
5870 }
5871
5872
lives_tree_view_new(void)5873 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_tree_view_new(void) {
5874 LiVESWidget *tview = NULL;
5875 #ifdef GUI_GTK
5876 tview = gtk_tree_view_new();
5877 #endif
5878 return tview;
5879 }
5880
5881
lives_tree_view_set_model(LiVESTreeView * tview,LiVESTreeModel * tmod)5882 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_view_set_model(LiVESTreeView *tview, LiVESTreeModel *tmod) {
5883 #ifdef GUI_GTK
5884 gtk_tree_view_set_model(tview, tmod);
5885 return TRUE;
5886 #endif
5887 return FALSE;
5888 }
5889
5890
lives_tree_view_get_model(LiVESTreeView * tview)5891 WIDGET_HELPER_GLOBAL_INLINE LiVESTreeModel *lives_tree_view_get_model(LiVESTreeView *tview) {
5892 LiVESTreeModel *tmod = NULL;
5893 #ifdef GUI_GTK
5894 tmod = gtk_tree_view_get_model(tview);
5895 #endif
5896 return tmod;
5897 }
5898
5899
lives_tree_view_get_selection(LiVESTreeView * tview)5900 WIDGET_HELPER_GLOBAL_INLINE LiVESTreeSelection *lives_tree_view_get_selection(LiVESTreeView *tview) {
5901 LiVESTreeSelection *tsel = NULL;
5902 #ifdef GUI_GTK
5903 tsel = gtk_tree_view_get_selection(tview);
5904 #endif
5905 return tsel;
5906 }
5907
5908
lives_tree_view_append_column(LiVESTreeView * tview,LiVESTreeViewColumn * tvcol)5909 WIDGET_HELPER_GLOBAL_INLINE int lives_tree_view_append_column(LiVESTreeView *tview, LiVESTreeViewColumn *tvcol) {
5910 #ifdef GUI_GTK
5911 gtk_tree_view_append_column(tview, tvcol);
5912 return TRUE;
5913 #endif
5914 return FALSE;
5915 }
5916
5917
lives_tree_view_set_headers_visible(LiVESTreeView * tview,boolean vis)5918 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_view_set_headers_visible(LiVESTreeView *tview, boolean vis) {
5919 #ifdef GUI_GTK
5920 gtk_tree_view_set_headers_visible(tview, vis);
5921 return TRUE;
5922 #endif
5923 return FALSE;
5924 }
5925
5926
lives_tree_view_get_hadjustment(LiVESTreeView * tview)5927 WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment *lives_tree_view_get_hadjustment(LiVESTreeView *tview) {
5928 LiVESAdjustment *adj = NULL;
5929 #ifdef GUI_GTK
5930 #if GTK_CHECK_VERSION(3, 0, 0)
5931 adj = gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(tview));
5932 #else
5933 adj = gtk_tree_view_get_hadjustment(tview);
5934 #endif
5935 #endif
5936 return adj;
5937 }
5938
5939
lives_tree_view_column_new_with_attributes(const char * title,LiVESCellRenderer * crend,...)5940 WIDGET_HELPER_GLOBAL_INLINE LiVESTreeViewColumn *lives_tree_view_column_new_with_attributes(const char *title,
5941 LiVESCellRenderer *crend,
5942 ...) {
5943 LiVESTreeViewColumn *tvcol = NULL;
5944 va_list args;
5945 va_start(args, crend);
5946 int column;
5947 char *attribute;
5948 boolean expand = FALSE;
5949 #ifdef GUI_GTK
5950
5951 tvcol = gtk_tree_view_column_new();
5952 gtk_tree_view_column_set_title(tvcol, title);
5953 gtk_tree_view_column_pack_start(tvcol, crend, expand);
5954
5955 attribute = va_arg(args, char *);
5956
5957 while (attribute) {
5958 column = va_arg(args, int);
5959 gtk_tree_view_column_add_attribute(tvcol, crend, attribute, column);
5960 attribute = va_arg(args, char *);
5961 }
5962
5963 #endif
5964 va_end(args);
5965 return tvcol;
5966 }
5967
5968
lives_tree_view_column_set_sizing(LiVESTreeViewColumn * tvcol,LiVESTreeViewColumnSizing type)5969 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_view_column_set_sizing(LiVESTreeViewColumn *tvcol,
5970 LiVESTreeViewColumnSizing type) {
5971 #ifdef GUI_GTK
5972 gtk_tree_view_column_set_sizing(tvcol, type);
5973 return TRUE;
5974 #endif
5975 return FALSE;
5976 }
5977
5978
lives_tree_view_column_set_fixed_width(LiVESTreeViewColumn * tvcol,int fwidth)5979 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_view_column_set_fixed_width(LiVESTreeViewColumn *tvcol, int fwidth) {
5980 #ifdef GUI_GTK
5981 gtk_tree_view_column_set_fixed_width(tvcol, fwidth);
5982 return TRUE;
5983 #endif
5984 return FALSE;
5985 }
5986
5987
lives_tree_selection_get_selected(LiVESTreeSelection * tsel,LiVESTreeModel ** tmod,LiVESTreeIter * titer)5988 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_selection_get_selected(LiVESTreeSelection *tsel, LiVESTreeModel **tmod,
5989 LiVESTreeIter *titer) {
5990 #ifdef GUI_GTK
5991 return gtk_tree_selection_get_selected(tsel, tmod, titer);
5992 #endif
5993 return FALSE;
5994 }
5995
5996
lives_tree_selection_set_mode(LiVESTreeSelection * tsel,LiVESSelectionMode tselmod)5997 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_selection_set_mode(LiVESTreeSelection *tsel, LiVESSelectionMode tselmod) {
5998 #ifdef GUI_GTK
5999 gtk_tree_selection_set_mode(tsel, tselmod);
6000 return TRUE;
6001 #endif
6002 return FALSE;
6003 }
6004
6005
lives_tree_selection_select_iter(LiVESTreeSelection * tsel,LiVESTreeIter * titer)6006 WIDGET_HELPER_GLOBAL_INLINE boolean lives_tree_selection_select_iter(LiVESTreeSelection *tsel, LiVESTreeIter *titer) {
6007 #ifdef GUI_GTK
6008 gtk_tree_selection_select_iter(tsel, titer);
6009 return TRUE;
6010 #endif
6011 return FALSE;
6012 }
6013
6014
lives_list_store_new(int ncols,...)6015 WIDGET_HELPER_GLOBAL_INLINE LiVESListStore *lives_list_store_new(int ncols, ...) {
6016 LiVESListStore *lstore = NULL;
6017 va_list argList;
6018 va_start(argList, ncols);
6019 #ifdef GUI_GTK
6020 if (ncols > 0) {
6021 GType types[ncols];
6022 register int i;
6023 for (i = 0; i < ncols; i++) {
6024 types[i] = va_arg(argList, long unsigned int);
6025 }
6026 lstore = gtk_list_store_newv(ncols, types);
6027 }
6028 #endif
6029 va_end(argList);
6030 return lstore;
6031 }
6032
6033
lives_list_store_set(LiVESListStore * lstore,LiVESTreeIter * titer,...)6034 WIDGET_HELPER_GLOBAL_INLINE boolean lives_list_store_set(LiVESListStore *lstore, LiVESTreeIter *titer, ...) {
6035 boolean res = FALSE;
6036 va_list argList;
6037 va_start(argList, titer);
6038 #ifdef GUI_GTK
6039 gtk_list_store_set_valist(lstore, titer, argList);
6040 res = TRUE;
6041 #endif
6042 va_end(argList);
6043 return res;
6044 }
6045
6046
lives_list_store_insert(LiVESListStore * lstore,LiVESTreeIter * titer,int position)6047 WIDGET_HELPER_GLOBAL_INLINE boolean lives_list_store_insert(LiVESListStore *lstore, LiVESTreeIter *titer, int position) {
6048 #ifdef GUI_GTK
6049 gtk_list_store_insert(lstore, titer, position);
6050 return TRUE;
6051 #endif
6052 return FALSE;
6053 }
6054
6055
lives_label_get_text(LiVESLabel * label)6056 WIDGET_HELPER_GLOBAL_INLINE const char *lives_label_get_text(LiVESLabel *label) {
6057 #ifdef GUI_GTK
6058 return gtk_label_get_text(label);
6059 #endif
6060 return NULL;
6061 }
6062
6063
lives_label_set_text(LiVESLabel * label,const char * text)6064 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_text(LiVESLabel *label, const char *text) {
6065 if (!text) return lives_label_set_text(label, "");
6066 if (widget_opts.use_markup) return lives_label_set_markup(label, text);
6067 #ifdef GUI_GTK
6068 if (widget_opts.mnemonic_label) gtk_label_set_text_with_mnemonic(label, text);
6069 else gtk_label_set_text(label, text);
6070 return TRUE;
6071 #endif
6072 return FALSE;
6073 }
6074
6075
lives_label_set_markup(LiVESLabel * label,const char * markup)6076 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_markup(LiVESLabel *label, const char *markup) {
6077 #ifdef GUI_GTK
6078 if (!widget_opts.mnemonic_label) gtk_label_set_markup(label, markup);
6079 else gtk_label_set_markup_with_mnemonic(label, markup);
6080 return TRUE;
6081 #endif
6082 return FALSE;
6083 }
6084
6085
lives_label_set_mnemonic_widget(LiVESLabel * label,LiVESWidget * widget)6086 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_mnemonic_widget(LiVESLabel *label, LiVESWidget *widget) {
6087 #ifdef GUI_GTK
6088 gtk_label_set_mnemonic_widget(label, widget);
6089 return TRUE;
6090 #endif
6091 return FALSE;
6092 }
6093
6094
lives_label_get_mnemonic_widget(LiVESLabel * label)6095 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_label_get_mnemonic_widget(LiVESLabel *label) {
6096 LiVESWidget *widget = NULL;
6097 #ifdef GUI_GTK
6098 widget = gtk_label_get_mnemonic_widget(label);
6099 #endif
6100 return widget;
6101 }
6102
6103
lives_label_set_selectable(LiVESLabel * label,boolean setting)6104 WIDGET_HELPER_GLOBAL_INLINE boolean lives_label_set_selectable(LiVESLabel *label, boolean setting) {
6105 #ifdef GUI_GTK
6106 gtk_label_set_selectable(label, setting);
6107 return TRUE;
6108 #endif
6109 return FALSE;
6110 }
6111
6112
lives_editable_get_editable(LiVESEditable * editable)6113 WIDGET_HELPER_GLOBAL_INLINE boolean lives_editable_get_editable(LiVESEditable *editable) {
6114 #ifdef GUI_GTK
6115 return gtk_editable_get_editable(editable);
6116 #endif
6117 return FALSE;
6118 }
6119
6120
lives_editable_set_editable(LiVESEditable * editable,boolean is_editable)6121 WIDGET_HELPER_GLOBAL_INLINE boolean lives_editable_set_editable(LiVESEditable *editable, boolean is_editable) {
6122 lives_widget_set_can_focus(LIVES_WIDGET(editable), is_editable);
6123 #ifdef GUI_GTK
6124 gtk_editable_set_editable(editable, is_editable);
6125 return TRUE;
6126 #endif
6127 return FALSE;
6128 }
6129
6130
lives_editable_select_region(LiVESEditable * editable,int start_pos,int end_pos)6131 WIDGET_HELPER_GLOBAL_INLINE boolean lives_editable_select_region(LiVESEditable *editable, int start_pos, int end_pos) {
6132 #ifdef GUI_GTK
6133 gtk_editable_select_region(editable, start_pos, end_pos);
6134 return TRUE;
6135 #endif
6136 return FALSE;
6137 }
6138
6139
lives_entry_new(void)6140 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_entry_new(void) {
6141 LiVESWidget *entry = NULL;
6142 #ifdef GUI_GTK
6143 entry = gtk_entry_new();
6144 #endif
6145 return entry;
6146 }
6147
6148
lives_entry_set_max_length(LiVESEntry * entry,int len)6149 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_max_length(LiVESEntry *entry, int len) {
6150 // entry length (not display length)
6151 #ifdef GUI_GTK
6152 gtk_entry_set_max_length(entry, len);
6153 return TRUE;
6154 #endif
6155 return FALSE;
6156 }
6157
6158
lives_entry_set_activates_default(LiVESEntry * entry,boolean act)6159 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_activates_default(LiVESEntry *entry, boolean act) {
6160 #ifdef GUI_GTK
6161 gtk_entry_set_activates_default(entry, act);
6162 return TRUE;
6163 #endif
6164 return FALSE;
6165 }
6166
6167
lives_entry_get_activates_default(LiVESEntry * entry)6168 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_get_activates_default(LiVESEntry *entry) {
6169 #ifdef GUI_GTK
6170 return gtk_entry_get_activates_default(entry);
6171 #endif
6172 return FALSE;
6173 }
6174
6175
lives_entry_set_visibility(LiVESEntry * entry,boolean vis)6176 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_visibility(LiVESEntry *entry, boolean vis) {
6177 #ifdef GUI_GTK
6178 gtk_entry_set_visibility(entry, vis);
6179 return TRUE;
6180 #endif
6181 return FALSE;
6182 }
6183
6184
lives_entry_set_has_frame(LiVESEntry * entry,boolean has)6185 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_has_frame(LiVESEntry *entry, boolean has) {
6186 #ifdef GUI_GTK
6187 gtk_entry_set_has_frame(entry, has);
6188 return TRUE;
6189 #endif
6190 return FALSE;
6191 }
6192
6193
lives_entry_set_alignment(LiVESEntry * entry,float align)6194 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_alignment(LiVESEntry *entry, float align) {
6195 #ifdef GUI_GTK
6196 gtk_entry_set_alignment(entry, align);
6197 return TRUE;
6198 #endif
6199 return FALSE;
6200 }
6201
6202
lives_entry_get_text(LiVESEntry * entry)6203 WIDGET_HELPER_GLOBAL_INLINE const char *lives_entry_get_text(LiVESEntry *entry) {
6204 #ifdef GUI_GTK
6205 return gtk_entry_get_text(entry);
6206 #endif
6207 return NULL;
6208 }
6209
6210
lives_entry_set_text(LiVESEntry * entry,const char * text)6211 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_text(LiVESEntry *entry, const char *text) {
6212 #ifdef GUI_GTK
6213 if (widget_opts.justify == LIVES_JUSTIFY_START) lives_entry_set_alignment(entry, 0.);
6214 else if (widget_opts.justify == LIVES_JUSTIFY_CENTER) lives_entry_set_alignment(entry, 0.5);
6215 if (widget_opts.justify == LIVES_JUSTIFY_END) lives_entry_set_alignment(entry, 1.);
6216 gtk_entry_set_text(entry, text);
6217 return TRUE;
6218 #endif
6219 return FALSE;
6220 }
6221
6222
lives_entry_set_width_chars(LiVESEntry * entry,int nchars)6223 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_width_chars(LiVESEntry *entry, int nchars) {
6224 // display length
6225 #ifdef GUI_GTK
6226 #if GTK_CHECK_VERSION(3, 12, 0)
6227 gtk_entry_set_max_width_chars(entry, nchars);
6228 #endif
6229 gtk_entry_set_width_chars(entry, nchars);
6230 return TRUE;
6231 #endif
6232 return FALSE;
6233 }
6234
6235
lives_scrolled_window_new(LiVESAdjustment * hadj,LiVESAdjustment * vadj)6236 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_scrolled_window_new(LiVESAdjustment *hadj, LiVESAdjustment *vadj) {
6237 LiVESWidget *swindow = NULL;
6238 #ifdef GUI_GTK
6239 swindow = gtk_scrolled_window_new(hadj, vadj);
6240 #endif
6241 return swindow;
6242 }
6243
6244
lives_scrolled_window_get_hadjustment(LiVESScrolledWindow * swindow)6245 WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment *lives_scrolled_window_get_hadjustment(LiVESScrolledWindow *swindow) {
6246 LiVESAdjustment *adj = NULL;
6247 #ifdef GUI_GTK
6248 adj = gtk_scrolled_window_get_hadjustment(swindow);
6249 #endif
6250 return adj;
6251 }
6252
6253
lives_scrolled_window_get_vadjustment(LiVESScrolledWindow * swindow)6254 WIDGET_HELPER_GLOBAL_INLINE LiVESAdjustment *lives_scrolled_window_get_vadjustment(LiVESScrolledWindow *swindow) {
6255 LiVESAdjustment *adj = NULL;
6256 #ifdef GUI_GTK
6257 adj = gtk_scrolled_window_get_vadjustment(swindow);
6258 #endif
6259 return adj;
6260 }
6261
6262
lives_scrolled_window_set_policy(LiVESScrolledWindow * scrolledwindow,LiVESPolicyType hpolicy,LiVESPolicyType vpolicy)6263 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scrolled_window_set_policy(LiVESScrolledWindow *scrolledwindow,
6264 LiVESPolicyType hpolicy,
6265 LiVESPolicyType vpolicy) {
6266 #ifdef GUI_GTK
6267 gtk_scrolled_window_set_policy(scrolledwindow, hpolicy, vpolicy);
6268 return TRUE;
6269 #endif
6270 return FALSE;
6271 }
6272
6273
lives_scrolled_window_add_with_viewport(LiVESScrolledWindow * scrolledwindow,LiVESWidget * child)6274 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scrolled_window_add_with_viewport(LiVESScrolledWindow *scrolledwindow,
6275 LiVESWidget *child) {
6276 #ifdef GUI_GTK
6277 #if !GTK_CHECK_VERSION(3, 8, 0)
6278 gtk_scrolled_window_add_with_viewport(scrolledwindow, child);
6279 #else
6280 lives_container_add(LIVES_CONTAINER(scrolledwindow), child);
6281 #endif
6282 return TRUE;
6283 #endif
6284 return FALSE;
6285 }
6286
6287
lives_scrolled_window_set_min_content_height(LiVESScrolledWindow * scrolledwindow,int height)6288 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scrolled_window_set_min_content_height(LiVESScrolledWindow *scrolledwindow,
6289 int height) {
6290 #ifdef GUI_GTK
6291 #if GTK_CHECK_VERSION(3, 0, 0)
6292 gtk_scrolled_window_set_min_content_height(scrolledwindow, height);
6293 return TRUE;
6294 #endif
6295 #endif
6296 return FALSE;
6297 }
6298
6299
lives_scrolled_window_set_min_content_width(LiVESScrolledWindow * scrolledwindow,int width)6300 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scrolled_window_set_min_content_width(LiVESScrolledWindow *scrolledwindow,
6301 int width) {
6302 #ifdef GUI_GTK
6303 #if GTK_CHECK_VERSION(3, 0, 0)
6304 gtk_scrolled_window_set_min_content_width(scrolledwindow, width);
6305 return TRUE;
6306 #endif
6307 #endif
6308 return FALSE;
6309 }
6310
6311
lives_xwindow_raise(LiVESXWindow * xwin)6312 WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_raise(LiVESXWindow *xwin) {
6313 #ifdef GUI_GTK
6314 gdk_window_raise(xwin);
6315 return TRUE;
6316 #endif
6317 return FALSE;
6318 }
6319
6320
lives_xwindow_set_cursor(LiVESXWindow * xwin,LiVESXCursor * cursor)6321 WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_set_cursor(LiVESXWindow *xwin, LiVESXCursor *cursor) {
6322 #ifdef GUI_GTK
6323 if (GDK_IS_WINDOW(xwin)) {
6324 if (!cursor || gdk_window_get_display(xwin) == gdk_cursor_get_display(cursor)) {
6325 gdk_window_set_cursor(xwin, cursor);
6326 return TRUE;
6327 }
6328 }
6329 #endif
6330 return FALSE;
6331 }
6332
6333
lives_dialog_set_has_separator(LiVESDialog * dialog,boolean has)6334 WIDGET_HELPER_GLOBAL_INLINE boolean lives_dialog_set_has_separator(LiVESDialog *dialog, boolean has) {
6335 // return TRUE if implemented
6336
6337 #ifdef GUI_GTK
6338 #if !GTK_CHECK_VERSION(3, 0, 0)
6339 gtk_dialog_set_has_separator(dialog, has);
6340 return TRUE;
6341 #endif
6342 #endif
6343 return FALSE;
6344 }
6345
6346
lives_widget_set_hexpand(LiVESWidget * widget,boolean state)6347 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_hexpand(LiVESWidget *widget, boolean state) {
6348 // return TRUE if implemented
6349 #ifdef GUI_GTK
6350 #if GTK_CHECK_VERSION(3, 0, 0)
6351 gtk_widget_set_hexpand(widget, state);
6352 return TRUE;
6353 #endif
6354 #endif
6355 return FALSE;
6356 }
6357
6358
lives_widget_set_vexpand(LiVESWidget * widget,boolean state)6359 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_vexpand(LiVESWidget *widget, boolean state) {
6360 // return TRUE if implemented
6361 #ifdef GUI_GTK
6362 #if GTK_CHECK_VERSION(3, 0, 0)
6363 gtk_widget_set_vexpand(widget, state);
6364 return TRUE;
6365 #endif
6366 #endif
6367 return FALSE;
6368 }
6369
6370
lives_menu_new(void)6371 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_menu_new(void) {
6372 LiVESWidget *menu = NULL;
6373 #ifdef GUI_GTK
6374 menu = gtk_menu_new();
6375 #endif
6376 return menu;
6377 }
6378
6379
lives_menu_bar_new(void)6380 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_menu_bar_new(void) {
6381 LiVESWidget *menubar = NULL;
6382 #ifdef GUI_GTK
6383 menubar = gtk_menu_bar_new();
6384 #endif
6385 return menubar;
6386 }
6387
6388
lives_menu_item_new(void)6389 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_menu_item_new(void) {
6390 LiVESWidget *menuitem = NULL;
6391 #ifdef GUI_GTK
6392 menuitem = gtk_menu_item_new();
6393 #endif
6394 return menuitem;
6395 }
6396
6397
lives_menu_item_new_with_label(const char * label)6398 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_menu_item_new_with_label(const char *label) {
6399 LiVESWidget *menuitem = NULL;
6400 #ifdef GUI_GTK
6401 if (!widget_opts.mnemonic_label) menuitem = gtk_menu_item_new_with_label(label);
6402 else menuitem = gtk_menu_item_new_with_mnemonic(label);
6403 #endif
6404 return menuitem;
6405 }
6406
6407
lives_menu_item_set_accel_path(LiVESMenuItem * menuitem,const char * path)6408 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_item_set_accel_path(LiVESMenuItem *menuitem, const char *path) {
6409 #ifdef GUI_GTK
6410 gtk_menu_item_set_accel_path(menuitem, path);
6411 return TRUE;
6412 #endif
6413 return FALSE;
6414 }
6415
6416
lives_menu_item_get_submenu(LiVESMenuItem * menuitem)6417 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_menu_item_get_submenu(LiVESMenuItem *menuitem) {
6418 #ifdef GUI_GTK
6419 return gtk_menu_item_get_submenu(menuitem);
6420 #endif
6421 return NULL;
6422 }
6423
6424
lives_image_menu_item_new_with_label(const char * label)6425 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_image_menu_item_new_with_label(const char *label) {
6426 LiVESWidget *menuitem = NULL;
6427 #ifdef GUI_GTK
6428 #if GTK_CHECK_VERSION(3, 10, 0)
6429 if (!widget_opts.mnemonic_label) menuitem = gtk_menu_item_new_with_label(label);
6430 else menuitem = gtk_menu_item_new_with_mnemonic(label);
6431 #else
6432 if (!widget_opts.mnemonic_label) menuitem = gtk_image_menu_item_new_with_label(label);
6433 else menuitem = gtk_image_menu_item_new_with_mnemonic(label);
6434 #endif
6435 #endif
6436 return menuitem;
6437 }
6438
6439
lives_radio_menu_item_new_with_label(LiVESSList * group,const char * label)6440 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_radio_menu_item_new_with_label(LiVESSList *group, const char *label) {
6441 LiVESWidget *menuitem = NULL;
6442 #ifdef GUI_GTK
6443 if (!widget_opts.mnemonic_label) menuitem = gtk_radio_menu_item_new_with_label(group, label);
6444 else menuitem = gtk_radio_menu_item_new_with_mnemonic(group, label);
6445 #endif
6446 return menuitem;
6447 }
6448
6449
lives_radio_menu_item_get_group(LiVESRadioMenuItem * rmenuitem)6450 WIDGET_HELPER_GLOBAL_INLINE LiVESSList *lives_radio_menu_item_get_group(LiVESRadioMenuItem *rmenuitem) {
6451 #ifdef GUI_GTK
6452 return gtk_radio_menu_item_get_group(rmenuitem);
6453 #endif
6454 return NULL;
6455 }
6456
6457
lives_check_menu_item_new_with_label(const char * label)6458 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_check_menu_item_new_with_label(const char *label) {
6459 LiVESWidget *menuitem = NULL;
6460 #ifdef GUI_GTK
6461 if (!widget_opts.mnemonic_label) menuitem = gtk_check_menu_item_new_with_label(label);
6462 else menuitem = gtk_check_menu_item_new_with_mnemonic(label); // TODO - deprecated
6463 #endif
6464 return menuitem;
6465 }
6466
6467
lives_check_menu_item_set_draw_as_radio(LiVESCheckMenuItem * item,boolean setting)6468 WIDGET_HELPER_GLOBAL_INLINE boolean lives_check_menu_item_set_draw_as_radio(LiVESCheckMenuItem *item, boolean setting) {
6469 #ifdef GUI_GTK
6470 gtk_check_menu_item_set_draw_as_radio(item, setting);
6471 return TRUE;
6472 #endif
6473 return FALSE;
6474 }
6475
6476
lives_image_menu_item_new_from_stock(const char * stock_id,LiVESAccelGroup * accel_group)6477 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_image_menu_item_new_from_stock(const char *stock_id,
6478 LiVESAccelGroup *accel_group) {
6479 LiVESWidget *menuitem = NULL;
6480 #ifdef GUI_GTK
6481 #if GTK_CHECK_VERSION(3, 10, 0)
6482 char *xstock_id = lives_strdup(stock_id); // need to back this up as we will use translation functions
6483 menuitem = gtk_menu_item_new_with_mnemonic(xstock_id);
6484
6485 if (!strcmp(xstock_id, LIVES_STOCK_LABEL_SAVE)) {
6486 lives_menu_item_set_accel_path(LIVES_MENU_ITEM(menuitem), LIVES_ACCEL_PATH_SAVE);
6487 }
6488
6489 if (!strcmp(xstock_id, LIVES_STOCK_LABEL_QUIT)) {
6490 lives_menu_item_set_accel_path(LIVES_MENU_ITEM(menuitem), LIVES_ACCEL_PATH_QUIT);
6491 }
6492 lives_free(xstock_id);
6493 #else
6494 menuitem = gtk_image_menu_item_new_from_stock(stock_id, accel_group);
6495 #endif
6496 #endif
6497 return menuitem;
6498 }
6499
6500
lives_menu_tool_button_new(LiVESWidget * icon,const char * label)6501 WIDGET_HELPER_GLOBAL_INLINE LiVESToolItem *lives_menu_tool_button_new(LiVESWidget *icon, const char *label) {
6502 LiVESToolItem *toolitem = NULL;
6503 #ifdef GUI_GTK
6504 toolitem = gtk_menu_tool_button_new(icon, label);
6505 #endif
6506 return toolitem;
6507 }
6508
6509
lives_menu_tool_button_set_menu(LiVESMenuToolButton * toolbutton,LiVESWidget * menu)6510 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_tool_button_set_menu(LiVESMenuToolButton *toolbutton, LiVESWidget *menu) {
6511 #ifdef GUI_GTK
6512 gtk_menu_tool_button_set_menu(toolbutton, menu);
6513 return TRUE;
6514 #endif
6515 return FALSE;
6516 }
6517
6518
lives_menu_item_set_submenu(LiVESMenuItem * menuitem,LiVESWidget * menu)6519 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_item_set_submenu(LiVESMenuItem *menuitem, LiVESWidget *menu) {
6520 #ifdef GUI_GTK
6521 gtk_menu_item_set_submenu(menuitem, menu);
6522 return TRUE;
6523 #endif
6524 return FALSE;
6525 }
6526
6527
lives_menu_item_activate(LiVESMenuItem * menuitem)6528 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_item_activate(LiVESMenuItem *menuitem) {
6529 #ifdef GUI_GTK
6530 gtk_menu_item_activate(menuitem);
6531 return TRUE;
6532 #endif
6533 return FALSE;
6534 }
6535
6536
lives_check_menu_item_set_active(LiVESCheckMenuItem * item,boolean state)6537 WIDGET_HELPER_GLOBAL_INLINE boolean lives_check_menu_item_set_active(LiVESCheckMenuItem *item, boolean state) {
6538 #ifdef GUI_GTK
6539 gtk_check_menu_item_set_active(item, state);
6540 return TRUE;
6541 #endif
6542 return FALSE;
6543 }
6544
6545
lives_check_menu_item_get_active(LiVESCheckMenuItem * item)6546 WIDGET_HELPER_GLOBAL_INLINE boolean lives_check_menu_item_get_active(LiVESCheckMenuItem *item) {
6547 #ifdef GUI_GTK
6548 return gtk_check_menu_item_get_active(item);
6549 #endif
6550 return FALSE;
6551 }
6552
6553
6554 #if !GTK_CHECK_VERSION(3, 10, 0)
6555
lives_image_menu_item_set_image(LiVESImageMenuItem * item,LiVESWidget * image)6556 WIDGET_HELPER_GLOBAL_INLINE boolean lives_image_menu_item_set_image(LiVESImageMenuItem *item, LiVESWidget *image) {
6557 #ifdef GUI_GTK
6558 gtk_image_menu_item_set_image(item, image);
6559 return TRUE;
6560 #endif
6561 return FALSE;
6562 }
6563
6564 #endif
6565
lives_menu_set_title(LiVESMenu * menu,const char * title)6566 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_set_title(LiVESMenu *menu, const char *title) {
6567 #ifdef GUI_GTK
6568 #if !GTK_CHECK_VERSION(3, 10, 0)
6569 char *ntitle = lives_strdup_printf("%s%s", widget_opts.title_prefix, title);
6570 gtk_menu_set_title(menu, ntitle);
6571 lives_free(ntitle);
6572 return TRUE;
6573 #endif
6574 #endif
6575 return FALSE;
6576 }
6577
6578
lives_menu_popup(LiVESMenu * menu,LiVESXEventButton * event)6579 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_popup(LiVESMenu *menu, LiVESXEventButton *event) {
6580 #ifdef GUI_GTK
6581 #if GTK_CHECK_VERSION(3, 22, 0)
6582 gtk_menu_popup_at_pointer(menu, NULL);
6583 #else
6584 gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time);
6585 #endif
6586 return TRUE;
6587 #endif
6588 return FALSE;
6589 }
6590
6591
lives_menu_reorder_child(LiVESMenu * menu,LiVESWidget * child,int pos)6592 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_reorder_child(LiVESMenu *menu, LiVESWidget *child, int pos) {
6593 #ifdef GUI_GTK
6594 gtk_menu_reorder_child(menu, child, pos);
6595 return TRUE;
6596 #endif
6597 return FALSE;
6598 }
6599
6600
lives_menu_detach(LiVESMenu * menu)6601 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_detach(LiVESMenu *menu) {
6602 // NB also calls detacher callback
6603 #ifdef GUI_GTK
6604 gtk_menu_detach(menu);
6605 return TRUE;
6606 #endif
6607 return FALSE;
6608 }
6609
6610
lives_menu_shell_append(LiVESMenuShell * menushell,LiVESWidget * child)6611 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_shell_append(LiVESMenuShell *menushell, LiVESWidget *child) {
6612 #ifdef GUI_GTK
6613 gtk_menu_shell_append(menushell, child);
6614 return TRUE;
6615 #endif
6616 return FALSE;
6617 }
6618
6619
lives_menu_shell_insert(LiVESMenuShell * menushell,LiVESWidget * child,int pos)6620 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_shell_insert(LiVESMenuShell *menushell, LiVESWidget *child, int pos) {
6621 #ifdef GUI_GTK
6622 gtk_menu_shell_insert(menushell, child, pos);
6623 return TRUE;
6624 #endif
6625 return FALSE;
6626 }
6627
6628
lives_menu_shell_prepend(LiVESMenuShell * menushell,LiVESWidget * child)6629 WIDGET_HELPER_GLOBAL_INLINE boolean lives_menu_shell_prepend(LiVESMenuShell *menushell, LiVESWidget *child) {
6630 #ifdef GUI_GTK
6631 gtk_menu_shell_prepend(menushell, child);
6632 return TRUE;
6633 #endif
6634 return FALSE;
6635 }
6636
6637
lives_image_menu_item_set_always_show_image(LiVESImageMenuItem * item,boolean show)6638 WIDGET_HELPER_GLOBAL_INLINE boolean lives_image_menu_item_set_always_show_image(LiVESImageMenuItem *item, boolean show) {
6639 // return TRUE if implemented
6640 #ifdef GUI_GTK
6641 #if GTK_CHECK_VERSION(2, 16, 0)
6642 #if !GTK_CHECK_VERSION(3, 10, 0)
6643 gtk_image_menu_item_set_always_show_image(item, show);
6644 #endif
6645 return TRUE;
6646 #endif
6647 #endif
6648 return FALSE;
6649 }
6650
6651
lives_scale_set_draw_value(LiVESScale * scale,boolean draw_value)6652 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scale_set_draw_value(LiVESScale *scale, boolean draw_value) {
6653 #ifdef GUI_GTK
6654 return TRUE;
6655 #endif
6656 return FALSE;
6657 }
6658
6659
lives_scale_set_value_pos(LiVESScale * scale,LiVESPositionType ptype)6660 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scale_set_value_pos(LiVESScale *scale, LiVESPositionType ptype) {
6661 #ifdef GUI_GTK
6662 gtk_scale_set_value_pos(scale, ptype);
6663 return TRUE;
6664 #endif
6665 return FALSE;
6666 }
6667
6668
lives_scale_set_digits(LiVESScale * scale,int digits)6669 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scale_set_digits(LiVESScale *scale, int digits) {
6670 #ifdef GUI_GTK
6671 gtk_scale_set_digits(scale, digits);
6672 return TRUE;
6673 #endif
6674 return FALSE;
6675 }
6676
6677
lives_scale_button_set_orientation(LiVESScaleButton * scale,LiVESOrientation orientation)6678 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scale_button_set_orientation(LiVESScaleButton *scale, LiVESOrientation orientation) {
6679 // return TRUE if implemented
6680 #ifdef GUI_GTK
6681 #if GTK_CHECK_VERSION(3, 0, 0)
6682 gtk_orientable_set_orientation(GTK_ORIENTABLE(scale), orientation);
6683 return TRUE;
6684 #else
6685 #if GTK_CHECK_VERSION(2, 14, 0)
6686 gtk_scale_button_set_orientation(scale, orientation);
6687 return TRUE;
6688 #endif
6689 #endif
6690 #endif
6691 return FALSE;
6692 }
6693
6694
lives_scale_button_get_value(LiVESScaleButton * scale)6695 WIDGET_HELPER_GLOBAL_INLINE double lives_scale_button_get_value(LiVESScaleButton *scale) {
6696 double value = 0.;
6697 #ifdef GUI_GTK
6698 #if GTK_CHECK_VERSION(2, 14, 0)
6699 value = gtk_scale_button_get_value(scale);
6700 #else
6701 value = gtk_adjustment_get_value(gtk_range_get_adjustment(scale));
6702 #endif
6703 #endif
6704 return value;
6705 }
6706
6707
lives_scale_button_set_value(LiVESScaleButton * scale,double value)6708 WIDGET_HELPER_GLOBAL_INLINE boolean lives_scale_button_set_value(LiVESScaleButton *scale, double value) {
6709 #ifdef GUI_GTK
6710 #if GTK_CHECK_VERSION(2, 14, 0)
6711 gtk_scale_button_set_value(scale, value);
6712 #else
6713 gtk_adjustment_set_value(gtk_range_get_adjustment(scale), value);
6714 #endif
6715 return TRUE;
6716 #endif
6717 return FALSE;
6718 }
6719
6720
lives_file_chooser_get_filename(LiVESFileChooser * chooser)6721 WIDGET_HELPER_GLOBAL_INLINE char *lives_file_chooser_get_filename(LiVESFileChooser *chooser) {
6722 char *fname = NULL;
6723 #ifdef GUI_GTK
6724 fname = gtk_file_chooser_get_filename(chooser);
6725 #endif
6726 return fname;
6727 }
6728
6729
lives_file_chooser_get_filenames(LiVESFileChooser * chooser)6730 WIDGET_HELPER_GLOBAL_INLINE LiVESSList *lives_file_chooser_get_filenames(LiVESFileChooser *chooser) {
6731 LiVESSList *fnlist = NULL;
6732 #ifdef GUI_GTK
6733 fnlist = gtk_file_chooser_get_filenames(chooser);
6734 #endif
6735 return fnlist;
6736 }
6737
6738
6739 #if GTK_CHECK_VERSION(3,2,0)
lives_font_chooser_get_font(LiVESFontChooser * fc)6740 WIDGET_HELPER_GLOBAL_INLINE char *lives_font_chooser_get_font(LiVESFontChooser *fc) {
6741 return gtk_font_chooser_get_font(fc);
6742 }
6743
lives_font_chooser_set_font(LiVESFontChooser * fc,const char * fontname)6744 WIDGET_HELPER_GLOBAL_INLINE boolean lives_font_chooser_set_font(LiVESFontChooser *fc,
6745 const char *fontname) {
6746 gtk_font_chooser_set_font(fc, fontname);
6747 return TRUE;
6748 }
6749
lives_font_chooser_get_font_desc(LiVESFontChooser * fc)6750 WIDGET_HELPER_GLOBAL_INLINE LingoFontDescription *lives_font_chooser_get_font_desc(LiVESFontChooser *fc) {
6751 return gtk_font_chooser_get_font_desc(fc);
6752 }
6753
lives_font_chooser_set_font_desc(LiVESFontChooser * fc,LingoFontDescription * lfd)6754 WIDGET_HELPER_GLOBAL_INLINE boolean lives_font_chooser_set_font_desc(LiVESFontChooser *fc,
6755 LingoFontDescription *lfd) {
6756 gtk_font_chooser_set_font_desc(fc, lfd);
6757 return TRUE;
6758 }
6759 #endif
6760
6761
6762 #ifdef GUI_GTK
lives_grid_new(void)6763 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_grid_new(void) {
6764 LiVESWidget *grid = NULL;
6765 #ifdef GUI_GTK
6766 #if GTK_CHECK_VERSION(3,2,0) // required for grid widget
6767 grid = gtk_grid_new();
6768 #endif
6769 #endif
6770 return grid;
6771 }
6772
6773
lives_grid_set_row_spacing(LiVESGrid * grid,uint32_t spacing)6774 WIDGET_HELPER_GLOBAL_INLINE boolean lives_grid_set_row_spacing(LiVESGrid *grid, uint32_t spacing) {
6775 #ifdef GUI_GTK
6776 #if GTK_CHECK_VERSION(3,2,0) // required for grid widget
6777 gtk_grid_set_row_spacing(grid, spacing);
6778 return TRUE;
6779 #endif
6780 #endif
6781 return FALSE;
6782 }
6783
6784
lives_grid_set_column_spacing(LiVESGrid * grid,uint32_t spacing)6785 WIDGET_HELPER_GLOBAL_INLINE boolean lives_grid_set_column_spacing(LiVESGrid *grid, uint32_t spacing) {
6786 #ifdef GUI_GTK
6787 #if GTK_CHECK_VERSION(3,2,0) // required for grid widget
6788 gtk_grid_set_column_spacing(grid, spacing);
6789 return TRUE;
6790 #endif
6791 #endif
6792 return FALSE;
6793 }
6794
6795
lives_grid_remove_row(LiVESGrid * grid,int posn)6796 WIDGET_HELPER_GLOBAL_INLINE boolean lives_grid_remove_row(LiVESGrid *grid, int posn) {
6797 #ifdef GUI_GTK
6798 #if GTK_CHECK_VERSION(3, 10, 0)
6799 gtk_grid_remove_row(grid, posn);
6800 return TRUE;
6801 #endif
6802 #endif
6803 return FALSE;
6804 }
6805
6806
lives_grid_insert_row(LiVESGrid * grid,int posn)6807 WIDGET_HELPER_GLOBAL_INLINE boolean lives_grid_insert_row(LiVESGrid *grid, int posn) {
6808 #ifdef GUI_GTK
6809 #if GTK_CHECK_VERSION(3, 10, 0)
6810 gtk_grid_insert_row(grid, posn);
6811 return TRUE;
6812 #endif
6813
6814 return FALSE;
6815 }
6816
6817
lives_grid_attach_next_to(LiVESGrid * grid,LiVESWidget * child,LiVESWidget * sibling,LiVESPositionType side,int width,int height)6818 WIDGET_HELPER_GLOBAL_INLINE boolean lives_grid_attach_next_to(LiVESGrid *grid, LiVESWidget *child, LiVESWidget *sibling,
6819 LiVESPositionType side, int width, int height) {
6820 #ifdef GUI_GTK
6821 #if GTK_CHECK_VERSION(3,2,0) // required for grid widget
6822 gtk_grid_attach_next_to(grid, child, sibling, side, width, height);
6823 return TRUE;
6824 #endif
6825 #endif
6826 return FALSE;
6827 }
6828 #endif
6829 #endif
6830
lives_frame_new(const char * label)6831 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_frame_new(const char *label) {
6832 LiVESWidget *frame = NULL;
6833 #ifdef GUI_GTK
6834 frame = gtk_frame_new(label);
6835 #endif
6836 return frame;
6837 }
6838
6839
lives_frame_set_label(LiVESFrame * frame,const char * label)6840 WIDGET_HELPER_GLOBAL_INLINE boolean lives_frame_set_label(LiVESFrame *frame, const char *label) {
6841 #ifdef GUI_GTK
6842 gtk_frame_set_label(frame, label);
6843 return TRUE;
6844 #endif
6845 return FALSE;
6846 }
6847
6848
lives_frame_set_label_align(LiVESFrame * frame,float xalign,float yalign)6849 WIDGET_HELPER_GLOBAL_INLINE boolean lives_frame_set_label_align(LiVESFrame *frame, float xalign, float yalign) {
6850 #ifdef GUI_GTK
6851 gtk_frame_set_label_align(frame, xalign, yalign);
6852 return TRUE;
6853 #endif
6854 return FALSE;
6855 }
6856
6857
lives_frame_set_label_widget(LiVESFrame * frame,LiVESWidget * widget)6858 WIDGET_HELPER_GLOBAL_INLINE boolean lives_frame_set_label_widget(LiVESFrame *frame, LiVESWidget *widget) {
6859 #ifdef GUI_GTK
6860 gtk_frame_set_label_widget(frame, widget);
6861 return TRUE;
6862 #endif
6863 return FALSE;
6864 }
6865
6866
lives_frame_get_label_widget(LiVESFrame * frame)6867 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_frame_get_label_widget(LiVESFrame *frame) {
6868 LiVESWidget *widget = NULL;
6869 #ifdef GUI_GTK
6870 widget = gtk_frame_get_label_widget(frame);
6871 #endif
6872 return widget;
6873 }
6874
6875
lives_frame_set_shadow_type(LiVESFrame * frame,LiVESShadowType stype)6876 WIDGET_HELPER_GLOBAL_INLINE boolean lives_frame_set_shadow_type(LiVESFrame *frame, LiVESShadowType stype) {
6877 #ifdef GUI_GTK
6878 gtk_frame_set_shadow_type(frame, stype);
6879 return TRUE;
6880 #endif
6881 return FALSE;
6882 }
6883
6884
lives_notebook_new(void)6885 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_notebook_new(void) {
6886 LiVESWidget *nbook = NULL;
6887 #ifdef GUI_GTK
6888 nbook = gtk_notebook_new();
6889 #endif
6890 return nbook;
6891 }
6892
6893
lives_notebook_get_nth_page(LiVESNotebook * nbook,int pagenum)6894 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_notebook_get_nth_page(LiVESNotebook *nbook, int pagenum) {
6895 LiVESWidget *page = NULL;
6896 #ifdef GUI_GTK
6897 page = gtk_notebook_get_nth_page(nbook, pagenum);
6898 #endif
6899 return page;
6900 }
6901
6902
lives_notebook_get_current_page(LiVESNotebook * nbook)6903 WIDGET_HELPER_GLOBAL_INLINE int lives_notebook_get_current_page(LiVESNotebook *nbook) {
6904 int pagenum = -1;
6905 #ifdef GUI_GTK
6906 pagenum = gtk_notebook_get_current_page(nbook);
6907 #endif
6908 return pagenum;
6909 }
6910
6911
lives_notebook_set_current_page(LiVESNotebook * nbook,int pagenum)6912 WIDGET_HELPER_GLOBAL_INLINE boolean lives_notebook_set_current_page(LiVESNotebook *nbook, int pagenum) {
6913 #ifdef GUI_GTK
6914 gtk_notebook_set_current_page(nbook, pagenum);
6915 return TRUE;
6916 #endif
6917 return FALSE;
6918 }
6919
6920
lives_notebook_set_tab_label(LiVESNotebook * nbook,LiVESWidget * child,LiVESWidget * tablabel)6921 WIDGET_HELPER_GLOBAL_INLINE boolean lives_notebook_set_tab_label(LiVESNotebook *nbook, LiVESWidget *child,
6922 LiVESWidget *tablabel) {
6923 #ifdef GUI_GTK
6924 gtk_notebook_set_tab_label(nbook, child, tablabel);
6925 return TRUE;
6926 #endif
6927 return FALSE;
6928 }
6929
6930
lives_table_new(uint32_t rows,uint32_t cols,boolean homogeneous)6931 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_table_new(uint32_t rows, uint32_t cols, boolean homogeneous) {
6932 LiVESWidget *table = NULL;
6933 #ifdef GUI_GTK
6934 #if LIVES_TABLE_IS_GRID // required for grid remove row
6935 register int i;
6936 GtkGrid *grid = (GtkGrid *)lives_grid_new();
6937 gtk_grid_set_row_homogeneous(grid, homogeneous);
6938 gtk_grid_set_column_homogeneous(grid, homogeneous);
6939
6940 for (i = 0; i < rows; i++) {
6941 lives_grid_insert_row(grid, 0);
6942 }
6943
6944 for (i = 0; i < cols; i++) {
6945 gtk_grid_insert_column(grid, 0);
6946 }
6947
6948 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(grid), ROWS_KEY, LIVES_INT_TO_POINTER(rows));
6949 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(grid), COLS_KEY, LIVES_INT_TO_POINTER(cols));
6950 table = (LiVESWidget *)grid;
6951 #else
6952 table = gtk_table_new(rows, cols, homogeneous);
6953 #endif
6954 #endif
6955 return table;
6956 }
6957
6958
lives_table_set_row_spacings(LiVESTable * table,uint32_t spacing)6959 WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_set_row_spacings(LiVESTable *table, uint32_t spacing) {
6960 #ifdef GUI_GTK
6961 #if LIVES_TABLE_IS_GRID // required for grid remove row
6962 lives_grid_set_row_spacing(table, spacing);
6963 #else
6964 gtk_table_set_row_spacings(table, spacing);
6965 return TRUE;
6966 #endif
6967 #endif
6968 return FALSE;
6969 }
6970
6971
lives_table_set_col_spacings(LiVESTable * table,uint32_t spacing)6972 WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_set_col_spacings(LiVESTable *table, uint32_t spacing) {
6973 #ifdef GUI_GTK
6974 #if LIVES_TABLE_IS_GRID // required for grid remove row
6975 lives_grid_set_column_spacing(table, spacing);
6976 #else
6977 gtk_table_set_col_spacings(table, spacing);
6978 return TRUE;
6979 #endif
6980 #endif
6981 return FALSE;
6982 }
6983
6984
lives_table_set_row_homogeneous(LiVESTable * table,boolean homogeneous)6985 WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_set_row_homogeneous(LiVESTable *table, boolean homogeneous) {
6986 #ifdef GUI_GTK
6987 #if LIVES_TABLE_IS_GRID
6988 gtk_grid_set_row_homogeneous(table, homogeneous);
6989 return TRUE;
6990 #else
6991 gtk_table_set_homogeneous(table, homogeneous);
6992 #endif
6993 #endif
6994 return FALSE;
6995 }
6996
6997
lives_table_set_column_homogeneous(LiVESTable * table,boolean homogeneous)6998 WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_set_column_homogeneous(LiVESTable *table, boolean homogeneous) {
6999 #ifdef GUI_GTK
7000 #if LIVES_TABLE_IS_GRID
7001 gtk_grid_set_column_homogeneous(table, homogeneous);
7002 return TRUE;
7003 #else
7004 gtk_table_set_homogeneous(table, homogeneous);
7005 #endif
7006 #endif
7007 return FALSE;
7008 }
7009
7010
lives_table_resize(LiVESTable * table,uint32_t rows,uint32_t cols)7011 WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_resize(LiVESTable *table, uint32_t rows, uint32_t cols) {
7012 #ifdef GUI_GTK
7013 #if LIVES_TABLE_IS_GRID // required for grid remove row
7014 register int i;
7015
7016 for (i = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(table), ROWS_KEY)); i < rows; i++) {
7017 lives_grid_insert_row(table, i);
7018 }
7019
7020 for (i = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(table), COLS_KEY)); i < cols; i++) {
7021 gtk_grid_insert_column(table, i);
7022 }
7023
7024 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(table), ROWS_KEY, LIVES_INT_TO_POINTER(rows));
7025 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(table), COLS_KEY, LIVES_INT_TO_POINTER(cols));
7026 #else
7027 gtk_table_resize(table, rows, cols);
7028 #endif
7029 return TRUE;
7030 #endif
7031 return FALSE;
7032 }
7033
7034
lives_table_attach(LiVESTable * table,LiVESWidget * child,uint32_t left,uint32_t right,uint32_t top,uint32_t bottom,LiVESAttachOptions xoptions,LiVESAttachOptions yoptions,uint32_t xpad,uint32_t ypad)7035 WIDGET_HELPER_GLOBAL_INLINE boolean lives_table_attach(LiVESTable *table, LiVESWidget *child, uint32_t left, uint32_t right,
7036 uint32_t top, uint32_t bottom, LiVESAttachOptions xoptions, LiVESAttachOptions yoptions,
7037 uint32_t xpad, uint32_t ypad) {
7038 #ifdef GUI_GTK
7039 #if LIVES_TABLE_IS_GRID // required for grid remove row
7040 gtk_grid_attach(table, child, left, top, right - left, bottom - top);
7041 if (xoptions & LIVES_EXPAND)
7042 lives_widget_set_hexpand(child, TRUE);
7043 else
7044 lives_widget_set_hexpand(child, FALSE);
7045 if (yoptions & LIVES_EXPAND)
7046 lives_widget_set_vexpand(child, TRUE);
7047 else
7048 lives_widget_set_vexpand(child, FALSE);
7049
7050 lives_widget_set_margin_left(child, xpad);
7051 lives_widget_set_margin_right(child, xpad);
7052
7053 lives_widget_set_margin_top(child, ypad);
7054 lives_widget_set_margin_bottom(child, ypad);
7055 #else
7056 gtk_table_attach(table, child, left, right, top, bottom, xoptions, yoptions, xpad, ypad);
7057 #endif
7058 return TRUE;
7059 #endif
7060 return FALSE;
7061 }
7062
7063
lives_color_button_new_with_color(const LiVESWidgetColor * color)7064 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_color_button_new_with_color(const LiVESWidgetColor *color) {
7065 LiVESWidget *cbutton = NULL;
7066 #ifdef GUI_GTK
7067 #if GTK_CHECK_VERSION(3, 0, 0)
7068 cbutton = gtk_color_button_new_with_rgba(color);
7069 #else
7070 cbutton = gtk_color_button_new_with_color(color);
7071 #endif
7072 #endif
7073 return cbutton;
7074 }
7075
7076
lives_color_button_get_color(LiVESColorButton * button,LiVESWidgetColor * color)7077 WIDGET_HELPER_GLOBAL_INLINE LiVESWidgetColor *lives_color_button_get_color(LiVESColorButton *button, LiVESWidgetColor *color) {
7078 #ifdef GUI_GTK
7079 #if GTK_CHECK_VERSION(3, 4, 0)
7080 gtk_color_chooser_get_rgba((GtkColorChooser *)button, color);
7081 #else
7082 #if GTK_CHECK_VERSION(3, 0, 0)
7083 gtk_color_button_get_rgba((GtkColorChooser *)button, color);
7084 #else
7085 gtk_color_button_get_color(button, color);
7086 #endif
7087 #endif
7088 return color;
7089 #endif
7090 return NULL;
7091 }
7092
7093
lives_color_button_set_alpha(LiVESColorButton * button,int16_t alpha)7094 WIDGET_HELPER_GLOBAL_INLINE boolean lives_color_button_set_alpha(LiVESColorButton *button, int16_t alpha) {
7095 #ifdef GUI_GTK
7096 #if GTK_CHECK_VERSION(3, 4, 0)
7097 LiVESWidgetColor color;
7098 gtk_color_chooser_get_rgba((GtkColorChooser *)button, &color);
7099 color.alpha = LIVES_WIDGET_COLOR_SCALE(alpha);
7100 gtk_color_chooser_set_rgba((GtkColorChooser *)button, &color);
7101 #else
7102 gtk_color_button_set_alpha(button, alpha);
7103 #endif
7104 return TRUE;
7105 #endif
7106 return FALSE;
7107 }
7108
7109
lives_color_button_get_alpha(LiVESColorButton * button)7110 WIDGET_HELPER_GLOBAL_INLINE int16_t lives_color_button_get_alpha(LiVESColorButton *button) {
7111 #ifdef GUI_GTK
7112 #if GTK_CHECK_VERSION(3, 4, 0)
7113 LiVESWidgetColor color;
7114 gtk_color_chooser_get_rgba((GtkColorChooser *)button, &color);
7115 return LIVES_WIDGET_COLOR_STRETCH(color.alpha);
7116 #else
7117 return gtk_color_button_get_alpha(button);
7118 #endif
7119 #endif
7120 return -1;
7121 }
7122
7123
lives_color_button_set_color(LiVESColorButton * button,const LiVESWidgetColor * color)7124 WIDGET_HELPER_GLOBAL_INLINE boolean lives_color_button_set_color(LiVESColorButton *button, const LiVESWidgetColor *color) {
7125 #ifdef GUI_GTK
7126 #if GTK_CHECK_VERSION(3, 4, 0)
7127 gtk_color_chooser_set_rgba((GtkColorChooser *)button, color);
7128 #else
7129 #if GTK_CHECK_VERSION(3, 0, 0)
7130 gtk_color_button_set_rgba((GtkColorChooser *)button, color);
7131 #else
7132 gtk_color_button_set_color(button, color);
7133 #endif
7134 #endif
7135 return TRUE;
7136 #endif
7137 return FALSE;
7138 }
7139
7140
lives_color_button_set_title(LiVESColorButton * button,const char * title)7141 WIDGET_HELPER_GLOBAL_INLINE boolean lives_color_button_set_title(LiVESColorButton *button, const char *title) {
7142 #ifdef GUI_GTK
7143 char *ntitle = lives_strdup_printf("%s%s", widget_opts.title_prefix, title);
7144 gtk_color_button_set_title(button, title);
7145 lives_free(ntitle);
7146 return TRUE;
7147 #endif
7148 return FALSE;
7149 }
7150
7151
lives_color_button_set_use_alpha(LiVESColorButton * button,boolean use_alpha)7152 WIDGET_HELPER_GLOBAL_INLINE boolean lives_color_button_set_use_alpha(LiVESColorButton *button, boolean use_alpha) {
7153 #ifdef GUI_GTK
7154 #if GTK_CHECK_VERSION(3, 4, 0)
7155 gtk_color_chooser_set_use_alpha((GtkColorChooser *)button, use_alpha);
7156 #else
7157 #if GTK_CHECK_VERSION(3, 0, 0)
7158 gtk_color_button_set_use_alpha((GtkColorChooser *)button, use_alpha);
7159 #else
7160 gtk_color_button_set_use_alpha(button, use_alpha);
7161 #endif
7162 #endif
7163 return TRUE;
7164 #endif
7165 return FALSE;
7166 }
7167
7168
lives_widget_get_mods(LiVESXDevice * device,LiVESWidget * widget,int * x,int * y,LiVESXModifierType * modmask)7169 WIDGET_HELPER_LOCAL_INLINE boolean lives_widget_get_mods(LiVESXDevice *device, LiVESWidget *widget, int *x, int *y,
7170 LiVESXModifierType *modmask) {
7171 #ifdef GUI_GTK
7172 LiVESXWindow *xwin;
7173 if (!widget) xwin = gdk_get_default_root_window();
7174 else xwin = lives_widget_get_xwindow(widget);
7175 if (!xwin) {
7176 LIVES_ERROR("Tried to get pointer for windowless widget");
7177 return TRUE;
7178 }
7179 #if GTK_CHECK_VERSION(3, 0, 0)
7180 gdk_window_get_device_position(xwin, device, x, y, modmask);
7181 #else
7182 gdk_window_get_pointer(xwin, x, y, modmask);
7183 #endif
7184 return TRUE;
7185 #endif
7186 return FALSE;
7187 }
7188
7189
lives_widget_get_pointer(LiVESXDevice * device,LiVESWidget * widget,int * x,int * y)7190 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_pointer(LiVESXDevice *device, LiVESWidget *widget, int *x, int *y) {
7191 return lives_widget_get_mods(device, widget, x, y, NULL);
7192 }
7193
7194
lives_widget_get_modmask(LiVESXDevice * device,LiVESWidget * widget,LiVESXModifierType * modmask)7195 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_modmask(LiVESXDevice *device, LiVESWidget *widget,
7196 LiVESXModifierType *modmask) {
7197 return lives_widget_get_mods(device, widget, NULL, NULL, modmask);
7198 }
7199
7200
lives_widget_destroyed(LiVESWidget * widget,void ** ptr)7201 static boolean lives_widget_destroyed(LiVESWidget *widget, void **ptr) {
7202 if (ptr) *ptr = NULL;
7203 return FALSE;
7204 }
7205
7206
lives_widget_timetodie(LiVESWidget * widget,LiVESWidget * getoverhere)7207 static boolean lives_widget_timetodie(LiVESWidget *widget, LiVESWidget *getoverhere) {
7208 if (LIVES_IS_WIDGET(getoverhere)) lives_widget_destroy(getoverhere);
7209 return FALSE;
7210 }
7211
7212
lives_widget_nullify_with(LiVESWidget * widget,void ** ptr)7213 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_nullify_with(LiVESWidget *widget, void **ptr) {
7214 lives_signal_sync_connect(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_DESTROY_SIGNAL,
7215 LIVES_GUI_CALLBACK(lives_widget_destroyed),
7216 ptr);
7217 return TRUE;
7218 }
7219
7220
lives_widget_destroy_with(LiVESWidget * widget,LiVESWidget * dieplease)7221 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_destroy_with(LiVESWidget *widget, LiVESWidget *dieplease) {
7222 lives_signal_sync_connect(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_DESTROY_SIGNAL,
7223 LIVES_GUI_CALLBACK(lives_widget_timetodie),
7224 dieplease);
7225 return TRUE;
7226 }
7227
7228
lives_widget_get_display(LiVESWidget * widget)7229 WIDGET_HELPER_GLOBAL_INLINE LiVESXDisplay *lives_widget_get_display(LiVESWidget *widget) {
7230 LiVESXDisplay *disp = NULL;
7231 #ifdef GUI_GTK
7232 disp = gtk_widget_get_display(widget);
7233 #endif
7234 return disp;
7235 }
7236
7237
lives_display_get_window_at_pointer(LiVESXDevice * device,LiVESXDisplay * display,int * win_x,int * win_y)7238 WIDGET_HELPER_GLOBAL_INLINE LiVESXWindow *lives_display_get_window_at_pointer
7239 (LiVESXDevice *device, LiVESXDisplay *display, int *win_x, int *win_y) {
7240 LiVESXWindow *xwindow = NULL;
7241 #ifdef GUI_GTK
7242 #if GTK_CHECK_VERSION(3, 0, 0)
7243 if (!device) return NULL;
7244 xwindow = gdk_device_get_window_at_position(device, win_x, win_y);
7245 #else
7246 xwindow = gdk_display_get_window_at_pointer(display, win_x, win_y);
7247 #endif
7248 #endif
7249 return xwindow;
7250 }
7251
7252
lives_display_get_pointer(LiVESXDevice * device,LiVESXDisplay * display,LiVESXScreen ** screen,int * x,int * y,LiVESXModifierType * mask)7253 WIDGET_HELPER_GLOBAL_INLINE boolean lives_display_get_pointer
7254 (LiVESXDevice *device, LiVESXDisplay *display, LiVESXScreen **screen, int *x, int *y, LiVESXModifierType *mask) {
7255 #ifdef GUI_GTK
7256 #if GTK_CHECK_VERSION(3, 0, 0)
7257 if (!device) return TRUE;
7258 gdk_device_get_position(device, screen, x, y);
7259 #else
7260 gdk_display_get_pointer(display, screen, x, y, mask);
7261 #endif
7262 return TRUE;
7263 #endif
7264 return FALSE;
7265 }
7266
7267
lives_display_warp_pointer(LiVESXDevice * device,LiVESXDisplay * display,LiVESXScreen * screen,int x,int y)7268 WIDGET_HELPER_GLOBAL_INLINE boolean lives_display_warp_pointer
7269 (LiVESXDevice *device, LiVESXDisplay *display, LiVESXScreen *screen, int x, int y) {
7270 #ifdef GUI_GTK
7271 #if GTK_CHECK_VERSION(3, 0, 0)
7272 if (!device) return TRUE;
7273 gdk_device_warp(device, screen, x, y);
7274 #else
7275 #if GLIB_CHECK_VERSION(2, 8, 0)
7276 gdk_display_warp_pointer(display, screen, x, y);
7277 #endif
7278 #endif
7279 return TRUE;
7280 #endif
7281 return FALSE;
7282 }
7283
7284
lives_widget_get_display_type(LiVESWidget * widget)7285 WIDGET_HELPER_GLOBAL_INLINE lives_display_t lives_widget_get_display_type(LiVESWidget *widget) {
7286 lives_display_t dtype = LIVES_DISPLAY_TYPE_UNKNOWN;
7287 #ifdef GUI_GTK
7288 if (GDK_IS_X11_DISPLAY(gtk_widget_get_display(widget))) dtype = LIVES_DISPLAY_TYPE_X11;
7289 #ifdef GDK_WINDOWING_WAYLAND
7290 else if (GDK_IS_WAYLAND_DISPLAY(gtk_widget_get_display(widget))) dtype = LIVES_DISPLAY_TYPE_WAYLAND;
7291 #endif
7292 else if (GDK_IS_WIN32_DISPLAY(gtk_widget_get_display(widget))) dtype = LIVES_DISPLAY_TYPE_WIN32;
7293 #endif
7294 return dtype;
7295 }
7296
7297
lives_widget_get_xwinid(LiVESWidget * widget,const char * msg)7298 WIDGET_HELPER_GLOBAL_INLINE uint64_t lives_widget_get_xwinid(LiVESWidget *widget, const char *msg) {
7299 uint64_t xwin = -1;
7300 #ifdef GUI_GTK
7301 #ifdef GDK_WINDOWING_X11
7302 if (lives_widget_get_display_type(widget) == LIVES_DISPLAY_TYPE_X11)
7303 xwin = (uint64_t)GDK_WINDOW_XID(lives_widget_get_xwindow(widget));
7304 else
7305 #endif
7306 #ifdef GDK_WINDOWING_WIN32
7307 if (lives_widget_get_display_type(widget) == LIVES_DISPLAY_TYPE_WIN32)
7308 xwin = (uint64_t)gdk_win32_window_get_handle(lives_widget_get_xwindow(widget));
7309 else
7310 #endif
7311 #endif
7312 if (msg) LIVES_WARN(msg);
7313
7314 return xwin;
7315 }
7316
7317
lives_timer_add(uint32_t interval,LiVESWidgetSourceFunc function,livespointer data)7318 WIDGET_HELPER_GLOBAL_INLINE uint32_t lives_timer_add(uint32_t interval, LiVESWidgetSourceFunc function, livespointer data) {
7319 // interval in milliseconds
7320 lives_sigdata_t *sigdata = (lives_sigdata_t *)lives_calloc(1, sizeof(lives_sigdata_t));
7321 sigdata->callback = (lives_funcptr_t)function;
7322 sigdata->user_data = data;
7323 sigdata->is_timer = TRUE;
7324
7325 #ifdef GUI_GTK
7326 #if GTK_CHECK_VERSION(3, 0, 0)
7327 if (interval > 1000) {
7328 sigdata->funcid = g_timeout_add_seconds(interval / 1000., async_timer_handler, sigdata);
7329 } else {
7330 sigdata->funcid = g_timeout_add(interval, async_timer_handler, sigdata);
7331 }
7332 #else
7333 sigdata->funcid = gtk_timeout_add(interval, async_timer_handler, sigdata);
7334 #endif
7335 #endif
7336
7337 return sigdata->funcid;
7338 }
7339
7340
lives_timer_remove(uint32_t timer)7341 WIDGET_HELPER_GLOBAL_INLINE boolean lives_timer_remove(uint32_t timer) {
7342 #ifdef GUI_GTK
7343 g_source_remove(timer);
7344 return TRUE;
7345 #endif
7346 return FALSE;
7347 }
7348
7349
lives_idle_add(LiVESWidgetSourceFunc function,livespointer data)7350 WIDGET_HELPER_GLOBAL_INLINE uint32_t lives_idle_add(LiVESWidgetSourceFunc function, livespointer data) {
7351 lives_sigdata_t *sigdata = (lives_sigdata_t *)lives_calloc(1, sizeof(lives_sigdata_t));
7352 sigdata->callback = (lives_funcptr_t)function;
7353 sigdata->user_data = data;
7354 sigdata->is_timer = TRUE;
7355
7356 sigdata->funcid = g_idle_add(async_timer_handler, sigdata);
7357 return sigdata->funcid;
7358 }
7359
7360
lives_source_remove(uint32_t handle)7361 WIDGET_HELPER_GLOBAL_INLINE boolean lives_source_remove(uint32_t handle) {
7362 return lives_timer_remove(handle);
7363 }
7364
7365
lives_accelerator_get_default_mod_mask(void)7366 WIDGET_HELPER_GLOBAL_INLINE uint32_t lives_accelerator_get_default_mod_mask(void) {
7367 #ifdef GUI_GTK
7368 return gtk_accelerator_get_default_mod_mask();
7369 #endif
7370 return 0;
7371 }
7372
7373
lives_screen_get_width(LiVESXScreen * screen)7374 WIDGET_HELPER_GLOBAL_INLINE int lives_screen_get_width(LiVESXScreen *screen) {
7375 #ifdef GUI_GTK
7376 #if !GTK_CHECK_VERSION(3, 22, 0)
7377 return gdk_screen_get_width(screen);
7378 #endif
7379 #endif
7380 return 0;
7381 }
7382
7383
lives_screen_get_height(LiVESXScreen * screen)7384 WIDGET_HELPER_GLOBAL_INLINE int lives_screen_get_height(LiVESXScreen *screen) {
7385 #ifdef GUI_GTK
7386 #if !GTK_CHECK_VERSION(3, 22, 0)
7387 return gdk_screen_get_height(screen);
7388 #endif
7389 #endif
7390 return 0;
7391 }
7392
7393
global_recent_manager_add(const char * full_file_name)7394 WIDGET_HELPER_GLOBAL_INLINE boolean global_recent_manager_add(const char *full_file_name) {
7395 #ifdef GUI_GTK
7396 char *tmp = g_filename_to_uri(full_file_name, NULL, NULL);
7397 gtk_recent_manager_add_item(gtk_recent_manager_get_default(), tmp);
7398 g_free(tmp);
7399 return TRUE;
7400 #endif
7401 return FALSE;
7402 }
7403
7404
lives_cursor_new_from_pixbuf(LiVESXDisplay * disp,LiVESPixbuf * pixbuf,int x,int y)7405 WIDGET_HELPER_GLOBAL_INLINE LiVESXCursor *lives_cursor_new_from_pixbuf(LiVESXDisplay *disp, LiVESPixbuf *pixbuf, int x, int y) {
7406 LiVESXCursor *cursor = NULL;
7407 #ifdef GUI_GTK
7408 cursor = gdk_cursor_new_from_pixbuf(disp, pixbuf, x, y);
7409 #endif
7410 return cursor;
7411 }
7412
7413
lives_has_toplevel_focus(LiVESWidget * widget)7414 WIDGET_HELPER_GLOBAL_INLINE boolean lives_has_toplevel_focus(LiVESWidget *widget) {
7415 #ifdef GUI_GTK
7416 return gtk_window_has_toplevel_focus(LIVES_WINDOW(widget));
7417 #endif
7418 return TRUE;
7419 }
7420
7421
lives_entry_set_editable(LiVESEntry * entry,boolean editable)7422 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_editable(LiVESEntry *entry, boolean editable) {
7423 return lives_editable_set_editable(LIVES_EDITABLE(entry), editable);
7424 }
7425
7426
lives_entry_get_editable(LiVESEntry * entry)7427 WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_get_editable(LiVESEntry *entry) {
7428 return lives_editable_get_editable(LIVES_EDITABLE(entry));
7429 }
7430
7431
7432 // compound functions
7433
lives_image_scale(LiVESImage * image,int width,int height,LiVESInterpType interp_type)7434 WIDGET_HELPER_GLOBAL_INLINE boolean lives_image_scale(LiVESImage *image, int width, int height, LiVESInterpType interp_type) {
7435 LiVESPixbuf *pixbuf;
7436 if (!LIVES_IS_IMAGE(image)) return FALSE;
7437 pixbuf = lives_image_get_pixbuf(image);
7438 if (pixbuf) {
7439 LiVESPixbuf *new_pixbuf = lives_pixbuf_scale_simple(pixbuf, width, height, interp_type);
7440 lives_image_set_from_pixbuf(image, new_pixbuf);
7441 //if (LIVES_IS_WIDGET_OBJECT(pixbuf)) lives_widget_object_unref(pixbuf);
7442 if (new_pixbuf && LIVES_IS_WIDGET_OBJECT(new_pixbuf)) lives_widget_object_unref(new_pixbuf);
7443 }
7444 return TRUE;
7445 }
7446
7447
lives_widget_set_pack_type(LiVESBox * box,LiVESWidget * child,LiVESPackType pack)7448 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_pack_type(LiVESBox *box, LiVESWidget *child, LiVESPackType pack) {
7449 #ifdef GUI_GTK
7450 boolean expand, fill;
7451 uint32_t padding;
7452 gtk_box_query_child_packing(box, child, &expand, &fill, &padding, NULL);
7453 lives_box_set_child_packing(box, child, expand, fill, padding, pack);
7454 #endif
7455 return FALSE;
7456 }
7457
7458
lives_label_set_hpadding(LiVESLabel * label,int pad)7459 WIDGET_HELPER_GLOBAL_INLINE void lives_label_set_hpadding(LiVESLabel *label, int pad) {
7460 const char *text = lives_label_get_text(label);
7461 lives_label_set_width_chars(label, strlen(text) + pad);
7462 }
7463
7464
7465 #define H_ALIGN_ADJ (22. * widget_opts.scale) // why 22 ? no idea
7466
align_horizontal_with(LiVESWidget * thingtoadd,LiVESWidget * thingtoalignwith)7467 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *align_horizontal_with(LiVESWidget *thingtoadd, LiVESWidget *thingtoalignwith) {
7468 #ifdef GUI_GTK
7469 GtkWidget *fixed = gtk_fixed_new();
7470 int x = lives_widget_get_allocation_x(thingtoalignwith);
7471 // allow for 1 packing_width before adding the real widget
7472 gtk_fixed_put(GTK_FIXED(fixed), thingtoadd, x - H_ALIGN_ADJ - widget_opts.packing_width, 0);
7473 lives_widget_set_show_hide_parent(thingtoadd);
7474 return fixed;
7475 #endif
7476 return NULL;
7477 }
7478
7479
lives_box_pack_first(LiVESBox * box,LiVESWidget * child,boolean expand,boolean fill,uint32_t padding)7480 WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_first(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill,
7481 uint32_t padding) {
7482 if (lives_box_pack_start(box, child, expand, fill, padding))
7483 return lives_box_reorder_child(box, child, 0);
7484 return FALSE;
7485 }
7486
7487
lives_tooltips_copy(LiVESWidget * dest,LiVESWidget * source)7488 void lives_tooltips_copy(LiVESWidget *dest, LiVESWidget *source) {
7489 #ifdef GUI_GTK
7490 #if GTK_CHECK_VERSION(2, 12, 0)
7491 boolean mustfree = TRUE;
7492 char *text = (char *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(source), TTIPS_KEY);
7493 if (!text) text = gtk_widget_get_tooltip_text(source);
7494 else mustfree = FALSE;
7495 lives_widget_set_tooltip_text(dest, text);
7496 if (mustfree && text) lives_free(text);
7497 #else
7498 GtkTooltipsData *td = gtk_tooltips_data_get(source);
7499 if (!td) return;
7500 gtk_tooltips_set_tip(td->tooltips, dest, td->tip_text, td->tip_private);
7501 #endif
7502 #endif
7503 #ifdef GUI_QT
7504 dest->setToolTip(source->toolTip());
7505 #endif
7506 }
7507
7508
lives_combo_populate(LiVESCombo * combo,LiVESList * list)7509 boolean lives_combo_populate(LiVESCombo *combo, LiVESList *list) {
7510 LiVESList *revlist;
7511
7512 // remove any current list
7513 LiVESTreeModel *tmodel = lives_combo_get_model(combo);
7514 if (tmodel) {
7515 if (!lives_combo_set_active_index(combo, -1)) return FALSE;
7516 if (!lives_combo_remove_all_text(combo)) return FALSE;
7517 }
7518
7519 if (lives_list_length(list) > COMBO_LIST_LIMIT) {
7520 // use a treestore
7521 LiVESTreeIter iter1, iter2;
7522 LiVESTreeStore *tstore = lives_tree_store_new(1, LIVES_COL_TYPE_STRING);
7523 char *cat;
7524 for (revlist = list; revlist; revlist = revlist->next) {
7525 cat = lives_strndup((const char *)revlist->data, 1);
7526 // returns the iter for cat if it already exists, else appends cat and returns it
7527 lives_tree_store_find_iter(tstore, 0, cat, NULL, &iter1);
7528 lives_tree_store_append(tstore, &iter2, &iter1); /* Acquire an iterator */
7529 lives_tree_store_set(tstore, &iter2, 0, revlist->data, -1);
7530 lives_free(cat);
7531 }
7532 lives_combo_set_model(LIVES_COMBO(combo), LIVES_TREE_MODEL(tstore));
7533 lives_combo_set_entry_text_column(combo, 0);
7534 } else {
7535 // reverse the list and then prepend the items
7536 // this is faster (O(1) than traversing the list and appending O(2))
7537 LiVESTreeIter iter;
7538 LiVESListStore *lstore = lives_list_store_new(1, LIVES_COL_TYPE_STRING);
7539 for (revlist = lives_list_last(list); revlist; revlist = revlist->prev) {
7540 gtk_list_store_prepend(lstore, &iter); /* Acquire an iterator */
7541 gtk_list_store_set(GTK_LIST_STORE(lstore), &iter, 0, revlist->data, -1);
7542 }
7543 lives_combo_set_model(LIVES_COMBO(combo), LIVES_TREE_MODEL(lstore));
7544 lives_combo_set_entry_text_column(combo, 0);
7545 }
7546 return TRUE;
7547 }
7548
7549
7550 ///// lives compounds
7551
lives_volume_button_new(LiVESOrientation orientation,LiVESAdjustment * adj,double volume)7552 LiVESWidget *lives_volume_button_new(LiVESOrientation orientation, LiVESAdjustment *adj, double volume) {
7553 LiVESWidget *volume_scale = NULL;
7554 #ifdef GUI_GTK
7555 #if GTK_CHECK_VERSION(2, 14, 0)
7556 volume_scale = gtk_volume_button_new();
7557 gtk_scale_button_set_value(GTK_SCALE_BUTTON(volume_scale), volume);
7558 lives_scale_button_set_orientation(LIVES_SCALE_BUTTON(volume_scale), orientation);
7559 #else
7560 if (orientation == LIVES_ORIENTATION_HORIZONTAL)
7561 volume_scale = gtk_hscale_new(adj);
7562 else
7563 volume_scale = gtk_vscale_new(adj);
7564
7565 gtk_scale_set_draw_value(GTK_SCALE(volume_scale), FALSE);
7566 #endif
7567 #endif
7568 return volume_scale;
7569 }
7570
7571
lives_button_ungrab_default_special(LiVESWidget * button)7572 boolean lives_button_ungrab_default_special(LiVESWidget *button) {
7573 LiVESWidget *toplevel = lives_widget_get_toplevel(button);
7574 LiVESWidget *deflt = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(toplevel), DEFBUTTON_KEY);
7575
7576 lives_widget_set_can_default(button, FALSE);
7577 if (button == deflt)
7578 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(LIVES_WIDGET_OBJECT(toplevel)),
7579 DEFBUTTON_KEY, NULL);
7580 #ifdef USE_SPECIAL_BUTTONS
7581 sbutt_render(button, 0, NULL);
7582 #endif
7583 return TRUE;
7584 }
7585
7586
lives_button_grab_default_special(LiVESWidget * button)7587 boolean lives_button_grab_default_special(LiVESWidget *button) {
7588 // grab default and set as default default
7589 if (!lives_widget_set_can_focus_and_default(button)) return FALSE;
7590 if (!lives_widget_grab_default(button)) return FALSE;
7591 else {
7592 LiVESWidget *toplevel = lives_widget_get_toplevel(button);
7593 LiVESWidget *deflt = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(toplevel), DEFBUTTON_KEY);
7594 if (button == deflt) return TRUE;
7595 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(LIVES_WIDGET_OBJECT(toplevel)),
7596 DEFBUTTON_KEY, button);
7597 #ifdef USE_SPECIAL_BUTTONS
7598 sbutt_render(button, 0, NULL);
7599 if (deflt) sbutt_render(deflt, 0, NULL);
7600 #endif
7601 }
7602 return TRUE;
7603 }
7604
_set_css_min_size(LiVESWidget * w,const char * sel,int mw,int mh)7605 static void _set_css_min_size(LiVESWidget *w, const char *sel, int mw, int mh) {
7606 #if GTK_CHECK_VERSION(3, 16, 0)
7607 char *tmp;
7608 if (mw > 0) {
7609 tmp = lives_strdup_printf("%dpx", mw);
7610 set_css_value_direct(w, LIVES_WIDGET_STATE_NORMAL, sel, "min-width", tmp);
7611 lives_free(tmp);
7612 }
7613 if (mh > 0) {
7614 tmp = lives_strdup_printf("%dpx", mh);
7615 set_css_value_direct(w, LIVES_WIDGET_STATE_NORMAL, sel, "min-height", tmp);
7616 lives_free(tmp);
7617 }
7618 #endif
7619 }
7620
set_css_min_size(LiVESWidget * w,int mw,int mh)7621 static void set_css_min_size(LiVESWidget *w, int mw, int mh) {
7622 _set_css_min_size(w, "", mw, mh);
7623 _set_css_min_size(w, "*", mw, mh);
7624 }
7625
set_css_min_size_selected(LiVESWidget * w,char * selector,int mw,int mh)7626 static void set_css_min_size_selected(LiVESWidget *w, char *selector, int mw, int mh) {
7627 _set_css_min_size(w, selector, mw, mh);
7628 }
7629
7630
7631 ///////////////// lives_layout ////////////////////////
7632
lives_layout_attach(LiVESLayout * layout,LiVESWidget * widget,int start,int end,int row)7633 WIDGET_HELPER_LOCAL_INLINE void lives_layout_attach(LiVESLayout *layout, LiVESWidget *widget, int start, int end, int row) {
7634 lives_table_attach(layout, widget, start, end, row, row + 1,
7635 (LiVESAttachOptions)(LIVES_FILL | (LIVES_SHOULD_EXPAND_EXTRA_WIDTH
7636 ? LIVES_EXPAND : 0)), (LiVESAttachOptions)(0), 0, 0);
7637 }
7638
7639
lives_layout_expansion_row_new(LiVESLayout * layout,LiVESWidget * widget)7640 LiVESWidget *lives_layout_expansion_row_new(LiVESLayout *layout, LiVESWidget *widget) {
7641 LiVESList *xwidgets = (LiVESList *)lives_widget_object_steal_data(LIVES_WIDGET_OBJECT(layout), EXP_LIST_KEY);
7642 LiVESWidget *box = NULL;
7643 int rows, columns;
7644 if (widget) box = lives_widget_get_parent(widget);
7645
7646 if (!box) {
7647 box = lives_layout_row_new(layout);
7648 if (widget) lives_layout_pack(LIVES_HBOX(box), widget);
7649 }
7650
7651 columns = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(layout), COLS_KEY));
7652 rows = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(layout), ROWS_KEY));
7653 if (columns > 1) {
7654 lives_widget_object_ref(LIVES_WIDGET_OBJECT(box));
7655 lives_widget_unparent(box);
7656 lives_layout_attach(layout, box, 0, columns, rows - 1);
7657 lives_widget_object_unref(LIVES_WIDGET_OBJECT(box));
7658 }
7659 lives_widget_set_halign(box, LIVES_ALIGN_FILL);
7660 //lives_widget_set_halign(widget, LIVES_ALIGN_CENTER);
7661 xwidgets = lives_list_prepend(xwidgets, box);
7662 lives_widget_object_set_data_list(LIVES_WIDGET_OBJECT(layout), EXP_LIST_KEY, xwidgets);
7663 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(box), LROW_KEY, LIVES_INT_TO_POINTER(rows) - 1);
7664 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(box), EXPANSION_KEY, LIVES_INT_TO_POINTER(widget_opts.expand));
7665 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(box), JUST_KEY, LIVES_INT_TO_POINTER(widget_opts.justify));
7666 widget_opts.last_container = box;
7667 if (widget) return widget;
7668 return box;
7669 }
7670
7671
lives_layout_resize(LiVESLayout * layout,int rows,int columns)7672 static boolean lives_layout_resize(LiVESLayout *layout, int rows, int columns) {
7673 LiVESList *xwidgets = (LiVESList *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(layout), EXP_LIST_KEY);
7674 lives_table_resize(LIVES_TABLE(layout), rows, columns);
7675 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(layout), ROWS_KEY, LIVES_INT_TO_POINTER(rows));
7676 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(layout), COLS_KEY, LIVES_INT_TO_POINTER(columns));
7677 while (xwidgets) {
7678 LiVESWidget *widget = (LiVESWidget *)xwidgets->data;
7679 int row = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), LROW_KEY));
7680 int expansion = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), EXPANSION_KEY));
7681 LiVESJustification justification = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
7682 JUST_KEY));
7683 int woe = widget_opts.expand;
7684 LiVESJustification woj = widget_opts.justify;
7685 lives_widget_object_ref(widget);
7686 lives_widget_unparent(widget);
7687 widget_opts.expand = expansion;
7688 widget_opts.justify = justification;
7689 lives_layout_attach(layout, widget, 0, columns, row);
7690 widget_opts.expand = woe;
7691 widget_opts.justify = woj;
7692 lives_widget_object_unref(widget);
7693 xwidgets = xwidgets->next;
7694 }
7695 return TRUE;
7696 }
7697
7698
lives_layout_pack(LiVESHBox * box,LiVESWidget * widget)7699 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_layout_pack(LiVESHBox *box, LiVESWidget *widget) {
7700 LiVESWidget *layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(box), WH_LAYOUT_KEY);
7701 if (layout) {
7702 LiVESList *xwidgets = (LiVESList *)lives_widget_object_steal_data(LIVES_WIDGET_OBJECT(layout), EXP_LIST_KEY);
7703 int row = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(layout), ROWS_KEY)) - 1;
7704 // remove any expansion widgets on this row
7705 if (xwidgets) {
7706 LiVESList *list = xwidgets;
7707 for (; list; list = list->next) {
7708 if (LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(xwidgets->data),
7709 LROW_KEY)) == row) {
7710 if (list->prev) list->prev->next = list->next;
7711 else xwidgets = list->next;
7712 if (list->next) list->next->prev = list->prev;
7713 list->prev = list->next = NULL;
7714 lives_list_free(list);
7715 break;
7716 // *INDENT-OFF*
7717 }}
7718 lives_widget_object_set_data_list(LIVES_WIDGET_OBJECT(layout), EXP_LIST_KEY, xwidgets);
7719 }}
7720 // *INDENT-ON*
7721 lives_box_pack_start(LIVES_BOX(box), widget, LIVES_SHOULD_EXPAND_EXTRA_WIDTH
7722 || (LIVES_IS_LABEL(widget) && LIVES_SHOULD_EXPAND_WIDTH),
7723 TRUE, LIVES_SHOULD_EXPAND_WIDTH
7724 ? widget_opts.packing_width >> 1 : 0);
7725 lives_widget_set_halign(widget, lives_justify_to_align(widget_opts.justify));
7726 lives_widget_set_show_hide_parent(widget);
7727 widget_opts.last_container = LIVES_WIDGET(box);
7728 return widget;
7729 }
7730
7731
lives_layout_new(LiVESBox * box)7732 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_layout_new(LiVESBox * box) {
7733 LiVESWidget *layout = lives_table_new(0, 0, FALSE);
7734 if (box) {
7735 if (LIVES_IS_VBOX(box)) {
7736 lives_box_pack_start(box, layout, LIVES_SHOULD_EXPAND_EXTRA_HEIGHT, TRUE,
7737 LIVES_SHOULD_EXPAND_HEIGHT ? widget_opts.packing_height : 0);
7738 } else {
7739 lives_box_pack_start(box, layout, LIVES_SHOULD_EXPAND_EXTRA_WIDTH, TRUE,
7740 LIVES_SHOULD_EXPAND_WIDTH ? widget_opts.packing_width : 0);
7741 }
7742 }
7743 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(layout), ROWS_KEY, LIVES_INT_TO_POINTER(1));
7744 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(layout), COLS_KEY, LIVES_INT_TO_POINTER(0));
7745 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(layout), WADDED_KEY, LIVES_INT_TO_POINTER(0));
7746 lives_widget_object_set_data_list(LIVES_WIDGET_OBJECT(layout), EXP_LIST_KEY, NULL);
7747 lives_table_set_col_spacings(LIVES_TABLE(layout), 0);
7748 if (LIVES_SHOULD_EXPAND_HEIGHT)
7749 lives_table_set_row_spacings(LIVES_TABLE(layout), widget_opts.packing_height);
7750 if (LIVES_SHOULD_EXPAND_EXTRA_WIDTH)
7751 lives_table_set_col_spacings(LIVES_TABLE(layout), widget_opts.packing_width);
7752 //lives_table_set_column_homogeneous(LIVES_TABLE(layout), FALSE);
7753 return layout;
7754 }
7755
7756
lives_layout_hbox_new(LiVESLayout * layout)7757 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_layout_hbox_new(LiVESLayout * layout) {
7758 LiVESWidget *hbox = lives_hbox_new(FALSE, 0);
7759 #if GTK_CHECK_VERSION(3, 0, 0)
7760 LiVESWidget *widget = hbox;
7761 #else
7762 LiVESWidget *alignment = lives_alignment_new(widget_opts.justify == LIVES_JUSTIFY_CENTER ? 0.5 : widget_opts.justify ==
7763 LIVES_JUSTIFY_END
7764 ? 1. : 0., .5, 0., 0.);
7765 LiVESWidget *widget = alignment;
7766 lives_container_add(LIVES_CONTAINER(alignment), hbox);
7767 #endif
7768
7769 int nadded = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(layout), WADDED_KEY));
7770 int rows = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(layout), ROWS_KEY));
7771 int columns = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(layout), COLS_KEY));
7772 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, layout);
7773 if (++nadded > columns) lives_layout_resize(layout, rows, nadded);
7774 lives_layout_attach(layout, widget, nadded - 1, nadded, rows - 1);
7775 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(layout), WADDED_KEY, LIVES_INT_TO_POINTER(nadded));
7776 if (widget_opts.apply_theme == 2) {
7777 lives_widget_apply_theme2(widget, LIVES_WIDGET_STATE_NORMAL, TRUE);
7778 }
7779 return hbox;
7780 }
7781
7782
lives_layout_add_row(LiVESLayout * layout)7783 WIDGET_HELPER_GLOBAL_INLINE int lives_layout_add_row(LiVESLayout * layout) {
7784 int rows = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(layout), ROWS_KEY));
7785 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(layout), ROWS_KEY, LIVES_INT_TO_POINTER(++rows));
7786 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(layout), WADDED_KEY, LIVES_INT_TO_POINTER(0));
7787 return rows;
7788 }
7789
7790
lives_layout_row_new(LiVESLayout * layout)7791 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_layout_row_new(LiVESLayout * layout) {
7792 lives_layout_add_row(layout);
7793 return lives_layout_hbox_new(layout);
7794 }
7795
7796
lives_layout_label_set_text(LiVESLabel * label,const char * text)7797 WIDGET_HELPER_GLOBAL_INLINE void lives_layout_label_set_text(LiVESLabel * label, const char *text) {
7798 if (text) {
7799 char *markup, *full_markup;
7800 if (!widget_opts.use_markup) markup = lives_markup_escape_text(text, -1);
7801 else markup = (char *)text;
7802 full_markup = lives_strdup_printf("<big><b>%s</b></big>", markup);
7803 lives_label_set_markup(label, full_markup);
7804 if (markup != text) lives_free(markup);
7805 lives_free(full_markup);
7806 }
7807 }
7808
7809
lives_layout_add_label(LiVESLayout * layout,const char * text,boolean horizontal)7810 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_layout_add_label(LiVESLayout * layout, const char *text, boolean horizontal) {
7811 if (horizontal) {
7812 LiVESWidget *hbox = lives_layout_hbox_new(layout);
7813 LiVESWidget *label = lives_standard_label_new_with_tooltips(text, LIVES_BOX(hbox), NULL);
7814 LiVESWidget *conter = widget_opts.last_container;
7815 widget_opts.last_label = label;
7816 lives_widget_object_ref(conter);
7817 lives_widget_unparent(conter);
7818 lives_layout_pack(LIVES_HBOX(hbox), conter);
7819 lives_widget_object_unref(conter);
7820 widget_opts.last_container = hbox;
7821 if (widget_opts.apply_theme == 2) set_child_alt_colour(hbox, TRUE);
7822 return label;
7823 } else {
7824 LiVESWidget *hbox = lives_hbox_new(FALSE, 0);
7825 LiVESWidget *label = lives_standard_label_new_with_tooltips(NULL, LIVES_BOX(hbox), NULL);
7826 LiVESWidget *conter = widget_opts.last_container;
7827 lives_layout_label_set_text(LIVES_LABEL(label), text);
7828 widget_opts.last_label = label;
7829 lives_widget_object_ref(conter);
7830 lives_widget_unparent(conter);
7831 lives_widget_destroy(hbox);
7832 lives_layout_expansion_row_new(layout, conter);
7833 lives_widget_object_ref(conter);
7834 widget_opts.last_container = hbox;
7835 if (widget_opts.apply_theme == 2) set_child_alt_colour(hbox, TRUE);
7836 return label;
7837 }
7838 }
7839
7840
lives_layout_add_fill(LiVESLayout * layout,boolean horizontal)7841 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_layout_add_fill(LiVESLayout * layout, boolean horizontal) {
7842 LiVESWidget *widget;
7843 if (horizontal) {
7844 LiVESWidget *hbox = lives_layout_hbox_new(layout);
7845 widget = add_fill_to_box(LIVES_BOX(hbox));
7846 widget_opts.last_container = hbox;
7847 } else {
7848 widget = lives_layout_add_label(layout, NULL, FALSE);
7849 lives_layout_expansion_row_new(layout, widget);
7850 }
7851 return widget;
7852 }
7853
7854
lives_layout_add_separator(LiVESLayout * layout,boolean horizontal)7855 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_layout_add_separator(LiVESLayout * layout, boolean horizontal) {
7856 LiVESWidget *separator;
7857 LiVESJustification woj = widget_opts.justify;
7858 widget_opts.justify = LIVES_JUSTIFY_CENTER;
7859 if (horizontal) separator = lives_layout_pack(LIVES_HBOX(lives_layout_hbox_new(layout)), lives_vseparator_new());
7860 else separator = add_hsep_to_box(LIVES_BOX(lives_layout_expansion_row_new(layout, NULL)));
7861 widget_opts.justify = woj;
7862 return separator;
7863 }
7864
7865 ////////////////////////////////////////////////////////////////////
7866
add_warn_image(LiVESWidget * widget,LiVESWidget * hbox)7867 static LiVESWidget *add_warn_image(LiVESWidget * widget, LiVESWidget * hbox) {
7868 LiVESWidget *warn_image = lives_image_new_from_stock(LIVES_STOCK_DIALOG_WARNING,
7869 widget_opts.icon_size);
7870 if (hbox) {
7871 if (!widget_opts.pack_end)
7872 lives_box_pack_start(LIVES_BOX(hbox), warn_image, FALSE, FALSE, 4);
7873 else
7874 lives_box_pack_end(LIVES_BOX(hbox), warn_image, FALSE, FALSE, 4);
7875 }
7876 lives_widget_set_no_show_all(warn_image, TRUE);
7877 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(warn_image), TTIPS_OVERRIDE_KEY, warn_image);
7878 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget), WARN_IMAGE_KEY, warn_image);
7879 lives_widget_set_sensitive_with(widget, warn_image);
7880 #if GTK_CHECK_VERSION(3, 16, 0)
7881 if (widget_opts.apply_theme) {
7882 set_css_value_direct(warn_image, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
7883 }
7884 #endif
7885 return warn_image;
7886 }
7887
7888
show_warn_image(LiVESWidget * widget,const char * text)7889 WIDGET_HELPER_GLOBAL_INLINE boolean show_warn_image(LiVESWidget * widget, const char *text) {
7890 LiVESWidget *warn_image;
7891 if (!(warn_image = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), WARN_IMAGE_KEY))) return FALSE;
7892 lives_widget_set_tooltip_text(warn_image, text);
7893 lives_widget_set_no_show_all(warn_image, FALSE);
7894 lives_widget_show_all(warn_image);
7895 lives_widget_set_sensitive(warn_image, TRUE);
7896 return TRUE;
7897 }
7898
hide_warn_image(LiVESWidget * widget)7899 WIDGET_HELPER_GLOBAL_INLINE boolean hide_warn_image(LiVESWidget * widget) {
7900 LiVESWidget *warn_image;
7901 if (!(warn_image = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), WARN_IMAGE_KEY))) return FALSE;
7902 lives_widget_set_no_show_all(warn_image, FALSE);
7903 lives_widget_hide(warn_image);
7904 return TRUE;
7905 }
7906
7907
make_inner_hbox(LiVESBox * box,boolean start)7908 static LiVESWidget *make_inner_hbox(LiVESBox * box, boolean start) {
7909 /// create an hbox, this gets packed into box
7910 /// "start" defines whether we pack at start or end
7911 /// if box is a vbox, "start" is ignored, and we pack a second hbox in the first
7912 /// so it is always hbox inside an hbox
7913 ///
7914 /// create a vbox, this is packed into hbox, this allows adding space on either side
7915 ///
7916 /// finally, create another hbox and pack into vbox, this will hold all sub widgets,
7917 /// e.g. labels, buttons, filler
7918 /// this allows for expanding the vertical size, whilst packing sub widgets horizontally
7919
7920 LiVESWidget *hbox = lives_hbox_new(FALSE, 0);
7921 LiVESWidget *vbox = lives_vbox_new(FALSE, 0);
7922
7923 if (widget_opts.apply_theme == 2) lives_widget_apply_theme2(hbox, LIVES_WIDGET_STATE_NORMAL, TRUE);
7924 else lives_widget_apply_theme(hbox, LIVES_WIDGET_STATE_NORMAL);
7925 if (LIVES_IS_HBOX(box)) {
7926 widget_opts.last_container = hbox;
7927 if (!widget_opts.pack_end)
7928 lives_box_pack_start(LIVES_BOX(box), hbox, LIVES_SHOULD_EXPAND_EXTRA_WIDTH,
7929 LIVES_SHOULD_EXPAND_WIDTH, LIVES_SHOULD_EXPAND_FOR(box)
7930 ? widget_opts.packing_width : 0);
7931 else
7932 lives_box_pack_end(LIVES_BOX(box), hbox, LIVES_SHOULD_EXPAND_EXTRA_WIDTH,
7933 LIVES_SHOULD_EXPAND_WIDTH, LIVES_SHOULD_EXPAND_FOR(box)
7934 ? widget_opts.packing_width : 0);
7935 } else {
7936 lives_box_pack_start(LIVES_BOX(box), hbox, FALSE, FALSE, LIVES_SHOULD_EXPAND_FOR(box)
7937 ? widget_opts.packing_height : 0);
7938 box = LIVES_BOX(hbox);
7939 hbox = lives_hbox_new(FALSE, 0);
7940 widget_opts.last_container = hbox;
7941 lives_box_pack_start(LIVES_BOX(box), hbox, FALSE, FALSE, LIVES_SHOULD_EXPAND_FOR(box)
7942 ? widget_opts.packing_width : 0);
7943 }
7944
7945 lives_widget_set_valign(hbox, LIVES_ALIGN_CENTER);
7946
7947 if (start)
7948 lives_box_pack_start(LIVES_BOX(hbox), vbox, LIVES_SHOULD_EXPAND_EXTRA_WIDTH,
7949 LIVES_SHOULD_EXPAND_EXTRA_WIDTH, 0);
7950 else
7951 lives_box_pack_end(LIVES_BOX(hbox), vbox, LIVES_SHOULD_EXPAND_EXTRA_WIDTH,
7952 LIVES_SHOULD_EXPAND_EXTRA_WIDTH, 0);
7953 lives_widget_set_show_hide_parent(vbox);
7954
7955 hbox = lives_hbox_new(FALSE, 0);
7956
7957 if (!LIVES_SHOULD_EXPAND_EXTRA_FOR(vbox)) lives_widget_set_valign(hbox, LIVES_ALIGN_CENTER);
7958 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, LIVES_SHOULD_EXPAND_FOR(vbox) ? widget_opts.packing_height / 2 : 0);
7959 lives_widget_set_show_hide_parent(hbox);
7960 return hbox;
7961 }
7962
7963
lives_widget_set_frozen(LiVESWidget * widget,boolean state)7964 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_frozen(LiVESWidget * widget, boolean state) {
7965 // set insens. but w.out dimming
7966 #if GTK_CHECK_VERSION(3, 16, 0)
7967 if (state) {
7968 set_css_value_direct(widget, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.75");
7969 } else
7970 set_css_value_direct(widget, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
7971 #endif
7972 return lives_widget_set_sensitive(widget, !state);
7973 }
7974
7975
7976 #ifdef USE_SPECIAL_BUTTONS
7977
7978 #define BT_PRE_WIDTH 4.0
7979 #define BT_UNPRE_WIDTH 2.0
7980
lives_painter_psurface_destroy_cb(livespointer data)7981 static void lives_painter_psurface_destroy_cb(livespointer data) {
7982 lives_painter_surface_t **pbsurf = (lives_painter_surface_t **)data;
7983 if (pbsurf) {
7984 lives_painter_surface_t *bsurf = *pbsurf;
7985 if (bsurf) lives_painter_surface_destroy(bsurf);
7986 lives_free(pbsurf);
7987 }
7988 }
7989
lives_widget_object_set_data_psurface(LiVESWidgetObject * obj,const char * key,livespointer data)7990 static void lives_widget_object_set_data_psurface(LiVESWidgetObject * obj, const char *key, livespointer data) {
7991 lives_widget_object_set_data_full(obj, key, data,
7992 (LiVESDestroyNotify)lives_painter_psurface_destroy_cb);
7993 }
7994
sbutt_render(LiVESWidget * sbutt,LiVESWidgetState state,livespointer user_data)7995 void sbutt_render(LiVESWidget * sbutt, LiVESWidgetState state, livespointer user_data) {
7996 if (!is_standard_widget(LIVES_WIDGET(sbutt))) return;
7997 else {
7998 LiVESWidget *widget = lives_bin_get_child(LIVES_BIN(sbutt));
7999 lives_painter_surface_t **pbsurf =
8000 (lives_painter_surface_t **)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
8001 SBUTT_SURFACE_KEY);
8002 state = lives_widget_get_state(sbutt); /// get updated state
8003 if (!pbsurf || !(*pbsurf)) return;
8004 else {
8005 lives_painter_t *cr;
8006 lives_painter_surface_t *bsurf;
8007 LingoLayout *layout =
8008 (LingoLayout *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(sbutt),
8009 SBUTT_LAYOUT_KEY);
8010 lives_colRGBA64_t fg, bg, pab, pab2;
8011 LiVESWidget *toplevel = lives_widget_get_toplevel(widget);
8012 LiVESWidget *deflt = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(toplevel), DEFBUTTON_KEY);
8013 LiVESWidget *defover = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(toplevel), DEFOVERRIDE_KEY);
8014 LiVESPixbuf *pixbuf = NULL;
8015 double offs_x = 0., offs_y = 0;
8016 boolean fake_default = (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(sbutt), SBUTT_FAKEDEF_KEY)
8017 ? TRUE : FALSE);
8018 boolean prelit = (state & LIVES_WIDGET_STATE_PRELIGHT) == 0 ? FALSE : TRUE;
8019 boolean insens = (state & LIVES_WIDGET_STATE_INSENSITIVE) == 0 ? FALSE : TRUE;
8020 boolean focused = lives_widget_is_focus(sbutt);
8021 uint32_t acc;
8022 int themetype;
8023 int width, height;
8024 int lw = 0, lh = 0, x_pos, y_pos, w_, h_;
8025 int pbw = 0, pbh = 0;
8026
8027 if (insens) prelit = focused = FALSE;
8028
8029 pab2.red = pab2.green = pab2.blue = 0;
8030 pab2.alpha = 1.;
8031
8032 themetype = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(sbutt), THEME_KEY));
8033 if (themetype) {
8034 if (themetype == 1) {
8035 widget_color_to_lives_rgba(&bg, &palette->normal_back);
8036 widget_color_to_lives_rgba(&fg, &palette->normal_fore);
8037 } else {
8038 widget_color_to_lives_rgba(&bg, &palette->menu_and_bars);
8039 widget_color_to_lives_rgba(&fg, &palette->menu_and_bars_fore);
8040 }
8041 if (prefs->extra_colours && mainw->pretty_colours) {
8042 widget_color_to_lives_rgba(&pab, &palette->nice1);
8043 widget_color_to_lives_rgba(&pab2, &palette->nice2);
8044 } else {
8045 widget_color_to_lives_rgba(&pab, &palette->menu_and_bars);
8046 widget_color_to_lives_rgba(&pab2, &palette->menu_and_bars);
8047 }
8048 }
8049
8050 bsurf = *pbsurf;
8051
8052 width = lives_widget_get_allocation_width(widget);
8053 height = lives_widget_get_allocation_height(widget);
8054
8055 cr = lives_painter_create_from_surface(bsurf);
8056
8057 if (themetype) {
8058 lives_painter_set_line_width(cr, BT_PRE_WIDTH);
8059 if (prelit) lives_painter_set_source_rgb_from_lives_rgba(cr, &pab);
8060 else lives_painter_set_source_rgb_from_lives_rgba(cr, &bg);
8061 lives_painter_rectangle(cr, 0, 0, width, height);
8062 lives_painter_stroke(cr);
8063 offs_x += BT_PRE_WIDTH;
8064 offs_y += BT_PRE_WIDTH;
8065
8066 lives_painter_set_line_width(cr, BT_UNPRE_WIDTH);
8067 lives_painter_set_source_rgb_from_lives_rgba(cr, &pab);
8068 lives_painter_rectangle(cr, offs_x, offs_y, width - offs_x * 2., height - offs_y * 2.);
8069 lives_painter_stroke(cr);
8070 } else {
8071 offs_x += BT_PRE_WIDTH;
8072 offs_y += BT_PRE_WIDTH;
8073 }
8074
8075 offs_x += BT_UNPRE_WIDTH;
8076 offs_y += BT_UNPRE_WIDTH;
8077
8078 /// account for rounding errors
8079 offs_x -= 2.;
8080 offs_y -= 2.;
8081
8082 if (offs_x < 0.) offs_x = 0.;
8083 if (offs_y < 0.) offs_y = 0.;
8084
8085 lives_painter_rectangle(cr, offs_x, offs_y, width - offs_x * 2., height - offs_y * 2.);
8086 lives_painter_clip(cr);
8087
8088 if (widget_opts.show_button_images
8089 || (pixbuf = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(sbutt), SBUTT_FORCEIMG_KEY))) {
8090 if (!pixbuf) pixbuf = (LiVESPixbuf *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(sbutt),
8091 SBUTT_PIXBUF_KEY);
8092 if (pixbuf) {
8093 pbw = lives_pixbuf_get_width(pixbuf);
8094 pbh = lives_pixbuf_get_height(pixbuf);
8095 }
8096 }
8097
8098 if (!layout) {
8099 const char *text = (const char *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(sbutt),
8100 SBUTT_TXT_KEY);
8101 if (text) {
8102 LiVESWidget *topl;
8103 LingoContext *ctx = gtk_widget_get_pango_context(widget);
8104 char *markup, *full_markup;
8105 layout = pango_layout_new(ctx);
8106 lingo_layout_set_alignment(layout, LINGO_ALIGN_CENTER);
8107
8108 markup = lives_markup_escape_text(text, -1);
8109 full_markup = lives_strdup_printf("<span size=\"%s\">%s</span>", widget_opts.text_size,
8110 markup);
8111
8112 lingo_layout_set_markup_with_accel(layout, full_markup, -1, '_', &acc);
8113 lives_free(markup); lives_free(full_markup);
8114 if (acc) {
8115 if (LIVES_IS_FRAME(toplevel)) topl = lives_bin_get_child(LIVES_BIN(toplevel));
8116 else topl = toplevel;
8117
8118 if (topl && LIVES_IS_WINDOW(topl)) {
8119 LiVESAccelGroup *accel_group =
8120 (LiVESAccelGroup *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(topl), BACCL_GROUP_KEY);
8121 if (!accel_group) {
8122 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(topl), BACCL_GROUP_KEY, accel_group);
8123 accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
8124 lives_window_add_accel_group(LIVES_WINDOW(topl), accel_group);
8125 } else {
8126 uint32_t oaccl = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(topl), BACCL_ACCL_KEY));
8127 if (oaccl) lives_widget_remove_accelerator(sbutt, accel_group, oaccl, (LiVESXModifierType)LIVES_ALT_MASK);
8128 }
8129 lives_widget_add_accelerator(sbutt, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
8130 acc, (LiVESXModifierType)LIVES_ALT_MASK, (LiVESAccelFlags)0);
8131 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(topl), BACCL_ACCL_KEY, LIVES_INT_TO_POINTER(acc));
8132 }
8133 }
8134 lingo_layout_get_size(layout, &w_, &h_);
8135
8136 // scale width, height to pixels
8137 lw = ((double)w_) / (double)LINGO_SCALE;
8138 lh = ((double)h_) / (double)LINGO_SCALE;
8139
8140 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget), SBUTT_LW_KEY,
8141 LIVES_INT_TO_POINTER(lw));
8142 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget), SBUTT_LH_KEY,
8143 LIVES_INT_TO_POINTER(lh));
8144 lives_widget_object_set_data_widget_object(LIVES_WIDGET_OBJECT(widget), SBUTT_LAYOUT_KEY,
8145 (livespointer)layout);
8146 }
8147 } else {
8148 lw = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
8149 SBUTT_LW_KEY));
8150 lh = LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget),
8151 SBUTT_LH_KEY));
8152 }
8153
8154 if (focused || fake_default || (sbutt == deflt && !defover)) {
8155 if (!fake_default && deflt && sbutt != deflt) {
8156 // clear def bg
8157 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(toplevel), DEFOVERRIDE_KEY, sbutt);
8158 sbutt_render(deflt, 0, NULL);
8159 }
8160 if (themetype) {
8161 lives_painter_set_source_rgb_from_lives_rgba(cr, &pab2);
8162 lives_painter_rectangle(cr, offs_x, offs_y, width - offs_x * 2., height - offs_y * 2.);
8163 lives_painter_fill(cr);
8164 }
8165 } else {
8166 if (sbutt == defover) {
8167 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(toplevel), DEFOVERRIDE_KEY, NULL);
8168 if (deflt) sbutt_render(deflt, 0, NULL);
8169 }
8170 if (themetype) {
8171 lives_painter_set_source_rgb_from_lives_rgba(cr, &bg);
8172 lives_painter_rectangle(cr, offs_x, offs_y, width - offs_x * 2., height - offs_y * 2.);
8173 lives_painter_fill(cr);
8174 }
8175 }
8176
8177 // top left of layout
8178 x_pos = (width - lw) >> 1;
8179 y_pos = (height - lh) >> 1;
8180
8181 // if pixbuf, offset a little more
8182 if (pixbuf && lw && layout) {
8183 if (!widget_opts.swap_label)
8184 x_pos -= (pbw + widget_opts.packing_width) >> 1;
8185 else
8186 x_pos += (pbw + widget_opts.packing_width) >> 1;
8187 }
8188
8189 if (lh && lw && layout) {
8190 layout_to_lives_painter(layout, cr, LIVES_TEXT_MODE_FOREGROUND_ONLY, &fg,
8191 &bg, lw, lh, x_pos, y_pos, x_pos, y_pos);
8192 if (LINGO_IS_LAYOUT(layout))
8193 lingo_painter_show_layout(cr, layout);
8194 }
8195
8196 if (pixbuf) {
8197 if (lw && layout) {
8198 // shift to get pixbuf pos
8199 if (!widget_opts.swap_label) {
8200 x_pos += (lw + widget_opts.packing_width);
8201 if (x_pos + pbw + widget_opts.packing_width + widget_opts.border_width < width)
8202 x_pos += widget_opts.packing_width;
8203 } else {
8204 x_pos -= (pbw + widget_opts.packing_width);
8205 if (x_pos > widget_opts.packing_width + widget_opts.border_width)
8206 x_pos -= widget_opts.packing_width;
8207 }
8208 } else x_pos -= pbw >> 1;
8209 y_pos = (height - pbh) >> 1;
8210 lives_painter_set_source_pixbuf(cr, pixbuf, x_pos, y_pos);
8211 lives_painter_rectangle(cr, 0, 0, pbw, pbh);
8212 lives_painter_paint(cr);
8213 }
8214 lives_painter_destroy(cr);
8215 lives_widget_queue_draw(sbutt);
8216 }
8217 }
8218 }
8219
8220
lives_standard_button_set_image(LiVESButton * sbutt,LiVESWidget * img)8221 WIDGET_HELPER_GLOBAL_INLINE boolean lives_standard_button_set_image(LiVESButton * sbutt,
8222 LiVESWidget * img) {
8223 if (!is_standard_widget(LIVES_WIDGET(sbutt))) return lives_button_set_image(sbutt, img);
8224
8225 if (img) {
8226 LiVESPixbuf *pixbuf = lives_image_get_pixbuf(LIVES_IMAGE(img));
8227 if (LIVES_IS_PIXBUF(pixbuf)) lives_widget_object_set_data_widget_object(LIVES_WIDGET_OBJECT(sbutt),
8228 SBUTT_PIXBUF_KEY, (livespointer)pixbuf);
8229 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(sbutt),
8230 SBUTT_FORCEIMG_KEY, pixbuf);
8231 } else {
8232 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(sbutt),
8233 SBUTT_PIXBUF_KEY, NULL);
8234 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(sbutt),
8235 SBUTT_FORCEIMG_KEY, NULL);
8236 }
8237 sbutt_render(LIVES_WIDGET(sbutt), 0, NULL);
8238 return TRUE;
8239 }
8240
8241
lives_standard_button_new(int width,int height)8242 LiVESWidget *lives_standard_button_new(int width, int height) {
8243 lives_painter_surface_t **pbsurf =
8244 (lives_painter_surface_t **)lives_calloc(1, sizeof(lives_painter_surface_t *));
8245 LiVESWidget *button, *da;
8246
8247 button = lives_button_new();
8248
8249 if (widget_opts.apply_theme) {
8250 set_standard_widget(button, TRUE);
8251
8252 if (palette->style & STYLE_LIGHT)
8253 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(button), THEME_KEY,
8254 LIVES_INT_TO_POINTER(2));
8255 else
8256 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(button), THEME_KEY,
8257 LIVES_INT_TO_POINTER(widget_opts.apply_theme));
8258
8259 #if GTK_CHECK_VERSION(3, 16, 0)
8260 set_css_min_size(button, width, height);
8261 set_css_value_direct(button, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8262
8263 lives_widget_set_padding(button, 0);
8264 set_css_value_direct(button, LIVES_WIDGET_STATE_NORMAL, "", "background", "none");
8265 set_css_value_direct(button, LIVES_WIDGET_STATE_NORMAL, "", "border-width", "0px");
8266 #endif
8267 }
8268
8269 da = lives_standard_drawing_area_new(LIVES_GUI_CALLBACK(all_expose), pbsurf);
8270 lives_widget_object_set_data_psurface(LIVES_WIDGET_OBJECT(da),
8271 SBUTT_SURFACE_KEY, (livespointer)pbsurf);
8272
8273 lives_container_add(LIVES_CONTAINER(button), da);
8274 lives_widget_set_show_hide_with(button, da);
8275
8276 lives_widget_set_can_focus_and_default(button);
8277
8278 lives_signal_sync_connect(LIVES_GUI_OBJECT(button), LIVES_WIDGET_STATE_CHANGED_SIGNAL,
8279 LIVES_GUI_CALLBACK(sbutt_render), NULL);
8280 #ifdef USE_SPECIAL_BUTTONS
8281 lives_widget_apply_theme(button, LIVES_WIDGET_STATE_NORMAL);
8282 #endif
8283 lives_widget_set_app_paintable(button, TRUE);
8284 lives_widget_set_app_paintable(da, TRUE);
8285 lives_widget_set_size_request(button, width, height);
8286
8287 return button;
8288 }
8289
lives_standard_button_set_label(LiVESButton * sbutt,const char * txt)8290 WIDGET_HELPER_GLOBAL_INLINE boolean lives_standard_button_set_label(LiVESButton * sbutt,
8291 const char *txt) {
8292 if (!is_standard_widget(LIVES_WIDGET(sbutt))) return lives_button_set_label(sbutt, txt);
8293 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(sbutt), SBUTT_LAYOUT_KEY, NULL);
8294 lives_widget_object_set_data_auto(LIVES_WIDGET_OBJECT(sbutt), SBUTT_TXT_KEY,
8295 txt ? lives_strdup(txt) : NULL);
8296 lives_widget_queue_draw(LIVES_WIDGET(sbutt));
8297 return TRUE;
8298 }
8299
lives_standard_button_new_with_label(const char * txt,int width,int height)8300 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_button_new_with_label(const char *txt,
8301 int width, int height) {
8302 LiVESWidget *sbutt = lives_standard_button_new(width, height);
8303 lives_standard_button_set_label(LIVES_BUTTON(sbutt), txt);
8304 return sbutt;
8305 }
8306
lives_standard_button_get_label(LiVESButton * sbutt)8307 WIDGET_HELPER_GLOBAL_INLINE const char *lives_standard_button_get_label(LiVESButton * sbutt) {
8308 if (!is_standard_widget(LIVES_WIDGET(sbutt))) return lives_button_get_label(sbutt);
8309 return lives_widget_object_get_data(LIVES_WIDGET_OBJECT(sbutt), SBUTT_TXT_KEY);
8310 }
8311 #endif
8312
8313
8314
_lives_standard_button_set_full(LiVESWidget * sbutt,LiVESBox * box,boolean fake_default,const char * ttips)8315 static LiVESWidget *_lives_standard_button_set_full(LiVESWidget * sbutt, LiVESBox * box,
8316 boolean fake_default, const char *ttips) {
8317 LiVESWidget *img_tips = NULL, *hbox;
8318
8319 if (ttips) img_tips = lives_widget_set_tooltip_text(sbutt, ttips);
8320
8321 lives_button_set_focus_on_click(LIVES_BUTTON(sbutt), FALSE);
8322
8323 if (box) {
8324 LiVESWidget *layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(box), WH_LAYOUT_KEY);
8325 int packing_width = 0;
8326 boolean expand;
8327
8328 if (layout) {
8329 box = LIVES_BOX(lives_layout_hbox_new(LIVES_TABLE(layout)));
8330 hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
8331 lives_widget_set_show_hide_with(sbutt, hbox);
8332 } else hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
8333
8334 expand = LIVES_SHOULD_EXPAND_EXTRA_FOR(hbox);
8335 if (expand) add_fill_to_box(LIVES_BOX(hbox));
8336 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width;
8337
8338 lives_widget_set_hexpand(sbutt, FALSE);
8339 lives_widget_set_valign(sbutt, LIVES_ALIGN_CENTER);
8340
8341 lives_box_pack_start(LIVES_BOX(hbox), sbutt, LIVES_SHOULD_EXPAND_WIDTH,
8342 expand, packing_width);
8343
8344 if (expand) add_fill_to_box(LIVES_BOX(hbox));
8345 lives_widget_set_show_hide_parent(sbutt);
8346
8347 add_warn_image(sbutt, hbox);
8348 if (img_tips) {
8349 lives_box_pack_start(LIVES_BOX(hbox), img_tips, FALSE, FALSE, widget_opts.packing_width >> 1);
8350 }
8351 }
8352
8353 #ifdef USE_SPECIAL_BUTTONS
8354 if (is_standard_widget(LIVES_WIDGET(sbutt))) {
8355 if (fake_default) {
8356 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(LIVES_WIDGET_OBJECT(sbutt)),
8357 SBUTT_FAKEDEF_KEY, sbutt);
8358 }
8359 sbutt_render(sbutt, 0, NULL);
8360 #endif
8361 }
8362 return sbutt;
8363 }
8364
8365
lives_standard_button_new_full(const char * label,int width,int height,LiVESBox * box,boolean fake_default,const char * ttips)8366 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_button_new_full(const char *label, int width,
8367 int height, LiVESBox * box,
8368 boolean fake_default,
8369 const char *ttips) {
8370 LiVESWidget *sbutt = lives_standard_button_new_with_label(label, width, height);
8371 return _lives_standard_button_set_full(sbutt, box, fake_default, ttips);
8372 }
8373
8374
lives_standard_button_new_from_stock_full(const char * stock_id,const char * label,int width,int height,LiVESBox * box,boolean fake_default,const char * ttips)8375 LiVESWidget *lives_standard_button_new_from_stock_full(const char *stock_id, const char *label,
8376 int width, int height, LiVESBox * box,
8377 boolean fake_default,
8378 const char *ttips) {
8379 LiVESWidget *sbutt = lives_standard_button_new_from_stock(stock_id, label, width, height);
8380 return _lives_standard_button_set_full(sbutt, box, fake_default, ttips);
8381 }
8382
lives_standard_hpaned_new(void)8383 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_hpaned_new(void) {
8384 LiVESWidget *hpaned;
8385 #ifdef GUI_GTK
8386 #if !GTK_CHECK_VERSION(3, 0, 0)
8387 hpaned = lives_hpaned_new();
8388 #else
8389 hpaned = gtk_paned_new(LIVES_ORIENTATION_HORIZONTAL);
8390 gtk_paned_set_wide_handle(GTK_PANED(hpaned), TRUE);
8391 if (widget_opts.apply_theme) {
8392 set_standard_widget(hpaned, TRUE);
8393 #if GTK_CHECK_VERSION(3, 16, 0)
8394 if (prefs->extra_colours && mainw->pretty_colours) {
8395 char *colref = gdk_rgba_to_string(&palette->nice1);
8396 // clear background image
8397 char *tmp = lives_strdup_printf("image(%s)", colref);
8398 set_css_value_direct(hpaned, LIVES_WIDGET_STATE_NORMAL, "separator",
8399 "background-image", tmp);
8400 lives_free(tmp);
8401 lives_free(colref);
8402 }
8403 #endif
8404 }
8405 #endif
8406 #endif
8407 return hpaned;
8408 }
8409
lives_standard_vpaned_new(void)8410 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_vpaned_new(void) {
8411 LiVESWidget *vpaned;
8412 #ifdef GUI_GTK
8413 #if GTK_CHECK_VERSION(3, 0, 0)
8414 vpaned = lives_vpaned_new();
8415 #else
8416 vpaned = gtk_paned_new(LIVES_ORIENTATION_VERTICAL);
8417 gtk_paned_set_wide_handle(GTK_PANED(vpaned), TRUE);
8418 if (widget_opts.apply_theme) {
8419 set_standard_widget(vpaned, TRUE);
8420 #if GTK_CHECK_VERSION(3, 16, 0)
8421 if (prefs->extra_colours && mainw->pretty_colours) {
8422 char *colref = gdk_rgba_to_string(&palette->nice1);
8423 // clear background image
8424 char *tmp = lives_strdup_printf("image(%s)", colref);
8425 set_css_value_direct(vpaned, LIVES_WIDGET_STATE_NORMAL, "separator",
8426 "background-image", tmp);
8427 lives_free(tmp);
8428 lives_free(colref);
8429 }
8430 #endif
8431 }
8432 #endif
8433 #endif
8434 return vpaned;
8435 }
8436
8437
lives_standard_menu_new(void)8438 LiVESWidget *lives_standard_menu_new(void) {
8439 LiVESWidget *menu = lives_menu_new();
8440 if (menu) {
8441 if (widget_opts.apply_theme) {
8442 set_standard_widget(menu, TRUE);
8443 lives_widget_apply_theme2(menu, LIVES_WIDGET_STATE_NORMAL, TRUE);
8444 #if !GTK_CHECK_VERSION(3, 16, 0)
8445 lives_widget_apply_theme_dimmed2(menu, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
8446 set_child_dimmed_colour2(menu, BUTTON_DIM_VAL);
8447 #else
8448 set_css_value_direct(menu, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8449 #endif
8450 }
8451 }
8452 return menu;
8453 }
8454
8455
lives_standard_menu_item_new(void)8456 LiVESWidget *lives_standard_menu_item_new(void) {
8457 LiVESWidget *menuitem = lives_menu_item_new();
8458 if (menuitem) {
8459 if (widget_opts.apply_theme) {
8460 set_standard_widget(menuitem, TRUE);
8461 lives_widget_apply_theme2(menuitem, LIVES_WIDGET_STATE_NORMAL, TRUE);
8462 #if !GTK_CHECK_VERSION(3, 16, 0)
8463 lives_widget_apply_theme_dimmed2(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
8464 set_child_dimmed_colour2(menuitem, BUTTON_DIM_VAL);
8465 #else
8466 set_css_value_direct(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8467 #endif
8468 }
8469 }
8470 return menuitem;
8471 }
8472
8473
lives_standard_menu_item_new_with_label(const char * label)8474 LiVESWidget *lives_standard_menu_item_new_with_label(const char *label) {
8475 LiVESWidget *menuitem = lives_menu_item_new_with_label(label);
8476 if (menuitem) {
8477 if (widget_opts.apply_theme) {
8478 set_standard_widget(menuitem, TRUE);
8479 lives_widget_apply_theme2(menuitem, LIVES_WIDGET_STATE_NORMAL, TRUE);
8480 #if !GTK_CHECK_VERSION(3, 16, 0)
8481 lives_widget_apply_theme_dimmed2(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
8482 set_child_dimmed_colour2(menuitem, BUTTON_DIM_VAL);
8483 #else
8484 set_css_value_direct(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8485 #endif
8486 }
8487 }
8488 return menuitem;
8489 }
8490
8491
lives_standard_image_menu_item_new_with_label(const char * label)8492 LiVESWidget *lives_standard_image_menu_item_new_with_label(const char *label) {
8493 LiVESWidget *menuitem = lives_image_menu_item_new_with_label(label);
8494 if (menuitem) {
8495 if (widget_opts.apply_theme) {
8496 set_standard_widget(menuitem, TRUE);
8497 lives_widget_apply_theme2(menuitem, LIVES_WIDGET_STATE_NORMAL, TRUE);
8498 #if !GTK_CHECK_VERSION(3, 16, 0)
8499 lives_widget_apply_theme_dimmed2(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
8500 set_child_dimmed_colour2(menuitem, BUTTON_DIM_VAL);
8501 #else
8502 set_css_value_direct(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8503 #endif
8504 }
8505 }
8506 return menuitem;
8507 }
8508
8509
8510
lives_standard_image_menu_item_new_from_stock(const char * stock_id,LiVESAccelGroup * accel_group)8511 LiVESWidget *lives_standard_image_menu_item_new_from_stock(const char *stock_id, LiVESAccelGroup * accel_group) {
8512 LiVESWidget *menuitem = lives_image_menu_item_new_from_stock(stock_id, accel_group);
8513 if (menuitem) {
8514 if (widget_opts.apply_theme) {
8515 set_standard_widget(menuitem, TRUE);
8516 lives_widget_apply_theme2(menuitem, LIVES_WIDGET_STATE_NORMAL, TRUE);
8517 #if !GTK_CHECK_VERSION(3, 16, 0)
8518 lives_widget_apply_theme_dimmed2(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
8519 set_child_dimmed_colour2(menuitem, BUTTON_DIM_VAL);
8520 #else
8521 set_css_value_direct(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8522 #endif
8523 }
8524 }
8525 return menuitem;
8526 }
8527
8528
lives_standard_radio_menu_item_new_with_label(LiVESSList * group,const char * label)8529 LiVESWidget *lives_standard_radio_menu_item_new_with_label(LiVESSList * group, const char *label) {
8530 LiVESWidget *menuitem = lives_radio_menu_item_new_with_label(group, label);
8531 if (menuitem) {
8532 if (widget_opts.apply_theme) {
8533 set_standard_widget(menuitem, TRUE);
8534 lives_widget_apply_theme2(menuitem, LIVES_WIDGET_STATE_NORMAL, TRUE);
8535 #if !GTK_CHECK_VERSION(3, 16, 0)
8536 lives_widget_apply_theme_dimmed2(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
8537 set_child_dimmed_colour2(menuitem, BUTTON_DIM_VAL);
8538 #else
8539 set_css_value_direct(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8540 #endif
8541 }
8542 }
8543 return menuitem;
8544 }
8545
8546
lives_standard_check_menu_item_new_with_label(const char * label,boolean active)8547 LiVESWidget *lives_standard_check_menu_item_new_with_label(const char *label, boolean active) {
8548 LiVESWidget *menuitem = lives_check_menu_item_new_with_label(label);
8549 lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(menuitem), active);
8550 if (menuitem) {
8551 if (widget_opts.apply_theme) {
8552 set_standard_widget(menuitem, TRUE);
8553 lives_widget_apply_theme2(menuitem, LIVES_WIDGET_STATE_NORMAL, TRUE);
8554 #if !GTK_CHECK_VERSION(3, 16, 0)
8555 lives_widget_apply_theme_dimmed2(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
8556 set_child_dimmed_colour2(menuitem, BUTTON_DIM_VAL);
8557 #else
8558 set_css_value_direct(menuitem, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8559 #endif
8560 }
8561 }
8562 return menuitem;
8563 }
8564
togglevar_cb(LiVESWidget * w,boolean * var)8565 static void togglevar_cb(LiVESWidget * w, boolean * var) {if (var) *var = !(*var);}
8566
8567 LiVESWidget *
lives_standard_check_menu_item_new_for_var(const char * labeltext,boolean * var,boolean invert)8568 lives_standard_check_menu_item_new_for_var(const char *labeltext, boolean * var, boolean invert) {
8569 LiVESWidget *mi = lives_standard_check_menu_item_new_with_label(labeltext, TRUE);
8570 if (invert) lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mi), !(*var));
8571 else lives_check_menu_item_set_active(LIVES_CHECK_MENU_ITEM(mi), *var);
8572 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(mi), LIVES_WIDGET_TOGGLED_SIGNAL,
8573 LIVES_GUI_CALLBACK(togglevar_cb),
8574 (livespointer)var);
8575 return mi;
8576 }
8577
8578
lives_standard_notebook_new(const LiVESWidgetColor * bg_color,const LiVESWidgetColor * act_color)8579 LiVESWidget *lives_standard_notebook_new(const LiVESWidgetColor * bg_color, const LiVESWidgetColor * act_color) {
8580 LiVESWidget *notebook = lives_notebook_new();
8581
8582 #if GTK_CHECK_VERSION(3, 16, 0)
8583 if (widget_opts.apply_theme) {
8584 char *colref = gdk_rgba_to_string(bg_color);
8585 set_standard_widget(notebook, TRUE);
8586 // clear background image
8587 set_css_value_direct(notebook, LIVES_WIDGET_STATE_NORMAL, "*", "background", "none");
8588 set_css_value_direct(notebook, LIVES_WIDGET_STATE_NORMAL, "*", "background-color", colref);
8589 lives_free(colref);
8590 colref = gdk_rgba_to_string(act_color);
8591 set_css_value_direct(notebook, LIVES_WIDGET_STATE_ACTIVE, "*", "background", "none");
8592 set_css_value_direct(notebook, LIVES_WIDGET_STATE_ACTIVE, "*", "background-color", colref);
8593 lives_free(colref);
8594 }
8595 #endif
8596 lives_widget_set_hexpand(notebook, TRUE);
8597 return notebook;
8598 }
8599
8600
lives_standard_label_new(const char * text)8601 LiVESWidget *lives_standard_label_new(const char *text) {
8602 LiVESWidget *label = NULL;
8603 label = lives_label_new(NULL);
8604 // allows markup
8605
8606 if (text) lives_label_set_text(LIVES_LABEL(label), text);
8607 lives_widget_set_text_size(label, LIVES_WIDGET_STATE_NORMAL, widget_opts.text_size);
8608 lives_widget_set_halign(label, lives_justify_to_align(widget_opts.justify));
8609 if (widget_opts.apply_theme) {
8610 set_standard_widget(label, TRUE);
8611 #if !GTK_CHECK_VERSION(3, 24, 0)
8612 // non functional in gtk 3.18
8613 set_child_dimmed_colour(label, BUTTON_DIM_VAL);
8614 set_child_colour(label, TRUE);
8615 #else
8616 set_css_value_direct(label, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
8617 #endif
8618
8619 if (widget_opts.apply_theme == 2) lives_widget_apply_theme2(label, LIVES_WIDGET_STATE_NORMAL, TRUE);
8620 else lives_widget_apply_theme(label, LIVES_WIDGET_STATE_NORMAL);
8621
8622 #if !GTK_CHECK_VERSION(3, 16, 0)
8623 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(label), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
8624 LIVES_GUI_CALLBACK(widget_state_cb),
8625 NULL);
8626 widget_state_cb(LIVES_WIDGET_OBJECT(label), NULL, NULL);
8627 #endif
8628 }
8629 return label;
8630 }
8631
8632
lives_standard_label_new_with_tooltips(const char * text,LiVESBox * box,const char * tips)8633 LiVESWidget *lives_standard_label_new_with_tooltips(const char *text, LiVESBox * box,
8634 const char *tips) {
8635 LiVESWidget *label = lives_standard_label_new(text);
8636 LiVESWidget *img_tips = make_ttips_image_for(label, tips);
8637 LiVESWidget *hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
8638 lives_box_pack_start(LIVES_BOX(hbox), label, FALSE, FALSE, widget_opts.packing_width);
8639 if (img_tips) {
8640 add_warn_image(label, hbox);
8641 lives_box_pack_start(LIVES_BOX(hbox), img_tips, FALSE, FALSE, widget_opts.packing_width >> 1);
8642 }
8643 lives_widget_set_show_hide_parent(label);
8644 return label;
8645 }
8646
8647
lives_big_and_bold(const char * fmt,...)8648 char *lives_big_and_bold(const char *fmt, ...) {
8649 va_list xargs;
8650 char *text, *text2, *text3;
8651 va_start(xargs, fmt);
8652 text = lives_strdup_vprintf(fmt, xargs);
8653 va_end(xargs);
8654 text2 = lives_markup_escape_text(text, -1);
8655 lives_free(text);
8656 text3 = lives_strdup_printf("<big><b>%s</b></big>", text2);
8657 lives_free(text2);
8658 return text3;
8659 }
8660
8661
lives_standard_formatted_label_new(const char * text)8662 LiVESWidget *lives_standard_formatted_label_new(const char *text) {
8663 LiVESWidget *label;
8664 char *form_text;
8665 form_text = lives_strdup_printf("\n%s\n", text);
8666
8667 widget_opts.justify = LIVES_JUSTIFY_CENTER;
8668 widget_opts.mnemonic_label = FALSE;
8669 label = lives_standard_label_new(NULL);
8670 if (widget_opts.use_markup)
8671 lives_label_set_markup(LIVES_LABEL(label), form_text);
8672 else
8673 lives_label_set_text(LIVES_LABEL(label), form_text);
8674 widget_opts.mnemonic_label = TRUE;
8675 widget_opts.justify = LIVES_JUSTIFY_DEFAULT;
8676 if (lives_strlen(text) < MIN_MSG_WIDTH_CHARS) {
8677 lives_label_set_width_chars(LIVES_LABEL(label), MIN_MSG_WIDTH_CHARS);
8678 }
8679
8680 lives_free(form_text);
8681 return label;
8682 }
8683
8684
lives_label_chomp(LiVESLabel * label)8685 LIVES_GLOBAL_INLINE void lives_label_chomp(LiVESLabel * label) {
8686 char *txt = lives_strdup(lives_label_get_text(label));
8687 lives_chomp(txt);
8688 lives_label_set_text(label, txt);
8689 lives_free(txt);
8690 }
8691
8692
lives_standard_drawing_area_new(LiVESGuiCallback callback,lives_painter_surface_t ** ppsurf)8693 LiVESWidget *lives_standard_drawing_area_new(LiVESGuiCallback callback, lives_painter_surface_t **ppsurf) {
8694 LiVESWidget *darea = NULL;
8695 #ifdef GUI_GTK
8696 darea = gtk_drawing_area_new();
8697 lives_widget_set_app_paintable(darea, TRUE);
8698 if (ppsurf) {
8699 if (callback)
8700 #if GTK_CHECK_VERSION(4, 0, 0)
8701 gtk_drawing_area_set_draw_func(darea, callback, (livespointer)ppsurf, NULL);
8702 #else
8703 lives_signal_connect(LIVES_GUI_OBJECT(darea), LIVES_WIDGET_EXPOSE_EVENT,
8704 LIVES_GUI_CALLBACK(callback),
8705 (livespointer)ppsurf);
8706 #endif
8707 lives_signal_sync_connect(LIVES_GUI_OBJECT(darea), LIVES_WIDGET_CONFIGURE_EVENT,
8708 LIVES_GUI_CALLBACK(all_config),
8709 (livespointer)ppsurf);
8710 }
8711 if (widget_opts.apply_theme) {
8712 set_standard_widget(darea, TRUE);
8713 lives_widget_apply_theme(darea, LIVES_WIDGET_STATE_NORMAL);
8714 }
8715 #endif
8716 return darea;
8717 }
8718
8719
lives_standard_label_new_with_mnemonic_widget(const char * text,LiVESWidget * mnemonic_widget)8720 LiVESWidget *lives_standard_label_new_with_mnemonic_widget(const char *text, LiVESWidget * mnemonic_widget) {
8721 LiVESWidget *label = NULL;
8722
8723 label = lives_standard_label_new("");
8724 lives_label_set_text(LIVES_LABEL(label), text);
8725
8726 if (mnemonic_widget) lives_label_set_mnemonic_widget(LIVES_LABEL(label), mnemonic_widget);
8727
8728 return label;
8729 }
8730
8731
lives_standard_frame_new(const char * labeltext,float xalign,boolean invis)8732 LiVESWidget *lives_standard_frame_new(const char *labeltext, float xalign, boolean invis) {
8733 LiVESWidget *frame = lives_frame_new(NULL);
8734 LiVESWidget *label = NULL;
8735
8736 if (LIVES_SHOULD_EXPAND)
8737 lives_container_set_border_width(LIVES_CONTAINER(frame), widget_opts.border_width);
8738
8739 if (labeltext) {
8740 label = lives_standard_label_new(labeltext);
8741 lives_frame_set_label_widget(LIVES_FRAME(frame), label);
8742 }
8743
8744 widget_opts.last_label = label;
8745
8746 if (invis) lives_frame_set_shadow_type(LIVES_FRAME(frame), LIVES_SHADOW_NONE);
8747
8748 if (widget_opts.apply_theme) {
8749 set_standard_widget(frame, TRUE);
8750 lives_widget_apply_theme(frame, LIVES_WIDGET_STATE_NORMAL);
8751 lives_widget_set_text_color(frame, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
8752
8753 #if !GTK_CHECK_VERSION(3, 24, 0)
8754 if (prefs->extra_colours && mainw->pretty_colours)
8755 lives_widget_set_bg_color(frame, LIVES_WIDGET_STATE_NORMAL, &palette->nice1);
8756 else
8757 lives_widget_set_bg_color(frame, LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars);
8758 #else
8759 if (prefs->extra_colours && mainw->pretty_colours) {
8760 char *colref = gdk_rgba_to_string(&palette->nice1);
8761 set_css_value_direct(frame, LIVES_WIDGET_STATE_NORMAL, "border",
8762 "border-color", colref);
8763 lives_free(colref);
8764 } else {
8765 char *colref = gdk_rgba_to_string(&palette->menu_and_bars);
8766 set_css_value_direct(frame, LIVES_WIDGET_STATE_NORMAL, "border",
8767 "border-color", colref);
8768 lives_free(colref);
8769 }
8770 #endif
8771 }
8772 if (xalign >= 0.) lives_frame_set_label_align(LIVES_FRAME(frame), xalign, 0.5);
8773
8774 return frame;
8775 }
8776
8777
lives_justify_to_align(LiVESJustification justify)8778 WIDGET_HELPER_GLOBAL_INLINE LiVESAlign lives_justify_to_align(LiVESJustification justify) {
8779 if (justify == LIVES_JUSTIFY_DEFAULT) return LIVES_ALIGN_START;
8780 if (justify == LIVES_JUSTIFY_CENTER) return LIVES_ALIGN_CENTER;
8781 else return LIVES_ALIGN_END;
8782 }
8783
8784
lives_get_scroll_direction(LiVESXEventScroll * event)8785 WIDGET_HELPER_GLOBAL_INLINE LiVESScrollDirection lives_get_scroll_direction(LiVESXEventScroll * event) {
8786 #ifdef GUI_GTK
8787 #if GTK_CHECK_VERSION(3, 4, 0)
8788 double dx, dy;
8789 if (gdk_event_get_scroll_deltas(LIVES_XEVENT(event), &dx, &dy)) {
8790 if (dy < 0.) return LIVES_SCROLL_UP;
8791 if (dy > 0.) return LIVES_SCROLL_DOWN;
8792 }
8793 #endif
8794 #if GTK_CHECK_VERSION(3, 2, 0)
8795 LiVESScrollDirection direction;
8796 gdk_event_get_scroll_direction(LIVES_XEVENT(event), &direction);
8797 return direction;
8798 #else
8799 return event->direction;
8800 #endif
8801 #endif
8802 return LIVES_SCROLL_UP;
8803 }
8804
8805
_make_label_eventbox(const char * labeltext,LiVESWidget * widget,boolean add_sens)8806 static LiVESWidget *_make_label_eventbox(const char *labeltext, LiVESWidget * widget, boolean add_sens) {
8807 LiVESWidget *label;
8808 LiVESWidget *eventbox = lives_event_box_new();
8809 if (widget) lives_tooltips_copy(eventbox, widget);
8810 if (widget && widget_opts.mnemonic_label && labeltext) {
8811 label = lives_standard_label_new_with_mnemonic_widget(labeltext, widget);
8812 } else label = lives_standard_label_new(labeltext);
8813
8814 widget_opts.last_label = label;
8815 lives_container_add(LIVES_CONTAINER(eventbox), label);
8816 lives_widget_set_halign(label, lives_justify_to_align(widget_opts.justify));
8817
8818 if (widget && (LIVES_IS_TOGGLE_BUTTON(widget) || LIVES_IS_TOGGLE_TOOL_BUTTON(widget))) {
8819 lives_signal_sync_connect(LIVES_GUI_OBJECT(eventbox), LIVES_WIDGET_BUTTON_PRESS_EVENT,
8820 LIVES_GUI_CALLBACK(label_act_toggle),
8821 widget);
8822 }
8823 if (add_sens) {
8824 lives_widget_set_sensitive_with(widget, eventbox);
8825 lives_widget_set_sensitive_with(eventbox, label);
8826 }
8827 lives_widget_set_show_hide_with(widget, eventbox);
8828 lives_widget_set_show_hide_with(eventbox, label);
8829 if (widget_opts.apply_theme) {
8830 // default themeing
8831 lives_widget_apply_theme(eventbox, LIVES_WIDGET_STATE_NORMAL);
8832 lives_widget_apply_theme(eventbox, LIVES_WIDGET_STATE_INSENSITIVE);
8833
8834 #if !GTK_CHECK_VERSION(3, 16, 0)
8835 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(label), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
8836 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
8837 #endif
8838 }
8839 return eventbox;
8840 }
8841
make_label_eventbox(const char * labeltext,LiVESWidget * widget)8842 WIDGET_HELPER_LOCAL_INLINE LiVESWidget *make_label_eventbox(const char *labeltext, LiVESWidget * widget) {
8843 return _make_label_eventbox(labeltext, widget, TRUE);
8844 }
8845
8846
sens_insens_cb(LiVESWidgetObject * object,livespointer pspec,livespointer user_data)8847 static void sens_insens_cb(LiVESWidgetObject * object, livespointer pspec, livespointer user_data) {
8848 LiVESWidget *widget = (LiVESWidget *)object;
8849 LiVESWidget *other = (LiVESWidget *)user_data;
8850 boolean sensitive = lives_widget_get_sensitive(widget);
8851 if (lives_widget_get_sensitive(other) != sensitive) {
8852 lives_widget_set_sensitive(other, sensitive);
8853 }
8854 }
8855
8856
lives_widget_set_sensitive_with(LiVESWidget * w1,LiVESWidget * w2)8857 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_sensitive_with(LiVESWidget * w1, LiVESWidget * w2) {
8858 // set w2 sensitivity == w1
8859 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(w1), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
8860 LIVES_GUI_CALLBACK(sens_insens_cb),
8861 (livespointer)w2);
8862 return TRUE;
8863 }
8864
8865
lives_widget_show_all_cb(LiVESWidget * other,livespointer user_data)8866 static void lives_widget_show_all_cb(LiVESWidget * other, livespointer user_data) {
8867 LiVESWidget *controller;
8868
8869 if (LIVES_IS_WIDGET_OBJECT(other)) {
8870 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(other), SHOWALL_OVERRIDE_KEY)) return;
8871 controller = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(other),
8872 SHOWHIDE_CONTROLLER_KEY);
8873 if (controller) {
8874 if (lives_widget_get_no_show_all(controller)) {
8875 lives_widget_set_no_show_all(other, TRUE);
8876 lives_widget_hide(other);
8877 return;
8878 }
8879 }
8880 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(other), TTIPS_HIDE_KEY)) {
8881 if (prefs->show_tooltips) {
8882 lives_widget_set_no_show_all(other, FALSE);
8883 lives_widget_show(other);
8884 }
8885 return;
8886 }
8887
8888 if (controller && !lives_widget_get_no_show_all(controller)) {
8889 if (lives_widget_get_no_show_all(other)) {
8890 lives_widget_set_no_show_all(other, FALSE);
8891 }
8892 }
8893 /* if (!lives_widget_is_visible(widget)) { */
8894 /* lives_widget_show_all(widget); */
8895 /* } */
8896 if (!lives_widget_is_visible(other)) {
8897 lives_widget_show_all(other);
8898 }
8899 }
8900 }
8901
lives_widget_set_show_hide_with(LiVESWidget * widget,LiVESWidget * other)8902 boolean lives_widget_set_show_hide_with(LiVESWidget * widget, LiVESWidget * other) {
8903 // show / hide the other widget when and only when the child is shown / hidden
8904 if (!widget || !other) return FALSE;
8905 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(other),
8906 SHOWHIDE_CONTROLLER_KEY, widget);
8907 if (!widget_opts.no_gui) {
8908 lives_signal_sync_connect(LIVES_GUI_OBJECT(other), LIVES_WIDGET_SHOW_SIGNAL,
8909 LIVES_GUI_CALLBACK(lives_widget_show_all_cb),
8910 (livespointer)(widget));
8911
8912 lives_signal_sync_connect_swapped(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_SHOW_SIGNAL,
8913 LIVES_GUI_CALLBACK(lives_widget_show_all_cb),
8914 (livespointer)(other));
8915
8916 lives_signal_sync_connect_swapped(LIVES_GUI_OBJECT(widget), LIVES_WIDGET_HIDE_SIGNAL,
8917 LIVES_GUI_CALLBACK(lives_widget_hide),
8918 (livespointer)(other));
8919 }
8920 return TRUE;
8921 }
8922
8923
lives_widget_unset_show_hide_with(LiVESWidget * widget,LiVESWidget * other)8924 boolean lives_widget_unset_show_hide_with(LiVESWidget * widget, LiVESWidget * other) {
8925 // show / hide the other widget when and only when the child is shown / hidden
8926 if (!widget || !other) return FALSE;
8927 lives_signal_handlers_sync_disconnect_by_func
8928 (widget, LIVES_GUI_CALLBACK(lives_widget_show_all_cb), (livespointer)other);
8929 lives_signal_handlers_sync_disconnect_by_func
8930 (other, LIVES_GUI_CALLBACK(lives_widget_show_all_cb), (livespointer)widget);
8931 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(other),
8932 SHOWHIDE_CONTROLLER_KEY, NULL);
8933 return TRUE;
8934 }
8935
8936
lives_widget_set_show_hide_parent(LiVESWidget * widget)8937 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_show_hide_parent(LiVESWidget * widget) {
8938 LiVESWidget *parent = lives_widget_get_parent(widget);
8939 if (parent) return lives_widget_set_show_hide_with(widget, parent);
8940 return FALSE;
8941 }
8942
8943
lives_standard_switch_new(const char * labeltext,boolean active,LiVESBox * box,const char * tooltip)8944 LiVESWidget *lives_standard_switch_new(const char *labeltext, boolean active, LiVESBox * box,
8945 const char *tooltip) {
8946 LiVESWidget *swtch = NULL;
8947 #if !LIVES_HAS_SWITCH_WIDGET
8948 return lives_standard_check_button_new(labeltext, active, box, tooltip);
8949 #else
8950 LiVESWidget *eventbox = NULL;
8951 LiVESWidget *container = NULL;
8952 LiVESWidget *hbox;
8953 LiVESWidget *img_tips = NULL;
8954
8955 #if GTK_CHECK_VERSION(3, 14, 0)
8956 char *colref;
8957 #endif
8958 //char *tmp;
8959
8960 boolean expand;
8961
8962 swtch = lives_switch_new();
8963
8964 widget_opts.last_label = NULL;
8965
8966 if (tooltip) img_tips = lives_widget_set_tooltip_text(swtch, tooltip);
8967
8968 if (box) {
8969 int packing_width = 0;
8970
8971 if (labeltext) {
8972 eventbox = make_label_eventbox(labeltext, swtch);
8973 lives_widget_set_show_hide_with(swtch, eventbox);
8974 }
8975
8976 hbox = make_inner_hbox(LIVES_BOX(box), !widget_opts.swap_label);
8977 lives_widget_set_show_hide_parent(swtch);
8978 container = widget_opts.last_container;
8979
8980 expand = LIVES_SHOULD_EXPAND_EXTRA_FOR(hbox);
8981 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width;
8982
8983 if (widget_opts.swap_label && eventbox)
8984 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
8985
8986 if (expand) add_fill_to_box(LIVES_BOX(hbox));
8987
8988 lives_box_pack_start(LIVES_BOX(hbox), swtch, expand, expand,
8989 !eventbox ? packing_width : 0);
8990
8991 if (expand) add_fill_to_box(LIVES_BOX(hbox));
8992
8993 if (!widget_opts.swap_label && eventbox)
8994 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
8995
8996 add_warn_image(swtch, hbox);
8997
8998 if (img_tips) {
8999 lives_box_pack_start(LIVES_BOX(hbox), img_tips, FALSE, FALSE, widget_opts.packing_width >> 1);
9000 }
9001 }
9002
9003 if (widget_opts.apply_theme) {
9004 #if GTK_CHECK_VERSION(3, 0, 0)
9005 #if GTK_CHECK_VERSION(3, 16, 0)
9006 char *tmp;
9007 #endif
9008 set_standard_widget(swtch, TRUE);
9009 lives_widget_apply_theme(swtch, LIVES_WIDGET_STATE_NORMAL);
9010 set_css_min_size(swtch, widget_opts.css_min_width, widget_opts.css_min_height);
9011
9012 #if GTK_CHECK_VERSION(3, 16, 0)
9013 if (prefs->extra_colours && mainw->pretty_colours) {
9014 lives_widget_set_border_color(swtch, LIVES_WIDGET_STATE_NORMAL, &palette->nice1);
9015
9016 colref = gdk_rgba_to_string(&palette->menu_and_bars);
9017 tmp = lives_strdup_printf("image(%s)", colref);
9018 set_css_value_direct(swtch, LIVES_WIDGET_STATE_NORMAL, "slider",
9019 "background-image", tmp);
9020 lives_free(tmp);
9021 lives_free(colref);
9022
9023 colref = gdk_rgba_to_string(&palette->nice2);
9024 tmp = lives_strdup_printf("image(%s)", colref);
9025 set_css_value_direct(swtch, LIVES_WIDGET_STATE_INSENSITIVE, "slider",
9026 "background-image", tmp);
9027 lives_free(tmp);
9028 lives_free(colref);
9029
9030 lives_widget_set_border_color(swtch, LIVES_WIDGET_STATE_INSENSITIVE, &palette->nice2);
9031 }
9032 colref = gdk_rgba_to_string(&palette->normal_fore);
9033 tmp = lives_strdup_printf("image(%s)", colref);
9034 set_css_value_direct(swtch, LIVES_WIDGET_STATE_CHECKED, "slider",
9035 "background-image", tmp);
9036 lives_free(tmp);
9037 lives_free(colref);
9038 #endif
9039 #endif
9040 }
9041 lives_switch_set_active(LIVES_SWITCH(swtch), active);
9042 widget_opts.last_container = container;
9043 #endif
9044 return swtch;
9045 }
9046
9047
lives_standard_check_button_new(const char * labeltext,boolean active,LiVESBox * box,const char * tooltip)9048 LiVESWidget *lives_standard_check_button_new(const char *labeltext, boolean active, LiVESBox * box,
9049 const char *tooltip) {
9050 LiVESWidget *checkbutton = NULL;
9051 LiVESWidget *eventbox = NULL;
9052 LiVESWidget *hbox;
9053 LiVESWidget *container = NULL;
9054 LiVESWidget *img_tips = NULL;
9055
9056 #if GTK_CHECK_VERSION(3, 14, 0)
9057 char *colref;
9058 #endif
9059 char *tmp;
9060
9061 boolean expand;
9062
9063 #if LIVES_HAS_SWITCH_WIDGET
9064 if (prefs->cb_is_switch) return lives_standard_switch_new(labeltext, active, box, tooltip);
9065 else
9066 #endif
9067 checkbutton = lives_check_button_new();
9068
9069 widget_opts.last_label = NULL;
9070
9071 if (tooltip) img_tips = lives_widget_set_tooltip_text(checkbutton, tooltip);
9072
9073 if (box) {
9074 int packing_width = 0;
9075
9076 if (labeltext) {
9077 eventbox = make_label_eventbox(labeltext, checkbutton);
9078 lives_widget_set_show_hide_with(checkbutton, eventbox);
9079 }
9080
9081 hbox = make_inner_hbox(LIVES_BOX(box), !widget_opts.swap_label);
9082 lives_widget_set_show_hide_parent(checkbutton);
9083 container = widget_opts.last_container;
9084
9085 expand = LIVES_SHOULD_EXPAND_EXTRA_FOR(hbox);
9086 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width;
9087
9088 if (widget_opts.swap_label && eventbox)
9089 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
9090
9091 if (expand) add_fill_to_box(LIVES_BOX(hbox));
9092
9093 lives_box_pack_start(LIVES_BOX(hbox), checkbutton, expand, expand,
9094 !eventbox ? packing_width : 0);
9095
9096 if (expand) add_fill_to_box(LIVES_BOX(hbox));
9097
9098 if (!widget_opts.swap_label && eventbox)
9099 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
9100
9101 add_warn_image(checkbutton, hbox);
9102
9103 if (img_tips) {
9104 lives_box_pack_start(LIVES_BOX(hbox), img_tips, FALSE, FALSE, widget_opts.packing_width >> 1);
9105 }
9106 }
9107
9108 if (widget_opts.apply_theme) {
9109 set_standard_widget(checkbutton, TRUE);
9110 lives_widget_apply_theme(checkbutton, LIVES_WIDGET_STATE_NORMAL);
9111 #if GTK_CHECK_VERSION(3, 0, 0)
9112 set_css_min_size(checkbutton, widget_opts.css_min_width, widget_opts.css_min_height);
9113 #if GTK_CHECK_VERSION(3, 16, 0)
9114 if (prefs->extra_colours && mainw->pretty_colours) {
9115 if (!(palette->style & STYLE_LIGHT))
9116 colref = gdk_rgba_to_string(&palette->nice2);
9117 else
9118 colref = gdk_rgba_to_string(&palette->menu_and_bars);
9119
9120 tmp = lives_strdup_printf("image(%s)", colref);
9121 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_NORMAL, "check",
9122 "background-image", tmp);
9123 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_CHECKED, "check",
9124 "background-image", tmp);
9125 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_CHECKED, "check",
9126 "border-image", tmp);
9127 lives_free(colref); lives_free(tmp);
9128
9129 colref = gdk_rgba_to_string(&palette->normal_fore);
9130 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_CHECKED, "check",
9131 "color", colref);
9132 lives_free(colref);
9133
9134 /* colref = gdk_rgba_to_string(&palette->nice2); */
9135 /* tmp = lives_strdup_printf("image(%s)", colref); */
9136 /* set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_INSENSITIVE, "check", */
9137 /* "background-image", tmp); */
9138 /* set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_INSENSITIVE, "check", */
9139 /* "border-image", tmp); */
9140 //lives_free(tmp);
9141 } else {
9142 colref = gdk_rgba_to_string(&palette->normal_fore);
9143 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_CHECKED, "check",
9144 "color", colref);
9145 lives_free(colref);
9146
9147 colref = gdk_rgba_to_string(&palette->normal_back);
9148 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_CHECKED, "check",
9149 "background-color", colref);
9150 lives_free(colref);
9151 }
9152 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
9153 #endif
9154 #endif
9155 }
9156
9157 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(checkbutton), active);
9158 widget_opts.last_container = container;
9159 return checkbutton;
9160 }
9161
9162
lives_glowing_check_button_new(const char * labeltext,LiVESBox * box,const char * tooltip,boolean * togglevalue)9163 LiVESWidget *lives_glowing_check_button_new(const char *labeltext, LiVESBox * box, const char *tooltip, boolean * togglevalue) {
9164 boolean active = FALSE;
9165 LiVESWidget *checkbutton;
9166 #if GTK_CHECK_VERSION(3, 16, 0)
9167 char *colref;
9168 #endif
9169 if (togglevalue) active = *togglevalue;
9170
9171 checkbutton = lives_standard_check_button_new(labeltext, active, box, tooltip);
9172 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
9173 LIVES_GUI_CALLBACK(lives_cool_toggled),
9174 togglevalue);
9175 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget_opts.last_label),
9176 THEME_KEY, LIVES_INT_TO_POINTER(2));
9177
9178 if (prefs->lamp_buttons) {
9179 lives_toggle_button_set_mode(LIVES_TOGGLE_BUTTON(checkbutton), FALSE);
9180 lives_widget_set_bg_color(checkbutton, LIVES_WIDGET_STATE_ACTIVE, &palette->light_green);
9181 lives_widget_set_bg_color(checkbutton, LIVES_WIDGET_STATE_NORMAL, &palette->dark_red);
9182 lives_cool_toggled(checkbutton, togglevalue);
9183 lives_signal_sync_connect(LIVES_GUI_OBJECT(checkbutton), LIVES_WIDGET_EXPOSE_EVENT,
9184 LIVES_GUI_CALLBACK(draw_cool_toggle), NULL);
9185 if (widget_opts.apply_theme) {
9186
9187 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_NORMAL, "",
9188 "box-shadow", "4px 0 alpha(white, 0.5)");
9189 #if GTK_CHECK_VERSION(3, 16, 0)
9190 colref = gdk_rgba_to_string(&palette->dark_red);
9191 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_NORMAL, "button",
9192 "color", colref);
9193 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_NORMAL, "button",
9194 "background-color", colref);
9195 lives_free(colref);
9196
9197 /* if (prefs->extra_colours && mainw->pretty_colours) { */
9198 /* colref = gdk_rgba_to_string(&palette->nice3); */
9199 /* set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_CHECKED, "button", */
9200 /* "color", colref); */
9201 /* set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_CHECKED, "button", */
9202 /* "background-color", colref); */
9203 /* lives_free(colref); */
9204 /* } */
9205
9206 set_css_value_direct(checkbutton, LIVES_WIDGET_STATE_NORMAL, "",
9207 "transition-duration", "0.2s");
9208 #endif
9209 }
9210 }
9211 return checkbutton;
9212 }
9213
9214
lives_glowing_tool_button_new(const char * labeltext,LiVESToolbar * tbar,const char * tooltip,boolean * togglevalue)9215 LiVESWidget *lives_glowing_tool_button_new(const char *labeltext, LiVESToolbar * tbar, const char *tooltip,
9216 boolean * togglevalue) {
9217 LiVESToolItem *titem = lives_tool_item_new();
9218 LiVESWidget *hbox = lives_hbox_new(FALSE, 0);
9219 widget_opts.expand = LIVES_EXPAND_DEFAULT_HEIGHT;
9220 LiVESWidget *button = lives_glowing_check_button_new(labeltext, LIVES_BOX(hbox), tooltip, togglevalue);
9221 widget_opts.expand = LIVES_EXPAND_DEFAULT;
9222 lives_container_add(LIVES_CONTAINER(titem), hbox);
9223 if (tbar) lives_toolbar_insert(tbar, titem, -1);
9224 return button;
9225 }
9226
9227
lives_standard_menu_tool_button_new(LiVESWidget * icon,const char * label)9228 LiVESToolItem *lives_standard_menu_tool_button_new(LiVESWidget * icon, const char *label) {
9229 LiVESToolItem *toolitem = NULL;
9230 #ifdef GUI_GTK
9231 toolitem = lives_menu_tool_button_new(icon, label);
9232 if (widget_opts.apply_theme) {
9233 LiVESList *children = lives_container_get_children(LIVES_CONTAINER(toolitem)), *list = children;
9234 set_standard_widget(LIVES_WIDGET(toolitem), TRUE);
9235 lives_widget_set_bg_color(LIVES_WIDGET(toolitem), LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars);
9236 while (list) {
9237 LiVESWidget *widget = (LiVESWidget *)list->data;
9238 if (LIVES_IS_VBOX(widget)) {
9239 LiVESList *children2 = lives_container_get_children(LIVES_CONTAINER(toolitem)), *list2 = children2;
9240 lives_container_set_border_width(LIVES_CONTAINER(widget), 0);
9241 while (list2) {
9242 LiVESWidget *child = (LiVESWidget *)list2->data;
9243 if (LIVES_IS_CONTAINER(child)) lives_container_set_border_width(LIVES_CONTAINER(child), 0);
9244 lives_widget_set_valign(child, LIVES_ALIGN_FILL);
9245 lives_widget_set_halign(child, LIVES_ALIGN_FILL);
9246 lives_widget_set_margin_left(child, 0.);
9247 lives_widget_set_margin_right(child, 0.);
9248 lives_widget_set_margin_top(child, 0.);
9249 lives_widget_set_margin_bottom(child, 0.);
9250 list2 = list2->next;
9251 }
9252 lives_widget_set_bg_color(widget, LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars);
9253 list2 = list2->next;
9254 lives_list_free(children2);
9255 }
9256 list = list->next;
9257 }
9258 lives_list_free(children);
9259 }
9260 #endif
9261 return toolitem;
9262 }
9263
9264
lives_standard_radio_button_new(const char * labeltext,LiVESSList ** rbgroup,LiVESBox * box,const char * tooltip)9265 LiVESWidget *lives_standard_radio_button_new(const char *labeltext, LiVESSList **rbgroup, LiVESBox * box, const char *tooltip) {
9266 LiVESWidget *radiobutton = NULL;
9267
9268 // pack a themed check button into box
9269
9270 LiVESWidget *eventbox = NULL;
9271 LiVESWidget *img_tips = NULL;
9272 LiVESWidget *hbox;
9273
9274 #if GTK_CHECK_VERSION(3, 16, 0)
9275 char *colref, *tmp; //*csstxt;
9276 #endif
9277
9278 boolean expand;
9279
9280 widget_opts.last_label = NULL;
9281
9282 radiobutton = lives_radio_button_new(*rbgroup);
9283
9284 *rbgroup = lives_radio_button_get_group(LIVES_RADIO_BUTTON(radiobutton));
9285
9286 if (tooltip) img_tips = lives_widget_set_tooltip_text(radiobutton, tooltip);
9287
9288 if (box) {
9289 int packing_width = 0;
9290
9291 if (labeltext) {
9292 eventbox = make_label_eventbox(labeltext, radiobutton);
9293 }
9294
9295 hbox = make_inner_hbox(LIVES_BOX(box), !widget_opts.swap_label);
9296 expand = LIVES_SHOULD_EXPAND_EXTRA_FOR(hbox);
9297
9298 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width;
9299
9300 if (widget_opts.swap_label && eventbox)
9301 lives_box_pack_start(LIVES_BOX(hbox), eventbox, TRUE, FALSE, packing_width);
9302
9303 if (expand) add_fill_to_box(LIVES_BOX(hbox));
9304
9305 lives_box_pack_start(LIVES_BOX(hbox), radiobutton, expand, FALSE,
9306 !eventbox ? packing_width : 0);
9307
9308 if (expand) add_fill_to_box(LIVES_BOX(hbox));
9309
9310 if (!widget_opts.swap_label && eventbox)
9311 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
9312
9313 lives_widget_set_show_hide_parent(radiobutton);
9314
9315 add_warn_image(radiobutton, hbox);
9316
9317 if (img_tips) {
9318 lives_box_pack_start(LIVES_BOX(hbox), img_tips, FALSE, FALSE, widget_opts.packing_width >> 1);
9319 }
9320 }
9321
9322 if (widget_opts.apply_theme) {
9323 set_standard_widget(radiobutton, TRUE);
9324 lives_widget_apply_theme(radiobutton, LIVES_WIDGET_STATE_NORMAL);
9325 #if GTK_CHECK_VERSION(3, 16, 0)
9326 if (prefs->extra_colours && mainw->pretty_colours) {
9327
9328 if (!(palette->style & STYLE_LIGHT))
9329 colref = gdk_rgba_to_string(&palette->nice2);
9330 else
9331 colref = gdk_rgba_to_string(&palette->menu_and_bars);
9332 set_css_value_direct(radiobutton, LIVES_WIDGET_STATE_NORMAL, "radio", "color", colref);
9333 tmp = lives_strdup_printf("image(%s)", colref);
9334 set_css_value_direct(radiobutton, LIVES_WIDGET_STATE_NORMAL, "radio",
9335 "background-image", tmp);
9336 lives_free(colref);
9337
9338 if (!(palette->style & STYLE_LIGHT))
9339 colref = gdk_rgba_to_string(&palette->normal_fore);
9340 else {
9341 set_css_value_direct(radiobutton, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.25");
9342 set_css_value_direct(radiobutton, LIVES_WIDGET_STATE_CHECKED, "", "opacity", "0.5");
9343 colref = gdk_rgba_to_string(&palette->nice3);
9344 }
9345 set_css_value_direct(radiobutton, LIVES_WIDGET_STATE_CHECKED, "radio", "color", colref);
9346
9347 tmp = lives_strdup_printf("image(%s)", colref);
9348 set_css_value_direct(radiobutton, LIVES_WIDGET_STATE_CHECKED, "radio",
9349 "background-image", tmp);
9350 /* csstxt = lives_strdup_printf("-gtk-gradient (radial, center center, 0, center center, " */
9351 /* "0.125, to (%s), to (rgba(0,0,0,0)))", colref); */
9352 /* set_css_value_direct(radiobutton, LIVES_WIDGET_STATE_CHECKED, "radio", */
9353 /* "border-image-source", csstxt); */
9354 //lives_free(csstxt);
9355 lives_free(tmp);
9356 lives_free(colref);
9357 }
9358 #endif
9359 }
9360 return radiobutton;
9361 }
9362
9363
lives_spin_button_set_step_increment(LiVESSpinButton * button,double step_increment)9364 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_step_increment(LiVESSpinButton * button, double step_increment) {
9365 #ifdef GUI_GTK
9366 LiVESAdjustment *adj = lives_spin_button_get_adjustment(button);
9367 lives_adjustment_set_step_increment(adj, step_increment);
9368 return TRUE;
9369 #endif
9370 return FALSE;
9371 }
9372
9373
lives_spin_button_set_snap_to_multiples(LiVESSpinButton * button,double mult)9374 WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_snap_to_multiples(LiVESSpinButton * button, double mult) {
9375 #ifdef GUI_GTK
9376 lives_spin_button_set_step_increment(button, mult);
9377 lives_spin_button_set_snap_to_ticks(button, TRUE);
9378 return TRUE;
9379 #endif
9380 return FALSE;
9381 }
9382
9383
calc_spin_button_width(double min,double max,int dp)9384 size_t calc_spin_button_width(double min, double max, int dp) {
9385 char *txt = lives_strdup_printf("%d", (int)max);
9386 size_t maxlen = strlen(txt);
9387 lives_free(txt);
9388 txt = lives_strdup_printf("%d", (int)min);
9389 if (strlen(txt) > maxlen) maxlen = strlen(txt);
9390 lives_free(txt);
9391 if (dp > 0) maxlen += dp + 1;
9392 if (maxlen < MIN_SPINBUTTON_SIZE) return MIN_SPINBUTTON_SIZE;
9393 return maxlen;
9394 }
9395
9396
lives_standard_spin_button_new(const char * labeltext,double val,double min,double max,double step,double page,int dp,LiVESBox * box,const char * tooltip)9397 LiVESWidget *lives_standard_spin_button_new(const char *labeltext, double val, double min,
9398 double max, double step, double page, int dp, LiVESBox * box,
9399 const char *tooltip) {
9400 // pack a themed spin button into box
9401 LiVESWidget *spinbutton = NULL;
9402 LiVESWidget *img_tips = NULL;
9403 LiVESWidget *eventbox = NULL;
9404 LiVESWidget *container = NULL;
9405 LiVESWidget *hbox;
9406 LiVESAdjustment *adj;
9407
9408 #if GTK_CHECK_VERSION(3, 14, 0)
9409 char *colref;
9410 #endif
9411
9412 boolean expand;
9413
9414 int maxlen;
9415 widget_opts.last_label = NULL;
9416
9417 adj = lives_adjustment_new(val, min, max, step, page, 0.);
9418 spinbutton = lives_spin_button_new(adj, 1, dp);
9419
9420 val = lives_spin_button_get_snapval(LIVES_SPIN_BUTTON(spinbutton), val);
9421 lives_spin_button_set_value(LIVES_SPIN_BUTTON(spinbutton), val);
9422 lives_spin_button_update(LIVES_SPIN_BUTTON(spinbutton));
9423 set_standard_widget(spinbutton, TRUE);
9424
9425 if (tooltip) img_tips = lives_widget_set_tooltip_text(spinbutton, tooltip);
9426
9427 maxlen = calc_spin_button_width(min, max, dp);
9428 lives_entry_set_width_chars(LIVES_ENTRY(spinbutton), maxlen);
9429
9430 lives_entry_set_activates_default(LIVES_ENTRY(spinbutton), TRUE);
9431 lives_entry_set_has_frame(LIVES_ENTRY(spinbutton), TRUE);
9432 lives_entry_set_alignment(LIVES_ENTRY(spinbutton), 0.2);
9433 #ifdef GUI_GTK
9434 //gtk_spin_button_set_update_policy(LIVES_SPIN_BUTTON(spinbutton), GTK_UPDATE_ALWAYS);
9435 gtk_spin_button_set_numeric(LIVES_SPIN_BUTTON(spinbutton), TRUE);
9436 gtk_entry_set_overwrite_mode(LIVES_ENTRY(spinbutton), TRUE);
9437 #endif
9438
9439 if (box) {
9440 LiVESWidget *layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(box),
9441 WH_LAYOUT_KEY);
9442 int packing_width = 0;
9443
9444 if (labeltext) {
9445 eventbox = make_label_eventbox(labeltext, spinbutton);
9446 lives_widget_set_show_hide_with(spinbutton, eventbox);
9447 }
9448
9449 hbox = make_inner_hbox(LIVES_BOX(box), widget_opts.swap_label || !eventbox);
9450 lives_widget_set_show_hide_with(spinbutton, hbox);
9451 container = widget_opts.last_container;
9452
9453 expand = LIVES_SHOULD_EXPAND_EXTRA_FOR(hbox);
9454
9455 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width;
9456
9457 if (!widget_opts.swap_label && eventbox) {
9458 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
9459
9460 if (layout) {
9461 // pack end because box is a layout hbox
9462 lives_widget_set_pack_type(LIVES_BOX(box), container, LIVES_PACK_END);
9463 box = LIVES_BOX(lives_layout_hbox_new(LIVES_TABLE(layout)));
9464 hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
9465 }
9466 }
9467
9468 if (expand) add_fill_to_box(LIVES_BOX(hbox));
9469
9470 lives_box_pack_start(LIVES_BOX(hbox), spinbutton, expand, TRUE, packing_width);
9471
9472 if (expand) add_fill_to_box(LIVES_BOX(hbox));
9473
9474 if (widget_opts.swap_label && eventbox) {
9475 if (layout) {
9476 box = LIVES_BOX(lives_layout_hbox_new(LIVES_TABLE(layout)));
9477 hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
9478 lives_widget_set_show_hide_with(spinbutton, hbox);
9479 }
9480 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
9481 }
9482 lives_widget_set_show_hide_parent(spinbutton);
9483
9484 add_warn_image(spinbutton, hbox);
9485
9486 if (img_tips) {
9487 lives_box_pack_start(LIVES_BOX(hbox), img_tips, FALSE, FALSE, widget_opts.packing_width >> 1);
9488 }
9489 }
9490
9491 if (widget_opts.apply_theme) {
9492 set_css_min_size(spinbutton, widget_opts.css_min_width, ((widget_opts.css_min_height * 3 + 3) >> 2) << 1);
9493
9494 #if !GTK_CHECK_VERSION(3, 16, 0)
9495 // breaks button insens !
9496 lives_widget_apply_theme2(LIVES_WIDGET(spinbutton), LIVES_WIDGET_STATE_NORMAL, TRUE);
9497 lives_widget_apply_theme_dimmed2(spinbutton, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
9498 #else
9499 lives_widget_apply_theme2(LIVES_WIDGET(spinbutton), LIVES_WIDGET_STATE_NORMAL, FALSE);
9500
9501 colref = gdk_rgba_to_string(&palette->normal_fore);
9502 set_css_value_direct(spinbutton, LIVES_WIDGET_STATE_NORMAL, "", "color", colref);
9503 lives_free(colref);
9504
9505 set_css_value_direct(spinbutton, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
9506 set_css_value_direct(spinbutton, LIVES_WIDGET_STATE_INSENSITIVE, "button", "opacity", "0.5");
9507
9508 if (prefs->extra_colours && mainw->pretty_colours) {
9509 char *tmp;
9510 colref = gdk_rgba_to_string(&palette->nice1);
9511 set_css_value_direct(spinbutton, LIVES_WIDGET_STATE_NORMAL, "", "border-color", colref);
9512 tmp = lives_strdup_printf("0 0 0 1px %s inset", colref);
9513 set_css_value_direct(spinbutton, LIVES_WIDGET_STATE_FOCUSED, "", "box-shadow", tmp);
9514 lives_free(tmp);
9515 lives_free(colref);
9516 colref = gdk_rgba_to_string(&palette->nice2);
9517 set_css_value_direct(spinbutton, LIVES_WIDGET_STATE_NORMAL, "", "caret-color", colref);
9518 set_css_value_direct(spinbutton, LIVES_WIDGET_STATE_NORMAL, "entry selection", "background-color", colref);
9519 lives_free(colref);
9520 colref = gdk_rgba_to_string(&palette->normal_fore);
9521 set_css_value_direct(spinbutton, LIVES_WIDGET_STATE_NORMAL, "entry selection", "color", colref);
9522 lives_free(colref);
9523 }
9524 #endif
9525 set_child_dimmed_colour2(spinbutton, BUTTON_DIM_VAL);// insens, themecols 1, child only
9526 }
9527
9528 widget_opts.last_container = container;
9529 return spinbutton;
9530 }
9531
9532
setminsz(LiVESWidget * widget,livespointer data)9533 static void setminsz(LiVESWidget * widget, livespointer data) {
9534 set_css_min_size(widget, widget_opts.css_min_width, ((widget_opts.css_min_height * 3 + 3) >> 2) << 1);
9535 if (LIVES_IS_BUTTON(widget)) {
9536 set_css_value_direct(widget, LIVES_WIDGET_STATE_NORMAL, "", "padding-top", "0");
9537 set_css_value_direct(widget, LIVES_WIDGET_STATE_NORMAL, "", "padding-bottom", "0");
9538 }
9539 if (LIVES_IS_CONTAINER(widget)) {
9540 lives_container_forall(LIVES_CONTAINER(widget), setminsz, NULL);
9541 }
9542 }
9543
lives_standard_combo_new(const char * labeltext,LiVESList * list,LiVESBox * box,const char * tooltip)9544 LiVESWidget *lives_standard_combo_new(const char *labeltext, LiVESList * list, LiVESBox * box, const char *tooltip) {
9545 LiVESWidget *combo = NULL;
9546 // pack a themed combo box into box
9547
9548 // seems like it is not possible to set the arrow colours
9549 // nor the entireity of the background for the popup list
9550
9551 LiVESWidget *eventbox = NULL;
9552 LiVESWidget *container = NULL;
9553 LiVESWidget *hbox;
9554 LiVESWidget *img_tips = NULL;
9555 LiVESEntry *entry;
9556
9557 boolean expand;
9558
9559 widget_opts.last_label = NULL;
9560
9561 combo = lives_combo_new();
9562
9563 if (tooltip) img_tips = lives_widget_set_tooltip_text(combo, tooltip);
9564
9565 entry = (LiVESEntry *)lives_combo_get_entry(LIVES_COMBO(combo));
9566 lives_widget_set_text_size(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_NORMAL, widget_opts.text_size);
9567
9568 lives_entry_set_has_frame(entry, TRUE);
9569 lives_entry_set_editable(LIVES_ENTRY(entry), FALSE);
9570 lives_entry_set_activates_default(entry, TRUE);
9571 lives_entry_set_width_chars(LIVES_ENTRY(entry), SHORT_ENTRY_WIDTH);
9572
9573 lives_widget_set_sensitive_with(LIVES_WIDGET(entry), combo);
9574 lives_widget_set_sensitive_with(combo, LIVES_WIDGET(entry));
9575
9576 lives_widget_set_can_focus(LIVES_WIDGET(entry), FALSE);
9577
9578 lives_combo_set_focus_on_click(LIVES_COMBO(combo), FALSE);
9579
9580 lives_widget_add_events(LIVES_WIDGET(entry), LIVES_BUTTON_RELEASE_MASK);
9581 lives_signal_sync_connect_swapped(LIVES_GUI_OBJECT(entry), LIVES_WIDGET_BUTTON_RELEASE_EVENT,
9582 LIVES_GUI_CALLBACK(lives_combo_popup), combo);
9583
9584 if (box) {
9585 LiVESWidget *layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(box), WH_LAYOUT_KEY);
9586 int packing_width = 0;
9587
9588 if (labeltext) {
9589 eventbox = make_label_eventbox(labeltext, LIVES_WIDGET(entry));
9590 }
9591
9592 hbox = make_inner_hbox(LIVES_BOX(box), widget_opts.swap_label || !eventbox);
9593 lives_widget_set_show_hide_with(combo, hbox);
9594 container = widget_opts.last_container;
9595
9596 expand = LIVES_SHOULD_EXPAND_EXTRA_FOR(hbox);
9597 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width;
9598
9599 if (!widget_opts.swap_label && eventbox) {
9600 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
9601 if (layout) {
9602 // pack end because box is a layout hbox
9603 lives_widget_set_pack_type(LIVES_BOX(box), container, LIVES_PACK_END);
9604 box = LIVES_BOX(lives_layout_hbox_new(LIVES_TABLE(layout)));
9605 hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
9606 }
9607 }
9608
9609 if (expand) add_fill_to_box(LIVES_BOX(hbox));
9610
9611 lives_widget_set_hexpand(combo, FALSE);
9612 lives_widget_set_valign(combo, LIVES_ALIGN_CENTER);
9613 lives_box_pack_start(LIVES_BOX(hbox), combo, LIVES_SHOULD_EXPAND_WIDTH,
9614 expand, !eventbox ? packing_width : 0);
9615
9616 if (expand) add_fill_to_box(LIVES_BOX(hbox));
9617
9618 if (widget_opts.swap_label && eventbox) {
9619 if (layout) {
9620 box = LIVES_BOX(lives_layout_hbox_new(LIVES_TABLE(layout)));
9621 hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
9622 lives_widget_set_show_hide_with(combo, hbox);
9623 }
9624 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, 0);
9625 }
9626 lives_widget_set_show_hide_parent(combo);
9627
9628 add_warn_image(combo, hbox);
9629
9630 if (img_tips) {
9631 lives_box_pack_start(LIVES_BOX(hbox), img_tips, FALSE, FALSE, widget_opts.packing_width >> 1);
9632 }
9633 }
9634
9635 if (list) {
9636 lives_combo_populate(LIVES_COMBO(combo), list);
9637 lives_combo_set_active_index(LIVES_COMBO(combo), 0);
9638 }
9639
9640 if (widget_opts.apply_theme) {
9641 set_standard_widget(combo, TRUE);
9642 set_child_alt_colour(combo, TRUE);
9643
9644 #if GTK_CHECK_VERSION(3, 0, 0)
9645 set_css_min_size(combo, widget_opts.css_min_width, ((widget_opts.css_min_height * 3 + 3) >> 2) << 1);
9646 lives_container_forall(LIVES_CONTAINER(combo), setminsz, NULL);
9647
9648 set_css_value_direct(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_NORMAL, "", "border-radius", "5px");
9649
9650 #if !GTK_CHECK_VERSION(3, 16, 0)
9651 set_child_dimmed_colour(combo, BUTTON_DIM_VAL); // insens, themecols 1, child only
9652 #else
9653 set_css_value_direct(combo, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
9654 if (prefs->extra_colours && mainw->pretty_colours) {
9655 char *tmp;
9656 char *colref = gdk_rgba_to_string(&palette->nice1);
9657 set_css_value_direct(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_NORMAL, "", "border-color", colref);
9658 tmp = lives_strdup_printf("0 0 0 1px %s inset", colref);
9659 set_css_value_direct(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_FOCUSED, "", "box-shadow", tmp);
9660 lives_free(tmp);
9661 lives_free(colref);
9662 }
9663 #endif
9664 #endif
9665 #if !GTK_CHECK_VERSION(3, 16, 0)
9666 lives_widget_apply_theme_dimmed(combo, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
9667 lives_widget_apply_theme_dimmed(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
9668 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(entry), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
9669 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
9670 widget_state_cb(LIVES_WIDGET_OBJECT(entry), NULL, NULL);
9671 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(combo), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
9672 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
9673 widget_state_cb(LIVES_WIDGET_OBJECT(combo), NULL, NULL);
9674 #endif
9675 }
9676 widget_opts.last_container = container;
9677 return combo;
9678 }
9679
9680
lives_standard_combo_new_with_model(LiVESTreeModel * model,LiVESBox * box)9681 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_combo_new_with_model(LiVESTreeModel * model, LiVESBox * box) {
9682 LiVESWidget *combo = lives_standard_combo_new(NULL, NULL, box, NULL);
9683 lives_combo_set_model(LIVES_COMBO(combo), model);
9684 return combo;
9685 }
9686
9687
lives_standard_entry_new(const char * labeltext,const char * txt,int dispwidth,int maxchars,LiVESBox * box,const char * tooltip)9688 LiVESWidget *lives_standard_entry_new(const char *labeltext, const char *txt, int dispwidth, int maxchars,
9689 LiVESBox * box, const char *tooltip) {
9690 LiVESWidget *entry = NULL;
9691 LiVESWidget *img_tips = NULL;
9692 LiVESWidget *container = NULL;
9693 LiVESWidget *hbox = NULL;
9694 LiVESWidget *eventbox = NULL;
9695
9696 boolean expand;
9697
9698 widget_opts.last_label = NULL;
9699
9700 entry = lives_entry_new();
9701 lives_widget_set_valign(entry, LIVES_ALIGN_CENTER);
9702
9703 lives_widget_set_text_size(entry, LIVES_WIDGET_STATE_NORMAL, widget_opts.text_size);
9704
9705 if (tooltip) img_tips = lives_widget_set_tooltip_text(entry, tooltip);
9706
9707 if (txt) lives_entry_set_text(LIVES_ENTRY(entry), txt);
9708
9709 if (dispwidth != -1) lives_entry_set_width_chars(LIVES_ENTRY(entry), dispwidth);
9710 else {
9711 if (LIVES_SHOULD_EXPAND_EXTRA_WIDTH) lives_entry_set_width_chars(LIVES_ENTRY(entry), MEDIUM_ENTRY_WIDTH);
9712 else if (LIVES_SHOULD_EXPAND_WIDTH) lives_entry_set_width_chars(LIVES_ENTRY(entry), MEDIUM_ENTRY_WIDTH);
9713 }
9714
9715 if (maxchars != -1) lives_entry_set_max_length(LIVES_ENTRY(entry), maxchars);
9716
9717 lives_entry_set_activates_default(LIVES_ENTRY(entry), TRUE);
9718 lives_entry_set_has_frame(LIVES_ENTRY(entry), TRUE);
9719
9720 //lives_widget_set_halign(entry, LIVES_ALIGN_START); // NO ! - causes entry to shrink
9721 if (widget_opts.justify == LIVES_JUSTIFY_START) {
9722 lives_entry_set_alignment(LIVES_ENTRY(entry), 0.);
9723 }
9724 if (widget_opts.justify == LIVES_JUSTIFY_CENTER) {
9725 lives_entry_set_alignment(LIVES_ENTRY(entry), 0.5);
9726 }
9727 if (widget_opts.justify == LIVES_JUSTIFY_END) {
9728 lives_entry_set_alignment(LIVES_ENTRY(entry), 1.);
9729 }
9730
9731 if (box) {
9732 LiVESWidget *layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(box),
9733 WH_LAYOUT_KEY);
9734 int packing_width = 0;
9735
9736 if (labeltext) {
9737 eventbox = make_label_eventbox(labeltext, entry);
9738 }
9739
9740 hbox = make_inner_hbox(LIVES_BOX(box), widget_opts.swap_label || !eventbox);
9741 lives_widget_set_show_hide_with(entry, hbox);
9742 container = widget_opts.last_container;
9743
9744 expand = LIVES_SHOULD_EXPAND_EXTRA_FOR(hbox);
9745
9746 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width;
9747
9748 if (!widget_opts.swap_label && eventbox) {
9749 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
9750
9751 if (layout) {
9752 // pack end because box is a layout hbox
9753 lives_widget_set_pack_type(LIVES_BOX(box), container, LIVES_PACK_END);
9754 box = LIVES_BOX(lives_layout_hbox_new(LIVES_TABLE(layout)));
9755 hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
9756 }
9757 }
9758
9759 if (expand && dispwidth != -1) add_fill_to_box(LIVES_BOX(hbox));
9760
9761 lives_box_pack_start(LIVES_BOX(hbox), entry, LIVES_SHOULD_EXPAND_WIDTH, dispwidth == -1, packing_width);
9762
9763 if (expand && dispwidth != -1) add_fill_to_box(LIVES_BOX(hbox));
9764
9765 if (widget_opts.swap_label && eventbox) {
9766 if (layout) {
9767 box = LIVES_BOX(lives_layout_hbox_new(LIVES_TABLE(layout)));
9768 hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
9769 lives_widget_set_show_hide_with(entry, hbox);
9770 }
9771 lives_box_pack_start(LIVES_BOX(hbox), eventbox, FALSE, FALSE, packing_width);
9772 }
9773 lives_widget_set_show_hide_parent(entry);
9774
9775 add_warn_image(entry, hbox);
9776
9777 if (img_tips) {
9778 lives_box_pack_start(LIVES_BOX(hbox), img_tips, FALSE, FALSE, widget_opts.packing_width >> 1);
9779 }
9780 }
9781
9782 if (widget_opts.apply_theme) {
9783 set_standard_widget(entry, TRUE);
9784 lives_widget_apply_theme2(entry, LIVES_WIDGET_STATE_NORMAL, TRUE);
9785 #if GTK_CHECK_VERSION(3, 0, 0)
9786 set_css_min_size(entry, widget_opts.css_min_width, ((widget_opts.css_min_height * 3 + 3) >> 2) << 1);
9787 #if GTK_CHECK_VERSION(3, 16, 0)
9788 if (prefs->extra_colours && mainw->pretty_colours) {
9789 char *tmp;
9790 char *colref = gdk_rgba_to_string(&palette->nice1);
9791 set_css_value_direct(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_NORMAL, "", "border-color", colref);
9792 set_css_value_direct(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_FOCUSED, "", "border-color", colref);
9793 tmp = lives_strdup_printf("0 0 0 2px %s inset", colref);
9794 set_css_value_direct(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_FOCUSED, "", "box-shadow", tmp);
9795 lives_free(tmp);
9796 lives_free(colref);
9797 colref = gdk_rgba_to_string(&palette->nice2);
9798 set_css_value_direct(LIVES_WIDGET(entry), LIVES_WIDGET_STATE_NORMAL, "selection", "background-color", colref);
9799 lives_free(colref);
9800 }
9801
9802 set_css_value_direct(entry, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
9803 #endif
9804 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(entry), LIVES_WIDGET_NOTIFY_SIGNAL "editable",
9805 LIVES_GUI_CALLBACK(edit_state_cb), NULL);
9806 #if !GTK_CHECK_VERSION(3, 16, 0)
9807 lives_widget_apply_theme_dimmed(entry, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
9808 #endif
9809 #else
9810 lives_widget_apply_theme_dimmed(entry, LIVES_WIDGET_STATE_INSENSITIVE, BUTTON_DIM_VAL);
9811 #endif
9812 #if !GTK_CHECK_VERSION(3, 16, 0)
9813 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(entry), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
9814 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
9815 widget_state_cb(LIVES_WIDGET_OBJECT(entry), NULL, NULL);
9816 #endif
9817 }
9818
9819 //lives_widget_set_size_request(entry, -1, (widget_opts.css_min_height * 2 + 1) >> 1);
9820 widget_opts.last_container = container;
9821 return entry;
9822 }
9823
lives_standard_progress_bar_new(void)9824 LiVESWidget *lives_standard_progress_bar_new(void) {
9825 LiVESWidget *pbar;
9826 #ifdef PROGBAR_IS_ENTRY
9827 pbar = lives_entry_new();
9828 set_standard_widget(pbar, TRUE);
9829 lives_widget_set_valign(pbar, LIVES_ALIGN_CENTER);
9830 lives_widget_set_text_size(pbar, LIVES_WIDGET_STATE_NORMAL, widget_opts.text_size);
9831 lives_entry_set_editable(LIVES_ENTRY(pbar), FALSE);
9832 lives_widget_set_can_focus(LIVES_WIDGET(pbar), FALSE);
9833 if (widget_opts.justify == LIVES_JUSTIFY_START) {
9834 lives_entry_set_alignment(LIVES_ENTRY(pbar), 0.);
9835 }
9836 if (widget_opts.justify == LIVES_JUSTIFY_CENTER) {
9837 lives_entry_set_alignment(LIVES_ENTRY(pbar), 0.5);
9838 }
9839 if (widget_opts.justify == LIVES_JUSTIFY_END) {
9840 lives_entry_set_alignment(LIVES_ENTRY(pbar), 1.);
9841 }
9842 #else
9843 pbar = lives_progress_bar_new();
9844 #endif
9845
9846 if (widget_opts.apply_theme) {
9847 lives_widget_apply_theme(pbar, LIVES_WIDGET_STATE_NORMAL);
9848 #if GTK_CHECK_VERSION(3, 0, 0)
9849 #if GTK_CHECK_VERSION(3, 16, 0)
9850 char *tmp, *colref;
9851 #endif
9852 #ifdef PROGBAR_IS_ENTRY
9853 char *colref2;
9854 #endif
9855 set_standard_widget(pbar, TRUE);
9856 set_css_min_size(pbar, -1, widget_opts.css_min_height);
9857 #if GTK_CHECK_VERSION(3, 16, 0)
9858 if (prefs->extra_colours && mainw->pretty_colours) {
9859 colref = gdk_rgba_to_string(&palette->nice1);
9860 tmp = lives_strdup_printf("image(%s)", colref);
9861 set_css_value_direct(pbar, LIVES_WIDGET_STATE_NORMAL, "progress",
9862 "background-image", tmp);
9863 set_css_value_direct(pbar, LIVES_WIDGET_STATE_NORMAL, "progress",
9864 "background-color", colref);
9865 set_css_value_direct(pbar, LIVES_WIDGET_STATE_NORMAL, "progress",
9866 "color", colref);
9867 set_css_value_direct(pbar, LIVES_WIDGET_STATE_NORMAL, "progress",
9868 "border-color", colref);
9869 lives_free(tmp);
9870 #ifdef PROGBAR_IS_ENTRY
9871 colref2 = gdk_rgba_to_string(&palette->nice2);
9872 tmp = lives_strdup_printf("linear-gradient(to right, %s, %s)", colref2, colref);
9873 set_css_value_direct(pbar, LIVES_WIDGET_STATE_INSENSITIVE, "progress",
9874 "background-image", tmp);
9875 lives_free(tmp);
9876 lives_free(colref2);
9877 set_css_min_size_selected(pbar, "progress", widget_opts.css_min_width * 4, widget_opts.css_min_height);
9878 #endif
9879 lives_free(colref);
9880 }
9881 #ifdef PROGBAR_IS_ENTRY
9882 set_css_min_size_selected(pbar, "progress", -1, -1);
9883 #endif
9884 #endif
9885 #endif
9886 }
9887
9888 return pbar;
9889 }
9890
9891
lives_dialog_add_button_from_stock(LiVESDialog * dialog,const char * stock_id,const char * label,int response_id)9892 LiVESWidget *lives_dialog_add_button_from_stock(LiVESDialog * dialog, const char *stock_id, const char *label,
9893 int response_id) {
9894 int bwidth = LIVES_SHOULD_EXPAND_EXTRA_WIDTH ? DLG_BUTTON_WIDTH * 2 : DLG_BUTTON_WIDTH;
9895 LiVESWidget *button = lives_standard_button_new_from_stock(stock_id, label, bwidth,
9896 DLG_BUTTON_HEIGHT);
9897 LiVESWidget *first_button;
9898
9899 if (dialog) lives_dialog_add_action_widget(dialog, button, response_id);
9900 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(button), NWIDTH_KEY, LIVES_INT_TO_POINTER(bwidth));
9901 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(button), THEME_KEY,
9902 LIVES_INT_TO_POINTER(widget_opts.apply_theme));
9903
9904 if (dialog) {
9905 /// if we have only ome button, center it
9906 if (!(first_button =
9907 (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(dialog), FBUTT_KEY))) {
9908 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(dialog), FBUTT_KEY, (livespointer)button);
9909 if (LIVES_SHOULD_EXPAND_WIDTH) lives_button_center(button);
9910 } else {
9911 /// else attach at end
9912 lives_button_uncenter(first_button,
9913 LIVES_POINTER_TO_INT(lives_widget_object_get_data
9914 (LIVES_WIDGET_OBJECT(first_button), NWIDTH_KEY)));
9915 }
9916 }
9917
9918 lives_widget_apply_theme(button, LIVES_WIDGET_STATE_NORMAL);
9919 if (is_standard_widget(button)) sbutt_render(button, 0L, NULL);
9920 return button;
9921 }
9922
9923
dlg_focus_changed(LiVESContainer * c,LiVESWidget * widget,livespointer user_data)9924 WIDGET_HELPER_LOCAL_INLINE void dlg_focus_changed(LiVESContainer * c, LiVESWidget * widget, livespointer user_data) {
9925 #if GTK_CHECK_VERSION(2, 18, 0)
9926 LiVESWidget *entry = NULL;
9927 while (LIVES_IS_CONTAINER(widget)) {
9928 LiVESWidget *fchild = lives_container_get_focus_child(LIVES_CONTAINER(widget));
9929 if (!fchild || fchild == widget) break;
9930 widget = fchild;
9931 }
9932
9933 if (LIVES_IS_COMBO(widget)) {
9934 entry = lives_combo_get_entry(LIVES_COMBO(widget));
9935 } else entry = widget;
9936
9937 if (entry && LIVES_IS_ENTRY(entry)) {
9938 if (lives_entry_get_activates_default(LIVES_ENTRY(widget))) {
9939 LiVESWidget *toplevel = lives_widget_get_toplevel(widget);
9940 LiVESWidget *button;
9941 if (!LIVES_IS_WIDGET(toplevel)) return;
9942 button = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(toplevel), DEFBUTTON_KEY);
9943 if (button && lives_widget_is_sensitive(button)) {
9944 // default button gets the default
9945 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(toplevel), CDEF_KEY, NULL);
9946 lives_widget_grab_default(button);
9947 lives_widget_queue_draw(button);
9948 }
9949 }
9950 }
9951 #endif
9952 }
9953
9954
lives_dialog_set_button_layout(LiVESDialog * dlg,LiVESButtonBoxStyle bstyle)9955 WIDGET_HELPER_GLOBAL_INLINE boolean lives_dialog_set_button_layout(LiVESDialog * dlg,
9956 LiVESButtonBoxStyle bstyle) {
9957 LiVESWidget *bbox = lives_dialog_get_action_area(dlg);
9958 return lives_button_box_set_layout(LIVES_BUTTON_BOX(bbox), bstyle);
9959 }
9960
9961
lives_dialog_add_escape(LiVESDialog * dlg,LiVESWidget * button)9962 WIDGET_HELPER_GLOBAL_INLINE LiVESAccelGroup *lives_dialog_add_escape(LiVESDialog * dlg, LiVESWidget * button) {
9963 LiVESAccelGroup *accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
9964 lives_widget_add_accelerator(button, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
9965 LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
9966 lives_window_add_accel_group(LIVES_WINDOW(dlg), accel_group);
9967 return accel_group;
9968 }
9969
9970
lives_standard_dialog_new(const char * title,boolean add_std_buttons,int width,int height)9971 LiVESWidget *lives_standard_dialog_new(const char *title, boolean add_std_buttons, int width, int height) {
9972 // in case of problems, try setting widget_opts.no_gui=TRUE
9973
9974 LiVESWidget *dialog = NULL;
9975
9976 dialog = lives_dialog_new();
9977
9978 /* set_css_value_direct(dialog, LIVES_WIDGET_STATE_NORMAL, "", "opacity", "1."); */
9979 /* set_css_value_direct(dialog, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0."); */
9980 /* set_css_value_direct(dialog, LIVES_WIDGET_STATE_INSENSITIVE, "", */
9981 /* "transition-duration", "4s"); */
9982 /* set_css_value_direct(dialog, LIVES_WIDGET_STATE_NORMAL, "", */
9983 /* "transition-duration", "4s"); */
9984 /* lives_widget_set_sensitive(dialog, FALSE); */
9985
9986 if (width <= 0) width = 8;
9987 if (height <= 0) height = 8;
9988
9989 if (!widget_opts.no_gui) {
9990 LiVESWindow *transient = widget_opts.transient;
9991 if (!transient) transient = get_transient_full();
9992 if (transient) lives_window_set_transient_for(LIVES_WINDOW(dialog), transient);
9993 }
9994
9995 lives_window_set_monitor(LIVES_WINDOW(dialog), widget_opts.monitor);
9996
9997 #if !GTK_CHECK_VERSION(3, 0, 0)
9998 if (height > 8 && width > 8) {
9999 #endif
10000 lives_widget_set_minimum_size(dialog, width, height);
10001 #if !GTK_CHECK_VERSION(3, 0, 0)
10002 }
10003 #endif
10004
10005 lives_window_set_default_size(LIVES_WINDOW(dialog), width, height);
10006 lives_widget_set_size_request(dialog, width, height);
10007
10008 if (title) lives_window_set_title(LIVES_WINDOW(dialog), title);
10009
10010 lives_window_set_deletable(LIVES_WINDOW(dialog), FALSE);
10011
10012 if (LIVES_SHOULD_EXPAND_WIDTH) lives_widget_set_hexpand(dialog, TRUE);
10013 if (LIVES_SHOULD_EXPAND_HEIGHT) lives_widget_set_vexpand(dialog, TRUE);
10014
10015 /* #if !GTK_CHECK_VERSION(3, 0, 0) */
10016 /* lives_dialog_set_has_separator(LIVES_DIALOG(dialog), FALSE); */
10017 /* #endif */
10018
10019 if (widget_opts.apply_theme) {
10020 lives_widget_apply_theme(dialog, LIVES_WIDGET_STATE_NORMAL);
10021 funkify_dialog(dialog);
10022 #if GTK_CHECK_VERSION(2, 18, 0)
10023 lives_signal_sync_connect(LIVES_GUI_OBJECT(lives_dialog_get_content_area(LIVES_DIALOG(dialog))),
10024 LIVES_WIDGET_SET_FOCUS_CHILD_SIGNAL,
10025 LIVES_GUI_CALLBACK(dlg_focus_changed), NULL);
10026 #endif
10027 } else {
10028 lives_container_set_border_width(LIVES_CONTAINER(dialog), widget_opts.border_width * 2);
10029 }
10030
10031 // do this before widget_show(), then call lives_window_center() afterwards
10032 lives_window_set_position(LIVES_WINDOW(dialog), LIVES_WIN_POS_CENTER_ALWAYS);
10033
10034 if (add_std_buttons) {
10035 // cancel button will automatically destroy the dialog
10036 // ok button needs manual destruction
10037
10038 LiVESAccelGroup *accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
10039 LiVESWidget *cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog),
10040 LIVES_STOCK_CANCEL, NULL, LIVES_RESPONSE_CANCEL);
10041
10042 LiVESWidget *okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog),
10043 LIVES_STOCK_OK, NULL, LIVES_RESPONSE_OK);
10044
10045 lives_button_grab_default_special(okbutton);
10046
10047 lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
10048 LIVES_GUI_CALLBACK(lives_general_button_clicked), NULL);
10049
10050 lives_widget_add_accelerator(cancelbutton, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
10051 LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
10052
10053 if (widget_opts.apply_theme) {
10054 #if !GTK_CHECK_VERSION(3, 16, 0)
10055 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
10056 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
10057 widget_state_cb(LIVES_WIDGET_OBJECT(cancelbutton), NULL, NULL);
10058
10059 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
10060 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
10061 widget_state_cb(LIVES_WIDGET_OBJECT(okbutton), NULL, NULL);
10062 #endif
10063 }
10064
10065 lives_window_add_accel_group(LIVES_WINDOW(dialog), accel_group);
10066 }
10067
10068 lives_signal_sync_connect(LIVES_GUI_OBJECT(dialog), LIVES_WIDGET_DELETE_EVENT,
10069 LIVES_GUI_CALLBACK(return_true), NULL);
10070
10071 if (!widget_opts.non_modal)
10072 lives_window_set_modal(LIVES_WINDOW(dialog), TRUE);
10073
10074 if (!widget_opts.non_modal)
10075 lives_window_set_resizable(LIVES_WINDOW(dialog), FALSE);
10076
10077 return dialog;
10078 }
10079
10080
lives_standard_font_chooser_new(void)10081 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_font_chooser_new(void) {
10082 LiVESWidget *font_choo = NULL;
10083 int width = DEF_BUTTON_WIDTH, height = DEF_BUTTON_HEIGHT;
10084 #ifdef GUI_GTK
10085 #if GTK_CHECK_VERSION(3, 2, 0)
10086 char *ttl;
10087 font_choo = gtk_font_button_new();
10088 gtk_font_button_set_show_size(GTK_FONT_BUTTON(font_choo), FALSE);
10089 gtk_font_chooser_set_show_preview_entry(GTK_FONT_CHOOSER(font_choo), TRUE);
10090 gtk_font_chooser_set_preview_text(GTK_FONT_CHOOSER(font_choo), "LiVES");
10091 ttl = lives_strdup_printf("%s%s", widget_opts.title_prefix, _("Choose a Font..."));
10092 gtk_font_button_set_title(GTK_FONT_BUTTON(font_choo), ttl);
10093 lives_free(ttl);
10094
10095 if (widget_opts.apply_theme) {
10096 set_standard_widget(font_choo, TRUE);
10097 lives_widget_apply_theme2(font_choo, LIVES_WIDGET_STATE_NORMAL, TRUE);
10098
10099 #if GTK_CHECK_VERSION(3, 16, 0)
10100 set_css_min_size(font_choo, width, height);
10101 set_css_value_direct(font_choo, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
10102
10103 lives_widget_set_padding(font_choo, 0);
10104 set_css_value_direct(font_choo, LIVES_WIDGET_STATE_NORMAL, "", "background", "none");
10105 //set_css_value_direct(font_choo, LIVES_WIDGET_STATE_NORMAL, "", "border-width", "0px");
10106
10107 if (prefs->extra_colours && mainw->pretty_colours) {
10108 char *tmp;
10109 char *colref = gdk_rgba_to_string(&palette->nice1);
10110 set_css_value_direct(LIVES_WIDGET(font_choo), LIVES_WIDGET_STATE_NORMAL, "", "border-color", colref);
10111 tmp = lives_strdup_printf("0 0 0 1px %s inset", colref);
10112 set_css_value_direct(LIVES_WIDGET(font_choo), LIVES_WIDGET_STATE_PRELIGHT, "", "box-shadow", tmp);
10113 lives_free(tmp);
10114 lives_free(colref);
10115 colref = gdk_rgba_to_string(&palette->nice2);
10116 set_css_value_direct(LIVES_WIDGET(font_choo), LIVES_WIDGET_STATE_NORMAL, "", "background-color", colref);
10117 }
10118
10119 #endif
10120 }
10121 #endif
10122 #endif
10123 return font_choo;
10124 }
10125
10126
10127 extern void on_filesel_button_clicked(LiVESButton *, livespointer);
10128
lives_standard_dfentry_new(const char * labeltext,const char * txt,const char * defdir,int dispwidth,int maxchars,LiVESBox * box,const char * tooltip,boolean isdir)10129 static LiVESWidget *lives_standard_dfentry_new(const char *labeltext, const char *txt, const char *defdir, int dispwidth,
10130 int maxchars,
10131 LiVESBox * box, const char *tooltip, boolean isdir) {
10132 LiVESWidget *direntry = NULL;
10133 LiVESWidget *buttond;
10134 LiVESWidget *img_tips;
10135 LiVESWidget *warn_img;
10136
10137 if (!box) return NULL;
10138
10139 direntry = lives_standard_entry_new(labeltext, txt, dispwidth, maxchars == -1 ? PATH_MAX : maxchars, box, tooltip);
10140 lives_entry_set_editable(LIVES_ENTRY(direntry), FALSE);
10141
10142 // add dir, with filechooser button
10143 buttond = lives_standard_file_button_new(isdir, defdir);
10144 if (widget_opts.last_label) lives_label_set_mnemonic_widget(LIVES_LABEL(widget_opts.last_label), buttond);
10145 lives_box_pack_start(LIVES_BOX(lives_widget_get_parent(direntry)), buttond, FALSE, FALSE, widget_opts.packing_width);
10146
10147
10148 if ((warn_img = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(direntry), WARN_IMAGE_KEY))) {
10149 lives_box_reorder_child(LIVES_BOX(lives_widget_get_parent(direntry)), buttond,
10150 get_box_child_index(LIVES_BOX(lives_widget_get_parent(direntry)), warn_img));
10151 } else if ((img_tips = lives_widget_object_get_data(LIVES_WIDGET_OBJECT(direntry), HAS_TTIPS_IMAGE_KEY))) {
10152 lives_box_reorder_child(LIVES_BOX(lives_widget_get_parent(direntry)), buttond,
10153 get_box_child_index(LIVES_BOX(lives_widget_get_parent(direntry)), img_tips));
10154 }
10155
10156 lives_signal_sync_connect(buttond, LIVES_WIDGET_CLICKED_SIGNAL, LIVES_GUI_CALLBACK(on_filesel_button_clicked),
10157 (livespointer)direntry);
10158 lives_widget_set_sensitive_with(buttond, direntry);
10159 lives_widget_set_show_hide_with(buttond, direntry);
10160 return direntry;
10161 }
10162
10163
lives_standard_direntry_new(const char * labeltext,const char * txt,int dispwidth,int maxchars,LiVESBox * box,const char * tooltip)10164 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_direntry_new(const char *labeltext, const char *txt, int dispwidth,
10165 int maxchars,
10166 LiVESBox * box, const char *tooltip) {
10167 return lives_standard_dfentry_new(labeltext, txt, txt, dispwidth, maxchars, box, tooltip, TRUE);
10168 }
10169
10170
lives_standard_fileentry_new(const char * labeltext,const char * txt,const char * defdir,int dispwidth,int maxchars,LiVESBox * box,const char * tooltip)10171 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_fileentry_new(const char *labeltext, const char *txt,
10172 const char *defdir,
10173 int dispwidth, int maxchars, LiVESBox * box, const char *tooltip) {
10174 return lives_standard_dfentry_new(labeltext, txt, defdir, dispwidth, maxchars, box, tooltip, FALSE);
10175 }
10176
10177
lives_standard_toolbar_new(void)10178 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_toolbar_new(void) {
10179 LiVESWidget *toolbar = lives_toolbar_new();
10180 lives_toolbar_set_show_arrow(LIVES_TOOLBAR(toolbar), TRUE);
10181 lives_toolbar_set_style(LIVES_TOOLBAR(toolbar), LIVES_TOOLBAR_ICONS);
10182 lives_toolbar_set_icon_size(LIVES_TOOLBAR(toolbar), widget_opts.icon_size);
10183 if (widget_opts.apply_theme) {
10184 #if GTK_CHECK_VERSION(3, 0, 0)
10185 set_css_min_size(toolbar, widget_opts.css_min_width, widget_opts.css_min_height);
10186 #endif
10187 }
10188 return toolbar;
10189 }
10190
10191
lives_standard_hscale_new(LiVESAdjustment * adj)10192 LiVESWidget *lives_standard_hscale_new(LiVESAdjustment * adj) {
10193 LiVESWidget *hscale = NULL;
10194 #ifdef GUI_GTK
10195 #if GTK_CHECK_VERSION(3, 0, 0)
10196 hscale = gtk_scale_new(LIVES_ORIENTATION_HORIZONTAL, adj);
10197
10198 if (widget_opts.apply_theme) {
10199 #if GTK_CHECK_VERSION(3, 16, 0)
10200 char *colref = gdk_rgba_to_string(&palette->white);
10201 char *tmp = lives_strdup_printf("image(%s)", colref);
10202 set_css_value_direct(hscale, LIVES_WIDGET_STATE_NORMAL, "*",
10203 "background-image", tmp);
10204 lives_free(tmp);
10205 lives_free(colref);
10206
10207 if (prefs->extra_colours && mainw->pretty_colours) {
10208 colref = gdk_rgba_to_string(&palette->nice1);
10209 tmp = lives_strdup_printf("image(%s)", colref);
10210 set_css_value_direct(hscale, LIVES_WIDGET_STATE_NORMAL, "trough",
10211 "background-image", tmp);
10212 lives_free(tmp);
10213 lives_free(colref);
10214 }
10215
10216 set_css_min_size_selected(hscale, "slider", widget_opts.css_min_width, widget_opts.css_min_height);
10217 set_css_min_size_selected(hscale, "scale", DEF_BUTTON_WIDTH, widget_opts.css_min_height);
10218 set_css_value_direct(hscale, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
10219 #endif
10220 }
10221
10222 #else
10223 hscale = gtk_hscale_new(adj);
10224 #endif
10225 gtk_scale_set_draw_value(LIVES_SCALE(hscale), FALSE);
10226 #endif
10227 return hscale;
10228 }
10229
10230
lives_standard_hruler_new(void)10231 LiVESWidget *lives_standard_hruler_new(void) {
10232 LiVESWidget *hruler = NULL;
10233
10234 #ifdef GUI_GTK
10235 #if GTK_CHECK_VERSION(3, 0, 0)
10236 hruler = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, NULL);
10237 gtk_scale_set_draw_value(GTK_SCALE(hruler), FALSE);
10238 #if GTK_CHECK_VERSION(3, 4, 0)
10239 gtk_scale_set_has_origin(GTK_SCALE(hruler), FALSE);
10240 #endif
10241 gtk_scale_set_digits(GTK_SCALE(hruler), 8);
10242 #else
10243 hruler = gtk_hruler_new();
10244 lives_widget_apply_theme(hruler, LIVES_WIDGET_STATE_INSENSITIVE);
10245 #endif
10246
10247 #endif
10248
10249 return hruler;
10250 }
10251
10252
lives_scrolled_window_scroll_to(LiVESScrolledWindow * sw,LiVESPositionType pos)10253 double lives_scrolled_window_scroll_to(LiVESScrolledWindow * sw, LiVESPositionType pos) {
10254 double val;
10255 LiVESAdjustment *adj;
10256 if (!sw) return -1.;
10257 else {
10258 if (pos == LIVES_POS_TOP || pos == LIVES_POS_BOTTOM) {
10259 adj = lives_scrolled_window_get_vadjustment(sw);
10260 } else {
10261 adj = lives_scrolled_window_get_hadjustment(sw);
10262 }
10263
10264 if (pos == LIVES_POS_TOP || pos == LIVES_POS_LEFT) val = lives_adjustment_get_lower(adj);
10265 else val = lives_adjustment_get_upper(adj) - lives_adjustment_get_page_size(adj);
10266 lives_adjustment_set_value(adj, val);
10267 }
10268 return val;
10269 }
10270
10271
lives_standard_scrolled_window_new(int width,int height,LiVESWidget * child)10272 LiVESWidget *lives_standard_scrolled_window_new(int width, int height, LiVESWidget * child) {
10273 LiVESWidget *scrolledwindow = NULL;
10274 LiVESWidget *swchild;
10275
10276 scrolledwindow = lives_scrolled_window_new(NULL, NULL);
10277 lives_scrolled_window_set_policy(LIVES_SCROLLED_WINDOW(scrolledwindow),
10278 LIVES_POLICY_AUTOMATIC, LIVES_POLICY_AUTOMATIC);
10279
10280 if (LIVES_SHOULD_EXPAND_WIDTH)
10281 lives_widget_set_hexpand(scrolledwindow, TRUE);
10282 if (LIVES_SHOULD_EXPAND_HEIGHT)
10283 lives_widget_set_vexpand(scrolledwindow, TRUE);
10284
10285 lives_container_set_border_width(LIVES_CONTAINER(scrolledwindow), widget_opts.border_width);
10286
10287 if (child) {
10288 #ifdef GUI_GTK
10289 #if GTK_CHECK_VERSION(3, 0, 0)
10290 if (!LIVES_IS_SCROLLABLE(child))
10291 #else
10292 if (!LIVES_IS_TEXT_VIEW(child))
10293 #endif
10294 {
10295 lives_scrolled_window_add_with_viewport(LIVES_SCROLLED_WINDOW(scrolledwindow), child);
10296 } else {
10297 if (!LIVES_SHOULD_EXPAND_EXTRA_WIDTH) {
10298 LiVESWidget *align;
10299 align = lives_alignment_new(.5, 0., 0., 0.);
10300 lives_container_add(LIVES_CONTAINER(align), child);
10301 lives_scrolled_window_add_with_viewport(LIVES_SCROLLED_WINDOW(scrolledwindow), align);
10302 } else {
10303 lives_container_add(LIVES_CONTAINER(scrolledwindow), child);
10304 }
10305 }
10306 #endif
10307 #ifdef GUI_QT
10308 lives_container_add(scrolledwindow, child);
10309 #endif
10310 }
10311
10312 swchild = lives_bin_get_child(LIVES_BIN(scrolledwindow));
10313
10314 #ifdef GUI_QT
10315 if (width > -1 || height > -1)
10316 lives_widget_set_minimum_size(scrolledwindow, width, height);
10317 #endif
10318
10319 lives_widget_apply_theme(swchild, LIVES_WIDGET_STATE_NORMAL);
10320
10321 if (LIVES_SHOULD_EXPAND_WIDTH) {
10322 lives_widget_set_halign(swchild, LIVES_ALIGN_FILL);
10323 lives_widget_set_hexpand(swchild, TRUE);
10324 }
10325 if (LIVES_SHOULD_EXPAND_HEIGHT)
10326 lives_widget_set_vexpand(swchild, TRUE);
10327
10328 if (LIVES_IS_CONTAINER(child) && LIVES_SHOULD_EXPAND) lives_container_set_border_width(LIVES_CONTAINER(child),
10329 widget_opts.border_width >> 1);
10330
10331 #ifdef GUI_GTK
10332 if (GTK_IS_VIEWPORT(swchild))
10333 gtk_viewport_set_shadow_type(GTK_VIEWPORT(swchild), LIVES_SHADOW_IN);
10334
10335 if (width != 0 && height != 0) {
10336 #if !GTK_CHECK_VERSION(3, 0, 0)
10337 if (width > -1 || height > -1)
10338 lives_widget_set_size_request(scrolledwindow, width, height);
10339 lives_widget_set_minimum_size(scrolledwindow, width, height); // crash if we dont have toplevel win
10340 #else
10341 if (height != -1) lives_scrolled_window_set_min_content_height(LIVES_SCROLLED_WINDOW(scrolledwindow), height);
10342 if (width != -1) lives_scrolled_window_set_min_content_width(LIVES_SCROLLED_WINDOW(scrolledwindow), width);
10343 #endif
10344 }
10345 #endif
10346
10347 return scrolledwindow;
10348 }
10349
10350
lives_standard_expander_new(const char * ltext,LiVESBox * box,LiVESWidget * child)10351 LiVESWidget *lives_standard_expander_new(const char *ltext, LiVESBox * box, LiVESWidget * child) {
10352 LiVESWidget *expander = NULL, *container = NULL, *label = NULL;
10353
10354 #ifdef GUI_GTK
10355 LiVESWidget *hbox;
10356 char *labeltext;
10357
10358 if (LIVES_SHOULD_EXPAND) {
10359 labeltext = lives_strdup_printf("<big>%s</big>", ltext);
10360 } else labeltext = lives_strdup(ltext);
10361
10362 expander = lives_expander_new(labeltext);
10363 lives_free(labeltext);
10364
10365 lives_expander_set_use_markup(LIVES_EXPANDER(expander), TRUE);
10366
10367 if (box) {
10368 int packing_width = 0;
10369
10370 hbox = make_inner_hbox(LIVES_BOX(box), TRUE);
10371 lives_widget_set_show_hide_parent(expander);
10372 container = widget_opts.last_container;
10373
10374 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width;
10375
10376 if (widget_opts.justify == LIVES_JUSTIFY_CENTER || widget_opts.justify == LIVES_JUSTIFY_START)
10377 add_fill_to_box(LIVES_BOX(hbox));
10378
10379 if (widget_opts.justify == LIVES_JUSTIFY_START) lives_widget_set_halign(expander, LIVES_ALIGN_START);
10380 if (widget_opts.justify != LIVES_JUSTIFY_END) add_fill_to_box(LIVES_BOX(hbox));
10381
10382 if (widget_opts.justify == LIVES_JUSTIFY_CENTER) lives_widget_set_halign(expander, LIVES_ALIGN_CENTER);
10383 lives_box_pack_start(LIVES_BOX(hbox), expander, TRUE, TRUE, packing_width);
10384 lives_widget_set_valign(expander, LIVES_ALIGN_CENTER);
10385
10386 if (widget_opts.justify == LIVES_JUSTIFY_END) lives_widget_set_halign(expander, LIVES_ALIGN_END);
10387 if (widget_opts.justify != LIVES_JUSTIFY_START) add_fill_to_box(LIVES_BOX(hbox));
10388
10389 if (child) lives_container_add(LIVES_CONTAINER(expander), child);
10390 lives_container_set_border_width(LIVES_CONTAINER(expander), widget_opts.border_width);
10391 }
10392
10393 if (widget_opts.apply_theme) {
10394 #ifdef GUI_GTK
10395 #if !GTK_CHECK_VERSION(3, 16, 0)
10396 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(expander), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
10397 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
10398 widget_state_cb(LIVES_WIDGET_OBJECT(expander), NULL, NULL);
10399
10400 if (widget_opts.last_label) {
10401 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(widget_opts.last_label), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
10402 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
10403 widget_state_cb(LIVES_WIDGET_OBJECT(widget_opts.last_label), NULL, NULL);
10404 }
10405 #else
10406 set_css_value_direct(expander, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
10407 #endif
10408 lives_widget_apply_theme(expander, LIVES_WIDGET_STATE_NORMAL);
10409 lives_container_forall(LIVES_CONTAINER(expander), set_child_colour_internal, LIVES_INT_TO_POINTER(TRUE));
10410 #endif
10411 }
10412 label = lives_expander_get_label_widget(LIVES_EXPANDER(expander));
10413 #endif
10414 widget_opts.last_container = container;
10415 widget_opts.last_label = label;
10416 return expander;
10417 }
10418
10419
lives_standard_table_new(uint32_t rows,uint32_t cols,boolean homogeneous)10420 LiVESWidget *lives_standard_table_new(uint32_t rows, uint32_t cols, boolean homogeneous) {
10421 LiVESWidget *table = lives_table_new(rows, cols, homogeneous);
10422 lives_widget_apply_theme(table, LIVES_WIDGET_STATE_NORMAL);
10423 if (LIVES_SHOULD_EXPAND_WIDTH) lives_table_set_row_spacings(LIVES_TABLE(table),
10424 LIVES_SHOULD_EXPAND_EXTRA_WIDTH ? (widget_opts.packing_width << 2) : widget_opts.packing_width);
10425 else lives_table_set_row_spacings(LIVES_TABLE(table), 0);
10426 if (LIVES_SHOULD_EXPAND_HEIGHT) lives_table_set_col_spacings(LIVES_TABLE(table),
10427 LIVES_SHOULD_EXPAND_EXTRA_HEIGHT ? (widget_opts.packing_height << 2) : widget_opts.packing_height);
10428 else lives_table_set_col_spacings(LIVES_TABLE(table), 0);
10429 return table;
10430 }
10431
10432
lives_standard_text_view_new(const char * text,LiVESTextBuffer * tbuff)10433 LiVESWidget *lives_standard_text_view_new(const char *text, LiVESTextBuffer * tbuff) {
10434 LiVESWidget *textview;
10435
10436 if (!tbuff)
10437 textview = lives_text_view_new();
10438 else
10439 textview = lives_text_view_new_with_buffer(tbuff);
10440
10441 lives_widget_set_text_size(textview, LIVES_WIDGET_STATE_NORMAL, widget_opts.text_size);
10442 lives_text_view_set_editable(LIVES_TEXT_VIEW(textview), FALSE);
10443 lives_text_view_set_wrap_mode(LIVES_TEXT_VIEW(textview), LIVES_WRAP_WORD);
10444 lives_text_view_set_cursor_visible(LIVES_TEXT_VIEW(textview), FALSE);
10445 lives_container_set_border_width(LIVES_CONTAINER(textview), 2);
10446
10447 if (text) {
10448 lives_text_view_set_text(LIVES_TEXT_VIEW(textview), text, -1);
10449 }
10450
10451 if (widget_opts.apply_theme) {
10452 lives_widget_apply_theme3(textview, LIVES_WIDGET_STATE_NORMAL);
10453 if (prefs->extra_colours && mainw->pretty_colours) {
10454 char *colref = gdk_rgba_to_string(&palette->menu_and_bars);
10455 set_css_value_direct(textview, LIVES_WIDGET_STATE_NORMAL, "", "background-color", colref);
10456 lives_free(colref);
10457 }
10458 set_css_value_direct(textview, LIVES_WIDGET_STATE_INSENSITIVE, "", "opacity", "0.5");
10459 }
10460
10461 lives_text_view_set_justification(LIVES_TEXT_VIEW(textview), widget_opts.justify);
10462 if (widget_opts.justify == LIVES_JUSTIFY_CENTER) {
10463 lives_widget_set_halign(textview, LIVES_ALIGN_CENTER);
10464 lives_widget_set_valign(textview, LIVES_ALIGN_CENTER);
10465 }
10466 return textview;
10467 }
10468
10469
lives_standard_file_button_new(boolean is_dir,const char * def_dir)10470 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_file_button_new(boolean is_dir, const char *def_dir) {
10471 LiVESWidget *fbutton;
10472 LiVESWidget *image = lives_image_new_from_stock(LIVES_STOCK_OPEN, LIVES_ICON_SIZE_BUTTON);
10473
10474 /// height X height is correct
10475 fbutton = lives_standard_button_new(DEF_BUTTON_HEIGHT, DEF_BUTTON_HEIGHT);
10476 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(fbutton), ISDIR_KEY, LIVES_INT_TO_POINTER(is_dir));
10477 if (def_dir) lives_widget_object_set_data(LIVES_WIDGET_OBJECT(fbutton), DEFDIR_KEY, (livespointer)def_dir);
10478 lives_standard_button_set_image(LIVES_BUTTON(fbutton), image);
10479 return fbutton;
10480 }
10481
10482
lives_lock_button_get_locked(LiVESButton * button)10483 WIDGET_HELPER_GLOBAL_INLINE boolean lives_lock_button_get_locked(LiVESButton * button) {
10484 return (boolean)LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(button),
10485 ISLOCKED_KEY));
10486 }
10487
10488
_on_lock_button_clicked(LiVESButton * button,livespointer user_data)10489 static void _on_lock_button_clicked(LiVESButton * button, livespointer user_data) {
10490 LiVESWidget *image;
10491 int locked = !(LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(button),
10492 ISLOCKED_KEY)));
10493 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(button), ISLOCKED_KEY, LIVES_INT_TO_POINTER(locked));
10494 if (locked) {
10495 image = lives_image_new_from_stock(LIVES_LIVES_STOCK_LOCKED, LIVES_ICON_SIZE_BUTTON);
10496 lives_widget_set_opacity(LIVES_WIDGET(button), 1.0);
10497 } else {
10498 image = lives_image_new_from_stock(LIVES_LIVES_STOCK_UNLOCKED, LIVES_ICON_SIZE_BUTTON);
10499 lives_widget_set_opacity(LIVES_WIDGET(button), .75);
10500 }
10501 lives_standard_button_set_image(LIVES_BUTTON(button), image);
10502 }
10503
10504
label_act_lockbutton(LiVESWidget * widget,LiVESXEventButton * event,LiVESButton * lockbutton)10505 boolean label_act_lockbutton(LiVESWidget * widget, LiVESXEventButton * event, LiVESButton * lockbutton) {
10506 if (!lives_widget_is_sensitive(LIVES_WIDGET(lockbutton))) return FALSE;
10507 _on_lock_button_clicked(lockbutton, NULL);
10508 return FALSE;
10509 }
10510
10511
lives_lock_button_toggle(LiVESButton * button)10512 boolean lives_lock_button_toggle(LiVESButton * button) {
10513 _on_lock_button_clicked(button, NULL);
10514 return lives_lock_button_get_locked(button);
10515 }
10516
10517
lives_standard_lock_button_new(boolean is_locked,int width,int height,const char * label,const char * tooltip)10518 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_lock_button_new(boolean is_locked, int width,
10519 int height,
10520 const char *label,
10521 const char *tooltip) {
10522 LiVESWidget *lockbutton;
10523 lockbutton = lives_standard_button_new_with_label(label, width, height);
10524 lives_button_set_focus_on_click(LIVES_BUTTON(lockbutton), FALSE);
10525 if (tooltip) lives_widget_set_tooltip_text(lockbutton, tooltip);
10526 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(lockbutton), ISLOCKED_KEY, LIVES_INT_TO_POINTER(!is_locked));
10527 lives_signal_sync_connect(lockbutton, LIVES_WIDGET_CLICKED_SIGNAL, LIVES_GUI_CALLBACK(_on_lock_button_clicked), NULL);
10528 _on_lock_button_clicked(LIVES_BUTTON(lockbutton), LIVES_INT_TO_POINTER(widget_opts.apply_theme));
10529 return lockbutton;
10530 }
10531
10532
on_pwcolselx(LiVESButton * button,lives_rfx_t * rfx)10533 static void on_pwcolselx(LiVESButton * button, lives_rfx_t *rfx) {
10534 LiVESWidgetColor selected;
10535 LiVESWidget *sp_red = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(button), SPRED_KEY);
10536 LiVESWidget *sp_green = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(button), SPGREEN_KEY);
10537 LiVESWidget *sp_blue = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(button), SPBLUE_KEY);
10538 LiVESWidget *sp_alpha = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(button), SPALPHA_KEY);
10539
10540 int r, g, b, a;
10541
10542 lives_color_button_get_color(LIVES_COLOR_BUTTON(button), &selected);
10543
10544 // get 0. -> 255. values
10545 if (sp_red) {
10546 r = (int)((double)(selected.red + LIVES_WIDGET_COLOR_SCALE_255(0.5)) / (double)LIVES_WIDGET_COLOR_SCALE_255(1.));
10547 lives_spin_button_set_value(LIVES_SPIN_BUTTON(sp_red), (double)r);
10548 }
10549
10550 if (sp_green) {
10551 g = (int)((double)(selected.green + LIVES_WIDGET_COLOR_SCALE_255(0.5)) / (double)LIVES_WIDGET_COLOR_SCALE_255(1.));
10552 lives_spin_button_set_value(LIVES_SPIN_BUTTON(sp_green), (double)g);
10553 }
10554
10555 if (sp_blue) {
10556 b = (int)((double)(selected.blue + LIVES_WIDGET_COLOR_SCALE_255(0.5)) / (double)LIVES_WIDGET_COLOR_SCALE_255(1.));
10557 lives_spin_button_set_value(LIVES_SPIN_BUTTON(sp_blue), (double)b);
10558 }
10559
10560 if (sp_alpha) {
10561 #if !LIVES_WIDGET_COLOR_HAS_ALPHA
10562 a = lives_color_button_get_alpha(LIVES_COLOR_BUTTON(button)) / 255.;
10563 #else
10564 a = (int)((double)(selected.alpha + LIVES_WIDGET_COLOR_SCALE_255(0.5)) / (double)LIVES_WIDGET_COLOR_SCALE_255(1.));
10565 #endif
10566 lives_spin_button_set_value(LIVES_SPIN_BUTTON(sp_alpha), (double)a);
10567 }
10568
10569 lives_color_button_set_color(LIVES_COLOR_BUTTON(button), &selected);
10570 }
10571
10572
after_param_red_changedx(LiVESSpinButton * spinbutton,livespointer udata)10573 static void after_param_red_changedx(LiVESSpinButton * spinbutton, livespointer udata) {
10574 LiVESWidgetColor colr;
10575
10576 LiVESWidget *cbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), CBUTTON_KEY);
10577 LiVESWidget *sp_green = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPGREEN_KEY);
10578 LiVESWidget *sp_blue = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPBLUE_KEY);
10579 #if LIVES_WIDGET_COLOR_HAS_ALPHA
10580 LiVESWidget *sp_alpha = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPALPHA_KEY);
10581 #endif
10582
10583 int new_red = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
10584 int old_green = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_green));
10585 int old_blue = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_blue));
10586
10587 colr.red = LIVES_WIDGET_COLOR_SCALE_255(new_red);
10588 colr.green = LIVES_WIDGET_COLOR_SCALE_255(old_green);
10589 colr.blue = LIVES_WIDGET_COLOR_SCALE_255(old_blue);
10590
10591 #if LIVES_WIDGET_COLOR_HAS_ALPHA
10592 if (sp_alpha) {
10593 int old_alpha = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_alpha));
10594 colr.alpha = LIVES_WIDGET_COLOR_SCALE_255(old_alpha);
10595 } else colr.alpha = 1.0;
10596 #endif
10597 lives_color_button_set_color(LIVES_COLOR_BUTTON(cbutton), &colr);
10598 }
10599
10600
after_param_green_changedx(LiVESSpinButton * spinbutton,livespointer udata)10601 static void after_param_green_changedx(LiVESSpinButton * spinbutton, livespointer udata) {
10602 LiVESWidgetColor colr;
10603
10604 LiVESWidget *cbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), CBUTTON_KEY);
10605 LiVESWidget *sp_red = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPRED_KEY);
10606 LiVESWidget *sp_blue = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPBLUE_KEY);
10607 #if LIVES_WIDGET_COLOR_HAS_ALPHA
10608 LiVESWidget *sp_alpha = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPALPHA_KEY);
10609 #endif
10610
10611 int new_green = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
10612 int old_red = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_red));
10613 int old_blue = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_blue));
10614
10615 colr.red = LIVES_WIDGET_COLOR_SCALE_255(old_red);
10616 colr.green = LIVES_WIDGET_COLOR_SCALE_255(new_green);
10617 colr.blue = LIVES_WIDGET_COLOR_SCALE_255(old_blue);
10618
10619 #if LIVES_WIDGET_COLOR_HAS_ALPHA
10620 if (sp_alpha) {
10621 int old_alpha = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_alpha));
10622 colr.alpha = LIVES_WIDGET_COLOR_SCALE_255(old_alpha);
10623 } else colr.alpha = 1.0;
10624 #endif
10625 lives_color_button_set_color(LIVES_COLOR_BUTTON(cbutton), &colr);
10626 }
10627
10628
after_param_blue_changedx(LiVESSpinButton * spinbutton,livespointer udata)10629 static void after_param_blue_changedx(LiVESSpinButton * spinbutton, livespointer udata) {
10630 LiVESWidgetColor colr;
10631
10632 LiVESWidget *cbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), CBUTTON_KEY);
10633 LiVESWidget *sp_green = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPGREEN_KEY);
10634 LiVESWidget *sp_red = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPRED_KEY);
10635 #if LIVES_WIDGET_COLOR_HAS_ALPHA
10636 LiVESWidget *sp_alpha = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPALPHA_KEY);
10637 #endif
10638
10639 int new_blue = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
10640 int old_green = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_green));
10641 int old_red = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_red));
10642
10643 colr.red = LIVES_WIDGET_COLOR_SCALE_255(old_red);
10644 colr.green = LIVES_WIDGET_COLOR_SCALE_255(old_green);
10645 colr.blue = LIVES_WIDGET_COLOR_SCALE_255(new_blue);
10646
10647 #if LIVES_WIDGET_COLOR_HAS_ALPHA
10648 if (sp_alpha) {
10649 int old_alpha = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_alpha));
10650 colr.alpha = LIVES_WIDGET_COLOR_SCALE_255(old_alpha);
10651 } else colr.alpha = 1.0;
10652 #endif
10653 lives_color_button_set_color(LIVES_COLOR_BUTTON(cbutton), &colr);
10654 }
10655
10656
after_param_alpha_changedx(LiVESSpinButton * spinbutton,livespointer udata)10657 static void after_param_alpha_changedx(LiVESSpinButton * spinbutton, livespointer udata) {
10658 LiVESWidgetColor colr;
10659
10660 LiVESWidget *cbutton = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(spinbutton), CBUTTON_KEY);
10661 LiVESWidget *sp_green = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPGREEN_KEY);
10662 LiVESWidget *sp_blue = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPBLUE_KEY);
10663 LiVESWidget *sp_red = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(cbutton), SPRED_KEY);
10664
10665 int new_alpha = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(spinbutton));
10666 int old_red = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_red));
10667 int old_green = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_green));
10668 int old_blue = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(sp_blue));
10669
10670 colr.red = LIVES_WIDGET_COLOR_SCALE_255(old_red);
10671 colr.green = LIVES_WIDGET_COLOR_SCALE_255(old_green);
10672 colr.blue = LIVES_WIDGET_COLOR_SCALE_255(old_blue);
10673
10674 #if LIVES_WIDGET_COLOR_HAS_ALPHA
10675 colr.alpha = LIVES_WIDGET_COLOR_SCALE_255(new_alpha);
10676 #else
10677 lives_color_button_set_alpha(LIVES_COLOR_BUTTON(cbutton), LIVES_WIDGET_COLOR_SCALE_255(new_alpha));
10678 #endif
10679 lives_color_button_set_color(LIVES_COLOR_BUTTON(cbutton), &colr);
10680 }
10681
10682
lives_standard_color_button_new(LiVESBox * box,const char * name,boolean use_alpha,lives_colRGBA64_t * rgba,LiVESWidget ** sb_red,LiVESWidget ** sb_green,LiVESWidget ** sb_blue,LiVESWidget ** sb_alpha)10683 LiVESWidget *lives_standard_color_button_new(LiVESBox * box, const char *name, boolean use_alpha, lives_colRGBA64_t *rgba,
10684 LiVESWidget **sb_red, LiVESWidget **sb_green, LiVESWidget **sb_blue, LiVESWidget **sb_alpha) {
10685 LiVESWidgetColor colr;
10686 LiVESWidget *cbutton, *labelcname = NULL;
10687 LiVESWidget *hbox = NULL;
10688 LiVESWidget *layout;
10689 LiVESWidget *frame = lives_standard_frame_new(NULL, 0., FALSE);
10690 LiVESWidget *spinbutton_red = NULL, *spinbutton_green = NULL, *spinbutton_blue = NULL, *spinbutton_alpha = NULL;
10691 LiVESWidget *parent = NULL;
10692 char *tmp, *tmp2;
10693
10694 int packing_width = 0;
10695
10696 boolean parent_is_layout = FALSE;
10697 boolean expand = FALSE;
10698
10699 widget_opts.last_label = NULL;
10700
10701 lives_container_set_border_width(LIVES_CONTAINER(frame), 0);
10702
10703 if (box) {
10704 parent = lives_widget_get_parent(LIVES_WIDGET(box));
10705 if (parent && LIVES_IS_TABLE(parent) &&
10706 lives_widget_object_get_data(LIVES_WIDGET_OBJECT(parent), WADDED_KEY)) {
10707 parent_is_layout = TRUE;
10708 lives_table_set_column_homogeneous(LIVES_TABLE(parent), FALSE);
10709 hbox = LIVES_WIDGET(box);
10710 } else {
10711 hbox = make_inner_hbox(LIVES_BOX(box), !box || widget_opts.swap_label || !labelcname);
10712 }
10713 expand = LIVES_SHOULD_EXPAND_EXTRA_FOR(hbox);
10714
10715 if (LIVES_SHOULD_EXPAND_WIDTH) packing_width = widget_opts.packing_width >> 1;
10716 }
10717
10718 colr.red = LIVES_WIDGET_COLOR_SCALE_65535(rgba->red);
10719 colr.green = LIVES_WIDGET_COLOR_SCALE_65535(rgba->green);
10720 colr.blue = LIVES_WIDGET_COLOR_SCALE_65535(rgba->blue);
10721 #if LIVES_WIDGET_COLOR_HAS_ALPHA
10722 if (use_alpha) colr.alpha = LIVES_WIDGET_COLOR_SCALE_65535(rgba->alpha);
10723 else colr.alpha = 1.;
10724 #endif
10725
10726 cbutton = lives_color_button_new_with_color(&colr);
10727
10728 lives_color_button_set_use_alpha(LIVES_COLOR_BUTTON(cbutton), use_alpha);
10729 lives_color_button_set_color(LIVES_COLOR_BUTTON(cbutton), &colr);
10730 lives_widget_apply_theme(cbutton, LIVES_WIDGET_STATE_NORMAL);
10731 lives_widget_apply_theme2(cbutton, LIVES_WIDGET_STATE_PRELIGHT, TRUE);
10732 lives_widget_set_border_color(frame, LIVES_WIDGET_STATE_NORMAL, &palette->normal_fore);
10733
10734 #if !LIVES_WIDGET_COLOR_HAS_ALPHA
10735 if (use_alpha)
10736 lives_color_button_set_alpha(LIVES_COLOR_BUTTON(cbutton), rgba->alpha);
10737 #endif
10738
10739 if (name && box) {
10740 // must do this before re-using translation string !
10741 if (widget_opts.mnemonic_label) {
10742 labelcname = lives_standard_label_new_with_mnemonic_widget(name, cbutton);
10743 } else labelcname = lives_standard_label_new(name);
10744 lives_widget_set_show_hide_with(cbutton, labelcname);
10745 lives_widget_set_sensitive_with(cbutton, labelcname);
10746 }
10747
10748 lives_widget_set_tooltip_text(cbutton, (_("Click to set the colour")));
10749 lives_color_button_set_title(LIVES_COLOR_BUTTON(cbutton), _("Select Colour"));
10750
10751 if (box) {
10752 if (!widget_opts.swap_label) {
10753 if (labelcname) {
10754 if (LIVES_SHOULD_EXPAND_WIDTH) lives_widget_set_margin_left(labelcname, widget_opts.packing_width >> 2);
10755 lives_box_pack_start(LIVES_BOX(hbox), labelcname, FALSE, FALSE, widget_opts.packing_width);
10756 if (parent_is_layout) {
10757 hbox = lives_layout_hbox_new(LIVES_TABLE(parent));
10758 widget_opts.justify = LIVES_JUSTIFY_END;
10759 }
10760 }
10761 }
10762
10763 if (sb_red) {
10764 layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY);
10765 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, NULL);
10766 spinbutton_red = lives_standard_spin_button_new((tmp = (_("_Red"))), rgba->red / 255., 0., 255., 1., 1., 0,
10767 (LiVESBox *)hbox, (tmp2 = (_("The red value (0 - 255)"))));
10768 lives_free(tmp);
10769 lives_free(tmp2);
10770 lives_entry_set_width_chars(LIVES_ENTRY(spinbutton_red), 3);
10771 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, layout);
10772 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(spinbutton_red), CBUTTON_KEY, cbutton);
10773 *sb_red = spinbutton_red;
10774 lives_signal_sync_connect(LIVES_GUI_OBJECT(spinbutton_red), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
10775 LIVES_GUI_CALLBACK(after_param_red_changedx), NULL);
10776 if (parent_is_layout) {
10777 hbox = lives_layout_hbox_new(LIVES_TABLE(parent));
10778 } else if (expand) add_fill_to_box(LIVES_BOX(hbox));
10779 lives_widget_set_sensitive_with(cbutton, spinbutton_red);
10780 lives_widget_set_show_hide_with(cbutton, spinbutton_red);
10781 }
10782
10783 if (sb_green) {
10784 layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY);
10785 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, NULL);
10786 spinbutton_green = lives_standard_spin_button_new((tmp = (_("_Green"))), rgba->green / 255., 0., 255., 1., 1., 0,
10787 (LiVESBox *)hbox, (tmp2 = (_("The green value (0 - 255)"))));
10788 lives_free(tmp);
10789 lives_free(tmp2);
10790 lives_entry_set_width_chars(LIVES_ENTRY(spinbutton_green), 3);
10791 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, layout);
10792 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(spinbutton_green), CBUTTON_KEY, cbutton);
10793 *sb_green = spinbutton_green;
10794 lives_signal_sync_connect(LIVES_GUI_OBJECT(spinbutton_green), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
10795 LIVES_GUI_CALLBACK(after_param_green_changedx), NULL);
10796 if (parent_is_layout) {
10797 hbox = lives_layout_hbox_new(LIVES_TABLE(parent));
10798 } else if (expand) add_fill_to_box(LIVES_BOX(hbox));
10799 lives_widget_set_sensitive_with(cbutton, spinbutton_green);
10800 lives_widget_set_show_hide_with(cbutton, spinbutton_green);
10801 }
10802
10803 if (sb_blue) {
10804 layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY);
10805 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, NULL);
10806 spinbutton_blue = lives_standard_spin_button_new((tmp = (_("_Blue"))), rgba->blue / 255., 0., 255., 1., 1., 0,
10807 (LiVESBox *)hbox, (tmp2 = (_("The blue value (0 - 255)"))));
10808 lives_free(tmp);
10809 lives_free(tmp2);
10810 lives_entry_set_width_chars(LIVES_ENTRY(spinbutton_blue), 3);
10811 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, layout);
10812 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(spinbutton_blue), CBUTTON_KEY, cbutton);
10813 *sb_blue = spinbutton_blue;
10814 lives_signal_sync_connect(LIVES_GUI_OBJECT(spinbutton_blue), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
10815 LIVES_GUI_CALLBACK(after_param_blue_changedx), NULL);
10816 if (parent_is_layout) {
10817 hbox = lives_layout_hbox_new(LIVES_TABLE(parent));
10818 } else if (expand) add_fill_to_box(LIVES_BOX(hbox));
10819 lives_widget_set_sensitive_with(cbutton, spinbutton_blue);
10820 lives_widget_set_show_hide_with(cbutton, spinbutton_blue);
10821 }
10822
10823 if (use_alpha && sb_alpha) {
10824 layout = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY);
10825 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, NULL);
10826 spinbutton_alpha = lives_standard_spin_button_new((tmp = (_("_Alpha"))), rgba->alpha / 255., 0., 255., 1., 1., 0,
10827 (LiVESBox *)hbox, (tmp2 = (_("The alpha value (0 - 255)"))));
10828 lives_free(tmp);
10829 lives_free(tmp2);
10830 lives_entry_set_width_chars(LIVES_ENTRY(spinbutton_alpha), 3);
10831 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(hbox), WH_LAYOUT_KEY, layout);
10832 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(spinbutton_alpha), CBUTTON_KEY, cbutton);
10833 *sb_alpha = spinbutton_alpha;
10834 lives_signal_sync_connect(LIVES_GUI_OBJECT(spinbutton_alpha), LIVES_WIDGET_VALUE_CHANGED_SIGNAL,
10835 LIVES_GUI_CALLBACK(after_param_alpha_changedx), NULL);
10836 if (parent_is_layout) {
10837 hbox = lives_layout_hbox_new(LIVES_TABLE(parent));
10838 } else if (expand) add_fill_to_box(LIVES_BOX(hbox));
10839 lives_widget_set_sensitive_with(cbutton, spinbutton_alpha);
10840 lives_widget_set_show_hide_with(cbutton, spinbutton_alpha);
10841 }
10842
10843 if (parent_is_layout) {
10844 widget_opts.justify = LIVES_JUSTIFY_DEFAULT;
10845 hbox = make_inner_hbox(LIVES_BOX(hbox), TRUE);
10846 }
10847
10848 lives_container_add(LIVES_CONTAINER(frame), cbutton);
10849 lives_box_pack_start(LIVES_BOX(hbox), frame, TRUE, FALSE, packing_width * 2.);
10850
10851 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(cbutton), SPRED_KEY, spinbutton_red);
10852 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(cbutton), SPGREEN_KEY, spinbutton_green);
10853 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(cbutton), SPBLUE_KEY, spinbutton_blue);
10854 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(cbutton), SPALPHA_KEY, spinbutton_alpha);
10855
10856 lives_widget_set_show_hide_parent(cbutton);
10857
10858 if (widget_opts.apply_theme) {
10859 lives_widget_set_padding(cbutton, 0);
10860 }
10861
10862 if (widget_opts.swap_label) {
10863 if (labelcname) {
10864 if (parent_is_layout) {
10865 hbox = lives_layout_hbox_new(LIVES_TABLE(parent));
10866 widget_opts.justify = LIVES_JUSTIFY_START;
10867 }
10868 if (LIVES_SHOULD_EXPAND_WIDTH) lives_widget_set_margin_right(labelcname, widget_opts.packing_width >> 2);
10869 lives_box_pack_start(LIVES_BOX(hbox), labelcname, FALSE, FALSE, widget_opts.packing_width);
10870 }
10871 }
10872 }
10873
10874 if (parent_is_layout) {
10875 widget_opts.justify = LIVES_JUSTIFY_DEFAULT;
10876 }
10877
10878 lives_signal_sync_connect(LIVES_GUI_OBJECT(cbutton), LIVES_WIDGET_COLOR_SET_SIGNAL,
10879 LIVES_GUI_CALLBACK(on_pwcolselx), NULL);
10880
10881 widget_opts.last_label = labelcname;
10882 return cbutton;
10883 }
10884
10885
10886 // utils
10887
10888 #if GTK_CHECK_VERSION(3, 10, 0)
10889
10890 static const char *LIVES_STOCK_ALTS[N_STOCK_ALTS];
10891
lives_get_stock_icon_alt(int alt_stock_id)10892 const char *lives_get_stock_icon_alt(int alt_stock_id) {
10893 return LIVES_STOCK_ALTS[alt_stock_id];
10894 }
10895
10896 static const char *lives_icon_get_stock_alt(LiVESIconTheme * icon_theme, const char *str, ...) GNU_SENTINEL;
lives_icon_get_stock_alt(LiVESIconTheme * icon_theme,const char * str,...)10897 static const char *lives_icon_get_stock_alt(LiVESIconTheme * icon_theme, const char *str, ...) {
10898 va_list xargs;
10899 va_start(xargs, str);
10900 for (; str; str++) {
10901 if (lives_has_icon(icon_theme, str, LIVES_ICON_SIZE_BUTTON)) break;
10902 }
10903 va_end(xargs);
10904 return str;
10905 }
10906 #endif
10907
10908
widget_helper_set_stock_icon_alts(LiVESIconTheme * icon_theme)10909 void widget_helper_set_stock_icon_alts(LiVESIconTheme * icon_theme) {
10910 #if GTK_CHECK_VERSION(3, 10, 0)
10911 LIVES_STOCK_ALTS[STOCK_ALTS_MEDIA_PAUSE] =
10912 lives_icon_get_stock_alt(icon_theme, LIVES_STOCK_MEDIA_PAUSE_ALT_1, LIVES_STOCK_MEDIA_PAUSE_ALT_2, (char *)NULL);
10913 LIVES_STOCK_ALTS[STOCK_ALTS_KEEP] =
10914 lives_icon_get_stock_alt(icon_theme, LIVES_STOCK_KEEP_ALT_1, LIVES_STOCK_KEEP_ALT_2, (char *)NULL);
10915 #endif
10916 }
10917
10918
widget_helper_init(void)10919 boolean widget_helper_init(void) {
10920 #ifdef GUI_GTK
10921 GSList *flist, *slist;
10922 LiVESList *dlist, *xlist = NULL;
10923 register int i;
10924 #endif
10925
10926 #if !defined(GUI_GTK) || GTK_CHECK_VERSION(3, 10, 0)
10927 lives_snprintf(LIVES_STOCK_LABEL_CANCEL, 32, "%s", (_("_Cancel")));
10928 lives_snprintf(LIVES_STOCK_LABEL_OK, 32, "%s", (_("_OK")));
10929 lives_snprintf(LIVES_STOCK_LABEL_YES, 32, "%s", (_("_Yes")));
10930 lives_snprintf(LIVES_STOCK_LABEL_NO, 32, "%s", (_("_No")));
10931 lives_snprintf(LIVES_STOCK_LABEL_SAVE, 32, "%s", (_("_Save")));
10932 lives_snprintf(LIVES_STOCK_LABEL_SAVE_AS, 32, "%s", (_("Save _As")));
10933 lives_snprintf(LIVES_STOCK_LABEL_OPEN, 32, "%s", (_("_Open")));
10934 lives_snprintf(LIVES_STOCK_LABEL_QUIT, 32, "%s", (_("_Quit")));
10935 lives_snprintf(LIVES_STOCK_LABEL_APPLY, 32, "%s", (_("_Apply")));
10936 lives_snprintf(LIVES_STOCK_LABEL_CLOSE, 32, "%s", (_("_Close")));
10937 lives_snprintf(LIVES_STOCK_LABEL_REVERT, 32, "%s", (_("_Revert")));
10938 lives_snprintf(LIVES_STOCK_LABEL_REFRESH, 32, "%s", (_("_Refresh")));
10939 lives_snprintf(LIVES_STOCK_LABEL_DELETE, 32, "%s", (_("_Delete")));
10940 lives_snprintf(LIVES_STOCK_LABEL_GO_FORWARD, 32, "%s", (_("_Forward")));
10941 lives_snprintf(LIVES_STOCK_LABEL_MEDIA_FORWARD, 32, "%s", (_("R_ewind")));
10942 lives_snprintf(LIVES_STOCK_LABEL_MEDIA_REWIND, 32, "%s", (_("_Forward")));
10943 lives_snprintf(LIVES_STOCK_LABEL_MEDIA_PLAY, 32, "%s", (_("_Play")));
10944 lives_snprintf(LIVES_STOCK_LABEL_MEDIA_PAUSE, 32, "%s", (_("P_ause")));
10945 lives_snprintf(LIVES_STOCK_LABEL_MEDIA_STOP, 32, "%s", (_("_Stop")));
10946 lives_snprintf(LIVES_STOCK_LABEL_MEDIA_RECORD, 32, "%s", (_("_Record")));
10947 lives_snprintf(LIVES_STOCK_LABEL_SELECT_ALL, 32, "%s", (_("_Select All")));
10948
10949 // non-standard
10950 lives_snprintf(LIVES_STOCK_LABEL_CLOSE_WINDOW, 32, "%s", (_("_Close Window")));
10951 lives_snprintf(LIVES_STOCK_LABEL_SKIP, 32, "%s", (_("_Skip")));
10952 lives_snprintf(LIVES_STOCK_LABEL_SELECT, 32, "%s", (_("_Select")));
10953 #endif
10954
10955 def_widget_opts = _def_widget_opts;
10956 lives_memcpy(&widget_opts, &def_widget_opts, sizeof(widget_opts_t));
10957
10958 // TODO: - for rtl set swap_labels ?
10959
10960 #ifdef GUI_GTK
10961 gtk_accel_map_add_entry("<LiVES>/save", LIVES_KEY_s, LIVES_CONTROL_MASK);
10962 gtk_accel_map_add_entry("<LiVES>/quit", LIVES_KEY_q, LIVES_CONTROL_MASK);
10963
10964 slist = flist = gdk_pixbuf_get_formats();
10965 while (slist) {
10966 GdkPixbufFormat *form = (GdkPixbufFormat *)slist->data;
10967 char **ext = gdk_pixbuf_format_get_extensions(form);
10968 for (i = 0; ext[i]; i++) {
10969 xlist = lives_list_append_unique(xlist, lives_strdup(ext[i]));
10970 }
10971 lives_strfreev(ext);
10972 slist = slist->next;
10973 }
10974 g_slist_free(flist);
10975 #endif
10976
10977 if (xlist) {
10978 dlist = xlist;
10979 widget_opts.image_filter = (char **)lives_malloc((lives_list_length(xlist) + 1) * sizeof(char *));
10980 for (i = 0; dlist; i++) {
10981 widget_opts.image_filter[i] = lives_strdup_printf("*.%s", (char *)dlist->data);
10982 dlist = dlist->next;
10983 }
10984 widget_opts.image_filter[i] = NULL;
10985 lives_list_free_all(&xlist);
10986 }
10987 return TRUE;
10988 }
10989
10990
widget_opts_rescale(double scale)10991 boolean widget_opts_rescale(double scale) {
10992 widget_opts.scale = scale;
10993 if (def_widget_opts.css_min_width != -1) {
10994 widget_opts.css_min_width = (int)((double)def_widget_opts.css_min_width * widget_opts.scale + .5);
10995 widget_opts.css_min_width = ((widget_opts.css_min_width + 1) >> 1) << 1;
10996 }
10997 if (def_widget_opts.css_min_height != -1) {
10998 widget_opts.css_min_height = (int)((double)def_widget_opts.css_min_height * widget_opts.scale + .5);
10999 widget_opts.css_min_height = ((widget_opts.css_min_height + 1) >> 1) << 1;
11000 }
11001 widget_opts.border_width = (int)((double)def_widget_opts.border_width * widget_opts.scale + .5);
11002 widget_opts.packing_width = (int)((double)def_widget_opts.packing_width * widget_opts.scale + .5);
11003 widget_opts.packing_height = (int)((double)def_widget_opts.packing_height * widget_opts.scale + .5);
11004 widget_opts.filler_len = (int)((double)def_widget_opts.filler_len * widget_opts.scale + .5);
11005 return TRUE;
11006 }
11007
11008
lives_widget_queue_draw_if_visible(LiVESWidget * widget)11009 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_draw_if_visible(LiVESWidget * widget) {
11010 if (GTK_IS_WIDGET(widget) && gtk_widget_is_drawable(widget)) {
11011 lives_widget_queue_draw(widget);
11012 return TRUE;
11013 }
11014 return FALSE;
11015 }
11016
11017
lives_widget_queue_draw_and_update(LiVESWidget * widget)11018 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_queue_draw_and_update(LiVESWidget * widget) {
11019 lives_widget_queue_draw(widget);
11020 lives_widget_process_updates(widget);
11021 return FALSE;
11022 }
11023
11024
lives_utf8_strcmpfunc(livesconstpointer a,livesconstpointer b,livespointer fwd)11025 int lives_utf8_strcmpfunc(livesconstpointer a, livesconstpointer b, livespointer fwd) {
11026 // do not inline !
11027 int ret;
11028 char *tmp1, *tmp2;
11029 if (LIVES_POINTER_TO_INT(fwd))
11030 ret = lives_strcmp_ordered((tmp1 = lives_utf8_collate_key(a, -1)),
11031 (tmp2 = lives_utf8_collate_key(b, -1)));
11032 else
11033 ret = lives_strcmp_ordered((tmp1 = lives_utf8_collate_key(b, -1)),
11034 (tmp2 = lives_utf8_collate_key(a, -1)));
11035 lives_free(tmp1);
11036 lives_free(tmp2);
11037 return ret;
11038 }
11039
11040
lives_utf8_menu_strcmpfunc(livesconstpointer a,livesconstpointer b,livespointer fwd)11041 static int lives_utf8_menu_strcmpfunc(livesconstpointer a, livesconstpointer b, livespointer fwd) {
11042 return lives_utf8_strcmpfunc(lives_menu_item_get_text((LiVESWidget *)a), lives_menu_item_get_text((LiVESWidget *)b), fwd);
11043 }
11044
11045
lives_menu_list_sort_alpha(LiVESList * list,boolean fwd)11046 WIDGET_HELPER_LOCAL_INLINE LiVESList *lives_menu_list_sort_alpha(LiVESList * list, boolean fwd) {
11047 return lives_list_sort_with_data(list, lives_utf8_menu_strcmpfunc, LIVES_INT_TO_POINTER(fwd));
11048 }
11049
11050
add_sorted_list_to_menu(LiVESMenu * menu,LiVESList * menu_list)11051 LiVESList *add_sorted_list_to_menu(LiVESMenu * menu, LiVESList * menu_list) {
11052 LiVESList **seclist;
11053 LiVESList *xmenu_list = menu_list = lives_menu_list_sort_alpha(menu_list, TRUE);
11054 while (menu_list) {
11055 if (!(LIVES_POINTER_TO_INT(lives_widget_object_get_data(LIVES_WIDGET_OBJECT(menu_list->data), HIDDEN_KEY)))) {
11056 lives_container_add(LIVES_CONTAINER(menu), (LiVESWidget *)menu_list->data);
11057 }
11058 if ((seclist = (LiVESList **)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(menu_list->data), SECLIST_KEY)) != NULL)
11059 * seclist = lives_list_prepend(*seclist, lives_widget_object_get_data(LIVES_WIDGET_OBJECT(menu_list->data),
11060 SECLIST_VAL_KEY));
11061 menu_list = menu_list->next;
11062 }
11063 return xmenu_list;
11064 }
11065
11066
lives_has_icon(LiVESIconTheme * icon_theme,const char * stock_id,LiVESIconSize size)11067 boolean lives_has_icon(LiVESIconTheme * icon_theme, const char *stock_id, LiVESIconSize size) {
11068 boolean has_icon = FALSE;
11069 #ifdef GUI_GTK
11070 #if GTK_CHECK_VERSION(3, 0, 0)
11071 GtkIconInfo *iset = gtk_icon_theme_lookup_icon(icon_theme, stock_id, size, 0);
11072 #else
11073 GtkIconSet *iset = gtk_icon_factory_lookup_default(stock_id);
11074 #endif
11075 has_icon = (iset != NULL);
11076 #endif
11077 return has_icon;
11078 }
11079
11080
lives_painter_set_source_rgb_from_lives_rgb(lives_painter_t * cr,lives_colRGB48_t * col)11081 WIDGET_HELPER_GLOBAL_INLINE lives_colRGB48_t *lives_painter_set_source_rgb_from_lives_rgb(lives_painter_t *cr,
11082 lives_colRGB48_t *col) {
11083 lives_painter_set_source_rgb(cr, (double)col->red / 65535.,
11084 (double)col->green / 65535.,
11085 (double)col->blue / 65535.);
11086 return col;
11087 }
11088
11089
lives_painter_set_source_rgb_from_lives_rgba(lives_painter_t * cr,lives_colRGBA64_t * col)11090 WIDGET_HELPER_GLOBAL_INLINE lives_colRGBA64_t *lives_painter_set_source_rgb_from_lives_rgba(lives_painter_t *cr,
11091 lives_colRGBA64_t *col) {
11092 lives_painter_set_source_rgb(cr, (double)col->red / 65535.,
11093 (double)col->green / 65535.,
11094 (double)col->blue / 65535.);
11095 return col;
11096 }
11097
11098
lives_painter_set_source_rgb_from_lives_widget_color(lives_painter_t * cr,LiVESWidgetColor * wcol)11099 WIDGET_HELPER_GLOBAL_INLINE LiVESWidgetColor *lives_painter_set_source_rgb_from_lives_widget_color(lives_painter_t *cr,
11100 LiVESWidgetColor * wcol) {
11101 lives_colRGBA64_t col;
11102 widget_color_to_lives_rgba(&col, wcol);
11103 lives_painter_set_source_rgb_from_lives_rgba(cr, &col);
11104 return wcol;
11105 }
11106
11107
clear_widget_bg(LiVESWidget * widget,lives_painter_surface_t * s)11108 WIDGET_HELPER_GLOBAL_INLINE boolean clear_widget_bg(LiVESWidget * widget, lives_painter_surface_t *s) {
11109 lives_painter_t *cr;
11110 if (!s) return FALSE;
11111 if (!(cr = lives_painter_create_from_surface(s))) return FALSE;
11112 else {
11113 int rwidth = lives_widget_get_allocation_width(LIVES_WIDGET(widget));
11114 int rheight = lives_widget_get_allocation_height(LIVES_WIDGET(widget));
11115 lives_painter_render_background(widget, cr, 0., 0., rwidth, rheight);
11116 lives_painter_destroy(cr);
11117 }
11118 return TRUE;
11119 }
11120
11121
clear_widget_bg_area(LiVESWidget * widget,lives_painter_surface_t * s,double x,double y,double width,double height)11122 WIDGET_HELPER_GLOBAL_INLINE boolean clear_widget_bg_area(LiVESWidget * widget, lives_painter_surface_t *s,
11123 double x, double y, double width, double height) {
11124 lives_painter_t *cr;
11125 if (!s) return FALSE;
11126 if (!(cr = lives_painter_create_from_surface(s))) return FALSE;
11127 else {
11128 int rwidth = lives_widget_get_allocation_width(LIVES_WIDGET(widget));
11129 int rheight = lives_widget_get_allocation_height(LIVES_WIDGET(widget));
11130 if (width <= 0.) width = rwidth;
11131 if (height <= 0.) height = rheight;
11132 lives_painter_render_background(widget, cr, x, y, width, height);
11133 lives_painter_destroy(cr);
11134 }
11135 return TRUE;
11136 }
11137
11138
lives_cursor_unref(LiVESXCursor * cursor)11139 WIDGET_HELPER_GLOBAL_INLINE boolean lives_cursor_unref(LiVESXCursor * cursor) {
11140 #ifdef GUI_GTK
11141 #if GTK_CHECK_VERSION(3, 0, 0)
11142 g_object_unref(LIVES_GUI_OBJECT(cursor));
11143 #else
11144 gdk_cursor_unref(cursor);
11145 return TRUE;
11146 #endif
11147 #endif
11148 #ifdef GUI_QT
11149 delete cursor;
11150 return TRUE;
11151 #endif
11152 return FALSE;
11153 }
11154
11155
lives_widget_apply_theme(LiVESWidget * widget,LiVESWidgetState state)11156 void lives_widget_apply_theme(LiVESWidget * widget, LiVESWidgetState state) {
11157 if (!palette || ((palette->style & STYLE_1) && !widget_opts.apply_theme)) return;
11158 lives_widget_set_fg_color(widget, state, &palette->normal_fore);
11159 lives_widget_set_bg_color(widget, state, &palette->normal_back);
11160 #if GTK_CHECK_VERSION(3, 0, 0)
11161 lives_widget_set_base_color(widget, state, &palette->normal_back);
11162 lives_widget_set_text_color(widget, state, &palette->normal_fore);
11163 #endif
11164 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget), THEME_KEY,
11165 LIVES_INT_TO_POINTER(widget_opts.apply_theme));
11166 }
11167
11168
lives_widget_apply_theme2(LiVESWidget * widget,LiVESWidgetState state,boolean set_fg)11169 void lives_widget_apply_theme2(LiVESWidget * widget, LiVESWidgetState state, boolean set_fg) {
11170 if (!widget_opts.apply_theme) {
11171 if (!(palette->style & STYLE_1)) {
11172 lives_widget_set_fg_color(widget, state, &palette->normal_fore);
11173 lives_widget_set_bg_color(widget, state, &palette->normal_back);
11174 }
11175 return;
11176 }
11177 if (set_fg)
11178 lives_widget_set_fg_color(widget, state, &palette->menu_and_bars_fore);
11179 lives_widget_set_bg_color(widget, state, &palette->menu_and_bars);
11180 }
11181
11182
lives_widget_apply_theme3(LiVESWidget * widget,LiVESWidgetState state)11183 void lives_widget_apply_theme3(LiVESWidget * widget, LiVESWidgetState state) {
11184 if (!widget_opts.apply_theme) {
11185 if (!(palette->style & STYLE_1)) {
11186 lives_widget_set_fg_color(widget, state, &palette->normal_fore);
11187 lives_widget_set_bg_color(widget, state, &palette->normal_back);
11188 }
11189 return;
11190 }
11191 if (palette->style & STYLE_1) {
11192 lives_widget_set_text_color(widget, state, &palette->info_text);
11193 lives_widget_set_base_color(widget, state, &palette->info_base);
11194 lives_widget_set_fg_color(widget, state, &palette->info_text);
11195 lives_widget_set_bg_color(widget, state, &palette->info_base);
11196 }
11197 }
11198
11199
lives_widget_apply_theme_dimmed(LiVESWidget * widget,LiVESWidgetState state,int dimval)11200 void lives_widget_apply_theme_dimmed(LiVESWidget * widget, LiVESWidgetState state, int dimval) {
11201 if (!widget_opts.apply_theme) return;
11202 if (palette->style & STYLE_1) {
11203 LiVESWidgetColor dimmed_fg;
11204 lives_widget_color_copy(&dimmed_fg, &palette->normal_fore);
11205 lives_widget_color_mix(&dimmed_fg, &palette->normal_back, (float)dimval / 65535.);
11206 lives_widget_set_fg_color(widget, state, &dimmed_fg);
11207 lives_widget_set_bg_color(widget, state, &palette->normal_back);
11208 }
11209 }
11210
11211
lives_widget_apply_theme_dimmed2(LiVESWidget * widget,LiVESWidgetState state,int dimval)11212 void lives_widget_apply_theme_dimmed2(LiVESWidget * widget, LiVESWidgetState state, int dimval) {
11213 if (!widget_opts.apply_theme) return;
11214 if (palette->style & STYLE_1) {
11215 LiVESWidgetColor dimmed_fg;
11216 lives_widget_color_copy(&dimmed_fg, &palette->menu_and_bars_fore);
11217 lives_widget_color_mix(&dimmed_fg, &palette->menu_and_bars, (float)dimval / 65535.);
11218 lives_widget_set_fg_color(widget, state, &dimmed_fg);
11219 lives_widget_set_bg_color(widget, state, &palette->menu_and_bars);
11220 }
11221 }
11222
11223
lives_entry_set_completion_from_list(LiVESEntry * entry,LiVESList * xlist)11224 boolean lives_entry_set_completion_from_list(LiVESEntry * entry, LiVESList * xlist) {
11225 #ifdef GUI_GTK
11226 GtkListStore *store;
11227 LiVESEntryCompletion *completion;
11228 store = gtk_list_store_new(1, LIVES_COL_TYPE_STRING);
11229
11230 while (xlist) {
11231 LiVESTreeIter iter;
11232 gtk_list_store_append(store, &iter);
11233 gtk_list_store_set(store, &iter, 0, (char *)xlist->data, -1);
11234 xlist = xlist->next;
11235 }
11236
11237 completion = gtk_entry_completion_new();
11238 gtk_entry_completion_set_model(completion, (GtkTreeModel *)store);
11239 gtk_entry_completion_set_text_column(completion, 0);
11240 gtk_entry_completion_set_inline_completion(completion, TRUE);
11241 gtk_entry_completion_set_popup_set_width(completion, TRUE);
11242 gtk_entry_completion_set_popup_completion(completion, TRUE);
11243 gtk_entry_completion_set_popup_single_match(completion, FALSE);
11244 gtk_entry_set_completion(entry, completion);
11245 return TRUE;
11246 #endif
11247 return FALSE;
11248 }
11249
11250
lives_window_center(LiVESWindow * window)11251 boolean lives_window_center(LiVESWindow * window) {
11252 if (!widget_opts.no_gui) {
11253 int xcen, ycen;
11254 int width, height;
11255 int bx, by;
11256
11257 lives_window_set_monitor(LIVES_WINDOW(window), widget_opts.monitor);
11258
11259 if (!mainw->mgeom) {
11260 lives_widget_show(LIVES_WIDGET(window));
11261 lives_window_set_position(LIVES_WINDOW(window), LIVES_WIN_POS_CENTER_ALWAYS);
11262 return TRUE;
11263 }
11264
11265 lives_window_set_position(LIVES_WINDOW(window), LIVES_WIN_POS_CENTER_ALWAYS);
11266
11267 width = lives_widget_get_allocation_width(LIVES_WIDGET(window));
11268 if (width == 0) width = ((int)(620. * widget_opts.scale)); // MIN_MSGBOX_WIDTH in interface.h
11269 height = lives_widget_get_allocation_height(LIVES_WIDGET(window));
11270
11271 get_border_size(LIVES_WIDGET(window), &bx, &by);
11272 width += bx;
11273 height += by;
11274
11275 xcen = mainw->mgeom[widget_opts.monitor].x + ((mainw->mgeom[widget_opts.monitor].width - width) >> 1);
11276
11277 ycen = mainw->mgeom[widget_opts.monitor].y + ((mainw->mgeom[widget_opts.monitor].height - height) >> 1);
11278 lives_window_move(LIVES_WINDOW(window), xcen, ycen);
11279 }
11280 return TRUE;
11281 }
11282
11283
lives_window_uncenter(LiVESWindow * window)11284 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_uncenter(LiVESWindow * window) {
11285 lives_window_set_position(LIVES_WINDOW(window), LIVES_WIN_POS_NONE);
11286 return TRUE;
11287 }
11288
11289
lives_widget_get_fg_color(LiVESWidget * widget,LiVESWidgetColor * color)11290 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_get_fg_color(LiVESWidget * widget, LiVESWidgetColor * color) {
11291 return lives_widget_get_fg_state_color(widget, LIVES_WIDGET_STATE_NORMAL, color);
11292 }
11293
11294
lives_widget_unparent(LiVESWidget * widget)11295 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_unparent(LiVESWidget * widget) {
11296 return lives_container_remove(LIVES_CONTAINER(lives_widget_get_parent(widget)), widget);
11297 }
11298
11299
_toggle_if_condmet(LiVESWidget * tbut,livespointer widget,boolean cond,const char * type)11300 static void _toggle_if_condmet(LiVESWidget * tbut, livespointer widget, boolean cond, const char *type) {
11301 char *keyval;
11302 int *condx;
11303
11304 if (!cond) {
11305 keyval = lives_strdup_printf("%p_in%s_cond", widget, type);
11306 condx = (int *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(tbut), keyval);
11307 if (condx && *condx != 0) cond = TRUE;
11308 } else {
11309 keyval = lives_strdup_printf("%p_%s_cond", widget, type);
11310 condx = (int *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(tbut), keyval);
11311 if (condx && *condx <= 0) cond = FALSE;
11312 }
11313 lives_free(keyval);
11314 if (!strcmp(type, "sens"))
11315 lives_widget_set_sensitive(LIVES_WIDGET(widget), cond);
11316 else if (!strcmp(type, "visi")) {
11317 if (cond) lives_widget_show(LIVES_WIDGET(widget));
11318 else lives_widget_hide(LIVES_WIDGET(widget));
11319 }
11320 }
11321
toggle_set_sensitive(LiVESWidget * tbut,livespointer widget)11322 static void toggle_set_sensitive(LiVESWidget * tbut, livespointer widget) {
11323 if (LIVES_IS_TOGGLE_BUTTON(tbut))
11324 _toggle_if_condmet(tbut, widget, lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(tbut)), "sens");
11325 else if (LIVES_IS_TOGGLE_TOOL_BUTTON(tbut))
11326 _toggle_if_condmet(tbut, widget, lives_toggle_tool_button_get_active(LIVES_TOGGLE_TOOL_BUTTON(tbut)),
11327 "sens");
11328 else if (LIVES_IS_CHECK_MENU_ITEM(tbut))
11329 _toggle_if_condmet(tbut, widget, lives_check_menu_item_get_active(LIVES_CHECK_MENU_ITEM(tbut)),
11330 "sens");
11331 }
11332
toggle_set_insensitive(LiVESWidget * tbut,livespointer widget)11333 static void toggle_set_insensitive(LiVESWidget * tbut, livespointer widget) {
11334 if (LIVES_IS_TOGGLE_BUTTON(tbut))
11335 _toggle_if_condmet(tbut, widget, !lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(tbut)),
11336 "sens");
11337 if (LIVES_IS_TOGGLE_TOOL_BUTTON(tbut))
11338 _toggle_if_condmet(tbut, widget, !lives_toggle_tool_button_get_active(LIVES_TOGGLE_TOOL_BUTTON(tbut)),
11339 "sens");
11340 else if (LIVES_IS_CHECK_MENU_ITEM(tbut))
11341 _toggle_if_condmet(tbut, widget, !lives_check_menu_item_get_active(LIVES_CHECK_MENU_ITEM(tbut)),
11342 "sens");
11343 }
11344
toggle_set_visible(LiVESWidget * tbut,livespointer widget)11345 static void toggle_set_visible(LiVESWidget * tbut, livespointer widget) {
11346 if (LIVES_IS_TOGGLE_BUTTON(tbut))
11347 _toggle_if_condmet(tbut, widget, lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(tbut)), "visi");
11348 else if (LIVES_IS_TOGGLE_TOOL_BUTTON(tbut))
11349 _toggle_if_condmet(tbut, widget, lives_toggle_tool_button_get_active(LIVES_TOGGLE_TOOL_BUTTON(tbut)),
11350 "visi");
11351 else if (LIVES_IS_CHECK_MENU_ITEM(tbut))
11352 _toggle_if_condmet(tbut, widget, lives_check_menu_item_get_active(LIVES_CHECK_MENU_ITEM(tbut)),
11353 "visi");
11354 }
11355
toggle_set_invisible(LiVESWidget * tbut,livespointer widget)11356 static void toggle_set_invisible(LiVESWidget * tbut, livespointer widget) {
11357 if (LIVES_IS_TOGGLE_BUTTON(tbut))
11358 _toggle_if_condmet(tbut, widget, !lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(tbut)),
11359 "visi");
11360 else if (LIVES_IS_TOGGLE_TOOL_BUTTON(tbut))
11361 _toggle_if_condmet(tbut, widget, !lives_toggle_tool_button_get_active(LIVES_TOGGLE_TOOL_BUTTON(tbut)),
11362 "visi");
11363 else if (LIVES_IS_CHECK_MENU_ITEM(tbut))
11364 _toggle_if_condmet(tbut, widget, !lives_check_menu_item_get_active(LIVES_CHECK_MENU_ITEM(tbut)),
11365 "visi");
11366 }
11367
11368 // togglebutton functions
11369
toggle_sets_sensitive_cond(LiVESWidget * tb,LiVESWidget * widget,livespointer condsens,livespointer condinsens,boolean invert)11370 boolean toggle_sets_sensitive_cond(LiVESWidget * tb, LiVESWidget * widget,
11371 livespointer condsens, livespointer condinsens, boolean invert) {
11372 if (condsens) {
11373 /// set sensitive only if *condsens > 0
11374 char *keyval = lives_strdup_printf("%p_sens_cond", widget);
11375 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(tb), keyval, condsens);
11376 }
11377
11378 if (condinsens) {
11379 /// set insensitive only if *condinsens == 0
11380 char *keyval = lives_strdup_printf("%p_insens_cond", widget);
11381 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(tb), keyval, condinsens);
11382 }
11383
11384 if (!invert) {
11385 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(tb), LIVES_WIDGET_TOGGLED_SIGNAL,
11386 LIVES_GUI_CALLBACK(toggle_set_sensitive),
11387 (livespointer)widget);
11388 toggle_set_sensitive(LIVES_WIDGET(tb), (livespointer)widget);
11389 } else {
11390 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(tb), LIVES_WIDGET_TOGGLED_SIGNAL,
11391 LIVES_GUI_CALLBACK(toggle_set_insensitive),
11392 (livespointer)widget);
11393 toggle_set_insensitive(tb, (livespointer)widget);
11394 }
11395 return TRUE;
11396 }
11397
toggle_sets_visible_cond(LiVESWidget * tb,LiVESWidget * widget,livespointer condsens,livespointer condinsens,boolean invert)11398 boolean toggle_sets_visible_cond(LiVESWidget * tb, LiVESWidget * widget,
11399 livespointer condsens, livespointer condinsens, boolean invert) {
11400 if (condsens) {
11401 /// set sensitive only if *condsens > 0
11402 char *keyval = lives_strdup_printf("%p_visi_cond", widget);
11403 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(tb), keyval, condsens);
11404 }
11405
11406 if (condinsens) {
11407 /// set insensitive only if *condinsens == 0
11408 char *keyval = lives_strdup_printf("%p_invisi_cond", widget);
11409 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(tb), keyval, condinsens);
11410 }
11411
11412 if (!invert) {
11413 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(tb), LIVES_WIDGET_TOGGLED_SIGNAL,
11414 LIVES_GUI_CALLBACK(toggle_set_visible),
11415 (livespointer)widget);
11416 toggle_set_sensitive(tb, (livespointer)widget);
11417 } else {
11418 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(tb), LIVES_WIDGET_TOGGLED_SIGNAL,
11419 LIVES_GUI_CALLBACK(toggle_set_invisible),
11420 (livespointer)widget);
11421 toggle_set_insensitive(tb, (livespointer)widget);
11422 }
11423 return TRUE;
11424 }
11425
11426
toggle_sets_sensitive(LiVESToggleButton * tb,LiVESWidget * widget,boolean invert)11427 WIDGET_HELPER_GLOBAL_INLINE boolean toggle_sets_sensitive(LiVESToggleButton * tb, LiVESWidget * widget,
11428 boolean invert) {
11429 return toggle_sets_sensitive_cond(LIVES_WIDGET(tb), widget, NULL, NULL, invert);
11430 }
toggle_toolbutton_sets_sensitive(LiVESToggleToolButton * ttb,LiVESWidget * widget,boolean invert)11431 WIDGET_HELPER_GLOBAL_INLINE boolean toggle_toolbutton_sets_sensitive(LiVESToggleToolButton * ttb, LiVESWidget * widget,
11432 boolean invert) {
11433 return toggle_sets_sensitive_cond(LIVES_WIDGET(ttb), widget, NULL, NULL, invert);
11434 }
menu_sets_sensitive(LiVESCheckMenuItem * mi,LiVESWidget * widget,boolean invert)11435 WIDGET_HELPER_GLOBAL_INLINE boolean menu_sets_sensitive(LiVESCheckMenuItem * mi, LiVESWidget * widget,
11436 boolean invert) {
11437 return toggle_sets_sensitive_cond(LIVES_WIDGET(mi), widget, NULL, NULL, invert);
11438 }
11439
toggle_sets_visible(LiVESToggleButton * tb,LiVESWidget * widget,boolean invert)11440 WIDGET_HELPER_GLOBAL_INLINE boolean toggle_sets_visible(LiVESToggleButton * tb, LiVESWidget * widget,
11441 boolean invert) {
11442 return toggle_sets_visible_cond(LIVES_WIDGET(tb), widget, NULL, NULL, invert);
11443 }
toggle_toolbutton_sets_visible(LiVESToggleToolButton * ttb,LiVESWidget * widget,boolean invert)11444 WIDGET_HELPER_GLOBAL_INLINE boolean toggle_toolbutton_sets_visible(LiVESToggleToolButton * ttb, LiVESWidget * widget,
11445 boolean invert) {
11446 return toggle_sets_visible_cond(LIVES_WIDGET(ttb), widget, NULL, NULL, invert);
11447 }
menu_sets_visible(LiVESCheckMenuItem * mi,LiVESWidget * widget,boolean invert)11448 WIDGET_HELPER_GLOBAL_INLINE boolean menu_sets_visible(LiVESCheckMenuItem * mi, LiVESWidget * widget,
11449 boolean invert) {
11450 return toggle_sets_visible_cond(LIVES_WIDGET(mi), widget, NULL, NULL, invert);
11451 }
11452
11453
11454 // widget callback sets togglebutton active
widget_act_toggle(LiVESWidget * widget,LiVESWidget * togglebutton)11455 boolean widget_act_toggle(LiVESWidget * widget, LiVESWidget * togglebutton) {
11456 if (!lives_widget_is_sensitive(LIVES_WIDGET(togglebutton))) return FALSE;
11457 if (LIVES_IS_TOGGLE_TOOL_BUTTON(togglebutton))
11458 lives_toggle_tool_button_set_active(LIVES_TOGGLE_TOOL_BUTTON(togglebutton), TRUE);
11459 else
11460 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(togglebutton), TRUE);
11461 return FALSE;
11462 }
11463
11464
11465 // widget callback sets togglebutton inactive
widget_inact_toggle(LiVESWidget * widget,LiVESWidget * togglebutton)11466 boolean widget_inact_toggle(LiVESWidget * widget, LiVESWidget * togglebutton) {
11467 if (!lives_widget_is_sensitive(LIVES_WIDGET(togglebutton))) return FALSE;
11468 if (LIVES_IS_TOGGLE_TOOL_BUTTON(togglebutton))
11469 lives_toggle_tool_button_set_active(LIVES_TOGGLE_TOOL_BUTTON(togglebutton), FALSE);
11470 else
11471 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(togglebutton), FALSE);
11472 return FALSE;
11473 }
11474
11475
label_act_toggle(LiVESWidget * widget,LiVESXEventButton * event,LiVESWidget * togglebutton)11476 boolean label_act_toggle(LiVESWidget * widget, LiVESXEventButton * event, LiVESWidget * togglebutton) {
11477 if (mainw && LIVES_IS_PLAYING) return FALSE;
11478 if (LIVES_IS_TOGGLE_TOOL_BUTTON(togglebutton))
11479 return lives_toggle_tool_button_toggle(LIVES_TOGGLE_TOOL_BUTTON(togglebutton));
11480 return lives_toggle_button_toggle(LIVES_TOGGLE_BUTTON(togglebutton));
11481 }
11482
11483
11484 // set callback so that togglebutton controls var
toggle_toggles_var(LiVESToggleButton * tbut,boolean * var,boolean invert)11485 WIDGET_HELPER_GLOBAL_INLINE boolean toggle_toggles_var(LiVESToggleButton * tbut, boolean * var, boolean invert) {
11486 if (invert) lives_toggle_button_set_active(tbut, !(*var));
11487 else lives_toggle_button_set_active(tbut, *var);
11488 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(tbut), LIVES_WIDGET_TOGGLED_SIGNAL,
11489 LIVES_GUI_CALLBACK(togglevar_cb),
11490 (livespointer)var);
11491 return TRUE;
11492 }
11493
lives_toggle_button_toggle(LiVESToggleButton * tbutton)11494 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_toggle(LiVESToggleButton * tbutton) {
11495 if (lives_toggle_button_get_active(tbutton)) return lives_toggle_button_set_active(tbutton, FALSE);
11496 else return lives_toggle_button_set_active(tbutton, TRUE);
11497 }
11498
lives_toggle_tool_button_toggle(LiVESToggleToolButton * tbutton)11499 WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_tool_button_toggle(LiVESToggleToolButton * tbutton) {
11500 if (lives_toggle_tool_button_get_active(tbutton)) return lives_toggle_tool_button_set_active(tbutton, FALSE);
11501 else return lives_toggle_tool_button_set_active(tbutton, TRUE);
11502 }
11503
11504
_set_tooltips_state(LiVESWidget * widget,livespointer state)11505 static void _set_tooltips_state(LiVESWidget * widget, livespointer state) {
11506 #ifdef GUI_GTK
11507 #if GTK_CHECK_VERSION(2, 12, 0)
11508 char *ttip;
11509 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), TTIPS_OVERRIDE_KEY)) return;
11510
11511 if (LIVES_POINTER_TO_INT(state)) {
11512 // enable
11513 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), TTIPS_HIDE_KEY)) {
11514 if (!lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), SHOWALL_OVERRIDE_KEY)) {
11515 lives_widget_show(widget);
11516 }
11517 return;
11518 }
11519 ttip = (char *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), TTIPS_KEY);
11520 if (ttip) {
11521 lives_widget_set_tooltip_text(widget, ttip);
11522 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget), TTIPS_KEY, NULL);
11523 }
11524 } else {
11525 if (lives_widget_object_get_data(LIVES_WIDGET_OBJECT(widget), TTIPS_HIDE_KEY)) {
11526 lives_widget_hide(widget);
11527 return;
11528 }
11529 ttip = gtk_widget_get_tooltip_text(widget);
11530 lives_widget_object_set_data_auto(LIVES_WIDGET_OBJECT(widget), TTIPS_KEY, ttip);
11531 lives_widget_set_tooltip_text(widget, NULL);
11532 }
11533 if (LIVES_IS_CONTAINER(widget)) {
11534 lives_container_forall(LIVES_CONTAINER(widget), _set_tooltips_state, state);
11535 }
11536 #endif
11537 #endif
11538
11539 }
11540
11541
set_tooltips_state(LiVESWidget * widget,boolean state)11542 WIDGET_HELPER_GLOBAL_INLINE boolean set_tooltips_state(LiVESWidget * widget, boolean state) {
11543 #ifdef GUI_GTK
11544 #if GTK_CHECK_VERSION(2, 12, 0)
11545 _set_tooltips_state(widget, LIVES_INT_TO_POINTER(state));
11546 return TRUE;
11547 #endif
11548 #endif
11549 return FALSE;
11550 }
11551
11552
lives_spin_button_get_snapval(LiVESSpinButton * button,double val)11553 WIDGET_HELPER_GLOBAL_INLINE double lives_spin_button_get_snapval(LiVESSpinButton * button, double val) {
11554 double stepval, min, max, nval, stepfix;
11555 int digs = gtk_spin_button_get_digits(button);
11556 boolean wrap = gtk_spin_button_get_wrap(button);
11557 double tenpow = (double)lives_10pow(digs);
11558 gtk_spin_button_get_increments(button, &stepval, NULL);
11559 gtk_spin_button_get_range(button, &min, &max);
11560 stepfix = tenpow / stepval;
11561 if (val >= 0.)
11562 nval = (double)((int64_t)(val * stepfix + .5)) / stepfix;
11563 else
11564 nval = (double)((int64_t)(val * stepfix - .5)) / stepfix;
11565 if (nval < min) {
11566 if (wrap) while (nval < min) nval += (max - min);
11567 else nval = min;
11568 }
11569 if (nval > max) {
11570 if (wrap) while (nval > max) nval -= (max - min);
11571 else nval = max;
11572 }
11573 return nval;
11574 }
11575
11576
set_child_colour_internal(LiVESWidget * widget,livespointer set_allx)11577 static void set_child_colour_internal(LiVESWidget * widget, livespointer set_allx) {
11578 boolean set_all = LIVES_POINTER_TO_INT(set_allx);
11579
11580 if (!set_all && LIVES_IS_BUTTON(widget)) return; // avoids a problem with filechooser
11581 if (set_all || LIVES_IS_LABEL(widget)) {
11582 lives_widget_apply_theme(widget, LIVES_WIDGET_STATE_NORMAL);
11583 if (!LIVES_IS_LABEL(widget))
11584 lives_widget_apply_theme(widget, LIVES_WIDGET_STATE_INSENSITIVE);
11585 }
11586 if (LIVES_IS_CONTAINER(widget)) {
11587 lives_container_forall(LIVES_CONTAINER(widget), set_child_colour_internal, set_allx);
11588 }
11589 }
11590
11591
set_child_colour(LiVESWidget * widget,boolean set_all)11592 WIDGET_HELPER_GLOBAL_INLINE void set_child_colour(LiVESWidget * widget, boolean set_all) {
11593 // set widget and all children widgets
11594 // if set_all is FALSE, we only set labels (and ignore labels in buttons)
11595 set_child_colour_internal(widget, LIVES_INT_TO_POINTER(set_all));
11596 }
11597
11598
set_child_dimmed_colour_internal(LiVESWidget * widget,livespointer dim)11599 static void set_child_dimmed_colour_internal(LiVESWidget * widget, livespointer dim) {
11600 int dimval = LIVES_POINTER_TO_INT(dim);
11601
11602 lives_widget_apply_theme_dimmed(widget, LIVES_WIDGET_STATE_INSENSITIVE, dimval);
11603 lives_widget_apply_theme_dimmed(widget, LIVES_WIDGET_STATE_NORMAL, dimval);
11604
11605 if (LIVES_IS_CONTAINER(widget)) {
11606 lives_container_forall(LIVES_CONTAINER(widget), set_child_dimmed_colour_internal, dim);
11607 }
11608 }
11609
11610
set_child_dimmed_colour(LiVESWidget * widget,int dim)11611 WIDGET_HELPER_GLOBAL_INLINE void set_child_dimmed_colour(LiVESWidget * widget, int dim) {
11612 // set widget and all children widgets
11613 // fg is affected dim value
11614 // dim takes a value from 0 (full fg) -> 65535 (full bg)
11615 set_child_dimmed_colour_internal(widget, LIVES_INT_TO_POINTER(dim));
11616 }
11617
11618
set_child_dimmed_colour2_internal(LiVESWidget * widget,livespointer dim)11619 static void set_child_dimmed_colour2_internal(LiVESWidget * widget, livespointer dim) {
11620 int dimval = LIVES_POINTER_TO_INT(dim);
11621
11622 lives_widget_apply_theme_dimmed2(widget, LIVES_WIDGET_STATE_INSENSITIVE, dimval);
11623
11624 if (LIVES_IS_CONTAINER(widget)) {
11625 lives_container_forall(LIVES_CONTAINER(widget), set_child_dimmed_colour2_internal, dim);
11626 }
11627 }
11628
11629
set_child_dimmed_colour2(LiVESWidget * widget,int dim)11630 WIDGET_HELPER_GLOBAL_INLINE void set_child_dimmed_colour2(LiVESWidget * widget, int dim) {
11631 // set widget and all children widgets
11632 // fg is affected dim value
11633 // dim takes a value from 0 (full fg) -> 65535 (full bg)
11634 set_child_dimmed_colour2_internal(widget, LIVES_INT_TO_POINTER(dim));
11635 }
11636
11637
set_child_alt_colour_internal(LiVESWidget * widget,livespointer set_allx)11638 static void set_child_alt_colour_internal(LiVESWidget * widget, livespointer set_allx) {
11639 boolean set_all = LIVES_POINTER_TO_INT(set_allx);
11640
11641 if (!set_all && LIVES_IS_BUTTON(widget)) return;
11642
11643 if (set_all || LIVES_IS_LABEL(widget)) {
11644 lives_widget_apply_theme2(widget, LIVES_WIDGET_STATE_INSENSITIVE, TRUE);
11645 lives_widget_apply_theme2(widget, LIVES_WIDGET_STATE_NORMAL, TRUE);
11646 lives_widget_object_set_data(LIVES_WIDGET_OBJECT(widget),
11647 THEME_KEY, LIVES_INT_TO_POINTER(2));
11648 }
11649
11650 if (LIVES_IS_CONTAINER(widget)) {
11651 lives_container_forall(LIVES_CONTAINER(widget), set_child_alt_colour_internal, set_allx);
11652 }
11653 }
11654
11655
set_child_alt_colour(LiVESWidget * widget,boolean set_all)11656 WIDGET_HELPER_GLOBAL_INLINE void set_child_alt_colour(LiVESWidget * widget, boolean set_all) {
11657 // set widget and all children widgets
11658 // if set_all is FALSE, we only set labels (and ignore labels in buttons)
11659
11660 set_child_alt_colour_internal(widget, LIVES_INT_TO_POINTER(set_all));
11661 }
11662
11663
set_child_alt_colour_internal_prelight(LiVESWidget * widget,livespointer data)11664 static void set_child_alt_colour_internal_prelight(LiVESWidget * widget, livespointer data) {
11665 lives_widget_apply_theme2(widget, LIVES_WIDGET_STATE_PRELIGHT, TRUE);
11666 if (LIVES_IS_CONTAINER(widget)) {
11667 lives_container_forall(LIVES_CONTAINER(widget), set_child_alt_colour_internal_prelight, NULL);
11668 }
11669 }
11670
11671
set_child_alt_colour_prelight(LiVESWidget * widget)11672 WIDGET_HELPER_GLOBAL_INLINE void set_child_alt_colour_prelight(LiVESWidget * widget) {
11673 // set widget and all children widgets
11674 // if set_all is FALSE, we only set labels (and ignore labels in buttons)
11675 set_child_alt_colour_internal_prelight(widget, NULL);
11676 }
11677
11678
set_child_colour3_internal(LiVESWidget * widget,livespointer set_allx)11679 static void set_child_colour3_internal(LiVESWidget * widget, livespointer set_allx) {
11680 boolean set_all = LIVES_POINTER_TO_INT(set_allx);
11681
11682 if (!set_all && (LIVES_IS_BUTTON(widget))) {// || LIVES_IS_SCROLLBAR(widget))) {
11683 lives_widget_set_base_color(widget, LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars);
11684 lives_widget_set_text_color(widget, LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars_fore);
11685 return;
11686 }
11687
11688 if (set_all || LIVES_IS_LABEL(widget)) {
11689 lives_widget_apply_theme3(widget, LIVES_WIDGET_STATE_NORMAL);
11690 }
11691
11692 if (LIVES_IS_CONTAINER(widget)) {
11693 lives_container_forall(LIVES_CONTAINER(widget), set_child_colour3_internal, set_allx);
11694 }
11695 }
11696
11697
set_child_colour3(LiVESWidget * widget,boolean set_all)11698 WIDGET_HELPER_GLOBAL_INLINE void set_child_colour3(LiVESWidget * widget, boolean set_all) {
11699 // set widget and all children widgets
11700 // if set_all is FALSE, we only set labels (and ignore labels in buttons)
11701
11702 set_child_colour3_internal(widget, LIVES_INT_TO_POINTER(set_all));
11703 }
11704
11705
lives_text_view_get_text(LiVESTextView * textview)11706 char *lives_text_view_get_text(LiVESTextView * textview) {
11707 LiVESTextIter siter, eiter;
11708 LiVESTextBuffer *textbuf = lives_text_view_get_buffer(textview);
11709 lives_text_buffer_get_start_iter(textbuf, &siter);
11710 lives_text_buffer_get_end_iter(textbuf, &eiter);
11711 return lives_text_buffer_get_text(textbuf, &siter, &eiter, FALSE);
11712 }
11713
11714
lives_text_view_set_text(LiVESTextView * textview,const char * text,int len)11715 boolean lives_text_view_set_text(LiVESTextView * textview, const char *text, int len) {
11716 LiVESTextBuffer *textbuf = lives_text_view_get_buffer(textview);
11717 if (textbuf)
11718 return lives_text_buffer_set_text(textbuf, text, len);
11719 return FALSE;
11720 }
11721
11722
lives_text_buffer_insert_at_end(LiVESTextBuffer * tbuff,const char * text)11723 boolean lives_text_buffer_insert_at_end(LiVESTextBuffer * tbuff, const char *text) {
11724 LiVESTextIter xiter;
11725 if (lives_text_buffer_get_end_iter(tbuff, &xiter))
11726 return lives_text_buffer_insert(tbuff, &xiter, text, -1);
11727 return FALSE;
11728 }
11729
11730
get_box_child_index(LiVESBox * box,LiVESWidget * tchild)11731 int get_box_child_index(LiVESBox * box, LiVESWidget * tchild) {
11732 LiVESList *list = lives_container_get_children(LIVES_CONTAINER(box));
11733 int val = -1;
11734 if (list) {
11735 val = lives_list_index(list, tchild);
11736 lives_list_free(list);
11737 }
11738 return val;
11739 }
11740
11741
lives_box_pack_top(LiVESBox * box,LiVESWidget * child,boolean expand,boolean fill,uint32_t padding)11742 WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_top(LiVESBox * box, LiVESWidget * child, boolean expand, boolean fill,
11743 uint32_t padding) {
11744 lives_box_pack_start(box, child, expand, fill, padding);
11745 lives_box_reorder_child(box, child, 0);
11746 return TRUE;
11747 }
11748
11749
lives_container_child_set_shrinkable(LiVESContainer * c,LiVESWidget * child,boolean val)11750 WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_child_set_shrinkable(LiVESContainer * c, LiVESWidget * child, boolean val) {
11751 #ifdef GUI_GTK
11752 GValue xbool = G_VALUE_INIT;
11753 g_value_init(&xbool, G_TYPE_BOOLEAN);
11754 g_value_set_boolean(&xbool, val);
11755 gtk_container_child_set_property(c, child, "shrink", &xbool);
11756 return TRUE;
11757 #endif
11758 return FALSE;
11759 }
11760
11761
set_submenu_colours(LiVESMenu * menu,LiVESWidgetColor * colf,LiVESWidgetColor * colb)11762 boolean set_submenu_colours(LiVESMenu * menu, LiVESWidgetColor * colf, LiVESWidgetColor * colb) {
11763 LiVESList *children = lives_container_get_children(LIVES_CONTAINER(menu)), *list = children;
11764 lives_widget_set_bg_color(LIVES_WIDGET(menu), LIVES_WIDGET_STATE_NORMAL, colb);
11765 lives_widget_set_fg_color(LIVES_WIDGET(menu), LIVES_WIDGET_STATE_NORMAL, colf);
11766 while (list) {
11767 LiVESWidget *child = (LiVESWidget *)list->data;
11768 if (LIVES_IS_MENU_ITEM(child)) {
11769 if ((menu = (LiVESMenu *)lives_menu_item_get_submenu(LIVES_MENU_ITEM(child))))
11770 set_submenu_colours(menu, colf, colb);
11771 else {
11772 lives_widget_set_bg_color(LIVES_WIDGET(child), LIVES_WIDGET_STATE_NORMAL, colb);
11773 lives_widget_set_fg_color(LIVES_WIDGET(child), LIVES_WIDGET_STATE_NORMAL, colf);
11774 }
11775 }
11776 list = list->next;
11777 }
11778 if (children) lives_list_free(children);
11779 return TRUE;
11780 }
11781
11782
lives_spin_button_configure(LiVESSpinButton * spinbutton,double value,double lower,double upper,double step_increment,double page_increment)11783 boolean lives_spin_button_configure(LiVESSpinButton * spinbutton, double value, double lower,
11784 double upper, double step_increment, double page_increment) {
11785 LiVESAdjustment *adj = lives_spin_button_get_adjustment(spinbutton);
11786
11787 #ifdef GUI_GTK
11788 #if GTK_CHECK_VERSION(2, 14, 0)
11789 gtk_adjustment_configure(adj, value, lower, upper, step_increment, page_increment, 0.);
11790 #else
11791 g_object_freeze_notify(LIVES_WIDGET_OBJECT(adj));
11792 adj->upper = upper;
11793 adj->lower = lower;
11794 adj->value = value;
11795 adj->step_increment = step_increment;
11796 adj->page_increment = page_increment;
11797 g_object_thaw_notify(LIVES_WIDGET_OBJECT(adj));
11798 return TRUE;
11799 #endif
11800 #endif
11801 return FALSE;
11802 }
11803
11804
lives_tree_store_find_iter(LiVESTreeStore * tstore,int col,const char * val,LiVESTreeIter * titer1,LiVESTreeIter * titer2)11805 boolean lives_tree_store_find_iter(LiVESTreeStore * tstore, int col, const char *val, LiVESTreeIter * titer1,
11806 LiVESTreeIter * titer2) {
11807 #ifdef GUI_GTK
11808 if (gtk_tree_model_iter_children(LIVES_TREE_MODEL(tstore), titer2, titer1)) {
11809 char *ret;
11810 while (1) {
11811 gtk_tree_model_get(LIVES_TREE_MODEL(tstore), titer2, col, &ret, -1);
11812 if (!lives_strcmp(ret, val)) {
11813 lives_free(ret);
11814 return TRUE;
11815 }
11816 lives_free(ret);
11817 if (!gtk_tree_model_iter_next(LIVES_TREE_MODEL(tstore), titer2)) break;
11818 }
11819 }
11820 lives_tree_store_append(tstore, titer2, titer1);
11821 lives_tree_store_set(tstore, titer2, col, val, -1);
11822 return TRUE;
11823 #endif
11824 return FALSE;
11825 }
11826
11827
11828 ///// lives specific functions
11829
11830 #include "rte_window.h"
11831 #include "ce_thumbs.h"
11832
11833 static boolean noswitch = FALSE;
11834 static boolean re_add_idlefunc = FALSE;
11835
do_some_things(void)11836 static void do_some_things(void) {
11837 // som old junk that may or may not be relevant now
11838
11839 /// clip switching is not permitted during these "artificial" context updates
11840 noswitch = mainw->noswitch;
11841
11842 /// except under very specific conditions:
11843 mainw->noswitch = !mainw->cs_is_permitted;
11844
11845 if (mainw->multitrack && mainw->multitrack->idlefunc > 0) {
11846 /// remove th multitrack timer; we don't want to trigger an autosave right now
11847 lives_timer_remove(mainw->multitrack->idlefunc);
11848 mainw->multitrack->idlefunc = 0;
11849 if (!mainw->mt_needs_idlefunc) {
11850 re_add_idlefunc = mainw->mt_needs_idlefunc = TRUE;
11851 }
11852 }
11853
11854 if (!mainw->is_exiting) {
11855 /// update the state of some widgets caused by OOB changes
11856 if (rte_window) rtew_set_key_check_state();
11857 if (mainw->ce_thumbs) {
11858 ce_thumbs_set_key_check_state();
11859 ce_thumbs_apply_liberation();
11860 if (mainw->ce_upd_clip) {
11861 ce_thumbs_highlight_current_clip();
11862 mainw->ce_upd_clip = FALSE;
11863 // *INDENT-OFF*
11864 }}}
11865 // *INDENT-ON*
11866 }
11867
11868
do_more_stuff(void)11869 static void do_more_stuff(void) {
11870 /// re-enable the multitrack autosave timer if removed it, otherwise caller can do it
11871 if (re_add_idlefunc) maybe_add_mt_idlefunc();
11872
11873 /// restore the prior state, in case it was reset by cs_is_permitted
11874 mainw->noswitch = noswitch;
11875 }
11876
11877
lives_widget_context_update(void)11878 boolean lives_widget_context_update(void) {
11879 volatile boolean clutch;
11880 static pthread_mutex_t ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
11881 if (timer_running) return FALSE;
11882 if (mainw->no_context_update) return FALSE;
11883 if (pthread_mutex_trylock(&ctx_mutex)) return FALSE;
11884 else {
11885 LiVESWidgetContext *ctx = lives_widget_context_get_thread_default();
11886 do_some_things();
11887 if (ctx && ctx != lives_widget_context_default() && gov_running) {
11888 clutch = mainw->clutch = FALSE;
11889 while (!clutch && !mainw->is_exiting) {
11890 lives_nanosleep(NSLEEP_TIME);
11891 clutch = mainw->clutch;
11892 }
11893 } else {
11894 int count = 0;
11895 while (count++ < EV_LIM && !mainw->is_exiting && lives_widget_context_pending(NULL)) {
11896 //LiVESXEvent *ev = lives_widgets_get_current_event();
11897 //if (ev) g_print("ev was %d\n", ev->type);
11898 //else g_print("NULL event\n");
11899 lives_widget_context_iteration(NULL, FALSE);
11900 //lives_nanosleep(NSLEEP_TIME);
11901 }
11902 }
11903 do_more_stuff();
11904 }
11905 pthread_mutex_unlock(&ctx_mutex);
11906 return TRUE;
11907 }
11908
11909
lives_menu_add_separator(LiVESMenu * menu)11910 LiVESWidget *lives_menu_add_separator(LiVESMenu * menu) {
11911 LiVESWidget *separatormenuitem = lives_menu_item_new();
11912 if (separatormenuitem) {
11913 lives_container_add(LIVES_CONTAINER(menu), separatormenuitem);
11914 lives_widget_set_sensitive(separatormenuitem, FALSE);
11915 }
11916 return separatormenuitem;
11917 }
11918
11919
lives_menu_item_set_text(LiVESWidget * menuitem,const char * text,boolean use_mnemonic)11920 WIDGET_HELPER_GLOBAL_INLINE void lives_menu_item_set_text(LiVESWidget * menuitem, const char *text, boolean use_mnemonic) {
11921 LiVESWidget *label;
11922 if (LIVES_IS_MENU_ITEM(menuitem)) {
11923 label = lives_bin_get_child(LIVES_BIN(menuitem));
11924 widget_opts.mnemonic_label = use_mnemonic;
11925 lives_label_set_text(LIVES_LABEL(label), text);
11926 widget_opts.mnemonic_label = TRUE;
11927 }
11928 }
11929
11930
lives_menu_item_get_text(LiVESWidget * menuitem)11931 WIDGET_HELPER_GLOBAL_INLINE const char *lives_menu_item_get_text(LiVESWidget * menuitem) {
11932 // text MUST be at least 255 chars long
11933 LiVESWidget *label = lives_bin_get_child(LIVES_BIN(menuitem));
11934 return lives_label_get_text(LIVES_LABEL(label));
11935 }
11936
11937
lives_display_get_n_screens(LiVESXDisplay * disp)11938 WIDGET_HELPER_GLOBAL_INLINE int lives_display_get_n_screens(LiVESXDisplay * disp) {
11939 #ifdef GUI_GTK
11940 #if GTK_CHECK_VERSION(3, 10, 0)
11941 return 1;
11942 #else
11943 return gdk_display_get_n_screens(disp);
11944 #endif
11945 #endif
11946 return 1;
11947 }
11948
11949
lives_set_cursor_style(lives_cursor_t cstyle,LiVESWidget * widget)11950 void lives_set_cursor_style(lives_cursor_t cstyle, LiVESWidget * widget) {
11951 #ifdef GUI_GTK
11952 LiVESXWindow *window;
11953 GdkCursor *cursor = NULL;
11954 GdkDisplay *disp;
11955 GdkCursorType ctype = GDK_X_CURSOR;
11956
11957 if (!widget) {
11958 if (mainw->recovering_files || ((!mainw->multitrack && mainw->is_ready)
11959 || (mainw->multitrack &&
11960 mainw->multitrack->is_ready))) {
11961 if (cstyle != LIVES_CURSOR_NORMAL && mainw->cursor_style == cstyle) return;
11962 window = lives_widget_get_xwindow(LIVES_MAIN_WINDOW_WIDGET);
11963 } else return;
11964 } else window = lives_widget_get_xwindow(widget);
11965
11966 if (!window || !LIVES_IS_XWINDOW(window)) return;
11967
11968 switch (cstyle) {
11969 case LIVES_CURSOR_NORMAL:
11970 break;
11971 case LIVES_CURSOR_BUSY:
11972 ctype = GDK_WATCH;
11973 break;
11974 case LIVES_CURSOR_CENTER_PTR:
11975 ctype = GDK_CENTER_PTR;
11976 break;
11977 case LIVES_CURSOR_HAND2:
11978 ctype = GDK_HAND2;
11979 break;
11980 case LIVES_CURSOR_SB_H_DOUBLE_ARROW:
11981 ctype = GDK_SB_H_DOUBLE_ARROW;
11982 break;
11983 case LIVES_CURSOR_CROSSHAIR:
11984 ctype = GDK_CROSSHAIR;
11985 break;
11986 case LIVES_CURSOR_TOP_LEFT_CORNER:
11987 ctype = GDK_TOP_LEFT_CORNER;
11988 break;
11989 case LIVES_CURSOR_BOTTOM_RIGHT_CORNER:
11990 ctype = GDK_BOTTOM_RIGHT_CORNER;
11991 break;
11992 default: return;
11993 }
11994 if (!widget) {
11995 if (mainw->multitrack) mainw->multitrack->cursor_style = cstyle;
11996 else mainw->cursor_style = cstyle;
11997 }
11998 #if GTK_CHECK_VERSION(2, 22, 0)
11999 cursor = gdk_window_get_cursor(window);
12000 if (cursor && gdk_cursor_get_cursor_type(cursor) == ctype) return;
12001 cursor = NULL;
12002 #endif
12003 disp = gdk_window_get_display(window);
12004 if (cstyle != LIVES_CURSOR_NORMAL) {
12005 cursor = gdk_cursor_new_for_display(disp, ctype);
12006 gdk_window_set_cursor(window, cursor);
12007 } else gdk_window_set_cursor(window, NULL);
12008 if (cursor) lives_cursor_unref(cursor);
12009 #endif
12010
12011 // TODO: gdk_x11_cursor_update_theme (
12012 // XFixesChangeCursor (Display *dpy, Cursor source, Cursor destination);
12013 // and then wait for X11 event...
12014 // then no need for the majority of lives_window_process_updates().....
12015 }
12016
12017
hide_cursor(LiVESXWindow * window)12018 void hide_cursor(LiVESXWindow * window) {
12019 //make the cursor invisible in playback windows
12020 #ifdef GUI_GTK
12021
12022 #if GTK_CHECK_VERSION(2, 16, 0)
12023 if (GDK_IS_WINDOW(window)) {
12024 #if GTK_CHECK_VERSION(3, 16, 0)
12025 GdkCursor *cursor = gdk_cursor_new_for_display(gdk_window_get_display(window), GDK_BLANK_CURSOR);
12026 #else
12027 GdkCursor *cursor = gdk_cursor_new(GDK_BLANK_CURSOR);
12028 #endif
12029 if (cursor) {
12030 gdk_window_set_cursor(window, cursor);
12031 lives_cursor_unref(cursor);
12032 }
12033 }
12034 #else
12035 static GdkCursor *hidden_cursor = NULL;
12036
12037 char cursor_bits[] = {0x00};
12038 char cursormask_bits[] = {0x00};
12039 GdkPixmap *source, *mask;
12040 GdkColor fg = { 0, 0, 0, 0 };
12041 GdkColor bg = { 0, 0, 0, 0 };
12042
12043 if (!hidden_cursor) {
12044 source = gdk_bitmap_create_from_data(NULL, cursor_bits, 1, 1);
12045 mask = gdk_bitmap_create_from_data(NULL, cursormask_bits, 1, 1);
12046 hidden_cursor = gdk_cursor_new_from_pixmap(source, mask, &fg, &bg, 0, 0);
12047 g_object_unref(source);
12048 g_object_unref(mask);
12049 }
12050 if (GDK_IS_WINDOW(window)) gdk_window_set_cursor(window, hidden_cursor);
12051 #endif
12052 #endif
12053 }
12054
12055
unhide_cursor(LiVESXWindow * window)12056 WIDGET_HELPER_GLOBAL_INLINE boolean unhide_cursor(LiVESXWindow * window) {
12057 if (LIVES_IS_XWINDOW(window)) return lives_xwindow_set_cursor(window, NULL);
12058 return FALSE;
12059 }
12060
12061 ///#define USE_REVEAL - not working here
funkify_dialog(LiVESWidget * dialog)12062 void funkify_dialog(LiVESWidget * dialog) {
12063 if (prefs->funky_widgets) {
12064 LiVESWidget *frame = lives_standard_frame_new(NULL, 0., FALSE);
12065 LiVESWidget *box = lives_vbox_new(FALSE, 0);
12066 LiVESWidget *content = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
12067 LiVESWidget *action = lives_dialog_get_action_area(LIVES_DIALOG(dialog));
12068
12069 lives_container_set_border_width(LIVES_CONTAINER(dialog), 0);
12070 lives_container_set_border_width(LIVES_CONTAINER(frame), 0);
12071
12072 lives_widget_object_ref(content);
12073 lives_widget_unparent(content);
12074
12075 lives_container_add(LIVES_CONTAINER(dialog), frame);
12076 lives_container_add(LIVES_CONTAINER(frame), box);
12077
12078 lives_box_pack_start(LIVES_BOX(box), content, TRUE, TRUE, 0);
12079
12080 lives_widget_set_margin_top(action, widget_opts.packing_height); // only works for gtk+ 3.x
12081
12082 lives_widget_show_all(frame);
12083
12084 lives_container_set_border_width(LIVES_CONTAINER(box), widget_opts.border_width * 2);
12085 #ifdef USE_REVEAL
12086 gtk_revealer_set_reveal_child(GTK_REVEALER(frame), TRUE);
12087 #endif
12088 } else {
12089 lives_container_set_border_width(LIVES_CONTAINER(dialog), widget_opts.border_width);
12090 }
12091 }
12092
12093
lives_cool_toggled(LiVESWidget * tbutton,livespointer user_data)12094 void lives_cool_toggled(LiVESWidget * tbutton, livespointer user_data) {
12095 #if GTK_CHECK_VERSION(3, 0, 0)
12096 //#if !GTK_CHECK_VERSION(3, 16, 0)
12097 // connect toggled event to this
12098 boolean *ret = (boolean *)user_data, active;
12099 if (!LIVES_IS_INTERACTIVE) return;
12100 active = ((LIVES_IS_TOGGLE_BUTTON(tbutton)
12101 && lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(tbutton))) ||
12102 (LIVES_IS_TOGGLE_TOOL_BUTTON(tbutton)
12103 && lives_toggle_tool_button_get_active(LIVES_TOGGLE_TOOL_BUTTON(tbutton))));
12104 if (prefs->lamp_buttons) {
12105 if (active) {
12106 lives_widget_set_bg_color(tbutton, LIVES_WIDGET_STATE_ACTIVE, &palette->light_green);
12107 } else lives_widget_set_bg_color(tbutton, LIVES_WIDGET_STATE_NORMAL, &palette->dark_red);
12108 }
12109 if (ret) *ret = active;
12110 lives_widget_queue_draw(tbutton);
12111 //#endif
12112 #endif
12113 }
12114
12115
draw_cool_toggle(LiVESWidget * widget,lives_painter_t * cr,livespointer data)12116 boolean draw_cool_toggle(LiVESWidget * widget, lives_painter_t *cr, livespointer data) {
12117 // connect expose event to this
12118 double rwidth = (double)lives_widget_get_allocation_width(LIVES_WIDGET(widget));
12119 double rheight = (double)lives_widget_get_allocation_height(LIVES_WIDGET(widget));
12120 double rad, scalex = 1., scaley = .8;
12121 boolean active =
12122 ((LIVES_IS_TOGGLE_BUTTON(widget) && lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(widget))) ||
12123 (LIVES_IS_TOGGLE_TOOL_BUTTON(widget)
12124 && lives_toggle_tool_button_get_active(LIVES_TOGGLE_TOOL_BUTTON(widget))));
12125
12126 if (!mainw->multitrack) rheight /= 2.;
12127
12128 lives_painter_translate(cr, rwidth * (1. - scalex) / 2., rheight * (1. - scaley) / 2.);
12129
12130 rwidth *= scalex;
12131 rheight *= scaley;
12132
12133 if (widget == mainw->ext_audio_mon) rwidth = rheight = 4.;
12134
12135 // draw the inside
12136 if (active) {
12137 lives_painter_set_source_rgba(cr, palette->light_green.red, palette->light_green.green,
12138 palette->light_green.blue, 1.);
12139 } else {
12140 lives_painter_set_source_rgba(cr, palette->dark_red.red, palette->dark_red.green,
12141 palette->dark_red.blue, 1.);
12142 }
12143
12144 // draw rounded rctangle
12145 lives_painter_rectangle(cr, 0, rwidth / 4,
12146 rwidth,
12147 rheight - rwidth / 2);
12148 lives_painter_fill(cr);
12149
12150 lives_painter_rectangle(cr, rwidth / 4, 0,
12151 rwidth / 2,
12152 rwidth / 4);
12153 lives_painter_fill(cr);
12154
12155 lives_painter_rectangle(cr, rwidth / 4, rheight - rwidth / 4,
12156 rwidth / 2,
12157 rwidth / 4);
12158 lives_painter_fill(cr);
12159 //#endif
12160
12161 rad = rwidth / 4.;
12162
12163 lives_painter_move_to(cr, rwidth / 4., rwidth / 4.);
12164 lives_painter_line_to(cr, 0., rwidth / 4.);
12165 lives_painter_arc(cr, rwidth / 4., rwidth / 4., rad, M_PI, 1.5 * M_PI);
12166 lives_painter_line_to(cr, rwidth / 4., rwidth / 4.);
12167 lives_painter_fill(cr);
12168
12169 lives_painter_move_to(cr, rwidth / 4.*3., rwidth / 4.);
12170 lives_painter_line_to(cr, rwidth / 4.*3., 0.);
12171 lives_painter_arc(cr, rwidth / 4.*3., rwidth / 4., rad, -M_PI / 2., 0.);
12172 lives_painter_line_to(cr, rwidth / 4.*3., rwidth / 4.);
12173 lives_painter_fill(cr);
12174
12175 lives_painter_move_to(cr, rwidth / 4., rheight - rwidth / 4.);
12176 lives_painter_line_to(cr, rwidth / 4., rheight);
12177 lives_painter_arc(cr, rwidth / 4., rheight - rwidth / 4., rad, M_PI / 2., M_PI);
12178 lives_painter_line_to(cr, rwidth / 4., rheight - rwidth / 4.);
12179 lives_painter_fill(cr);
12180
12181 lives_painter_move_to(cr, rwidth / 4.*3., rheight - rwidth / 4.);
12182 lives_painter_line_to(cr, rwidth, rheight - rwidth / 4.);
12183 lives_painter_arc(cr, rwidth / 4.*3., rheight - rwidth / 4., rad, 0., M_PI / 2.);
12184 lives_painter_line_to(cr, rwidth / 4.*3., rheight - rwidth / 4.);
12185 lives_painter_fill(cr);
12186
12187 // draw the surround
12188
12189 lives_painter_new_path(cr);
12190
12191 lives_painter_set_source_rgba(cr, 0., 0., 0., .8);
12192 lives_painter_set_line_width(cr, 1.);
12193
12194 lives_painter_arc(cr, rwidth / 4., rwidth / 4., rad, M_PI, 1.5 * M_PI);
12195 lives_painter_stroke(cr);
12196 lives_painter_arc(cr, rwidth / 4.*3., rwidth / 4., rad, -M_PI / 2., 0.);
12197 lives_painter_stroke(cr);
12198 lives_painter_arc(cr, rwidth / 4., rheight - rwidth / 4., rad, M_PI / 2., M_PI);
12199 lives_painter_stroke(cr);
12200 lives_painter_arc(cr, rwidth / 4.*3., rheight - rwidth / 4., rad, 0., M_PI / 2.);
12201
12202 lives_painter_stroke(cr);
12203
12204 lives_painter_move_to(cr, rwidth / 4., 0);
12205 lives_painter_line_to(cr, rwidth / 4.*3., 0);
12206
12207 lives_painter_stroke(cr);
12208
12209 lives_painter_move_to(cr, rwidth / 4., rheight);
12210 lives_painter_line_to(cr, rwidth / 4.*3., rheight);
12211
12212 lives_painter_stroke(cr);
12213
12214 lives_painter_move_to(cr, 0., rwidth / 4.);
12215 lives_painter_line_to(cr, 0., rheight - rwidth / 4.);
12216
12217 lives_painter_stroke(cr);
12218
12219 lives_painter_move_to(cr, rwidth, rwidth / 4.);
12220 lives_painter_line_to(cr, rwidth, rheight - rwidth / 4.);
12221
12222 lives_painter_stroke(cr);
12223
12224 if (active) {
12225 lives_painter_set_source_rgba(cr, 1., 1., 1., .6);
12226
12227 lives_painter_move_to(cr, rwidth / 4., rwidth / 4.);
12228 lives_painter_line_to(cr, rwidth / 4.*3., rheight - rwidth / 4.);
12229 lives_painter_stroke(cr);
12230
12231 lives_painter_move_to(cr, rwidth / 4., rheight - rwidth / 4.);
12232 lives_painter_line_to(cr, rwidth / 4.*3., rwidth / 4.);
12233 lives_painter_stroke(cr);
12234 }
12235 return TRUE;
12236 }
12237
12238
12239
lives_window_get_inner_size(LiVESWindow * win,int * x,int * y)12240 WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_get_inner_size(LiVESWindow * win, int *x, int *y) {
12241 // get size request for child to fill window "win" (assuming win is maximised and moved maximum top / left)
12242 #ifdef GUI_GTK
12243 GdkRectangle rect;
12244 gint wx, wy;
12245 gdk_window_get_frame_extents(lives_widget_get_xwindow(LIVES_WIDGET(win)), &rect);
12246 gdk_window_get_origin(lives_widget_get_xwindow(LIVES_WIDGET(win)), &wx, &wy);
12247 if (x) *x = mainw->mgeom[widget_opts.monitor].width - (wx - rect.x) * 2;
12248 if (y) *y = mainw->mgeom[widget_opts.monitor].height;
12249 return TRUE;
12250 #endif
12251 return FALSE;
12252 }
12253
12254
get_border_size(LiVESWidget * win,int * bx,int * by)12255 boolean get_border_size(LiVESWidget * win, int *bx, int *by) {
12256 #ifdef GUI_GTK
12257 if (win == LIVES_MAIN_WINDOW_WIDGET) {
12258 int eww, ewh;
12259 if (get_screen_usable_size(&eww, &ewh)) {
12260 if (bx) *bx = mainw->mgeom[widget_opts.monitor].phys_width - eww;
12261 if (by) *by = mainw->mgeom[widget_opts.monitor].phys_height - ewh;
12262 return TRUE;
12263 }
12264 if (bx) *bx =
12265 mainw->mgeom[widget_opts.monitor].phys_width - mainw->mgeom[widget_opts.monitor].width;
12266 if (by) *by =
12267 mainw->mgeom[widget_opts.monitor].phys_height - mainw->mgeom[widget_opts.monitor].height;
12268 } else {
12269 GdkRectangle rect;
12270 GdkWindow *xwin = lives_widget_get_xwindow(win);
12271 int gww, gwh;
12272 if (!xwin) return FALSE;
12273
12274 gdk_window_get_frame_extents(lives_widget_get_xwindow(win), &rect);
12275 gdk_window_get_origin(xwin, &gww, &gwh);
12276
12277 if (bx) {
12278 *bx = rect.width - lives_widget_get_allocation_width(win);
12279 }
12280 if (by) {
12281 *by = rect.height - lives_widget_get_allocation_height(win);
12282 }
12283 }
12284 return TRUE;
12285 #endif
12286 return FALSE;
12287 }
12288
12289 // Set active string to the combo box
lives_combo_set_active_string(LiVESCombo * combo,const char * active_str)12290 WIDGET_HELPER_GLOBAL_INLINE boolean lives_combo_set_active_string(LiVESCombo * combo, const char *active_str) {
12291 return lives_entry_set_text(LIVES_ENTRY(lives_bin_get_child(LIVES_BIN(combo))), active_str);
12292 }
12293
12294
lives_combo_get_entry(LiVESCombo * widget)12295 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_combo_get_entry(LiVESCombo * widget) {
12296 return lives_bin_get_child(LIVES_BIN(widget));
12297 }
12298
12299
lives_widget_set_can_focus_and_default(LiVESWidget * widget)12300 WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_can_focus_and_default(LiVESWidget * widget) {
12301 if (!lives_widget_set_can_focus(widget, TRUE)) return FALSE;
12302 return lives_widget_set_can_default(widget, TRUE);
12303 }
12304
12305
lives_general_button_clicked(LiVESButton * button,livespointer data_to_free)12306 void lives_general_button_clicked(LiVESButton * button, livespointer data_to_free) {
12307 // destroy the button top-level and free data
12308 if (LIVES_IS_WIDGET(lives_widget_get_toplevel(LIVES_WIDGET(button)))) {
12309 lives_widget_destroy(lives_widget_get_toplevel(LIVES_WIDGET(button)));
12310 lives_widget_process_updates(LIVES_MAIN_WINDOW_WIDGET);
12311 }
12312 lives_freep((void **)&data_to_free);
12313
12314 /// TODO: this is BAD. Need to check that mainw->mt_needs_idlefunc is set conistently
12315 maybe_add_mt_idlefunc(); ///< add idlefunc iff mainw->mt_needs_idlefunc is set
12316 }
12317
12318
lives_standard_hseparator_new(void)12319 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_hseparator_new(void) {
12320 LiVESWidget *hseparator = lives_hseparator_new();
12321 if (widget_opts.apply_theme) {
12322 if (prefs->extra_colours && mainw->pretty_colours) {
12323 lives_widget_set_bg_color(hseparator, LIVES_WIDGET_STATE_NORMAL, &palette->nice1);
12324 } else {
12325 lives_widget_set_bg_color(hseparator, LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars);
12326 }
12327 lives_widget_set_fg_color(hseparator, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
12328 }
12329 if (LIVES_SHOULD_EXPAND_HEIGHT)
12330 lives_widget_set_margin_top(hseparator, widget_opts.packing_height);
12331 if (LIVES_SHOULD_EXPAND_EXTRA_HEIGHT)
12332 lives_widget_set_margin_bottom(hseparator, widget_opts.packing_height);
12333 return hseparator;
12334 }
12335
12336
lives_standard_vseparator_new(void)12337 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_standard_vseparator_new(void) {
12338 LiVESWidget *vseparator = lives_vseparator_new();
12339 if (widget_opts.apply_theme) {
12340 if (prefs->extra_colours && mainw->pretty_colours) {
12341 lives_widget_set_bg_color(vseparator, LIVES_WIDGET_STATE_NORMAL, &palette->nice1);
12342 } else {
12343 lives_widget_set_bg_color(vseparator, LIVES_WIDGET_STATE_NORMAL, &palette->menu_and_bars);
12344 }
12345 lives_widget_set_fg_color(vseparator, LIVES_WIDGET_STATE_NORMAL, &palette->normal_back);
12346 }
12347 if (LIVES_SHOULD_EXPAND_WIDTH)
12348 lives_widget_set_margin_left(vseparator, widget_opts.packing_width);
12349 if (LIVES_SHOULD_EXPAND_EXTRA_WIDTH)
12350 lives_widget_set_margin_right(vseparator, widget_opts.packing_width);
12351 return vseparator;
12352 }
12353
12354
add_hsep_to_box(LiVESBox * box)12355 LiVESWidget *add_hsep_to_box(LiVESBox * box) {
12356 LiVESWidget *hseparator = lives_standard_hseparator_new();
12357 int packing_height = widget_opts.packing_height;
12358 if (LIVES_IS_HBOX(box)) packing_height = 0;
12359 lives_box_pack_start(box, hseparator, LIVES_IS_HBOX(box)
12360 || LIVES_SHOULD_EXPAND_EXTRA_FOR(box), TRUE, packing_height);
12361 return hseparator;
12362 }
12363
12364
add_vsep_to_box(LiVESBox * box)12365 LiVESWidget *add_vsep_to_box(LiVESBox * box) {
12366 LiVESWidget *vseparator = lives_standard_vseparator_new();
12367 int packing_width = widget_opts.packing_width >> 1;
12368 if (LIVES_SHOULD_EXPAND_EXTRA_FOR(box)) packing_width *= 2;
12369 if (LIVES_IS_VBOX(box)) packing_width = 0;
12370 lives_box_pack_start(box, vseparator, LIVES_IS_VBOX(box)
12371 || LIVES_SHOULD_EXPAND_EXTRA_FOR(box), TRUE, packing_width);
12372 return vseparator;
12373 }
12374
12375
12376 //#define SHOW_FILL
add_fill_to_box(LiVESBox * box)12377 LiVESWidget *add_fill_to_box(LiVESBox * box) {
12378 #ifdef SHOW_FILL
12379 LiVESWidget *widget = lives_label_new("fill");
12380 #else
12381 LiVESWidget *widget = lives_standard_label_new("");
12382 #endif
12383 if (LIVES_IS_HBOX(box)) {
12384 int flen = 0;
12385 if (LIVES_SHOULD_EXPAND_FOR(box)) {
12386 int w = 0;
12387 LingoContext *ctx = lives_widget_create_lingo_context(LIVES_WIDGET(box));
12388 flen = widget_opts.filler_len;
12389 if (ctx && LINGO_IS_CONTEXT(ctx)) {
12390 LingoLayout *layout = lingo_layout_new(ctx);
12391 if (layout && LINGO_IS_LAYOUT(layout)) {
12392 lingo_layout_set_text(layout, "X", -1);
12393 lingo_layout_get_size(layout, &w, NULL);
12394 w /= LINGO_SCALE;
12395 lives_widget_object_unref(layout);
12396 }
12397 lives_widget_object_unref(ctx);
12398 }
12399 if (w) {
12400 int nchars = (float)widget_opts.filler_len / (float)w;
12401 if (nchars > 0) {
12402 flen = 0;
12403 lives_label_set_width_chars(LIVES_LABEL(widget), nchars);
12404 }
12405 }
12406 }
12407 lives_box_pack_start(box, widget, LIVES_SHOULD_EXPAND_EXTRA_FOR(box), TRUE, flen);
12408 if (LIVES_SHOULD_EXPAND_EXTRA_FOR(box))
12409 lives_widget_set_hexpand(widget, TRUE);
12410 } else {
12411 if (LIVES_SHOULD_EXPAND_EXTRA_FOR(box)) {
12412 lives_box_pack_start(box, widget, TRUE, TRUE, widget_opts.filler_len);
12413 lives_widget_set_vexpand(widget, TRUE);
12414 } else lives_box_pack_start(box, widget, FALSE, TRUE, LIVES_SHOULD_EXPAND_FOR(box) ? widget_opts.packing_height : 0);
12415 }
12416 if (widget_opts.apply_theme == 2) set_child_alt_colour(widget, TRUE);
12417 return widget;
12418 }
12419
12420
add_spring_to_box(LiVESBox * box,int min)12421 LiVESWidget *add_spring_to_box(LiVESBox * box, int min) {
12422 LiVESWidget *widget;
12423 int filler_len = widget_opts.filler_len;
12424 int woe = widget_opts.expand;
12425 widget_opts.filler_len = min;
12426 widget_opts.expand = LIVES_EXPAND_EXTRA;
12427 widget = add_fill_to_box(box);
12428 widget_opts.expand = woe;
12429 widget_opts.filler_len = filler_len;
12430 return widget;
12431 }
12432
12433
lives_toolbar_insert_space(LiVESToolbar * bar)12434 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_toolbar_insert_space(LiVESToolbar * bar) {
12435 LiVESWidget *spacer = NULL;
12436 #ifdef GUI_GTK
12437 spacer = LIVES_WIDGET(lives_separator_tool_item_new());
12438 gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(spacer), FALSE);
12439 gtk_tool_item_set_homogeneous(LIVES_TOOL_ITEM(spacer), FALSE);
12440 gtk_tool_item_set_expand(LIVES_TOOL_ITEM(spacer), LIVES_SHOULD_EXPAND_WIDTH);
12441 lives_toolbar_insert(LIVES_TOOLBAR(bar), LIVES_TOOL_ITEM(spacer), -1);
12442 #endif
12443 return spacer;
12444 }
12445
12446
lives_toolbar_insert_label(LiVESToolbar * bar,const char * text,LiVESWidget * actwidg)12447 WIDGET_HELPER_GLOBAL_INLINE LiVESWidget *lives_toolbar_insert_label(LiVESToolbar * bar, const char *text,
12448 LiVESWidget * actwidg) {
12449 LiVESWidget *item = NULL;
12450 widget_opts.last_label = widget_opts.last_container = NULL;
12451 #ifdef GUI_GTK
12452 item = LIVES_WIDGET(lives_tool_item_new());
12453 if (!actwidg) {
12454 widget_opts.last_label = lives_label_new(text);
12455 lives_container_add(LIVES_CONTAINER(item), widget_opts.last_label);
12456 } else {
12457 widget_opts.last_container = _make_label_eventbox(text, actwidg, FALSE);
12458 lives_container_add(LIVES_CONTAINER(item), widget_opts.last_container);
12459 }
12460 lives_toolbar_insert(bar, LIVES_TOOL_ITEM(item), -1);
12461 #endif
12462 return item;
12463 }
12464
12465
lives_button_box_set_button_width(LiVESButtonBox * bbox,LiVESWidget * button,int min_width)12466 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_box_set_button_width(LiVESButtonBox * bbox, LiVESWidget * button,
12467 int min_width) {
12468 lives_button_box_set_layout(bbox, LIVES_BUTTONBOX_SPREAD);
12469 #ifdef GUI_GTK
12470 #if !GTK_CHECK_VERSION(3, 0, 0)
12471 gtk_button_box_set_child_size(bbox, min_width / 4, DLG_BUTTON_HEIGHT);
12472 return TRUE;
12473 #endif
12474 #endif
12475 lives_widget_set_size_request(button, min_width, DLG_BUTTON_HEIGHT);
12476 return TRUE;
12477 return FALSE;
12478 }
12479
12480
lives_button_box_make_first(LiVESButtonBox * bbox,LiVESWidget * widget)12481 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_box_make_first(LiVESButtonBox * bbox, LiVESWidget * widget) {
12482 #ifdef GUI_GTK
12483 gtk_button_box_set_child_secondary(bbox, widget, TRUE);
12484 gtk_button_box_set_child_non_homogeneous(bbox, widget, TRUE);
12485 if (LIVES_SHOULD_EXPAND_WIDTH) {
12486 if (LIVES_IS_CONTAINER(widget))
12487 lives_container_set_border_width(LIVES_CONTAINER(widget), widget_opts.border_width);
12488 }
12489 return TRUE;
12490 #endif
12491 return FALSE;
12492 }
12493
12494
lives_dialog_make_widget_first(LiVESDialog * dlg,LiVESWidget * widget)12495 WIDGET_HELPER_GLOBAL_INLINE boolean lives_dialog_make_widget_first(LiVESDialog * dlg, LiVESWidget * widget) {
12496 LiVESWidget *daa = lives_dialog_get_action_area(dlg);
12497 return lives_button_box_make_first(LIVES_BUTTON_BOX(daa), widget);
12498 }
12499
12500
12501
lives_button_center(LiVESWidget * button)12502 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_center(LiVESWidget * button) {
12503 if (LIVES_SHOULD_EXPAND_WIDTH)
12504 lives_widget_set_size_request(button, DEF_BUTTON_WIDTH * 4, DLG_BUTTON_HEIGHT);
12505 lives_button_box_set_layout(LIVES_BUTTON_BOX(lives_widget_get_parent(button)),
12506 LIVES_BUTTONBOX_CENTER);
12507 lives_widget_set_halign(lives_widget_get_parent(button), LIVES_ALIGN_CENTER);
12508 return TRUE;
12509 }
12510
12511
lives_button_uncenter(LiVESWidget * button,int normal_width)12512 WIDGET_HELPER_GLOBAL_INLINE boolean lives_button_uncenter(LiVESWidget * button, int normal_width) {
12513 lives_widget_set_size_request(button, normal_width, DLG_BUTTON_HEIGHT);
12514 lives_button_box_set_layout(LIVES_BUTTON_BOX(lives_widget_get_parent(button)), LIVES_BUTTONBOX_END);
12515 lives_widget_set_halign(lives_widget_get_parent(button), LIVES_ALIGN_FILL);
12516 return TRUE;
12517 }
12518
12519
lives_tool_button_set_border_color(LiVESWidget * button,LiVESWidgetState state,LiVESWidgetColor * colour)12520 boolean lives_tool_button_set_border_color(LiVESWidget * button, LiVESWidgetState state, LiVESWidgetColor * colour) {
12521 if (LIVES_IS_TOOL_BUTTON(button)) {
12522 LiVESWidget *widget, *parent;
12523 widget = lives_tool_button_get_icon_widget(LIVES_TOOL_BUTTON(button));
12524 if (!widget) widget = lives_tool_button_get_label_widget(LIVES_TOOL_BUTTON(button));
12525 if (widget) {
12526 parent = lives_widget_get_parent(widget);
12527 if (parent) lives_widget_set_bg_color(parent, state, colour);
12528 lives_widget_set_valign(widget, LIVES_ALIGN_FILL);
12529 lives_widget_set_halign(widget, LIVES_ALIGN_FILL);
12530 }
12531 return TRUE;
12532 }
12533 return FALSE;
12534 }
12535
12536
lives_standard_tool_button_new(LiVESToolbar * bar,GtkWidget * icon_widget,const char * label,const char * tooltips)12537 LiVESWidget *lives_standard_tool_button_new(LiVESToolbar * bar, GtkWidget * icon_widget, const char *label,
12538 const char *tooltips) {
12539 LiVESToolItem *tbutton;
12540 widget_opts.last_label = NULL;
12541 if (label) {
12542 if (LIVES_SHOULD_EXPAND_HEIGHT) {
12543 char *labeltext = lives_strdup_printf("\n%s\n", label);
12544 widget_opts.last_label = lives_standard_label_new(labeltext);
12545 lives_free(labeltext);
12546 } else widget_opts.last_label = lives_standard_label_new(label);
12547 }
12548 tbutton = lives_tool_button_new(icon_widget, NULL);
12549 if (widget_opts.last_label) lives_tool_button_set_label_widget(LIVES_TOOL_BUTTON(tbutton), widget_opts.last_label);
12550 if (widget_opts.apply_theme) {
12551 #if !GTK_CHECK_VERSION(3, 16, 0)
12552 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(tbutton), LIVES_WIDGET_NOTIFY_SIGNAL "sensitive",
12553 LIVES_GUI_CALLBACK(widget_state_cb), NULL);
12554 widget_state_cb(LIVES_WIDGET_OBJECT(tbutton), NULL, NULL);
12555 #endif
12556 }
12557 if (tooltips) lives_widget_set_tooltip_text(LIVES_WIDGET(tbutton), tooltips);
12558 if (bar) lives_toolbar_insert(bar, tbutton, -1);
12559 return LIVES_WIDGET(tbutton);
12560 }
12561
12562
lives_accel_path_disconnect(LiVESAccelGroup * group,const char * path)12563 WIDGET_HELPER_GLOBAL_INLINE boolean lives_accel_path_disconnect(LiVESAccelGroup * group, const char *path) {
12564 #ifdef GUI_GTK
12565 GtkAccelKey key;
12566 gtk_accel_map_lookup_entry(path, &key);
12567 gtk_accel_group_disconnect_key(group, key.accel_key, key.accel_mods);
12568 return TRUE;
12569 #endif
12570 return FALSE;
12571 }
12572
12573
lives_rgba_col_new(int red,int green,int blue,int alpha)12574 WIDGET_HELPER_GLOBAL_INLINE lives_colRGBA64_t lives_rgba_col_new(int red, int green, int blue, int alpha) {
12575 lives_colRGBA64_t lcol = {red, green, blue, alpha};
12576 return lcol;
12577 }
12578
12579
widget_color_to_lives_rgba(lives_colRGBA64_t * lcolor,LiVESWidgetColor * color)12580 WIDGET_HELPER_GLOBAL_INLINE lives_colRGBA64_t *widget_color_to_lives_rgba(lives_colRGBA64_t *lcolor, LiVESWidgetColor * color) {
12581 lcolor->red = LIVES_WIDGET_COLOR_STRETCH(color->red);
12582 lcolor->green = LIVES_WIDGET_COLOR_STRETCH(color->green);
12583 lcolor->blue = LIVES_WIDGET_COLOR_STRETCH(color->blue);
12584 #if LIVES_WIDGET_COLOR_HAS_ALPHA
12585 lcolor->alpha = LIVES_WIDGET_COLOR_STRETCH(color->alpha);
12586 #else
12587 lcolor->alpha = 65535;
12588 #endif
12589 return lcolor;
12590 }
12591
12592
lives_rgba_to_widget_color(LiVESWidgetColor * color,lives_colRGBA64_t * lcolor)12593 WIDGET_HELPER_GLOBAL_INLINE LiVESWidgetColor *lives_rgba_to_widget_color(LiVESWidgetColor * color, lives_colRGBA64_t *lcolor) {
12594 color->red = LIVES_WIDGET_COLOR_SCALE_65535(lcolor->red);
12595 color->green = LIVES_WIDGET_COLOR_SCALE_65535(lcolor->green);
12596 color->blue = LIVES_WIDGET_COLOR_SCALE_65535(lcolor->blue);
12597 #if LIVES_WIDGET_COLOR_HAS_ALPHA
12598 color->alpha = LIVES_WIDGET_COLOR_SCALE_65535(lcolor->alpha);
12599 #endif
12600 return color;
12601 }
12602
12603
lives_rgba_equal(lives_colRGBA64_t * col1,lives_colRGBA64_t * col2)12604 WIDGET_HELPER_GLOBAL_INLINE boolean lives_rgba_equal(lives_colRGBA64_t *col1, lives_colRGBA64_t *col2) {
12605 return !lives_memcmp(col1, col2, sizeof(lives_colRGBA64_t));
12606 }
12607
12608
lives_rgba_copy(lives_colRGBA64_t * col1,lives_colRGBA64_t * col2)12609 WIDGET_HELPER_GLOBAL_INLINE lives_colRGBA64_t *lives_rgba_copy(lives_colRGBA64_t *col1, lives_colRGBA64_t *col2) {
12610 col1->red = col2->red;
12611 col1->green = col2->green;
12612 col1->blue = col2->blue;
12613 col1->alpha = col2->alpha;
12614 return col1;
12615 }
12616
12617
get_textsizes_list(void)12618 LiVESList *get_textsizes_list(void) {
12619 LiVESList *textsize_list = NULL;
12620 #ifdef GUI_GTK
12621 textsize_list = lives_list_append(textsize_list, (_("Extra extra small")));
12622 textsize_list = lives_list_append(textsize_list, (_("Extra small")));
12623 textsize_list = lives_list_append(textsize_list, (_("Small")));
12624 textsize_list = lives_list_append(textsize_list, (_("Medium")));
12625 textsize_list = lives_list_append(textsize_list, (_("Large")));
12626 textsize_list = lives_list_append(textsize_list, (_("Extra large")));
12627 textsize_list = lives_list_append(textsize_list, (_("Extra extra large")));
12628 #endif
12629 return textsize_list;
12630 }
12631
12632
lives_textsize_to_string(int val)12633 const char *lives_textsize_to_string(int val) {
12634 switch (val) {
12635 case 0:
12636 return LIVES_TEXT_SIZE_XX_SMALL;
12637 case 1:
12638 return LIVES_TEXT_SIZE_X_SMALL;
12639 case 2:
12640 return LIVES_TEXT_SIZE_SMALL;
12641 case 3:
12642 return LIVES_TEXT_SIZE_MEDIUM;
12643 case 4:
12644 return LIVES_TEXT_SIZE_LARGE;
12645 case 5:
12646 return LIVES_TEXT_SIZE_X_LARGE;
12647 case 6:
12648 return LIVES_TEXT_SIZE_XX_LARGE;
12649 default:
12650 return LIVES_TEXT_SIZE_NORMAL;
12651 }
12652 }
12653