ui/motif/entry.c

Sun, 07 Dec 2025 12:24:12 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 07 Dec 2025 12:24:12 +0100
changeset 964
c563220d9aea
parent 899
7e153ce81477
child 966
e411ed7c5f10
permissions
-rw-r--r--

implement ui_listview_destroy (Motif)

/*
 * 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 "entry.h"


UIWIDGET ui_spinbox_create(UiObject *obj, UiSpinBoxArgs *args) {
    Arg xargs[16];
    int n = 0;
    
    double min = args->min;
    double max = args->max != 0 ? args->max : 1000;
    
    UiVar *var = NULL;
    UiVarType vartype = 0;
    if(args->varname) {
        var = uic_get_var(obj->ctx, args->varname);
        if(var) {
            vartype = var->type;
        } else {
            var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, args->varname, UI_VAR_RANGE);
            vartype = UI_VAR_RANGE;
        }
    }
    
    if(!var) {
        if(args->intvalue) {
            var = uic_widget_var(obj->ctx, obj->ctx, args->intvalue, NULL, UI_VAR_INTEGER);
            vartype = UI_VAR_INTEGER;
        } else if(args->doublevalue) {
            var = uic_widget_var(obj->ctx, obj->ctx, args->doublevalue, NULL, UI_VAR_DOUBLE);
            vartype = UI_VAR_DOUBLE;
        } else if(args->rangevalue) {
            var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, NULL, UI_VAR_RANGE);
            vartype = UI_VAR_RANGE;
        }
    }
    
    if(vartype == UI_VAR_RANGE) {
        UiRange *r = var->value;
        min = r->min;
        max = r->max;
    }
    if(args->step == 0) {
        args->step = 1;
    }
    
    UiContainerPrivate *ctn = ui_obj_container(obj);
    UiLayout layout = UI_ARGS2LAYOUT(args);

    
    XtSetArg(xargs[n], XmNminimumValue, 0); n++;
    XtSetArg(xargs[n], XmNmaximumValue, 100); n++;
    XtSetArg(xargs[n], XmNincrementValue, 1); n++;
    XtSetArg(xargs[n], XmNspinBoxChildType, XmNUMERIC); n++;
    
    Widget parent = ui_container_prepare(ctn, &layout, xargs, &n);
    
    char *name = args->name ? (char*)args->name : "button";
    Widget spinbox = XmCreateSimpleSpinBox(parent, name, xargs, n);
    XtManageChild(spinbox);
    ui_container_add(ctn, spinbox);
    
    ui_set_widget_groups(obj->ctx, spinbox, args->groups);
    
    WidgetList children;
    Cardinal num_children;
    unsigned char type;
    
    Widget textfield = NULL;
    XtVaGetValues(
            spinbox,
            XmNchildren, &children,
            XmNnumChildren, &num_children,
            NULL);

    for(int i = 0;i<num_children;i++) {
        XtVaGetValues(children[i], XmNspinBoxChildType, &type, NULL);
        Widget w = children[i];
        if(type == XmNUMERIC) {
            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->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) {
    Boolean update_value = TRUE;
    double value = spinbox->value;
    switch(cb->reason) {
        case XmCR_OK: {
            update_value = FALSE;
            break;
        }
        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);
        
        UiEvent event;
        event.obj = spinbox->obj;
        event.window = event.obj->window;
        event.document = event.obj->ctx->document;
        event.eventdata = NULL;
        event.eventdatatype = 0;
        event.intval = (int64_t)value;
        event.set = ui_get_setop();
        
        if(spinbox->onchange) {
            spinbox->onchange(&event, spinbox->onchangedata);
        }

        UiObserver *obs = *spinbox->obs;
        ui_notify_evt(*spinbox->obs, &event);
    }
}

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;
}

mercurial