# HG changeset patch # User Olaf Wintermann # Date 1756020669 -7200 # Node ID 2082c80fb010c191650b959b547124df9127bf85 # Parent 3905f542e15021bfbc40e6bbb19a6d3b5c7dab00 add table widget (Cocoa) diff -r 3905f542e150 -r 2082c80fb010 make/xcode/toolkit/toolkit/main.m --- a/make/xcode/toolkit/toolkit/main.m Sat Aug 23 18:41:20 2025 +0200 +++ b/make/xcode/toolkit/toolkit/main.m Sun Aug 24 09:31:09 2025 +0200 @@ -77,6 +77,10 @@ printf("activate\n"); } +static void* table_getvalue(void *elm, int col) { + return elm; +} + void application_startup(UiEvent *event, void *data) { UiObject *obj = ui_window("My Window", NULL); //WindowData *wdata = ui_malloc(obj->ctx, sizeof(WindowData)); @@ -85,9 +89,10 @@ MyDocument *doc = create_doc(); ui_attach_document(obj->ctx, doc); + UiModel *model = ui_model(obj->ctx, UI_STRING, "Column 1", UI_STRING, "Column 2", UI_STRING, "Column 3", -1); ui_grid(obj, .columnspacing = 10, .rowspacing = 10) { - ui_listview(obj, .fill = UI_ON, .varname = "list1", .onactivate = action_list_activate, .onselection = action_list_selection, .multiselection = TRUE); + ui_table(obj, .fill = UI_ON, .varname = "list1", .model = model, .getvalue = table_getvalue, .onactivate = action_list_activate, .onselection = action_list_selection, .multiselection = TRUE); } diff -r 3905f542e150 -r 2082c80fb010 ui/cocoa/list.m --- a/ui/cocoa/list.m Sat Aug 23 18:41:20 2025 +0200 +++ b/ui/cocoa/list.m Sun Aug 24 09:31:09 2025 +0200 @@ -39,6 +39,31 @@ return elm; } +/* --------------------------- ListView --------------------------- */ + +/* + * adds a NSTableViewDelegate that handles all events and calls + * callbacks specified in the UiListArgs + */ +static void add_listdelegate(UiObject *obj, NSTableView *tableview, UiListArgs *args) { + ListDelegate *delegate = [[ListDelegate alloc] init:tableview obj:obj]; + delegate.onactivate = args->onactivate; + delegate.onactivatedata = args->onactivatedata; + delegate.onselection = args->onselection; + delegate.onselectiondata = args->onselectiondata; + tableview.delegate = delegate; + objc_setAssociatedObject(tableview, "ui_listdelegate", delegate, OBJC_ASSOCIATION_RETAIN); + tableview.doubleAction = @selector(activateEvent:); + tableview.target = delegate; +} + +static void bind_list_to_tableview(UiList *list, NSTableView *tableview) { + list->obj = (__bridge void*)tableview; + list->update = ui_tableview_update; + list->getselection = ui_tableview_getselection; + list->setselection = ui_tableview_setselection; +} + UIWIDGET ui_listview_create(UiObject* obj, UiListArgs *args) { NSScrollView *scrollview = [[NSScrollView alloc] init]; @@ -55,23 +80,12 @@ UiLayout layout = UI_INIT_LAYOUT(args); ui_container_add(obj, scrollview, &layout, TRUE); - ListDelegate *delegate = [[ListDelegate alloc] init:tableview obj:obj]; - delegate.onactivate = args->onactivate; - delegate.onactivatedata = args->onactivatedata; - delegate.onselection = args->onselection; - delegate.onselectiondata = args->onselectiondata; - tableview.delegate = delegate; - objc_setAssociatedObject(tableview, "ui_listdelegate", delegate, OBJC_ASSOCIATION_RETAIN); - tableview.doubleAction = @selector(activateEvent:); - tableview.target = delegate; + add_listdelegate(obj, tableview, args); UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); if(var) { UiList *list = var->value; - list->obj = (__bridge void*)tableview; - list->update = ui_tableview_update; - list->getselection = ui_tableview_getselection; - list->setselection = ui_tableview_setselection; + bind_list_to_tableview(list, tableview); ui_getvaluefunc2 getvalue = args->getvalue2; void *getvaluedata = args->getvalue2data; @@ -85,7 +99,6 @@ } NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:@"column"]; - column.width = 400; [tableview addTableColumn:column]; ListDataSource *dataSource = [[ListDataSource alloc] init:tableview.tableColumns var:var getvalue:getvalue getvaluedata:getvaluedata]; @@ -99,6 +112,80 @@ return (__bridge void*)scrollview; } +/* --------------------------- TableView --------------------------- */ + +UIWIDGET ui_table_create(UiObject* obj, UiListArgs *args) { + NSScrollView *scrollview = [[NSScrollView alloc] init]; + + NSTableView *tableview = [[NSTableView alloc] init]; + tableview.autoresizingMask = NSViewWidthSizable; + + if(args->multiselection) { + tableview.allowsMultipleSelection = YES; + } + + UiLayout layout = UI_INIT_LAYOUT(args); + ui_container_add(obj, scrollview, &layout, TRUE); + + add_listdelegate(obj, tableview, args); + + // convert model + NSMutableArray *cols = [[NSMutableArray alloc] init]; + UiModel *model = args->model; + if(model) { + for(int i=0;icolumns;i++) { + char *title = model->titles[i]; + UiModelType type = model->types[i]; + int width = model->columnsize[i]; + NSString *identifier = [[NSString alloc] initWithUTF8String:title]; + NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:identifier]; + column.title = identifier; + if(width > 0) { + column.width = width; + } + if(type >= UI_ICON) { + // TODO + } + [tableview addTableColumn:column]; + [cols addObject:column]; + } + } + + UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); + if(var) { + UiList *list = var->value; + bind_list_to_tableview(list, tableview); + + ui_getvaluefunc2 getvalue = args->getvalue2; + void *getvaluedata = args->getvalue2data; + if(!getvalue) { + if(args->getvalue) { + getvalue = getvalue_wrapper; + getvaluedata = (void*)args->getvalue; + } else { + fprintf(stderr, "Error: tableview requires getvalue or getvalue2 func\n"); + return (__bridge void*)scrollview; + } + } + + ListDataSource *dataSource = [[ListDataSource alloc] init:cols var:var getvalue:getvalue getvaluedata:getvaluedata]; + if(model) { + dataSource.model = ui_model_copy(obj->ctx, model); + } + + tableview.dataSource = dataSource; + [tableview reloadData]; + + objc_setAssociatedObject(tableview, "ui_datasource", dataSource, OBJC_ASSOCIATION_RETAIN); + } + + scrollview.documentView = tableview; + + return (__bridge void*)scrollview; +} + +/* ------ common functions ------ */ + void ui_tableview_update(UiList *list, int i) { NSTableView *tableview = (__bridge NSTableView*)list->obj; if(i < 0) { @@ -121,3 +208,5 @@ } [tableview selectRowIndexes:indexSet byExtendingSelection:NO]; } + + diff -r 3905f542e150 -r 2082c80fb010 ui/ui/tree.h --- a/ui/ui/tree.h Sat Aug 23 18:41:20 2025 +0200 +++ b/ui/ui/tree.h Sun Aug 24 09:31:09 2025 +0200 @@ -256,6 +256,15 @@ #define UI_SUBLISTS(...) (UiSubList[]){ __VA_ARGS__, (UiSubList){NULL,NULL,NULL,0} } +/* + * Creates an UiModel, that specifies columns for a table widget. + * + * For each column a column type (UiModelType) and a title string + * (char*) must be specified. The column list must be terminated + * with -1. + * + * UiModel *model = ui_model(ctx, UI_STRING, "Column 1", UI_STRING, "Column 2", -1); + */ UIEXPORT UiModel* ui_model(UiContext *ctx, ...); UIEXPORT UiModel* ui_model_copy(UiContext *ctx, UiModel* model); UIEXPORT void ui_model_free(UiContext *ctx, UiModel *mi);