ui/common/types.c

changeset 115
e57ca2747782
parent 113
dde28a806552
equal deleted inserted replaced
114:3da24640513a 115:e57ca2747782
31 #include <string.h> 31 #include <string.h>
32 #include <stdarg.h> 32 #include <stdarg.h>
33 33
34 #include <cx/list.h> 34 #include <cx/list.h>
35 #include <cx/array_list.h> 35 #include <cx/array_list.h>
36 #include "../ui/tree.h" 36 #include "../ui/list.h"
37 #include "types.h" 37 #include "types.h"
38 #include "context.h" 38 #include "context.h"
39 #include "../ui/image.h" 39 #include "../ui/image.h"
40 40
41 static ui_list_init_func default_list_init; 41 static ui_list_init_func default_list_init;
42 static void *default_list_init_userdata; 42 static void *default_list_init_userdata;
43 static ui_list_destroy_func default_list_destroy;
44 static void *default_list_destroy_userdata;
43 45
44 UiObserver* ui_observer_new(ui_callback f, void *data) { 46 UiObserver* ui_observer_new(ui_callback f, void *data) {
45 UiObserver *observer = malloc(sizeof(UiObserver)); 47 UiObserver *observer = malloc(sizeof(UiObserver));
46 observer->callback = f; 48 observer->callback = f;
47 observer->data = data; 49 observer->data = data;
103 list->next = ui_list_next; 105 list->next = ui_list_next;
104 list->get = ui_list_get; 106 list->get = ui_list_get;
105 list->count = ui_list_count; 107 list->count = ui_list_count;
106 } 108 }
107 109
110 void uic_ucx_list_destroy(UiContext *ctx, UiList *list, void *unused) {
111 cxListFree(list->data);
112 ui_free(ctx, list);
113 }
114
108 UiList* ui_list_new(UiContext *ctx, const char *name) { 115 UiList* ui_list_new(UiContext *ctx, const char *name) {
109 return ui_list_new2(ctx, name, default_list_init ? default_list_init : uic_ucx_list_init, default_list_init_userdata); 116 return ui_list_new2(ctx, name, default_list_init ? default_list_init : uic_ucx_list_init, default_list_init_userdata);
110 } 117 }
111 118
112 UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func listinit, void *userdata) { 119 UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func listinit, void *userdata) {
119 } 126 }
120 127
121 return list; 128 return list;
122 } 129 }
123 130
124 void ui_list_free(UiList *list) { 131 void ui_list_free(UiContext *ctx, UiList *list) {
125 cxListFree(list->data); 132 if(!default_list_destroy) {
126 free(list); 133 uic_ucx_list_destroy(ctx, list, NULL);
134 } else {
135 default_list_destroy(ctx, list, default_list_destroy_userdata);
136 }
137
127 } 138 }
128 139
129 void* ui_list_first(UiList *list) { 140 void* ui_list_first(UiList *list) {
130 list->iter = (void*)(intptr_t)0; 141 list->iter = (void*)(intptr_t)0;
131 return cxListAt(list->data, 0); 142 return cxListAt(list->data, 0);
199 char *name; 210 char *name;
200 } UiColumn; 211 } UiColumn;
201 212
202 UiModel* ui_model(UiContext *ctx, ...) { 213 UiModel* ui_model(UiContext *ctx, ...) {
203 UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel)); 214 UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel));
215 info->ctx = ctx;
204 216
205 va_list ap; 217 va_list ap;
206 va_start(ap, ctx); 218 va_start(ap, ctx);
207 219
208 CxList *cols = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(UiColumn), 32); 220 CxList *cols = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(UiColumn), 32);
238 return info; 250 return info;
239 } 251 }
240 252
241 #define UI_MODEL_DEFAULT_ALLOC_SIZE 16 253 #define UI_MODEL_DEFAULT_ALLOC_SIZE 16
242 254
255
256 static void model_notify_observer(UiModel *model, int insert, int delete) {
257 UiModelChangeObserver *obs = model->observer;
258 while(obs) {
259 obs->update(model, obs->userdata, insert, delete);
260 obs = obs->next;
261 }
262 }
263
243 UiModel* ui_model_new(UiContext *ctx) { 264 UiModel* ui_model_new(UiContext *ctx) {
244 UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel)); 265 UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel));
266 info->ctx = ctx;
245 info->alloc = UI_MODEL_DEFAULT_ALLOC_SIZE; 267 info->alloc = UI_MODEL_DEFAULT_ALLOC_SIZE;
246 info->types = ui_calloc(ctx, UI_MODEL_DEFAULT_ALLOC_SIZE, sizeof(UiModelType)); 268 info->types = ui_calloc(ctx, UI_MODEL_DEFAULT_ALLOC_SIZE, sizeof(UiModelType));
247 info->titles = ui_calloc(ctx, UI_MODEL_DEFAULT_ALLOC_SIZE, sizeof(char*)); 269 info->titles = ui_calloc(ctx, UI_MODEL_DEFAULT_ALLOC_SIZE, sizeof(char*));
248 info->columnsize = ui_calloc(ctx, UI_MODEL_DEFAULT_ALLOC_SIZE, sizeof(int)); 270 info->columnsize = ui_calloc(ctx, UI_MODEL_DEFAULT_ALLOC_SIZE, sizeof(int));
249 return info; 271 return info;
250 } 272 }
251 273
252 void ui_model_add_column(UiContext *ctx, UiModel *model, UiModelType type, const char *title, int width) { 274 void ui_model_add_column(UiModel *model, UiModelType type, const char *title, int width) {
275 UiContext *ctx = model->ctx;
253 if(model->columns >= model->alloc) { 276 if(model->columns >= model->alloc) {
254 model->alloc += UI_MODEL_DEFAULT_ALLOC_SIZE; 277 model->alloc += UI_MODEL_DEFAULT_ALLOC_SIZE;
255 model->types = ui_realloc(ctx, model->types, model->alloc * sizeof(UiModelType)); 278 model->types = ui_realloc(ctx, model->types, model->alloc * sizeof(UiModelType));
256 model->titles = ui_realloc(ctx, model->titles, model->alloc * sizeof(char*)); 279 model->titles = ui_realloc(ctx, model->titles, model->alloc * sizeof(char*));
257 model->columnsize = ui_realloc(ctx, model->columnsize, model->alloc * sizeof(int)); 280 model->columnsize = ui_realloc(ctx, model->columnsize, model->alloc * sizeof(int));
258 } 281 }
259 model->types[model->columns] = type; 282 int index = model->columns;
260 model->titles[model->columns] = ui_strdup(ctx, title); 283 model->types[index] = type;
261 model->columnsize[model->columns] = width; 284 model->titles[index] = ui_strdup(ctx, title);
285 model->columnsize[index] = width;
286
287 model_notify_observer(model, index, -1);
288
262 model->columns++; 289 model->columns++;
263 } 290 }
264 291
265 UiModel* ui_model_copy(UiContext *ctx, UiModel* model) { 292 UiModel* ui_model_copy(UiContext *ctx, UiModel* model) {
266 const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator; 293 const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator;
267 294
268 UiModel* newmodel = cxMalloc(a, sizeof(UiModel)); 295 UiModel* newmodel = cxMalloc(a, sizeof(UiModel));
296 newmodel->ctx = ctx;
269 *newmodel = *model; 297 *newmodel = *model;
270 298
271 newmodel->types = cxCalloc(a, model->columns, sizeof(UiModelType)); 299 newmodel->types = cxCalloc(a, model->columns, sizeof(UiModelType));
272 memcpy(newmodel->types, model->types, model->columns); 300 memcpy(newmodel->types, model->types, model->columns);
273 301
279 memcpy(newmodel->columnsize, model->columnsize, model->columns*sizeof(int)); 307 memcpy(newmodel->columnsize, model->columnsize, model->columns*sizeof(int));
280 308
281 return newmodel; 309 return newmodel;
282 } 310 }
283 311
284 void ui_model_free(UiContext *ctx, UiModel *mi) { 312 void ui_model_ref(UiModel *model) {
285 const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator; 313 model->ref++;
314 }
315
316 void ui_model_unref(UiModel *model) {
317 if(--model->ref == 0) {
318 ui_model_free(model);
319 }
320 }
321
322 void ui_model_add_observer(UiModel *model, ui_model_update_func update, void *data) {
323 UiModelChangeObserver *observer = ui_malloc(model->ctx, sizeof(UiModelChangeObserver));
324 observer->update = update;
325 observer->userdata = data;
326 observer->next = NULL;
327
328 if(model->observer) {
329 UiModelChangeObserver *last = model->observer;
330 while(last->next) {
331 last = last->next;
332 }
333 last->next = observer;
334 } else {
335 model->observer = observer;
336 }
337 }
338
339 void ui_model_remove_observer(UiModel *model, void *data) {
340 if(model->observer) {
341 UiModelChangeObserver *obs = model->observer;
342 UiModelChangeObserver *prev = NULL;
343 while(obs) {
344 if(obs->userdata == data) {
345 // remove
346 if(prev) {
347 prev->next = obs->next;
348 } else {
349 model->observer = obs->next;
350 }
351 // free
352 ui_free(model->ctx, obs);
353 break;
354 }
355 prev = obs;
356 obs = obs->next;
357 }
358 }
359 }
360
361 void ui_model_free(UiModel *mi) {
362 UiContext *ctx = mi->ctx;
363 const CxAllocator* a = ctx->allocator;
286 for(int i=0;i<mi->columns;i++) { 364 for(int i=0;i<mi->columns;i++) {
287 ui_free(ctx, mi->titles[i]); 365 ui_free(ctx, mi->titles[i]);
366 }
367 UiModelChangeObserver *obs = mi->observer;
368 while(obs) {
369 UiModelChangeObserver *n = obs->next;
370 cxFree(a, obs);
371 obs = n;
288 } 372 }
289 cxFree(a, mi->types); 373 cxFree(a, mi->types);
290 cxFree(a, mi->titles); 374 cxFree(a, mi->titles);
291 cxFree(a, mi->columnsize); 375 cxFree(a, mi->columnsize);
292 cxFree(a, mi); 376 cxFree(a, mi);
722 list->setselection(list, sel); 806 list->setselection(list, sel);
723 } 807 }
724 } 808 }
725 809
726 UIEXPORT void ui_listselection_free(UiListSelection selection) { 810 UIEXPORT void ui_listselection_free(UiListSelection selection) {
727 if (selection.rows) { 811 free(selection.rows);
728 free(selection.rows);
729 }
730 } 812 }
731 813
732 UIEXPORT UiStr ui_str(char *cstr) { 814 UIEXPORT UiStr ui_str(char *cstr) {
733 return (UiStr) { cstr, NULL }; 815 return (UiStr) { cstr, NULL };
734 } 816 }
785 destr->observer = observer; 867 destr->observer = observer;
786 cxMempoolSetDestructor(destr, (cx_destructor_func)observer_destructor); 868 cxMempoolSetDestructor(destr, (cx_destructor_func)observer_destructor);
787 } 869 }
788 870
789 static int ui_set_op = 0; 871 static int ui_set_op = 0;
872 static int ui_onchange_events_enabled = TRUE;
790 873
791 void ui_setop_enable(int set) { 874 void ui_setop_enable(int set) {
792 ui_set_op = set; 875 ui_set_op = set;
793 } 876 }
794 877
795 int ui_get_setop(void) { 878 int ui_get_setop(void) {
796 return ui_set_op; 879 return ui_set_op;
880 }
881
882 void ui_onchange_events_enable(UiBool enable) {
883 ui_onchange_events_enabled = enable;
884 }
885
886 UiBool ui_onchange_events_is_enabled(void) {
887 return ui_onchange_events_enabled;
797 } 888 }
798 889
799 /* ---------------- List initializers and wrapper functions ---------------- */ 890 /* ---------------- List initializers and wrapper functions ---------------- */
800 891
801 void ui_global_list_initializer(ui_list_init_func func, void *userdata) { 892 void ui_global_list_initializer(ui_list_init_func func, void *userdata) {
802 default_list_init = func; 893 default_list_init = func;
803 default_list_init_userdata = userdata; 894 default_list_init_userdata = userdata;
804 } 895 }
805 896
897 void ui_global_list_destructor(ui_list_destroy_func func, void *userdata) {
898 default_list_destroy = func;
899 default_list_destroy_userdata = userdata;
900 }
901
806 void ui_list_class_set_first(UiList *list, void*(*first)(UiList *list)) { 902 void ui_list_class_set_first(UiList *list, void*(*first)(UiList *list)) {
807 list->first = first; 903 list->first = first;
808 } 904 }
809 905
810 void ui_list_class_set_next(UiList *list, void*(*next)(UiList *list)) { 906 void ui_list_class_set_next(UiList *list, void*(*next)(UiList *list)) {

mercurial