ui/gtk/container.c

branch
newapi
changeset 422
c1354a29a7e9
parent 410
a080c69125d1
equal deleted inserted replaced
421:3b969399f962 422:c1354a29a7e9
944 return NULL; 944 return NULL;
945 } 945 }
946 946
947 947
948 948
949 /* -------------------- ItemList Container -------------------- */
950
951 static void remove_item(void *data, void *item) {
952 UiGtkItemListContainer *ct = data;
953 UiObject *obj = item;
954 if(ct->remove_items) {
955 BOX_REMOVE(ct->widget, obj->widget);
956 }
957 uic_object_destroy(obj);
958 }
959
960 static void update_itemlist(UiList *list, int c) {
961 UiGtkItemListContainer *ct = list->obj;
962
963 CxMap *new_items = cxHashMapCreateSimple(CX_STORE_POINTERS);
964 new_items->collection.advanced_destructor = remove_item;
965 new_items->collection.destructor_data = ct;
966
967 // only create new widgets for new elements, so at first we have
968 // to find which elements are new
969 // check which elements in the list are already in the container
970 void *elm = list->first(list);
971 int j = 0;
972 while(elm) {
973 CxHashKey key = cx_hash_key(&elm, sizeof(void*));
974 UiObject *item_obj = cxMapRemoveAndGet(ct->current_items, key);
975 if(item_obj) {
976 g_object_ref(G_OBJECT(item_obj->widget));
977 BOX_REMOVE(ct->widget, item_obj->widget);
978 cxMapPut(new_items, key, item_obj);
979 }
980 elm = list->next(list);
981 j++;
982 }
983
984 // ct->current_items only contains elements, that are not in the list
985 cxMapDestroy(ct->current_items); // calls destructor remove_item
986 ct->current_items = new_items;
987
988 // add all items
989 int index = 0;
990 elm = list->first(list);
991 while(elm) {
992 CxHashKey key = cx_hash_key(&elm, sizeof(void*));
993 UiObject *item_obj = cxMapGet(ct->current_items, key);
994 if(item_obj) {
995 // re-add previously created widget
996 ui_box_container_add(ct->container, item_obj->widget, FALSE);
997 } else {
998 // create new widget and object for this list element
999 CxMempool *mp = cxBasicMempoolCreate(256);
1000 const CxAllocator *a = mp->allocator;
1001 UiObject *obj = cxCalloc(a, 1, sizeof(UiObject));
1002 obj->ctx = uic_context(obj, mp);
1003 obj->window = NULL;
1004 obj->widget = ui_subcontainer_create(
1005 ct->subcontainer,
1006 obj,
1007 ct->spacing,
1008 ct->columnspacing,
1009 ct->rowspacing,
1010 ct->margin);
1011 ui_box_container_add(ct->container, obj->widget, FALSE);
1012 if(ct->create_ui) {
1013 ct->create_ui(obj, index, elm, ct->userdata);
1014 }
1015 cxMapPut(new_items, key, obj);
1016 }
1017 elm = list->next(list);
1018 index++;
1019 }
1020 }
1021
1022 static void destroy_itemlist_container(GtkWidget *w, UiGtkItemListContainer *container) {
1023 container->remove_items = FALSE;
1024 cxMapDestroy(container->current_items);
1025 free(container);
1026 }
1027
1028 UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs args) {
1029 UiObject *current = uic_current_obj(obj);
1030 UiContainer *ct = current->container;
1031 UI_APPLY_LAYOUT1(current, args);
1032
1033 GtkWidget *box = args.container == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing);
1034 ui_set_name_and_style(box, args.name, args.style_class);
1035 GtkWidget *widget = args.margin > 0 ? ui_box_set_margin(box, args.margin) : box;
1036 ct->add(ct, widget, TRUE);
1037
1038 UiGtkItemListContainer *container = malloc(sizeof(UiGtkItemListContainer));
1039 container->parent = obj;
1040 container->widget = box;
1041 container->container = ui_box_container(current, box, args.container);
1042 container->create_ui = args.create_ui;
1043 container->userdata = args.userdata;
1044 container->subcontainer = args.subcontainer;
1045 container->current_items = cxHashMapCreateSimple(CX_STORE_POINTERS);
1046 container->current_items->collection.advanced_destructor = remove_item;
1047 container->current_items->collection.destructor_data = container;
1048 container->margin = args.sub_margin;
1049 container->spacing = args.sub_spacing;
1050 container->columnspacing = args.sub_columnspacing;
1051 container->rowspacing = args.sub_rowspacing;
1052 container->remove_items = TRUE;
1053
1054 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_LIST);
1055 if(var) {
1056 UiList *list = var->value;
1057 list->obj = container;
1058 list->update = update_itemlist;
1059 update_itemlist(list, 0);
1060 }
1061 g_signal_connect(
1062 box,
1063 "destroy",
1064 G_CALLBACK(destroy_itemlist_container),
1065 container);
1066
1067 return box;
1068 }
949 1069
950 1070
951 1071
952 /* 1072 /*
953 * -------------------- Layout Functions -------------------- 1073 * -------------------- Layout Functions --------------------

mercurial