add dialog window (GTK) newapi

Wed, 23 Oct 2024 14:52:18 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 23 Oct 2024 14:52:18 +0200
branch
newapi
changeset 344
870dd3d41d83
parent 343
54f5d7eb1335
child 345
d2ccc543f432

add dialog window (GTK)

application/main.c file | annotate | diff | comparison | revisions
ui/gtk/button.c file | annotate | diff | comparison | revisions
ui/gtk/button.h file | annotate | diff | comparison | revisions
ui/gtk/container.c file | annotate | diff | comparison | revisions
ui/gtk/container.h file | annotate | diff | comparison | revisions
ui/gtk/headerbar.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.h file | annotate | diff | comparison | revisions
ui/gtk/window.c file | annotate | diff | comparison | revisions
ui/ui/window.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Tue Oct 22 21:17:01 2024 +0200
+++ b/application/main.c	Wed Oct 23 14:52:18 2024 +0200
@@ -79,6 +79,22 @@
     ui_dialog(event->obj, .title = "Dialog Title", .content = "Content Label", .button1_label = "btn1", .button2_label = "btn2", .input = TRUE, .closebutton_label = "Cancel");
 }
 
+void action_dialog_button(UiEvent *event, void *userdata) {
+    ui_close(event->obj);
+}
+
+void action_toolbar_dialog(UiEvent *event, void *userdata) {
+    
+    UiObject *dialog = ui_dialog_window(event->obj, .title  = "Dialog Window", .lbutton1 = "Cancel 1", .lbutton2 = "Btn2", .rbutton3 = "Btn3", .rbutton4 = "Login 4", .onclick = action_dialog_button, .show_closebutton = UI_OFF);
+    
+    ui_vbox(dialog, .margin = 10, .spacing = 10) {
+        ui_label(dialog, .label = "Enter password:");
+        ui_passwordfield(dialog, .varname = "password");
+    }
+    
+    ui_show(dialog);
+}
+
 void action_toolbar_newwindow(UiEvent *event, void *userdata) {
     UiObject *obj = ui_simple_window("New Window", NULL);
     
@@ -236,7 +252,12 @@
             }
         }
         ui_tab(obj, "Tab 2") {
-            ui_button(obj, .label = "Button", .onclick=action_tab2_button);
+            ui_button(obj, .label = "Button 1", .onclick=action_tab2_button);
+            ui_button(obj, .label = "Button 2", .onclick=action_tab2_button);
+            ui_button(obj, .label = "Button 3", .onclick=action_tab2_button);
+            ui_button(obj, .label = "Button 4", .onclick=action_tab2_button);
+            ui_button(obj, .label = "Button 5", .onclick=action_tab2_button);
+            ui_button(obj, .label = "Button 6", .onclick=action_tab2_button);
         }
         ui_tab(obj, "Tab 3") {
             UiTabViewArgs args = {0};
@@ -276,7 +297,7 @@
     
     ui_toolbar_item("Test", .label = "Test", .onclick = action_toolbar_button);
     ui_toolbar_item("Test2", .label = "New Window", .onclick = action_toolbar_newwindow);
-    ui_toolbar_item("Test3", .label = "Test 3", .onclick = action_toolbar_button);
+    ui_toolbar_item("Test3", .label = "Dialog", .onclick = action_toolbar_dialog);
     ui_toolbar_item("Test4", .label = "Test 4", .onclick = action_toolbar_button);
     ui_toolbar_item("Test5", .label = "Test 5", .onclick = action_toolbar_button);
     ui_toolbar_item("Test6", .label = "Test 6", .onclick = action_toolbar_button);
--- a/ui/gtk/button.c	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/gtk/button.c	Wed Oct 23 14:52:18 2024 +0200
@@ -59,7 +59,8 @@
         const char *label,
         const char *icon,
         ui_callback onclick,
-        void *userdata)
+        void *userdata,
+        int event_value)
 {
     GtkWidget *button = gtk_button_new_with_label(label);
     ui_button_set_icon_name(button, icon);
@@ -69,7 +70,7 @@
         event->obj = obj;
         event->userdata = userdata;
         event->callback = onclick;
-        event->value = 0;
+        event->value = event_value;
         event->customdata = NULL;
 
         g_signal_connect(
@@ -89,7 +90,7 @@
 
 UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs args) {
     UiObject* current = uic_current_obj(obj);
-    GtkWidget *button = ui_create_button(obj, args.label, args.icon, args.onclick, args.onclickdata);
+    GtkWidget *button = ui_create_button(obj, args.label, args.icon, args.onclick, args.onclickdata, 0);
     ui_set_name_and_style(button, args.name, args.style_class);
     ui_set_widget_groups(obj->ctx, button, args.groups);
     UI_APPLY_LAYOUT1(current, args);
--- a/ui/gtk/button.h	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/gtk/button.h	Wed Oct 23 14:52:18 2024 +0200
@@ -46,7 +46,8 @@
         const char *label,
         const char *icon,
         ui_callback onclick,
-        void *userdata);
+        void *userdata,
+        int event_value);
 
 void ui_setup_togglebutton(
         UiObject *obj,
--- a/ui/gtk/container.c	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/gtk/container.c	Wed Oct 23 14:52:18 2024 +0200
@@ -242,7 +242,7 @@
 
 
 
-static GtkWidget* box_set_margin(GtkWidget *box, int margin) {
+GtkWidget* ui_box_set_margin(GtkWidget *box, int margin) {
     GtkWidget *ret = box;
 #if GTK_MAJOR_VERSION >= 3
 #if GTK_MAJOR_VERSION * 1000 + GTK_MINOR_VERSION >= 3012
@@ -270,7 +270,7 @@
     
     GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing);
     ui_set_name_and_style(box, args.name, args.style_class);
-    GtkWidget *widget = args.margin > 0 ? box_set_margin(box, args.margin) : box;
+    GtkWidget *widget = args.margin > 0 ? ui_box_set_margin(box, args.margin) : box;
     ct->add(ct, widget, TRUE);
     
     UiObject *newobj = uic_object_new(obj, box);
@@ -288,7 +288,7 @@
     return ui_box_create(obj, args, UI_CONTAINER_HBOX);
 }
 
-static GtkWidget* create_grid(int colspacing, int rowspacing) {
+GtkWidget* ui_create_grid_widget(int colspacing, int rowspacing) {
 #if GTK_MAJOR_VERSION >= 3
     GtkWidget *grid = gtk_grid_new();
     gtk_grid_set_column_spacing(GTK_GRID(grid), colspacing);
@@ -306,9 +306,9 @@
     UI_APPLY_LAYOUT1(current, args);
     GtkWidget *widget;
     
-    GtkWidget *grid = create_grid(args.columnspacing, args.rowspacing);
+    GtkWidget *grid = ui_create_grid_widget(args.columnspacing, args.rowspacing);
     ui_set_name_and_style(grid, args.name, args.style_class);
-    widget = box_set_margin(grid, args.margin);
+    widget = ui_box_set_margin(grid, args.margin);
     current->container->add(current->container, widget, TRUE);
     
     UiObject *newobj = uic_object_new(obj, grid);
@@ -621,13 +621,13 @@
             break;
         }
         case UI_CONTAINER_GRID: {
-            sub = create_grid(data->columnspacing, data->rowspacing);
+            sub = ui_create_grid_widget(data->columnspacing, data->rowspacing);
             newobj->container = ui_grid_container(newobj, sub);
             break;
         }
     }
     newobj->widget = sub;
-    GtkWidget *widget = box_set_margin(sub, data->margin);
+    GtkWidget *widget = ui_box_set_margin(sub, data->margin);
     
     data->add_tab(data->widget, tab_index, name, widget);
     
--- a/ui/gtk/container.h	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/gtk/container.h	Wed Oct 23 14:52:18 2024 +0200
@@ -137,11 +137,13 @@
 UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame);
 void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
 
