implement spinbox value binding (Motif)

Sat, 15 Nov 2025 09:24:55 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 15 Nov 2025 09:24:55 +0100
changeset 898
0484fc666c1d
parent 897
0d488f04078d
child 899
7e153ce81477

implement spinbox value binding (Motif)

application/main.c file | annotate | diff | comparison | revisions
ui/motif/button.c file | annotate | diff | comparison | revisions
ui/motif/entry.c file | annotate | diff | comparison | revisions
ui/motif/entry.h file | annotate | diff | comparison | revisions
ui/motif/menu.c file | annotate | diff | comparison | revisions
ui/motif/text.c file | annotate | diff | comparison | revisions
ui/motif/toolkit.c file | annotate | diff | comparison | revisions
ui/motif/toolkit.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Fri Nov 14 22:02:00 2025 +0100
+++ b/application/main.c	Sat Nov 15 09:24:55 2025 +0100
@@ -921,6 +921,7 @@
     UiList *list;
     UiInteger *spinner;
     UiInteger *tab;
+    UiDouble *num;
 } WData;
 
 
@@ -975,6 +976,7 @@
     wdata->list = ui_list_new(obj->ctx, NULL);
     wdata->spinner = ui_int_new(obj->ctx, NULL);
     wdata->tab = ui_int_new(obj->ctx, NULL);
+    wdata->num = ui_double_new(obj->ctx, "num");
     obj->window = wdata;
     
     ui_list_append(wdata->list, "List Item 1");
@@ -1012,7 +1014,7 @@
         
         ui_tab(obj, "Tab 4") {
             ui_grid(obj, .margin = 10) {
-                ui_spinbox(obj, .varname = "num1");
+                ui_spinbox(obj, .varname = "num");
             }
         }
     }
--- a/ui/motif/button.c	Fri Nov 14 22:02:00 2025 +0100
+++ b/ui/motif/button.c	Sat Nov 15 09:24:55 2025 +0100
@@ -77,7 +77,7 @@
        XtAddCallback(
                 button,
                 XmNdestroyCallback,
-                (XtCallbackProc)ui_destroy_eventdata,
+                (XtCallbackProc)ui_destroy_data,
                 eventdata);
     }
     
@@ -224,7 +224,7 @@
     XtAddCallback(
             widget,
             XmNdestroyCallback,
-            (XtCallbackProc)ui_destroy_eventdata,
+            (XtCallbackProc)ui_destroy_data,
             event);
 }
 
@@ -341,7 +341,7 @@
     XtAddCallback(
             rbutton,
             XmNdestroyCallback,
-            (XtCallbackProc)ui_destroy_eventdata,
+            (XtCallbackProc)ui_destroy_data,
             event);
 }
 
@@ -411,7 +411,7 @@
     XtAddCallback(
             button,
             XmNdestroyCallback,
-            (XtCallbackProc)ui_destroy_eventdata,
+            (XtCallbackProc)ui_destroy_data,
             event);
     
     XmStringFree(label);
--- a/ui/motif/entry.c	Fri Nov 14 22:02:00 2025 +0100
+++ b/ui/motif/entry.c	Sat Nov 15 09:24:55 2025 +0100
@@ -106,46 +106,160 @@
             textfield = children[i];
         }
     }
-    
+     
     UiSpinBox *data = malloc(sizeof(UiSpinBox));
     data->obj = obj;
     data->textfield = textfield;
     data->var = var;
     data->vartype = vartype;
+    data->obs = NULL;
     data->onchange = args->onchange;
     data->onchangedata = args->onchangedata;
-    data->last_value = 0;
+    data->value = 0;
     data->min = min;
     data->max = max;
     data->increment = args->step;
     data->digits = args->digits;
     
