diff -r 7b3a3130be44 -r 64ded9f6a6c6 ui/gtk/list.c
--- a/ui/gtk/list.c	Mon Jan 06 22:22:55 2025 +0100
+++ b/ui/gtk/list.c	Tue Feb 25 21:11:00 2025 +0100
@@ -388,6 +388,13 @@
         GtkColumnViewColumn *column = gtk_column_view_column_new(model->titles[i], factory);
         gtk_column_view_column_set_resizable(column, true);
         gtk_column_view_append_column(GTK_COLUMN_VIEW(view), column);
+        
+        int size = model->columnsize[i];
+        if(size > 0) {
+            gtk_column_view_column_set_fixed_width(column, size);
+        } else if(size < 0) {
+            gtk_column_view_column_set_expand(column, TRUE);
+        }
     }
     
     // bind listview to list
@@ -447,13 +454,7 @@
     }
 }
 
-void ui_columnview_activate(void *ignore, guint position, gpointer userdata) {
-    UiListView *view = userdata;
-    listview_event(view->onactivate, view->onactivatedata, view);
-}
-
-void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) {
-    UiListView *view = userdata;
+static void listview_update_selection(UiListView *view) {
     free(view->selection.rows);
     view->selection.count = 0;
     view->selection.rows = NULL;
@@ -476,7 +477,19 @@
     } else {
         free(newselection);
     }
+}
     
+void ui_columnview_activate(void *ignore, guint position, gpointer userdata) {
+    UiListView *view = userdata;
+    if(view->selection.count == 0) {
+        listview_update_selection(view);
+    }
+    listview_event(view->onactivate, view->onactivatedata, view);
+}
+
+void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) {
+    UiListView *view = userdata;
+    listview_update_selection(view);
     listview_event(view->onselection, view->onselectiondata, view);
 }
 
@@ -513,7 +526,7 @@
 
 void ui_listview_update2(UiList *list, int i) {
     UiListView *view = list->obj;
-    ui_update_liststore(view->liststore, view->var->value);
+    ui_update_liststore(view->liststore, list);
 }
 
 UiListSelection ui_listview_getselection2(UiList *list) {
@@ -614,8 +627,8 @@
                     }
                     case UI_INTEGER: {
                         g_value_init(&value, G_TYPE_INT);
-                        int *intptr = data;
-                        g_value_set_int(&value, *intptr);
+                        intptr_t intptr = (intptr_t)data;
+                        g_value_set_int(&value, (int)intptr);
                         break;
                     }
                     case UI_ICON: {
@@ -1559,6 +1572,34 @@
 }
 #endif
 
