Wed, 09 Sep 2026 18:57:52 +0200
add API spec for new treeview
| application/Makefile | file | annotate | diff | comparison | revisions | |
| application/main.c | file | annotate | diff | comparison | revisions | |
| client/Makefile | file | annotate | diff | comparison | revisions | |
| ui/common/Makefile | file | annotate | diff | comparison | revisions | |
| ui/gtk/Makefile | file | annotate | diff | comparison | revisions | |
| ui/gtk/list.c | file | annotate | diff | comparison | revisions | |
| ui/gtk/list.h | file | annotate | diff | comparison | revisions | |
| ui/gtk/objs.mk | file | annotate | diff | comparison | revisions | |
| ui/gtk/tree.c | file | annotate | diff | comparison | revisions | |
| ui/gtk/tree.h | file | annotate | diff | comparison | revisions | |
| ui/ui/list.h | file | annotate | diff | comparison | revisions | |
| ui/ui/tree.h | file | annotate | diff | comparison | revisions | |
| ui/ui/ui.h | file | annotate | diff | comparison | revisions |
--- a/application/Makefile Tue Sep 08 16:08:59 2026 +0200 +++ b/application/Makefile Wed Sep 09 18:57:52 2026 +0200 @@ -57,9 +57,8 @@ ../build/application/demo_bindings$(OBJ_EXT): demo_bindings.c \ demo_bindings.h $(CC) -o $@ $(CFLAGS) $(TK_CFLAGS) -c $< - -../build/application/demo_states$(OBJ_EXT): demo_states.c \ - demo_states.h + +../build/application/demo_states$(OBJ_EXT): demo_states.c demo_states.h $(CC) -o $@ $(CFLAGS) $(TK_CFLAGS) -c $< ../build/application/main$(OBJ_EXT): main.c
--- a/application/main.c Tue Sep 08 16:08:59 2026 +0200 +++ b/application/main.c Wed Sep 09 18:57:52 2026 +0200 @@ -203,6 +203,7 @@ UiString *link_label; UiString *link_uri; UiList *submenulist; + UiList *tree; UiModel *model; } MyDocument; @@ -218,6 +219,11 @@ static UiThreadpool *threadpool; +typedef struct TreeNode { + char *name; + int depth; +} TreeNode; + int threadfunc(void *data) { printf("thr wait for data...\n"); ui_condvar_wait(cond); @@ -389,6 +395,33 @@ ui_int_new(docctx, "menu_radio"); + doc->tree = ui_list_new(docctx, "tree"); + TreeNode *root = malloc(sizeof(TreeNode)); + root->name = "Root"; + root->depth = 0; + ui_list_append(doc->tree, root); + + TreeNode *node_a = malloc(sizeof(TreeNode)); + node_a->name = "Folder"; + node_a->depth = 1; + ui_list_append(doc->tree, node_a); + + TreeNode *node_a0 = malloc(sizeof(TreeNode)); + node_a0->name = "Leaf 1"; + node_a0->depth = 2; + ui_list_append(doc->tree, node_a0); + + TreeNode *node_a1 = malloc(sizeof(TreeNode)); + node_a1->name = "Leaf 2"; + node_a1->depth = 2; + ui_list_append(doc->tree, node_a1); + + TreeNode *node_1 = malloc(sizeof(TreeNode)); + node_1->name = "Leaf 3"; + node_1->depth = 1; + ui_list_append(doc->tree, node_1); + + //doc->text = ui_text_new(docctx, "text"); return doc; } @@ -537,6 +570,16 @@ return FALSE; } +void* tree_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) { + TreeNode *node = elm; + return node->name; +} + +int tree_getdepth(UiList *list, void *elm, int row, void *userdata) { + TreeNode *node = elm; + return node->depth; +} + void sourcelist_getvalue(UiList *list, void *sublistdata, void *rowdata, int index, UiSubListItem *item, void *userdata) { ui_menubuilder_ref(sourcelist_menu); item->label = strdup(rowdata); @@ -906,6 +949,10 @@ ui_tab(obj, "Tab 12") { ui_drawingarea(obj, .fill = TRUE, .draw = draw); } + ui_tab(obj, "Tab 13") { + UiModel *model = ui_model(obj->ctx, UI_STRING, "test", -1); + ui_treeview(obj, .fill = TRUE, .model = model, .show_header = TRUE, .getvalue = tree_getvalue, .getdepth = tree_getdepth, .varname = "tree"); + } } /*
--- a/client/Makefile Tue Sep 08 16:08:59 2026 +0200 +++ b/client/Makefile Wed Sep 09 18:57:52 2026 +0200 @@ -59,7 +59,8 @@ ../ui/common/../ui/button.h ../ui/common/../ui/entry.h \ ../ui/common/../ui/menu.h ../ui/common/../ui/toolbar.h \ ../ui/common/../ui/list.h ../ui/common/../ui/text.h \ - ../ui/common/../ui/webview.h ../ui/common/../ui/widget.h + ../ui/common/../ui/webview.h ../ui/common/../ui/image.h \ + ../ui/common/../ui/widget.h $(CC) -o $@ $(CFLAGS) $(TK_CFLAGS) $(CLIENT_CFLAGS) -c $< ../build/client/main$(OBJ_EXT): main.c main.h ../ui/common/message.h \ @@ -73,6 +74,7 @@ ../ui/common/../ui/button.h ../ui/common/../ui/entry.h \ ../ui/common/../ui/menu.h ../ui/common/../ui/toolbar.h \ ../ui/common/../ui/list.h ../ui/common/../ui/text.h \ - ../ui/common/../ui/webview.h ../ui/common/../ui/widget.h + ../ui/common/../ui/webview.h ../ui/common/../ui/image.h \ + ../ui/common/../ui/widget.h $(CC) -o $@ $(CFLAGS) $(TK_CFLAGS) $(CLIENT_CFLAGS) -c $<
--- a/ui/common/Makefile Tue Sep 08 16:08:59 2026 +0200 +++ b/ui/common/Makefile Wed Sep 09 18:57:52 2026 +0200 @@ -40,7 +40,8 @@ common/../ui/window.h common/../ui/toolkit.h common/../ui/container.h \ common/../ui/display.h common/../ui/button.h common/../ui/entry.h \ common/../ui/menu.h common/../ui/toolbar.h common/../ui/list.h \ - common/../ui/text.h common/../ui/webview.h common/../ui/widget.h + common/../ui/text.h common/../ui/webview.h common/../ui/image.h \ + common/../ui/widget.h $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< $(COMMON_OBJPRE)uic_condvar$(OBJ_EXT): common/condvar.c common/condvar.h \
--- a/ui/gtk/Makefile Tue Sep 08 16:08:59 2026 +0200 +++ b/ui/gtk/Makefile Wed Sep 09 18:57:52 2026 +0200 @@ -105,7 +105,8 @@ gtk/../common/toolbar.h gtk/../common/../ui/toolbar.h \ gtk/../common/menu.h gtk/../common/../ui/menu.h \ gtk/../common/../ui/toolkit.h gtk/button.h gtk/../ui/button.h gtk/menu.h \ - gtk/../ui/menu.h gtk/../common/menu.h gtk/../ui/properties.h + gtk/../ui/menu.h gtk/../common/menu.h gtk/../ui/widget.h \ + gtk/../ui/properties.h $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< $(GTK_OBJPRE)icon.o: gtk/icon.c gtk/toolkit.h gtk/../ui/toolkit.h \ @@ -120,7 +121,8 @@ gtk/../common/context.h gtk/../common/../ui/toolkit.h \ gtk/../common/action.h gtk/../common/object.h gtk/container.h \ gtk/../ui/container.h gtk/menu.h gtk/../ui/menu.h gtk/../common/menu.h \ - gtk/../common/../ui/menu.h gtk/widget.h gtk/../ui/widget.h + gtk/../common/../ui/menu.h gtk/widget.h gtk/../ui/widget.h \ + gtk/../common/action.h $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< $(GTK_OBJPRE)list.o: gtk/list.c gtk/../common/context.h \ @@ -180,6 +182,13 @@ gtk/../common/menu.h gtk/../common/threadpool.h gtk/../common/app.h $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< +$(GTK_OBJPRE)tree.o: gtk/tree.c gtk/tree.h gtk/../ui/tree.h \ + gtk/../ui/list.h gtk/../ui/toolkit.h gtk/toolkit.h gtk/../ui/toolkit.h \ + gtk/../common/context.h gtk/../common/../ui/toolkit.h \ + gtk/../common/action.h gtk/../common/object.h gtk/../common/container.h \ + gtk/../common/../ui/container.h gtk/../common/../ui/toolkit.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + $(GTK_OBJPRE)webview.o: gtk/webview.c gtk/toolkit.h gtk/../ui/toolkit.h \ gtk/../common/context.h gtk/../common/../ui/toolkit.h \ gtk/../common/action.h gtk/../common/object.h gtk/container.h \ @@ -204,6 +213,6 @@ gtk/../ui/toolkit.h gtk/../common/object.h gtk/toolbar.h \ gtk/../ui/toolbar.h gtk/list.h gtk/../ui/list.h gtk/container.h \ gtk/../ui/container.h gtk/headerbar.h gtk/button.h gtk/../ui/button.h \ - gtk/window.h + gtk/window.h gtk/widget.h gtk/../ui/widget.h $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
--- 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*));
--- a/ui/gtk/list.h Tue Sep 08 16:08:59 2026 +0200 +++ b/ui/gtk/list.h Wed Sep 09 18:57:52 2026 +0200 @@ -30,6 +30,7 @@ #define LIST_H #include "../ui/list.h" +#include "../ui/tree.h" #include "toolkit.h" #include <cx/array_list.h> @@ -98,6 +99,10 @@ void *onsavedata; UiListSelection selection; + ui_tree_getdepthfunc getdepth; + void *getdepthdata; + UiBool istreeview; + }; typedef struct UiTreeEventData { @@ -139,6 +144,7 @@ UiSubListEventData current_eventdata; }; +void* ui_null_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult); #if GTK_CHECK_VERSION(4, 10, 0) @@ -160,10 +166,6 @@ void* ui_strmodel_getvalue(void *elm, int column); -UIWIDGET ui_listview_var(UiObject *obj, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *udata); -UIWIDGET ui_table_var(UiObject *obj, UiVar *var, UiModel *model, UiListCallbacks cb); - -GtkWidget* ui_get_tree_widget(UIWIDGET widget); void ui_listview_update_model(UiModel *model, void *userdata, int insert_index, int delete_index); void ui_listview_update(UiList *list, int i); @@ -211,6 +213,18 @@ UiListSelection ui_listbox_list_getselection(UiList *list); void ui_listbox_row_activate(GtkListBox *self, GtkListBoxRow *row, gpointer user_data); + +#if GTK_CHECK_VERSION(4, 10, 0) + +typedef struct _ObjWrapper { + GObject parent_instance; + void *data; + int i; +} ObjWrapper; + +ObjWrapper* ui_gobj_wrapper_new(void* data, int i); + +#endif #ifdef __cplusplus }
--- a/ui/gtk/objs.mk Tue Sep 08 16:08:59 2026 +0200 +++ b/ui/gtk/objs.mk Wed Sep 09 18:57:52 2026 +0200 @@ -39,6 +39,7 @@ GTKOBJ += display.o GTKOBJ += text.o GTKOBJ += list.o +GTKOBJ += tree.o GTKOBJ += image.o GTKOBJ += icon.o GTKOBJ += graphics.o
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/gtk/tree.c Wed Sep 09 18:57:52 2026 +0200 @@ -0,0 +1,35 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 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. + */ + +#include "tree.h" +#include "list.h" +#include "container.h" + +#include "../common/context.h" + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/gtk/tree.h Wed Sep 09 18:57:52 2026 +0200 @@ -0,0 +1,80 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 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. + */ + +#ifndef TREE_H +#define TREE_H + +#include "../ui/tree.h" +#include "toolkit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct UiTreeView UiTreeView; + +struct UiTreeView { + UiObject *obj; + GtkWidget *widget; + UiVar *var; + UiModel *model; + UiBool multiselection; + ui_tree_getdepthfunc getdepth; + void *getdepthdata; + ui_getvaluefunc2 getvalue; + void *getvaluedata; + + ui_callback onactivate; + void *onactivatedata; + char *onactivate_action; + ui_callback onselection; + void *onselectiondata; + char *onselection_action; + ui_callback ondragstart; + void *ondragstartdata; + char *ondragstart_action; + ui_callback ondragcomplete; + void *ondragcompletedata; + char *ondragcomplete_action; + ui_callback ondrop; + void *ondropdata; + char *ondrop_action; +}; + +typedef struct UiTreeColData { + UiTreeView *treeview; + int column; +} UiTreeColData; + + +#ifdef __cplusplus +} +#endif + +#endif /* TREE_H */ +
--- a/ui/ui/list.h Tue Sep 08 16:08:59 2026 +0200 +++ b/ui/ui/list.h Wed Sep 09 18:57:52 2026 +0200 @@ -26,8 +26,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef UI_TREE_H -#define UI_TREE_H +#ifndef UI_LIST_H +#define UI_LIST_H #include "toolkit.h" @@ -372,5 +372,5 @@ } #endif -#endif /* UI_TREE_H */ +#endif /* UI_LIST_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/ui/tree.h Wed Sep 09 18:57:52 2026 +0200 @@ -0,0 +1,101 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 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. + */ + +#ifndef UI_TREE_H +#define UI_TREE_H + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct UiTreeArgs UiTreeArgs; + +typedef int (*ui_tree_getdepthfunc)(UiList *list, void *elm, int row, void *userdata); + +struct UiTreeArgs { + UiBool fill; + UiBool hexpand; + UiBool vexpand; + UiBool hfill; + UiBool vfill; + UiBool override_defaults; + int margin; + int margin_left; + int margin_right; + int margin_top; + int margin_bottom; + int colspan; + int rowspan; + int width; + int height; + const char *name; + const char *style_class; + + UiList *list; + const char* varname; + UiModel *model; + ui_tree_getdepthfunc getdepth; + void *getdepthdata; + ui_getvaluefunc2 getvalue; + void *getvaluedata; + + ui_callback onactivate; + void *onactivatedata; + const char *onactivate_action; + ui_callback onselection; + void *onselectiondata; + const char *onselection_action; + ui_callback ondragstart; + void *ondragstartdata; + const char *ondragstart_action; + ui_callback ondragcomplete; + void *ondragcompletedata; + const char *ondragcomplete_action; + ui_callback ondrop; + void *ondropdata; + const char *ondrop_action; + UiBool multiselection; + UiBool show_header; + UiMenuBuilder *contextmenu; + + const int *states; + const int *visibility_states; +}; + +#define ui_treeview(obj, ...) ui_treeview_create(obj, &(UiTreeArgs) { __VA_ARGS__ } ) + +UIEXPORT UIWIDGET ui_treeview_create(UiObject *obj, UiTreeArgs *args); + +#ifdef __cplusplus +} +#endif + +#endif /* UI_TREE_H */ +