ui/common/context.c

changeset 431
bb7da585debc
parent 420
28a5920bebe0
child 440
7c4b9cba09ca
equal deleted inserted replaced
169:fe49cff3c571 431:bb7da585debc
30 #include <stdlib.h> 30 #include <stdlib.h>
31 #include <string.h> 31 #include <string.h>
32 #include <inttypes.h> 32 #include <inttypes.h>
33 #include <stdarg.h> 33 #include <stdarg.h>
34 34
35 #include <cx/array_list.h>
36 #include <cx/compare.h>
37 #include <cx/mempool.h>
38
35 #include "context.h" 39 #include "context.h"
36 #include "../ui/window.h" 40 #include "../ui/window.h"
37 #include "document.h" 41 #include "document.h"
38 #include "types.h" 42 #include "types.h"
39 43
44
40 static UiContext* global_context; 45 static UiContext* global_context;
41 46
42 void uic_init_global_context(void) { 47 void uic_init_global_context(void) {
43 UcxMempool *mp = ucx_mempool_new(32); 48 CxMempool *mp = cxBasicMempoolCreate(32);
44 global_context = uic_context(NULL, mp); 49 global_context = uic_context(NULL, mp);
45 } 50 }
46 51
47 UiContext* ui_global_context(void) { 52 UiContext* ui_global_context(void) {
48 return global_context; 53 return global_context;
49 } 54 }
50 55
51 UiContext* uic_context(UiObject *toplevel, UcxMempool *mp) { 56 UiContext* uic_context(UiObject *toplevel, CxMempool *mp) {
52 UiContext *ctx = ucx_mempool_malloc(mp, sizeof(UiContext)); 57 UiContext *ctx = cxMalloc(mp->allocator, sizeof(UiContext));
53 memset(ctx, 0, sizeof(UiContext)); 58 memset(ctx, 0, sizeof(UiContext));
54 ctx->mempool = mp; 59 ctx->mp = mp;
60 ctx->allocator = mp->allocator;
55 ctx->obj = toplevel; 61 ctx->obj = toplevel;
56 ctx->vars = ucx_map_new_a(mp->allocator, 16); 62 ctx->vars = cxHashMapCreate(mp->allocator, CX_STORE_POINTERS, 16);
63
64 ctx->documents = cxLinkedListCreate(mp->allocator, cx_cmp_intptr, CX_STORE_POINTERS);
65 ctx->group_widgets = cxLinkedListCreate(mp->allocator, cx_cmp_ptr, sizeof(UiGroupWidget));
66 ctx->groups = cxArrayListCreate(mp->allocator, cx_cmp_int, sizeof(int), 32);
57 67
58 ctx->attach_document = uic_context_attach_document; 68 ctx->attach_document = uic_context_attach_document;
59 ctx->detach_document2 = uic_context_detach_document2; 69 ctx->detach_document2 = uic_context_detach_document2;
60 70
61 #ifdef UI_GTK 71 #if UI_GTK2 || UI_GTK3
62 if(toplevel && toplevel->widget) { 72 if(toplevel && toplevel->widget) {
63 ctx->accel_group = gtk_accel_group_new(); 73 ctx->accel_group = gtk_accel_group_new();
64 gtk_window_add_accel_group(GTK_WINDOW(toplevel->widget), ctx->accel_group); 74 gtk_window_add_accel_group(GTK_WINDOW(toplevel->widget), ctx->accel_group);
65 } 75 }
66 #endif 76 #endif
70 80
71 UiContext* uic_root_context(UiContext *ctx) { 81 UiContext* uic_root_context(UiContext *ctx) {
72 return ctx->parent ? uic_root_context(ctx->parent) : ctx; 82 return ctx->parent ? uic_root_context(ctx->parent) : ctx;
73 } 83 }
74 84
85 void uic_context_prepare_close(UiContext *ctx) {
86 cxListClear(ctx->groups);
87 cxListClear(ctx->group_widgets);
88 }
89
75 void uic_context_attach_document(UiContext *ctx, void *document) { 90 void uic_context_attach_document(UiContext *ctx, void *document) {
76 ctx->documents = ucx_list_append_a(ctx->mempool->allocator, ctx->documents, document); 91 cxListAdd(ctx->documents, document);
77 ctx->document = ctx->documents->data; 92 ctx->document = document;
78 93
79 UiContext *doc_ctx = ui_document_context(document); 94 UiContext *doc_ctx = ui_document_context(document);
80 95
81 // check if any parent context has an unbound variable with the same name 96 // check if any parent context has an unbound variable with the same name
82 // as any document variable 97 // as any document variable
83 UiContext *var_ctx = ctx; 98 UiContext *var_ctx = ctx;
84 while(var_ctx) { 99 while(var_ctx) {
85 if(var_ctx->vars_unbound && var_ctx->vars_unbound->count > 0) { 100 if(var_ctx->vars_unbound && cxMapSize(var_ctx->vars_unbound) > 0) {
86 UcxMapIterator i = ucx_map_iterator(var_ctx->vars_unbound); 101 CxIterator i = cxMapIterator(var_ctx->vars_unbound);
87 UiVar *var; 102 cx_foreach(CxMapEntry*, entry, i) {
88 // rmkeys holds all keys, that shall be removed from vars_unbound 103 printf("attach %s\n", entry->key->data);
89 UcxKey *rmkeys = calloc(var_ctx->vars_unbound->count, sizeof(UcxKey)); 104 UiVar *var = entry->value;
90 size_t numkeys = 0; 105 UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key);
91 UCX_MAP_FOREACH(key, var, i) {
92 UiVar *docvar = ucx_map_get(doc_ctx->vars, key);
93 if(docvar) { 106 if(docvar) {
94 // bind var to document var 107 // bind var to document var
95 uic_copy_binding(var, docvar, TRUE); 108 uic_copy_binding(var, docvar, TRUE);
96 rmkeys[numkeys++] = key; // save the key for removal 109 cxIteratorFlagRemoval(i);
97 } 110 }
98 } 111 }
99 // now that we may have bound some vars to the document,
100 // we can remove them from the unbound map
101 for(size_t k=0;k<numkeys;k++) {
102 ucx_map_remove(var_ctx->vars_unbound, rmkeys[k]);
103 }
104 } 112 }
105 113
106 var_ctx = ctx->parent; 114 var_ctx = ctx->parent;
107 } 115 }
108 } 116 }
109 117
110 static void uic_context_unbind_vars(UiContext *ctx) { 118 static void uic_context_unbind_vars(UiContext *ctx) {
111 UcxMapIterator i = ucx_map_iterator(ctx->vars); 119 CxIterator i = cxMapIterator(ctx->vars);
112 UiVar *var; 120 cx_foreach(CxMapEntry*, entry, i) {
113 UCX_MAP_FOREACH(key, var, i) { 121 UiVar *var = entry->value;
114 if(var->from && var->from_ctx) { 122 if(var->from && var->from_ctx) {
115 uic_save_var2(var); 123 uic_save_var2(var);
116 uic_copy_binding(var, var->from, FALSE); 124 uic_copy_binding(var, var->from, FALSE);
117 ucx_map_put(var->from_ctx->vars_unbound, key, var->from); 125 cxMapPut(var->from_ctx->vars_unbound, *entry->key, var->from);
118 var->from_ctx = ctx; 126 var->from_ctx = ctx;
119 } 127 }
120 } 128 }
121 129
122 UCX_FOREACH(elm, ctx->documents) { 130 if(ctx->documents) {
123 UiContext *subctx = ui_document_context(elm->data); 131 i = cxListIterator(ctx->documents);
124 uic_context_unbind_vars(subctx); 132 cx_foreach(void *, doc, i) {
133 UiContext *subctx = ui_document_context(doc);
134 uic_context_unbind_vars(subctx);
135 }
125 } 136 }
126 } 137 }
127 138
128 void uic_context_detach_document2(UiContext *ctx, void *document) { 139 void uic_context_detach_document2(UiContext *ctx, void *document) {
129 // find the document in the documents list 140 // find the document in the documents list
130 UcxList *doc = NULL; 141 ssize_t docIndex = cxListFind(ctx->documents, document);
131 UCX_FOREACH(elm, ctx->documents) { 142 if(docIndex < 0) {
132 if(elm->data == document) { 143 return;
133 doc = elm; 144 }
134 break; 145
135 } 146 cxListRemove(ctx->documents, docIndex);
136 } 147 ctx->document = cxListAt(ctx->documents, 0);
137 if(!doc) {
138 return; // document is not a subdocument of this context
139 }
140
141 ctx->documents = ucx_list_remove_a(ctx->mempool->allocator, ctx->documents, doc);
142 ctx->document = ctx->documents ? ctx->documents->data : NULL;
143 148
144 UiContext *docctx = ui_document_context(document); 149 UiContext *docctx = ui_document_context(document);
145 uic_context_unbind_vars(docctx); // unbind all doc/subdoc vars from the parent 150 uic_context_unbind_vars(docctx); // unbind all doc/subdoc vars from the parent
146 } 151 }
147 152
148 void uic_context_detach_all(UiContext *ctx) { 153 void uic_context_detach_all(UiContext *ctx) {
149 UcxList *ls = ucx_list_clone(ctx->documents, NULL, NULL); 154 // copy list
150 UCX_FOREACH(elm, ls) { 155 CxList *ls = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS);
151 ctx->detach_document2(ctx, elm->data); 156 CxIterator i = cxListIterator(ctx->documents);
152 } 157 cx_foreach(void *, doc, i) {
153 ucx_list_free(ls); 158 cxListAdd(ls, doc);
154 } 159 }
155 160
156 static UiVar* ctx_getvar(UiContext *ctx, UcxKey key) { 161 // detach documents
157 UiVar *var = ucx_map_get(ctx->vars, key); 162 i = cxListIterator(ls);
158 if(!var) { 163 cx_foreach(void *, doc, i) {
159 UCX_FOREACH(elm, ctx->documents) { 164 ctx->detach_document2(ctx, doc);
160 UiContext *subctx = ui_document_context(elm->data); 165 }
166
167 cxListDestroy(ls);
168 }
169
170 static UiVar* ctx_getvar(UiContext *ctx, CxHashKey key) {
171 UiVar *var = cxMapGet(ctx->vars, key);
172 if(!var && ctx->documents) {
173 CxIterator i = cxListIterator(ctx->documents);
174 cx_foreach(void *, doc, i) {
175 UiContext *subctx = ui_document_context(doc);
161 var = ctx_getvar(subctx, key); 176 var = ctx_getvar(subctx, key);
162 if(var) { 177 if(var) {
163 break; 178 break;
164 } 179 }
165 } 180 }
166 } 181 }
167 return var; 182 return var;
168 } 183 }
169 184
170 UiVar* uic_get_var(UiContext *ctx, const char *name) { 185 UiVar* uic_get_var(UiContext *ctx, const char *name) {
171 UcxKey key = ucx_key(name, strlen(name)); 186 CxHashKey key = cx_hash_key(name, strlen(name));
172 return ctx_getvar(ctx, key); 187 return ctx_getvar(ctx, key);
173 } 188 }
174 189
175 UiVar* uic_create_var(UiContext *ctx, const char *name, UiVarType type) { 190 UiVar* uic_create_var(UiContext *ctx, const char *name, UiVarType type) {
191 if(ctx->vars_unbound) {
192 UiVar *unbound = cxMapGet(ctx->vars_unbound, name);
193 if(unbound) {
194 return unbound;
195 }
196 }
197
176 UiVar *var = uic_get_var(ctx, name); 198 UiVar *var = uic_get_var(ctx, name);
177 if(var) { 199 if(var) {
178 if(var->type == type) { 200 if(var->type == type) {
179 return var; 201 return var;
180 } else { 202 } else {
186 var->type = type; 208 var->type = type;
187 var->value = uic_create_value(ctx, type); 209 var->value = uic_create_value(ctx, type);
188 var->from = NULL; 210 var->from = NULL;
189 var->from_ctx = ctx; 211 var->from_ctx = ctx;
190 212
213 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var);
214
191 if(!ctx->vars_unbound) { 215 if(!ctx->vars_unbound) {
192 ctx->vars_unbound = ucx_map_new_a(ctx->mempool->allocator, 16); 216 ctx->vars_unbound = cxHashMapCreate(ctx->allocator, CX_STORE_POINTERS, 16);
193 } 217 }
194 ucx_map_cstr_put(ctx->vars_unbound, name, var); 218 cxMapPut(ctx->vars_unbound, name, var);
195 219
220 return var;
221 }
222
223 UiVar* uic_create_value_var(UiContext* ctx, void* value) {
224 UiVar *var = (UiVar*)ui_malloc(ctx, sizeof(UiVar));
225 var->from = NULL;
226 var->from_ctx = ctx;
227 var->value = value;
228 var->type = UI_VAR_SPECIAL;
196 return var; 229 return var;
197 } 230 }
198 231
199 void* uic_create_value(UiContext *ctx, UiVarType type) { 232 void* uic_create_value(UiContext *ctx, UiVarType type) {
200 void *val = NULL; 233 void *val = NULL;
222 } 255 }
223 case UI_VAR_RANGE: { 256 case UI_VAR_RANGE: {
224 val = ui_range_new(ctx, NULL); 257 val = ui_range_new(ctx, NULL);
225 break; 258 break;
226 } 259 }
260 case UI_VAR_GENERIC: {
261 val = ui_generic_new(ctx, NULL);
262 }
227 } 263 }
228 return val; 264 return val;
229 } 265 }
266
267
268 UiVar* uic_widget_var(UiContext* toplevel, UiContext* current, void* value, const char* varname, UiVarType type) {
269 if (value) {
270 return uic_create_value_var(current, value);
271 }
272 if (varname) {
273 return uic_create_var(toplevel, varname, type);
274 }
275 return NULL;
276 }
277
230 278
231 void uic_copy_binding(UiVar *from, UiVar *to, UiBool copytodoc) { 279 void uic_copy_binding(UiVar *from, UiVar *to, UiBool copytodoc) {
232 // check type 280 // check type
233 if(from->type != to->type) { 281 if(from->type != to->type) {
234 fprintf(stderr, "UI Error: var has incompatible type.\n"); 282 fprintf(stderr, "UI Error: var has incompatible type.\n");
281 t->set(t, tvalue); 329 t->set(t, tvalue);
282 t->setposition(t, t->pos); 330 t->setposition(t, t->pos);
283 break; 331 break;
284 } 332 }
285 case UI_VAR_LIST: { 333 case UI_VAR_LIST: {
286 UiList *f = fromvalue; 334 // TODO: not sure how correct this is
335
336 UiList *f = from->value;
287 UiList *t = to->value; 337 UiList *t = to->value;
288 if(!f->obj) break; 338 if (f->obj) {
289 uic_list_copy(f, t); 339 t->obj = f->obj;
290 t->update(t, -1); 340 t->update = f->update;
341 t->getselection = f->getselection;
342 t->setselection = f->setselection;
343 }
344
345 UiVar tmp = *from;
346 *from = *to;
347 *to = tmp;
348
349 UiList* t2 = to->value;
350 ui_notify(t2->observers, NULL);
351
291 break; 352 break;
292 } 353 }
293 case UI_VAR_RANGE: { 354 case UI_VAR_RANGE: {
294 UiRange *f = fromvalue; 355 UiRange *f = fromvalue;
295 UiRange *t = to->value; 356 UiRange *t = to->value;
296 if(!f->obj) break; 357 if(!f->obj) break;
297 uic_range_copy(f, t); 358 uic_range_copy(f, t);
298 t->setextent(t, t->extent); 359 t->setextent(t, t->extent);
299 t->setrange(t, t->min, t->max); 360 t->setrange(t, t->min, t->max);
300 t->set(t, t->value); 361 t->set(t, t->value);
362 break;
363 }
364 case UI_VAR_GENERIC: {
365 UiGeneric *f = fromvalue;
366 UiGeneric *t = to->value;
367 if(!f->obj) break;
368 uic_generic_copy(f, t);
369 t->set(t, t->value, t->type);
301 break; 370 break;
302 } 371 }
303 } 372 }
304 } 373 }
305 374
310 case UI_VAR_DOUBLE: uic_double_save(var->value); break; 379 case UI_VAR_DOUBLE: uic_double_save(var->value); break;
311 case UI_VAR_STRING: uic_string_save(var->value); break; 380 case UI_VAR_STRING: uic_string_save(var->value); break;
312 case UI_VAR_TEXT: uic_text_save(var->value); break; 381 case UI_VAR_TEXT: uic_text_save(var->value); break;
313 case UI_VAR_LIST: break; 382 case UI_VAR_LIST: break;
314 case UI_VAR_RANGE: uic_range_save(var->value); break; 383 case UI_VAR_RANGE: uic_range_save(var->value); break;
384 case UI_VAR_GENERIC: uic_generic_save(var->value); break;
315 } 385 }
316 } 386 }
317 387
318 void uic_unbind_var(UiVar *var) { 388 void uic_unbind_var(UiVar *var) {
319 switch(var->type) { 389 switch(var->type) {
322 case UI_VAR_DOUBLE: uic_double_unbind(var->value); break; 392 case UI_VAR_DOUBLE: uic_double_unbind(var->value); break;
323 case UI_VAR_STRING: uic_string_unbind(var->value); break; 393 case UI_VAR_STRING: uic_string_unbind(var->value); break;
324 case UI_VAR_TEXT: uic_text_unbind(var->value); break; 394 case UI_VAR_TEXT: uic_text_unbind(var->value); break;
325 case UI_VAR_LIST: uic_list_unbind(var->value); break; 395 case UI_VAR_LIST: uic_list_unbind(var->value); break;
326 case UI_VAR_RANGE: uic_range_unbind(var->value); break; 396 case UI_VAR_RANGE: uic_range_unbind(var->value); break;
397 case UI_VAR_GENERIC: uic_generic_unbind(var->value); break;
327 } 398 }
328 } 399 }
329 400
330 void uic_reg_var(UiContext *ctx, char *name, UiVarType type, void *value) { 401 void uic_reg_var(UiContext *ctx, char *name, UiVarType type, void *value) {
331 // TODO: do we need/want this? Why adding vars to a context after 402 // TODO: do we need/want this? Why adding vars to a context after
356 UiVar *var = ui_malloc(ctx, sizeof(UiVar)); 427 UiVar *var = ui_malloc(ctx, sizeof(UiVar));
357 var->type = type; 428 var->type = type;
358 var->value = value; 429 var->value = value;
359 var->from = NULL; 430 var->from = NULL;
360 var->from_ctx = ctx; 431 var->from_ctx = ctx;
361 size_t oldcount = ctx->vars->count; 432 size_t oldcount = cxMapSize(ctx->vars);
362 ucx_map_cstr_put(ctx->vars, name, var); 433 cxMapPut(ctx->vars, name, var);
363 if(ctx->vars->count != oldcount + 1) { 434 if(cxMapSize(ctx->vars) != oldcount + 1) {
364 fprintf(stderr, "UiError: var '%s' already exists\n", name); 435 fprintf(stderr, "UiError: var '%s' already exists\n", name);
365 } 436 }
366 437
367 // TODO: remove? 438 // TODO: remove?
368 // a widget is already bound to a var with this name 439 // a widget is already bound to a var with this name
373 } 444 }
374 */ 445 */
375 } 446 }
376 447
377 void uic_remove_bound_var(UiContext *ctx, UiVar *var) { 448 void uic_remove_bound_var(UiContext *ctx, UiVar *var) {
378 // TODO: implement 449 // TODO
379 printf("TODO: implement uic_remove_bound_var\n");
380 } 450 }
381 451
382 452
383 // public API 453 // public API
384 454
393 void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) { 463 void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) {
394 ctx->close_callback = fnc; 464 ctx->close_callback = fnc;
395 ctx->close_data = udata; 465 ctx->close_data = udata;
396 } 466 }
397 467
468 UIEXPORT void ui_context_destroy(UiContext *ctx) {
469 cxMempoolDestroy(ctx->mp);
470 }
471
398 472
399 void ui_set_group(UiContext *ctx, int group) { 473 void ui_set_group(UiContext *ctx, int group) {
400 if(ucx_list_find(ctx->groups, (void*)(intptr_t)group, NULL, NULL) == -1) { 474 if(cxListFind(ctx->groups, &group) == -1) {
401 ctx->groups = ucx_list_append_a(ctx->mempool->allocator, ctx->groups, (void*)(intptr_t)group); 475 cxListAdd(ctx->groups, &group);
402 } 476 }
403 477
404 // enable/disable group widgets 478 // enable/disable group widgets
405 uic_check_group_widgets(ctx); 479 uic_check_group_widgets(ctx);
406 } 480 }
407 481
408 void ui_unset_group(UiContext *ctx, int group) { 482 void ui_unset_group(UiContext *ctx, int group) {
409 int i = ucx_list_find(ctx->groups, (void*)(intptr_t)group, NULL, NULL); 483 int i = cxListFind(ctx->groups, &group);
410 if(i != -1) { 484 if(i != -1) {
411 UcxList *elm = ucx_list_get(ctx->groups, i); 485 cxListRemove(ctx->groups, i);
412 ctx->groups = ucx_list_remove_a(ctx->mempool->allocator, ctx->groups, elm);
413 } 486 }
414 487
415 // enable/disable group widgets 488 // enable/disable group widgets
416 uic_check_group_widgets(ctx); 489 uic_check_group_widgets(ctx);
417 } 490 }
418 491
419 int* ui_active_groups(UiContext *ctx, int *ngroups) { 492 int* ui_active_groups(UiContext *ctx, int *ngroups) {
420 if(!ctx->groups) { 493 *ngroups = cxListSize(ctx->groups);
421 return NULL; 494 return cxListAt(ctx->groups, 0);
422 }
423
424 int nelm = ucx_list_size(ctx->groups);
425 int *groups = calloc(sizeof(int), nelm);
426
427 int i = 0;
428 UCX_FOREACH(elm, ctx->groups) {
429 groups[i++] = (intptr_t)elm->data;
430 }
431
432 *ngroups = nelm;
433 return groups;
434 } 495 }
435 496
436 void uic_check_group_widgets(UiContext *ctx) { 497 void uic_check_group_widgets(UiContext *ctx) {
437 int ngroups = 0; 498 int ngroups = 0;
438 int *groups = ui_active_groups(ctx, &ngroups); 499 int *groups = ui_active_groups(ctx, &ngroups);
439 500
440 UCX_FOREACH(elm, ctx->group_widgets) { 501 CxIterator i = cxListIterator(ctx->group_widgets);
441 UiGroupWidget *gw = elm->data; 502 cx_foreach(UiGroupWidget *, gw, i) {
442 char *check = calloc(1, gw->numgroups); 503 char *check = calloc(1, gw->numgroups);
443 504
444 for(int i=0;i<ngroups;i++) { 505 for(int i=0;i<ngroups;i++) {
445 for(int k=0;k<gw->numgroups;k++) { 506 for(int k=0;k<gw->numgroups;k++) {
446 if(groups[i] == gw->groups[k]) { 507 if(groups[i] == gw->groups[k]) {
454 if(check[i] == 0) { 515 if(check[i] == 0) {
455 enable = 0; 516 enable = 0;
456 break; 517 break;
457 } 518 }
458 } 519 }
520 free(check);
459 gw->enable(gw->widget, enable); 521 gw->enable(gw->widget, enable);
460 }
461
462 if(groups) {
463 free(groups);
464 } 522 }
465 } 523 }
466 524
467 void ui_widget_set_groups(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...) { 525 void ui_widget_set_groups(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...) {
468 // get groups 526 // get groups
469 UcxList *groups = NULL; 527 CxList *groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16);
470 va_list ap; 528 va_list ap;
471 va_start(ap, enable); 529 va_start(ap, enable);
472 int group; 530 int group;
473 while((group = va_arg(ap, int)) != -1) { 531 while((group = va_arg(ap, int)) != -1) {
474 groups = ucx_list_append(groups, (void*)(intptr_t)group); 532 cxListAdd(groups, &group);
475 } 533 }
476 va_end(ap); 534 va_end(ap);
477 535
478 uic_add_group_widget(ctx, widget, enable, groups); 536 uic_add_group_widget(ctx, widget, enable, groups);
479 537
480 ucx_list_free(groups); 538 cxListDestroy(groups);
481 } 539 }
482 540
483 void uic_add_group_widget(UiContext *ctx, void *widget, ui_enablefunc enable, UcxList *groups) { 541 size_t uic_group_array_size(const int *groups) {
484 UcxMempool *mp = ctx->mempool; 542 int i;
485 UiGroupWidget *gw = ucx_mempool_malloc(mp, sizeof(UiGroupWidget)); 543 for(i=0;groups[i] >= 0;i++) { }
486 544 return i;
487 gw->widget = widget; 545 }
488 gw->enable = enable; 546
489 gw->numgroups = ucx_list_size(groups); 547 void uic_add_group_widget(UiContext *ctx, void *widget, ui_enablefunc enable, CxList *groups) {
490 gw->groups = ucx_mempool_calloc(mp, gw->numgroups, sizeof(int)); 548 uic_add_group_widget_i(ctx, widget, enable, cxListAt(groups, 0), cxListSize(groups));
491 int i = 0; 549 }
492 UCX_FOREACH(elm, groups) { 550
493 gw->groups[i++] = (intptr_t)elm->data; 551 void uic_add_group_widget_i(UiContext *ctx, void *widget, ui_enablefunc enable, const int *groups, size_t numgroups) {
494 } 552 const CxAllocator *a = ctx->allocator;
495 553 UiGroupWidget gw;
496 ctx->group_widgets = ucx_list_append_a( 554
497 mp->allocator, 555 gw.widget = widget;
498 ctx->group_widgets, 556 gw.enable = enable;
499 gw); 557 gw.numgroups = numgroups;
558 gw.groups = cxCalloc(a, numgroups, sizeof(int));
559
560 // copy groups
561 if(groups) {
562 memcpy(gw.groups, groups, gw.numgroups * sizeof(int));
563 }
564
565 cxListAdd(ctx->group_widgets, &gw);
566 }
567
568 void uic_remove_group_widget(UiContext *ctx, void *widget) {
569 (void)cxListFindRemove(ctx->group_widgets, widget);
570 }
571
572 UIEXPORT void *ui_allocator(UiContext *ctx) {
573 return (void*)ctx->allocator;
574 }
575
576 void* ui_cx_mempool(UiContext *ctx) {
577 return ctx->mp;
500 } 578 }
501 579
502 void* ui_malloc(UiContext *ctx, size_t size) { 580 void* ui_malloc(UiContext *ctx, size_t size) {
503 return ctx ? ucx_mempool_malloc(ctx->mempool, size) : NULL; 581 return ctx ? cxMalloc(ctx->allocator, size) : NULL;
504 } 582 }
505 583
506 void* ui_calloc(UiContext *ctx, size_t nelem, size_t elsize) { 584 void* ui_calloc(UiContext *ctx, size_t nelem, size_t elsize) {
507 return ctx ? ucx_mempool_calloc(ctx->mempool, nelem, elsize) : NULL; 585 return ctx ? cxCalloc(ctx->allocator, nelem, elsize) : NULL;
508 } 586 }
509 587
510 void ui_free(UiContext *ctx, void *ptr) { 588 void ui_free(UiContext *ctx, void *ptr) {
511 if(ctx) { 589 if(ctx && ptr) {
512 ucx_mempool_free(ctx->mempool, ptr); 590 cxFree(ctx->allocator, ptr);
513 } 591 }
514 } 592 }
515 593
516 void* ui_realloc(UiContext *ctx, void *ptr, size_t size) { 594 void* ui_realloc(UiContext *ctx, void *ptr, size_t size) {
517 return ctx ? ucx_mempool_realloc(ctx->mempool, ptr, size) : NULL; 595 return ctx ? cxRealloc(ctx->allocator, ptr, size) : NULL;
518 } 596 }
519 597
598 UIEXPORT char* ui_strdup(UiContext *ctx, const char *str) {
599 if(!ctx) {
600 return NULL;
601 }
602 cxstring s = cx_str(str);
603 cxmutstr d = cx_strdup_a(ctx->allocator, s);
604 return d.ptr;
605 }

mercurial