97 list->next = ui_list_next; |
100 list->next = ui_list_next; |
98 list->get = ui_list_get; |
101 list->get = ui_list_get; |
99 list->count = ui_list_count; |
102 list->count = ui_list_count; |
100 list->observers = NULL; |
103 list->observers = NULL; |
101 |
104 |
102 list->data = NULL; |
105 list->data = cxArrayListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS, 32); |
103 list->iter = NULL; |
106 list->iter = NULL; |
104 |
107 |
105 list->update = NULL; |
108 list->update = NULL; |
|
109 list->getselection = NULL; |
106 list->obj = NULL; |
110 list->obj = NULL; |
107 |
111 |
108 if(name) { |
112 if(name) { |
109 uic_reg_var(ctx, name, UI_VAR_LIST, list); |
113 uic_reg_var(ctx, name, UI_VAR_LIST, list); |
110 } |
114 } |
111 |
115 |
112 return list; |
116 return list; |
113 } |
117 } |
114 |
118 |
115 void ui_list_free(UiList *list) { |
119 void ui_list_free(UiList *list) { |
116 ucx_list_free(list->data); |
120 cxListDestroy(list->data); |
117 free(list); |
121 free(list); |
118 } |
122 } |
119 |
123 |
120 void* ui_list_first(UiList *list) { |
124 void* ui_list_first(UiList *list) { |
121 UcxList *elm = list->data; |
125 list->iter = (void*)(intptr_t)0; |
122 list->iter = elm; |
126 return cxListAt(list->data, 0); |
123 return elm ? elm->data : NULL; |
|
124 } |
127 } |
125 |
128 |
126 void* ui_list_next(UiList *list) { |
129 void* ui_list_next(UiList *list) { |
127 UcxList *elm = list->iter; |
130 intptr_t iter = (intptr_t)list->iter; |
|
131 iter++; |
|
132 void *elm = cxListAt(list->data, iter); |
128 if(elm) { |
133 if(elm) { |
129 elm = elm->next; |
134 list->iter = (void*)iter; |
130 if(elm) { |
135 } |
131 list->iter = elm; |
136 return elm; |
132 return elm->data; |
|
133 } |
|
134 } |
|
135 return NULL; |
|
136 } |
137 } |
137 |
138 |
138 void* ui_list_get(UiList *list, int i) { |
139 void* ui_list_get(UiList *list, int i) { |
139 UcxList *elm = ucx_list_get(list->data, i); |
140 return cxListAt(list->data, i); |
140 if(elm) { |
|
141 list->iter = elm; |
|
142 return elm->data; |
|
143 } else { |
|
144 return NULL; |
|
145 } |
|
146 } |
141 } |
147 |
142 |
148 int ui_list_count(UiList *list) { |
143 int ui_list_count(UiList *list) { |
149 UcxList *elm = list->data; |
144 return cxListSize(list->data); |
150 return (int)ucx_list_size(elm); |
|
151 } |
145 } |
152 |
146 |
153 void ui_list_append(UiList *list, void *data) { |
147 void ui_list_append(UiList *list, void *data) { |
154 list->data = ucx_list_append(list->data, data); |
148 cxListAdd(list->data, data); |
155 } |
149 } |
156 |
150 |
157 void ui_list_prepend(UiList *list, void *data) { |
151 void ui_list_prepend(UiList *list, void *data) { |
158 list->data = ucx_list_prepend(list->data, data); |
152 cxListInsert(list->data, 0, data); |
|
153 } |
|
154 |
|
155 void ui_list_remove(UiList *list, int i) { |
|
156 cxListRemove(list->data, i); |
159 } |
157 } |
160 |
158 |
161 void ui_list_clear(UiList *list) { |
159 void ui_list_clear(UiList *list) { |
162 ucx_list_free(list->data); |
160 cxListClear(list->data); |
163 list->data = NULL; |
161 } |
|
162 |
|
163 UIEXPORT void ui_list_update(UiList *list) { |
|
164 if(list->update) { |
|
165 list->update(list, 0); |
|
166 } |
164 } |
167 } |
165 |
168 |
166 void ui_list_addobsv(UiList *list, ui_callback f, void *data) { |
169 void ui_list_addobsv(UiList *list, ui_callback f, void *data) { |
167 list->observers = ui_add_observer(list->observers, f, data); |
170 list->observers = ui_add_observer(list->observers, f, data); |
168 } |
171 } |
181 UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel)); |
184 UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel)); |
182 |
185 |
183 va_list ap; |
186 va_list ap; |
184 va_start(ap, ctx); |
187 va_start(ap, ctx); |
185 |
188 |
186 UcxList *cols = NULL; |
189 CxList *cols = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(UiColumn), 32); |
187 int type; |
190 int type; |
188 while((type = va_arg(ap, int)) != -1) { |
191 while((type = va_arg(ap, int)) != -1) { |
189 char *name = va_arg(ap, char*); |
192 char *name = va_arg(ap, char*); |
190 |
193 |
191 UiColumn *column = malloc(sizeof(UiColumn)); |
194 UiColumn column; |
192 column->type = type; |
195 column.type = type; |
193 column->name = name; |
196 column.name = name; |
194 |
197 |
195 cols = ucx_list_append(cols, column); |
198 cxListAdd(cols, &column); |
196 } |
199 } |
197 |
200 |
198 va_end(ap); |
201 va_end(ap); |
199 |
202 |
200 size_t len = ucx_list_size(cols); |
203 size_t len = cxListSize(cols); |
201 info->columns = len; |
204 info->columns = len; |
202 info->types = ui_calloc(ctx, len, sizeof(UiModelType)); |
205 info->types = ui_calloc(ctx, len, sizeof(UiModelType)); |
203 info->titles = ui_calloc(ctx, len, sizeof(char*)); |
206 info->titles = ui_calloc(ctx, len, sizeof(char*)); |
|
207 info->columnsize = ui_calloc(ctx, len, sizeof(int)); |
204 |
208 |
205 int i = 0; |
209 int i = 0; |
206 UCX_FOREACH(elm, cols) { |
210 CxIterator iter = cxListIterator(cols); |
207 UiColumn *c = elm->data; |
211 cx_foreach(UiColumn*, c, iter) { |
208 info->types[i] = c->type; |
212 info->types[i] = c->type; |
209 info->titles[i] = c->name; |
213 info->titles[i] = c->name; |
210 free(c); |
|
211 i++; |
214 i++; |
212 } |
215 } |
213 ucx_list_free(cols); |
216 cxListDestroy(cols); |
214 |
217 |
215 return info; |
218 return info; |
216 } |
219 } |
217 |
220 |
|
221 UiModel* ui_model_copy(UiContext *ctx, UiModel* model) { |
|
222 const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator; |
|
223 |
|
224 UiModel* newmodel = cxMalloc(a, sizeof(UiModel)); |
|
225 *newmodel = *model; |
|
226 |
|
227 newmodel->types = cxCalloc(a, model->columns, sizeof(UiModelType)); |
|
228 memcpy(newmodel->types, model->types, model->columns); |
|
229 |
|
230 newmodel->titles = cxCalloc(a, model->columns, sizeof(char*)); |
|
231 for (int i = 0; i < model->columns; i++) { |
|
232 newmodel->titles[i] = model->titles[i] ? cx_strdup_a(a, cx_str(model->titles[i])).ptr : NULL; |
|
233 } |
|
234 |
|
235 return newmodel; |
|
236 } |
|
237 |
218 void ui_model_free(UiContext *ctx, UiModel *mi) { |
238 void ui_model_free(UiContext *ctx, UiModel *mi) { |
219 ucx_mempool_free(ctx->mempool, mi->types); |
239 const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator; |
220 ucx_mempool_free(ctx->mempool, mi->titles); |
240 cxFree(a, mi->types); |
221 ucx_mempool_free(ctx->mempool, mi); |
241 cxFree(a, mi->titles); |
|
242 cxFree(a, mi); |
222 } |
243 } |
223 |
244 |
224 // types |
245 // types |
225 |
246 |
226 // public functions |
247 // public functions |
265 memset(r, 0, sizeof(UiRange)); |
286 memset(r, 0, sizeof(UiRange)); |
266 if(name) { |
287 if(name) { |
267 uic_reg_var(ctx, name, UI_VAR_RANGE, r); |
288 uic_reg_var(ctx, name, UI_VAR_RANGE, r); |
268 } |
289 } |
269 return r; |
290 return r; |
|
291 } |
|
292 |
|
293 UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, char *name) { |
|
294 UiGeneric *g = ui_malloc(ctx, sizeof(UiGeneric)); |
|
295 memset(g, 0, sizeof(UiGeneric)); |
|
296 if(name) { |
|
297 uic_reg_var(ctx, name, UI_VAR_GENERIC, g); |
|
298 } |
|
299 return g; |
|
300 } |
|
301 |
|
302 |
|
303 void ui_int_set(UiInteger* i, int64_t value) { |
|
304 if (i && i->set) { |
|
305 i->set(i, value); |
|
306 } |
|
307 } |
|
308 |
|
309 int64_t ui_int_get(UiInteger* i) { |
|
310 if (i) { |
|
311 return i->get ? i->get(i) : i->value; |
|
312 } else { |
|
313 return 0; |
|
314 } |
|
315 } |
|
316 |
|
317 void ui_double_set(UiDouble* d, double value) { |
|
318 if (d && d->set) { |
|
319 d->set(d, value); |
|
320 } |
|
321 } |
|
322 |
|
323 double ui_double_get(UiDouble* d) { |
|
324 if (d) { |
|
325 return d->get ? d->get(d) : d->value; |
|
326 } |
|
327 else { |
|
328 return 0; |
|
329 } |
|
330 } |
|
331 |
|
332 void ui_string_set(UiString* s, const char* value) { |
|
333 if (s && s->set) { |
|
334 s->set(s, value); |
|
335 } |
|
336 } |
|
337 |
|
338 char* ui_string_get(UiString* s) { |
|
339 if (s) { |
|
340 return s->get ? s->get(s) : s->value.ptr; |
|
341 } |
|
342 else { |
|
343 return 0; |
|
344 } |
|
345 } |
|
346 |
|
347 void ui_text_set(UiText* s, const char* value) { |
|
348 if (s && s->set) { |
|
349 s->set(s, value); |
|
350 } |
|
351 } |
|
352 |
|
353 char* ui_text_get(UiText* s) { |
|
354 if (s) { |
|
355 return s->get ? s->get(s) : s->value.ptr; |
|
356 } |
|
357 else { |
|
358 return 0; |
|
359 } |
270 } |
360 } |
271 |
361 |
272 |
362 |
273 // private functions |
363 // private functions |
274 void uic_int_copy(UiInteger *from, UiInteger *to) { |
364 void uic_int_copy(UiInteger *from, UiInteger *to) { |
387 |
488 |
388 void uic_list_unbind(UiList *l) { |
489 void uic_list_unbind(UiList *l) { |
389 l->update = NULL; |
490 l->update = NULL; |
390 l->obj = NULL; |
491 l->obj = NULL; |
391 } |
492 } |
|
493 |
|
494 void uic_generic_unbind(UiGeneric *g) { |
|
495 g->get = NULL; |
|
496 g->get_type = NULL; |
|
497 g->set = NULL; |
|
498 g->obj = NULL; |
|
499 } |
|
500 |
|
501 |
|
502 UIEXPORT UiListSelection ui_list_getselection(UiList *list) { |
|
503 if (list->getselection) { |
|
504 return list->getselection(list); |
|
505 } |
|
506 return (UiListSelection){ 0, NULL }; |
|
507 } |
|
508 |
|
509 UIEXPORT void ui_list_setselection(UiList *list, int index) { |
|
510 if (list->setselection && index >= 0) { |
|
511 UiListSelection sel; |
|
512 sel.count = 1; |
|
513 sel.rows = &index; |
|
514 list->setselection(list, sel); |
|
515 } |
|
516 } |
|
517 |
|
518 UIEXPORT void ui_listselection_free(UiListSelection selection) { |
|
519 if (selection.rows) { |
|
520 free(selection.rows); |
|
521 } |
|
522 } |
|
523 |
|
524 UIEXPORT UiStr ui_str(char *cstr) { |
|
525 return (UiStr) { cstr, NULL }; |
|
526 } |
|
527 |
|
528 UIEXPORT UiStr ui_str_free(char *str, void (*freefunc)(void *v)) { |
|
529 return (UiStr) { str, freefunc }; |
|
530 } |
|
531 |
|
532 |
|
533 UIEXPORT UiFileList ui_filelist_copy(UiFileList list) { |
|
534 char **newlist = calloc(sizeof(char*), list.nfiles); |
|
535 for (int i = 0; i < list.nfiles; i++) { |
|
536 newlist[i] = strdup(list.files[i]); |
|
537 } |
|
538 return (UiFileList) { newlist, list.nfiles }; |
|
539 } |
|
540 |
|
541 UIEXPORT void ui_filelist_free(UiFileList list) { |
|
542 for (int i = 0; i < list.nfiles; i++) { |
|
543 free(list.files[i]); |
|
544 } |
|
545 free(list.files); |
|
546 } |
|
547 |
|
548 |
|
549 typedef struct UiObserverDestructor { |
|
550 UiList *list; |
|
551 UiObserver *observer; |
|
552 } UiObserverDestructor; |
|
553 |
|
554 static void observer_destructor(UiObserverDestructor *destr) { |
|
555 UiObserver *remove_obs = destr->observer; |
|
556 UiObserver *obs = destr->list->observers; |
|
557 UiObserver *prev = NULL; |
|
558 while(obs) { |
|
559 if(obs == remove_obs) { |
|
560 if(prev) { |
|
561 prev->next = obs->next; |
|
562 } else { |
|
563 destr->list->observers = obs->next; |
|
564 } |
|
565 break; |
|
566 } |
|
567 prev = obs; |
|
568 obs = obs->next; |
|
569 } |
|
570 free(remove_obs); |
|
571 } |
|
572 |
|
573 void uic_list_register_observer_destructor(UiContext *ctx, UiList *list, UiObserver *observer) { |
|
574 CxMempool *mp = ctx->mp; |
|
575 UiObserverDestructor *destr = cxMalloc(mp->allocator, sizeof(UiObserverDestructor)); |
|
576 destr->list = list; |
|
577 destr->observer = observer; |
|
578 cxMempoolSetDestructor(destr, (cx_destructor_func)observer_destructor); |
|
579 } |