add minimally working listview (Cocoa)

Sat, 23 Aug 2025 17:45:15 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 23 Aug 2025 17:45:15 +0200
changeset 711
673e7e41c93e
parent 710
6c7f700e4900
child 712
9693f447a0c7

add minimally working listview (Cocoa)

make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj file | annotate | diff | comparison | revisions
make/xcode/toolkit/toolkit/main.m file | annotate | diff | comparison | revisions
ui/cocoa/ListDataSource.h file | annotate | diff | comparison | revisions
ui/cocoa/ListDataSource.m file | annotate | diff | comparison | revisions
ui/cocoa/ListDelegate.h file | annotate | diff | comparison | revisions
ui/cocoa/ListDelegate.m file | annotate | diff | comparison | revisions
ui/cocoa/list.h file | annotate | diff | comparison | revisions
ui/cocoa/list.m file | annotate | diff | comparison | revisions
--- a/make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj	Sat Aug 23 14:24:09 2025 +0200
+++ b/make/xcode/toolkit/toolkit.xcodeproj/project.pbxproj	Sat Aug 23 17:45:15 2025 +0200
@@ -46,6 +46,9 @@
 		ED65815F2CFF4BF200F5402F /* WindowManager.m in Sources */ = {isa = PBXBuildFile; fileRef = ED65815E2CFF4BF200F5402F /* WindowManager.m */; };
 		ED8687E52D999CF3002F3EC2 /* menu.m in Sources */ = {isa = PBXBuildFile; fileRef = ED8687E42D999CF3002F3EC2 /* menu.m */; };
 		EDB452C32E302C65006FB12D /* image.m in Sources */ = {isa = PBXBuildFile; fileRef = EDB452C22E302C65006FB12D /* image.m */; };