+    UiObserver **obs = NULL;
+    if(var) {
+        double value = 0;
+        switch(vartype) {
+            default: break;
+            case UI_VAR_INTEGER: {
+                UiInteger *i = var->value;
+                i->get = ui_spinbutton_getint;
+                i->set = ui_spinbutton_setint;
+                i->obj = data;
+                value = (double)i->value;
+                obs = &i->observers;
+                break;
+            }
+            case UI_VAR_DOUBLE: {
+                UiDouble *d = var->value;
+                d->get = ui_spinbutton_getdouble;
+                d->set = ui_spinbutton_setdouble;
+                d->obj = data;
+                value = d->value;
+                obs = &d->observers;
+                break;
+            }
+            case UI_VAR_RANGE: {
+                UiRange *r = var->value;
+                r->get = ui_spinbutton_getrangeval;
+                r->set = ui_spinbutton_setrangeval;
+                r->setrange = ui_spinbutton_setrange;
+                r->setextent = ui_spinbutton_setextent;
+                r->obj = data;
+                value = r->value;
+                obs = &r->observers;
+                break;
+            }
+        }
+        ui_spinbox_set_value(data, value);
+    }
+    data->obs = obs;
+    
     XtAddCallback(
             spinbox,
             XmNvalueChangedCallback,
             (XtCallbackProc)ui_spinbox_value_changed,
             data);
     
+    XtAddCallback(
+            spinbox,
+            XmNdestroyCallback,
+            (XtCallbackProc)ui_destroy_data,
+            data);
+    
     XmTextFieldSetString(textfield, "0");
     
     
     return spinbox;
 }
 
+void ui_spinbox_set_value(UiSpinBox *spinbox, double value) {
+    if(value < spinbox->min) {
+        value = spinbox->min;
+    }
+    if(value > spinbox->max) {
+        value = spinbox->max;
+    }
+    
+    char buf[32];
+    snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->value);
+    XmTextFieldSetString(spinbox->textfield, buf);
+    spinbox->value = value;
+}
+
 void ui_spinbox_value_changed(Widget widget, UiSpinBox *spinbox, XmSpinBoxCallbackStruct *cb) {
-    char buf[32];
+    Boolean update_value = TRUE;
+    double value = spinbox->value;
     switch(cb->reason) {
-        case 62: {
-            spinbox->last_value += spinbox->increment;
-            snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->last_value);
-            XmTextFieldSetString(spinbox->textfield, buf);
+        case XmCR_OK: {
+            update_value = FALSE;
             break;
         }
-        case 63: {
-            spinbox->last_value -= spinbox->increment;
-            snprintf(buf, 32, "%.*f", spinbox->digits, spinbox->last_value);
-            XmTextFieldSetString(spinbox->textfield, buf);
+        case XmCR_SPIN_NEXT: {
+            value += spinbox->increment;
+            break;
+        }
+        case XmCR_SPIN_PRIOR: {
+            value -= spinbox->increment;
             break;
         }
     }
+    
+    if(update_value) {
+        ui_spinbox_set_value(spinbox, value);
+    }
 }
+
+int64_t ui_spinbutton_getint(UiInteger *i) {
+    UiSpinBox *spinbox = i->obj;
+    i->value = (int64_t)spinbox->value;
+    return i->value;
+}
+
+void ui_spinbutton_setint(UiInteger *i, int64_t val) {
+    UiSpinBox *spinbox = i->obj;
+    ui_spinbox_set_value(spinbox, (double)val);
+    i->value = spinbox->value;
+}
+
+double ui_spinbutton_getdouble(UiDouble *d) {
+    UiSpinBox *spinbox = d->obj;
+    d->value = spinbox->value;
+    return d->value;
+}
+
+void ui_spinbutton_setdouble(UiDouble *d, double val) {
+    UiSpinBox *spinbox = d->obj;
+    ui_spinbox_set_value(spinbox, val);
+    d->value = spinbox->value;
+}
+
+double ui_spinbutton_getrangeval(UiRange *r) {
+    UiSpinBox *spinbox = r->obj;
+    r->value = spinbox->value;
+    return r->value;
+}
+
+void ui_spinbutton_setrangeval(UiRange *r, double val) {
+    UiSpinBox *spinbox = r->obj;
+    ui_spinbox_set_value(spinbox, val);
+    r->value = spinbox->value;
+}
+void ui_spinbutton_setrange(UiRange *r, double min, double max) {
+    UiSpinBox *spinbox = r->obj;
+    spinbox->min = min;
+    spinbox->max = max;
+    r->min = min;
+    r->max = max;
+}
+
+void ui_spinbutton_setextent(UiRange *r, double extent) {
+    UiSpinBox *spinbox = r->obj;
+    spinbox->increment = extent;
+    r->extent = extent;
+}
--- a/ui/motif/entry.h	Fri Nov 14 22:02:00 2025 +0100
+++ b/ui/motif/entry.h	Sat Nov 15 09:24:55 2025 +0100
@@ -44,17 +44,31 @@
     Widget textfield;
     UiVar *var;
     UiVarType vartype;
+    UiObserver **obs;
     ui_callback onchange;
     void* onchangedata;
-    double last_value;
+    double value;
     double min;
     double max;
     double increment;
     int digits;
 } UiSpinBox;
