ui/gtk/display.c

changeset 431
bb7da585debc
parent 358
98b26a19cbeb
--- a/ui/gtk/display.c	Sun May 23 09:44:43 2021 +0200
+++ b/ui/gtk/display.c	Sat Jan 04 16:38:48 2025 +0100
@@ -31,12 +31,14 @@
 
 #include "display.h"
 #include "container.h"
-#include <ucx/mempool.h>
 #include "../common/context.h"
 #include "../common/object.h"
+#include "../ui/display.h"
+
+#include <cx/printf.h>
 
 static void set_alignment(GtkWidget *widget, float xalign, float yalign) {
-#if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16
+#if GTK_MAJOR_VERSION >= 4 || (GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16)
     gtk_label_set_xalign(GTK_LABEL(widget), xalign);
     gtk_label_set_yalign(GTK_LABEL(widget), yalign);
 #else
@@ -44,30 +46,108 @@
 #endif
 }
 
-UIWIDGET ui_label(UiObject *obj, char *label) { 
-    GtkWidget *widget = gtk_label_new(label);
+UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) {
+    UiObject* current = uic_current_obj(obj);
     
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(ct, widget, FALSE);
+    const char *css_class = NULL;
+    char *markup = NULL;
+    if(args.label) {
+        #if GTK_MAJOR_VERSION < 3
+            switch(args.style) {
+                case UI_LABEL_STYLE_DEFAULT: break;
+                case UI_LABEL_STYLE_TITLE: {
+                    cxmutstr m = cx_asprintf("<b>%s</b>", args.label);
+                    markup = m.ptr;
+                    args.label = NULL;
+                }
+                case UI_LABEL_STYLE_SUBTITLE: {
+                    break;
+                }
+                case UI_LABEL_STYLE_DIM: {
+                    break;
+                }
+            }
+#       else
+            switch(args.style) {
+                case UI_LABEL_STYLE_DEFAULT: break;
+                case UI_LABEL_STYLE_TITLE: {
+                    css_class = "ui_label_title";
+                    break;
+                }
+                case UI_LABEL_STYLE_SUBTITLE: {
+                    css_class = "subtitle";
+                    break;
+                }
+                case UI_LABEL_STYLE_DIM: {
+                    css_class = "dim-label";
+                    break;
+                }
+            }
+#       endif
+    }
+
+    
+    GtkWidget *widget = gtk_label_new(args.label);
+    if(markup) {
+        gtk_label_set_markup(GTK_LABEL(widget), markup);
+        free(markup);
+    }
+    
+    if(css_class) {
+        WIDGET_ADD_CSS_CLASS(widget, css_class);
+    }
+    
+    switch(args.align) {
+        case UI_ALIGN_DEFAULT: break;
+        case UI_ALIGN_LEFT: set_alignment(widget, 0, .5); break;
+        case UI_ALIGN_RIGHT: set_alignment(widget, 1, .5); break;
+        case UI_ALIGN_CENTER: break; // TODO
+    }
+    
+
+    UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING);
+    if(var) {
+        UiString* value = (UiString*)var->value;
+        value->obj = widget;
+        value->get = ui_label_get;
+        value->set = ui_label_set;
+    }
+    
+    UI_APPLY_LAYOUT1(current, args);
+    current->container->add(current->container, widget, FALSE);
     
     return widget;
 }
 
-UIWIDGET ui_llabel(UiObject *obj, char *label) {
-    UIWIDGET widget = ui_label(obj, label);
-    set_alignment(widget, 0, .5);
-    return widget;
+UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args) {
+    args.align = UI_ALIGN_LEFT;
+    return ui_label_create(obj, args);
+}
+
+UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args) {
+    args.align = UI_ALIGN_RIGHT;
+    return ui_label_create(obj, args);
 }
 
