update toolkit, fix download/upload progressbar

Sun, 29 Sep 2024 20:25:41 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 29 Sep 2024 20:25:41 +0200
changeset 45
ab71409644b0
parent 44
473954dc6b74
child 46
31bc86844659

update toolkit, fix download/upload progressbar

application/davcontroller.c file | annotate | diff | comparison | revisions
application/window.c file | annotate | diff | comparison | revisions
ui/gtk/button.c file | annotate | diff | comparison | revisions
ui/gtk/container.c file | annotate | diff | comparison | revisions
ui/gtk/display.c file | annotate | diff | comparison | revisions
ui/gtk/entry.c file | annotate | diff | comparison | revisions
ui/gtk/headerbar.c file | annotate | diff | comparison | revisions
ui/gtk/text.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.h file | annotate | diff | comparison | revisions
ui/gtk/window.c file | annotate | diff | comparison | revisions
ui/ui/button.h file | annotate | diff | comparison | revisions
ui/ui/container.h file | annotate | diff | comparison | revisions
ui/ui/entry.h file | annotate | diff | comparison | revisions
ui/ui/text.h file | annotate | diff | comparison | revisions
--- a/application/davcontroller.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/application/davcontroller.c	Sun Sep 29 20:25:41 2024 +0200
@@ -707,7 +707,7 @@
     if (sz_downloaded_end) {
         *sz_downloaded_end = 0;
     }
