ui/common/context.c

changeset 108
77254bd6dccb
parent 103
6606616eca9f
child 110
c00e968d018b
equal deleted inserted replaced
107:b34bd1557c6c 108:77254bd6dccb
56 UiContext* uic_context(UiObject *toplevel, CxMempool *mp) { 56 UiContext* uic_context(UiObject *toplevel, CxMempool *mp) {
57 UiContext *ctx = cxMalloc(mp->allocator, sizeof(UiContext)); 57 UiContext *ctx = cxMalloc(mp->allocator, sizeof(UiContext));
58 memset(ctx, 0, sizeof(UiContext)); 58 memset(ctx, 0, sizeof(UiContext));
59 ctx->mp = mp; 59 ctx->mp = mp;
60 ctx->allocator = mp->allocator; 60 ctx->allocator = mp->allocator;
61 ctx->destroy_handler = cxArrayListCreate(ctx->allocator, NULL, sizeof(UiDestroyHandler), 16);
61 ctx->obj = toplevel; 62 ctx->obj = toplevel;
62 ctx->vars = cxHashMapCreate(mp->allocator, CX_STORE_POINTERS, 16); 63 ctx->vars = cxHashMapCreate(mp->allocator, CX_STORE_POINTERS, 16);
63 64
64 ctx->documents = cxLinkedListCreate(mp->allocator, cx_cmp_ptr, CX_STORE_POINTERS); 65 ctx->documents = cxLinkedListCreate(mp->allocator, cx_cmp_ptr, CX_STORE_POINTERS);
65 ctx->group_widgets = cxLinkedListCreate(mp->allocator, cx_cmp_ptr, sizeof(UiGroupWidget)); 66 ctx->group_widgets = cxLinkedListCreate(mp->allocator, cx_cmp_ptr, sizeof(UiGroupWidget));
66 ctx->groups = cxArrayListCreate(mp->allocator, cx_cmp_int, sizeof(int), 32); 67 ctx->groups = cxArrayListCreate(mp->allocator, cx_cmp_int, sizeof(int), 32);
67 68
68 ctx->attach_document = uic_context_attach_document; 69 ctx->attach_document = uic_context_attach_document;
69 ctx->detach_document2 = uic_context_detach_document2; 70 ctx->detach_document2 = uic_context_detach_document;
70 71
71 #if UI_GTK2 || UI_GTK3 72 #if UI_GTK2 || UI_GTK3
72 if(toplevel && toplevel->widget) { 73 if(toplevel && toplevel->widget) {
73 ctx->accel_group = gtk_accel_group_new(); 74 ctx->accel_group = gtk_accel_group_new();
74 gtk_window_add_accel_group(GTK_WINDOW(toplevel->widget), ctx->accel_group); 75 gtk_window_add_accel_group(GTK_WINDOW(toplevel->widget), ctx->accel_group);
78 return ctx; 79 return ctx;
79 } 80 }
80 81
81 UiContext* uic_root_context(UiContext *ctx) { 82 UiContext* uic_root_context(UiContext *ctx) {
82 return ctx->parent ? uic_root_context(ctx->parent) : ctx; 83 return ctx->parent ? uic_root_context(ctx->parent) : ctx;
84 }
85
86 void uic_context_add_destructor(UiContext *ctx, cx_destructor_func func, void *data) {
87 UiDestroyHandler handler;
88 handler.destructor = func;
89 handler.data = data;
90 cxListAdd(ctx->destroy_handler, &handler);
83 } 91 }
84 92
85 void uic_context_prepare_close(UiContext *ctx) { 93 void uic_context_prepare_close(UiContext *ctx) {
86 cxListClear(ctx->groups); 94 cxListClear(ctx->groups);
87 cxListClear(ctx->group_widgets); 95 cxListClear(ctx->group_widgets);
118 126
119 static void uic_context_unbind_vars(UiContext *ctx) { 127 static void uic_context_unbind_vars(UiContext *ctx) {
120 CxMapIterator mi = cxMapIterator(ctx->vars); 128 CxMapIterator mi = cxMapIterator(ctx->vars);
121 cx_foreach(CxMapEntry*, entry, mi) { 129 cx_foreach(CxMapEntry*, entry, mi) {
122 UiVar *var = entry->value; 130 UiVar *var = entry->value;
123 if(var->from && var->from_ctx && var->from_ctx != ctx) { 131 // var->from && var->from_ctx && var->from_ctx != ctx
132 if(var->from) {
124 uic_save_var2(var); 133 uic_save_var2(var);
125 uic_copy_binding(var, var->from, FALSE); 134 uic_copy_binding(var, var->from, FALSE);
126 cxMapPut(var->from_ctx->vars_unbound, *entry->key, var->from); 135 cxMapPut(var->from->from_ctx->vars_unbound, *entry->key, var->from);
127 var->from_ctx = ctx; 136 var->from = NULL;
128 } 137 }
129 } 138 }
130 139
131 if(ctx->documents) { 140 if(ctx->documents) {
132 CxIterator i = cxListIterator(ctx->documents); 141 CxIterator i = cxListIterator(ctx->documents);
135 uic_context_unbind_vars(subctx); 144 uic_context_unbind_vars(subctx);
136 } 145 }
137 } 146 }
138 } 147 }
139 148
140 void uic_context_detach_document2(UiContext *ctx, void *document) { 149 void uic_context_detach_document(UiContext *ctx, void *document) {
141 // find the document in the documents list 150 // find the document in the documents list
142 size_t docIndex = cxListFind(ctx->documents, document); 151 size_t docIndex = cxListFind(ctx->documents, document);
143 if(!cxListIndexValid(ctx->documents, docIndex)) { 152 if(!cxListIndexValid(ctx->documents, docIndex)) {
144 return; 153 return;
145 } 154 }
207 } 216 }
208 217
209 var = ui_malloc(ctx, sizeof(UiVar)); 218 var = ui_malloc(ctx, sizeof(UiVar));
210 var->type = type; 219 var->type = type;
211 var->value = uic_create_value(ctx, type); 220 var->value = uic_create_value(ctx, type);
221 var->original_value = NULL;
212 var->from = NULL; 222 var->from = NULL;
213 var->from_ctx = ctx; 223 var->from_ctx = ctx;
214 224
215 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var); 225 cxMempoolSetDestructor(var, (cx_destructor_func)uic_unbind_var);
216 226
225 UiVar* uic_create_value_var(UiContext* ctx, void* value) { 235 UiVar* uic_create_value_var(UiContext* ctx, void* value) {
226 UiVar *var = (UiVar*)ui_malloc(ctx, sizeof(UiVar)); 236 UiVar *var = (UiVar*)ui_malloc(ctx, sizeof(UiVar));
227 var->from = NULL; 237 var->from = NULL;
228 var->from_ctx = ctx; 238 var->from_ctx = ctx;
229 var->value = value; 239 var->value = value;
240 var->original_value = NULL;
230 var->type = UI_VAR_SPECIAL; 241 var->type = UI_VAR_SPECIAL;
231 return var; 242 return var;
232 } 243 }
233 244
234 void* uic_create_value(UiContext *ctx, UiVarType type) { 245 void* uic_create_value(UiContext *ctx, UiVarType type) {
284 fprintf(stderr, "UI Error: var has incompatible type.\n"); 295 fprintf(stderr, "UI Error: var has incompatible type.\n");
285 return; 296 return;
286 } 297 }
287 298
288 void *fromvalue = from->value; 299 void *fromvalue = from->value;
300 void *tovalue = to->value;
289 // update var 301 // update var
290 if(copytodoc) { 302 if(copytodoc) {
291 to->from = from; 303 to->from = from; // from which UiVar are the bindings copied
292 to->from_ctx = from->from_ctx; 304 from->original_value = fromvalue; // save original value otherwise it would be lost
305 // widgets store a reference to the UiVar with their value
306 // the UiVar object must be updated to contain the current value object
307 from->value = tovalue;
308 } else {
309 if(to->original_value) {
310 to->value = to->original_value;
311 tovalue = to->value;
312 }
293 } 313 }
294 314
295 ui_setop_enable(TRUE); 315 ui_setop_enable(TRUE);
296 316
297 // copy binding 317 // copy binding
299 switch(from->type) { 319 switch(from->type) {
300 default: fprintf(stderr, "uic_copy_binding: wtf!\n"); break; 320 default: fprintf(stderr, "uic_copy_binding: wtf!\n"); break;
301 case UI_VAR_SPECIAL: break; 321 case UI_VAR_SPECIAL: break;
302 case UI_VAR_INTEGER: { 322 case UI_VAR_INTEGER: {
303 UiInteger *f = fromvalue; 323 UiInteger *f = fromvalue;
304 UiInteger *t = to->value; 324 UiInteger *t = tovalue;
305 if(!f->obj) break; 325 if(!f->obj) break;
306 uic_int_copy(f, t); 326 uic_int_copy(f, t);
307 t->set(t, t->value); 327 t->set(t, t->value);
308 break; 328 break;
309 } 329 }
310 case UI_VAR_DOUBLE: { 330 case UI_VAR_DOUBLE: {
311 UiDouble *f = fromvalue; 331 UiDouble *f = fromvalue;
312 UiDouble *t = to->value; 332 UiDouble *t = tovalue;
313 if(!f->obj) break; 333 if(!f->obj) break;
314 uic_double_copy(f, t); 334 uic_double_copy(f, t);
315 t->set(t, t->value); 335 t->set(t, t->value);
316 break; 336 break;
317 } 337 }
318 case UI_VAR_STRING: { 338 case UI_VAR_STRING: {
319 UiString *f = fromvalue; 339 UiString *f = fromvalue;
320 UiString *t = to->value; 340 UiString *t = tovalue;
321 if(!f->obj) break; 341 if(!f->obj) break;
322 uic_string_copy(f, t); 342 uic_string_copy(f, t);
323 char *tvalue = t->value.ptr ? t->value.ptr : ""; 343 char *tvalue = t->value.ptr ? t->value.ptr : "";
344 char *fvalue = f->value.ptr ? f->value.ptr : "";
324 t->set(t, tvalue); 345 t->set(t, tvalue);
325 break; 346 break;
326 } 347 }
327 case UI_VAR_TEXT: { 348 case UI_VAR_TEXT: {
328 UiText *f = fromvalue; 349 UiText *f = fromvalue;
329 UiText *t = to->value; 350 UiText *t = tovalue;
330 if(!f->obj) break; 351 if(!f->obj) break;
331 uic_text_copy(f, t); 352 uic_text_copy(f, t);
332 t->restore(t); 353 t->restore(t);
333 break; 354 break;
334 } 355 }
335 case UI_VAR_LIST: { 356 case UI_VAR_LIST: {
336 // TODO: not sure how correct this is 357 UiList *f = fromvalue;
337 358 UiList *t = tovalue;
338 UiList *f = from->value; 359 uic_list_copy(f, t);
339 UiList *t = to->value; 360 ui_list_update(t);
340 if (f->obj) {
341 t->obj = f->obj;
342 t->update = f->update;
343 t->getselection = f->getselection;
344 t->setselection = f->setselection;
345 }
346
347 UiVar tmp = *from;
348 *from = *to;
349 *to = tmp;
350
351 UiList* t2 = to->value;
352 if(t->update) {
353 t->update(t, -1);
354 }
355 ui_notify(t2->observers, NULL); // TODO: why not t?
356
357 break; 361 break;
358 } 362 }
359 case UI_VAR_RANGE: { 363 case UI_VAR_RANGE: {
360 UiRange *f = fromvalue; 364 UiRange *f = fromvalue;
361 UiRange *t = to->value; 365 UiRange *t = tovalue;
362 if(!f->obj) break; 366 if(!f->obj) break;
363 uic_range_copy(f, t); 367 uic_range_copy(f, t);
364 t->setextent(t, t->extent); 368 t->setextent(t, t->extent);
365 t->setrange(t, t->min, t->max); 369 t->setrange(t, t->min, t->max);
366 t->set(t, t->value); 370 t->set(t, t->value);
367 break; 371 break;
368 } 372 }
369 case UI_VAR_GENERIC: { 373 case UI_VAR_GENERIC: {
370 UiGeneric *f = fromvalue; 374 UiGeneric *f = fromvalue;
371 UiGeneric *t = to->value; 375 UiGeneric *t = tovalue;
372 if(!f->obj) break; 376 if(!f->obj) break;
373 uic_generic_copy(f, t); 377 uic_generic_copy(f, t);
374 t->set(t, t->value, t->type); 378 t->set(t, t->value, t->type);
375 break; 379 break;
376 } 380 }
403 case UI_VAR_RANGE: uic_range_unbind(var->value); break; 407 case UI_VAR_RANGE: uic_range_unbind(var->value); break;
404 case UI_VAR_GENERIC: uic_generic_unbind(var->value); break; 408 case UI_VAR_GENERIC: uic_generic_unbind(var->value); break;
405 } 409 }
406 } 410 }
407 411
408 void uic_reg_var(UiContext *ctx, char *name, UiVarType type, void *value) { 412 void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value) {
409 // TODO: do we need/want this? Why adding vars to a context after 413 // TODO: do we need/want this? Why adding vars to a context after
410 // widgets reference these? Workarounds: 414 // widgets reference these? Workarounds:
411 // 1. add vars to ctx before creating ui 415 // 1. add vars to ctx before creating ui
412 // 2. create ui, create new document with vars, attach doc 416 // 2. create ui, create new document with vars, attach doc
413 // also it would be possible to create a function, that scans unbound vars 417 // also it would be possible to create a function, that scans unbound vars
461 465
462 void ui_attach_document(UiContext *ctx, void *document) { 466 void ui_attach_document(UiContext *ctx, void *document) {
463 uic_context_attach_document(ctx, document); 467 uic_context_attach_document(ctx, document);
464 } 468 }
465 469
466 void ui_detach_document2(UiContext *ctx, void *document) { 470 void ui_detach_document(UiContext *ctx, void *document) {
467 uic_context_detach_document2(ctx, document); 471 uic_context_detach_document(ctx, document);
468 } 472 }
469 473
470 void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) { 474 void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) {
471 ctx->close_callback = fnc; 475 ctx->close_callback = fnc;
472 ctx->close_data = udata; 476 ctx->close_data = udata;
473 } 477 }
474 478
475 UIEXPORT void ui_context_destroy(UiContext *ctx) { 479 void ui_context_destroy(UiContext *ctx) {
480 CxIterator i = cxListIterator(ctx->destroy_handler);
481 cx_foreach(UiDestroyHandler *, h, i) {
482 h->destructor(h->data);
483 }
476 cxMempoolFree(ctx->mp); 484 cxMempoolFree(ctx->mp);
485 }
486
487 UiContext* ui_context_parent(UiContext *ctx) {
488 return ctx->parent;
477 } 489 }
478 490
479 491
480 void ui_set_group(UiContext *ctx, int group) { 492 void ui_set_group(UiContext *ctx, int group) {
481 if(!cxListIndexValid(ctx->groups, cxListFind(ctx->groups, &group))) { 493 if(!cxListIndexValid(ctx->groups, cxListFind(ctx->groups, &group))) {

mercurial