-UIWIDGET ui_rlabel(UiObject *obj, char *label) {
-    UIWIDGET widget = ui_label(obj, label);
-    //gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_RIGHT);
-    
-    set_alignment(widget, 1, .5);
-    return widget;
+char* ui_label_get(UiString *s) {
+    if(s->value.ptr) {
+        s->value.free(s->value.ptr);
+    }
+    s->value.ptr = g_strdup(gtk_label_get_text(GTK_LABEL(s->obj)));
+    s->value.free = (ui_freefunc)g_free;
+    return s->value.ptr;
 }
 
-UIWIDGET ui_space(UiObject *obj) {
+void ui_label_set(UiString *s, const char *value) {
+    gtk_label_set_text(GTK_LABEL(s->obj), value);
+    if(s->value.ptr) {
+        s->value.free(s->value.ptr);
+        s->value.ptr = NULL;
+        s->value.free = NULL;
+    }
+}
+
+UIWIDGET ui_space_deprecated(UiObject *obj) {
     GtkWidget *widget = gtk_label_new("");
     UiContainer *ct = uic_get_current_container(obj);
     ct->add(ct, widget, TRUE);
@@ -75,8 +155,8 @@
     return widget;
 }
 
-UIWIDGET ui_separator(UiObject *obj) {
-#if UI_GTK3
+UIWIDGET ui_separator_deprecated(UiObject *obj) {
+#if GTK_MAJOR_VERSION >= 3
     GtkWidget *widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
 #else
     GtkWidget *widget = gtk_hseparator_new();
@@ -89,40 +169,97 @@
 
 /* ------------------------- progress bar ------------------------- */
 
-UIWIDGET ui_progressbar(UiObject *obj, UiDouble *value) {
-    UiVar *var = malloc(sizeof(UiVar));
-    var->value = value;
-    var->type = UI_VAR_SPECIAL;
-    return ui_progressbar_var(obj, var);
-}
+typedef struct UiProgressBarRange {
+    double min;
+    double max;
+} UiProgressBarRange;
 
-UIWIDGET ui_progressbar_nv(UiObject *obj, char *varname) {
-    UiVar *var = uic_create_var(obj->ctx, varname, UI_VAR_DOUBLE);
-    return ui_progressbar_var(obj, var);
-}
-
-UIWIDGET ui_progressbar_var(UiObject *obj, UiVar *var) {
+UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) {
+    UiObject* current = uic_current_obj(obj);
+    
     GtkWidget *progressbar = gtk_progress_bar_new();
+    if(args.max > args.min) {
+        UiProgressBarRange *range = malloc(sizeof(UiProgressBarRange));
+        range->min = args.min;
+        range->max = args.max;
+        g_signal_connect(
+                progressbar,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                range);
+        g_object_set_data(G_OBJECT(progressbar), "ui_range", range);
+    }
+    
+    
+    UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_DOUBLE);
     if(var && var->value) {
         UiDouble *value = var->value;
         value->get = ui_progressbar_get;
         value->set = ui_progressbar_set;
         value->obj = progressbar;
-        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), 0.5);
+        ui_progressbar_set(value, value->value);
     }
     
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(ct, progressbar, FALSE);
+    UI_APPLY_LAYOUT1(current, args);
+    current->container->add(current->container, progressbar, FALSE);
     
     return progressbar;
 }
 
 double ui_progressbar_get(UiDouble *d) {
-    d->value = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(d->obj));
+    UiProgressBarRange *range = g_object_get_data(d->obj, "ui_range");
+    double fraction = gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(d->obj));
+    if(range) {
+        fraction = range->min + (range->max - range->min) * fraction;
+    }
+    d->value = fraction;
     return d->value;
 }
 
 void ui_progressbar_set(UiDouble *d, double value) {
+    d->value = value;
+    UiProgressBarRange *range = g_object_get_data(d->obj, "ui_range");
+    if(range) {
+        value = (value - range->min) / (range->max - range->min);
+    }
     gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(d->obj), value);
-    d->value = value;
 }
+
+
+/* ------------------------- progress spinner ------------------------- */
+
+UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args) {
+    UiObject* current = uic_current_obj(obj);
+    
+    GtkWidget *spinner = gtk_spinner_new();
+    
+    UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER);
+    if(var && var->value) {
+        UiInteger *value = var->value;
+        value->get = ui_spinner_get;
+        value->set = ui_spinner_set;
+        value->obj = spinner;
+        ui_spinner_set(value, value->value);
+    }
+    
+    UI_APPLY_LAYOUT1(current, args);
+    current->container->add(current->container, spinner, FALSE);
+    
+    return spinner;
+}
+
+int64_t ui_spinner_get(UiInteger *i) {
+    return i->value;
+}
+
+void ui_spinner_set(UiInteger *i, int64_t value) {
+    i->value = value;
+    if(i->obj) {
+        GtkSpinner *spinner = GTK_SPINNER(i->obj);
+        if(value != 0) {
+            gtk_spinner_start(spinner);
+        } else {
+            gtk_spinner_stop(spinner);
+        }
+    }
+}

mercurial