-
+    
     if (download->total_bytes > 0) {
         double progress = (double)download->downloaded_bytes / (double)download->total_bytes;
         ui_set(download->progress, progress*100);
@@ -780,7 +780,6 @@
     DavResource *res = dav_resource_new(file->download->download_sn, file->path);
     dav_get_content(res, file, (dav_write_func)ddfile_write);
 
-    file->download->downloaded_bytes += ftell(f);
     file->download->downloaded_files++;
 
     ui_call_mainthread(uithr_download_update_progress, file->download);
@@ -928,7 +927,7 @@
         ui_rlabel(dialog, .value = download->label_top_right);
         ui_newline(dialog);
 
-        ui_progressbar(dialog, .value = download->progress, .colspan = 2, .hexpand = TRUE);
+        ui_progressbar(dialog, .value = download->progress, .min = 0, .max = 100, .colspan = 2, .hexpand = TRUE);
         ui_newline(dialog);
 
         ui_llabel(dialog, .value = download->label_bottom_left);
--- a/application/window.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/application/window.c	Sun Sep 29 20:25:41 2024 +0200
@@ -57,11 +57,11 @@
 
     // navigation bar
 
-    ui_hbox(obj, .fill = UI_OFF, .margin = 8) {
-        ui_button(obj, .icon = UI_ICON_GO_BACK, .onclick = action_go_back);
-        ui_button(obj, .icon = UI_ICON_GO_FORWARD, .onclick = action_go_forward);
-        
-        ui_label(obj, .label = " "); // replace when we have a ui_space widget
+    ui_hbox(obj, .fill = UI_OFF, .margin = 8, .spacing = 8) {
+        ui_hbox(obj, .fill = UI_OFF, .style_class="linked") {
+            ui_button(obj, .icon = UI_ICON_GO_BACK, .onclick = action_go_back);
+            ui_button(obj, .icon = UI_ICON_GO_FORWARD, .onclick = action_go_forward);
+        }
 
         ui_path_textfield(obj, .fill = UI_ON, .getpathelm = dav_get_pathelm, .onactivate = action_path_selected, .varname = "path");
 
--- a/ui/gtk/button.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/button.c	Sun Sep 29 20:25:41 2024 +0200
@@ -90,6 +90,7 @@
 UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs args) {
     UiObject* current = uic_current_obj(obj);
     GtkWidget *button = ui_create_button(obj, args.label, args.icon, args.onclick, args.onclickdata);
+    ui_set_name_and_style(button, args.name, args.style_class);
     UI_APPLY_LAYOUT1(current, args);
     current->container->add(current->container, button, FALSE);
     return button;
@@ -230,6 +231,7 @@
     UiObject* current = uic_current_obj(obj);
     
     ui_setup_togglebutton(current, widget, args.label, args.icon, args.varname, args.value, args.onchange, args.onchangedata);
+    ui_set_name_and_style(widget, args.name, args.style_class);
     
     UI_APPLY_LAYOUT1(current, args);
     current->container->add(current->container, widget, FALSE);
@@ -340,6 +342,7 @@
     }
     
     GtkWidget *rbutton = RADIOBUTTON_NEW(rg, args.label); 
+    ui_set_name_and_style(rbutton, args.name, args.style_class);
     if(rgroup) {
 #if GTK_MAJOR_VERSION >= 4
         if(rg) {
--- a/ui/gtk/container.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/container.c	Sun Sep 29 20:25:41 2024 +0200
@@ -266,6 +266,7 @@
     UI_APPLY_LAYOUT1(current, args);
     
     GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing);
+    ui_set_name_and_style(box, args.name, args.style_class);
     GtkWidget *widget = args.margin > 0 ? box_set_margin(box, args.margin) : box;
     ct->add(ct, widget, TRUE);
     
@@ -303,6 +304,7 @@
     GtkWidget *widget;
     
     GtkWidget *grid = create_grid(args.columnspacing, args.rowspacing);
+    ui_set_name_and_style(grid, args.name, args.style_class);
     widget = box_set_margin(grid, args.margin);
     current->container->add(current->container, widget, TRUE);
     
@@ -319,6 +321,7 @@
     UI_APPLY_LAYOUT1(current, args);
     
     GtkWidget *sw = SCROLLEDWINDOW_NEW();
+    ui_set_name_and_style(sw, args.name, args.style_class);
     UiObject *newobj = uic_object_new(obj, sw);
     newobj->container = ui_scrolledwindow_container(obj, sw);
     uic_obj_add(obj, newobj);
--- a/ui/gtk/display.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/display.c	Sun Sep 29 20:25:41 2024 +0200
@@ -119,10 +119,27 @@
 
 /* ------------------------- progress bar ------------------------- */
 
+typedef struct UiProgressBarRange {
+    double min;
+    double max;
+} UiProgressBarRange;
+
 UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) {
     UiObject* current = uic_current_obj(obj);
     
     GtkWidget *progressbar = gtk_progress_bar_new();
+    if(args.max > args.min) {
+        UiProgressBarRange *range = malloc(sizeof(UiProgressBarRange));
+        range->min = args.min;
+        range->max = args.max;
+        g_signal_connect(
+                progressbar,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                range);
+        g_object_set_data(G_OBJECT(progressbar), "ui_range", range);
+    }
+    
     
     UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_DOUBLE);
     if(var && var->value) {
@@ -130,7 +147,7 @@
         value->get = ui_progressbar_get;
         value->set = ui_progressbar_set;
         value->obj = progressbar;
-        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), 0.5);
+        ui_progressbar_set(value, value->value);
     }
     
     UI_APPLY_LAYOUT1(current, args);
@@ -140,13 +157,22 @@
 }
 
 double ui_progressbar_get(UiDouble *d) {
-    d->value = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(d->obj));
+    UiProgressBarRange *range = g_object_get_data(d->obj, "ui_range");
+    double fraction = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(d->obj));
+    if(range) {
+        fraction = range->min + (range->max - range->min) * fraction;
+    }
+    d->value = fraction;
     return d->value;
 }
 
 void ui_progressbar_set(UiDouble *d, double value) {
+    d->value = value;
+    UiProgressBarRange *range = g_object_get_data(d->obj, "ui_range");
+    if(range) {
+        value = (value - range->min) / (range->max - range->min);
+    }
     gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(d->obj), value);
-    d->value = value;
 }
 
 
