ui/gtk/list.c

changeset 1244
a29b53f97d1a
parent 1192
96858abf075a
--- a/ui/gtk/list.c	Tue Sep 08 16:08:59 2026 +0200
+++ b/ui/gtk/list.c	Wed Sep 09 18:57:52 2026 +0200
@@ -55,7 +55,7 @@
     return elm;
 }
 
-static void* null_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
+void* ui_null_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
     return NULL;
 }
 
@@ -117,23 +117,61 @@
         tableview->getvalue = getvalue_wrapper;
         tableview->getvaluedata = (void*)args->getvalue;
     } else {
-        tableview->getvalue = null_getvalue;
+        tableview->getvalue = ui_null_getvalue;
     }
       
     return tableview;
 }
 
+static UiListView* create_treeview(UiObject *obj, UiTreeArgs *args) {
+    UiListView *treeview = malloc(sizeof(UiListView));
+    memset(treeview, 0, sizeof(UiListView));
+    treeview->obj = obj;
+    treeview->model = args->model;
+    treeview->multiselection = args->multiselection;
+    treeview->onactivate = args->onactivate;
+    treeview->onactivatedata = args->onactivatedata;
+    treeview->onactivate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
+    treeview->onselection = args->onselection;
+    treeview->onselectiondata = args->onselectiondata;
+    treeview->onselection_action = args->onselection_action ? strdup(args->onselection_action) : NULL;
+    treeview->ondragstart = args->ondragstart;
+    treeview->ondragstartdata = args->ondragstartdata;
+    treeview->ondragstart_action = args->ondragstart_action ? strdup(args->ondragstart_action) : NULL;
+    treeview->ondragcomplete = args->ondragcomplete;
+    treeview->ondragcompletedata = args->ondragcompletedata;
+    treeview->ondragcomplete_action = args->ondragcomplete_action ? strdup(args->ondragcomplete_action) : NULL;
+    treeview->ondrop = args->ondrop;
+    treeview->ondropdata = args->ondropdata;
+    treeview->ondrop_action = args->ondrop_action ? strdup(args->ondrop_action) : NULL;
+    treeview->selection.count = 0;
+    treeview->selection.rows = NULL;
+    treeview->current_row = -1;
+    
+#if GTK_CHECK_VERSION(4, 0, 0)
+    treeview->coldata.listview = treeview;
+    treeview->coldata.column = 0;
+#endif
+    
+    if(args->getvalue != NULL) {
+        treeview->getvalue = args->getvalue;
+        treeview->getvaluedata = args->getvaluedata;
+    } else {
+        args->getvalue = ui_null_getvalue;
+    }
+    
+    treeview->istreeview = TRUE;
+    treeview->getdepth = args->getdepth;
+    treeview->getdepthdata = args->getdepthdata;
+      
+    return treeview;
+}
+
 #if GTK_CHECK_VERSION(4, 10, 0)
 
 
 /* BEGIN GObject wrapper for generic pointers */
 
-typedef struct _ObjWrapper {
-    GObject parent_instance;
-    void *data;
-    int i;
-} ObjWrapper;
-
 typedef struct _ObjWrapperClass {
     GObjectClass parent_class;
 } ObjWrapperClass;
@@ -148,7 +186,7 @@
     self->data = NULL;
 }
 
