| 352 [combobox selectItemAtIndex:selection.rows[0]]; |
357 [combobox selectItemAtIndex:selection.rows[0]]; |
| 353 } else { |
358 } else { |
| 354 [combobox selectItemAtIndex: -1]; |
359 [combobox selectItemAtIndex: -1]; |
| 355 } |
360 } |
| 356 } |
361 } |
| |
362 |
| |
363 |
| |
364 /* --------------------------- SourceList --------------------------- */ |
| |
365 |
| |
366 static void sublist_free(const CxAllocator *a, UiSubList *sl) { |
| |
367 cxFree(a, (char*)sl->varname); |
| |
368 cxFree(a, (char*)sl->header); |
| |
369 } |
| |
370 |
| |
371 static UiSubList copy_sublist(const CxAllocator *a, UiSubList *sl) { |
| |
372 UiSubList new_sl; |
| |
373 new_sl.value = sl->value; |
| |
374 new_sl.varname = sl->varname ? cx_strdup_a(a, cx_str(sl->varname)).ptr : NULL; |
| |
375 new_sl.header = sl->header ? cx_strdup_a(a, cx_str(sl->header)).ptr : NULL; |
| |
376 new_sl.separator = sl->separator; |
| |
377 new_sl.userdata = sl->userdata; |
| |
378 return new_sl; |
| |
379 } |
| |
380 |
| |
381 static CxList* copy_sublists(const CxAllocator *a, UiSourceListArgs *args) { |
| |
382 if(args->sublists) { |
| |
383 size_t max = args->numsublists; |
| |
384 if(max == 0) { |
| |
385 max = INT_MAX; |
| |
386 } |
| |
387 |
| |
388 CxList *sublists = cxArrayListCreate(a, NULL, sizeof(UiSubList), args->numsublists); |
| |
389 sublists->collection.advanced_destructor = (cx_destructor_func2)sublist_free; |
| |
390 |
| |
391 for(int i=0;i<max;i++) { |
| |
392 UiSubList *sl = &args->sublists[i]; |
| |
393 if(sl->value == NULL && sl->varname == NULL) { |
| |
394 break; |
| |
395 } |
| |
396 |
| |
397 UiSubList new_sl = copy_sublist(a, sl); |
| |
398 cxListAdd(sublists, &new_sl); |
| |
399 } |
| |
400 |
| |
401 return sublists; |
| |
402 } |
| |
403 return NULL; |
| |
404 } |
| |
405 |
| |
406 UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs *args) { |
| |
407 // create views |
| |
408 NSScrollView *scrollview = [[NSScrollView alloc] init]; |
| |
409 scrollview.autoresizingMask = NSViewWidthSizable; |
| |
410 |
| |
411 NSOutlineView *outline = [[NSOutlineView alloc]init]; |
| |
412 NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:@"label"]; |
| |
413 [outline addTableColumn:column]; |
| |
414 outline.outlineTableColumn = column; |
| |
415 outline.headerView = NULL; |
| |
416 |
| |
417 outline.style = NSTableViewStyleSourceList; |
| |
418 |
| |
419 // Make background transparent so vibrancy shows through |
| |
420 outline.backgroundColor = [NSColor clearColor]; |
| |
421 scrollview.drawsBackground = NO; |
| |
422 |
| |
423 scrollview.documentView = outline; |
| |
424 |
| |
425 UiLayout layout = UI_ARGS2LAYOUT(args); |
| |
426 ui_container_add(obj, scrollview, &layout); |
| |
427 |
| |
428 // datasource and delegate |
| |
429 UiSourceList *data = [[UiSourceList alloc] init:obj]; |
| |
430 data.sublists = copy_sublists(obj->ctx->allocator, args); |
| |
431 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->dynamic_sublist, args->varname, UI_VAR_LIST); |
| |
432 if(var) { |
| |
433 UiList *list = var->value; |
| |
434 list->obj = (__bridge void*)data; |
| |
435 list->update = ui_sourcelist_update; |
| |
436 } |
| |
437 data.dynamic_sublists = var; |
| |
438 data.getvalue = args->getvalue; |
| |
439 data.getvaluedata = args->getvaluedata; |
| |
440 data.onactivate = args->onactivate; |
| |
441 data.onactivatedata = args->onactivatedata; |
| |
442 data.onbuttonclick = args->onbuttonclick; |
| |
443 data.onactivatedata = args->onbuttonclickdata; |
| |
444 [data update:-1]; |
| |
445 |
| |
446 outline.dataSource = data; |
| |
447 //outline.delegate = data; |
| |
448 |
| |
449 objc_setAssociatedObject(outline, "ui_datasource", data, OBJC_ASSOCIATION_RETAIN); |
| |
450 |
| |
451 return (__bridge void*)scrollview; |
| |
452 } |
| |
453 |
| |
454 void ui_sourcelist_update(UiList *list, int row) { |
| |
455 UiSourceList *sourcelist = (__bridge UiSourceList*)list->obj; |
| |
456 [sourcelist update:row]; |
| |
457 } |
| |
458 |
| |
459 |
| |
460 @implementation UiSourceList |
| |
461 |
| |
462 - (id)init:(UiObject*)obj { |
| |
463 _obj = obj; |
| |
464 _sections = [[NSMutableArray alloc] initWithCapacity:16]; |
| |
465 return self; |
| |
466 } |
| |
467 |
| |
468 - (void)dealloc { |
| |
469 cxListFree(_sublists); |
| |
470 } |
| |
471 |
| |
472 - (void)update:(int)row { |
| |
473 // TODO: check row |
| |
474 |
| |
475 [_sections removeAllObjects]; |
| |
476 |
| |
477 CxIterator i = cxListIterator(_sublists); |
| |
478 cx_foreach(UiSubList *, sl, i) { |
| |
479 UiSourceListItem *section = [[UiSourceListItem alloc] init:self sublist:sl]; |
| |
480 [section update:-1]; |
| |
481 [_sections addObject:section]; |
| |
482 } |
| |
483 } |
| |
484 |
| |
485 // NSOutlineViewDataSource implementation |
| |
486 |
| |
487 - (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item { |
| |
488 if(item == nil) { |
| |
489 return _sections.count; |
| |
490 } else { |
| |
491 UiSourceListItem *i = item; |
| |
492 return i.items.count; |
| |
493 } |
| |
494 } |
| |
495 |
| |
496 - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item { |
| |
497 UiSourceListItem *i = item; |
| |
498 return [i isSection]; |
| |
499 } |
| |
500 |
| |
501 - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item { |
| |
502 UiSourceListItem *i = item; |
| |
503 if(i) { |
| |
504 return [i.items objectAtIndex:index]; |
| |
505 } |
| |
506 return [_sections objectAtIndex:index]; |
| |
507 } |
| |
508 |
| |
509 - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { |
| |
510 UiSourceListItem *i = item; |
| |
511 if([[tableColumn identifier] isEqualToString:@"label"]) { |
| |
512 return i.label; |
| |
513 } |
| |
514 return nil; |
| |
515 } |
| |
516 |
| |
517 - (void)outlineView:(NSOutlineView *)outlineView |
| |
518 setObjectValue:(id)object |
| |
519 forTableColumn:(NSTableColumn *)tableColumn |
| |
520 byItem:(id)item { |
| |
521 |
| |
522 } |
| |
523 |
| |
524 @end |
| |
525 |
| |
526 @implementation UiSourceListItem |
| |
527 |
| |
528 - (id)init:(UiSourceList*)sourcelist sublist:(UiSubList*)sublist { |
| |
529 _sourcelist = sourcelist; |
| |
530 _sublist = sublist; |
| |
531 _items = [[NSMutableArray alloc]initWithCapacity:16]; |
| |
532 if(sublist->header) { |
| |
533 _label = [[NSString alloc]initWithUTF8String:sublist->header]; |
| |
534 } |
| |
535 UiVar *var = uic_widget_var(sourcelist.obj->ctx, |
| |
536 sourcelist.obj->ctx, |
| |
537 sublist->value, |
| |
538 sublist->varname, |
| |
539 UI_VAR_LIST); |
| |
540 _var = var; |
| |
541 return self; |
| |
542 } |
| |
543 |
| |
544 - (id)init:(UiSubListItem*)item { |
| |
545 if(item->label) { |
| |
546 _label = [[NSString alloc]initWithUTF8String:item->label]; |
| |
547 } |
| |
548 return self; |
| |
549 } |
| |
550 |
| |
551 - (BOOL)isSection { |
| |
552 return _sublist != NULL; |
| |
553 } |
| |
554 |
| |
555 - (void)update:(int)row { |
| |
556 [_items removeAllObjects]; |
| |
557 if(_var == NULL) { |
| |
558 return; |
| |
559 } |
| |
560 UiList *list = _var->value; |
| |
561 void *elm = list->first(list); |
| |
562 int index = 0; |
| |
563 while(elm) { |
| |
564 UiSubListItem item = { NULL, NULL, NULL, NULL, NULL, NULL }; |
| |
565 if(_sourcelist.getvalue) { |
| |
566 _sourcelist.getvalue(list, _sublist->userdata, elm, index, &item, _sourcelist.getvaluedata); |
| |
567 } else { |
| |
568 item.label = strdup(elm); |
| |
569 } |
| |
570 |
| |
571 [_items addObject:[[UiSourceListItem alloc] init:&item]]; |
| |
572 |
| |
573 elm = list->next(list); |
| |
574 index++; |
| |
575 } |
| |
576 } |
| |
577 |
| |
578 @end |
| |
579 |