--- a/ui/gtk/entry.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/entry.c	Sun Sep 29 20:25:41 2024 +0200
@@ -70,6 +70,7 @@
     }
 #endif
     GtkWidget *spin = gtk_spin_button_new_with_range(min, max, args.step);
+    ui_set_name_and_style(spin, args.name, args.style_class);
     gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), args.digits);
     UiObserver **obs = NULL;
     if(var) {
--- a/ui/gtk/headerbar.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/headerbar.c	Sun Sep 29 20:25:41 2024 +0200
@@ -152,19 +152,28 @@
         UiObject *obj,
         enum UiToolbarPos pos)
 {
+    
+    
+#if GTK_MAJOR_VERSION >= 4
     GtkWidget *menubutton = gtk_menu_button_new();
-    
     if(item->args.label) {
         gtk_menu_button_set_label(GTK_MENU_BUTTON(menubutton), item->args.label);
     }
     if(item->args.icon) {
         gtk_menu_button_set_icon_name(GTK_MENU_BUTTON(menubutton), item->args.icon); 
     }
-   
+    
     GMenu *menu = g_menu_new();
     ui_gmenu_add_menu_items(menu, 0, &item->menu, obj);
     
     gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(menubutton), G_MENU_MODEL(menu));
+#else
+    GtkWidget *menubutton = gtk_menu_button_new();
+    
+    // TODO
+    
+    
+#endif
     
     headerbar_add(headerbar, box, menubutton, pos);
 }
--- a/ui/gtk/text.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/text.c	Sun Sep 29 20:25:41 2024 +0200
@@ -542,6 +542,7 @@
 
 static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool password, UiTextFieldArgs args) {
     GtkWidget *textfield = gtk_entry_new();
+    ui_set_name_and_style(textfield, args.name, args.style_class);
     
     UiObject* current = uic_current_obj(obj);
     UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING);
@@ -700,7 +701,6 @@
 }
 
 static void ui_path_textfield_destroy(GtkWidget *object, UiPathTextField *pathtf) {
-    free(pathtf->hbox);
     g_object_unref(pathtf->entry);
     free(pathtf);
 }
--- a/ui/gtk/toolkit.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/toolkit.c	Sun Sep 29 20:25:41 2024 +0200
@@ -383,4 +383,26 @@
 
 
 
-#endif
\ No newline at end of file
+#endif
+
+void ui_set_name_and_style(GtkWidget *widget, const char *name, const char *style_classes) {
+    if(name) {
+        gtk_widget_set_name(widget, name);
+    }
+    if(style_classes) {
+        cxstring *cls = NULL;
+        size_t numClasses = cx_strsplit_a(cxDefaultAllocator, cx_str(style_classes), CX_STR(" "), 128, &cls);
+        for(int i=0;i<numClasses;i++) {
+            cxmutstr m = cx_strdup(cls[i]);
+#if GTK_MAJOR_VERSION >= 4
+            gtk_widget_add_css_class(widget, m.ptr);
+#elif GTK_MAJOR_VERSION >= 3
+            GtkStyleContext *ctx = gtk_widget_get_style_context(widget);
+            gtk_style_context_add_class(ctx, m.ptr);
+#endif
+            free(m.ptr);
+        }
+        free(cls);
+        
+    }
+}
--- a/ui/gtk/toolkit.h	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/toolkit.h	Sun Sep 29 20:25:41 2024 +0200
@@ -136,6 +136,8 @@
 
 int ui_get_scalefactor();
 
+void ui_set_name_and_style(GtkWidget *widget, const char *name, const char *style);
+
 void ui_destroy_userdata(GtkWidget *object, void *userdata);
 void ui_destroy_vardata(GtkWidget *object, UiVarEventData *data);
 void ui_destroy_boundvar(UiContext *ctx, UiVar *var);
--- a/ui/gtk/window.c	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/gtk/window.c	Sun Sep 29 20:25:41 2024 +0200
@@ -119,11 +119,13 @@
     GtkWidget *toolbar_view = adw_toolbar_view_new();
     adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), toolbar_view);
     adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(toolbar_view), vbox);