+GtkWidget* ui_box_set_margin(GtkWidget *box, int margin);
 UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, UiSubContainerType type);
 
 UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type);
 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);
 void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
 
--- a/ui/gtk/headerbar.c	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/gtk/headerbar.c	Wed Oct 23 14:52:18 2024 +0200
@@ -114,7 +114,7 @@
         UiObject *obj,
         enum UiToolbarPos pos)
 {
-    GtkWidget *button = ui_create_button(obj, item->args.label, item->args.icon, item->args.onclick, item->args.onclickdata);
+    GtkWidget *button = ui_create_button(obj, item->args.label, item->args.icon, item->args.onclick, item->args.onclickdata, 0);
     WIDGET_ADD_CSS_CLASS(button, "flat");
     headerbar_add(headerbar, box, button, pos);
 }
--- a/ui/gtk/toolkit.c	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/gtk/toolkit.c	Wed Oct 23 14:52:18 2024 +0200
@@ -166,8 +166,11 @@
 }
 
 void ui_close(UiObject *obj) {
-    // TODO
-    //gtk_widget_destroy(obj->widget);
+#if GTK_CHECK_VERSION(4, 0, 0)
+    gtk_window_close(GTK_WINDOW(obj->widget));
+#else
+    gtk_widget_destroy(obj->widget);
+#endif
 }
 
 
