| 100 ctx->document = document; |
101 ctx->document = document; |
| 101 |
102 |
| 102 UiContext *doc_ctx = ui_document_context(document); |
103 UiContext *doc_ctx = ui_document_context(document); |
| 103 doc_ctx->parent = ctx; |
104 doc_ctx->parent = ctx; |
| 104 |
105 |
| 105 // check if any parent context has an unbound variable with the same name |
106 // if a document variable has the same name as a parent variable, |
| 106 // as any document variable |
107 // move the bindings to the document |
| 107 UiContext *var_ctx = ctx; |
108 UiContext *var_ctx = ctx; |
| 108 while(var_ctx) { |
109 while(var_ctx) { |
| 109 if(var_ctx->vars_unbound && cxMapSize(var_ctx->vars_unbound) > 0) { |
110 CxMapIterator i = cxMapIterator(var_ctx->vars); |
| 110 CxMapIterator i = cxMapIterator(var_ctx->vars_unbound); |
111 cx_foreach(CxMapEntry*, entry, i) { |
| 111 cx_foreach(CxMapEntry*, entry, i) { |
112 printf("attach %.*s\n", (int)entry->key->len, entry->key->data); |
| 112 printf("attach %s\n", entry->key->data); |
113 UiVar *var = entry->value; |
| 113 UiVar *var = entry->value; |
114 UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key); |
| 114 UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key); |
115 if(docvar) { |
| 115 if(docvar) { |
116 // bind var to document var |
| 116 // bind var to document var |
117 uic_copy_binding(var, docvar, TRUE); |
| 117 uic_copy_binding(var, docvar, TRUE); |
118 cxIteratorFlagRemoval(i); |
| 118 cxIteratorFlagRemoval(i); |
|
| 119 } |
|
| 120 } |
119 } |
| 121 } |
120 } |
| 122 |
121 |
| 123 var_ctx = var_ctx->parent; |
122 var_ctx = var_ctx->parent; |
| 124 } |
123 } |
| 127 static void uic_context_unbind_vars(UiContext *ctx) { |
126 static void uic_context_unbind_vars(UiContext *ctx) { |
| 128 CxMapIterator mi = cxMapIterator(ctx->vars); |
127 CxMapIterator mi = cxMapIterator(ctx->vars); |
| 129 cx_foreach(CxMapEntry*, entry, mi) { |
128 cx_foreach(CxMapEntry*, entry, mi) { |
| 130 UiVar *var = entry->value; |
129 UiVar *var = entry->value; |
| 131 // var->from && var->from_ctx && var->from_ctx != ctx |
130 // var->from && var->from_ctx && var->from_ctx != ctx |
| |
131 uic_save_var(var); |
| 132 if(var->from) { |
132 if(var->from) { |
| 133 uic_save_var2(var); |
|
| 134 uic_copy_binding(var, var->from, FALSE); |
133 uic_copy_binding(var, var->from, FALSE); |
| 135 cxMapPut(var->from->from_ctx->vars_unbound, *entry->key, var->from); |
134 cxMapPut(var->from->from_ctx->vars, *entry->key, var->from); |
| 136 var->from = NULL; |
135 var->from = NULL; |
| 137 } |
136 } |
| 138 } |
137 } |
| 139 |
138 |
| 140 if(ctx->documents) { |
139 if(ctx->documents) { |
| 197 CxHashKey key = cx_hash_key(name, strlen(name)); |
196 CxHashKey key = cx_hash_key(name, strlen(name)); |
| 198 return ctx_getvar(ctx, key); |
197 return ctx_getvar(ctx, key); |
| 199 } |
198 } |
| 200 |
199 |
| 201 UiVar* uic_create_var(UiContext *ctx, const char *name, UiVarType type) { |
200 UiVar* uic_create_var(UiContext *ctx, const char *name, UiVarType type) { |
| 202 if(ctx->vars_unbound) { |
|
| 203 UiVar *unbound = cxMapGet(ctx->vars_unbound, name); |
|
| 204 if(unbound) { |
|
| 205 return unbound; |
|
| 206 } |
|
| 207 } |
|
| 208 |
|
| 209 UiVar *var = uic_get_var(ctx, name); |
201 UiVar *var = uic_get_var(ctx, name); |
| 210 if(var) { |
202 if(var) { |
| 211 if(var->type == type) { |
203 if(var->type == type) { |
| 212 return var; |
204 return var; |
| 213 } else { |
205 } else { |
| 222 var->from = NULL; |
214 var->from = NULL; |
| 223 var->from_ctx = ctx; |
215 var->from_ctx = ctx; |
| 224 |
216 |
| 225 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var); |
217 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var); |
| 226 |
218 |
| 227 if(!ctx->vars_unbound) { |
219 cxMapPut(ctx->vars, name, var); |
| 228 ctx->vars_unbound = cxHashMapCreate(ctx->allocator, CX_STORE_POINTERS, 16); |
|
| 229 } |
|
| 230 cxMapPut(ctx->vars_unbound, name, var); |
|
| 231 |
220 |
| 232 return var; |
221 return var; |
| 233 } |
222 } |
| 234 |
223 |
| 235 UiVar* uic_create_value_var(UiContext* ctx, void* value) { |
224 UiVar* uic_create_value_var(UiContext* ctx, void* value) { |
| 276 } |
265 } |
| 277 return val; |
266 return val; |
| 278 } |
267 } |
| 279 |
268 |
| 280 |
269 |
| 281 UiVar* uic_widget_var(UiContext* toplevel, UiContext* current, void* value, const char* varname, UiVarType type) { |
270 UiVar* uic_widget_var(UiContext *toplevel, UiContext *current, void *value, const char *varname, UiVarType type) { |
| 282 if (value) { |
271 if (value) { |
| 283 return uic_create_value_var(current, value); |
272 return uic_create_value_var(current, value); |
| 284 } |
273 } |
| 285 if (varname) { |
274 if (varname) { |
| 286 return uic_create_var(toplevel, varname, type); |
275 return uic_create_var(toplevel, varname, type); |
| 381 } |
370 } |
| 382 |
371 |
| 383 ui_setop_enable(FALSE); |
372 ui_setop_enable(FALSE); |
| 384 } |
373 } |
| 385 |
374 |
| 386 void uic_save_var2(UiVar *var) { |
375 void uic_save_var(UiVar *var) { |
| 387 switch(var->type) { |
376 switch(var->type) { |
| 388 case UI_VAR_SPECIAL: break; |
377 case UI_VAR_SPECIAL: break; |
| 389 case UI_VAR_INTEGER: uic_int_save(var->value); break; |
378 case UI_VAR_INTEGER: uic_int_save(var->value); break; |
| 390 case UI_VAR_DOUBLE: uic_double_save(var->value); break; |
379 case UI_VAR_DOUBLE: uic_double_save(var->value); break; |
| 391 case UI_VAR_STRING: uic_string_save(var->value); break; |
380 case UI_VAR_STRING: uic_string_save(var->value); break; |
| 540 gw->enable(gw->widget, enable); |
529 gw->enable(gw->widget, enable); |
| 541 } |
530 } |
| 542 } |
531 } |
| 543 |
532 |
| 544 void ui_widget_set_groups(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...) { |
533 void ui_widget_set_groups(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...) { |
| |
534 if(enable == NULL) { |
| |
535 enable = (ui_enablefunc)ui_set_enabled; |
| |
536 } |
| 545 // get groups |
537 // get groups |
| 546 CxList *groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16); |
538 CxList *groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16); |
| 547 va_list ap; |
539 va_list ap; |
| 548 va_start(ap, enable); |
540 va_start(ap, enable); |
| 549 int group; |
541 int group; |
| 555 uic_add_group_widget(ctx, widget, enable, groups); |
547 uic_add_group_widget(ctx, widget, enable, groups); |
| 556 |
548 |
| 557 cxListFree(groups); |
549 cxListFree(groups); |
| 558 } |
550 } |
| 559 |
551 |
| |
552 void ui_widget_set_groups2(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, int *groups, int ngroups) { |
| |
553 if(enable == NULL) { |
| |
554 enable = (ui_enablefunc)ui_set_enabled; |
| |
555 } |
| |
556 CxList *ls = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), ngroups); |
| |
557 for(int i=0;i<ngroups;i++) { |
| |
558 cxListAdd(ls, groups+i); |
| |
559 } |
| |
560 uic_add_group_widget(ctx, widget, enable, ls); |
| |
561 cxListFree(ls); |
| |
562 } |
| |
563 |
| |
564 void ui_widget_set_visibility_states(UiContext *ctx, UIWIDGET widget, int *states, int nstates) { |
| |
565 ui_widget_set_groups2(ctx, widget, (ui_enablefunc)ui_set_visible, states, nstates); |
| |
566 } |
| |
567 |
| 560 size_t uic_group_array_size(const int *groups) { |
568 size_t uic_group_array_size(const int *groups) { |
| 561 int i; |
569 int i; |
| 562 for(i=0;groups[i] >= 0;i++) { } |
570 for(i=0;groups[i] >= 0;i++) { } |
| 563 return i; |
571 return i; |
| 564 } |
572 } |