-ObjWrapper* obj_wrapper_new(void* data, int i) {
+ObjWrapper* ui_gobj_wrapper_new(void* data, int i) {
     ObjWrapper *obj = g_object_new(obj_wrapper_get_type(), NULL);
     obj->data = data;
     obj->i = i;
@@ -760,6 +798,110 @@
     return scroll_area;
 }
 
+
+
+UIWIDGET ui_treeview_create(UiObject *obj, UiTreeArgs *args) {
+    GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
+    //g_list_store_append(ls, v1);
+    
+    // create obj to store all relevant data we need for handling events
+    // and list updates
+    UiListView *tableview = create_treeview(obj, args);
+    
+    GtkSelectionModel *selection_model = create_selection_model(tableview, ls, args->multiselection);
+    GtkWidget *view = gtk_column_view_new(GTK_SELECTION_MODEL(selection_model));
+    if(!args->show_header) {
+        gtk_widget_set_visible(gtk_widget_get_first_child(view), FALSE);
+    }
+    
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
+    
+    // init tableview
+    tableview->widget = view;
+    tableview->var = var;
+    tableview->liststore = ls;
+    tableview->selectionmodel = selection_model;
+    g_signal_connect(
+                view,
+                "destroy",
+                G_CALLBACK(ui_listview_destroy),
+                tableview);
+    
+    
+    // create columns from UiModel
+    UiModel *model = args->model;
+    int columns = 0;
+    if(model) {
+        columns = model->columns;
+        ui_model_add_observer(model, ui_listview_update_model, tableview);
+    }
+    
+    tableview->columns = calloc(columns, sizeof(int));
+    tableview->numcolumns = columns;
+    
+    tableview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128);
+    tableview->bound_rows->collection.simple_destructor = (cx_destructor_func)free;
+    
+    int addi = 0;
+    for(int i=0;i<columns;i++) {
+        tableview->columns[i] = i+addi;
+        
+        if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) {
+            // icon+text has 2 data columns
+            addi++;
+        }
+        
+        add_column(tableview, i);
+    }
+    
+    // bind listview to list
+    if(var && var->value) {
+        UiList *list = var->value;
+        
+        list->obj = tableview;
+        list->update = ui_listview_update2;
+        list->getselection = ui_listview_getselection2;
+        list->setselection = ui_listview_setselection2;
+        
+        ui_update_liststore(ls, list);
+    }
+    
+    // event handling
+    if(args->onactivate || args->onactivate_action) {
+        g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), tableview);
+    }
+    if(args->contextmenu) {
+        UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view);
+        ui_widget_set_contextmenu(view, menu);
+    }
+    
+    // add widget to parent
+    GtkWidget *scroll_area = SCROLLEDWINDOW_NEW();
+    gtk_scrolled_window_set_policy(
+            GTK_SCROLLED_WINDOW(scroll_area),
+            GTK_POLICY_AUTOMATIC,
+            GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS  
+    SCROLLEDWINDOW_SET_CHILD(scroll_area, view);
+    
+    if(args->width > 0 || args->height > 0) {
+        int width = args->width;
+        int height = args->height;
+        if(width == 0) {
+            width = -1;
+        }
+        if(height == 0) {
+            height = -1;
+        }
+        gtk_widget_set_size_request(scroll_area, width, height);
+    }
+    
+    UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
+    UiLayout layout = UI_ARGS2LAYOUT(args);
+    ct->add(ct, scroll_area, &layout);
+    
+    return scroll_area;
+}
+
 void ui_listview_update_model(UiModel *model, void *userdata, int insert_index, int delete_index) {
     UiListView *listview = userdata;
     if(insert_index >= listview->numcolumns) {
@@ -918,7 +1060,7 @@
     int i = 0;
     void *elm = list->first(list);
     while(elm) {
-        ObjWrapper *obj = obj_wrapper_new(elm, i++);
+        ObjWrapper *obj = ui_gobj_wrapper_new(elm, i++);
         g_list_store_append(liststore, obj);
         elm = list->next(list);
     }
@@ -927,7 +1069,7 @@
 void ui_update_liststore_static(GListStore *liststore, char **elm, size_t nelm) {
     g_list_store_remove_all(liststore);
     for(int i=0;i<nelm;i++) {
-        ObjWrapper *obj = obj_wrapper_new(elm[i], i);
+        ObjWrapper *obj = ui_gobj_wrapper_new(elm[i], i);
         g_list_store_append(liststore, obj);
     }
 }
@@ -2123,10 +2265,6 @@
 #endif
 
 
-GtkWidget* ui_get_tree_widget(UIWIDGET widget) {
-    return SCROLLEDWINDOW_GET_CHILD(widget);
-}
-
 static char** targets2array(char *target0, va_list ap, int *nelm) {
     int al = 16;
     char **targets = calloc(16, sizeof(char*));

mercurial