1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdarg.h>
33
34 #include <cx/list.h>
35 #include <cx/array_list.h>
36 #include "../ui/tree.h"
37 #include "types.h"
38 #include "context.h"
39
40
41
42 UiObserver* ui_observer_new(ui_callback f,
void *data) {
43 UiObserver *observer = malloc(
sizeof(UiObserver));
44 observer->callback = f;
45 observer->data = data;
46 observer->next =
NULL;
47 return observer;
48 }
49
50 UiObserver* ui_obsvlist_add(UiObserver *list, UiObserver *observer) {
51 if(!list) {
52 return observer;
53 }
else {
54 UiObserver *l = list;
55 while(l->next) {
56 l = l->next;
57 }
58 l->next = observer;
59 return list;
60 }
61 }
62
63 UiObserver* ui_add_observer(UiObserver *list, ui_callback f,
void *data) {
64 UiObserver *observer = ui_observer_new(f, data);
65 return ui_obsvlist_add(list, observer);
66 }
67
68 void ui_notify(UiObserver *observer,
void *data) {
69 ui_notify_except(observer,
NULL, data);
70 }
71
72 void ui_notify_except(UiObserver *observer, UiObserver *exc,
void *data) {
73 UiEvent evt;
74 evt.obj =
NULL;
75 evt.window =
NULL;
76 evt.document =
NULL;
77 evt.eventdata = data;
78 evt.intval =
0;
79
80 while(observer) {
81 if(observer != exc) {
82 observer->callback(&evt, observer->data);
83 }
84 observer = observer->next;
85 }
86 }
87
88 void ui_notify_evt(UiObserver *observer, UiEvent *event) {
89 while(observer) {
90 observer->callback(event, observer->data);
91 observer = observer->next;
92 }
93 }
94
95
96
97 UiList* ui_list_new(UiContext *ctx,
char *name) {
98 UiList *list = malloc(
sizeof(UiList));
99 list->first = ui_list_first;
100 list->next = ui_list_next;
101 list->get = ui_list_get;
102 list->count = ui_list_count;
103 list->observers =
NULL;
104
105 list->data = cxArrayListCreate(cxDefaultAllocator,
NULL,
CX_STORE_POINTERS,
32);
106 list->iter =
NULL;
107
108 list->update =
NULL;
109 list->getselection =
NULL;
110 list->obj =
NULL;
111
112 if(name) {
113 uic_reg_var(ctx, name,
UI_VAR_LIST, list);
114 }
115
116 return list;
117 }
118
119 void ui_list_free(UiList *list) {
120 cxListDestroy(list->data);
121 free(list);
122 }
123
124 void* ui_list_first(UiList *list) {
125 list->iter = (
void*)(
intptr_t)
0;
126 return cxListAt(list->data,
0);
127 }
128
129 void* ui_list_next(UiList *list) {
130 intptr_t iter = (
intptr_t)list->iter;
131 iter++;
132 void *elm = cxListAt(list->data, iter);
133 if(elm) {
134 list->iter = (
void*)iter;
135 }
136 return elm;
137 }
138
139 void* ui_list_get(UiList *list,
int i) {
140 return cxListAt(list->data, i);
141 }
142
143 int ui_list_count(UiList *list) {
144 return cxListSize(list->data);
145 }
146
147 void ui_list_append(UiList *list,
void *data) {
148 cxListAdd(list->data, data);
149 }
150
151 void ui_list_prepend(UiList *list,
void *data) {
152 cxListInsert(list->data,
0, data);
153 }
154
155 void ui_list_remove(UiList *list,
int i) {
156 cxListRemove(list->data, i);
157 }
158
159 void ui_list_clear(UiList *list) {
160 cxListClear(list->data);
161 }
162
163 UIEXPORT void ui_list_update(UiList *list) {
164 if(list->update) {
165 list->update(list,
0);
166 }
167 }
168
169 void ui_list_addobsv(UiList *list, ui_callback f,
void *data) {
170 list->observers = ui_add_observer(list->observers, f, data);
171 }
172
173 void ui_list_notify(UiList *list) {
174 ui_notify(list->observers, list);
175 }
176
177
178 typedef struct {
179 int type;
180 char *name;
181 } UiColumn;
182
183 UiModel* ui_model(UiContext *ctx, ...) {
184 UiModel *info = ui_calloc(ctx,
1,
sizeof(UiModel));
185
186 va_list ap;
187 va_start(ap, ctx);
188
189 CxList *cols = cxArrayListCreate(cxDefaultAllocator,
NULL,
sizeof(UiColumn),
32);
190 int type;
191 while((type = va_arg(ap,
int)) != -
1) {
192 char *name = va_arg(ap,
char*);
193
194 UiColumn column;
195 column.type = type;
196 column.name = name;
197
198 cxListAdd(cols, &column);
199 }
200
201 va_end(ap);
202
203 size_t len = cxListSize(cols);
204 info->columns = len;
205 info->types = ui_calloc(ctx, len,
sizeof(UiModelType));
206 info->titles = ui_calloc(ctx, len,
sizeof(
char*));
207 info->columnsize = ui_calloc(ctx, len,
sizeof(
int));
208
209 int i =
0;
210 CxIterator iter = cxListIterator(cols);
211 cx_foreach(UiColumn*, c, iter) {
212 info->types[i] = c->type;
213 info->titles[i] = c->name;
214 i++;
215 }
216 cxListDestroy(cols);
217
218 return info;
219 }
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
238 void ui_model_free(UiContext *ctx, UiModel *mi) {
239 const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator;
240 cxFree(a, mi->types);
241 cxFree(a, mi->titles);
242 cxFree(a, mi);
243 }
244
245
246
247
248 UiInteger* ui_int_new(UiContext *ctx,
char *name) {
249 UiInteger *i = ui_malloc(ctx,
sizeof(UiInteger));
250 memset(i,
0,
sizeof(UiInteger));
251 if(name) {
252 uic_reg_var(ctx, name,
UI_VAR_INTEGER, i);
253 }
254 return i;
255 }
256
257 UiDouble* ui_double_new(UiContext *ctx,
char *name) {
258 UiDouble *d = ui_malloc(ctx,
sizeof(UiDouble));
259 memset(d,
0,
sizeof(UiDouble));
260 if(name) {
261 uic_reg_var(ctx, name,
UI_VAR_DOUBLE, d);
262 }
263 return d;
264 }
265
266 UiString* ui_string_new(UiContext *ctx,
char *name) {
267 UiString *s = ui_malloc(ctx,
sizeof(UiString));
268 memset(s,
0,
sizeof(UiString));
269 if(name) {
270 uic_reg_var(ctx, name,
UI_VAR_STRING, s);
271 }
272 return s;
273 }
274
275 UiText* ui_text_new(UiContext *ctx,
char *name) {
276 UiText *t = ui_malloc(ctx,
sizeof(UiText));
277 memset(t,
0,
sizeof(UiText));
278 if(name) {
279 uic_reg_var(ctx, name,
UI_VAR_TEXT, t);
280 }
281 return t;
282 }
283
284 UiRange* ui_range_new(UiContext *ctx,
char *name) {
285 UiRange *r = ui_malloc(ctx,
sizeof(UiRange));
286 memset(r,
0,
sizeof(UiRange));
287 if(name) {
288 uic_reg_var(ctx, name,
UI_VAR_RANGE, r);
289 }
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 }
360 }
361
362
363
364 void uic_int_copy(UiInteger *from, UiInteger *to) {
365 to->get = from->get;
366 to->set = from->set;
367 to->obj = from->obj;
368 }
369
370 void uic_double_copy(UiDouble *from, UiDouble *to) {
371 to->get = from->get;
372 to->set = from->set;
373 to->obj = from->obj;
374 }
375
376 void uic_string_copy(UiString *from, UiString *to) {
377 to->get = from->get;
378 to->set = from->set;
379 to->obj = from->obj;
380 }
381
382 void uic_text_copy(UiText *from, UiText *to) {
383 to->get = from->get;
384 to->set = from->set;
385 to->getsubstr = from->getsubstr;
386 to->insert = from->insert;
387 to->setposition = from->setposition;
388 to->position = from->position;
389 to->selection = from->selection;
390 to->length = from->length;
391 to->remove = from->remove;
392
393 to->obj = from->obj;
394
395 }
396
397 void uic_range_copy(UiRange *from, UiRange *to) {
398 to->get = from->get;
399 to->set = from->set;
400 to->setrange = from->setrange;
401 to->setextent = from->setextent;
402 to->obj = from->obj;
403 }
404
405 void uic_list_copy(UiList *from, UiList *to) {
406 to->update = from->update;
407 to->obj = from->obj;
408 }
409
410 void uic_generic_copy(UiGeneric *from, UiGeneric *to) {
411 to->get = from->get;
412 to->get_type = from->get_type;
413 to->set = from->set;
414 to->obj = from->obj;
415 }
416
417 void uic_int_save(UiInteger *i) {
418 if(!i->obj)
return;
419 i->value = i->get(i);
420 }
421
422 void uic_double_save(UiDouble *d) {
423 if(!d->obj)
return;
424 d->value = d->get(d);
425 }
426
427 void uic_string_save(UiString *s) {
428 if(!s->obj)
return;
429 s->get(s);
430 }
431
432 void uic_text_save(UiText *t) {
433 if(!t->obj)
return;
434 t->get(t);
435 t->position(t);
436 }
437
438 void uic_range_save(UiRange *r) {
439 if(!r->obj)
return;
440 r->get(r);
441 }
442
443 void uic_generic_save(UiGeneric *g) {
444 if(!g->obj)
return;
445 g->get(g);
446 }
447
448
449 void uic_int_unbind(UiInteger *i) {
450 i->get =
NULL;
451 i->set =
NULL;
452 i->obj =
NULL;
453 }
454
455 void uic_double_unbind(UiDouble *d) {
456 d->get =
NULL;
457 d->set =
NULL;
458 d->obj =
NULL;
459 }
460
461 void uic_string_unbind(UiString *s) {
462 s->get =
NULL;
463 s->set =
NULL;
464 s->obj =
NULL;
465 }
466
467 void uic_text_unbind(UiText *t) {
468 t->set =
NULL;
469 t->get =
NULL;
470 t->getsubstr =
NULL;
471 t->insert =
NULL;
472 t->setposition =
NULL;
473 t->position =
NULL;
474 t->selection =
NULL;
475 t->length =
NULL;
476 t->remove =
NULL;
477 t->obj =
NULL;
478 t->undomgr =
NULL;
479 }
480
481 void uic_range_unbind(UiRange *r) {
482 r->get =
NULL;
483 r->set =
NULL;
484 r->setextent =
NULL;
485 r->setrange =
NULL;
486 r->obj =
NULL;
487 }
488
489 void uic_list_unbind(UiList *l) {
490 l->update =
NULL;
491 l->obj =
NULL;
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 }
580