+
+static void add_sublist(UiListBox *uilistbox, CxList *sublists, UiSubList *sublist) {
+    UiListBoxSubList uisublist;
+    uisublist.var = uic_widget_var(
+            uilistbox->obj->ctx,
+            uilistbox->obj->ctx,
+            sublist->value,
+            sublist->varname,
+            UI_VAR_LIST);
+    uisublist.numitems = 0;
+    uisublist.header = sublist->header ? strdup(sublist->header) : NULL;
+    uisublist.separator = sublist->separator;
+    uisublist.widgets = cxLinkedListCreateSimple(CX_STORE_POINTERS);
+    uisublist.listbox = uilistbox;
+    uisublist.userdata = sublist->userdata;
+    uisublist.index = cxListSize(sublists);
+
+    // bind UiList
+    UiListBoxSubList *sublist_ptr = cxListAt(uilistbox->sublists, cxListSize(sublists)-1);
+    UiList *list = uisublist.var->value;
+    if(list) {
+        list->obj = sublist_ptr;
+        list->update = ui_listbox_list_update;
+    }
+
+    cxListAdd(sublists, &uisublist);
+}
+
 UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args) {
     UiObject* current = uic_current_obj(obj);
     
@@ -1596,42 +1637,32 @@
     uilistbox->sublists->collection.destructor_data = obj;
     uilistbox->first_row = NULL;
     
-    if(args.numsublists == 0 && args.sublists) {
-        args.numsublists = INT_MAX;
-    }
-    for(int i=0;i<args.numsublists;i++) {
-        UiSubList sublist = args.sublists[i];
-        if(!sublist.varname && !sublist.value) {
-            break;
+    if(args.sublists) {
+        // static sublist initalization
+        if(args.numsublists == 0 && args.sublists) {
+            args.numsublists = INT_MAX;
+        }
+        for(int i=0;i<args.numsublists;i++) {
+            UiSubList sublist = args.sublists[i];
+            if(!sublist.varname && !sublist.value) {
+                break;
+            }
+            
+            add_sublist(uilistbox, uilistbox->sublists, &sublist);
         }
         
-        UiListBoxSubList uisublist;
-        uisublist.var = uic_widget_var(
-                obj->ctx,
-                current->ctx,
-                sublist.value,
-                sublist.varname,
-                UI_VAR_LIST);
-        uisublist.numitems = 0;
-        uisublist.header = sublist.header ? strdup(sublist.header) : NULL;
-        uisublist.separator = sublist.separator;
-        uisublist.widgets = cxLinkedListCreateSimple(CX_STORE_POINTERS);
-        uisublist.listbox = uilistbox;
-        uisublist.userdata = sublist.userdata;
-        uisublist.index = i;
-        
-        cxListAdd(uilistbox->sublists, &uisublist);
-        
-        // bind UiList
-        UiListBoxSubList *sublist_ptr = cxListAt(uilistbox->sublists, cxListSize(uilistbox->sublists)-1);
-        UiList *list = uisublist.var->value;
-        if(list) {
-            list->obj = sublist_ptr;
-            list->update = ui_listbox_list_update;
+        // fill items
+        ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists));
+    } else {
+        UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.dynamic_sublist, args.varname, UI_VAR_LIST);
+        if(var) {
+            UiList *list = var->value;
+            list->obj = uilistbox;
+            list->update = ui_listbox_dynamic_update;
+            
+            ui_listbox_dynamic_update(list, 0);
         }
     }
-    // fill items
-    ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists));
     
     // register uilistbox for both widgets, so it doesn't matter which
     // widget is used later
@@ -1656,6 +1687,35 @@
     return scroll_area;
 }
 
+void ui_listbox_dynamic_update(UiList *list, int x) {
+    UiListBox *uilistbox = list->obj;
+    
+    // unbind/free previous list vars
+    CxIterator i = cxListIterator(uilistbox->sublists);
+    cx_foreach(UiListBoxSubList *, s, i) {
+        if(s->var) {
+            UiList *sl = s->var->value;
+            sl->obj = NULL;
+            sl->update = NULL;
+            if(s->var->type == UI_VAR_SPECIAL) {
+                ui_free(s->var->from_ctx, s->var);
+            }
+        }
+    }
+    
+    cxListFree(uilistbox->sublists);
+    CxList *new_sublists = cxArrayListCreateSimple(sizeof(UiListBoxSubList), list->count(list));
+    uilistbox->sublists = new_sublists;
+    
+    UiSubList *sublist = list->first(list);
+    while(sublist) {
+        add_sublist(uilistbox, new_sublists, sublist);
+        sublist = list->next(list);
+    }
+    
+    ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists));
+}
+
 void ui_listbox_update(UiListBox *listbox, int from, int to) {
     CxIterator i = cxListIterator(listbox->sublists);
     size_t pos = 0;
@@ -1777,11 +1837,19 @@
     }
     UiListBoxSubList *sublist = data->customdata0;
     
+    UiSubListEventData eventdata;
+    eventdata.list = sublist->var->value;
+    eventdata.sublist_index = sublist->index;
+    eventdata.row_index = data->value0;
+    eventdata.sublist_userdata = sublist->userdata;
+    eventdata.row_data = ui_list_get(eventdata.list, eventdata.row_index);
+    eventdata.event_data = data->customdata2;
+    
     UiEvent event;
     event.obj = data->obj;
     event.window = event.obj->window;
     event.document = event.obj->ctx->document;
-    event.eventdata = data->customdata2;
+    event.eventdata = &eventdata;
     event.intval = data->value0;
     
     if(data->callback) {