-    
+
     GtkWidget *headerbar = adw_header_bar_new();
     adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar);
     
-    ui_fill_headerbar(obj, headerbar);
+    if(!simple) {
+        ui_fill_headerbar(obj, headerbar);
+    }
 #elif GTK_MAJOR_VERSION >= 4
     WINDOW_SET_CONTENT(obj->widget, vbox);
 #else
@@ -259,12 +261,176 @@
 }
 
 
-#if GTK_MAJOR_VERSION >= 4
-static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {
-    // TODO
+#if GTK_MAJOR_VERSION >= 3
+UiFileList listmodel2filelist(GListModel *selection) {
+    UiFileList flist;
+    flist.files = NULL;
+    flist.nfiles = 0;
+    flist.nfiles = g_list_model_get_n_items(selection);
+    flist.files = calloc(flist.nfiles, sizeof(char*));
+    for(int i=0;i<flist.nfiles;i++) {
+        GFile *file = g_list_model_get_item(selection, i);
+        char *path = g_file_get_path(file);
+        flist.files[i] = path ? strdup(path) : NULL;
+        g_object_unref(file);
+    }
+    return flist;
+}
+#endif
+
+
+#if GTK_CHECK_VERSION(4, 10, 0)
+
+#define UI_GTK_FILEDIALOG_OPEN 16
+#define UI_GTK_FILEDIALOG_SAVE 32
+
+static void filechooser_opened(GObject *source, GAsyncResult *result, void *data) {
+    UiEventData *event = data;
+    
+    GFile *file = NULL;
+    GListModel *selection = NULL;
+    GError *error = NULL;
+    
+    int mode = event->value;
+    int multi = mode & UI_FILEDIALOG_SELECT_MULTI;
+    if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) {
+        if(multi) {
+            selection = gtk_file_dialog_select_multiple_folders_finish(GTK_FILE_DIALOG(source), result, &error);
+        } else {
+            file = gtk_file_dialog_select_folder_finish(GTK_FILE_DIALOG(source), result, &error);
+        }
+    } else if((mode & UI_GTK_FILEDIALOG_OPEN) == UI_GTK_FILEDIALOG_OPEN) {
+        if(multi) {
+            selection = gtk_file_dialog_open_multiple_finish(GTK_FILE_DIALOG(source), result, &error);
+        } else {
+            file = gtk_file_dialog_open_finish(GTK_FILE_DIALOG(source), result, &error);
+        }
+    } else {
+        file = gtk_file_dialog_save_finish(GTK_FILE_DIALOG(source), result, &error);
+    }
+    
+    UiEvent evt;
+    evt.obj = event->obj;
+    evt.document = evt.obj->ctx->document;
+    evt.window = evt.obj->window;
+    evt.intval = 0;
+    
+    UiFileList flist;
+    flist.files = NULL;
+    flist.nfiles = 0;
+    evt.eventdata = &flist;
+    
+    if(selection) {
+        flist = listmodel2filelist(selection);
+        g_object_unref(selection);
+    } else if(file) {
+        char *path = g_file_get_path(file);
+        if(path) {
+            flist.nfiles = 1;
+            flist.files = calloc(flist.nfiles, sizeof(char*));
+            flist.files[0] = strdup(path);
+        }
+        g_object_unref(file); 
+    }
+    
+    if(event->callback) {
+        event->callback(&evt, event->userdata);
+    }
+    
+    for(int i=0;i<flist.nfiles;i++) {
+        free(flist.files[i]);
+    }
+}
+
+static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, const char *name, ui_callback file_selected_callback, void *cbdata) {
+    if(action == GTK_FILE_CHOOSER_ACTION_OPEN) {
+        mode |= UI_GTK_FILEDIALOG_OPEN;
+    } else {
+        mode |= UI_GTK_FILEDIALOG_SAVE;
+    }
+    
+    UiEventData *event = malloc(sizeof(UiEventData));
+    event->callback = file_selected_callback;
+    event->userdata = cbdata;
+    event->customdata = NULL;
+    event->value = mode;
+    event->obj = obj;
+    
+    GtkWindow *parent = GTK_WINDOW(gtk_widget_get_root(obj->widget));
+    GtkFileDialog *dialog = gtk_file_dialog_new();
+    if(name) {
+        gtk_file_dialog_set_initial_name(dialog, name);
+    }
+    
+    int multi = mode & UI_FILEDIALOG_SELECT_MULTI;
+    if((mode & UI_FILEDIALOG_SELECT_FOLDER) == UI_FILEDIALOG_SELECT_FOLDER) {
+        if(multi) {
+            gtk_file_dialog_select_multiple_folders(dialog, parent, NULL, filechooser_opened, event);
+        } else {
+            gtk_file_dialog_select_folder(dialog, parent, NULL, filechooser_opened, event);
+        }
+    } else if(action == GTK_FILE_CHOOSER_ACTION_OPEN) {
+        if(multi) {
+            gtk_file_dialog_open_multiple(dialog, parent, NULL, filechooser_opened, event);
+        } else {
+            gtk_file_dialog_open(dialog, parent, NULL, filechooser_opened, event);
+        }
+    } else {
+        gtk_file_dialog_save(dialog, parent, NULL, filechooser_opened, event);
+    }
+    
+    g_object_unref(dialog);
 }
 #else
