ui/gtk/container.c

changeset 101
7b3a3130be44
parent 100
d2bd73d28ff1
equal deleted inserted replaced
100:d2bd73d28ff1 101:7b3a3130be44
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 = NULL;
975 cxMapRemoveAndGet(ct->current_items, key, &item_obj);
976 if(item_obj) {
977 g_object_ref(G_OBJECT(item_obj->widget));
978 BOX_REMOVE(ct->widget, item_obj->widget);
979 cxMapPut(new_items, key, item_obj);
980 }
981 elm = list->next(list);
982 j++;
983 }
984
985 // ct->current_items only contains elements, that are not in the list
986 cxMapFree(ct->current_items); // calls destructor remove_item
987 ct->current_items = new_items;
988
989 // add all items
990 int index = 0;
991 elm = list->first(list);
992 while(elm) {
993 CxHashKey key = cx_hash_key(&elm, sizeof(void*));
994 UiObject *item_obj = cxMapGet(ct->current_items, key);
995 if(item_obj) {
996 // re-add previously created widget
997 ui_box_container_add(ct->container, item_obj->widget, FALSE);
998 } else {
999 // create new widget and object for this list element
1000 CxMempool *mp = cxBasicMempoolCreate(256);
1001 const CxAllocator *a = mp->allocator;
1002 UiObject *obj = cxCalloc(a, 1, sizeof(UiObject));
1003 obj->ctx = uic_context(obj, mp);
1004 obj->window = NULL;
1005 obj->widget = ui_subcontainer_create(
1006 ct->subcontainer,
1007 obj,
1008 ct->spacing,
1009 ct->columnspacing,
1010 ct->rowspacing,
1011 ct->margin);
1012 ui_box_container_add(ct->container, obj->widget, FALSE);
1013 if(ct->create_ui) {
1014 ct->create_ui(obj, index, elm, ct->userdata);
1015 }
1016 cxMapPut(new_items, key, obj);
1017 }
1018 elm = list->next(list);
1019 index++;
1020 }
1021 }
1022
1023 static void destroy_itemlist_container(GtkWidget *w, UiGtkItemListContainer *container) {
1024 container->remove_items = FALSE;
1025 cxMapFree(container->current_items);
1026 free(container);
1027 }
1028
1029 UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs args) {
1030 UiObject *current = uic_current_obj(obj);
1031 UiContainer *ct = current->container;
1032 UI_APPLY_LAYOUT1(current, args);
1033
1034 GtkWidget *box = args.container == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing);
1035 ui_set_name_and_style(box, args.name, args.style_class);
1036 GtkWidget *widget = args.margin > 0 ? ui_box_set_margin(box, args.margin) : box;
1037 ct->add(ct, widget, TRUE);
1038
1039 UiGtkItemListContainer *container = malloc(sizeof(UiGtkItemListContainer));
1040 container->parent = obj;
1041 container->widget = box;
1042 container->container = ui_box_container(current, box, args.container);
1043 container->create_ui = args.create_ui;
1044 container->userdata = args.userdata;
1045 container->subcontainer = args.subcontainer;
1046 container->current_items = cxHashMapCreateSimple(CX_STORE_POINTERS);
1047 container->current_items->collection.advanced_destructor = remove_item;
1048 container->current_items->collection.destructor_data = container;
1049 container->margin = args.sub_margin;
1050 container->spacing = args.sub_spacing;
1051 container->columnspacing = args.sub_columnspacing;
1052 container->rowspacing = args.sub_rowspacing;
1053 container->remove_items = TRUE;
1054
1055 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_LIST);
1056 if(var) {
1057 UiList *list = var->value;
1058 list->obj = container;
1059 list->update = update_itemlist;
1060 update_itemlist(list, 0);
1061 }
1062 g_signal_connect(
1063 box,
1064 "destroy",
1065 G_CALLBACK(destroy_itemlist_container),
1066 container);
1067
1068 return box;
1069 }
949 1070
950 1071
951 1072
952 /* 1073 /*
953 * -------------------- Layout Functions -------------------- 1074 * -------------------- Layout Functions --------------------

mercurial