+		EDCD22272E59EEF5000612AF /* list.m in Sources */ = {isa = PBXBuildFile; fileRef = EDCD22262E59EEF5000612AF /* list.m */; };
+		EDCD22352E59F3B1000612AF /* ListDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = EDCD22342E59F3B1000612AF /* ListDataSource.m */; };
+		EDCD22382E5A160A000612AF /* ListDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EDCD22372E5A160A000612AF /* ListDelegate.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
@@ -149,6 +152,12 @@
 		ED8687E42D999CF3002F3EC2 /* menu.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = menu.m; path = ../../../ui/cocoa/menu.m; sourceTree = SOURCE_ROOT; };
 		EDB452C12E302C65006FB12D /* image.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = image.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/image.h; sourceTree = "<absolute>"; };
 		EDB452C22E302C65006FB12D /* image.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = image.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/image.m; sourceTree = "<absolute>"; };
+		EDCD22252E59EEF5000612AF /* list.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = list.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/list.h; sourceTree = "<absolute>"; };
+		EDCD22262E59EEF5000612AF /* list.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = list.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/list.m; sourceTree = "<absolute>"; };
+		EDCD22332E59F3B1000612AF /* ListDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ListDataSource.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/ListDataSource.h; sourceTree = "<absolute>"; };
+		EDCD22342E59F3B1000612AF /* ListDataSource.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ListDataSource.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/ListDataSource.m; sourceTree = "<absolute>"; };
+		EDCD22362E5A160A000612AF /* ListDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ListDelegate.h; path = /Users/olaf/Projekte/toolkit/ui/cocoa/ListDelegate.h; sourceTree = "<absolute>"; };
+		EDCD22372E5A160A000612AF /* ListDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ListDelegate.m; path = /Users/olaf/Projekte/toolkit/ui/cocoa/ListDelegate.m; sourceTree = "<absolute>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFileSystemSynchronizedRootGroup section */
@@ -269,6 +278,12 @@
 		ED65812E2CFF1A7200F5402F /* cocoa */ = {
 			isa = PBXGroup;
 			children = (
+				EDCD22362E5A160A000612AF /* ListDelegate.h */,
+				EDCD22372E5A160A000612AF /* ListDelegate.m */,
+				EDCD22332E59F3B1000612AF /* ListDataSource.h */,
+				EDCD22342E59F3B1000612AF /* ListDataSource.m */,
+				EDCD22252E59EEF5000612AF /* list.h */,
+				EDCD22262E59EEF5000612AF /* list.m */,
 				ED2F55AC2E34FAD800A84793 /* Toolbar.h */,
 				ED2F55AD2E34FAD800A84793 /* Toolbar.m */,
 				EDB452C12E302C65006FB12D /* image.h */,
@@ -402,9 +417,11 @@
 			files = (
 				ED6580EE2CFF19F900F5402F /* context.c in Sources */,
 				ED6580EF2CFF19F900F5402F /* menu.c in Sources */,
+				EDCD22352E59F3B1000612AF /* ListDataSource.m in Sources */,
 				ED6580F02CFF19F900F5402F /* threadpool.c in Sources */,
 				EDB452C32E302C65006FB12D /* image.m in Sources */,
 				ED6580F12CFF19F900F5402F /* condvar.c in Sources */,
+				EDCD22272E59EEF5000612AF /* list.m in Sources */,
 				ED65815F2CFF4BF200F5402F /* WindowManager.m in Sources */,
 				ED6580F22CFF19F900F5402F /* document.c in Sources */,
 				ED65811D2CFF1A3000F5402F /* linked_list.c in Sources */,
@@ -437,6 +454,7 @@
 				ED6580F52CFF19F900F5402F /* types.c in Sources */,
 				ED8687E52D999CF3002F3EC2 /* menu.m in Sources */,
 				ED6580F62CFF19F900F5402F /* properties.c in Sources */,
+				EDCD22382E5A160A000612AF /* ListDelegate.m in Sources */,
 				ED6580F72CFF19F900F5402F /* ucx_properties.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
--- a/make/xcode/toolkit/toolkit/main.m	Sat Aug 23 14:24:09 2025 +0200
+++ b/make/xcode/toolkit/toolkit/main.m	Sat Aug 23 17:45:15 2025 +0200
@@ -36,12 +36,18 @@
 
 typedef struct MyDocument {
     UiInteger *tbtoggle;
+    UiList *list1;
 } MyDocument;
 
 MyDocument* create_doc(void) {
     MyDocument *doc = ui_document_new(sizeof(MyDocument));
     UiContext *ctx = ui_document_context(doc);
     doc->tbtoggle = ui_int_new(ctx, "tbtoggle");
+    doc->list1 = ui_list_new(ctx, "list1");
+    ui_list_append(doc->list1, "Item 1");
+    ui_list_append(doc->list1, "Item 2");
+    ui_list_append(doc->list1, "Item 3");
+    ui_list_append(doc->list1, "Item 4");
     return doc;
 }
 
@@ -63,6 +69,14 @@
     printf("menuitem\n");
 }
 
+static void action_list_selection(UiEvent *event, void *userdata) {
+    printf("selection\n");
+}
+
+static void action_list_activate(UiEvent *event, void *userdata) {
+    printf("activate\n");
+}
+
 void application_startup(UiEvent *event, void *data) {
     UiObject *obj = ui_window("My Window", NULL);
     //WindowData *wdata = ui_malloc(obj->ctx, sizeof(WindowData));
@@ -73,7 +87,7 @@
     
     
     ui_grid(obj, .columnspacing = 10, .rowspacing = 10) {
-        ui_textarea(obj, .fill = UI_ON);
+        ui_listview(obj, .fill = UI_ON, .varname = "list1", .onactivate = action_list_activate, .onselection = action_list_selection);
     }
     
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/ListDataSource.h	Sat Aug 23 17:45:15 2025 +0200
@@ -0,0 +1,42 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+#import "../ui/tree.h"
+
+@interface ListDataSource : NSObject <NSTableViewDataSource>
+
+@property NSArray<NSTableColumn*> *columns;
+@property UiVar *var;
+@property ui_getvaluefunc2 getvalue;
+@property void *getvaluedata;
+@property UiModel *model;
+
+- (id) init:(NSArray<NSTableColumn*>*) columns var:(UiVar*)var getvalue:(ui_getvaluefunc2) getvaluefunc getvaluedata:(void*)userdata;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/ListDataSource.m	Sat Aug 23 17:45:15 2025 +0200
@@ -0,0 +1,110 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "ListDataSource.h"
+
+@implementation ListDataSource
+
+- (id) init:(NSArray<NSTableColumn*>*) columns var:(UiVar*)var getvalue:(ui_getvaluefunc2) getvaluefunc getvaluedata:(void*)userdata {
+    _columns = columns;
+    _var = var;
+    _getvalue = getvaluefunc;
+    _getvaluedata = userdata;
+    return self;
+}
+
+- (NSInteger) numberOfRowsInTableView:(NSTableView *) tableView {
+    if(_var) {
+        UiList *list = _var->value;
+        if(list->count) {
+            return list->count(list);
+        }
+    }
+    return 0;
+}
+
+- (id) tableView:(NSTableView *) tableView
+objectValueForTableColumn:(NSTableColumn *) tableColumn
+             row:(NSInteger) row
+{
+    id ret = nil;
+    UiList *list = _var->value;
+    void *elm = list->get(list, (int)row);
+    if(elm) {
+        // get column index
+        NSUInteger colIndex = [_columns indexOfObject:tableColumn];
+        if(colIndex == NSNotFound) {
+            return nil;
+        }
+        
+        // get UI model type for this column
+        UiModelType type = UI_STRING;
+        UiModel *model = _model;
+        if(model) {
+            if(colIndex >= model->columns) {
+                return nil;
+            }
+            type = model->types[colIndex];
+        }
+        
+        // convert the list element
+        UiBool freeResult = FALSE;
+        void *data = _getvalue(list, elm, (int)row, (int)colIndex, _getvaluedata, &freeResult);
+        
+        switch(type) {
+            case UI_STRING: {
+                ret = [[NSString alloc] initWithUTF8String:data];
+                break;
+            }
+            case UI_STRING_FREE: {
+                ret = [[NSString alloc] initWithUTF8String:data];
+                freeResult = TRUE;
+                break;
+            }
+            case UI_INTEGER: {
+                break;
+            }
+            case UI_ICON: {
+                break;
+            }
+            case UI_ICON_TEXT: {
+                break;
+            }
+            case UI_ICON_TEXT_FREE: {
+                break;
+            }
+        }
+        
+        if(freeResult) {
+            free(data);
+        }
+    }
+    return ret;
+}
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/ListDelegate.h	Sat Aug 23 17:45:15 2025 +0200
@@ -0,0 +1,43 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+
+@interface ListDelegate : NSObject <NSTableViewDelegate>
+
+@property UiObject    *obj;
+@property ui_callback onselection;
+@property void        *onselectiondata;
+@property ui_callback onactivate;
+@property void        *onactivatedata;
+
+- (id)init:(UiObject*)obj;
+
+- (void)activateEvent:(id)sender;
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/ListDelegate.m	Sat Aug 23 17:45:15 2025 +0200
@@ -0,0 +1,60 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "ListDelegate.h"
+
+@implementation ListDelegate
+
+- (id)init:(UiObject*)obj {
+    _obj = obj;
+    return self;
+}
+
+- (void)activateEvent:(id)sender {
+    NSTableView *table = sender;
+    if(_onactivate) {
+        int row = (int)table.clickedRow;
+        
+        UiListSelection sel;
+        sel.count = 1;
+        sel.rows = &row;
+        
+        UiEvent  event;
+        event.obj = _obj;
+        event.window = event.obj->window;
+        event.document = event.obj->ctx->document;
+        event.eventdata = &sel;
+        event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION;
+        event.intval = row;
+        event.set = ui_get_setop();
+        
+        _onactivate(&event, _onactivatedata);
+    }
+}
+
+@end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/list.h	Sat Aug 23 17:45:15 2025 +0200
@@ -0,0 +1,33 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "toolkit.h"
+#import "container.h"
+#import "../ui/tree.h"
+
+#import "ListDataSource.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/cocoa/list.m	Sat Aug 23 17:45:15 2025 +0200
@@ -0,0 +1,90 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "list.h"
+#import "ListDelegate.h"
+#import <objc/runtime.h>
+
+static void* getvalue_wrapper(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
+    ui_getvaluefunc getvalue = (ui_getvaluefunc)userdata;
+    return getvalue(elm, col);
+}
+
+static void* str_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
+    return elm;
+}
+
+UIWIDGET ui_listview_create(UiObject* obj, UiListArgs *args) {
+    NSScrollView *scrollview = [[NSScrollView alloc] init];
+    
+    NSTableView *tableview = [[NSTableView alloc] init];
+    tableview.autoresizingMask = NSViewWidthSizable;
+    tableview.headerView = nil;
+    
+    scrollview.documentView = tableview;
+    
+    UiLayout layout = UI_INIT_LAYOUT(args);
+    ui_container_add(obj, scrollview, &layout, TRUE);
+    
+    UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
+    if(var) {
+        ui_getvaluefunc2 getvalue = args->getvalue2;
+        void *getvaluedata = args->getvalue2data;
+        if(!getvalue) {
+            if(args->getvalue) {
+                getvalue = getvalue_wrapper;
+                getvaluedata = (void*)args->getvalue;
+            } else {
+                getvalue = str_getvalue; // by default list values are interpreted as strings
+            }
+        }
+        
+        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];
+        
+        tableview.dataSource = dataSource;
+        [tableview reloadData];
+        
+        objc_setAssociatedObject(tableview, "ui_datasource", dataSource, OBJC_ASSOCIATION_RETAIN);
+    }
+    
+    ListDelegate *delegate = [[ListDelegate alloc] init: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;
+    
+    return (__bridge void*)scrollview;
+}

mercurial