-static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {
+
+
+
+static void filechooser_response(GtkDialog* self, gint response_id, UiEventData *data) {
+    UiEvent evt;
+    evt.obj = data->obj;
+    evt.document = evt.obj->ctx->document;
+    evt.window = evt.obj->window;
+    evt.intval = 0;
+    
+    UiFileList flist;
+    flist.files = NULL;
+    flist.nfiles = 0;
+    evt.eventdata = &flist;
+    
+    if(response_id == GTK_RESPONSE_ACCEPT) {
+#if GTK_CHECK_VERSION(4, 0, 0)
+        GListModel *selection = gtk_file_chooser_get_files(GTK_FILE_CHOOSER(self));
+        flist = flist = listmodel2filelist(selection);
+        g_object_unref(selection);
+#else
+        GSList *selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(self));
+        flist.nfiles = g_slist_length(selection);
+        flist.files = calloc(flist.nfiles, sizeof(char*));
+        int i = 0;
+        while(selection) {
+            char *file = selection->data;
+            flist.files[i] = strdup(file);
+            g_free(file);
+            selection = selection->next;
+            i++;
+        }
+        g_slist_free(selection);
+#endif
+    }
+    
+    
+    if(data->callback) {
+        data->callback(&evt, data->userdata);
+    }
+    
+    for(int i=0;i<flist.nfiles;i++) {
+        free(flist.files[i]);
+    }
+    
+    WINDOW_DESTROY(GTK_WIDGET(self));
+}
+
+static void ui_gtkfilechooser(UiObject *obj, GtkFileChooserAction action, unsigned int mode, const char *name, ui_callback file_selected_callback, void *cbdata) {
     char *button;
     char *title;
     
@@ -305,6 +471,25 @@
         gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
     }
     
