ui/common/context.c

changeset 902
6872b59217a7
parent 885
28ecfe5399ae
child 905
41614c767451
equal deleted inserted replaced
901:884d70e847a3 902:6872b59217a7
112 printf("attach %.*s\n", (int)entry->key->len, (char*)entry->key->data); 112 printf("attach %.*s\n", (int)entry->key->len, (char*)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_var_binding(var, docvar, TRUE);
118 cxIteratorFlagRemoval(i); 118 cxIteratorFlagRemoval(i);
119 } 119 }
120 } 120 }
121 121
122 var_ctx = var_ctx->parent; 122 var_ctx = var_ctx->parent;
128 cx_foreach(CxMapEntry*, entry, mi) { 128 cx_foreach(CxMapEntry*, entry, mi) {
129 UiVar *var = entry->value; 129 UiVar *var = entry->value;
130 // var->from && var->from_ctx && var->from_ctx != ctx 130 // var->from && var->from_ctx && var->from_ctx != ctx
131 uic_save_var(var); 131 uic_save_var(var);
132 if(var->from) { 132 if(var->from) {
133 uic_copy_binding(var, var->from, FALSE); 133 uic_copy_var_binding(var, var->from, FALSE);
134 cxMapPut(var->from->from_ctx->vars, *entry->key, var->from); 134 cxMapPut(var->from->from_ctx->vars, *entry->key, var->from);
135 var->from = NULL; 135 var->from = NULL;
136 } 136 }
137 } 137 }
138 138
211 var->type = type; 211 var->type = type;
212 var->value = uic_create_value(ctx, type); 212 var->value = uic_create_value(ctx, type);
213 var->original_value = NULL; 213 var->original_value = NULL;
214 var->from = NULL; 214 var->from = NULL;
215 var->from_ctx = ctx; 215 var->from_ctx = ctx;
216 216 var->bound = FALSE;
217
217 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var); 218 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var);
218 219
219 cxMapPut(ctx->vars, name, var); 220 cxMapPut(ctx->vars, name, var);
220 221
221 return var; 222 return var;
264 } 265 }
265 } 266 }
266 return val; 267 return val;
267 } 268 }
268 269
270 // destroys a value, that was created by uic_create_value
271 void uic_destroy_value(UiContext *ctx, UiVarType type, void *value) {
272 switch(type) {
273 default: {
274 ui_free(ctx, value);
275 break;
276 }
277 case UI_VAR_SPECIAL: break;
278 case UI_VAR_STRING: {
279 UiString *s = value;
280 if(s->value.free) {
281 s->value.free(s->value.ptr);
282 }
283 ui_free(ctx, value);
284 }
285 case UI_VAR_TEXT: {
286 UiText *t = value;
287 if(t->value.free) {
288 t->value.free(t->value.ptr);
289 t->value.free = NULL;
290 t->value.ptr = NULL;
291 }
292 if(t->destroy) {
293 t->destroy(t);
294 }
295 ui_free(ctx, value);
296 }
297 case UI_VAR_LIST: {
298 ui_list_free(ctx, value);
299 break;
300 }
301 }
302 }
303
269 304
270 UiVar* uic_widget_var(UiContext *toplevel, UiContext *current, void *value, const char *varname, UiVarType type) { 305 UiVar* uic_widget_var(UiContext *toplevel, UiContext *current, void *value, const char *varname, UiVarType type) {
271 if (value) { 306 if (value) {
272 return uic_create_value_var(current, value); 307 return uic_create_value_var(current, value);
273 } 308 }
276 } 311 }
277 return NULL; 312 return NULL;
278 } 313 }
279 314
280 315
281 void uic_copy_binding(UiVar *from, UiVar *to, UiBool copytodoc) { 316 void uic_copy_var_binding(UiVar *from, UiVar *to, UiBool copytodoc) {
282 // check type 317 // check type
283 if(from->type != to->type) { 318 if(from->type != to->type) {
284 fprintf(stderr, "UI Error: var has incompatible type.\n"); 319 fprintf(stderr, "UI Error: var has incompatible type.\n");
285 return; 320 return;
286 } 321 }
299 to->value = to->original_value; 334 to->value = to->original_value;
300 tovalue = to->value; 335 tovalue = to->value;
301 } 336 }
302 } 337 }
303 338
304 ui_setop_enable(TRUE); 339 uic_copy_value_binding(from->type, from, to);
340 }
341
342 void uic_copy_value_binding(UiVarType type, void *from, void *to) {
343 ui_setop_enable(TRUE);
305 344
306 // copy binding 345 // copy binding
307 // we don't copy the observer, because the from var has never one 346 // we don't copy the observer, because the from value never has oberservers
308 switch(from->type) { 347 switch(type) {
309 default: fprintf(stderr, "uic_copy_binding: wtf!\n"); break; 348 default: fprintf(stderr, "uic_copy_binding: wtf!\n"); break;
310 case UI_VAR_SPECIAL: break; 349 case UI_VAR_SPECIAL: break;
311 case UI_VAR_INTEGER: { 350 case UI_VAR_INTEGER: {
312 UiInteger *f = fromvalue; 351 UiInteger *f = from;
313 UiInteger *t = tovalue; 352 UiInteger *t = to;
314 if(!f->obj) break; 353 if(!f->obj) break;
315 uic_int_copy(f, t); 354 uic_int_copy(f, t);
316 t->set(t, t->value); 355 t->set(t, t->value);
317 break; 356 break;
318 } 357 }
319 case UI_VAR_DOUBLE: { 358 case UI_VAR_DOUBLE: {
320 UiDouble *f = fromvalue; 359 UiDouble *f = from;
321 UiDouble *t = tovalue; 360 UiDouble *t = to;
322 if(!f->obj) break; 361 if(!f->obj) break;
323 uic_double_copy(f, t); 362 uic_double_copy(f, t);
324 t->set(t, t->value); 363 t->set(t, t->value);
325 break; 364 break;
326 } 365 }
327 case UI_VAR_STRING: { 366 case UI_VAR_STRING: {
328 UiString *f = fromvalue; 367 UiString *f = from;
329 UiString *t = tovalue; 368 UiString *t = to;
330 if(!f->obj) break; 369 if(!f->obj) break;
331 uic_string_copy(f, t); 370 uic_string_copy(f, t);
332 char *tvalue = t->value.ptr ? t->value.ptr : ""; 371 char *tvalue = t->value.ptr ? t->value.ptr : "";
333 char *fvalue = f->value.ptr ? f->value.ptr : ""; 372 char *fvalue = f->value.ptr ? f->value.ptr : "";
334 t->set(t, tvalue); 373 t->set(t, tvalue);
335 break; 374 break;
336 } 375 }
337 case UI_VAR_TEXT: { 376 case UI_VAR_TEXT: {
338 UiText *f = fromvalue; 377 UiText *f = from;
339 UiText *t = tovalue; 378 UiText *t = to;
340 if(!f->obj) break; 379 if(!f->obj) break;
341 uic_text_copy(f, t); 380 uic_text_copy(f, t);
342 t->restore(t); 381 t->restore(t);
343 break; 382 break;
344 } 383 }
345 case UI_VAR_LIST: { 384 case UI_VAR_LIST: {
346 UiList *f = fromvalue; 385 UiList *f = from;
347 UiList *t = tovalue; 386 UiList *t = to;
348 uic_list_copy(f, t); 387 uic_list_copy(f, t);
349 ui_list_update(t); 388 ui_list_update(t);
350 break; 389 break;
351 } 390 }
352 case UI_VAR_RANGE: { 391 case UI_VAR_RANGE: {
353 UiRange *f = fromvalue; 392 UiRange *f = from;
354 UiRange *t = tovalue; 393 UiRange *t = to;
355 if(!f->obj) break; 394 if(!f->obj) break;
356 uic_range_copy(f, t); 395 uic_range_copy(f, t);
357 t->setextent(t, t->extent); 396 t->setextent(t, t->extent);
358 t->setrange(t, t->min, t->max); 397 t->setrange(t, t->min, t->max);
359 t->set(t, t->value); 398 t->set(t, t->value);
360 break; 399 break;
361 } 400 }
362 case UI_VAR_GENERIC: { 401 case UI_VAR_GENERIC: {
363 UiGeneric *f = fromvalue; 402 UiGeneric *f = from;
364 UiGeneric *t = tovalue; 403 UiGeneric *t = to;
365 if(!f->obj) break; 404 if(!f->obj) break;
366 uic_generic_copy(f, t); 405 uic_generic_copy(f, t);
367 t->set(t, t->value, t->type); 406 t->set(t, t->value, t->type);
368 break; 407 break;
369 } 408 }
396 case UI_VAR_RANGE: uic_range_unbind(var->value); break; 435 case UI_VAR_RANGE: uic_range_unbind(var->value); break;
397 case UI_VAR_GENERIC: uic_generic_unbind(var->value); break; 436 case UI_VAR_GENERIC: uic_generic_unbind(var->value); break;
398 } 437 }
399 } 438 }
400 439
440 const char *uic_type2str(UiVarType type) {
441 switch(type) {
442 default: return "";
443 case UI_VAR_INTEGER: return "int";
444 case UI_VAR_DOUBLE: return "double";
445 case UI_VAR_STRING: return "string";
446 case UI_VAR_TEXT: return "text";
447 case UI_VAR_LIST: return "list";
448 case UI_VAR_RANGE: return "range";
449 case UI_VAR_GENERIC: return "generic";
450 }
451 }
452
401 void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value) { 453 void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value) {
402 // TODO: do we need/want this? Why adding vars to a context after 454 UiVar *var = cxMapGet(ctx->vars, name);
403 // widgets reference these? Workarounds: 455 if(!var) {
404 // 1. add vars to ctx before creating ui 456 // create new var and add it to the context var map
405 // 2. create ui, create new document with vars, attach doc 457 var = ui_malloc(ctx, sizeof(UiVar));
406 // also it would be possible to create a function, that scans unbound vars 458 cxMapPut(ctx->vars, name, var);
407 // and connects them to available vars 459 } else {
408 /* 460 // override var with new value
409 UiContext *rootctx = uic_root_context(ctx); 461 if(var->type != type) {
410 UiVar *b = NULL; 462 fprintf(stderr, "Error: var %s type mismatch: %s - %s\n", name, uic_type2str(var->type), type);
411 if(rootctx->bound) { 463 return;
412 // some widgets are already bound to some vars 464 }
413 b = ucx_map_cstr_get(rootctx->bound, name); 465 if(var->bound) {
414 if(b) { 466 fprintf(stderr, "Error: var %s already bound\n", name);
415 // a widget is bound to a var with this name 467 return;
416 // if ctx is the root context we can remove the var from bound 468 }
417 // because set_doc or detach can't fuck things up 469 UiInteger *prev_value = var->value;
418 if(ctx == rootctx) { 470 uic_copy_value_binding(type, prev_value, value);
419 ucx_map_cstr_remove(ctx->bound, name); 471 uic_destroy_value(var->from_ctx, var->type, var->value);
420 // TODO: free stuff 472 }
421 } 473
422 }
423 }
424 */
425
426 // create new var and add it to doc's vars
427 UiVar *var = ui_malloc(ctx, sizeof(UiVar));
428 var->type = type; 474 var->type = type;
429 var->value = value; 475 var->value = value;
430 var->from = NULL; 476 var->from = NULL;
431 var->from_ctx = ctx; 477 var->from_ctx = ctx;
432 size_t oldcount = cxMapSize(ctx->vars); 478 var->bound = TRUE;
433 cxMapPut(ctx->vars, name, var); 479 }
434 if(cxMapSize(ctx->vars) != oldcount + 1) {
435 fprintf(stderr, "UiError: var '%s' already exists\n", name);
436 }
437
438 // TODO: remove?
439 // a widget is already bound to a var with this name
440 // copy the binding (like uic_context_set_document)
441 /*
442 if(b) {
443 uic_copy_binding(b, var, TRUE);
444 }
445 */
446 }
447
448 void uic_remove_bound_var(UiContext *ctx, UiVar *var) {
449 // TODO
450 }
451
452 480
453 // public API 481 // public API
454 482
455 void ui_attach_document(UiContext *ctx, void *document) { 483 void ui_attach_document(UiContext *ctx, void *document) {
456 uic_context_attach_document(ctx, document); 484 uic_context_attach_document(ctx, document);

mercurial