ui/gtk/container.c

changeset 51
e324291ca9f8
parent 45
ab71409644b0
equal deleted inserted replaced
50:9c25e2616bfa 51:e324291ca9f8
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <limits.h> 31 #include <limits.h>
32 32
33 #include "container.h" 33 #include "container.h"
34 #include "toolkit.h" 34 #include "toolkit.h"
35 #include "headerbar.h"
35 36
36 #include "../common/context.h" 37 #include "../common/context.h"
37 #include "../common/object.h" 38 #include "../common/object.h"
38 39
39 40
226 ct->container.add = ui_tabview_container_add; 227 ct->container.add = ui_tabview_container_add;
227 return (UiContainer*)ct; 228 return (UiContainer*)ct;
228 } 229 }
229 230
230 void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { 231 void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
231 gtk_notebook_append_page( 232 UiGtkTabView *data = ui_widget_get_tabview_data(ct->widget);
232 GTK_NOTEBOOK(ct->widget), 233 if(!data) {
233 widget, 234 fprintf(stderr, "UI Error: widget is not a tabview");
234 gtk_label_new(ct->layout.label)); 235 return;
236 }
237 data->add_tab(ct->widget, -1, ct->layout.label, widget);
235 238
236 ui_reset_layout(ct->layout); 239 ui_reset_layout(ct->layout);
237 ct->current = widget; 240 ct->current = widget;
238 } 241 }
239 242
328 331
329 return sw; 332 return sw;
330 } 333 }
331 334
332 335
333 void ui_select_tab(UIWIDGET tabview, int tab) { 336 void ui_notebook_tab_select(UIWIDGET tabview, int tab) {
334 gtk_notebook_set_current_page(GTK_NOTEBOOK(tabview), tab); 337 gtk_notebook_set_current_page(GTK_NOTEBOOK(tabview), tab);
335 } 338 }
339
340 void ui_notebook_tab_remove(UIWIDGET tabview, int tab) {
341 gtk_notebook_remove_page(GTK_NOTEBOOK(tabview), tab);
342 }
343
344 void ui_notebook_tab_add(UIWIDGET widget, int index, const char *name, UIWIDGET child) {
345 gtk_notebook_insert_page(
346 GTK_NOTEBOOK(widget),
347 child,
348 gtk_label_new(name),
349 index);
350 }
351
352 int64_t ui_notebook_get(UiInteger *i) {
353 GtkNotebook *nb = i->obj;
354 i->value = gtk_notebook_get_current_page(nb);
355 return i->value;
356 }
357
358 void ui_notebook_set(UiInteger *i, int64_t value) {
359 GtkNotebook *nb = i->obj;
360 gtk_notebook_set_current_page(nb, value);
361 i->value = gtk_notebook_get_current_page(nb);
362 }
363
364
365 #if GTK_MAJOR_VERSION >= 4
366 static int stack_set_page(GtkWidget *stack, int index) {
367 GtkSelectionModel *pages = gtk_stack_get_pages(GTK_STACK(stack));
368 GListModel *list = G_LIST_MODEL(pages);
369 GtkStackPage *page = g_list_model_get_item(list, index);
370 if(page) {
371 gtk_stack_set_visible_child(GTK_STACK(stack), gtk_stack_page_get_child(page));
372 } else {
373 fprintf(stderr, "UI Error: ui_stack_set value out of bounds\n");
374 return -1;
375 }
376 return index;
377 }
378
379 void ui_stack_tab_select(UIWIDGET tabview, int tab) {
380 stack_set_page(tabview, tab);
381 }
382
383 void ui_stack_tab_remove(UIWIDGET tabview, int tab) {
384 GtkStack *stack = GTK_STACK(tabview);
385 GtkWidget *current = gtk_stack_get_visible_child(stack);
386 GtkSelectionModel *pages = gtk_stack_get_pages(stack);
387 GListModel *list = G_LIST_MODEL(pages);
388 GtkStackPage *page = g_list_model_get_item(list, tab);
389 if(page) {
390 gtk_stack_remove(stack, gtk_stack_page_get_child(page));
391 }
392 }
393
394 void ui_stack_tab_add(UIWIDGET widget, int index, const char *name, UIWIDGET child) {
395 (void)gtk_stack_add_titled(GTK_STACK(widget), child, name, name);
396 }
397
398 int64_t ui_stack_get(UiInteger *i) {
399 GtkStack *stack = GTK_STACK(i->obj);
400 GtkWidget *current = gtk_stack_get_visible_child(stack);
401 GtkSelectionModel *pages = gtk_stack_get_pages(stack);
402 GListModel *list = G_LIST_MODEL(pages);
403 int nitems = g_list_model_get_n_items(list);
404 for(int p=0;p<nitems;p++) {
405 GtkStackPage *page = g_list_model_get_item(list, p);
406 GtkWidget *child = gtk_stack_page_get_child(page);
407 if(child == current) {
408 i->value = p;
409 break;
410 }
411 }
412 return i->value;
413 }
414
415 void ui_stack_set(UiInteger *i, int64_t value) {
416 GtkWidget *widget = i->obj;
417 if(stack_set_page(widget, value) >= 0) {
418 i->value = value;
419 }
420 }
421 #elif GTK_MAJOR_VERSION >= 3
422 static GtkWidget* stack_get_child(GtkWidget *stack, int index) {
423 GList *children = gtk_container_get_children(GTK_CONTAINER(stack));
424 if(children) {
425 return g_list_nth_data(children, index);
426 }
427 return NULL;
428 }
429
430 void ui_stack_tab_select(UIWIDGET tabview, int tab) {
431 GtkWidget *child = stack_get_child(tabview, tab);
432 if(child) {
433 gtk_stack_set_visible_child(GTK_STACK(tabview), child);
434 }
435 }
436
437 void ui_stack_tab_remove(UIWIDGET tabview, int tab) {
438 GtkWidget *child = stack_get_child(tabview, tab);
439 if(child) {
440 gtk_container_remove(GTK_CONTAINER(tabview), child);
441 }
442 }
443
444 void ui_stack_tab_add(UIWIDGET widget, int index, const char *name, UIWIDGET child) {
445 gtk_stack_add_titled(GTK_STACK(widget), child, name, name);
446 }
447
448 int64_t ui_stack_get(UiInteger *i) {
449 GtkWidget *visible = gtk_stack_get_visible_child(GTK_STACK(i->obj));
450 GList *children = gtk_container_get_children(GTK_CONTAINER(i->obj));
451 GList *elm = children;
452 int n = 0;
453 int64_t v = -1;
454 while(elm) {
455 GtkWidget *child = elm->data;
456 if(child == visible) {
457 v = n;
458 break;
459 }
460
461 elm = elm->next;
462 n++;
463 }
464 g_list_free(children);
465 i->value = v;
466 return v;
467 }
468
469 void ui_stack_set(UiInteger *i, int64_t value) {
470 GtkWidget *child = stack_get_child(i->obj, value);
471 if(child) {
472 gtk_stack_set_visible_child(GTK_STACK(i->obj), child);
473 i->value = value;
474 }
475 }
476
477 #endif
478
479
480
481
482 UiGtkTabView* ui_widget_get_tabview_data(UIWIDGET tabview) {
483 return g_object_get_data(G_OBJECT(tabview), "ui_tabview");
484 }
485
486 typedef int64_t(*ui_tabview_get_func)(UiInteger*);
487 typedef void (*ui_tabview_set_func)(UiInteger*, int64_t);
488
489 UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) {
490 UiGtkTabView *data = malloc(sizeof(UiGtkTabView));
491 data->margin = args.margin;
492 data->spacing = args.spacing;
493 data->columnspacing = args.columnspacing;
494 data->rowspacing = args.rowspacing;
495
496 ui_tabview_get_func getfunc = NULL;
497 ui_tabview_set_func setfunc = NULL;
498
499 GtkWidget *widget = NULL;
500 GtkWidget *data_widget = NULL;
501 switch(args.tabview) {
502 case UI_TABVIEW_DOC: {
503 // TODO
504 break;
505 }
506 case UI_TABVIEW_NAVIGATION_SIDE: {
507 #if GTK_CHECK_VERSION(3, 10, 0)
508 widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
509 GtkWidget *sidebar = gtk_stack_sidebar_new();
510 BOX_ADD(widget, sidebar);
511 GtkWidget *stack = gtk_stack_new();
512 gtk_stack_set_transition_type (GTK_STACK(stack), GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN);
513 gtk_stack_sidebar_set_stack(GTK_STACK_SIDEBAR(sidebar), GTK_STACK(stack));
514 BOX_ADD_EXPAND(widget, stack);
515 data->select_tab = ui_stack_tab_select;
516 data->remove_tab = ui_stack_tab_remove;
517 data->add_tab = ui_stack_tab_add;
518 getfunc = ui_stack_get;
519 setfunc = ui_stack_set;
520 data_widget = stack;
521 #else
522 // TODO
523 #endif
524 break;
525 }
526 case UI_TABVIEW_DEFAULT: /* fall through */
527 case UI_TABVIEW_NAVIGATION_TOP: /* fall through */
528 case UI_TABVIEW_INVISIBLE: /* fall through */
529 case UI_TABVIEW_NAVIGATION_TOP2: {
530 widget = gtk_notebook_new();
531 data_widget = widget;
532 data->select_tab = ui_notebook_tab_select;
533 data->remove_tab = ui_notebook_tab_remove;
534 data->add_tab = ui_notebook_tab_add;
535 getfunc = ui_notebook_get;
536 setfunc = ui_notebook_set;
537 if(args.tabview == UI_TABVIEW_INVISIBLE) {
538 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(widget), FALSE);
539 gtk_notebook_set_show_border(GTK_NOTEBOOK(widget), FALSE);
540 }
541 break;
542 }
543 }
544
545 UiObject* current = uic_current_obj(obj);
546 if(args.value || args.varname) {
547 UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
548 UiInteger *i = var->value;
549 i->get = getfunc;
550 i->set = setfunc;
551 i->obj = data_widget;
552 }
553
554 g_object_set_data(G_OBJECT(widget), "ui_tabview", data);
555 data->widget = data_widget;
556 data->subcontainer = args.subcontainer;
557
558 UI_APPLY_LAYOUT1(current, args);
559 current->container->add(current->container, widget, TRUE);
560
561 UiObject *newobj = uic_object_new(obj, widget);
562 newobj->container = ui_tabview_container(obj, widget);
563 uic_obj_add(obj, newobj);
564 data->obj = newobj;
565
566 return widget;
567 }
568
569 void ui_tab_create(UiObject* obj, const char* title) {
570 UiObject* current = uic_current_obj(obj);
571 UiGtkTabView *data = ui_widget_get_tabview_data(current->widget);
572 if(!data) {
573 fprintf(stderr, "UI Error: widget is not a tabview\n");
574 return;
575 }
576
577 UiObject *newobj = ui_tabview_add(current->widget, title, -1);
578 current->next = newobj;
579 }
580
581
582
583 void ui_tabview_select(UIWIDGET tabview, int tab) {
584 UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
585 if(!data) {
586 fprintf(stderr, "UI Error: widget is not a tabview\n");
587 return;
588 }
589 data->select_tab(tabview, tab);
590 }
591
592 void ui_tabview_remove(UIWIDGET tabview, int tab) {
593 UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
594 if(!data) {
595 fprintf(stderr, "UI Error: widget is not a tabview\n");
596 return;
597 }
598 data->remove_tab(tabview, tab);
599 }
600
601 UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index) {
602 UiGtkTabView *data = ui_widget_get_tabview_data(tabview);
603 if(!data) {
604 fprintf(stderr, "UI Error: widget is not a tabview\n");
605 return NULL;
606 }
607
608 UiObject *newobj = cxCalloc(data->obj->ctx->allocator, 1, sizeof(UiObject));
609 newobj->ctx = data->obj->ctx;
610
611 GtkWidget *sub;
612 switch(data->subcontainer) {
613 default: {
614 sub = ui_gtk_vbox_new(data->spacing);
615 newobj->container = ui_box_container(newobj, sub, data->subcontainer);
616 break;
617 }
618 case UI_CONTAINER_HBOX: {
619 sub = ui_gtk_hbox_new(data->spacing);
620 newobj->container = ui_box_container(newobj, sub, data->subcontainer);
621 break;
622 }
623 case UI_CONTAINER_GRID: {
624 sub = create_grid(data->columnspacing, data->rowspacing);
625 newobj->container = ui_grid_container(newobj, sub);
626 break;
627 }
628 }
629 newobj->widget = sub;
630 GtkWidget *widget = box_set_margin(sub, data->margin);
631
632 data->add_tab(data->widget, tab_index, name, widget);
633
634 return newobj;
635 }
636
637
638 /* -------------------- Headerbar -------------------- */
639
640 static void hb_set_part(UiObject *obj, int part) {
641 UiObject* current = uic_current_obj(obj);
642 GtkWidget *headerbar = current->widget;
643
644 UiHeaderbarContainer *hb = cxCalloc(
645 obj->ctx->allocator,
646 1,
647 sizeof(UiHeaderbarContainer));
648 memcpy(hb, current->container, sizeof(UiHeaderbarContainer));
649
650 UiObject *newobj = uic_object_new(obj, headerbar);
651 newobj->container = (UiContainer*)hb;
652 uic_obj_add(obj, newobj);
653
654 hb->part = part;
655 }
656
657 void ui_headerbar_start_create(UiObject *obj) {
658 hb_set_part(obj, 0);
659 }
660
661 void ui_headerbar_center_create(UiObject *obj) {
662 hb_set_part(obj, 2);
663 }
664
665 void ui_headerbar_end_create(UiObject *obj) {
666 hb_set_part(obj, 1);
667 }
668
669 UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs args) {
670 UiObject *current = uic_current_obj(obj);
671 UiContainer *ct = current->container;
672 UI_APPLY_LAYOUT1(current, args);
673
674 GtkWidget *box = ui_gtk_hbox_new(args.alt_spacing);
675 ui_set_name_and_style(box, args.name, args.style_class);
676 ct->add(ct, box, FALSE);
677
678 UiObject *newobj = uic_object_new(obj, box);
679 newobj->container = ui_headerbar_fallback_container(obj, box);
680 uic_obj_add(obj, newobj);
681
682 return box;
683 }
684
685 static void hb_fallback_set_part(UiObject *obj, int part) {
686 UiObject* current = uic_current_obj(obj);
687 GtkWidget *headerbar = current->widget;
688
689 UiObject *newobj = uic_object_new(obj, headerbar);
690 newobj->container = ui_headerbar_container(obj, headerbar);
691 uic_obj_add(obj, newobj);
692
693 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)newobj->container;
694 hb->part = part;
695 }
696
697 UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar) {
698 UiHeaderbarContainer *ct = cxCalloc(
699 obj->ctx->allocator,
700 1,
701 sizeof(UiHeaderbarContainer));
702 ct->container.widget = headerbar;
703 ct->container.add = ui_headerbar_fallback_container_add;
704 return (UiContainer*)ct;
705 }
706
707 void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
708 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
709 BOX_ADD(ct->widget, widget);
710 }
711
712 #if GTK_CHECK_VERSION(3, 10, 0)
713
714 UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
715 GtkWidget *headerbar = g_object_get_data(G_OBJECT(obj->widget), "ui_headerbar");
716 if(!headerbar) {
717 return ui_headerbar_fallback_create(obj, args);
718 }
719
720 UiObject *newobj = uic_object_new(obj, headerbar);
721 newobj->container = ui_headerbar_container(obj, headerbar);
722 uic_obj_add(obj, newobj);
723
724 return headerbar;
725 }
726
727 UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) {
728 UiHeaderbarContainer *ct = cxCalloc(
729 obj->ctx->allocator,
730 1,
731 sizeof(UiHeaderbarContainer));
732 ct->container.widget = headerbar;
733 ct->container.add = ui_headerbar_container_add;
734 return (UiContainer*)ct;
735 }
736
737 void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
738 UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
739 if(hb->part == 0) {
740 UI_HEADERBAR_PACK_START(ct->widget, widget);
741 } else if(hb->part == 1) {
742 UI_HEADERBAR_PACK_END(ct->widget, widget);
743 } else if(hb->part == 2) {
744 if(!hb->centerbox) {
745 GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
746 hb->centerbox = box;
747 UI_HEADERBAR_SET_TITLE_WIDGET(ct->widget, box);
748 }
749 BOX_ADD(hb->centerbox, widget);
750 }
751 }
752
753 #else
754
755 UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
756 return ui_headerbar_fallback_create(obj, args);
757 }
758
759 #endif
336 760
337 /* -------------------- Splitpane -------------------- */ 761 /* -------------------- Splitpane -------------------- */
338 762
339 static GtkWidget* create_paned(UiOrientation orientation) { 763 static GtkWidget* create_paned(UiOrientation orientation) {
340 #if GTK_MAJOR_VERSION >= 3 764 #if GTK_MAJOR_VERSION >= 3

mercurial