@@ -345,6 +348,9 @@
 ".pathbar-button-inactive {\n"
 "  color: alpha(currentColor, 0.5);"
 "}\n"
+".ui_test {\n"
+"  background-color: red;\n"
+"}\n"
 ;
 
 #elif GTK_MAJOR_VERSION == 3
--- a/ui/gtk/toolkit.h	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/gtk/toolkit.h	Wed Oct 23 14:52:18 2024 +0200
@@ -59,7 +59,7 @@
 #define WINDOW_DESTROY(window) gtk_window_destroy(GTK_WINDOW(window))
 #define WINDOW_SET_CONTENT(window, child) gtk_window_set_child(GTK_WINDOW(window), child)
 #define BOX_ADD(box, child) gtk_box_append(GTK_BOX(box), child)
-#define BOX_ADD_EXPAND(box, child) gtk_widget_set_hexpand(child, TRUE); gtk_box_append(GTK_BOX(box), child)
+#define BOX_ADD_EXPAND(box, child) gtk_widget_set_hexpand(child, TRUE); gtk_widget_set_vexpand(child, TRUE); gtk_box_append(GTK_BOX(box), child)
 #define BOX_ADD_NO_EXPAND(box, child) gtk_box_append(GTK_BOX(box), child)
 #define ENTRY_SET_TEXT(entry, text) gtk_editable_set_text(GTK_EDITABLE(entry), text)
 #define ENTRY_GET_TEXT(entry) gtk_editable_get_text(GTK_EDITABLE(entry))
@@ -73,8 +73,8 @@
 #define WINDOW_DESTROY(window) gtk_widget_destroy(window)
 #define WINDOW_SET_CONTENT(window, child) gtk_container_add(GTK_CONTAINER(window), child)
 #define BOX_ADD(box, child) gtk_container_add(GTK_CONTAINER(box), child)
-#define BOX_ADD_EXPAND(box, child) gtk_box_pack_end(GTK_BOX(box), child, TRUE, TRUE, 0)
-#define BOX_ADD_NO_EXPAND(box, child) gtk_box_pack_end(GTK_BOX(box), child, TRUE, FALSE, 0)
+#define BOX_ADD_EXPAND(box, child) gtk_box_pack_start(GTK_BOX(box), child, TRUE, TRUE, 0)
+#define BOX_ADD_NO_EXPAND(box, child) gtk_box_pack_start(GTK_BOX(box), child, TRUE, FALSE, 0)  
 #define ENTRY_SET_TEXT(entry, text) gtk_entry_set_text(GTK_ENTRY(entry), text)
 #define ENTRY_GET_TEXT(entry) gtk_entry_get_text(GTK_ENTRY(entry))
 #define SCROLLEDWINDOW_NEW() gtk_scrolled_window_new(NULL, NULL)
--- a/ui/gtk/window.c	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/gtk/window.c	Wed Oct 23 14:52:18 2024 +0200
@@ -42,6 +42,7 @@
 #include "toolbar.h"
 #include "container.h"
 #include "headerbar.h"
