# HG changeset patch # User Olaf Wintermann # Date 1510484630 -3600 # Node ID 853685152c1d45a6b2c818e82d5fa22b121f3724 # Parent 29d98cff4f56df0a4bb498a932aa385b2a59dba0 adds spinner widget (GTK) diff -r 29d98cff4f56 -r 853685152c1d application/main.c --- a/application/main.c Sat Nov 11 12:22:16 2017 +0100 +++ b/application/main.c Sun Nov 12 12:03:50 2017 +0100 @@ -39,6 +39,8 @@ UiString *t2; UiString *t3; UiInteger *i; + UiDouble *d; + UiRange *r; } Document; Document *d1; @@ -82,6 +84,8 @@ doc->t3 = ui_string_new(ctx, "t3"); doc->i = ui_int_new(ctx, "int"); + doc->d = ui_double_new(ctx, "d"); + doc->r = ui_range_new(ctx, "r"); return doc; } @@ -97,6 +101,11 @@ printf("observ: %s\n", (char*)data); } +void doublechanged(UiEvent *event, void *data) { + UiDouble *d = event->eventdata; + printf("d: %f\n", (float)d->get(d)); +} + void application_startup(UiEvent *event, void *data) { //Document *doc = create_doc(); d1 = create_doc(); @@ -115,6 +124,12 @@ d1->t1->observers = ui_add_observer(d1->t1->observers, observ, "t1"); d1->text->observers = ui_add_observer(d1->text->observers, observ, "text"); + //ui_spinner_setrange(ui_spinnerf_nv(obj, 1, 0, "d"), 0, 1000); + ui_spinnerr_nv(obj, "r"); + d1->r->setrange(d1->r, 0, 10); + d1->r->setextent(d1->r, 1); + d1->d->observers = ui_add_observer(d1->d->observers, doublechanged, NULL); + ui_button(obj, "Switch Document", action_newdoc, NULL); ui_show(obj); diff -r 29d98cff4f56 -r 853685152c1d ui/common/context.c --- a/ui/common/context.c Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/common/context.c Sun Nov 12 12:03:50 2017 +0100 @@ -205,6 +205,10 @@ val = ui_int_new(ctx, NULL); break; } + case UI_VAR_DOUBLE: { + val = ui_double_new(ctx, NULL); + break; + } case UI_VAR_STRING: { val = ui_string_new(ctx, NULL); break; @@ -218,7 +222,7 @@ break; } case UI_VAR_RANGE: { - val = NULL; // TODO + val = ui_range_new(ctx, NULL); break; } } @@ -250,6 +254,14 @@ t->set(t, t->value); break; } + case UI_VAR_DOUBLE: { + UiDouble *f = from->value; + UiDouble *t = to->value; + if(!f->obj) break; + uic_double_copy(f, t); + t->set(t, t->value); + break; + } case UI_VAR_STRING: { UiString *f = from->value; UiString *t = to->value; @@ -298,6 +310,7 @@ void uic_save_var(UiVar *var) { switch(var->type) { case UI_VAR_INTEGER: uic_int_save(var->value); break; + case UI_VAR_DOUBLE: uic_double_save(var->value); break; case UI_VAR_STRING: uic_string_save(var->value); break; case UI_VAR_TEXT: uic_text_save(var->value); break; case UI_VAR_LIST: break; @@ -308,6 +321,7 @@ void uic_unbind_var(UiVar *var) { switch(var->type) { case UI_VAR_INTEGER: uic_int_unbind(var->value); break; + case UI_VAR_DOUBLE: uic_double_unbind(var->value); break; case UI_VAR_STRING: uic_string_unbind(var->value); break; case UI_VAR_TEXT: uic_text_unbind(var->value); break; case UI_VAR_LIST: uic_list_unbind(var->value); break; diff -r 29d98cff4f56 -r 853685152c1d ui/common/context.h --- a/ui/common/context.h Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/common/context.h Sun Nov 12 12:03:50 2017 +0100 @@ -48,6 +48,7 @@ enum UiVarType { UI_VAR_SPECIAL = 0, UI_VAR_INTEGER, + UI_VAR_DOUBLE, UI_VAR_STRING, UI_VAR_TEXT, UI_VAR_LIST, diff -r 29d98cff4f56 -r 853685152c1d ui/common/types.c --- a/ui/common/types.c Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/common/types.c Sun Nov 12 12:03:50 2017 +0100 @@ -223,6 +223,15 @@ return i; } +UiDouble* ui_double_new(UiContext *ctx, char *name) { + UiDouble *d = ui_malloc(ctx, sizeof(UiDouble)); + memset(d, 0, sizeof(UiDouble)); + if(name) { + uic_reg_var(ctx, name, UI_VAR_DOUBLE, d); + } + return d; +} + UiString* ui_string_new(UiContext *ctx, char *name) { UiString *s = ui_malloc(ctx, sizeof(UiString)); memset(s, 0, sizeof(UiString)); @@ -241,6 +250,15 @@ return t; } +UiRange* ui_range_new(UiContext *ctx, char *name) { + UiRange *r = ui_malloc(ctx, sizeof(UiRange)); + memset(r, 0, sizeof(UiRange)); + if(name) { + uic_reg_var(ctx, name, UI_VAR_RANGE, r); + } + return r; +} + // private functions void uic_int_copy(UiInteger *from, UiInteger *to) { @@ -249,6 +267,12 @@ to->obj = from->obj; } +void uic_double_copy(UiDouble *from, UiDouble *to) { + to->get = from->get; + to->set = from->set; + to->obj = from->obj; +} + void uic_string_copy(UiString *from, UiString *to) { to->get = from->get; to->set = from->set; @@ -289,6 +313,11 @@ i->value = i->get(i); } +void uic_double_save(UiDouble *d) { + if(!d->obj) return; + d->value = d->get(d); +} + void uic_string_save(UiString *s) { if(!s->obj) return; s->get(s); @@ -312,6 +341,12 @@ i->obj = NULL; } +void uic_double_unbind(UiDouble *d) { + d->get = NULL; + d->set = NULL; + d->obj = NULL; +} + void uic_string_unbind(UiString *s) { s->get = NULL; s->set = NULL; diff -r 29d98cff4f56 -r 853685152c1d ui/common/types.h --- a/ui/common/types.h Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/common/types.h Sun Nov 12 12:03:50 2017 +0100 @@ -37,17 +37,20 @@ void uic_int_copy(UiInteger *from, UiInteger *to); +void uic_double_copy(UiDouble *from, UiDouble *to); void uic_string_copy(UiString *from, UiString *to); void uic_text_copy(UiText *from, UiText *to); void uic_range_copy(UiRange *from, UiRange *to); void uic_list_copy(UiList *from, UiList *to); void uic_int_save(UiInteger *i); +void uic_double_save(UiDouble *d); void uic_string_save(UiString *s); void uic_text_save(UiText *t); void uic_range_save(UiRange *r); void uic_int_unbind(UiInteger *i); +void uic_double_unbind(UiDouble *d); void uic_string_unbind(UiString *s); void uic_text_unbind(UiText *t); void uic_range_unbind(UiRange *r); diff -r 29d98cff4f56 -r 853685152c1d ui/gtk/button.c --- a/ui/gtk/button.c Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/gtk/button.c Sun Nov 12 12:03:50 2017 +0100 @@ -122,6 +122,7 @@ UiVarEventData *event = malloc(sizeof(UiVarEventData)); event->obj = obj; event->var = var; + event->observers = NULL; g_signal_connect( button, @@ -179,6 +180,7 @@ UiVarEventData *event = malloc(sizeof(UiVarEventData)); event->obj = obj; event->var = var; + event->observers = NULL; g_signal_connect( rbutton, diff -r 29d98cff4f56 -r 853685152c1d ui/gtk/entry.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/gtk/entry.c Sun Nov 12 12:03:50 2017 +0100 @@ -0,0 +1,208 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 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 +#include + +#include "../common/context.h" +#include "../common/object.h" +#include "container.h" +#include "entry.h" + +#include "../../ucx/mempool.h" + +UIWIDGET ui_spinner(UiObject *obj, int step, UiInteger *i) { + UiVar *var = malloc(sizeof(UiVar)); + var->value = i; + var->type = UI_VAR_SPECIAL; + return ui_spinner_var(obj, step, 0, var, UI_VAR_INTEGER); +} + +UIWIDGET ui_spinnerf(UiObject *obj, double step, int digits, UiDouble *d) { + UiVar *var = malloc(sizeof(UiVar)); + var->value = d; + var->type = UI_VAR_SPECIAL; + return ui_spinner_var(obj, step, digits, var, UI_VAR_DOUBLE); +} + +UIWIDGET ui_spinnerr(UiObject *obj, UiRange *r) { + UiVar *var = malloc(sizeof(UiVar)); + var->value = r; + var->type = UI_VAR_SPECIAL; + return ui_spinner_var(obj, r->extent, 1, var, UI_VAR_RANGE); +} + +UIWIDGET ui_spinner_nv(UiObject *obj, int step, char *varname) { + UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_INTEGER); + return ui_spinner_var(obj, step, 0, var, UI_VAR_INTEGER); +} + +UIWIDGET ui_spinnerf_nv(UiObject *obj, double step, int digits, char *varname) { + UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_DOUBLE); + return ui_spinner_var(obj, step, digits, var, UI_VAR_DOUBLE); +} + +UIWIDGET ui_spinnerr_nv(UiObject *obj, char *varname) { + UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_RANGE); + UiRange *r = var->value; + return ui_spinner_var(obj, r->extent, 1, var, UI_VAR_RANGE); +} + +UIWIDGET ui_spinner_var(UiObject *obj, double step, int digits, UiVar *var, UiVarType type) { + double min = 0; + double max = 1000; + if(type == UI_VAR_RANGE) { + UiRange *r = var->value; + min = r->min; + max = r->max; + } + if(step == 0) { + step = 1; + } + GtkWidget *spin = gtk_spin_button_new_with_range(min, max, step); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), digits); + if(var) { + double value = 0; + UiObserver **obs = NULL; + switch(type) { + case UI_VAR_INTEGER: { + UiInteger *i = var->value; + i->get = ui_spinbutton_getint; + i->set = ui_spinbutton_setint; + i->obj = spin; + 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 = spin; + 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 = spin; + value = r->value; + obs = &r->observers; + break; + } + } + gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), value); + + UiVarEventData *event = malloc(sizeof(UiVarEventData)); + event->obj = obj; + event->var = var; + event->observers = obs; + + g_signal_connect( + spin, + "value-changed", + G_CALLBACK(ui_spinner_changed), + event); + g_signal_connect( + spin, + "destroy", + G_CALLBACK(ui_destroy_vardata), + event); + } + + UiContainer *ct = uic_get_current_container(obj); + ct->add(ct, spin, FALSE); + + return spin; +} + +void ui_spinner_setrange(UIWIDGET spinner, double min, double max) { + gtk_spin_button_set_range(GTK_SPIN_BUTTON(spinner), min, max); +} + +void ui_spinner_setdigits(UIWIDGET spinner, int digits) { + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spinner), digits); +} + + +void ui_spinner_changed(GtkSpinButton *spinner, UiVarEventData *event) { + UiEvent e; + e.obj = event->obj; + e.window = event->obj->window; + e.document = event->obj->ctx->document; + e.eventdata = event->var->value; + e.intval = 0; + + UiObserver *observer = *event->observers; + ui_notify_evt(observer, &e); +} + + +int64_t ui_spinbutton_getint(UiInteger *i) { + i->value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(i->obj)); + return i->value; +} + +void ui_spinbutton_setint(UiInteger *i, int64_t val) { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(i->obj), (double)val); + i->value = val; +} + +double ui_spinbutton_getdouble(UiDouble *d) { + d->value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(d->obj)); + return d->value; +} + +void ui_spinbutton_setdouble(UiDouble *d, double val) { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(d->obj), val); + d->value = val; +} + +double ui_spinbutton_getrangeval(UiRange *r) { + r->value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(r->obj)); + return r->value; +} + +void ui_spinbutton_setrangeval(UiRange *r, double val) { + gtk_spin_button_set_value(GTK_SPIN_BUTTON(r->obj), val); + r->value = val; +} +void ui_spinbutton_setrange(UiRange *r, double min, double max) { + gtk_spin_button_set_range(GTK_SPIN_BUTTON(r->obj), min, max); + r->min = min; + r->max = max; +} + +void ui_spinbutton_setextent(UiRange *r, double extent) { + gtk_spin_button_set_increments(GTK_SPIN_BUTTON(r->obj), extent, extent*10); + r->extent = extent; +} diff -r 29d98cff4f56 -r 853685152c1d ui/gtk/entry.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/gtk/entry.h Sun Nov 12 12:03:50 2017 +0100 @@ -0,0 +1,45 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: entry.h + * Author: olaf + * + * Created on 11. November 2017, 13:38 + */ + +#ifndef ENTRY_H +#define ENTRY_H + +#include "toolkit.h" +#include "../ui/entry.h" +#include "../common/context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +UIWIDGET ui_spinner_var(UiObject *obj, double step, int digits, UiVar *var, UiVarType type); +void ui_spinner_changed(GtkSpinButton *spinner, UiVarEventData *event); + +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 + +#endif /* ENTRY_H */ + diff -r 29d98cff4f56 -r 853685152c1d ui/gtk/objs.mk --- a/ui/gtk/objs.mk Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/gtk/objs.mk Sun Nov 12 12:03:50 2017 +0100 @@ -43,6 +43,7 @@ GTKOBJ += image.o GTKOBJ += graphics.o GTKOBJ += range.o +GTKOBJ += entry.o TOOLKITOBJS += $(GTKOBJ:%=$(GTK_OBJPRE)%) TOOLKITSOURCE += $(GTKOBJ:%.o=gtk/%.c) diff -r 29d98cff4f56 -r 853685152c1d ui/gtk/toolkit.h --- a/ui/gtk/toolkit.h Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/gtk/toolkit.h Sun Nov 12 12:03:50 2017 +0100 @@ -47,6 +47,7 @@ typedef struct UiVarEventData { UiObject *obj; UiVar *var; + UiObserver **observers; } UiVarEventData; diff -r 29d98cff4f56 -r 853685152c1d ui/ui/entry.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/ui/entry.h Sun Nov 12 12:03:50 2017 +0100 @@ -0,0 +1,54 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2017 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_ENTRY_H +#define UI_ENTRY_H + +#include "toolkit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +UIWIDGET ui_spinner(UiObject *obj, int step, UiInteger *i); +UIWIDGET ui_spinnerf(UiObject *obj, double step, int digits, UiDouble *d); +UIWIDGET ui_spinnerr(UiObject *obj, UiRange *r); + +UIWIDGET ui_spinner_nv(UiObject *obj, int step, char *varname); +UIWIDGET ui_spinnerf_nv(UiObject *obj, double step, int digits, char *varname); +UIWIDGET ui_spinnerr_nv(UiObject *obj, char *varname); + +void ui_spinner_setrange(UIWIDGET spinner, double min, double max); +void ui_spinner_setdigits(UIWIDGET spinner, int digits); + +#ifdef __cplusplus +} +#endif + +#endif /* UI_ENTRY_H */ + diff -r 29d98cff4f56 -r 853685152c1d ui/ui/toolkit.h --- a/ui/ui/toolkit.h Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/ui/toolkit.h Sun Nov 12 12:03:50 2017 +0100 @@ -94,6 +94,7 @@ typedef struct UiObserver UiObserver; typedef struct UiInteger UiInteger; +typedef struct UiDouble UiDouble; typedef struct UiString UiString; typedef struct UiText UiText; typedef struct UiList UiList; @@ -195,7 +196,16 @@ void (*set)(UiInteger*, int64_t); void *obj; - int64_t value; + int64_t value; + UiObserver *observers; +}; + +struct UiDouble { + double (*get)(UiDouble*); + void (*set)(UiDouble*, double); + void *obj; + + double value; UiObserver *observers; }; @@ -308,8 +318,10 @@ // types UiInteger* ui_int_new(UiContext *ctx, char *name); +UiDouble* ui_double_new(UiContext *ctx, char *name); UiString* ui_string_new(UiContext *ctx, char *name); UiText* ui_text_new(UiContext *ctx, char *name); +UiRange* ui_range_new(UiContext *ctx, char *name); UiObserver* ui_observer_new(ui_callback f, void *data); UiObserver* ui_obsvlist_add(UiObserver *list, UiObserver *observer); diff -r 29d98cff4f56 -r 853685152c1d ui/ui/ui.h --- a/ui/ui/ui.h Sat Nov 11 12:22:16 2017 +0100 +++ b/ui/ui/ui.h Sun Nov 12 12:03:50 2017 +0100 @@ -40,6 +40,7 @@ #include "properties.h" #include "tree.h" #include "graphics.h" +#include "entry.h" #include "range.h" #endif /* UI_H */