ui/gtk/container.c

changeset 112
c3f2f16fa4b8
parent 110
c00e968d018b
equal deleted inserted replaced
111:81c4f73236a4 112:c3f2f16fa4b8
35 #include "toolkit.h" 35 #include "toolkit.h"
36 #include "headerbar.h" 36 #include "headerbar.h"
37 37
38 #include "../common/context.h" 38 #include "../common/context.h"
39 #include "../common/object.h" 39 #include "../common/object.h"
40 #include "../common/container.h"
40 41
41 #include "../ui/properties.h" 42 #include "../ui/properties.h"
42 43
43 44
44 void ui_container_begin_close(UiObject *obj) { 45 void ui_container_begin_close(UiObject *obj) {
45 UiContainer *ct = uic_get_current_container(obj); 46 UiContainerX *ct = obj->container_end;
46 ct->close = 1; 47 ct->close = 1;
47 } 48 }
48 49
49 int ui_container_finish(UiObject *obj) { 50 int ui_container_finish(UiObject *obj) {
50 UiContainer *ct = uic_get_current_container(obj); 51 UiContainerX *ct = obj->container_end;
51 if(ct->close) { 52 if(ct->close) {
52 ui_end(obj); 53 ui_end_new(obj);
53 return 0; 54 return 0;
54 } 55 }
55 return 1; 56 return 1;
56 } 57 }
57 58
71 #endif 72 #endif
72 } 73 }
73 74
74 GtkWidget* ui_subcontainer_create( 75 GtkWidget* ui_subcontainer_create(
75 UiSubContainerType type, 76 UiSubContainerType type,
76 UiObject *newobj, 77 UiObject *obj,
77 int spacing, 78 int spacing,
78 int columnspacing, 79 int columnspacing,
79 int rowspacing, 80 int rowspacing,
80 int margin) 81 int margin)
81 { 82 {
82 GtkWidget *sub = NULL; 83 GtkWidget *sub = NULL;
83 GtkWidget *add = NULL; 84 GtkWidget *add = NULL;
85 UiContainerX *container = NULL;
84 switch(type) { 86 switch(type) {
85 default: { 87 default: {
86 sub = ui_gtk_vbox_new(spacing); 88 sub = ui_gtk_vbox_new(spacing);
87 add = ui_box_set_margin(sub, margin); 89 add = ui_gtk_set_margin(sub, margin, 0, 0, 0, 0);
88 newobj->container = ui_box_container(newobj, sub, type); 90 container = ui_box_container(obj, sub, type);
89 newobj->widget = sub;
90 break; 91 break;
91 } 92 }
92 case UI_CONTAINER_HBOX: { 93 case UI_CONTAINER_HBOX: {
93 sub = ui_gtk_hbox_new(spacing); 94 sub = ui_gtk_hbox_new(spacing);
94 add = ui_box_set_margin(sub, margin); 95 add = ui_gtk_set_margin(sub, margin, 0, 0, 0, 0);
95 newobj->container = ui_box_container(newobj, sub, type); 96 container = ui_box_container(obj, sub, type);
96 newobj->widget = sub;
97 break; 97 break;
98 } 98 }
99 case UI_CONTAINER_GRID: { 99 case UI_CONTAINER_GRID: {
100 sub = ui_create_grid_widget(columnspacing, rowspacing); 100 sub = ui_create_grid_widget(columnspacing, rowspacing);
101 add = ui_box_set_margin(sub, margin); 101 add = ui_gtk_set_margin(sub, margin, 0, 0, 0, 0);
102 newobj->container = ui_grid_container(newobj, sub, FALSE, FALSE, FALSE, FALSE); 102 container = ui_grid_container(obj, sub, FALSE, FALSE, FALSE, FALSE);
103 newobj->widget = sub;
104 break; 103 break;
105 } 104 }
106 case UI_CONTAINER_NO_SUB: { 105 case UI_CONTAINER_NO_SUB: {
107 break; 106 break;
108 } 107 }
109 } 108 }
109 if(container) {
110 uic_object_push_container(obj, container);
111 }
110 return add; 112 return add;
111 } 113 }
112 114
113 115
114 /* -------------------- Box Container -------------------- */ 116 /* -------------------- Box Container -------------------- */
115 UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type) { 117 UiContainerX* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type) {
116 UiBoxContainer *ct = cxCalloc( 118 UiBoxContainer *ct = cxCalloc(
117 obj->ctx->allocator, 119 obj->ctx->allocator,
118 1, 120 1,
119 sizeof(UiBoxContainer)); 121 sizeof(UiBoxContainer));
120 ct->container.widget = box; 122 ct->container.widget = box;
121 ct->container.add = ui_box_container_add; 123 ct->container.add = ui_box_container_add;
122 ct->type = type; 124 ct->type = type;
123 return (UiContainer*)ct; 125 return (UiContainerX*)ct;
124 } 126 }
125 127
126 void ui_box_container_add(UiContainer *ct, GtkWidget *widget) { 128 void ui_box_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
127 UiBoxContainer *bc = (UiBoxContainer*)ct; 129 UiBoxContainer *bc = (UiBoxContainer*)ct;
128 UiBool fill = ct->layout.fill; 130 widget = ui_gtk_set_margin(widget, layout->margin, layout->margin_left, layout->margin_right, layout->margin_top, layout->margin_bottom);
131
132 UiBool fill = layout->fill;
129 if(bc->has_fill && fill) { 133 if(bc->has_fill && fill) {
130 fprintf(stderr, "UiError: container has 2 filled widgets"); 134 fprintf(stderr, "UiError: container has 2 filled widgets");
131 fill = FALSE; 135 fill = FALSE;
132 } 136 }
133 if(fill) { 137 if(fill) {
150 154
151 #else 155 #else
152 gtk_box_pack_start(GTK_BOX(ct->widget), widget, expand, fill, 0); 156 gtk_box_pack_start(GTK_BOX(ct->widget), widget, expand, fill, 0);
153 #endif 157 #endif
154 158
155 ui_reset_layout(ct->layout);
156 ct->current = widget; 159 ct->current = widget;
157 } 160 }
158 161
159 UiContainer* ui_grid_container( 162 UiContainerX* ui_grid_container(
160 UiObject *obj, 163 UiObject *obj,
161 GtkWidget *grid, 164 GtkWidget *grid,
162 UiBool def_hexpand, 165 UiBool def_hexpand,
163 UiBool def_vexpand, 166 UiBool def_vexpand,
164 UiBool def_hfill, 167 UiBool def_hfill,
174 ct->def_vfill = def_vfill; 177 ct->def_vfill = def_vfill;
175 ct->container.widget = grid; 178 ct->container.widget = grid;
176 ct->container.add = ui_grid_container_add; 179 ct->container.add = ui_grid_container_add;
177 UI_GTK_V2(ct->width = 0); 180 UI_GTK_V2(ct->width = 0);
178 UI_GTK_V2(ct->height = 1); 181 UI_GTK_V2(ct->height = 1);
179 return (UiContainer*)ct; 182 return (UiContainerX*)ct;
180 } 183 }
184
181 185
182 #if GTK_MAJOR_VERSION >= 3 186 #if GTK_MAJOR_VERSION >= 3
183 void ui_grid_container_add(UiContainer *ct, GtkWidget *widget) { 187 void ui_grid_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
184 UiGridContainer *grid = (UiGridContainer*)ct; 188 UiGridContainer *grid = (UiGridContainer*)ct;
185 189 widget = ui_gtk_set_margin(widget, layout->margin, layout->margin_left, layout->margin_right, layout->margin_top, layout->margin_bottom);
186 if(ct->layout.newline) { 190
191 if(ct->container.newline) {
187 grid->x = 0; 192 grid->x = 0;
188 grid->y++; 193 grid->y++;
189 ct->layout.newline = FALSE; 194 ct->container.newline = FALSE;
190 } 195 }
191 196
192 int hexpand = FALSE; 197 uic_layout_setup_expand_fill(layout, grid->def_hexpand, grid->def_vexpand, grid->def_hfill, grid->def_vfill);
193 int vexpand = FALSE; 198
194 int hfill = FALSE; 199 if(!layout->hfill) {
195 int vfill = FALSE;
196 if(!ct->layout.override_defaults) {
197 if(grid->def_hexpand) {
198 hexpand = TRUE;
199 }
200 if(grid->def_hfill) {
201 hfill = TRUE;
202 }
203 if(grid->def_vexpand) {
204 vexpand = TRUE;
205 }
206 if(grid->def_vfill) {
207 vfill = TRUE;
208 }
209 }
210
211 UiBool fill = ct->layout.fill;
212 if(ct->layout.hexpand) {
213 hexpand = TRUE;
214 }
215 if(ct->layout.hfill) {
216 hfill = TRUE;
217 }
218 if(ct->layout.vexpand) {
219 vexpand = TRUE;
220 }
221 if(ct->layout.vfill) {
222 vfill = TRUE;
223 }
224 if(fill) {
225 hfill = TRUE;
226 vfill = TRUE;
227 hexpand = TRUE;
228 vexpand = TRUE;
229 }
230
231 if(!hfill) {
232 gtk_widget_set_halign(widget, GTK_ALIGN_START); 200 gtk_widget_set_halign(widget, GTK_ALIGN_START);
233 } 201 }
234 if(!vfill) { 202 if(!layout->vfill) {
235 gtk_widget_set_valign(widget, GTK_ALIGN_START); 203 gtk_widget_set_valign(widget, GTK_ALIGN_START);
236 } 204 }
237 205
238 gtk_widget_set_hexpand(widget, hexpand); 206 gtk_widget_set_hexpand(widget, layout->hexpand);
239 gtk_widget_set_vexpand(widget, vexpand); 207 gtk_widget_set_vexpand(widget, layout->vexpand);
240 208
241 int colspan = ct->layout.colspan > 0 ? ct->layout.colspan : 1; 209 int colspan = layout->colspan > 0 ? layout->colspan : 1;
242 int rowspan = ct->layout.rowspan > 0 ? ct->layout.rowspan : 1; 210 int rowspan = layout->rowspan > 0 ? layout->rowspan : 1;
243 211
244 gtk_grid_attach(GTK_GRID(ct->widget), widget, grid->x, grid->y, colspan, rowspan); 212 gtk_grid_attach(GTK_GRID(ct->widget), widget, grid->x, grid->y, colspan, rowspan);
245 grid->x += colspan; 213 grid->x += colspan;
246 214
247 ui_reset_layout(ct->layout); 215 grid->container.current = widget;
248 ct->current = widget;
249 } 216 }
250 #endif 217 #endif
251 #ifdef UI_GTK2 218 #ifdef UI_GTK2
252 void ui_grid_container_add(UiContainer *ct, GtkWidget *widget) { 219 void ui_grid_container_add(UiContainerPrivate *ct, GtkWidget *widget) {
253 UiGridContainer *grid = (UiGridContainer*)ct; 220 UiGridContainer *grid = (UiGridContainer*)ct;
254 221 widget = ui_gtk_set_margin(widget, layout->margin, layout->margin_left, layout->margin_right, layout->margin_top, layout->margin_bottom);
255 if(ct->layout.newline) { 222
223 if(ct->container.newline) {
256 grid->x = 0; 224 grid->x = 0;
257 grid->y++; 225 grid->y++;
258 ct->layout.newline = FALSE; 226 ct->container.newline = FALSE;
259 } 227 }
260 228
261 int hexpand = FALSE; 229 uic_layout_setup_expand_fill(layout, grid->def_hexpand, grid->def_vexpand, grid->def_hfill, grid->def_vfill);
262 int vexpand = FALSE;
263 int hfill = FALSE;
264 int vfill = FALSE;
265 if(!ct->layout.override_defaults) {
266 if(grid->def_hexpand) {
267 hexpand = TRUE;
268 hfill = TRUE;
269 } else if(grid->def_hfill) {
270 hfill = TRUE;
271 }
272 if(grid->def_vexpand) {
273 vexpand = TRUE;
274 vfill = TRUE;
275 } else if(grid->def_vfill) {
276 vfill = TRUE;
277 }
278 }
279
280 UiBool fill = ct->layout.fill;
281 if(ct->layout.hexpand) {
282 hexpand = TRUE;
283 hfill = TRUE;
284 } else if(ct->layout.hfill) {
285 hfill = TRUE;
286 }
287 if(ct->layout.vexpand) {
288 vexpand = TRUE;
289 vfill = TRUE;
290 } else if(ct->layout.vfill) {
291 vfill = TRUE;
292 }
293 if(fill) {
294 hfill = TRUE;
295 vfill = TRUE;
296 }
297 230
298 GtkAttachOptions xoptions = 0; 231 GtkAttachOptions xoptions = 0;
299 GtkAttachOptions yoptions = 0; 232 GtkAttachOptions yoptions = 0;
300 if(hexpand) { 233 if(layout->hexpand) {
301 xoptions = GTK_EXPAND; 234 xoptions = GTK_EXPAND;
302 } 235 }
303 if(hfill) { 236 if(layout->hfill) {
304 xoptions |= GTK_FILL; 237 xoptions |= GTK_FILL;
305 } 238 }
306 if(vexpand) { 239 if(layout->vexpand) {
307 yoptions = GTK_EXPAND; 240 yoptions = GTK_EXPAND;
308 } 241 }
309 if(vfill) { 242 if(layout->vfill) {
310 yoptions |= GTK_FILL; 243 yoptions |= GTK_FILL;
311 } 244 }
312 245
313 int colspan = ct->layout.colspan > 0 ? ct->layout.colspan : 1; 246 int colspan = layout->colspan > 0 ? layout->colspan : 1;
314 int rowspan = ct->layout.rowspan > 0 ? ct->layout.rowspan : 1; 247 int rowspan = layout->rowspan > 0 ? layout->rowspan : 1;
315 // TODO: use colspan/rowspan 248 // TODO: use colspan/rowspan
316 249
317 gtk_table_attach(GTK_TABLE(ct->widget), widget, grid->x, grid->x+1, grid->y, grid->y+1, xoptions, yoptions, 0, 0); 250 gtk_table_attach(GTK_TABLE(ct->widget), widget, grid->x, grid->x+1, grid->y, grid->y+1, xoptions, yoptions, 0, 0);
318 grid->x++; 251 grid->x++;
319 int nw = grid->x > grid->width ? grid->x : grid->width; 252 int nw = grid->x > grid->width ? grid->x : grid->width;
321 grid->width = nw; 254 grid->width = nw;
322 grid->height = grid->y + 1; 255 grid->height = grid->y + 1;
323 gtk_table_resize(GTK_TABLE(ct->widget), grid->width, grid->height); 256 gtk_table_resize(GTK_TABLE(ct->widget), grid->width, grid->height);
324 } 257 }
325 258
326 ui_reset_layout(ct->layout);
327 ct->current = widget; 259 ct->current = widget;
328 } 260 }
329 #endif 261 #endif
330 262
331 UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame) { 263 UiContainerX* ui_frame_container(UiObject *obj, GtkWidget *frame) {
332 UiContainer *ct = cxCalloc( 264 UiContainerPrivate *ct = cxCalloc(
333 obj->ctx->allocator, 265 obj->ctx->allocator,
334 1, 266 1,
335 sizeof(UiContainer)); 267 sizeof(UiContainerPrivate));
336 ct->widget = frame; 268 ct->widget = frame;
337 ct->add = ui_frame_container_add; 269 ct->add = ui_frame_container_add;
338 return ct; 270 return (UiContainerX*)ct;
339 } 271 }
340 272
341 void ui_frame_container_add(UiContainer *ct, GtkWidget *widget) { 273 void ui_frame_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
274 widget = ui_gtk_set_margin(widget, layout->margin, layout->margin_left, layout->margin_right, layout->margin_top, layout->margin_bottom);
342 FRAME_SET_CHILD(ct->widget, widget); 275 FRAME_SET_CHILD(ct->widget, widget);
343 } 276 ct->current = widget;
344 277 }
345 UiContainer* ui_expander_container(UiObject *obj, GtkWidget *expander) { 278
346 UiContainer *ct = cxCalloc( 279 UiContainerX* ui_expander_container(UiObject *obj, GtkWidget *expander) {
280 UiContainerPrivate *ct = cxCalloc(
347 obj->ctx->allocator, 281 obj->ctx->allocator,
348 1, 282 1,
349 sizeof(UiContainer)); 283 sizeof(UiContainerPrivate));
350 ct->widget = expander; 284 ct->widget = expander;
351 ct->add = ui_expander_container_add; 285 ct->add = ui_expander_container_add;
352 return ct; 286 return (UiContainerX*)ct;
353 } 287 }
354 288
355 void ui_expander_container_add(UiContainer *ct, GtkWidget *widget) { 289 void ui_expander_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
290 widget = ui_gtk_set_margin(widget, layout->margin, layout->margin_left, layout->margin_right, layout->margin_top, layout->margin_bottom);
356 EXPANDER_SET_CHILD(ct->widget, widget); 291 EXPANDER_SET_CHILD(ct->widget, widget);
357 } 292 ct->current = widget;
358 293 }
359 void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget) { 294
295 void ui_scrolledwindow_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
296 widget = ui_gtk_set_margin(widget, layout->margin, layout->margin_left, layout->margin_right, layout->margin_top, layout->margin_bottom);
360 // TODO: check if the widget implements GtkScrollable 297 // TODO: check if the widget implements GtkScrollable
361 SCROLLEDWINDOW_SET_CHILD(ct->widget, widget); 298 SCROLLEDWINDOW_SET_CHILD(ct->widget, widget);
362 ui_reset_layout(ct->layout);
363 ct->current = widget; 299 ct->current = widget;
364 } 300 }
365 301
366 UiContainer* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow) { 302 UiContainerX* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow) {
367 UiContainer *ct = cxCalloc( 303 UiContainerPrivate *ct = cxCalloc(
368 obj->ctx->allocator, 304 obj->ctx->allocator,
369 1, 305 1,
370 sizeof(UiContainer)); 306 sizeof(UiContainerPrivate));
371 ct->widget = scrolledwindow; 307 ct->widget = scrolledwindow;
372 ct->add = ui_scrolledwindow_container_add; 308 ct->add = ui_scrolledwindow_container_add;
373 return ct; 309 return (UiContainerX*)ct;
374 } 310 }
375 311
376 UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview) { 312 UiContainerX* ui_tabview_container(UiObject *obj, GtkWidget *tabview) {
377 UiTabViewContainer *ct = cxCalloc( 313 UiTabViewContainer *ct = cxCalloc(
378 obj->ctx->allocator, 314 obj->ctx->allocator,
379 1, 315 1,
380 sizeof(UiTabViewContainer)); 316 sizeof(UiTabViewContainer));
381 ct->container.widget = tabview; 317 ct->container.widget = tabview;
382 ct->container.add = ui_tabview_container_add; 318 ct->container.add = ui_tabview_container_add;
383 return (UiContainer*)ct; 319 return (UiContainerX*)ct;
384 } 320 }
385 321
386 void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget) { 322 void ui_tabview_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
387 UiGtkTabView *data = ui_widget_get_tabview_data(ct->widget); 323 UiGtkTabView *data = ui_widget_get_tabview_data(ct->widget);
388 if(!data) { 324 if(!data) {
389 fprintf(stderr, "UI Error: widget is not a tabview"); 325 fprintf(stderr, "UI Error: widget is not a tabview");
390 return; 326 return;
391 } 327 }
392 data->add_tab(ct->widget, -1, ct->layout.label, widget); 328 widget = ui_gtk_set_margin(widget, layout->margin, layout->margin_left, layout->margin_right, layout->margin_top, layout->margin_bottom);
393 329 data->add_tab(ct->widget, -1, layout->label, widget);
394 ui_reset_layout(ct->layout); 330
395 ct->current = widget; 331 ct->current = widget;
396 } 332 }
397 333
398 334 #ifdef UI_GTK2
399 335
400 GtkWidget* ui_box_set_margin(GtkWidget *box, int margin) { 336 static void alignment_child_visibility_changed(GtkWidget *widget, gpointer user_data) {
401 GtkWidget *ret = box; 337 gtk_widget_set_visible(gtk_widget_get_parent(widget), gtk_widget_get_visible(widget));
338 }
339
340 #endif
341
342 GtkWidget* ui_gtk_set_margin(GtkWidget *widget, int margin, int margin_left, int margin_right, int margin_top, int margin_bottom) {
343 if(margin > 0) {
344 margin_left = margin;
345 margin_right = margin;
346 margin_top = margin;
347 margin_bottom = margin;
348 }
349 GtkWidget *ret = widget;
402 #if GTK_MAJOR_VERSION >= 3 350 #if GTK_MAJOR_VERSION >= 3
403 #if GTK_MAJOR_VERSION * 1000 + GTK_MINOR_VERSION >= 3012 351 #if GTK_CHECK_VERSION(3, 12, 0)
404 gtk_widget_set_margin_start(box, margin); 352 gtk_widget_set_margin_start(widget, margin_left);
405 gtk_widget_set_margin_end(box, margin); 353 gtk_widget_set_margin_end(widget, margin_right);
406 #else 354 #else
407 gtk_widget_set_margin_left(box, margin); 355 gtk_widget_set_margin_left(widget, margin_left);
408 gtk_widget_set_margin_right(box, margin); 356 gtk_widget_set_margin_right(widget, margin_right);
409 #endif 357 #endif
410 gtk_widget_set_margin_top(box, margin); 358 gtk_widget_set_margin_top(widget, margin_top);
411 gtk_widget_set_margin_bottom(box, margin); 359 gtk_widget_set_margin_bottom(widget, margin_bottom);
412 #elif defined(UI_GTK2) 360 #elif defined(UI_GTK2)
413 GtkWidget *a = gtk_alignment_new(0.5, 0.5, 1, 1); 361 GtkWidget *a = gtk_alignment_new(0.5, 0.5, 1, 1);
414 gtk_alignment_set_padding(GTK_ALIGNMENT(a), margin, margin, margin, margin); 362 gtk_alignment_set_padding(GTK_ALIGNMENT(a), margin_top, margin_bottom, margin_left, margin_right);
415 gtk_container_add(GTK_CONTAINER(a), box); 363 gtk_container_add(GTK_CONTAINER(a), widget);
364 g_signal_connect(
365 widget,
366 "show",
367 G_CALLBACK(alignment_child_visibility_changed),
368 NULL);
369 g_signal_connect(
370 widget,
371 "hide",
372 G_CALLBACK(alignment_child_visibility_changed),
373 NULL);
416 ret = a; 374 ret = a;
417 #endif 375 #endif
418 return ret; 376 return ret;
419 } 377 }
420 378
421 UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType type) { 379 UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType type) {
422 UiObject *current = uic_current_obj(obj); 380 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
423 UiContainer *ct = current->container; 381 UiLayout layout = UI_ARGS2LAYOUT(args);
424 UI_APPLY_LAYOUT2(current, args);
425 382
426 GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args->spacing) : ui_gtk_hbox_new(args->spacing); 383 GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args->spacing) : ui_gtk_hbox_new(args->spacing);
427 ui_set_name_and_style(box, args->name, args->style_class); 384 ui_set_name_and_style(box, args->name, args->style_class);
428 GtkWidget *widget = args->margin > 0 ? ui_box_set_margin(box, args->margin) : box; 385 ct->add(ct, box, &layout);
429 ct->add(ct, widget); 386
430 387 UiContainerX *container = ui_box_container(obj, box, type);
431 UiObject *newobj = uic_object_new(obj, box); 388 uic_object_push_container(obj, container);
432 newobj->container = ui_box_container(obj, box, type); 389
433 uic_obj_add(obj, newobj); 390 return box;
434
435 return widget;
436 } 391 }
437 392
438 UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) { 393 UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) {
439 return ui_box_create(obj, args, UI_CONTAINER_VBOX); 394 return ui_box_create(obj, args, UI_CONTAINER_VBOX);
440 } 395 }
455 #endif 410 #endif
456 return grid; 411 return grid;
457 } 412 }
458 413
459 UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) { 414 UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
460 UiObject* current = uic_current_obj(obj); 415 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
461 UI_APPLY_LAYOUT2(current, args); 416 UiLayout layout = UI_ARGS2LAYOUT(args);
462 GtkWidget *widget; 417 GtkWidget *widget;
463 418
464 GtkWidget *grid = ui_create_grid_widget(args->columnspacing, args->rowspacing); 419 GtkWidget *grid = ui_create_grid_widget(args->columnspacing, args->rowspacing);
465 ui_set_name_and_style(grid, args->name, args->style_class); 420 ui_set_name_and_style(grid, args->name, args->style_class);
466 widget = ui_box_set_margin(grid, args->margin); 421 ct->add(ct, grid, &layout);
467 current->container->add(current->container, widget); 422
468 423 UiContainerX *container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill);
469 UiObject *newobj = uic_object_new(obj, grid); 424 uic_object_push_container(obj, container);
470 newobj->container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill); 425
471 uic_obj_add(obj, newobj); 426 return grid;
472 427 }
473 return widget; 428
429 static void frame_create_subcontainer(UiObject *obj, UiFrameArgs *args) {
430 switch(args->subcontainer) {
431 default:
432 case UI_CONTAINER_VBOX: {
433 UiContainerArgs sub_args = { .spacing = args->spacing, .margin = args->padding };
434 ui_vbox_create(obj, &sub_args);
435 break;
436 }
437 case UI_CONTAINER_HBOX: {
438 UiContainerArgs sub_args = { .spacing = args->spacing, .margin = args->padding };
439 ui_hbox_create(obj, &sub_args);
440 break;
441 }
442 case UI_CONTAINER_GRID: {
443 UiContainerArgs sub_args = { .columnspacing = args->columnspacing, .rowspacing = args->rowspacing, .margin = args->padding };
444 ui_grid_create(obj, &sub_args);
445 break;
446 }
447 case UI_CONTAINER_NO_SUB: {
448 break; // NOOP
449 }
450 }
474 } 451 }
475 452
476 UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) { 453 UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
477 UiObject* current = uic_current_obj(obj); 454 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
478 UI_APPLY_LAYOUT2(current, args); 455 UiLayout layout = UI_ARGS2LAYOUT(args);
479 456
480 GtkWidget *frame = gtk_frame_new(args->label); 457 GtkWidget *frame = gtk_frame_new(args->label);
481 UiObject *newobj = uic_object_new(obj, frame); 458 ct->add(ct, frame, &layout);
482 GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin); 459
460 GtkWidget *sub = ui_subcontainer_create(
461 args->subcontainer,
462 obj, args->spacing,
463 args->columnspacing,
464 args->rowspacing,
465 args->padding);
483 if(sub) { 466 if(sub) {
484 FRAME_SET_CHILD(frame, sub); 467 FRAME_SET_CHILD(frame, sub);
485 } else { 468 } else {
486 newobj->widget = frame; 469 UiContainerX *container = ui_frame_container(obj, frame);
487 newobj->container = ui_frame_container(obj, frame); 470 uic_object_push_container(obj, container);
488 } 471 }
489 current->container->add(current->container, frame);
490 uic_obj_add(obj, newobj);
491 472
492 return frame; 473 return frame;
493 } 474 }
494 475
495 UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) { 476 UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) {
496 UiObject* current = uic_current_obj(obj); 477 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
497 UI_APPLY_LAYOUT2(current, args); 478 UiLayout layout = UI_ARGS2LAYOUT(args);
498 479
499 GtkWidget *expander = gtk_expander_new(args->label); 480 GtkWidget *expander = gtk_expander_new(args->label);
500 gtk_expander_set_expanded(GTK_EXPANDER(expander), args->isexpanded); 481 gtk_expander_set_expanded(GTK_EXPANDER(expander), args->isexpanded);
501 UiObject *newobj = uic_object_new(obj, expander); 482 ct->add(ct, expander, &layout);
502 GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin); 483
484 GtkWidget *sub = ui_subcontainer_create(
485 args->subcontainer,
486 obj, args->spacing,
487 args->columnspacing,
488 args->rowspacing,
489 args->padding);
503 if(sub) { 490 if(sub) {
504 EXPANDER_SET_CHILD(expander, sub); 491 EXPANDER_SET_CHILD(expander, sub);
505 } else { 492 } else {
506 newobj->widget = expander; 493 UiContainerX *container = ui_expander_container(obj, expander);
507 newobj->container = ui_expander_container(obj, expander); 494 uic_object_push_container(obj, container);
508 } 495 }
509 current->container->add(current->container, expander);
510 uic_obj_add(obj, newobj);
511 496
512 return expander; 497 return expander;
513 } 498 }
514 499
515 500
516 UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) { 501 UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) {
517 UiObject* current = uic_current_obj(obj); 502 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
518 UI_APPLY_LAYOUT2(current, args); 503 UiLayout layout = UI_ARGS2LAYOUT(args);
519 504
520 GtkWidget *sw = SCROLLEDWINDOW_NEW(); 505 GtkWidget *sw = SCROLLEDWINDOW_NEW();
521 ui_set_name_and_style(sw, args->name, args->style_class); 506 ui_set_name_and_style(sw, args->name, args->style_class);
522 GtkWidget *widget = ui_box_set_margin(sw, args->margin); 507 ct->add(ct, sw, &layout);
523 current->container->add(current->container, widget); 508
524 509 GtkWidget *sub = ui_subcontainer_create(
525 UiObject *newobj = uic_object_new(obj, sw); 510 args->subcontainer,
526 GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin); 511 obj, args->spacing,
512 args->columnspacing,
513 args->rowspacing,
514 args->padding);
527 if(sub) { 515 if(sub) {
528 SCROLLEDWINDOW_SET_CHILD(sw, sub); 516 SCROLLEDWINDOW_SET_CHILD(sw, sub);
529 } else { 517 } else {
530 newobj->widget = sw; 518 UiContainerX *container = ui_scrolledwindow_container(obj, sw);
531 newobj->container = ui_scrolledwindow_container(obj, sw); 519 uic_object_push_container(obj, container);
532 } 520 }
533
534 uic_obj_add(obj, newobj);
535 521
536 return sw; 522 return sw;
537 } 523 }
538 524
539 525
739 typedef void (*ui_tabview_set_func)(UiInteger*, int64_t); 725 typedef void (*ui_tabview_set_func)(UiInteger*, int64_t);
740 726
741 UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) { 727 UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) {
742 UiGtkTabView *data = malloc(sizeof(UiGtkTabView)); 728 UiGtkTabView *data = malloc(sizeof(UiGtkTabView));
743 memset(data, 0, sizeof(UiGtkTabView)); 729 memset(data, 0, sizeof(UiGtkTabView));
744 data->margin = args->margin; 730 data->padding = args->padding;
745 data->spacing = args->spacing; 731 data->spacing = args->spacing;
746 data->columnspacing = args->columnspacing; 732 data->columnspacing = args->columnspacing;
747 data->rowspacing = args->rowspacing; 733 data->rowspacing = args->rowspacing;
748 734
749 ui_tabview_get_func getfunc = NULL; 735 ui_tabview_get_func getfunc = NULL;
799 } 785 }
800 break; 786 break;
801 } 787 }
802 } 788 }
803 789
804 UiObject* current = uic_current_obj(obj);
805 if(args->value || args->varname) { 790 if(args->value || args->varname) {
806 UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER); 791 UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER);
807 UiInteger *i = var->value; 792 UiInteger *i = var->value;
808 i->get = getfunc; 793 i->get = getfunc;
809 i->set = setfunc; 794 i->set = setfunc;
810 i->obj = data_widget; 795 i->obj = data_widget;
811 } 796 }
812 797
813 g_object_set_data(G_OBJECT(widget), "ui_tabview", data); 798 g_object_set_data(G_OBJECT(widget), "ui_tabview", data);
814 data->widget = data_widget; 799 data->widget = data_widget;
815 data->subcontainer = args->subcontainer; 800
816 801 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
817 UI_APPLY_LAYOUT2(current, args); 802 UiLayout layout = UI_ARGS2LAYOUT(args);
818 current->container->add(current->container, widget); 803 ct->add(ct, widget, &layout);
819 804
820 UiObject *newobj = uic_object_new(obj, widget); 805 UiContainerX *container = ui_tabview_container(obj, widget);
821 newobj->container = ui_tabview_container(obj, widget); 806 uic_object_push_container(obj, container);
822 uic_obj_add(obj, newobj);
823 data->obj = newobj;
824 807
825 return widget; 808 return widget;
826 } 809 }
827 810
811 static GtkWidget* create_tab(UiObject *obj, UiGtkTabView *tabview, const char *title, int tab) {
812 UiContainerX *container;
813 GtkWidget *sub;
814 switch(tabview->subcontainer) {
815 default: {
816 sub = ui_gtk_vbox_new(tabview->spacing);
817 container = ui_box_container(obj, sub, tabview->subcontainer);
818 break;
819 }
820 case UI_CONTAINER_HBOX: {
821 sub = ui_gtk_hbox_new(tabview->spacing);
822 container = ui_box_container(obj, sub, tabview->subcontainer);
823 break;
824 }
825 case UI_CONTAINER_GRID: {
826 sub = ui_create_grid_widget(tabview->columnspacing, tabview->rowspacing);
827 container = ui_grid_container(obj, sub, FALSE, FALSE, FALSE, FALSE);
828 break;
829 }
830 }
831
832 uic_object_push_container(obj, container);
833
834 GtkWidget *widget = ui_gtk_set_margin(sub, tabview->padding, 0, 0, 0, 0);
835 tabview->add_tab(tabview->widget, tab, title, widget);
836
837 return sub;
838 }
839
828 void ui_tab_create(UiObject* obj, const char* title) { 840 void ui_tab_create(UiObject* obj, const char* title) {
829 UiObject* current = uic_current_obj(obj); 841 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
830 UiGtkTabView *data = ui_widget_get_tabview_data(current->widget); 842 GtkWidget *tabview = ct->widget;
843 UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
831 if(!data) { 844 if(!data) {
832 fprintf(stderr, "UI Error: widget is not a tabview\n"); 845 fprintf(stderr, "UI Error: widget is not a tabview\n");
833 return; 846 return;
834 } 847 }
835 848
836 UiObject *newobj = ui_tabview_add(current->widget, title, -1); 849 create_tab(obj, data, title, -1);
837 current->next = newobj;
838 } 850 }
839 851
840 852
841 853
842 void ui_tabview_select(UIWIDGET tabview, int tab) { 854 void ui_tabview_select(UIWIDGET tabview, int tab) {
862 if(!data) { 874 if(!data) {
863 fprintf(stderr, "UI Error: widget is not a tabview\n"); 875 fprintf(stderr, "UI Error: widget is not a tabview\n");
864 return NULL; 876 return NULL;
865 } 877 }
866 878
867 UiObject *newobj = cxCalloc(data->obj->ctx->allocator, 1, sizeof(UiObject)); 879 UiObject *newobj = uic_object_new_toplevel();
868 newobj->ctx = data->obj->ctx; 880 newobj->widget = create_tab(newobj, data, name, tab_index);
869
870 GtkWidget *sub;
871 switch(data->subcontainer) {
872 default: {
873 sub = ui_gtk_vbox_new(data->spacing);
874 newobj->container = ui_box_container(newobj, sub, data->subcontainer);
875 break;
876 }
877 case UI_CONTAINER_HBOX: {
878 sub = ui_gtk_hbox_new(data->spacing);
879 newobj->container = ui_box_container(newobj, sub, data->subcontainer);
880 break;
881 }
882 case UI_CONTAINER_GRID: {
883 sub = ui_create_grid_widget(data->columnspacing, data->rowspacing);
884 newobj->container = ui_grid_container(newobj, sub, FALSE, FALSE, FALSE, FALSE);
885 break;
886 }
887 }
888 newobj->widget = sub;
889 GtkWidget *widget = ui_box_set_margin(sub, data->margin);
890
891 data->add_tab(data->widget, tab_index, name, widget);
892 881
893 return newobj; 882 return newobj;
894 } 883 }
895 884
896 885
897 /* -------------------- Headerbar -------------------- */ 886 /* -------------------- Headerbar -------------------- */
898 887
899 static void hb_set_part(UiObject *obj, int part) { 888 static void hb_set_part(UiObject *obj, int part) {
900 UiObject* current = uic_current_obj(obj); 889 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
901 GtkWidget *headerbar = current->widget; 890 GtkWidget *headerbar = ct->widget;
902 891
903 UiHeaderbarContainer *hb = cxCalloc( 892 UiHeaderbarContainer *hb = cxCalloc(
904 obj->ctx->allocator, 893 obj->ctx->allocator,
905 1, 894 1,
906 sizeof(UiHeaderbarContainer)); 895 sizeof(UiHeaderbarContainer));
907 memcpy(hb, current->container, sizeof(UiHeaderbarContainer)); 896 memcpy(hb, ct, sizeof(UiHeaderbarContainer));
908
909 UiObject *newobj = uic_object_new(obj, headerbar);
910 newobj->container = (UiContainer*)hb;
911 uic_obj_add(obj, newobj);
912
913 hb->part = part; 897 hb->part = part;
898 uic_object_push_container(obj, (UiContainerX*)hb);
914 } 899 }
915 900
916 void ui_headerbar_start_create(UiObject *obj) { 901 void ui_headerbar_start_create(UiObject *obj) {
917 hb_set_part(obj, 0); 902 hb_set_part(obj, 0);
918 } 903 }
924 void ui_headerbar_end_create(UiObject *obj) { 909 void ui_headerbar_end_create(UiObject *obj) {
925 hb_set_part(obj, 1); 910 hb_set_part(obj, 1);
926 } 911 }
927 912
928 UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs *args) { 913 UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs *args) {
929 UiObject *current = uic_current_obj(obj); 914 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
930 UiContainer *ct = current->container; 915 UiLayout layout = UI_ARGS2LAYOUT(args);
931 UI_APPLY_LAYOUT2(current, args);
932 916
933 GtkWidget *box = ui_gtk_hbox_new(args->alt_spacing); 917 GtkWidget *box = ui_gtk_hbox_new(args->alt_spacing);
934 ui_set_name_and_style(box, args->name, args->style_class); 918 ui_set_name_and_style(box, args->name, args->style_class);
935 ct->add(ct, box); 919 ct->add(ct, box, &layout);
936 920
937 UiObject *newobj = uic_object_new(obj, box); 921 UiContainerX *container = ui_headerbar_fallback_container(obj, box);
938 newobj->container = ui_headerbar_fallback_container(obj, box); 922 uic_object_push_container(obj, container);
939 uic_obj_add(obj, newobj);
940 923
941 return box; 924 return box;
942 } 925 }
943 926
944 static void hb_fallback_set_part(UiObject *obj, int part) { 927 static void hb_fallback_set_part(UiObject *obj, int part) {
945 UiObject* current = uic_current_obj(obj); 928 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
946 GtkWidget *headerbar = current->widget; 929 GtkWidget *headerbar = ct->widget;
947 930
948 UiObject *newobj = uic_object_new(obj, headerbar); 931 UiContainerX *container = ui_headerbar_container(obj, headerbar);
949 newobj->container = ui_headerbar_container(obj, headerbar); 932 uic_object_push_container(obj, container);
950 uic_obj_add(obj, newobj); 933
951 934 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)container;
952 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)newobj->container;
953 hb->part = part; 935 hb->part = part;
954 } 936 }
955 937
956 UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar) { 938 UiContainerX* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar) {
957 UiHeaderbarContainer *ct = cxCalloc( 939 UiHeaderbarContainer *ct = cxCalloc(
958 obj->ctx->allocator, 940 obj->ctx->allocator,
959 1, 941 1,
960 sizeof(UiHeaderbarContainer)); 942 sizeof(UiHeaderbarContainer));
961 ct->container.widget = headerbar; 943 ct->container.widget = headerbar;
962 ct->container.add = ui_headerbar_fallback_container_add; 944 ct->container.add = ui_headerbar_fallback_container_add;
963 return (UiContainer*)ct; 945 return (UiContainerX*)ct;
964 } 946 }
965 947
966 void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget) { 948 void ui_headerbar_fallback_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
967 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct; 949 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
968 BOX_ADD(ct->widget, widget); 950 BOX_ADD(ct->widget, widget);
969 } 951 }
970 952
971 #if GTK_CHECK_VERSION(3, 10, 0) 953 #if GTK_CHECK_VERSION(3, 10, 0)
972 954
973 UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) { 955 UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) {
974 GtkWidget *headerbar = g_object_get_data(G_OBJECT(obj->widget), "ui_headerbar"); 956 GtkWidget *headerbar = g_object_get_data(G_OBJECT(obj->widget), "ui_headerbar");
975 if(!headerbar) { 957 if(!headerbar) {
976 return ui_headerbar_fallback_create(obj, args); 958 return ui_headerbar_fallback_create(obj, args);
977 } 959 }
978 960
979 UiObject *newobj = uic_object_new(obj, headerbar); 961 UiContainerX *container = ui_headerbar_container(obj, headerbar);
980 newobj->container = ui_headerbar_container(obj, headerbar); 962 uic_object_push_container(obj, container);
981 uic_obj_add(obj, newobj);
982 963
983 return headerbar; 964 return headerbar;
984 } 965 }
985 966
986 UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) { 967 UiContainerX* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) {
987 UiHeaderbarContainer *ct = cxCalloc( 968 UiHeaderbarContainer *ct = cxCalloc(
988 obj->ctx->allocator, 969 obj->ctx->allocator,
989 1, 970 1,
990 sizeof(UiHeaderbarContainer)); 971 sizeof(UiHeaderbarContainer));
991 ct->container.widget = headerbar; 972 ct->container.widget = headerbar;
992 ct->container.add = ui_headerbar_container_add; 973 ct->container.add = ui_headerbar_container_add;
993 return (UiContainer*)ct; 974 return (UiContainerX*)ct;
994 } 975 }
995 976
996 void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget) { 977 void ui_headerbar_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
997 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct; 978 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
998 if(hb->part == 0) { 979 if(hb->part == 0) {
999 UI_HEADERBAR_PACK_START(ct->widget, widget); 980 UI_HEADERBAR_PACK_START(ct->widget, widget);
1000 } else if(hb->part == 1) { 981 } else if(hb->part == 1) {
1001 UI_HEADERBAR_PACK_END(ct->widget, widget); 982 UI_HEADERBAR_PACK_END(ct->widget, widget);
1026 fprintf(stderr, "Error: window is not configured for sidebar\n"); 1007 fprintf(stderr, "Error: window is not configured for sidebar\n");
1027 return NULL; 1008 return NULL;
1028 } 1009 }
1029 1010
1030 GtkWidget *box = ui_gtk_vbox_new(args->spacing); 1011 GtkWidget *box = ui_gtk_vbox_new(args->spacing);
1031 ui_box_set_margin(box, args->margin); 1012 ui_gtk_set_margin(box, args->margin, args->margin_left, args->margin_right, args->margin_top, args->margin_bottom);
1032 adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), box); 1013 adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), box);
1033 1014
1034 UiObject *newobj = uic_object_new(obj, box); 1015 UiContainerX *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
1035 newobj->container = ui_box_container(obj, box, UI_CONTAINER_VBOX); 1016 uic_object_push_container(obj, container);
1036 uic_obj_add(obj, newobj);
1037 1017
1038 return box; 1018 return box;
1039 } 1019 }
1040 #else 1020 #else
1041 UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args) { 1021 UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args) {
1042 GtkWidget *sidebar_vbox = g_object_get_data(G_OBJECT(obj->widget), "ui_sidebar"); 1022 GtkWidget *sidebar_vbox = g_object_get_data(G_OBJECT(obj->widget), "ui_sidebar");
1043 1023
1044 GtkWidget *box = ui_gtk_vbox_new(args->spacing); 1024 GtkWidget *box = ui_gtk_vbox_new(args->spacing);
1045 ui_box_set_margin(box, args->margin); 1025 ui_gtk_set_margin(box, args->margin, args->margin_left, args->margin_right, args->margin_top, args->margin_bottom);
1046 BOX_ADD_EXPAND(sidebar_vbox, box); 1026 BOX_ADD_EXPAND(sidebar_vbox, box);
1047 1027
1048 UiObject *newobj = uic_object_new(obj, box); 1028 UiContainerX *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
1049 newobj->container = ui_box_container(obj, box, UI_CONTAINER_VBOX); 1029 uic_object_push_container(obj, container);
1050 uic_obj_add(obj, newobj);
1051 1030
1052 return box; 1031 return box;
1053 } 1032 }
1054 #endif 1033 #endif
1055 1034
1061 return NULL; 1040 return NULL;
1062 } 1041 }
1063 1042
1064 GtkWidget *box = ui_gtk_vbox_new(args->spacing); 1043 GtkWidget *box = ui_gtk_vbox_new(args->spacing);
1065 ui_set_name_and_style(box, args->name, args->style_class); 1044 ui_set_name_and_style(box, args->name, args->style_class);
1066 ui_box_set_margin(box, args->margin); 1045 ui_gtk_set_margin(box, args->margin, args->margin_left, args->margin_right, args->margin_top, args->margin_bottom);
1067 BOX_ADD_EXPAND(pbox, box); 1046 BOX_ADD_EXPAND(pbox, box);
1068 1047
1069 UiObject *newobj = uic_object_new(obj, box); 1048 UiContainerX *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
1070 newobj->container = ui_box_container(obj, box, UI_CONTAINER_VBOX); 1049 uic_object_push_container(obj, container);
1071 uic_obj_add(obj, newobj);
1072 1050
1073 return box; 1051 return box;
1074 } 1052 }
1075 1053
1076 UIWIDGET ui_left_panel_create(UiObject *obj, UiSidebarArgs *args) { 1054 UIWIDGET ui_left_panel_create(UiObject *obj, UiSidebarArgs *args) {
1106 ui_set_property(property_name, buf); 1084 ui_set_property(property_name, buf);
1107 free(property_name); 1085 free(property_name);
1108 } 1086 }
1109 1087
1110 static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs *args) { 1088 static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs *args) {
1111 UiObject* current = uic_current_obj(obj); 1089 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
1090 UiLayout layout = UI_ARGS2LAYOUT(args);
1112 1091
1113 GtkWidget *pane0 = create_paned(orientation); 1092 GtkWidget *pane0 = create_paned(orientation);
1114 1093 ct->add(ct, pane0, &layout);
1115 UI_APPLY_LAYOUT2(current, args);
1116 current->container->add(current->container, pane0);
1117 1094
1118 int max = args->max_panes == 0 ? 2 : args->max_panes; 1095 int max = args->max_panes == 0 ? 2 : args->max_panes;
1119 1096
1120 if(args->position_property) { 1097 if(args->position_property) {
1121 const char *pos_str = ui_get_property(args->position_property); 1098 const char *pos_str = ui_get_property(args->position_property);
1132 "destroy", 1109 "destroy",
1133 G_CALLBACK(save_pane_pos), 1110 G_CALLBACK(save_pane_pos),
1134 strdup(args->position_property)); 1111 strdup(args->position_property));
1135 } 1112 }
1136 1113
1137 UiObject *newobj = uic_object_new(obj, pane0); 1114 UiSplitPane *splitpane = ui_create_splitpane_data(pane0, orientation, max, args->initial_position);
1138 newobj->container = ui_splitpane_container(obj, pane0, orientation, max, args->initial_position); 1115 UiContainerX *container = ui_splitpane_container(obj, pane0, splitpane);
1139 uic_obj_add(obj, newobj); 1116 uic_object_push_container(obj, container);
1140 1117
1141 g_object_set_data(G_OBJECT(pane0), "ui_splitpane", newobj->container); 1118 g_object_set_data(G_OBJECT(pane0), "ui_splitpane", splitpane);
1142 1119
1143 UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER); 1120 UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER);
1144 if(var) { 1121 if(var) {
1145 UiSplitPaneContainer *s = (UiSplitPaneContainer*)newobj->container;
1146 UiInteger *i = var->value; 1122 UiInteger *i = var->value;
1147 s->initial_position = i->value; 1123 splitpane->initial_position = i->value;
1148 1124
1149 i->obj = s; 1125 i->obj = splitpane;
1150 i->get = ui_splitpane_get; 1126 i->get = ui_splitpane_get;
1151 i->set = ui_splitpane_set; 1127 i->set = ui_splitpane_set;
1152 } 1128 }
1153 1129
1154 return pane0; 1130 return pane0;
1160 1136
1161 UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs *args) { 1137 UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs *args) {
1162 return splitpane_create(obj, UI_VERTICAL, args); 1138 return splitpane_create(obj, UI_VERTICAL, args);
1163 } 1139 }
1164 1140
1165 UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiOrientation orientation, int max, int init) { 1141 UiSplitPane* ui_create_splitpane_data(GtkWidget *pane, UiOrientation orientation, int max, int init) {
1166 UiSplitPaneContainer *ct = ui_calloc(obj->ctx, 1, sizeof(UiSplitPaneContainer)); 1142 UiSplitPane *ct = malloc(sizeof(UiSplitPane));
1167 ct->container.widget = pane;
1168 ct->container.add = ui_splitpane_container_add;
1169 ct->current_pane = pane; 1143 ct->current_pane = pane;
1170 ct->orientation = orientation; 1144 ct->orientation = orientation;
1171 ct->max = max; 1145 ct->max = max;
1172 ct->initial_position = init; 1146 ct->initial_position = init;
1173 ct->children = cxArrayListCreateSimple(CX_STORE_POINTERS, 4); 1147 ct->children = cxArrayListCreateSimple(CX_STORE_POINTERS, 4);
1174 return (UiContainer*)ct; 1148 return ct;
1175 } 1149 }
1176 1150
1177 void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget) { 1151 UiContainerX* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiSplitPane *data) {
1178 UiSplitPaneContainer *s = (UiSplitPaneContainer*)ct; 1152 UiSplitPaneContainer *ct = ui_calloc(obj->ctx, 1, sizeof(UiSplitPaneContainer));
1153 ct->container.widget = pane;
1154 ct->container.add = ui_splitpane_container_add;
1155 ct->splitpane = data;
1156 return (UiContainerX*)ct;
1157 }
1158
1159 void ui_splitpane_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
1160 UiSplitPaneContainer *sct = (UiSplitPaneContainer*)ct;
1161 UiSplitPane *s = sct->splitpane;
1179 1162
1180 if(s->nchildren >= s->max) { 1163 if(s->nchildren >= s->max) {
1181 fprintf(stderr, "splitpane: maximum number of children reached\n"); 1164 fprintf(stderr, "splitpane: maximum number of children reached\n");
1182 return; 1165 return;
1183 } 1166 }
1205 s->nchildren++; 1188 s->nchildren++;
1206 } 1189 }
1207 } 1190 }
1208 1191
1209 int64_t ui_splitpane_get(UiInteger *i) { 1192 int64_t ui_splitpane_get(UiInteger *i) {
1210 UiSplitPaneContainer *s = i->obj; 1193 UiSplitPane *s = i->obj;
1211 i->value = gtk_paned_get_position(GTK_PANED(s->container.widget)); 1194 i->value = gtk_paned_get_position(GTK_PANED(s->current_pane));
1212 return i->value; 1195 return i->value;
1213 } 1196 }
1214 1197
1215 void ui_splitpane_set(UiInteger *i, int64_t value) { 1198 void ui_splitpane_set(UiInteger *i, int64_t value) {
1216 UiSplitPaneContainer *s = i->obj; 1199 UiSplitPane *s = i->obj;
1217 i->value = value; 1200 i->value = value;
1218 gtk_paned_set_position(GTK_PANED(s->container.widget), (int)value); 1201 gtk_paned_set_position(GTK_PANED(s->current_pane), (int)value);
1219 } 1202 }
1220 1203
1221 UIEXPORT void ui_splitpane_set_visible(UIWIDGET splitpane, int child_index, UiBool visible) { 1204 UIEXPORT void ui_splitpane_set_visible(UIWIDGET splitpane, int child_index, UiBool visible) {
1222 UiSplitPaneContainer *ct = g_object_get_data(G_OBJECT(splitpane), "ui_splitpane"); 1205 UiSplitPane *s = g_object_get_data(G_OBJECT(splitpane), "ui_splitpane");
1223 if(!ct) { 1206 if(!s) {
1224 fprintf(stderr, "UI Error: not a splitpane\n"); 1207 fprintf(stderr, "UI Error: not a splitpane\n");
1225 return; 1208 return;
1226 } 1209 }
1227 1210
1228 GtkWidget *w = cxListAt(ct->children, child_index); 1211 GtkWidget *w = cxListAt(s->children, child_index);
1229 if(w) { 1212 if(w) {
1230 gtk_widget_set_visible(w, visible); 1213 gtk_widget_set_visible(w, visible);
1231 } 1214 }
1232 } 1215 }
1233 1216
1277 while(elm) { 1260 while(elm) {
1278 CxHashKey key = cx_hash_key(&elm, sizeof(void*)); 1261 CxHashKey key = cx_hash_key(&elm, sizeof(void*));
1279 UiObject *item_obj = cxMapGet(ct->current_items, key); 1262 UiObject *item_obj = cxMapGet(ct->current_items, key);
1280 if(item_obj) { 1263 if(item_obj) {
1281 // re-add previously created widget 1264 // re-add previously created widget
1282 ui_box_container_add(ct->container, item_obj->widget); 1265 UiLayout layout = {0};
1266 ui_box_container_add(ct->container, item_obj->widget, &layout);
1283 } else { 1267 } else {
1284 // create new widget and object for this list element 1268 // create new widget and object for this list element
1285 CxMempool *mp = cxMempoolCreateSimple(256); 1269 UiObject *obj = uic_object_new_toplevel();
1286 const CxAllocator *a = mp->allocator; 1270 obj->ctx->parent = ct->parent->ctx;
1287 UiObject *obj = cxCalloc(a, 1, sizeof(UiObject));
1288 obj->ctx = uic_context(obj, mp);
1289 obj->window = NULL; 1271 obj->window = NULL;
1290 obj->widget = ui_subcontainer_create( 1272 obj->widget = ui_subcontainer_create(
1291 ct->subcontainer, 1273 ct->subcontainer,
1292 obj, 1274 obj,
1293 ct->spacing, 1275 ct->spacing,
1294 ct->columnspacing, 1276 ct->columnspacing,
1295 ct->rowspacing, 1277 ct->rowspacing,
1296 ct->margin); 1278 ct->margin);
1297 ui_box_container_add(ct->container, obj->widget); 1279 UiLayout layout = {0};
1280 ui_box_container_add(ct->container, obj->widget, &layout);
1298 if(ct->create_ui) { 1281 if(ct->create_ui) {
1299 ct->create_ui(obj, index, elm, ct->userdata); 1282 ct->create_ui(obj, index, elm, ct->userdata);
1300 } 1283 }
1301 cxMapPut(new_items, key, obj); 1284 cxMapPut(new_items, key, obj);
1302 } 1285 }
1314 cxMapFree(container->current_items); 1297 cxMapFree(container->current_items);
1315 free(container); 1298 free(container);
1316 } 1299 }
1317 1300
1318 UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs *args) { 1301 UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs *args) {
1319 UiObject *current = uic_current_obj(obj); 1302 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
1320 UiContainer *ct = current->container; 1303 UiLayout layout = UI_ARGS2LAYOUT(args);
1321 UI_APPLY_LAYOUT2(current, args);
1322 1304
1323 GtkWidget *box = args->container == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args->spacing) : ui_gtk_hbox_new(args->spacing); 1305 GtkWidget *box = args->container == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args->spacing) : ui_gtk_hbox_new(args->spacing);
1324 ui_set_name_and_style(box, args->name, args->style_class); 1306 ui_set_name_and_style(box, args->name, args->style_class);
1325 GtkWidget *widget = args->margin > 0 ? ui_box_set_margin(box, args->margin) : box; 1307 ct->add(ct, box, &layout);
1326 ct->add(ct, widget);
1327 1308
1328 UiGtkItemListContainer *container = malloc(sizeof(UiGtkItemListContainer)); 1309 UiGtkItemListContainer *container = malloc(sizeof(UiGtkItemListContainer));
1329 container->parent = obj; 1310 container->parent = obj;
1330 container->widget = box; 1311 container->widget = box;
1331 container->container = ui_box_container(current, box, args->container); 1312 container->container = (UiContainerPrivate*)ui_box_container(obj, box, args->container);
1332 container->create_ui = args->create_ui; 1313 container->create_ui = args->create_ui;
1333 container->userdata = args->userdata; 1314 container->userdata = args->userdata;
1334 container->subcontainer = args->subcontainer; 1315 container->subcontainer = args->subcontainer;
1335 container->current_items = cxHashMapCreateSimple(CX_STORE_POINTERS); 1316 container->current_items = cxHashMapCreateSimple(CX_STORE_POINTERS);
1336 container->current_items->collection.advanced_destructor = remove_item; 1317 container->current_items->collection.advanced_destructor = remove_item;
1339 container->spacing = args->sub_spacing; 1320 container->spacing = args->sub_spacing;
1340 container->columnspacing = args->sub_columnspacing; 1321 container->columnspacing = args->sub_columnspacing;
1341 container->rowspacing = args->sub_rowspacing; 1322 container->rowspacing = args->sub_rowspacing;
1342 container->remove_items = TRUE; 1323 container->remove_items = TRUE;
1343 1324
1344 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_LIST); 1325 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_LIST);
1345 if(var) { 1326 if(var) {
1346 UiList *list = var->value; 1327 UiList *list = var->value;
1347 list->obj = container; 1328 list->obj = container;
1348 list->update = update_itemlist; 1329 list->update = update_itemlist;
1349 update_itemlist(list, 0); 1330 update_itemlist(list, 0);
1356 1337
1357 return box; 1338 return box;
1358 } 1339 }
1359 1340
1360 1341
1361
1362 /*
1363 * -------------------- Layout Functions --------------------
1364 *
1365 * functions for setting layout attributes for the current container
1366 *
1367 */
1368
1369 void ui_layout_fill(UiObject *obj, UiBool fill) {
1370 UiContainer *ct = uic_get_current_container(obj);
1371 ct->layout.fill = fill;
1372 }
1373
1374 void ui_layout_hexpand(UiObject *obj, UiBool expand) {
1375 UiContainer *ct = uic_get_current_container(obj);
1376 ct->layout.hexpand = expand;
1377 }
1378
1379 void ui_layout_vexpand(UiObject *obj, UiBool expand) {
1380 UiContainer *ct = uic_get_current_container(obj);
1381 ct->layout.vexpand = expand;
1382 }
1383
1384 void ui_layout_hfill(UiObject *obj, UiBool fill) {
1385 UiContainer *ct = uic_get_current_container(obj);
1386 ct->layout.hfill = fill;
1387 }
1388
1389 void ui_layout_vfill(UiObject *obj, UiBool fill) {
1390 UiContainer *ct = uic_get_current_container(obj);
1391 ct->layout.vfill = fill;
1392 }
1393
1394 UIEXPORT void ui_layout_override_defaults(UiObject *obj, UiBool d) {
1395 UiContainer *ct = uic_get_current_container(obj);
1396 ct->layout.override_defaults = d;
1397 }
1398
1399 void ui_layout_colspan(UiObject* obj, int cols) {
1400 UiContainer* ct = uic_get_current_container(obj);
1401 ct->layout.colspan = cols;
1402 }
1403
1404 void ui_layout_rowspan(UiObject* obj, int rows) {
1405 UiContainer* ct = uic_get_current_container(obj);
1406 ct->layout.rowspan = rows;
1407 }
1408
1409 void ui_newline(UiObject *obj) {
1410 UiContainer *ct = uic_get_current_container(obj);
1411 ct->layout.newline = TRUE;
1412 }
1413

mercurial