+    UiEventData *event = malloc(sizeof(UiEventData));
+    event->obj = obj;
+    event->userdata = cbdata;
+    event->callback = file_selected_callback;
+    event->value = 0;
+    event->customdata = NULL;
+    
+    g_signal_connect(
+                dialog,
+                "response",
+                G_CALLBACK(filechooser_response),
+                event);
+    g_signal_connect(
+                dialog,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
+    
+    
     UiEvent evt;
     evt.obj = obj;
     evt.document = evt.obj->ctx->document;
@@ -316,39 +501,15 @@
     flist.nfiles = 0;
     evt.eventdata = &flist;
     
-    int result = gtk_dialog_run(GTK_DIALOG (dialog));
-    GSList *selection = NULL;
-    if(result == GTK_RESPONSE_ACCEPT) {
-        selection = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
-        flist.nfiles = g_slist_length(selection);
-        flist.files = calloc(flist.nfiles, sizeof(char*));
-        int i = 0;
-        while(selection) {
-            flist.files[i] = selection->data;
-            selection = selection->next;
-            i++;
-        }
-    }
-    
-    if(file_selected_callback) {
-        file_selected_callback(&evt, cbdata);
-    }
-    
-    for(int i=0;i<flist.nfiles;i++) {
-        g_free(flist.files[i]);
-    } 
-    free(flist.files);
-    g_slist_free(selection);
-    
-    gtk_widget_destroy(dialog);
+    gtk_widget_show(dialog);
 }
 #endif
 
 void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {
-    ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_OPEN, mode, file_selected_callback, cbdata);
+    ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_OPEN, mode, NULL, file_selected_callback, cbdata);
 }
 
 void ui_savefiledialog(UiObject *obj, const char *name, ui_callback file_selected_callback, void *cbdata) {
-    ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, file_selected_callback, cbdata);
+    ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, name, file_selected_callback, cbdata);
 }
 
--- a/ui/ui/button.h	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/ui/button.h	Sun Sep 29 20:25:41 2024 +0200
@@ -41,6 +41,8 @@
     UiBool vexpand;
     int colspan;
     int rowspan;
+    const char *name;
+    const char *style_class;
 
     const char* label;
     const char* stockid;
@@ -56,7 +58,9 @@
     UiBool vexpand;
     int colspan;
     int rowspan;
-
+    const char *name;
+    const char *style_class;
+    
     const char* label;
     const char* stockid;
     const char* icon;
@@ -66,7 +70,7 @@
     ui_callback onchange;
     void* onchangedata;
 } UiToggleArgs;
-   
+ 
 #define ui_button(obj, ...) ui_button_create(obj, (UiButtonArgs){ __VA_ARGS__ } )
 #define ui_togglebutton(obj, ...) ui_togglebutton_create(obj, (UiToggleArgs){ __VA_ARGS__ } )
 #define ui_checkbox(obj, ...) ui_checkbox_create(obj, (UiToggleArgs){ __VA_ARGS__ } )
--- a/ui/ui/container.h	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/ui/container.h	Sun Sep 29 20:25:41 2024 +0200
@@ -56,6 +56,8 @@
     UiBool vexpand;
     int colspan;
     int rowspan;
+    const char *name;
+    const char *style_class;
 
     int margin;
     int spacing;
@@ -69,6 +71,8 @@
     UiBool vexpand;
     int colspan;
     int rowspan;
+    const char *name;
+    const char *style_class;
 
     UiSubContainerType subcontainer;
 
@@ -87,6 +91,8 @@
     UiBool vexpand;
     int colspan;
     int rowspan;
+    const char *name;
+    const char *style_class;
 
     UiTabViewType tabview;
 
--- a/ui/ui/entry.h	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/ui/entry.h	Sun Sep 29 20:25:41 2024 +0200
@@ -42,6 +42,8 @@
     UiBool vexpand;
     int colspan;
     int rowspan;
+    const char *name;
+    const char *style_class;
 
     double step;
     int digits;
--- a/ui/ui/text.h	Sun Sep 29 13:32:51 2024 +0200
+++ b/ui/ui/text.h	Sun Sep 29 20:25:41 2024 +0200
@@ -42,6 +42,8 @@
     int colspan;
     int rowspan;
     int width;
+    const char *name;
+    const char *style_class;
 
     UiString* value;
     const char* varname;
@@ -66,6 +68,8 @@
     UiBool vexpand;
     int colspan;
     int rowspan;
+    const char *name;
+    const char *style_class;
 
     UiString *value;
     const char* varname;

mercurial