#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "container.h"
#include "toolkit.h"
#include "headerbar.h"
#include "../common/context.h"
#include "../common/object.h"
void ui_container_begin_close(UiObject *obj) {
UiContainer *ct = uic_get_current_container(obj);
ct->close =
1;
}
int ui_container_finish(UiObject *obj) {
UiContainer *ct = uic_get_current_container(obj);
if(ct->close) {
ui_end(obj);
return 0;
}
return 1;
}
GtkWidget* ui_gtk_vbox_new(
int spacing) {
#if GTK_MAJOR_VERSION >=
3
return gtk_box_new(
GTK_ORIENTATION_VERTICAL, spacing);
#else
return gtk_vbox_new(
FALSE, spacing);
#endif
}
GtkWidget* ui_gtk_hbox_new(
int spacing) {
#if GTK_MAJOR_VERSION >=
3
return gtk_box_new(
GTK_ORIENTATION_HORIZONTAL, spacing);
#else
return gtk_hbox_new(
FALSE, spacing);
#endif
}
GtkWidget* ui_subcontainer_create(
UiSubContainerType type,
UiObject *newobj,
int spacing,
int columnspacing,
int rowspacing,
int margin)
{
GtkWidget *sub =
NULL;
GtkWidget *add =
NULL;
switch(type) {
default: {
sub = ui_gtk_vbox_new(spacing);
add = ui_box_set_margin(sub, margin);
newobj->container = ui_box_container(newobj, sub, type);
newobj->widget = sub;
break;
}
case UI_CONTAINER_HBOX: {
sub = ui_gtk_hbox_new(spacing);
add = ui_box_set_margin(sub, margin);
newobj->container = ui_box_container(newobj, sub, type);
newobj->widget = sub;
break;
}
case UI_CONTAINER_GRID: {
sub = ui_create_grid_widget(columnspacing, rowspacing);
add = ui_box_set_margin(sub, margin);
newobj->container = ui_grid_container(newobj, sub);
newobj->widget = sub;
break;
}
case UI_CONTAINER_NO_SUB: {
break;
}
}
return add;
}
UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type) {
UiBoxContainer *ct = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiBoxContainer));
ct->container.widget = box;
ct->container.add = ui_box_container_add;
ct->type = type;
return (UiContainer*)ct;
}
void ui_box_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
UiBoxContainer *bc = (UiBoxContainer*)ct;
if(ct->layout.fill !=
UI_LAYOUT_UNDEFINED) {
fill = ui_lb2bool(ct->layout.fill);
}
if(bc->has_fill && fill) {
fprintf(stderr,
"UiError: container has 2 filled widgets");
fill =
FALSE;
}
if(fill) {
bc->has_fill =
TRUE;
}
UiBool expand = fill;
#if GTK_MAJOR_VERSION >=
4
gtk_box_append(
GTK_BOX(ct->widget), widget);
GtkAlign align = expand ?
GTK_ALIGN_FILL :
GTK_ALIGN_START;
if(bc->type ==
UI_CONTAINER_VBOX) {
gtk_widget_set_valign(widget, align);
gtk_widget_set_vexpand(widget, expand);
gtk_widget_set_hexpand(widget,
TRUE);
}
else if(bc->type ==
UI_CONTAINER_HBOX) {
gtk_widget_set_halign(widget, align);
gtk_widget_set_hexpand(widget, expand);
gtk_widget_set_vexpand(widget,
TRUE);
}
#else
gtk_box_pack_start(
GTK_BOX(ct->widget), widget, expand, fill,
0);
#endif
ui_reset_layout(ct->layout);
ct->current = widget;
}
UiContainer* ui_grid_container(UiObject *obj, GtkWidget *grid) {
UiGridContainer *ct = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiGridContainer));
ct->container.widget = grid;
ct->container.add = ui_grid_container_add;
UI_GTK_V2(ct->width =
0);
UI_GTK_V2(ct->height =
1);
return (UiContainer*)ct;
}
#if GTK_MAJOR_VERSION >=
3
void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
UiGridContainer *grid = (UiGridContainer*)ct;
if(ct->layout.newline) {
grid->x =
0;
grid->y++;
ct->layout.newline =
FALSE;
}
int hexpand =
FALSE;
int vexpand =
FALSE;
int hfill =
FALSE;
int vfill =
FALSE;
if(ct->layout.fill !=
UI_LAYOUT_UNDEFINED) {
fill = ui_lb2bool(ct->layout.fill);
}
if(ct->layout.hexpand !=
UI_LAYOUT_UNDEFINED) {
hexpand = ct->layout.hexpand;
hfill =
TRUE;
}
if(ct->layout.vexpand !=
UI_LAYOUT_UNDEFINED) {
vexpand = ct->layout.vexpand;
vfill =
TRUE;
}
if(fill) {
hfill =
TRUE;
vfill =
TRUE;
}
if(!hfill) {
gtk_widget_set_halign(widget,
GTK_ALIGN_START);
}
if(!vfill) {
gtk_widget_set_valign(widget,
GTK_ALIGN_START);
}
gtk_widget_set_hexpand(widget, hexpand);
gtk_widget_set_vexpand(widget, vexpand);
int colspan = ct->layout.colspan >
0 ? ct->layout.colspan :
1;
int rowspan = ct->layout.rowspan >
0 ? ct->layout.rowspan :
1;
gtk_grid_attach(
GTK_GRID(ct->widget), widget, grid->x, grid->y, colspan, rowspan);
grid->x += colspan;
ui_reset_layout(ct->layout);
ct->current = widget;
}
#endif
#ifdef UI_GTK2
void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
UiGridContainer *grid = (UiGridContainer*)ct;
if(ct->layout.newline) {
grid->x =
0;
grid->y++;
ct->layout.newline =
FALSE;
}
int hexpand =
FALSE;
int vexpand =
FALSE;
if(ct->layout.hexpand !=
UI_LAYOUT_UNDEFINED) {
hexpand = ct->layout.hexpand;
}
if(ct->layout.vexpand !=
UI_LAYOUT_UNDEFINED) {
vexpand = ct->layout.vexpand;
}
GtkAttachOptions xoptions = hexpand ?
GTK_FILL |
GTK_EXPAND :
GTK_FILL;
GtkAttachOptions yoptions = vexpand ?
GTK_FILL |
GTK_EXPAND :
GTK_FILL;
int colspan = ct->layout.colspan >
0 ? ct->layout.colspan :
1;
int rowspan = ct->layout.rowspan >
0 ? ct->layout.rowspan :
1;
gtk_table_attach(
GTK_TABLE(ct->widget), widget, grid->x, grid->x+
1, grid->y, grid->y+
1, xoptions, yoptions,
0,
0);
grid->x++;
int nw = grid->x > grid->width ? grid->x : grid->width;
if(grid->x > grid->width || grid->y > grid->height) {
grid->width = nw;
grid->height = grid->y +
1;
gtk_table_resize(
GTK_TABLE(ct->widget), grid->width, grid->height);
}
ui_reset_layout(ct->layout);
ct->current = widget;
}
#endif
UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame) {
UiContainer *ct = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiContainer));
ct->widget = frame;
ct->add = ui_frame_container_add;
return ct;
}
void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
FRAME_SET_CHILD(ct->widget, widget);
}
UiContainer* ui_expander_container(UiObject *obj, GtkWidget *expander) {
UiContainer *ct = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiContainer));
ct->widget = expander;
ct->add = ui_expander_container_add;
return ct;
}
void ui_expander_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
EXPANDER_SET_CHILD(ct->widget, widget);
}
void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
SCROLLEDWINDOW_SET_CHILD(ct->widget, widget);
ui_reset_layout(ct->layout);
ct->current = widget;
}
UiContainer* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow) {
UiContainer *ct = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiContainer));
ct->widget = scrolledwindow;
ct->add = ui_scrolledwindow_container_add;
return ct;
}
UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview) {
UiTabViewContainer *ct = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiTabViewContainer));
ct->container.widget = tabview;
ct->container.add = ui_tabview_container_add;
return (UiContainer*)ct;
}
void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
UiGtkTabView *data = ui_widget_get_tabview_data(ct->widget);
if(!data) {
fprintf(stderr,
"UI Error: widget is not a tabview");
return;
}
data->add_tab(ct->widget, -
1, ct->layout.label, widget);
ui_reset_layout(ct->layout);
ct->current = widget;
}
GtkWidget* ui_box_set_margin(GtkWidget *box,
int margin) {
GtkWidget *ret = box;
#if GTK_MAJOR_VERSION >=
3
#if GTK_MAJOR_VERSION *
1000 +
GTK_MINOR_VERSION >=
3012
gtk_widget_set_margin_start(box, margin);
gtk_widget_set_margin_end(box, margin);
#else
gtk_widget_set_margin_left(box, margin);
gtk_widget_set_margin_right(box, margin);
#endif
gtk_widget_set_margin_top(box, margin);
gtk_widget_set_margin_bottom(box, margin);
#elif defined(
UI_GTK2)
GtkWidget *a = gtk_alignment_new(
0.
5,
0.
5,
1,
1);
gtk_alignment_set_padding(
GTK_ALIGNMENT(a), margin, margin, margin, margin);
gtk_container_add(
GTK_CONTAINER(a), box);
ret = a;
#endif
return ret;
}
UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, UiSubContainerType type) {
UiObject *current = uic_current_obj(obj);
UiContainer *ct = current->container;
UI_APPLY_LAYOUT1(current, args);
GtkWidget *box = type ==
UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing);
ui_set_name_and_style(box, args.name, args.style_class);
GtkWidget *widget = args.margin >
0 ? ui_box_set_margin(box, args.margin) : box;
ct->add(ct, widget,
TRUE);
UiObject *newobj = uic_object_new(obj, box);
newobj->container = ui_box_container(obj, box, type);
uic_obj_add(obj, newobj);
return widget;
}
UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) {
return ui_box_create(obj, args,
UI_CONTAINER_VBOX);
}
UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) {
return ui_box_create(obj, args,
UI_CONTAINER_HBOX);
}
GtkWidget* ui_create_grid_widget(
int colspacing,
int rowspacing) {
#if GTK_MAJOR_VERSION >=
3
GtkWidget *grid = gtk_grid_new();
gtk_grid_set_column_spacing(
GTK_GRID(grid), colspacing);
gtk_grid_set_row_spacing(
GTK_GRID(grid), rowspacing);
#else
GtkWidget *grid = gtk_table_new(
1,
1,
FALSE);
gtk_table_set_col_spacings(
GTK_TABLE(grid), colspacing);
gtk_table_set_row_spacings(
GTK_TABLE(grid), rowspacing);
#endif
return grid;
}
UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) {
UiObject* current = uic_current_obj(obj);
UI_APPLY_LAYOUT1(current, args);
GtkWidget *widget;
GtkWidget *grid = ui_create_grid_widget(args.columnspacing, args.rowspacing);
ui_set_name_and_style(grid, args.name, args.style_class);
widget = ui_box_set_margin(grid, args.margin);
current->container->add(current->container, widget,
TRUE);
UiObject *newobj = uic_object_new(obj, grid);
newobj->container = ui_grid_container(obj, grid);
uic_obj_add(obj, newobj);
return widget;
}
UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs args) {
UiObject* current = uic_current_obj(obj);
UI_APPLY_LAYOUT1(current, args);
GtkWidget *frame = gtk_frame_new(args.label);
UiObject *newobj = uic_object_new(obj, frame);
GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
if(sub) {
FRAME_SET_CHILD(frame, sub);
}
else {
newobj->widget = frame;
newobj->container = ui_frame_container(obj, frame);
}
current->container->add(current->container, frame,
FALSE);
uic_obj_add(obj, newobj);
return frame;
}
UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs args) {
UiObject* current = uic_current_obj(obj);
UI_APPLY_LAYOUT1(current, args);
GtkWidget *expander = gtk_expander_new(args.label);
gtk_expander_set_expanded(
GTK_EXPANDER(expander), args.isexpanded);
UiObject *newobj = uic_object_new(obj, expander);
GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
if(sub) {
EXPANDER_SET_CHILD(expander, sub);
}
else {
newobj->widget = expander;
newobj->container = ui_expander_container(obj, expander);
}
current->container->add(current->container, expander,
FALSE);
uic_obj_add(obj, newobj);
return expander;
}
UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs args) {
UiObject* current = uic_current_obj(obj);
UI_APPLY_LAYOUT1(current, args);
GtkWidget *sw =
SCROLLEDWINDOW_NEW();
ui_set_name_and_style(sw, args.name, args.style_class);
GtkWidget *widget = ui_box_set_margin(sw, args.margin);
current->container->add(current->container, widget,
TRUE);
UiObject *newobj = uic_object_new(obj, sw);
GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin);
if(sub) {
SCROLLEDWINDOW_SET_CHILD(sw, sub);
}
else {
newobj->widget = sw;
newobj->container = ui_scrolledwindow_container(obj, sw);
}
uic_obj_add(obj, newobj);
return sw;
}
void ui_notebook_tab_select(
UIWIDGET tabview,
int tab) {
gtk_notebook_set_current_page(
GTK_NOTEBOOK(tabview), tab);
}
void ui_notebook_tab_remove(
UIWIDGET tabview,
int tab) {
gtk_notebook_remove_page(
GTK_NOTEBOOK(tabview), tab);
}
void ui_notebook_tab_add(
UIWIDGET widget,
int index,
const char *name,
UIWIDGET child) {
gtk_notebook_insert_page(
GTK_NOTEBOOK(widget),
child,
gtk_label_new(name),
index);
}
int64_t ui_notebook_get(UiInteger *i) {
GtkNotebook *nb = i->obj;
i->value = gtk_notebook_get_current_page(nb);
return i->value;
}
void ui_notebook_set(UiInteger *i,
int64_t value) {
GtkNotebook *nb = i->obj;
gtk_notebook_set_current_page(nb, value);
i->value = gtk_notebook_get_current_page(nb);
}
#if GTK_MAJOR_VERSION >=
4
static int stack_set_page(GtkWidget *stack,
int index) {
GtkSelectionModel *pages = gtk_stack_get_pages(
GTK_STACK(stack));
GListModel *list =
G_LIST_MODEL(pages);
GtkStackPage *page = g_list_model_get_item(list, index);
if(page) {
gtk_stack_set_visible_child(
GTK_STACK(stack), gtk_stack_page_get_child(page));
}
else {
fprintf(stderr,
"UI Error: ui_stack_set value out of bounds\n");
return -
1;
}
return index;
}
void ui_stack_tab_select(
UIWIDGET tabview,
int tab) {
stack_set_page(tabview, tab);
}
void ui_stack_tab_remove(
UIWIDGET tabview,
int tab) {
GtkStack *stack =
GTK_STACK(tabview);
GtkWidget *current = gtk_stack_get_visible_child(stack);
GtkSelectionModel *pages = gtk_stack_get_pages(stack);
GListModel *list =
G_LIST_MODEL(pages);
GtkStackPage *page = g_list_model_get_item(list, tab);
if(page) {
gtk_stack_remove(stack, gtk_stack_page_get_child(page));
}
}
void ui_stack_tab_add(
UIWIDGET widget,
int index,
const char *name,
UIWIDGET child) {
(
void)gtk_stack_add_titled(
GTK_STACK(widget), child, name, name);
}
int64_t ui_stack_get(UiInteger *i) {
GtkStack *stack =
GTK_STACK(i->obj);
GtkWidget *current = gtk_stack_get_visible_child(stack);
GtkSelectionModel *pages = gtk_stack_get_pages(stack);
GListModel *list =
G_LIST_MODEL(pages);
int nitems = g_list_model_get_n_items(list);
for(
int p=
0;p<nitems;p++) {
GtkStackPage *page = g_list_model_get_item(list, p);
GtkWidget *child = gtk_stack_page_get_child(page);
if(child == current) {
i->value = p;
break;
}
}
return i->value;
}
void ui_stack_set(UiInteger *i,
int64_t value) {
GtkWidget *widget = i->obj;
if(stack_set_page(widget, value) >=
0) {
i->value = value;
}
}
#elif GTK_MAJOR_VERSION >=
3
static GtkWidget* stack_get_child(GtkWidget *stack,
int index) {
GList *children = gtk_container_get_children(
GTK_CONTAINER(stack));
if(children) {
return g_list_nth_data(children, index);
}
return NULL;
}
void ui_stack_tab_select(
UIWIDGET tabview,
int tab) {
GtkWidget *child = stack_get_child(tabview, tab);
if(child) {
gtk_stack_set_visible_child(
GTK_STACK(tabview), child);
}
}
void ui_stack_tab_remove(
UIWIDGET tabview,
int tab) {
GtkWidget *child = stack_get_child(tabview, tab);
if(child) {
gtk_container_remove(
GTK_CONTAINER(tabview), child);
}
}
void ui_stack_tab_add(
UIWIDGET widget,
int index,
const char *name,
UIWIDGET child) {
gtk_stack_add_titled(
GTK_STACK(widget), child, name, name);
}
int64_t ui_stack_get(UiInteger *i) {
GtkWidget *visible = gtk_stack_get_visible_child(
GTK_STACK(i->obj));
GList *children = gtk_container_get_children(
GTK_CONTAINER(i->obj));
GList *elm = children;
int n =
0;
int64_t v = -
1;
while(elm) {
GtkWidget *child = elm->data;
if(child == visible) {
v = n;
break;
}
elm = elm->next;
n++;
}
g_list_free(children);
i->value = v;
return v;
}
void ui_stack_set(UiInteger *i,
int64_t value) {
GtkWidget *child = stack_get_child(i->obj, value);
if(child) {
gtk_stack_set_visible_child(
GTK_STACK(i->obj), child);
i->value = value;
}
}
#endif
UiGtkTabView* ui_widget_get_tabview_data(
UIWIDGET tabview) {
return g_object_get_data(
G_OBJECT(tabview),
"ui_tabview");
}
typedef int64_t(*ui_tabview_get_func)(UiInteger*);
typedef void (*ui_tabview_set_func)(UiInteger*,
int64_t);
UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
UiGtkTabView *data = malloc(
sizeof(UiGtkTabView));
data->margin = args.margin;
data->spacing = args.spacing;
data->columnspacing = args.columnspacing;
data->rowspacing = args.rowspacing;
ui_tabview_get_func getfunc =
NULL;
ui_tabview_set_func setfunc =
NULL;
GtkWidget *widget =
NULL;
GtkWidget *data_widget =
NULL;
switch(args.tabview) {
case UI_TABVIEW_DOC: {
break;
}
case UI_TABVIEW_NAVIGATION_SIDE: {
#if GTK_CHECK_VERSION(
3,
10,
0)
widget = gtk_box_new(
GTK_ORIENTATION_HORIZONTAL,
0);
GtkWidget *sidebar = gtk_stack_sidebar_new();
BOX_ADD(widget, sidebar);
GtkWidget *stack = gtk_stack_new();
gtk_stack_set_transition_type (
GTK_STACK(stack),
GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN);
gtk_stack_sidebar_set_stack(
GTK_STACK_SIDEBAR(sidebar),
GTK_STACK(stack));
BOX_ADD_EXPAND(widget, stack);
data->select_tab = ui_stack_tab_select;
data->remove_tab = ui_stack_tab_remove;
data->add_tab = ui_stack_tab_add;
getfunc = ui_stack_get;
setfunc = ui_stack_set;
data_widget = stack;
#else
#endif
break;
}
case UI_TABVIEW_DEFAULT:
case UI_TABVIEW_NAVIGATION_TOP:
case UI_TABVIEW_INVISIBLE:
case UI_TABVIEW_NAVIGATION_TOP2: {
widget = gtk_notebook_new();
data_widget = widget;
data->select_tab = ui_notebook_tab_select;
data->remove_tab = ui_notebook_tab_remove;
data->add_tab = ui_notebook_tab_add;
getfunc = ui_notebook_get;
setfunc = ui_notebook_set;
if(args.tabview ==
UI_TABVIEW_INVISIBLE) {
gtk_notebook_set_show_tabs(
GTK_NOTEBOOK(widget),
FALSE);
gtk_notebook_set_show_border(
GTK_NOTEBOOK(widget),
FALSE);
}
break;
}
}
UiObject* current = uic_current_obj(obj);
if(args.value || args.varname) {
UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname,
UI_VAR_INTEGER);
UiInteger *i = var->value;
i->get = getfunc;
i->set = setfunc;
i->obj = data_widget;
}
g_object_set_data(
G_OBJECT(widget),
"ui_tabview", data);
data->widget = data_widget;
data->subcontainer = args.subcontainer;
UI_APPLY_LAYOUT1(current, args);
current->container->add(current->container, widget,
TRUE);
UiObject *newobj = uic_object_new(obj, widget);
newobj->container = ui_tabview_container(obj, widget);
uic_obj_add(obj, newobj);
data->obj = newobj;
return widget;
}
void ui_tab_create(UiObject* obj,
const char* title) {
UiObject* current = uic_current_obj(obj);
UiGtkTabView *data = ui_widget_get_tabview_data(current->widget);
if(!data) {
fprintf(stderr,
"UI Error: widget is not a tabview\n");
return;
}
UiObject *newobj = ui_tabview_add(current->widget, title, -
1);
current->next = newobj;
}
void ui_tabview_select(
UIWIDGET tabview,
int tab) {
UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
if(!data) {
fprintf(stderr,
"UI Error: widget is not a tabview\n");
return;
}
data->select_tab(tabview, tab);
}
void ui_tabview_remove(
UIWIDGET tabview,
int tab) {
UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
if(!data) {
fprintf(stderr,
"UI Error: widget is not a tabview\n");
return;
}
data->remove_tab(tabview, tab);
}
UiObject* ui_tabview_add(
UIWIDGET tabview,
const char *name,
int tab_index) {
UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
if(!data) {
fprintf(stderr,
"UI Error: widget is not a tabview\n");
return NULL;
}
UiObject *newobj = cxCalloc(data->obj->ctx->allocator,
1,
sizeof(UiObject));
newobj->ctx = data->obj->ctx;
GtkWidget *sub;
switch(data->subcontainer) {
default: {
sub = ui_gtk_vbox_new(data->spacing);
newobj->container = ui_box_container(newobj, sub, data->subcontainer);
break;
}
case UI_CONTAINER_HBOX: {
sub = ui_gtk_hbox_new(data->spacing);
newobj->container = ui_box_container(newobj, sub, data->subcontainer);
break;
}
case UI_CONTAINER_GRID: {
sub = ui_create_grid_widget(data->columnspacing, data->rowspacing);
newobj->container = ui_grid_container(newobj, sub);
break;
}
}
newobj->widget = sub;
GtkWidget *widget = ui_box_set_margin(sub, data->margin);
data->add_tab(data->widget, tab_index, name, widget);
return newobj;
}
static void hb_set_part(UiObject *obj,
int part) {
UiObject* current = uic_current_obj(obj);
GtkWidget *headerbar = current->widget;
UiHeaderbarContainer *hb = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiHeaderbarContainer));
memcpy(hb, current->container,
sizeof(UiHeaderbarContainer));
UiObject *newobj = uic_object_new(obj, headerbar);
newobj->container = (UiContainer*)hb;
uic_obj_add(obj, newobj);
hb->part = part;
}
void ui_headerbar_start_create(UiObject *obj) {
hb_set_part(obj,
0);
}
void ui_headerbar_center_create(UiObject *obj) {
hb_set_part(obj,
2);
}
void ui_headerbar_end_create(UiObject *obj) {
hb_set_part(obj,
1);
}
UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs args) {
UiObject *current = uic_current_obj(obj);
UiContainer *ct = current->container;
UI_APPLY_LAYOUT1(current, args);
GtkWidget *box = ui_gtk_hbox_new(args.alt_spacing);
ui_set_name_and_style(box, args.name, args.style_class);
ct->add(ct, box,
FALSE);
UiObject *newobj = uic_object_new(obj, box);
newobj->container = ui_headerbar_fallback_container(obj, box);
uic_obj_add(obj, newobj);
return box;
}
static void hb_fallback_set_part(UiObject *obj,
int part) {
UiObject* current = uic_current_obj(obj);
GtkWidget *headerbar = current->widget;
UiObject *newobj = uic_object_new(obj, headerbar);
newobj->container = ui_headerbar_container(obj, headerbar);
uic_obj_add(obj, newobj);
UiHeaderbarContainer *hb = (UiHeaderbarContainer*)newobj->container;
hb->part = part;
}
UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar) {
UiHeaderbarContainer *ct = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiHeaderbarContainer));
ct->container.widget = headerbar;
ct->container.add = ui_headerbar_fallback_container_add;
return (UiContainer*)ct;
}
void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
BOX_ADD(ct->widget, widget);
}
#if GTK_CHECK_VERSION(
3,
10,
0)
UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
GtkWidget *headerbar = g_object_get_data(
G_OBJECT(obj->widget),
"ui_headerbar");
if(!headerbar) {
return ui_headerbar_fallback_create(obj, args);
}
UiObject *newobj = uic_object_new(obj, headerbar);
newobj->container = ui_headerbar_container(obj, headerbar);
uic_obj_add(obj, newobj);
return headerbar;
}
UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) {
UiHeaderbarContainer *ct = cxCalloc(
obj->ctx->allocator,
1,
sizeof(UiHeaderbarContainer));
ct->container.widget = headerbar;
ct->container.add = ui_headerbar_container_add;
return (UiContainer*)ct;
}
void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
if(hb->part ==
0) {
UI_HEADERBAR_PACK_START(ct->widget, widget);
}
else if(hb->part ==
1) {
UI_HEADERBAR_PACK_END(ct->widget, widget);
}
else if(hb->part ==
2) {
if(!hb->centerbox) {
GtkWidget *box = gtk_box_new(
GTK_ORIENTATION_HORIZONTAL,
6);
hb->centerbox = box;
UI_HEADERBAR_SET_TITLE_WIDGET(ct->widget, box);
}
BOX_ADD(hb->centerbox, widget);
}
}
#else
UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
return ui_headerbar_fallback_create(obj, args);
}
#endif
#ifdef UI_LIBADWAITA
UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) {
GtkWidget *sidebar_toolbar_view = g_object_get_data(
G_OBJECT(obj->widget),
"ui_sidebar");
if(!sidebar_toolbar_view) {
fprintf(stderr,
"Error: window is not configured for sidebar\n");
return NULL;
}
GtkWidget *box = ui_gtk_vbox_new(args.spacing);
ui_box_set_margin(box, args.margin);
adw_toolbar_view_set_content(
ADW_TOOLBAR_VIEW(sidebar_toolbar_view), box);
UiObject *newobj = uic_object_new(obj, box);
newobj->container = ui_box_container(obj, box,
UI_CONTAINER_VBOX);
uic_obj_add(obj, newobj);
return box;
}
#else
UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) {
GtkWidget *sidebar_vbox = g_object_get_data(
G_OBJECT(obj->widget),
"ui_sidebar");
GtkWidget *box = ui_gtk_vbox_new(args.spacing);
ui_box_set_margin(box, args.margin);
BOX_ADD_EXPAND(sidebar_vbox, box);
UiObject *newobj = uic_object_new(obj, box);
newobj->container = ui_box_container(obj, box,
UI_CONTAINER_VBOX);
uic_obj_add(obj, newobj);
return box;
}
#endif
static GtkWidget* create_paned(UiOrientation orientation) {
#if GTK_MAJOR_VERSION >=
3
switch(orientation) {
case UI_HORIZONTAL:
return gtk_paned_new(
GTK_ORIENTATION_HORIZONTAL);
case UI_VERTICAL:
return gtk_paned_new(
GTK_ORIENTATION_VERTICAL);
}
#else
switch(orientation) {
case UI_HORIZONTAL:
return gtk_hpaned_new();
case UI_VERTICAL:
return gtk_vpaned_new();
}
#endif
return NULL;
}
void ui_layout_fill(UiObject *obj, UiBool fill) {
UiContainer *ct = uic_get_current_container(obj);
ct->layout.fill = ui_bool2lb(fill);
}
void ui_layout_hexpand(UiObject *obj, UiBool expand) {
UiContainer *ct = uic_get_current_container(obj);
ct->layout.hexpand = expand;
}
void ui_layout_vexpand(UiObject *obj, UiBool expand) {
UiContainer *ct = uic_get_current_container(obj);
ct->layout.vexpand = expand;
}
void ui_layout_hfill(UiObject *obj, UiBool fill) {
UiContainer *ct = uic_get_current_container(obj);
ct->layout.hfill = fill;
}
void ui_layout_vfill(UiObject *obj, UiBool fill) {
UiContainer *ct = uic_get_current_container(obj);
ct->layout.vfill = fill;
}
void ui_layout_colspan(UiObject* obj,
int cols) {
UiContainer* ct = uic_get_current_container(obj);
ct->layout.colspan = cols;
}
void ui_layout_rowspan(UiObject* obj,
int rows) {
UiContainer* ct = uic_get_current_container(obj);
ct->layout.rowspan = rows;
}
void ui_newline(UiObject *obj) {
UiContainer *ct = uic_get_current_container(obj);
ct->layout.newline =
TRUE;
}