]> uap-core.de Git - note.git/commitdiff
update toolkit
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 16 Feb 2025 20:23:22 +0000 (21:23 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 16 Feb 2025 20:23:22 +0000 (21:23 +0100)
21 files changed:
application/window.c
ui/gtk/container.c
ui/gtk/container.h
ui/gtk/objs.mk
ui/gtk/webview.c [new file with mode: 0644]
ui/gtk/webview.h [new file with mode: 0644]
ui/motif/Grid.c
ui/motif/container.c
ui/motif/container.h
ui/motif/list.c
ui/motif/text.c
ui/ui/button.h
ui/ui/container.h
ui/ui/display.h
ui/ui/entry.h
ui/ui/image.h
ui/ui/range.h
ui/ui/text.h
ui/ui/tree.h
ui/ui/ui.h
ui/ui/webview.h [new file with mode: 0644]

index d731c60f0478663a5c9648c3609033bbfd65d585..a152bb56d4fe6b4d520dbaa8a214d7a5cedff291 100644 (file)
@@ -52,7 +52,7 @@ void window_create() {
         ui_table(obj, .model = model, .varname = "notes");
         
         // splitpane right: content
-        ui_grid(obj, .columnspacing = 10, .rowspacing = 10) {
+        ui_grid(obj, .columnspacing = 10, .rowspacing = 10, .def_vfill = TRUE) {
             ui_label(obj, .label = "Title", .vfill = TRUE);
             ui_textfield(obj, .varname = "note_title", .hexpand = TRUE, .groups = UI_GROUPS(APP_STATE_NOTE_SELECTED));
             ui_newline(obj);
index 17b4e4c0da5988292083fbaf648309e853f368d5..9df30094c6129a7c7d97b1fede2ca511161cf949 100644 (file)
@@ -107,7 +107,7 @@ GtkWidget* ui_subcontainer_create(
         case UI_CONTAINER_GRID: {
             sub = ui_create_grid_widget(columnspacing, rowspacing);
             add = ui_box_set_margin(sub, margin);
-            newobj->container = ui_grid_container(newobj, sub);
+            newobj->container = ui_grid_container(newobj, sub, FALSE, FALSE, FALSE, FALSE);
             newobj->widget = sub;
             break;
         }
@@ -167,11 +167,22 @@ void ui_box_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
     ct->current = widget;
 }
 
-UiContainer* ui_grid_container(UiObject *obj, GtkWidget *grid) {
+UiContainer* ui_grid_container(
+        UiObject *obj,
+        GtkWidget *grid,
+        UiBool def_hexpand,
+        UiBool def_vexpand,
+        UiBool def_hfill,
+        UiBool def_vfill)
+{
     UiGridContainer *ct = cxCalloc(
             obj->ctx->allocator,
             1,
             sizeof(UiGridContainer));
+    ct->def_hexpand = def_hexpand;
+    ct->def_vexpand = def_vexpand;
+    ct->def_hfill = def_hfill;
+    ct->def_vfill = def_vfill;
     ct->container.widget = grid;
     ct->container.add = ui_grid_container_add;
     UI_GTK_V2(ct->width = 0);
@@ -193,15 +204,34 @@ void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
     int vexpand = FALSE;
     int hfill = FALSE;
     int vfill = FALSE;
+    if(!ct->layout.override_defaults) {
+        if(grid->def_hexpand) {
+            hexpand = TRUE;
+            hfill = TRUE;
+        } else if(grid->def_hfill) {
+            hfill = TRUE;
+        }
+        if(grid->def_vexpand) {
+            vexpand = TRUE;
+            vfill = TRUE;
+        } else if(grid->def_vfill) {
+            vfill = TRUE;
+        }
+    }
+    
     if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
         fill = ui_lb2bool(ct->layout.fill);
     }
-    if(ct->layout.hexpand != UI_LAYOUT_UNDEFINED) {
-        hexpand = ct->layout.hexpand;
+    if(ct->layout.hexpand) {
+        hexpand = TRUE;
+        hfill = TRUE;
+    } else if(ct->layout.hfill) {
         hfill = TRUE;
     }
-    if(ct->layout.vexpand != UI_LAYOUT_UNDEFINED) {
-        vexpand = ct->layout.vexpand;
+    if(ct->layout.vexpand) {
+        vexpand = TRUE;
+        vfill = TRUE;
+    } else if(ct->layout.vfill) {
         vfill = TRUE;
     }
     if(fill) {
@@ -241,14 +271,57 @@ void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
     
     int hexpand = FALSE;
     int vexpand = FALSE;
-    if(ct->layout.hexpand != UI_LAYOUT_UNDEFINED) {
-        hexpand = ct->layout.hexpand;
+    int hfill = FALSE;
+    int vfill = FALSE;
+    if(!ct->layout.override_defaults) {
+        if(grid->def_hexpand) {
+            hexpand = TRUE;
+            hfill = TRUE;
+        } else if(grid->def_hfill) {
+            hfill = TRUE;
+        }
+        if(grid->def_vexpand) {
+            vexpand = TRUE;
+            vfill = TRUE;
+        } else if(grid->def_vfill) {
+            vfill = TRUE;
+        }
+    }
+    
+    if(ct->layout.fill != UI_LAYOUT_UNDEFINED) {
+        fill = ui_lb2bool(ct->layout.fill);
+    }
+    if(ct->layout.hexpand) {
+        hexpand = TRUE;
+        hfill = TRUE;
+    } else if(ct->layout.hfill) {
+        hfill = TRUE;
+    }
+    if(ct->layout.vexpand) {
+        vexpand = TRUE;
+        vfill = TRUE;
+    } else if(ct->layout.vfill) {
+        vfill = TRUE;
+    }
+    if(fill) {
+        hfill = TRUE;
+        vfill = TRUE;
+    }
+    
+    GtkAttachOptions xoptions = 0;
+    GtkAttachOptions yoptions = 0;
+    if(hexpand) {
+        xoptions = GTK_EXPAND;
+    }
+    if(hfill) {
+        xoptions |= GTK_FILL;
     }
-    if(ct->layout.vexpand != UI_LAYOUT_UNDEFINED) {
-        vexpand = ct->layout.vexpand;
+    if(vexpand) {
+        yoptions = GTK_EXPAND;
+    }
+    if(vfill) {
+        yoptions |= GTK_FILL;
     }
-    GtkAttachOptions xoptions = hexpand ? GTK_FILL | GTK_EXPAND : GTK_FILL;
-    GtkAttachOptions yoptions = vexpand ? GTK_FILL | GTK_EXPAND : GTK_FILL;
     
     int colspan = ct->layout.colspan > 0 ? ct->layout.colspan : 1;
     int rowspan = ct->layout.rowspan > 0 ? ct->layout.rowspan : 1;
@@ -407,7 +480,7 @@ UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) {
     current->container->add(current->container, widget, TRUE);
     
     UiObject *newobj = uic_object_new(obj, grid);
-    newobj->container = ui_grid_container(obj, grid);
+    newobj->container = ui_grid_container(obj, grid, args.def_hexpand, args.def_vexpand, args.def_hfill, args.def_vfill);
     uic_obj_add(obj, newobj);
     
     return widget;
@@ -766,7 +839,7 @@ UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index) {
         }
         case UI_CONTAINER_GRID: {
             sub = ui_create_grid_widget(data->columnspacing, data->rowspacing);
-            newobj->container = ui_grid_container(newobj, sub);
+            newobj->container = ui_grid_container(newobj, sub, FALSE, FALSE, FALSE, FALSE);
             break;
         }
     }
@@ -1175,6 +1248,11 @@ void ui_layout_vfill(UiObject *obj, UiBool fill) {
     ct->layout.vfill = fill;
 }
 
+UIEXPORT void ui_layout_override_defaults(UiObject *obj, UiBool d) {
+    UiContainer *ct = uic_get_current_container(obj);
+    ct->layout.override_defaults = d;
+}
+
 void ui_layout_colspan(UiObject* obj, int cols) {
     UiContainer* ct = uic_get_current_container(obj);
     ct->layout.colspan = cols;
index 271ed507ce01d7263b2f0147c8a7e43200ddc3ad..421451da04f82aa233c1e08366734fe43547ea79 100644 (file)
@@ -66,6 +66,7 @@ struct UiLayout {
     UiBool       vexpand;
     UiBool       hfill;
     UiBool       vfill;
+    UiBool       override_defaults;
     int          width;
     int          colspan;
     int          rowspan;
@@ -90,6 +91,10 @@ typedef struct UiBoxContainer {
 
 typedef struct UiGridContainer {
     UiContainer container;
+    UiBool def_hexpand;
+    UiBool def_vexpand;
+    UiBool def_hfill;
+    UiBool def_vfill;
     int x;
     int y;
 #ifdef UI_GTK2
@@ -171,7 +176,13 @@ UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType
 void ui_box_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
 
 GtkWidget* ui_create_grid_widget(int colspacing, int rowspacing);
-UiContainer* ui_grid_container(UiObject *obj, GtkWidget *grid);
+UiContainer* ui_grid_container(
+        UiObject *obj,
+        GtkWidget *grid,
+        UiBool def_hexpand,
+        UiBool def_vexpand,
+        UiBool def_hfill,
+        UiBool def_vfill);
 void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
 
 UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame);
index 865216e00348bc78bed19e4b1aa546de86175d5e..ed89f4d41a47e5010192bd3831c457ab0f66f892 100644 (file)
@@ -46,6 +46,7 @@ GTKOBJ += range.o
 GTKOBJ += entry.o
 GTKOBJ += dnd.o
 GTKOBJ += headerbar.o
+GTKOBJ += webview.o
 
 TOOLKITOBJS += $(GTKOBJ:%=$(GTK_OBJPRE)%)
 TOOLKITSOURCE += $(GTKOBJ:%.o=gtk/%.c)
diff --git a/ui/gtk/webview.c b/ui/gtk/webview.c
new file mode 100644 (file)
index 0000000..6f204a1
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#include "toolkit.h"
+#include "container.h"
+#include "../ui/webview.h"
+
+#ifdef UI_WEBVIEW
+
+#include <webkit/webkit.h>
+
+UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs args) {
+    UiObject* current = uic_current_obj(obj);
+    
+    GtkWidget *webview = webkit_web_view_new();
+    webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview), "https://code.unixwork.de");
+    
+    ui_set_name_and_style(webview, args.name, args.style_class);
+    
+    ui_set_widget_groups(obj->ctx, webview, args.groups);
+    UI_APPLY_LAYOUT1(current, args);
+    current->container->add(current->container, webview, FALSE);
+    
+    return webview;
+}
+
+
+#endif
diff --git a/ui/gtk/webview.h b/ui/gtk/webview.h
new file mode 100644 (file)
index 0000000..f4fd44b
--- /dev/null
@@ -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.
+ */
+#ifndef WEBVIEW_H
+#define WEBVIEW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WEBVIEW_H */
+
index bb177ddcaefdaac810672e9a15c10726451a28bc..b1abbe0377bc13a14f7508669abd4b8493d2f7b8 100644 (file)
@@ -548,6 +548,8 @@ void grid_place_children(MyWidget w) {
             Dimension actual_width, actual_height;
             w->mywidget.sizerequest = TRUE;
             
+            //printf("sizerequest: %d x %d\n", (int)req_width, (int)req_height);
+            
             //XtWidgetGeometry request;
             //request.width = req_width;
             //request.request_mode = CWWidth;
index 3354d358ed5a01f313c7ee5d11dcd636a98735cf..08acc77ae373b1aefd3a6212ba02572a14f212df 100644 (file)
@@ -224,20 +224,23 @@ void ui_grid_container_add(UiContainerPrivate *ctn, Widget widget) {
 /* -------------------------- TabView Container -------------------------- */
 
 static void ui_tabbar_resize(Widget widget, XtPointer udata, XtPointer cdata) {
-    printf("ui_tabbar_resize\n");
-    
     UiMotifTabView *tabview = udata;
     
     int width = 0;
     int height = 0;
     XtVaGetValues(widget, XmNwidth, &width, XmNheight, &height, NULL);
-    int button_width = width / 4;
+    int numbuttons = cxListSize(tabview->tabs);
+    if(numbuttons == 0) {
+        return;
+    }
+    int button_width = width / numbuttons;
     int x = 0;
     
-    printf("width: %d\n", (int)width);
-    
     CxIterator i = cxListIterator(tabview->tabs);
     cx_foreach(UiTab *, tab, i) {
+        if(i.index + 1 == numbuttons) {
+            button_width = width - x;
+        }
         XtVaSetValues(
                 tab->tab_button,
                 XmNx, x,
@@ -255,19 +258,21 @@ static void ui_tabbar_resize(Widget widget, XtPointer udata, XtPointer cdata) {
 }
 
 static void ui_tabbar_expose(Widget widget, XtPointer udata, XtPointer cdata) {
-    printf("ui_tabbar_expose\n");
-    
     UiMotifTabView *tabview = udata;
-    CxIterator i = cxListIterator(tabview->tabs);
-    cx_foreach(UiTab *, tab, i) {
-        printf("y: %d\n", (int)tab->tab_button->core.y);
-    }
-    
     XmDrawingAreaCallbackStruct *cbs = (XmDrawingAreaCallbackStruct *)cdata;
     XEvent *event = cbs->event;
     Display *dpy = XtDisplay(widget); 
     
-    printf("width: %d\n", (int)widget->core.width);
+    if(!tabview->gc_initialized) {
+        XGCValues gcvals;
+        gcvals.foreground = tabview->fg1;
+        tabview->gc = XCreateGC(XtDisplay(tabview->tabbar), XtWindow(tabview->tabbar), (GCForeground), &gcvals);
+    }
+    
+    if(tabview->current_tab) {
+        Widget tab = tabview->current_tab->tab_button;
+        XFillRectangle(dpy, XtWindow(widget), tabview->gc, tab->core.x, tab->core.height, tab->core.width, 4);
+    }
 }
 
 UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs args) {
@@ -312,6 +317,7 @@ UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs args) {
     Widget content = XmCreateFrame(form, "tabviewcontent", xargs, n);
     
     // setup tabview object, that holds all relevant objects
+    tabview->obj = obj;
     tabview->form = form;
     tabview->tabbar = tabbar;
     tabview->content = content;
@@ -320,7 +326,7 @@ UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs args) {
     tabview->select = ui_motif_tabview_select;
     tabview->add = ui_motif_tabview_add_tab;
     tabview->remove = ui_motif_tabview_remove;
-    tabview->tabs = cxArrayListCreateSimple(sizeof(UiTab), 8);
+    tabview->tabs = cxArrayListCreate(obj->ctx->allocator, NULL, sizeof(UiTab), 8);
     
     UiTabViewContainer *ct = ui_malloc(obj->ctx, sizeof(UiTabViewContainer));
     ct->container.widget = form;
@@ -359,8 +365,65 @@ void ui_tab_create(UiObject *obj, const char* title) {
     tabview->add(tabview, -1, title, child);
 }
 
+void ui_tabview_select(UIWIDGET tabview, int tab) {
+    UiMotifTabView *tabviewdata = NULL;
+    XtVaGetValues(tabview, XmNuserData, &tabviewdata, NULL);
+    if(tabviewdata) {
+        ui_motif_tabview_select(tabviewdata, tab);
+    } else {
+        fprintf(stderr, "ui_tabview_select: widget is not a tabview\n");
+    }
+}
+
+void ui_tabview_remove(UIWIDGET tabview, int tab) {
+    UiMotifTabView *tabviewdata = NULL;
+    XtVaGetValues(tabview, XmNuserData, &tabviewdata, NULL);
+    if(tabviewdata) {
+        ui_motif_tabview_remove(tabviewdata, tab);
+    } else {
+        fprintf(stderr, "ui_tabview_select: widget is not a tabview\n");
+    }
+}
+
+UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index) {
+    UiMotifTabView *tabviewdata = NULL;
+    XtVaGetValues(tabview, XmNuserData, &tabviewdata, NULL);
+    if(tabviewdata) {
+        Arg args[16];
+        int n = 0;
+        
+        XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
+        XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
+        XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
+        XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
+        XtSetArg(args[n], XmNtopWidget, tabviewdata->tabbar); n++;
+        
+        Widget grid = XtCreateManagedWidget("vbox", gridClass, tabviewdata->content, args, n);
+        
+        UiObject *newobj = ui_calloc(tabviewdata->obj->ctx, 1, sizeof(UiObject));
+        newobj->ctx = tabviewdata->obj->ctx;
+        newobj->widget = grid;
+        UiContainerX *container = ui_box_container(newobj, grid, UI_BOX_VERTICAL);
+        newobj->container_begin = container;
+        newobj->container_end = container;
+        return newobj;
+    } else {
+        fprintf(stderr, "ui_tabview_select: widget is not a tabview\n");
+        return NULL;
+    }
+}
+
 void ui_motif_tabview_select(UiMotifTabView *tabview, int tab) {
-    
+    UiTab *t = cxListAt(tabview->tabs, tab);
+    if(t) {
+        ui_motif_tabview_change_tab(tabview, t);
+    }
+}
+
+static void ui_tab_button_callback(Widget widget, UiTab *tab, XtPointer d) {
+    UiMotifTabView *tabview = NULL;
+    XtVaGetValues(widget, XmNuserData, &tabview, NULL);
+    ui_motif_tabview_change_tab(tabview, tab);
 }
 
 void ui_motif_tabview_add_tab(UiMotifTabView *tabview, int index, const char *name, Widget child) {
@@ -373,8 +436,9 @@ void ui_motif_tabview_add_tab(UiMotifTabView *tabview, int index, const char *na
     XtSetArg(args[n], XmNlabelString, label); n++;
     XtSetArg(args[n], XmNshadowThickness, 0); n++;
     XtSetArg(args[n], XmNhighlightThickness, 0); n++;
+    XtSetArg(args[n], XmNuserData, tabview); n++;
     
-    Widget button = XmCreatePushButton(tabview->tabbar, "tab_button", args, 3);
+    Widget button = XmCreatePushButton(tabview->tabbar, "tab_button", args, n);
     XtManageChild(button);
     
     if(tabview->height == 0) {
@@ -385,19 +449,63 @@ void ui_motif_tabview_add_tab(UiMotifTabView *tabview, int index, const char *na
                 &tabview->bg1,
                 XmNbackground,
                 &tabview->bg2,
+                XmNhighlightColor,
+                &tabview->fg1,
                 XmNheight,
                 &h,
                 NULL);
         tabview->height = h + 2; // border
+        
+        XtVaSetValues(tabview->tabbar, XmNbackground, tabview->bg1, NULL);
     }
     
     tab.tab_button = button;
     tab.child = child;
+    size_t newtab_index = cxListSize(tabview->tabs);
     cxListAdd(tabview->tabs, &tab);
+    UiTab *newtab = cxListAt(tabview->tabs, newtab_index);
+    
+    XtAddCallback(
+            button,
+            XmNactivateCallback,
+            (XtCallbackProc)ui_tab_button_callback,
+            newtab);
+    
+    if(newtab_index == 0) {
+        ui_motif_tabview_change_tab(tabview, newtab);
+    } else {
+        XtVaSetValues(button, XmNbackground, tabview->bg1, NULL);
+    }
 }
 
 void ui_motif_tabview_remove(UiMotifTabView *tabview, int index) {
-    
+    UiTab *tab = cxListAt(tabview->tabs, index);
+    if(tab) {
+        if(tab == tabview->current_tab) {
+            if(index > 0) {
+                ui_motif_tabview_select(tabview, index-1);
+            } else {
+                if(index < cxListSize(tabview->tabs)) {
+                    ui_motif_tabview_select(tabview, index+1);
+                } else {
+                    tabview->current_tab = NULL;
+                }
+            }
+        }
+        XtDestroyWidget(tab->tab_button);
+        XtDestroyWidget(tab->child);
+        cxListRemove(tabview->tabs, index);
+    }
+}
+
+void ui_motif_tabview_change_tab(UiMotifTabView *tabview, UiTab *tab) {
+    if(tabview->current_tab) {
+        XtVaSetValues(tabview->current_tab->tab_button, XmNshadowThickness, 0, XmNbackground, tabview->bg1, NULL);
+        XtUnmanageChild(tabview->current_tab->child);
+    }
+    XtVaSetValues(tab->tab_button, XmNshadowThickness, 1, XmNbackground, tabview->bg2, NULL);
+    tabview->current_tab = tab;
+    XtManageChild(tab->child);
 }
 
 Widget ui_tabview_container_prepare(UiContainerPrivate *ctn, Arg *args, int *n) {
index 07e4cdc4b3dcdc9c5f944e85f2e5e4e83d7981a0..f467e4ac52dc2a792bad43ce73901fdf3c43423c 100644 (file)
@@ -104,15 +104,25 @@ typedef struct UiGridContainer {
     Dimension y;
 } UiGridContainer;
 
+typedef struct UiTab {
+    Widget tab_button;
+    Widget child;
+} UiTab;
+
 typedef struct UiMotifTabView UiMotifTabView;
 struct UiMotifTabView {
+    UiObject *obj;
     Widget form;
     Widget tabbar;
     Widget content;
     Widget current;
+    UiTab *current_tab;
     int height;
     Pixel bg1;
     Pixel bg2;
+    Pixel fg1;
+    GC gc;
+    int gc_initialized;
     UiTabViewType tabview;
     UiSubContainerType subcontainer;
     CxList *tabs;
@@ -121,11 +131,6 @@ struct UiMotifTabView {
     void (*remove)(UiMotifTabView *tabview, int index);
 };
 
-typedef struct UiTab {
-    Widget tab_button;
-    Widget child;
-} UiTab;
-
 typedef struct UiTabViewContainer {
     UiContainerPrivate container;
     UiMotifTabView *tabview;
@@ -134,6 +139,7 @@ typedef struct UiTabViewContainer {
 void ui_motif_tabview_select(UiMotifTabView *tabview, int tab);
 void ui_motif_tabview_add_tab(UiMotifTabView *tabview, int index, const char *name, Widget child);
 void ui_motif_tabview_remove(UiMotifTabView *tabview, int index);
+void ui_motif_tabview_change_tab(UiMotifTabView *tabview, UiTab *tab);
 
 Widget ui_tabview_container_prepare(UiContainerPrivate *ctn, Arg *args, int *n);
 void ui_tabview_container_add(UiContainerPrivate *ctn, Widget widget);
index 8633c510338ad5c12ce946d4d8c817b110d69c7b..2bdc35f77dc117147a500519627b34f64b9172a3 100644 (file)
@@ -196,3 +196,78 @@ void ui_listview_setselection(UiList *list, UiListSelection selection) {
 void* ui_strmodel_getvalue(void *elm, int column) {
     return column == 0 ? elm : NULL;
 }
+
+/* ------------------------------- Drop Down ------------------------------- */
+
+static void ui_dropdown_selection(
+        Widget w,
+        UiListView *listview,
+        XmComboBoxCallbackStruct *cb)
+{
+    UiListSelection sel = { 0, NULL };
+    if(cb->item_position > 0) {
+        sel.count = 1;
+        sel.rows = malloc(sizeof(int));
+        sel.rows[0] = cb->item_position-1;
+    }
+    UiEvent event;
+    event.obj = listview->obj;
+    event.window = event.obj->window;
+    event.document = event.obj->ctx->document;
+    event.eventdata = &sel;
+    event.intval = 0;
+    if(listview->onactivate) {
+        listview->onactivate(&event, listview->onactivatedata);
+    }
+    if(listview->onselection) {
+        listview->onselection(&event, listview->onselectiondata);
+    }
+}
+
+UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs args) {
+    Arg xargs[16];
+    int n = 0;
+    
+    UiContainerPrivate *ctn = ui_obj_container(obj);
+    UI_APPLY_LAYOUT(ctn->layout, args);
+    
+    char *name = args.name ? (char*)args.name : "dropdown";
+    Widget parent = ctn->prepare(ctn, xargs, &n);
+    Widget widget = XmCreateDropDownList(parent, name, xargs, n);
+    XtManageChild(widget);
+    
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.list, args.varname, UI_VAR_LIST);
+    
+    UiListView *listview = malloc(sizeof(UiListView));
+    memset(listview, 0, sizeof(UiListView));
+    listview->obj = obj;
+    listview->widget = widget;
+    listview->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
+    listview->var = var;
+    listview->onactivate = args.onactivate;
+    listview->onactivatedata = args.onactivatedata;
+    listview->onselection = args.onselection;
+    listview->onselectiondata = args.onselectiondata;
+    
+    if(var) {
+        UiList *list = var->value;
+        list->obj = listview;
+        list->update = ui_listview_update;
+        list->getselection = ui_listview_getselection;
+        list->setselection = ui_listview_setselection;
+        ui_listview_update(list, 0);
+    }
+    
+    XtAddCallback(
+                widget,
+                XmNdestroyCallback,
+                (XtCallbackProc)ui_listview_destroy,
+                listview);
+    XtAddCallback(
+                widget,
+                XmNselectionCallback,
+                (XtCallbackProc)ui_dropdown_selection,
+                listview);
+    
+    return widget;
+}
index 09d58b0ff88ab4378e68847cead51ef46d9c4b0d..87b5d6e7df216c6ce40fc8f66b953e73f7e24be7 100644 (file)
@@ -49,6 +49,7 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) {
     
     Widget parent = ctn->prepare(ctn, xargs, &n);
     char *name = args.name ? (char*)args.name : "textarea";
+    XtSetArg(xargs[n], XmNwidth, 100); n++;
     Widget widget = XmCreateScrolledText(parent, name, xargs, n);
     XtManageChild(widget);
     
index c53912e2be8d9e2913315b67cd3895541644f0b9..7123858199c8248a3ce0ff0d7a5b5d391611fdec 100644 (file)
@@ -41,6 +41,7 @@ typedef struct UiButtonArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -62,6 +63,7 @@ typedef struct UiToggleArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
index ea14d8ced4a175b92920c01149b121b74141349f..c7d6523431d8e7ee23f86d1af5e918ded3b30047 100644 (file)
@@ -63,6 +63,7 @@ typedef struct UiWidgetArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -75,6 +76,7 @@ typedef struct UiContainerArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -84,6 +86,10 @@ typedef struct UiContainerArgs {
     int spacing;
     int columnspacing;
     int rowspacing;
+    UiBool def_hfill;
+    UiBool def_vfill;
+    UiBool def_hexpand;
+    UiBool def_vexpand;
 } UiContainerArgs;
 
 typedef struct UiFrameArgs {
@@ -92,6 +98,7 @@ typedef struct UiFrameArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -114,6 +121,7 @@ typedef struct UiTabViewArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -141,6 +149,7 @@ typedef struct UiHeaderbarArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -166,6 +175,7 @@ typedef struct UiSplitPaneArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -188,6 +198,7 @@ typedef struct UiItemListContainerArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -256,6 +267,8 @@ struct UiContainerX {
 #define ui_headerbar0(obj) for(ui_headerbar_create(obj, (UiHeaderbarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_sidebar0(obj) for(ui_sidebar_create(obj, (UiSidebarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
 
+#define ui_tabview_w(obj, w, ...) for(w = ui_tabview_create(obj, (UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+
 #define ui_hsplitpane(obj, ...) for(ui_hsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_vsplitpane(obj, ...) for(ui_vsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_hsplitpane0(obj) for(ui_hsplitpane_create(obj, (UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
@@ -305,6 +318,7 @@ UIEXPORT void ui_layout_hexpand(UiObject *obj, UiBool expand);
 UIEXPORT void ui_layout_vexpand(UiObject *obj, UiBool expand);
 UIEXPORT void ui_layout_hfill(UiObject *obj, UiBool fill);
 UIEXPORT void ui_layout_vfill(UiObject *obj, UiBool fill);
+UIEXPORT void ui_layout_override_defaults(UiObject *obj, UiBool d);
 UIEXPORT void ui_layout_width(UiObject *obj, int width);
 UIEXPORT void ui_layout_height(UiObject* obj, int width);
 UIEXPORT void ui_layout_colspan(UiObject *obj, int cols);
@@ -338,6 +352,7 @@ UIEXPORT int ui_container_finish(UiObject *obj);
     if(args.vexpand) ui_layout_vexpand(obj, 1); \
     if(args.hfill) ui_layout_hfill(obj, 1); \
     if(args.vfill) ui_layout_vfill(obj, 1); \
+    if(args.override_defaults) ui_layout_override_defaults(obj, 1); \
     if(args.colspan > 0) ui_layout_colspan(obj, args.colspan); \
     if(args.rowspan > 0) ui_layout_rowspan(obj, args.rowspan); \
     /*force caller to add ';'*/(void)0
index 66f6f390af83797730ae59c59d8dcc088c57e23d..58b4c8476b09f5fa2b347d6039929d3bb7c0ad58 100644 (file)
@@ -63,6 +63,7 @@ typedef struct UiLabelArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -81,6 +82,7 @@ typedef struct UiProgressbarArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     int width;
@@ -99,6 +101,7 @@ typedef struct UiProgressbarSpinnerArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
index d6fc039e12592652b4b51c60d189bbd3f986e63b..5c8990a98f59d0d3b44ec50bea733e28e8d30ab2 100644 (file)
@@ -42,6 +42,7 @@ typedef struct UiSpinnerArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
index c26ec3cd58e1b6f2689fe77c713cce4338189a66..94ab8a6961db9e412acebf8cd04afbf70e4de739 100644 (file)
@@ -43,6 +43,7 @@ typedef struct UiImageViewerArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
index 28ebb3f189677b9d381cc3ce61e5054af9aa7494..6bceadf9dfce0a5ee1da9117a02e7c6c356125c3 100644 (file)
@@ -35,8 +35,8 @@
 extern "C" {
 #endif
 
-UIWIDGET ui_hscrollbar(UiObject *obj, UiRange *range, ui_callback f, void *userdata);
-UIWIDGET ui_vscrollbar(UiObject *obj, UiRange *range, ui_callback f, void *userdata);
+UIWIDGET ui_hscrollbar(UiObject *obj, UiRange *range, ui_callback f, void *userdata); // TODO
+UIWIDGET ui_vscrollbar(UiObject *obj, UiRange *range, ui_callback f, void *userdata); // TODO
 
 
 
index cb54f4c5bd1f1a8f3d47f50061acdb3f6773ab5f..5c40df5ba1f35e05f72ddafdf32f08bf2fddbf74 100644 (file)
@@ -41,6 +41,7 @@ typedef struct UiTextAreaArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     int width;
@@ -61,6 +62,7 @@ typedef struct UiTextFieldArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     int width;
@@ -94,6 +96,7 @@ typedef struct UiPathTextFieldArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
index a81b3afe56814b574c200d6b41a6ab760bb9b5c1..eb652f022711a86fc25e7f1218ef4f078f63b6c7 100644 (file)
@@ -109,6 +109,7 @@ struct UiListArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
@@ -173,6 +174,7 @@ struct UiSourceListArgs {
     UiBool vexpand;
     UiBool hfill;
     UiBool vfill;
+    UiBool override_defaults;
     int colspan;
     int rowspan;
     const char *name;
index a0311e958ab66fe36395909bcdd2467ce76f05f8..41883f13926c47aaa0e5cb843b9709648489f930 100644 (file)
@@ -47,5 +47,7 @@
 #include "dnd.h"
 #include "icons.h"
 
+#include "webview.h"
+
 #endif /* UI_H */
 
diff --git a/ui/ui/webview.h b/ui/ui/webview.h
new file mode 100644 (file)
index 0000000..18bb5ac
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef UI_WEBVIEW_H
+#define UI_WEBVIEW_H
+
+#include "toolkit.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+typedef struct UiWebviewArgs {
+    UiTri fill;
+    UiBool hexpand;
+    UiBool vexpand;
+    UiBool hfill;
+    UiBool vfill;
+    UiBool override_defaults;
+    int colspan;
+    int rowspan;
+    const char *name;
+    const char *style_class;
+    
+    const int* groups;
+} UiWebviewArgs;
+
+#define ui_webview(obj, ...) ui_webview_create(obj, (UiWebviewArgs){ __VA_ARGS__ } )
+
+UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs args);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UI_WEBVIEW_H */
+