+
+void ui_spinbox_set_value(UiSpinBox *spinbox, double value);
     
 void ui_spinbox_value_changed(Widget widget, UiSpinBox *spinbox, XmSpinBoxCallbackStruct *cb);
 
+int64_t ui_spinbutton_getint(UiInteger *i);
+void ui_spinbutton_setint(UiInteger *i, int64_t val);
+
+double ui_spinbutton_getdouble(UiDouble *d);
+void ui_spinbutton_setdouble(UiDouble *d, double val);
+
+double ui_spinbutton_getrangeval(UiRange *r);
+void ui_spinbutton_setrangeval(UiRange *r, double val);
+void ui_spinbutton_setrange(UiRange *r, double min, double max);
+void ui_spinbutton_setextent(UiRange *r, double extent);
+
 #ifdef __cplusplus
 }
 #endif
--- a/ui/motif/menu.c	Fri Nov 14 22:02:00 2025 +0100
+++ b/ui/motif/menu.c	Sat Nov 15 09:24:55 2025 +0100
@@ -145,7 +145,7 @@
        XtAddCallback(
                 mitem,
                 XmNdestroyCallback,
-                (XtCallbackProc)ui_destroy_eventdata,
+                (XtCallbackProc)ui_destroy_data,
                 eventdata);
     }
     
@@ -337,7 +337,7 @@
             XtAddCallback(
                     mitem,
                     XmNdestroyCallback,
-                    (XtCallbackProc)ui_destroy_eventdata,
+                    (XtCallbackProc)ui_destroy_data,
                     eventdata);
         }
         
--- a/ui/motif/text.c	Fri Nov 14 22:02:00 2025 +0100
+++ b/ui/motif/text.c	Sat Nov 15 09:24:55 2025 +0100
@@ -1018,7 +1018,7 @@
         XtAddCallback(
                 pathbar->widget,
                 XmNdestroyCallback,
-                (XtCallbackProc)ui_destroy_eventdata,
+                (XtCallbackProc)ui_destroy_data,
                 eventdata);
     }
     
--- a/ui/motif/toolkit.c	Fri Nov 14 22:02:00 2025 +0100
+++ b/ui/motif/toolkit.c	Sat Nov 15 09:24:55 2025 +0100
@@ -325,7 +325,7 @@
             4);
 }
 
-void ui_destroy_eventdata(Widget w, XtPointer data, XtPointer d) {
+void ui_destroy_data(Widget w, XtPointer data, XtPointer d) {
     free(data);
 }
 
--- a/ui/motif/toolkit.h	Fri Nov 14 22:02:00 2025 +0100
+++ b/ui/motif/toolkit.h	Sat Nov 15 09:24:55 2025 +0100
@@ -93,7 +93,7 @@
 void ui_secondary_event_loop(int *loop);
 void ui_window_dark_theme(Display *dp, Window window);
 
-void ui_destroy_eventdata(Widget w, XtPointer data, XtPointer d);
+void ui_destroy_data(Widget w, XtPointer data, XtPointer d);
 
 void ui_set_widget_groups(UiContext *ctx, Widget widget, const int *groups) ;
 void ui_set_widget_ngroups(UiContext *ctx, Widget widget, const int *groups, size_t ngroups);

mercurial