1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <limits.h>
32
33 #include "container.h"
34 #include "toolkit.h"
35 #include "headerbar.h"
36
37 #include "../common/context.h"
38 #include "../common/object.h"
39
40
41 void ui_container_begin_close(UiObject *obj) {
42 UiContainer *ct = uic_get_current_container(obj);
43 ct->close =
1;
44 }
45
46 int ui_container_finish(UiObject *obj) {
47 UiContainer *ct = uic_get_current_container(obj);
48 if(ct->close) {
49 ui_end(obj);
50 return 0;
51 }
52 return 1;
53 }
54
55 GtkWidget* ui_gtk_vbox_new(
int spacing) {
56 #if GTK_MAJOR_VERSION >=
3
57 return gtk_box_new(
GTK_ORIENTATION_VERTICAL, spacing);
58 #else
59 return gtk_vbox_new(
FALSE, spacing);
60 #endif
61 }
62
63 GtkWidget* ui_gtk_hbox_new(
int spacing) {
64 #if GTK_MAJOR_VERSION >=
3
65 return gtk_box_new(
GTK_ORIENTATION_HORIZONTAL, spacing);
66 #else
67 return gtk_hbox_new(
FALSE, spacing);
68 #endif
69 }
70
71 GtkWidget* ui_subcontainer_create(
72 UiSubContainerType type,
73 UiObject *newobj,
74 int spacing,
75 int columnspacing,
76 int rowspacing,
77 int margin)
78 {
79 GtkWidget *sub =
NULL;
80 GtkWidget *add =
NULL;
81 switch(type) {
82 default: {
83 sub = ui_gtk_vbox_new(spacing);
84 add = ui_box_set_margin(sub, margin);
85 newobj->container = ui_box_container(newobj, sub, type);
86 newobj->widget = sub;
87 break;
88 }
89 case UI_CONTAINER_HBOX: {
90 sub = ui_gtk_hbox_new(spacing);
91 add = ui_box_set_margin(sub, margin);
92 newobj->container = ui_box_container(newobj, sub, type);
93 newobj->widget = sub;
94 break;
95 }
96 case UI_CONTAINER_GRID: {
97 sub = ui_create_grid_widget(columnspacing, rowspacing);
98 add = ui_box_set_margin(sub, margin);
99 newobj->container = ui_grid_container(newobj, sub);
100 newobj->widget = sub;
101 break;
102 }
103 case UI_CONTAINER_NO_SUB: {
104 break;
105 }
106 }
107 return add;
108 }
109
110
111
112 UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type) {
113 UiBoxContainer *ct = cxCalloc(
114 obj->ctx->allocator,
115 1,
116 sizeof(UiBoxContainer));
117 ct->container.widget = box;
118 ct->container.add = ui_box_container_add;
119 ct->type = type;
120 return (UiContainer*)ct;
121 }
122
123 void ui_box_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
124 UiBoxContainer *bc = (UiBoxContainer*)ct;
125 if(ct->layout.fill !=
UI_LAYOUT_UNDEFINED) {
126 fill = ui_lb2bool(ct->layout.fill);
127 }
128
129 if(bc->has_fill && fill) {
130 fprintf(stderr,
"UiError: container has 2 filled widgets");
131 fill =
FALSE;
132 }
133 if(fill) {
134 bc->has_fill =
TRUE;
135 }
136
137 UiBool expand = fill;
138 #if GTK_MAJOR_VERSION >=
4
139 gtk_box_append(
GTK_BOX(ct->widget), widget);
140 GtkAlign align = expand ?
GTK_ALIGN_FILL :
GTK_ALIGN_START;
141 if(bc->type ==
UI_CONTAINER_VBOX) {
142 gtk_widget_set_valign(widget, align);
143 gtk_widget_set_vexpand(widget, expand);
144 gtk_widget_set_hexpand(widget,
TRUE);
145 }
else if(bc->type ==
UI_CONTAINER_HBOX) {
146 gtk_widget_set_halign(widget, align);
147 gtk_widget_set_hexpand(widget, expand);
148 gtk_widget_set_vexpand(widget,
TRUE);
149 }
150
151 #else
152 gtk_box_pack_start(
GTK_BOX(ct->widget), widget, expand, fill,
0);
153 #endif
154
155 ui_reset_layout(ct->layout);
156 ct->current = widget;
157 }
158
159 UiContainer* ui_grid_container(UiObject *obj, GtkWidget *grid) {
160 UiGridContainer *ct = cxCalloc(
161 obj->ctx->allocator,
162 1,
163 sizeof(UiGridContainer));
164 ct->container.widget = grid;
165 ct->container.add = ui_grid_container_add;
166 UI_GTK_V2(ct->width =
0);
167 UI_GTK_V2(ct->height =
1);
168 return (UiContainer*)ct;
169 }
170
171 #if GTK_MAJOR_VERSION >=
3
172 void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
173 UiGridContainer *grid = (UiGridContainer*)ct;
174
175 if(ct->layout.newline) {
176 grid->x =
0;
177 grid->y++;
178 ct->layout.newline =
FALSE;
179 }
180
181 int hexpand =
FALSE;
182 int vexpand =
FALSE;
183 int hfill =
FALSE;
184 int vfill =
FALSE;
185 if(ct->layout.fill !=
UI_LAYOUT_UNDEFINED) {
186 fill = ui_lb2bool(ct->layout.fill);
187 }
188 if(ct->layout.hexpand !=
UI_LAYOUT_UNDEFINED) {
189 hexpand = ct->layout.hexpand;
190 hfill =
TRUE;
191 }
192 if(ct->layout.vexpand !=
UI_LAYOUT_UNDEFINED) {
193 vexpand = ct->layout.vexpand;
194 vfill =
TRUE;
195 }
196 if(fill) {
197 hfill =
TRUE;
198 vfill =
TRUE;
199 }
200
201 if(!hfill) {
202 gtk_widget_set_halign(widget,
GTK_ALIGN_START);
203 }
204 if(!vfill) {
205 gtk_widget_set_valign(widget,
GTK_ALIGN_START);
206 }
207
208 gtk_widget_set_hexpand(widget, hexpand);
209 gtk_widget_set_vexpand(widget, vexpand);
210
211 int colspan = ct->layout.colspan >
0 ? ct->layout.colspan :
1;
212 int rowspan = ct->layout.rowspan >
0 ? ct->layout.rowspan :
1;
213
214 gtk_grid_attach(
GTK_GRID(ct->widget), widget, grid->x, grid->y, colspan, rowspan);
215 grid->x += colspan;
216
217 ui_reset_layout(ct->layout);
218 ct->current = widget;
219 }
220 #endif
221 #ifdef UI_GTK2
222 void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
223 UiGridContainer *grid = (UiGridContainer*)ct;
224
225 if(ct->layout.newline) {
226 grid->x =
0;
227 grid->y++;
228 ct->layout.newline =
FALSE;
229 }
230
231 int hexpand =
FALSE;
232 int vexpand =
FALSE;
233 if(ct->layout.hexpand !=
UI_LAYOUT_UNDEFINED) {
234 hexpand = ct->layout.hexpand;
235 }
236 if(ct->layout.vexpand !=
UI_LAYOUT_UNDEFINED) {
237 vexpand = ct->layout.vexpand;
238 }
239 GtkAttachOptions xoptions = hexpand ?
GTK_FILL |
GTK_EXPAND :
GTK_FILL;
240 GtkAttachOptions yoptions = vexpand ?
GTK_FILL |
GTK_EXPAND :
GTK_FILL;
241
242 int colspan = ct->layout.colspan >
0 ? ct->layout.colspan :
1;
243 int rowspan = ct->layout.rowspan >
0 ? ct->layout.rowspan :
1;
244
245
246 gtk_table_attach(
GTK_TABLE(ct->widget), widget, grid->x, grid->x+
1, grid->y, grid->y+
1, xoptions, yoptions,
0,
0);
247 grid->x++;
248 int nw = grid->x > grid->width ? grid->x : grid->width;
249 if(grid->x > grid->width || grid->y > grid->height) {
250 grid->width = nw;
251 grid->height = grid->y +
1;
252 gtk_table_resize(
GTK_TABLE(ct->widget), grid->width, grid->height);
253 }
254
255 ui_reset_layout(ct->layout);
256 ct->current = widget;
257 }
258 #endif
259
260 UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame) {
261 UiContainer *ct = cxCalloc(
262 obj->ctx->allocator,
263 1,
264 sizeof(UiContainer));
265 ct->widget = frame;
266 ct->add = ui_frame_container_add;
267 return ct;
268 }
269
270 void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
271 FRAME_SET_CHILD(ct->widget, widget);
272 }
273
274 UiContainer* ui_expander_container(UiObject *obj, GtkWidget *expander) {
275 UiContainer *ct = cxCalloc(
276 obj->ctx->allocator,
277 1,
278 sizeof(UiContainer));
279 ct->widget = expander;
280 ct->add = ui_expander_container_add;
281 return ct;
282 }
283
284 void ui_expander_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
285 EXPANDER_SET_CHILD(ct->widget, widget);
286 }
287
288 void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
289
290 SCROLLEDWINDOW_SET_CHILD(ct->widget, widget);
291 ui_reset_layout(ct->layout);
292 ct->current = widget;
293 }
294
295 UiContainer* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow) {
296 UiContainer *ct = cxCalloc(
297 obj->ctx->allocator,
298 1,
299 sizeof(UiContainer));
300 ct->widget = scrolledwindow;
301 ct->add = ui_scrolledwindow_container_add;
302 return ct;
303 }
304
305 UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview) {
306 UiTabViewContainer *ct = cxCalloc(
307 obj->ctx->allocator,
308 1,
309 sizeof(UiTabViewContainer));
310 ct->container.widget = tabview;
311 ct->container.add = ui_tabview_container_add;
312 return (UiContainer*)ct;
313 }
314
315 void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
316 UiGtkTabView *data = ui_widget_get_tabview_data(ct->widget);
317 if(!data) {
318 fprintf(stderr,
"UI Error: widget is not a tabview");
319 return;
320 }
321 data->add_tab(ct->widget, -
1, ct->layout.label, widget);
322
323 ui_reset_layout(ct->layout);
324 ct->current = widget;
325 }
326
327
328
329 GtkWidget* ui_box_set_margin(GtkWidget *box,
int margin) {
330 GtkWidget *ret = box;
331 #if GTK_MAJOR_VERSION >=
3
332 #if GTK_MAJOR_VERSION *
1000 +
GTK_MINOR_VERSION >=
3012
333 gtk_widget_set_margin_start(box, margin);
334 gtk_widget_set_margin_end(box, margin);
335 #else
336 gtk_widget_set_margin_left(box, margin);
337 gtk_widget_set_margin_right(box, margin);
338 #endif
339 gtk_widget_set_margin_top(box, margin);
340 gtk_widget_set_margin_bottom(box, margin);
341 #elif defined(
UI_GTK2)
342 GtkWidget *a = gtk_alignment_new(
0.
5,
0.
5,
1,
1);
343 gtk_alignment_set_padding(
GTK_ALIGNMENT(a), margin, margin, margin, margin);
344 gtk_container_add(
GTK_CONTAINER(a), box);
345 ret = a;
346 #endif
347 return ret;
348 }
349
350 UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, UiSubContainerType type) {
351 UiObject *current = uic_current_obj(obj);
352 UiContainer *ct = current->container;
353 UI_APPLY_LAYOUT1(current, args);
354
355 GtkWidget *box = type ==
UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing);
356 ui_set_name_and_style(box, args.name, args.style_class);
357 GtkWidget *widget = args.margin >
0 ? ui_box_set_margin(box, args.margin) : box;
358 ct->add(ct, widget,
TRUE);
359
360 UiObject *newobj = uic_object_new(obj, box);
361 newobj->container = ui_box_container(obj, box, type);
362 uic_obj_add(obj, newobj);
363
364 return widget;
365 }
366
367 UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) {
368 return ui_box_create(obj, args,
UI_CONTAINER_VBOX);
369 }
370
371 UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) {
372 return ui_box_create(obj, args,
UI_CONTAINER_HBOX);
373 }
374
375 GtkWidget* ui_create_grid_widget(
int colspacing,
int rowspacing) {
376 #if GTK_MAJOR_VERSION >=
3
377 GtkWidget *grid = gtk_grid_new();
378 gtk_grid_set_column_spacing(
GTK_GRID(grid), colspacing);
379 gtk_grid_set_row_spacing(
GTK_GRID(grid), rowspacing);
380 #else
381 GtkWidget *grid = gtk_table_new(
1,
1,
FALSE);
382 gtk_table_set_col_spacings(
GTK_TABLE(grid), colspacing);
383 gtk_table_set_row_spacings(
GTK_TABLE(grid), rowspacing);
384 #endif
385 return grid;
386 }
387
388 UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) {
389 UiObject* current = uic_current_obj(obj);
390 UI_APPLY_LAYOUT1(current, args);
391 GtkWidget *widget;
392
393 GtkWidget *grid = ui_create_grid_widget(args.columnspacing, args.rowspacing);
394 ui_set_name_and_style(grid, args.name, args.style_class);
395 widget = ui_box_set_margin(grid, args.margin);
396 current->container->add(current->container, widget,
TRUE);
397
398 UiObject *newobj = uic_object_new(obj, grid);
399 newobj->container = ui_grid_container(obj, grid);
400 uic_obj_add(obj, newobj);
401
402 return widget;
403 }
404
405 UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs args) {
406 UiObject* current = uic_current_obj(obj);
407 UI_APPLY_LAYOUT1(current, args);
408
409 GtkWidget *frame = gtk_frame_new(args.label);
410 UiObject *newobj = uic_object_new(obj, frame);
411 GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
412 if(sub) {
413 FRAME_SET_CHILD(frame, sub);
414 }
else {
415 newobj->widget = frame;
416 newobj->container = ui_frame_container(obj, frame);
417 }
418 current->container->add(current->container, frame,
FALSE);
419 uic_obj_add(obj, newobj);
420
421 return frame;
422 }
423
424 UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs args) {
425 UiObject* current = uic_current_obj(obj);
426 UI_APPLY_LAYOUT1(current, args);
427
428 GtkWidget *expander = gtk_expander_new(args.label);
429 gtk_expander_set_expanded(
GTK_EXPANDER(expander), args.isexpanded);
430 UiObject *newobj = uic_object_new(obj, expander);
431 GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
432 if(sub) {
433 EXPANDER_SET_CHILD(expander, sub);
434 }
else {
435 newobj->widget = expander;
436 newobj->container = ui_expander_container(obj, expander);
437 }
438 current->container->add(current->container, expander,
FALSE);
439 uic_obj_add(obj, newobj);
440
441 return expander;
442 }
443
444
445 UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs args) {
446 UiObject* current = uic_current_obj(obj);
447 UI_APPLY_LAYOUT1(current, args);
448
449 GtkWidget *sw =
SCROLLEDWINDOW_NEW();
450 ui_set_name_and_style(sw, args.name, args.style_class);
451 GtkWidget *widget = ui_box_set_margin(sw, args.margin);
452 current->container->add(current->container, widget,
TRUE);
453
454 UiObject *newobj = uic_object_new(obj, sw);
455 GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
456 if(sub) {
457 SCROLLEDWINDOW_SET_CHILD(sw, sub);
458 }
else {
459 newobj->widget = sw;
460 newobj->container = ui_scrolledwindow_container(obj, sw);
461 }
462
463 uic_obj_add(obj, newobj);
464
465 return sw;
466 }
467
468
469 void ui_notebook_tab_select(
UIWIDGET tabview,
int tab) {
470 gtk_notebook_set_current_page(
GTK_NOTEBOOK(tabview), tab);
471 }
472
473 void ui_notebook_tab_remove(
UIWIDGET tabview,
int tab) {
474 gtk_notebook_remove_page(
GTK_NOTEBOOK(tabview), tab);
475 }
476
477 void ui_notebook_tab_add(
UIWIDGET widget,
int index,
const char *name,
UIWIDGET child) {
478 gtk_notebook_insert_page(
479 GTK_NOTEBOOK(widget),
480 child,
481 gtk_label_new(name),
482 index);
483 }
484
485 int64_t ui_notebook_get(UiInteger *i) {
486 GtkNotebook *nb = i->obj;
487 i->value = gtk_notebook_get_current_page(nb);
488 return i->value;
489 }
490
491 void ui_notebook_set(UiInteger *i,
int64_t value) {
492 GtkNotebook *nb = i->obj;
493 gtk_notebook_set_current_page(nb, value);
494 i->value = gtk_notebook_get_current_page(nb);
495 }
496
497
498 #if GTK_MAJOR_VERSION >=
4
499 static int stack_set_page(GtkWidget *stack,
int index) {
500 GtkSelectionModel *pages = gtk_stack_get_pages(
GTK_STACK(stack));
501 GListModel *list =
G_LIST_MODEL(pages);
502 GtkStackPage *page = g_list_model_get_item(list, index);
503 if(page) {
504 gtk_stack_set_visible_child(
GTK_STACK(stack), gtk_stack_page_get_child(page));
505 }
else {
506 fprintf(stderr,
"UI Error: ui_stack_set value out of bounds\n");
507 return -
1;
508 }
509 return index;
510 }
511
512 void ui_stack_tab_select(
UIWIDGET tabview,
int tab) {
513 stack_set_page(tabview, tab);
514 }
515
516 void ui_stack_tab_remove(
UIWIDGET tabview,
int tab) {
517 GtkStack *stack =
GTK_STACK(tabview);
518 GtkWidget *current = gtk_stack_get_visible_child(stack);
519 GtkSelectionModel *pages = gtk_stack_get_pages(stack);
520 GListModel *list =
G_LIST_MODEL(pages);
521 GtkStackPage *page = g_list_model_get_item(list, tab);
522 if(page) {
523 gtk_stack_remove(stack, gtk_stack_page_get_child(page));
524 }
525 }
526
527 void ui_stack_tab_add(
UIWIDGET widget,
int index,
const char *name,
UIWIDGET child) {
528 (
void)gtk_stack_add_titled(
GTK_STACK(widget), child, name, name);
529 }
530
531 int64_t ui_stack_get(UiInteger *i) {
532 GtkStack *stack =
GTK_STACK(i->obj);
533 GtkWidget *current = gtk_stack_get_visible_child(stack);
534 GtkSelectionModel *pages = gtk_stack_get_pages(stack);
535 GListModel *list =
G_LIST_MODEL(pages);
536 int nitems = g_list_model_get_n_items(list);
537 for(
int p=
0;p<nitems;p++) {
538 GtkStackPage *page = g_list_model_get_item(list, p);
539 GtkWidget *child = gtk_stack_page_get_child(page);
540 if(child == current) {
541 i->value = p;
542 break;
543 }
544 }
545 return i->value;
546 }
547
548 void ui_stack_set(UiInteger *i,
int64_t value) {
549 GtkWidget *widget = i->obj;
550 if(stack_set_page(widget, value) >=
0) {
551 i->value = value;
552 }
553 }
554 #elif GTK_MAJOR_VERSION >=
3
555 static GtkWidget* stack_get_child(GtkWidget *stack,
int index) {
556 GList *children = gtk_container_get_children(
GTK_CONTAINER(stack));
557 if(children) {
558 return g_list_nth_data(children, index);
559 }
560 return NULL;
561 }
562
563 void ui_stack_tab_select(
UIWIDGET tabview,
int tab) {
564 GtkWidget *child = stack_get_child(tabview, tab);
565 if(child) {
566 gtk_stack_set_visible_child(
GTK_STACK(tabview), child);
567 }
568 }
569
570 void ui_stack_tab_remove(
UIWIDGET tabview,
int tab) {
571 GtkWidget *child = stack_get_child(tabview, tab);
572 if(child) {
573 gtk_container_remove(
GTK_CONTAINER(tabview), child);
574 }
575 }
576
577 void ui_stack_tab_add(
UIWIDGET widget,
int index,
const char *name,
UIWIDGET child) {
578 gtk_stack_add_titled(
GTK_STACK(widget), child, name, name);
579 }
580
581 int64_t ui_stack_get(UiInteger *i) {
582 GtkWidget *visible = gtk_stack_get_visible_child(
GTK_STACK(i->obj));
583 GList *children = gtk_container_get_children(
GTK_CONTAINER(i->obj));
584 GList *elm = children;
585 int n =
0;
586 int64_t v = -
1;
587 while(elm) {
588 GtkWidget *child = elm->data;
589 if(child == visible) {
590 v = n;
591 break;
592 }
593
594 elm = elm->next;
595 n++;
596 }
597 g_list_free(children);
598 i->value = v;
599 return v;
600 }
601
602 void ui_stack_set(UiInteger *i,
int64_t value) {
603 GtkWidget *child = stack_get_child(i->obj, value);
604 if(child) {
605 gtk_stack_set_visible_child(
GTK_STACK(i->obj), child);
606 i->value = value;
607 }
608 }
609
610 #endif
611
612
613
614
615 UiGtkTabView* ui_widget_get_tabview_data(
UIWIDGET tabview) {
616 return g_object_get_data(
G_OBJECT(tabview),
"ui_tabview");
617 }
618
619 typedef int64_t(*ui_tabview_get_func)(UiInteger*);
620 typedef void (*ui_tabview_set_func)(UiInteger*,
int64_t);
621
622 UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
623 UiGtkTabView *data = malloc(
sizeof(UiGtkTabView));
624 data->margin = args.margin;
625 data->spacing = args.spacing;
626 data->columnspacing = args.columnspacing;
627 data->rowspacing = args.rowspacing;
628
629 ui_tabview_get_func getfunc =
NULL;
630 ui_tabview_set_func setfunc =
NULL;
631
632 GtkWidget *widget =
NULL;
633 GtkWidget *data_widget =
NULL;
634 switch(args.tabview) {
635 case UI_TABVIEW_DOC: {
636
637 break;
638 }
639 case UI_TABVIEW_NAVIGATION_SIDE: {
640 #if GTK_CHECK_VERSION(
3,
10,
0)
641 widget = gtk_box_new(
GTK_ORIENTATION_HORIZONTAL,
0);
642 GtkWidget *sidebar = gtk_stack_sidebar_new();
643 BOX_ADD(widget, sidebar);
644 GtkWidget *stack = gtk_stack_new();
645 gtk_stack_set_transition_type (
GTK_STACK(stack),
GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN);
646 gtk_stack_sidebar_set_stack(
GTK_STACK_SIDEBAR(sidebar),
GTK_STACK(stack));
647 BOX_ADD_EXPAND(widget, stack);
648 data->select_tab = ui_stack_tab_select;
649 data->remove_tab = ui_stack_tab_remove;
650 data->add_tab = ui_stack_tab_add;
651 getfunc = ui_stack_get;
652 setfunc = ui_stack_set;
653 data_widget = stack;
654 #else
655
656 #endif
657 break;
658 }
659 case UI_TABVIEW_DEFAULT:
660 case UI_TABVIEW_NAVIGATION_TOP:
661 case UI_TABVIEW_INVISIBLE:
662 case UI_TABVIEW_NAVIGATION_TOP2: {
663 widget = gtk_notebook_new();
664 data_widget = widget;
665 data->select_tab = ui_notebook_tab_select;
666 data->remove_tab = ui_notebook_tab_remove;
667 data->add_tab = ui_notebook_tab_add;
668 getfunc = ui_notebook_get;
669 setfunc = ui_notebook_set;
670 if(args.tabview ==
UI_TABVIEW_INVISIBLE) {
671 gtk_notebook_set_show_tabs(
GTK_NOTEBOOK(widget),
FALSE);
672 gtk_notebook_set_show_border(
GTK_NOTEBOOK(widget),
FALSE);
673 }
674 break;
675 }
676 }
677
678 UiObject* current = uic_current_obj(obj);
679 if(args.value || args.varname) {
680 UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname,
UI_VAR_INTEGER);
681 UiInteger *i = var->value;
682 i->get = getfunc;
683 i->set = setfunc;
684 i->obj = data_widget;
685 }
686
687 g_object_set_data(
G_OBJECT(widget),
"ui_tabview", data);
688 data->widget = data_widget;
689 data->subcontainer = args.subcontainer;
690
691 UI_APPLY_LAYOUT1(current, args);
692 current->container->add(current->container, widget,
TRUE);
693
694 UiObject *newobj = uic_object_new(obj, widget);
695 newobj->container = ui_tabview_container(obj, widget);
696 uic_obj_add(obj, newobj);
697 data->obj = newobj;
698
699 return widget;
700 }
701
702 void ui_tab_create(UiObject* obj,
const char* title) {
703 UiObject* current = uic_current_obj(obj);
704 UiGtkTabView *data = ui_widget_get_tabview_data(current->widget);
705 if(!data) {
706 fprintf(stderr,
"UI Error: widget is not a tabview\n");
707 return;
708 }
709
710 UiObject *newobj = ui_tabview_add(current->widget, title, -
1);
711 current->next = newobj;
712 }
713
714
715
716 void ui_tabview_select(
UIWIDGET tabview,
int tab) {
717 UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
718 if(!data) {
719 fprintf(stderr,
"UI Error: widget is not a tabview\n");
720 return;
721 }
722 data->select_tab(tabview, tab);
723 }
724
725 void ui_tabview_remove(
UIWIDGET tabview,
int tab) {
726 UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
727 if(!data) {
728 fprintf(stderr,
"UI Error: widget is not a tabview\n");
729 return;
730 }
731 data->remove_tab(tabview, tab);
732 }
733
734 UiObject* ui_tabview_add(
UIWIDGET tabview,
const char *name,
int tab_index) {
735 UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
736 if(!data) {
737 fprintf(stderr,
"UI Error: widget is not a tabview\n");
738 return NULL;
739 }
740
741 UiObject *newobj = cxCalloc(data->obj->ctx->allocator,
1,
sizeof(UiObject));
742 newobj->ctx = data->obj->ctx;
743
744 GtkWidget *sub;
745 switch(data->subcontainer) {
746 default: {
747 sub = ui_gtk_vbox_new(data->spacing);
748 newobj->container = ui_box_container(newobj, sub, data->subcontainer);
749 break;
750 }
751 case UI_CONTAINER_HBOX: {
752 sub = ui_gtk_hbox_new(data->spacing);
753 newobj->container = ui_box_container(newobj, sub, data->subcontainer);
754 break;
755 }
756 case UI_CONTAINER_GRID: {
757 sub = ui_create_grid_widget(data->columnspacing, data->rowspacing);
758 newobj->container = ui_grid_container(newobj, sub);
759 break;
760 }
761 }
762 newobj->widget = sub;
763 GtkWidget *widget = ui_box_set_margin(sub, data->margin);
764
765 data->add_tab(data->widget, tab_index, name, widget);
766
767 return newobj;
768 }
769
770
771
772
773 static void hb_set_part(UiObject *obj,
int part) {
774 UiObject* current = uic_current_obj(obj);
775 GtkWidget *headerbar = current->widget;
776
777 UiHeaderbarContainer *hb = cxCalloc(
778 obj->ctx->allocator,
779 1,
780 sizeof(UiHeaderbarContainer));
781 memcpy(hb, current->container,
sizeof(UiHeaderbarContainer));
782
783 UiObject *newobj = uic_object_new(obj, headerbar);
784 newobj->container = (UiContainer*)hb;
785 uic_obj_add(obj, newobj);
786
787 hb->part = part;
788 }
789
790 void ui_headerbar_start_create(UiObject *obj) {
791 hb_set_part(obj,
0);
792 }
793
794 void ui_headerbar_center_create(UiObject *obj) {
795 hb_set_part(obj,
2);
796 }
797
798 void ui_headerbar_end_create(UiObject *obj) {
799 hb_set_part(obj,
1);
800 }
801
802 UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs args) {
803 UiObject *current = uic_current_obj(obj);
804 UiContainer *ct = current->container;
805 UI_APPLY_LAYOUT1(current, args);
806
807 GtkWidget *box = ui_gtk_hbox_new(args.alt_spacing);
808 ui_set_name_and_style(box, args.name, args.style_class);
809 ct->add(ct, box,
FALSE);
810
811 UiObject *newobj = uic_object_new(obj, box);
812 newobj->container = ui_headerbar_fallback_container(obj, box);
813 uic_obj_add(obj, newobj);
814
815 return box;
816 }
817
818 static void hb_fallback_set_part(UiObject *obj,
int part) {
819 UiObject* current = uic_current_obj(obj);
820 GtkWidget *headerbar = current->widget;
821
822 UiObject *newobj = uic_object_new(obj, headerbar);
823 newobj->container = ui_headerbar_container(obj, headerbar);
824 uic_obj_add(obj, newobj);
825
826 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)newobj->container;
827 hb->part = part;
828 }
829
830 UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar) {
831 UiHeaderbarContainer *ct = cxCalloc(
832 obj->ctx->allocator,
833 1,
834 sizeof(UiHeaderbarContainer));
835 ct->container.widget = headerbar;
836 ct->container.add = ui_headerbar_fallback_container_add;
837 return (UiContainer*)ct;
838 }
839
840 void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
841 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
842 BOX_ADD(ct->widget, widget);
843 }
844
845 #if GTK_CHECK_VERSION(
3,
10,
0)
846
847 UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
848 GtkWidget *headerbar = g_object_get_data(
G_OBJECT(obj->widget),
"ui_headerbar");
849 if(!headerbar) {
850 return ui_headerbar_fallback_create(obj, args);
851 }
852
853 UiObject *newobj = uic_object_new(obj, headerbar);
854 newobj->container = ui_headerbar_container(obj, headerbar);
855 uic_obj_add(obj, newobj);
856
857 return headerbar;
858 }
859
860 UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) {
861 UiHeaderbarContainer *ct = cxCalloc(
862 obj->ctx->allocator,
863 1,
864 sizeof(UiHeaderbarContainer));
865 ct->container.widget = headerbar;
866 ct->container.add = ui_headerbar_container_add;
867 return (UiContainer*)ct;
868 }
869
870 void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
871 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
872 if(hb->part ==
0) {
873 UI_HEADERBAR_PACK_START(ct->widget, widget);
874 }
else if(hb->part ==
1) {
875 UI_HEADERBAR_PACK_END(ct->widget, widget);
876 }
else if(hb->part ==
2) {
877 if(!hb->centerbox) {
878 GtkWidget *box = gtk_box_new(
GTK_ORIENTATION_HORIZONTAL,
6);
879 hb->centerbox = box;
880 UI_HEADERBAR_SET_TITLE_WIDGET(ct->widget, box);
881 }
882 BOX_ADD(hb->centerbox, widget);
883 }
884 }
885
886 #else
887
888 UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
889 return ui_headerbar_fallback_create(obj, args);
890 }
891
892 #endif
893
894
895
896 #ifdef UI_LIBADWAITA
897 UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) {
898 GtkWidget *sidebar_toolbar_view = g_object_get_data(
G_OBJECT(obj->widget),
"ui_sidebar");
899 if(!sidebar_toolbar_view) {
900 fprintf(stderr,
"Error: window is not configured for sidebar\n");
901 return NULL;
902 }
903
904 GtkWidget *box = ui_gtk_vbox_new(args.spacing);
905 ui_box_set_margin(box, args.margin);
906 adw_toolbar_view_set_content(
ADW_TOOLBAR_VIEW(sidebar_toolbar_view), box);
907
908 UiObject *newobj = uic_object_new(obj, box);
909 newobj->container = ui_box_container(obj, box,
UI_CONTAINER_VBOX);
910 uic_obj_add(obj, newobj);
911
912 return box;
913 }
914 #else
915 UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) {
916 GtkWidget *sidebar_vbox = g_object_get_data(
G_OBJECT(obj->widget),
"ui_sidebar");
917
918 GtkWidget *box = ui_gtk_vbox_new(args.spacing);
919 ui_box_set_margin(box, args.margin);
920 BOX_ADD_EXPAND(sidebar_vbox, box);
921
922 UiObject *newobj = uic_object_new(obj, box);
923 newobj->container = ui_box_container(obj, box,
UI_CONTAINER_VBOX);
924 uic_obj_add(obj, newobj);
925
926 return box;
927 }
928 #endif
929
930
931
932 static GtkWidget* create_paned(UiOrientation orientation) {
933 #if GTK_MAJOR_VERSION >=
3
934 switch(orientation) {
935 case UI_HORIZONTAL:
return gtk_paned_new(
GTK_ORIENTATION_HORIZONTAL);
936 case UI_VERTICAL:
return gtk_paned_new(
GTK_ORIENTATION_VERTICAL);
937 }
938 #else
939 switch(orientation) {
940 case UI_HORIZONTAL:
return gtk_hpaned_new();
941 case UI_VERTICAL:
return gtk_vpaned_new();
942 }
943 #endif
944 return NULL;
945 }
946
947
948
949
950
951
952
953
954
955
956
957
958
959 void ui_layout_fill(UiObject *obj, UiBool fill) {
960 UiContainer *ct = uic_get_current_container(obj);
961 ct->layout.fill = ui_bool2lb(fill);
962 }
963
964 void ui_layout_hexpand(UiObject *obj, UiBool expand) {
965 UiContainer *ct = uic_get_current_container(obj);
966 ct->layout.hexpand = expand;
967 }
968
969 void ui_layout_vexpand(UiObject *obj, UiBool expand) {
970 UiContainer *ct = uic_get_current_container(obj);
971 ct->layout.vexpand = expand;
972 }
973
974 void ui_layout_hfill(UiObject *obj, UiBool fill) {
975 UiContainer *ct = uic_get_current_container(obj);
976 ct->layout.hfill = fill;
977 }
978
979 void ui_layout_vfill(UiObject *obj, UiBool fill) {
980 UiContainer *ct = uic_get_current_container(obj);
981 ct->layout.vfill = fill;
982 }
983
984 void ui_layout_colspan(UiObject* obj,
int cols) {
985 UiContainer* ct = uic_get_current_container(obj);
986 ct->layout.colspan = cols;
987 }
988
989 void ui_layout_rowspan(UiObject* obj,
int rows) {
990 UiContainer* ct = uic_get_current_container(obj);
991 ct->layout.rowspan = rows;
992 }
993
994 void ui_newline(UiObject *obj) {
995 UiContainer *ct = uic_get_current_container(obj);
996 ct->layout.newline =
TRUE;
997 }
998
999