| 250 return info; |
250 return info; |
| 251 } |
251 } |
| 252 |
252 |
| 253 #define UI_MODEL_DEFAULT_ALLOC_SIZE 16 |
253 #define UI_MODEL_DEFAULT_ALLOC_SIZE 16 |
| 254 |
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 |
| 255 UiModel* ui_model_new(UiContext *ctx) { |
264 UiModel* ui_model_new(UiContext *ctx) { |
| 256 UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel)); |
265 UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel)); |
| 257 info->ctx = ctx; |
266 info->ctx = ctx; |
| 258 info->alloc = UI_MODEL_DEFAULT_ALLOC_SIZE; |
267 info->alloc = UI_MODEL_DEFAULT_ALLOC_SIZE; |
| 259 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)); |
| 260 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*)); |
| 261 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)); |
| 262 return info; |
271 return info; |
| 263 } |
272 } |
| 264 |
273 |
| 265 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; |
| 266 if(model->columns >= model->alloc) { |
276 if(model->columns >= model->alloc) { |
| 267 model->alloc += UI_MODEL_DEFAULT_ALLOC_SIZE; |
277 model->alloc += UI_MODEL_DEFAULT_ALLOC_SIZE; |
| 268 model->types = ui_realloc(ctx, model->types, model->alloc * sizeof(UiModelType)); |
278 model->types = ui_realloc(ctx, model->types, model->alloc * sizeof(UiModelType)); |
| 269 model->titles = ui_realloc(ctx, model->titles, model->alloc * sizeof(char*)); |
279 model->titles = ui_realloc(ctx, model->titles, model->alloc * sizeof(char*)); |
| 270 model->columnsize = ui_realloc(ctx, model->columnsize, model->alloc * sizeof(int)); |
280 model->columnsize = ui_realloc(ctx, model->columnsize, model->alloc * sizeof(int)); |
| 271 } |
281 } |
| 272 model->types[model->columns] = type; |
282 int index = model->columns; |
| 273 model->titles[model->columns] = ui_strdup(ctx, title); |
283 model->types[index] = type; |
| 274 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 |
| 275 model->columns++; |
289 model->columns++; |
| 276 } |
290 } |
| 277 |
291 |
| 278 UiModel* ui_model_copy(UiContext *ctx, UiModel* model) { |
292 UiModel* ui_model_copy(UiContext *ctx, UiModel* model) { |
| 279 const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator; |
293 const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator; |
| 297 |
311 |
| 298 void ui_model_ref(UiModel *model) { |
312 void ui_model_ref(UiModel *model) { |
| 299 model->ref++; |
313 model->ref++; |
| 300 } |
314 } |
| 301 |
315 |
| 302 void ui_model_unref(UiModel *model) { |
316 void ui_model_unref(UiModel *model) { |
| 303 if(--model->ref == 0) { |
317 if(--model->ref == 0) { |
| 304 ui_model_free(model); |
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 } |
| 305 } |
358 } |
| 306 } |
359 } |
| 307 |
360 |
| 308 void ui_model_free(UiModel *mi) { |
361 void ui_model_free(UiModel *mi) { |
| 309 UiContext *ctx = mi->ctx; |
362 UiContext *ctx = mi->ctx; |
| 310 const CxAllocator* a = ctx->allocator; |
363 const CxAllocator* a = ctx->allocator; |
| 311 for(int i=0;i<mi->columns;i++) { |
364 for(int i=0;i<mi->columns;i++) { |
| 312 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; |
| 313 } |
372 } |
| 314 cxFree(a, mi->types); |
373 cxFree(a, mi->types); |
| 315 cxFree(a, mi->titles); |
374 cxFree(a, mi->titles); |
| 316 cxFree(a, mi->columnsize); |
375 cxFree(a, mi->columnsize); |
| 317 cxFree(a, mi); |
376 cxFree(a, mi); |