From: Olaf Wintermann Date: Sun, 16 Feb 2025 20:23:22 +0000 (+0100) Subject: update toolkit X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=746c0b9f892a098f0ef0fcfcb7eedc8251b3a70b;p=note.git update toolkit --- diff --git a/application/window.c b/application/window.c index d731c60..a152bb5 100644 --- a/application/window.c +++ b/application/window.c @@ -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); diff --git a/ui/gtk/container.c b/ui/gtk/container.c index 17b4e4c..9df3009 100644 --- a/ui/gtk/container.c +++ b/ui/gtk/container.c @@ -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; diff --git a/ui/gtk/container.h b/ui/gtk/container.h index 271ed50..421451d 100644 --- a/ui/gtk/container.h +++ b/ui/gtk/container.h @@ -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); diff --git a/ui/gtk/objs.mk b/ui/gtk/objs.mk index 865216e..ed89f4d 100644 --- a/ui/gtk/objs.mk +++ b/ui/gtk/objs.mk @@ -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 index 0000000..6f204a1 --- /dev/null +++ b/ui/gtk/webview.c @@ -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 + +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 index 0000000..f4fd44b --- /dev/null +++ b/ui/gtk/webview.h @@ -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 */ + diff --git a/ui/motif/Grid.c b/ui/motif/Grid.c index bb177dd..b1abbe0 100644 --- a/ui/motif/Grid.c +++ b/ui/motif/Grid.c @@ -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; diff --git a/ui/motif/container.c b/ui/motif/container.c index 3354d35..08acc77 100644 --- a/ui/motif/container.c +++ b/ui/motif/container.c @@ -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) { diff --git a/ui/motif/container.h b/ui/motif/container.h index 07e4cdc..f467e4a 100644 --- a/ui/motif/container.h +++ b/ui/motif/container.h @@ -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); diff --git a/ui/motif/list.c b/ui/motif/list.c index 8633c51..2bdc35f 100644 --- a/ui/motif/list.c +++ b/ui/motif/list.c @@ -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; +} diff --git a/ui/motif/text.c b/ui/motif/text.c index 09d58b0..87b5d6e 100644 --- a/ui/motif/text.c +++ b/ui/motif/text.c @@ -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); diff --git a/ui/ui/button.h b/ui/ui/button.h index c53912e..7123858 100644 --- a/ui/ui/button.h +++ b/ui/ui/button.h @@ -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; diff --git a/ui/ui/container.h b/ui/ui/container.h index ea14d8c..c7d6523 100644 --- a/ui/ui/container.h +++ b/ui/ui/container.h @@ -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 diff --git a/ui/ui/display.h b/ui/ui/display.h index 66f6f39..58b4c84 100644 --- a/ui/ui/display.h +++ b/ui/ui/display.h @@ -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; diff --git a/ui/ui/entry.h b/ui/ui/entry.h index d6fc039..5c8990a 100644 --- a/ui/ui/entry.h +++ b/ui/ui/entry.h @@ -42,6 +42,7 @@ typedef struct UiSpinnerArgs { UiBool vexpand; UiBool hfill; UiBool vfill; + UiBool override_defaults; int colspan; int rowspan; const char *name; diff --git a/ui/ui/image.h b/ui/ui/image.h index c26ec3c..94ab8a6 100644 --- a/ui/ui/image.h +++ b/ui/ui/image.h @@ -43,6 +43,7 @@ typedef struct UiImageViewerArgs { UiBool vexpand; UiBool hfill; UiBool vfill; + UiBool override_defaults; int colspan; int rowspan; const char *name; diff --git a/ui/ui/range.h b/ui/ui/range.h index 28ebb3f..6bceadf 100644 --- a/ui/ui/range.h +++ b/ui/ui/range.h @@ -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 diff --git a/ui/ui/text.h b/ui/ui/text.h index cb54f4c..5c40df5 100644 --- a/ui/ui/text.h +++ b/ui/ui/text.h @@ -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; diff --git a/ui/ui/tree.h b/ui/ui/tree.h index a81b3af..eb652f0 100644 --- a/ui/ui/tree.h +++ b/ui/ui/tree.h @@ -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; diff --git a/ui/ui/ui.h b/ui/ui/ui.h index a0311e9..41883f1 100644 --- a/ui/ui/ui.h +++ b/ui/ui/ui.h @@ -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 index 0000000..18bb5ac --- /dev/null +++ b/ui/ui/webview.h @@ -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 */ +