| 101 ctx->document = document; |
101 ctx->document = document; |
| 102 |
102 |
| 103 UiContext *doc_ctx = ui_document_context(document); |
103 UiContext *doc_ctx = ui_document_context(document); |
| 104 doc_ctx->parent = ctx; |
104 doc_ctx->parent = ctx; |
| 105 |
105 |
| 106 // 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, |
| 107 // as any document variable |
107 // move the bindings to the document |
| 108 UiContext *var_ctx = ctx; |
108 UiContext *var_ctx = ctx; |
| 109 while(var_ctx) { |
109 while(var_ctx) { |
| 110 if(var_ctx->vars_unbound && cxMapSize(var_ctx->vars_unbound) > 0) { |
110 CxMapIterator i = cxMapIterator(var_ctx->vars); |
| 111 CxMapIterator i = cxMapIterator(var_ctx->vars_unbound); |
111 cx_foreach(CxMapEntry*, entry, i) { |
| 112 cx_foreach(CxMapEntry*, entry, i) { |
112 printf("attach %.*s\n", (int)entry->key->len, entry->key->data); |
| 113 printf("attach %s\n", entry->key->data); |
113 UiVar *var = entry->value; |
| 114 UiVar *var = entry->value; |
114 UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key); |
| 115 UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key); |
115 if(docvar) { |
| 116 if(docvar) { |
116 // bind var to document var |
| 117 // bind var to document var |
117 uic_copy_binding(var, docvar, TRUE); |
| 118 uic_copy_binding(var, docvar, TRUE); |
118 cxIteratorFlagRemoval(i); |
| 119 cxIteratorFlagRemoval(i); |
|
| 120 } |
|
| 121 } |
119 } |
| 122 } |
120 } |
| 123 |
121 |
| 124 var_ctx = var_ctx->parent; |
122 var_ctx = var_ctx->parent; |
| 125 } |
123 } |
| 128 static void uic_context_unbind_vars(UiContext *ctx) { |
126 static void uic_context_unbind_vars(UiContext *ctx) { |
| 129 CxMapIterator mi = cxMapIterator(ctx->vars); |
127 CxMapIterator mi = cxMapIterator(ctx->vars); |
| 130 cx_foreach(CxMapEntry*, entry, mi) { |
128 cx_foreach(CxMapEntry*, entry, mi) { |
| 131 UiVar *var = entry->value; |
129 UiVar *var = entry->value; |
| 132 // var->from && var->from_ctx && var->from_ctx != ctx |
130 // var->from && var->from_ctx && var->from_ctx != ctx |
| |
131 uic_save_var(var); |
| 133 if(var->from) { |
132 if(var->from) { |
| 134 uic_save_var2(var); |
|
| 135 uic_copy_binding(var, var->from, FALSE); |
133 uic_copy_binding(var, var->from, FALSE); |
| 136 cxMapPut(var->from->from_ctx->vars_unbound, *entry->key, var->from); |
134 cxMapPut(var->from->from_ctx->vars, *entry->key, var->from); |
| 137 var->from = NULL; |
135 var->from = NULL; |
| 138 } |
136 } |
| 139 } |
137 } |
| 140 |
138 |
| 141 if(ctx->documents) { |
139 if(ctx->documents) { |
| 198 CxHashKey key = cx_hash_key(name, strlen(name)); |
196 CxHashKey key = cx_hash_key(name, strlen(name)); |
| 199 return ctx_getvar(ctx, key); |
197 return ctx_getvar(ctx, key); |
| 200 } |
198 } |
| 201 |
199 |
| 202 UiVar* uic_create_var(UiContext *ctx, const char *name, UiVarType type) { |
200 UiVar* uic_create_var(UiContext *ctx, const char *name, UiVarType type) { |
| 203 if(ctx->vars_unbound) { |
|
| 204 UiVar *unbound = cxMapGet(ctx->vars_unbound, name); |
|
| 205 if(unbound) { |
|
| 206 return unbound; |
|
| 207 } |
|
| 208 } |
|
| 209 |
|
| 210 UiVar *var = uic_get_var(ctx, name); |
201 UiVar *var = uic_get_var(ctx, name); |
| 211 if(var) { |
202 if(var) { |
| 212 if(var->type == type) { |
203 if(var->type == type) { |
| 213 return var; |
204 return var; |
| 214 } else { |
205 } else { |
| 223 var->from = NULL; |
214 var->from = NULL; |
| 224 var->from_ctx = ctx; |
215 var->from_ctx = ctx; |
| 225 |
216 |
| 226 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var); |
217 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var); |
| 227 |
218 |
| 228 if(!ctx->vars_unbound) { |
219 cxMapPut(ctx->vars, name, var); |
| 229 ctx->vars_unbound = cxHashMapCreate(ctx->allocator, CX_STORE_POINTERS, 16); |
|
| 230 } |
|
| 231 cxMapPut(ctx->vars_unbound, name, var); |
|
| 232 |
220 |
| 233 return var; |
221 return var; |
| 234 } |
222 } |
| 235 |
223 |
| 236 UiVar* uic_create_value_var(UiContext* ctx, void* value) { |
224 UiVar* uic_create_value_var(UiContext* ctx, void* value) { |
| 277 } |
265 } |
| 278 return val; |
266 return val; |
| 279 } |
267 } |
| 280 |
268 |
| 281 |
269 |
| 282 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) { |
| 283 if (value) { |
271 if (value) { |
| 284 return uic_create_value_var(current, value); |
272 return uic_create_value_var(current, value); |
| 285 } |
273 } |
| 286 if (varname) { |
274 if (varname) { |
| 287 return uic_create_var(toplevel, varname, type); |
275 return uic_create_var(toplevel, varname, type); |
| 382 } |
370 } |
| 383 |
371 |
| 384 ui_setop_enable(FALSE); |
372 ui_setop_enable(FALSE); |
| 385 } |
373 } |
| 386 |
374 |
| 387 void uic_save_var2(UiVar *var) { |
375 void uic_save_var(UiVar *var) { |
| 388 switch(var->type) { |
376 switch(var->type) { |
| 389 case UI_VAR_SPECIAL: break; |
377 case UI_VAR_SPECIAL: break; |
| 390 case UI_VAR_INTEGER: uic_int_save(var->value); break; |
378 case UI_VAR_INTEGER: uic_int_save(var->value); break; |
| 391 case UI_VAR_DOUBLE: uic_double_save(var->value); break; |
379 case UI_VAR_DOUBLE: uic_double_save(var->value); break; |
| 392 case UI_VAR_STRING: uic_string_save(var->value); break; |
380 case UI_VAR_STRING: uic_string_save(var->value); break; |