+#include "button.h"
 
 static int nwindows = 0;
 
@@ -586,3 +587,145 @@
     ui_gtkfilechooser(obj, GTK_FILE_CHOOSER_ACTION_SAVE, 0, name, file_selected_callback, cbdata);
 }
 
+#if GTK_CHECK_VERSION(4, 10, 0)
+#define DIALOG_NEW() gtk_window_new()
+#else
+#define DIALOG_NEW() gtk_dialog_new()
+
+static void ui_dialogwindow_response(GtkDialog* self, gint response_id, gpointer user_data) {
+    UiEventData *event = user_data;
+    // TODO: do we need to check if response_id == GTK_RESPONSE_DELETE_EVENT?
+    if(event->callback) {
+        UiEvent e;
+        e.obj = event->obj;
+        e.window = event->obj->window;
+        e.document = event->obj->ctx->document;
+        e.eventdata = NULL;
+        e.intval = event->value;
+        event->callback(&e, event->userdata);
+    }
+}
+
+#endif
+
+#if GTK_CHECK_VERSION(4, 0, 0)
+#define HEADERBAR_SHOW_CLOSEBUTTON(headerbar, set) gtk_header_bar_set_show_title_buttons(GTK_HEADER_BAR(headerbar), set)
+#else
+#define HEADERBAR_SHOW_CLOSEBUTTON(headerbar, set) gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(headerbar), set)
+#endif
+
+
+
+UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs args) {
+    GtkWidget *dialog = DIALOG_NEW();
+    gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent->widget));
+    if(args.modal != UI_OFF) {
+        gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
+    }
+    
+    CxMempool *mp = cxBasicMempoolCreate(256);
+    UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); 
+    obj->ctx = uic_context(obj, mp);
+    obj->widget = dialog;
+    nwindows++;
+    
+    if(args.title != NULL) {
+        gtk_window_set_title(GTK_WINDOW(dialog), args.title);
+    }
+    
+#if ! GTK_CHECK_VERSION(4, 10, 0)
+    UiEventData *event = malloc(sizeof(UiEventData));
+    event->obj = obj;
+    event->userdata = args.onclickdata;
+    event->callback = args.onclick;
+    event->value = 0;
+    event->customdata = NULL;
+
+    g_signal_connect(dialog, "response", G_CALLBACK(ui_dialogwindow_response), event);
+    g_signal_connect(
+            dialog,
+            "destroy",
+            G_CALLBACK(ui_destroy_userdata),
+            event);
+#endif
+    
+    g_signal_connect(
+            dialog,
+            "destroy",
+            G_CALLBACK(ui_exit_event),
+            obj);
+    
+#if GTK_MAJOR_VERSION < 4
+    GtkWidget *c = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+    gtk_container_remove(GTK_CONTAINER(dialog), c);
+#endif
+    
+    GtkWidget *content_vbox = ui_gtk_vbox_new(0);
+    obj->container = ui_box_container(obj, content_vbox, UI_CONTAINER_VBOX);
+    if(args.lbutton1 || args.lbutton2 || args.rbutton3 || args.rbutton4) {
+#if GTK_CHECK_VERSION(3, 10, 0)
+        if(args.titlebar_buttons != UI_OFF) {
+            GtkWidget *headerbar = gtk_header_bar_new();
+            gtk_window_set_titlebar(GTK_WINDOW(dialog), headerbar);
+            if(args.show_closebutton == UI_OFF) {
+                HEADERBAR_SHOW_CLOSEBUTTON(headerbar, FALSE);
+            }
+            
+            if(args.lbutton1) {
+                GtkWidget *button = ui_create_button(obj, args.lbutton1, NULL, args.onclick, args.onclickdata, 1);
+                gtk_header_bar_pack_start(GTK_HEADER_BAR(headerbar), button);
+            }
+            if(args.lbutton2) {
+                GtkWidget *button = ui_create_button(obj, args.lbutton2, NULL, args.onclick, args.onclickdata, 2);
+                gtk_header_bar_pack_start(GTK_HEADER_BAR(headerbar), button);
+            }
+            
+            if(args.rbutton4) {
+                GtkWidget *button = ui_create_button(obj, args.rbutton4, NULL, args.onclick, args.onclickdata, 4);
+                gtk_header_bar_pack_end(GTK_HEADER_BAR(headerbar), button);
+            }
+            if(args.rbutton3) {
+                GtkWidget *button = ui_create_button(obj, args.rbutton3, NULL, args.onclick, args.onclickdata, 3);
+                gtk_header_bar_pack_end(GTK_HEADER_BAR(headerbar), button);
+            }
+            return obj;
+        }
+#endif
+        GtkWidget *vbox = ui_gtk_vbox_new(0);
+        WINDOW_SET_CONTENT(obj->widget, vbox);
+        
+        GtkWidget *separator = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
+        
+        GtkWidget *grid = ui_create_grid_widget(10, 10);
+        GtkWidget *widget = ui_box_set_margin(grid, 16);
+        gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE); 
+        
+        if(args.lbutton1) {
+            GtkWidget *button = ui_create_button(obj, args.lbutton1, NULL, args.onclick, args.onclickdata, 1);
+            gtk_grid_attach(GTK_GRID(grid), button, 0, 0, 1, 1);
+        }
+        if(args.lbutton2) {
+            GtkWidget *button = ui_create_button(obj, args.lbutton2, NULL, args.onclick, args.onclickdata, 2);
+            gtk_grid_attach(GTK_GRID(grid), button, 1, 0, 1, 1);
+        }
+        GtkWidget *space = gtk_label_new(NULL);
+        gtk_widget_set_hexpand(space, TRUE);
+        gtk_grid_attach(GTK_GRID(grid), space, 2, 0, 1, 1);
+        if(args.rbutton3) {
+            GtkWidget *button = ui_create_button(obj, args.rbutton3, NULL, args.onclick, args.onclickdata, 3);
+            gtk_grid_attach(GTK_GRID(grid), button, 3, 0, 1, 1);
+        }
+        if(args.rbutton3) {
+            GtkWidget *button = ui_create_button(obj, args.rbutton4, NULL, args.onclick, args.onclickdata, 4);
+            gtk_grid_attach(GTK_GRID(grid), button, 4, 0, 1, 1);
+        }
+        
+        BOX_ADD_EXPAND(vbox, content_vbox);   
+        BOX_ADD_NO_EXPAND(vbox, separator);
+        BOX_ADD_NO_EXPAND(vbox, widget);
+    } else {
+        WINDOW_SET_CONTENT(obj->widget, content_vbox);
+    }
+    
+    return obj;
+}
--- a/ui/ui/window.h	Tue Oct 22 21:17:01 2024 +0200
+++ b/ui/ui/window.h	Wed Oct 23 14:52:18 2024 +0200
@@ -50,8 +50,32 @@
     void *resultdata;
 } UiDialogArgs;
 
+typedef struct UiDialogWindowArgs {
+    UiBool modal;
+    UiBool titlebar_buttons;
+    UiBool show_closebutton;
+    const char *title;
+    const char *lbutton1;
+    const char *lbutton2;
+    const char *rbutton3;
+    const char *rbutton4;
+    const int *lbutton1_groups;
+    const int *lbutton2_groups;
+    const int *rbutton3_groups;
+    const int *rbutton4_groups;
+    int default_button;
+    int width;
+    int height;
+    ui_callback onclick;
+    void *onclickdata;
+} UiDialogWindowArgs;
+
 UIEXPORT UiObject* ui_window(const char *title, void *window_data);
 UIEXPORT UiObject* ui_simple_window(const char *title, void *window_data);
+UIEXPORT UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs args);
+
+#define ui_dialog_window(parent, ...) ui_dialog_window_create(parent, (UiDialogWindowArgs){ __VA_ARGS__ });
+#define ui_dialog_window0(parent) ui_dialog_window_create(parent, (UiDialogWindowArgs){ 0 });
 
 UIEXPORT void ui_window_size(UiObject *obj, int width, int height);
 

mercurial