add custom headerbar (GTK) newapi tip

Sun, 13 Oct 2024 16:05:06 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 13 Oct 2024 16:05:06 +0200
branch
newapi
changeset 336
56c12f44c2d3
parent 335
91d4f0391282

add custom headerbar (GTK)

application/main.c 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/headerbar.h file | annotate | diff | comparison | revisions
ui/gtk/window.c file | annotate | diff | comparison | revisions
ui/ui/container.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Sun Oct 13 14:34:12 2024 +0200
+++ b/application/main.c	Sun Oct 13 16:05:06 2024 +0200
@@ -76,6 +76,23 @@
     ui_dialog(event->obj, .title = "Dialog Title", .content = "Content Label", .button1_label = "btn1", .button2_label = "btn2", .input = TRUE, .closebutton_label = "Cancel");
 }
 
+void action_toolbar_newwindow(UiEvent *event, void *userdata) {
+    UiObject *obj = ui_simple_window("New Window", NULL);
+    
+    ui_headerbar0(obj) {
+        ui_headerbar_start(obj) {
+            ui_button(obj, .label = "Open");
+        }
+        ui_headerbar_end(obj) {
+            ui_button(obj, .label = "Test");
+        }
+    }
+    
+    ui_textarea(obj, .varname="text");
+    
+    ui_show(obj);
+}
+
 MyDocument* create_doc(void) {
     MyDocument *doc = ui_document_new(sizeof(MyDocument));
     UiContext *docctx = ui_document_context(doc);
@@ -227,7 +244,7 @@
     }
     
     ui_toolbar_item("Test", .label = "Test", .onclick = action_toolbar_button);
-    ui_toolbar_item("Test2", .label = "Test 2", .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("Test4", .label = "Test 4", .onclick = action_toolbar_button);
     ui_toolbar_item("Test5", .label = "Test 5", .onclick = action_toolbar_button);
--- a/ui/gtk/container.c	Sun Oct 13 14:34:12 2024 +0200
+++ b/ui/gtk/container.c	Sun Oct 13 16:05:06 2024 +0200
@@ -32,6 +32,7 @@
 
 #include "container.h"
 #include "toolkit.h"
+#include "headerbar.h"
 
 #include "../common/context.h"
 #include "../common/object.h"
@@ -633,6 +634,130 @@
     return newobj;
 }
 
+
+/* -------------------- Headerbar -------------------- */
+
+static void hb_set_part(UiObject *obj, int part) {
+    UiObject* current = uic_current_obj(obj);
+    GtkWidget *headerbar = current->widget;
+    
+    UiHeaderbarContainer *hb = cxCalloc(
+            obj->ctx->allocator,
+            1,
+            sizeof(UiHeaderbarContainer));
+    memcpy(hb, current->container, sizeof(UiHeaderbarContainer));
+    
+    UiObject *newobj = uic_object_new(obj, headerbar);
+    newobj->container = (UiContainer*)hb;
+    uic_obj_add(obj, newobj);
+    
+    hb->part = part;
+}
+
+void ui_headerbar_start_create(UiObject *obj) {
+    hb_set_part(obj, 0);
+}
+
+void ui_headerbar_center_create(UiObject *obj) {
+    hb_set_part(obj, 2);
+}
+
+void ui_headerbar_end_create(UiObject *obj) {
+    hb_set_part(obj, 1);
+}
+
+UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs args) {
+    UiObject *current = uic_current_obj(obj);
+    UiContainer *ct = current->container;
+    UI_APPLY_LAYOUT1(current, args);
+    
+    GtkWidget *box = ui_gtk_hbox_new(args.alt_spacing);
+    ui_set_name_and_style(box, args.name, args.style_class);
+    ct->add(ct, box, FALSE);
+    
+    UiObject *newobj = uic_object_new(obj, box);
+    newobj->container = ui_headerbar_fallback_container(obj, box);
+    uic_obj_add(obj, newobj);
+    
+    return box;
+}
+
+static void hb_fallback_set_part(UiObject *obj, int part) {
+    UiObject* current = uic_current_obj(obj);
+    GtkWidget *headerbar = current->widget;
+    
+    UiObject *newobj = uic_object_new(obj, headerbar);
+    newobj->container = ui_headerbar_container(obj, headerbar);
+    uic_obj_add(obj, newobj);
+    
+    UiHeaderbarContainer *hb = (UiHeaderbarContainer*)newobj->container;
+    hb->part = part;
+}
+
+UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar) {
+    UiHeaderbarContainer *ct = cxCalloc(
+            obj->ctx->allocator,
+            1,
+            sizeof(UiHeaderbarContainer));
+    ct->container.widget = headerbar;
+    ct->container.add = ui_headerbar_fallback_container_add;
+    return (UiContainer*)ct;
+}
+
+void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+    UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
+    BOX_ADD(ct->widget, widget);
+}
+
+#if GTK_CHECK_VERSION(3, 10, 0)
+
+UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
+    GtkWidget *headerbar = g_object_get_data(G_OBJECT(obj->widget), "ui_headerbar");
+    if(!headerbar) {
+        return ui_headerbar_fallback_create(obj, args);
+    }
+    
+    UiObject *newobj = uic_object_new(obj, headerbar);
+    newobj->container = ui_headerbar_container(obj, headerbar);
+    uic_obj_add(obj, newobj);
+    
+    return headerbar;    
+}
+
+UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) {
+    UiHeaderbarContainer *ct = cxCalloc(
+            obj->ctx->allocator,
+            1,
+            sizeof(UiHeaderbarContainer));
+    ct->container.widget = headerbar;
+    ct->container.add = ui_headerbar_container_add;
+    return (UiContainer*)ct;
+}
+
+void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+    UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct;
+    if(hb->part == 0) {
+        UI_HEADERBAR_PACK_START(ct->widget, widget);
+    } else if(hb->part == 1) {
+        UI_HEADERBAR_PACK_END(ct->widget, widget);
+    } else if(hb->part == 2) {
+        if(!hb->centerbox) {
+            GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
+            hb->centerbox = box;
+            UI_HEADERBAR_SET_TITLE_WIDGET(ct->widget, box);
+        }
+        BOX_ADD(hb->centerbox, widget);
+    }
+}
+
+#else
+
+UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) {
+    return ui_headerbar_fallback_create(obj, args);  
+}
+
+#endif
+
 /* -------------------- Splitpane -------------------- */
 
 static GtkWidget* create_paned(UiOrientation orientation) {
--- a/ui/gtk/container.h	Sun Oct 13 14:34:12 2024 +0200
+++ b/ui/gtk/container.h	Sun Oct 13 16:05:06 2024 +0200
@@ -124,6 +124,13 @@
     int rowspacing;
 } UiGtkTabView;
 
+typedef struct UiHeaderbarContainer {
+    UiContainer container;
+    GtkWidget *centerbox;
+    int part;
+    UiHeaderbarAlternative alternative; /* only used by fallback headerbar */
+} UiHeaderbarContainer;
+
 GtkWidget* ui_gtk_vbox_new(int spacing);
 GtkWidget* ui_gtk_hbox_new(int spacing);
 
@@ -153,6 +160,14 @@
 
 void ui_gtk_notebook_select_tab(GtkWidget *widget, int tab);
 
+#if GTK_CHECK_VERSION(3, 10, 0)
+UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar);
+void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+#endif
+
+UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar);
+void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/ui/gtk/headerbar.c	Sun Oct 13 14:34:12 2024 +0200
+++ b/ui/gtk/headerbar.c	Sun Oct 13 16:05:06 2024 +0200
@@ -31,25 +31,7 @@
 #include "button.h"
 #include "menu.h"
 
-#if GTK_MAJOR_VERSION >= 3
-
-#ifdef UI_LIBADWAITA
-#define UI_HEADERBAR AdwHeaderBar*
-#define UI_HEADERBAR_CAST(h) ADW_HEADER_BAR(h)
-#define UI_HEADERBAR_PACK_START(h, w) adw_header_bar_pack_start(ADW_HEADER_BAR(h), w)
-#define UI_HEADERBAR_PACK_END(h, w) adw_header_bar_pack_end(ADW_HEADER_BAR(h), w)
-#define UI_HEADERBAR_SET_TITLE_WIDGET(h, w) adw_header_bar_set_title_widget(ADW_HEADER_BAR(h), w)
-#else
-#define UI_HEADERBAR GtkHeaderBar*
-#define UI_HEADERBAR_CAST(h) GTK_HEADER_BAR(h)
-#define UI_HEADERBAR_PACK_START(h, w) gtk_header_bar_pack_start(GTK_HEADER_BAR(h), w)
-#define UI_HEADERBAR_PACK_END(h, w) gtk_header_bar_pack_end(GTK_HEADER_BAR(h), w)
-#if GTK_MAJOR_VERSION >= 4
-#define UI_HEADERBAR_SET_TITLE_WIDGET(h, w) gtk_header_bar_set_title_widget(GTK_HEADER_BAR(h), w)
-#else
-#define UI_HEADERBAR_SET_TITLE_WIDGET(h, w) gtk_header_bar_set_custom_title(GTK_HEADER_BAR(h), w)
-#endif
-#endif
+#if GTK_CHECK_VERSION(3, 10, 0)
     
 void ui_fill_headerbar(UiObject *obj, GtkWidget *headerbar) {
     CxList *left_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_LEFT);
--- a/ui/gtk/headerbar.h	Sun Oct 13 14:34:12 2024 +0200
+++ b/ui/gtk/headerbar.h	Sun Oct 13 16:05:06 2024 +0200
@@ -38,7 +38,25 @@
 extern "C" {
 #endif
 
-#if GTK_MAJOR_VERSION >= 3
+#if GTK_CHECK_VERSION(3, 10, 0)
+    
+#ifdef UI_LIBADWAITA
+#define UI_HEADERBAR AdwHeaderBar*
+#define UI_HEADERBAR_CAST(h) ADW_HEADER_BAR(h)
+#define UI_HEADERBAR_PACK_START(h, w) adw_header_bar_pack_start(ADW_HEADER_BAR(h), w)
+#define UI_HEADERBAR_PACK_END(h, w) adw_header_bar_pack_end(ADW_HEADER_BAR(h), w)
+#define UI_HEADERBAR_SET_TITLE_WIDGET(h, w) adw_header_bar_set_title_widget(ADW_HEADER_BAR(h), w)
+#else
+#define UI_HEADERBAR GtkHeaderBar*
+#define UI_HEADERBAR_CAST(h) GTK_HEADER_BAR(h)
+#define UI_HEADERBAR_PACK_START(h, w) gtk_header_bar_pack_start(GTK_HEADER_BAR(h), w)
+#define UI_HEADERBAR_PACK_END(h, w) gtk_header_bar_pack_end(GTK_HEADER_BAR(h), w)
+#if GTK_MAJOR_VERSION >= 4
+#define UI_HEADERBAR_SET_TITLE_WIDGET(h, w) gtk_header_bar_set_title_widget(GTK_HEADER_BAR(h), w)
+#else
+#define UI_HEADERBAR_SET_TITLE_WIDGET(h, w) gtk_header_bar_set_custom_title(GTK_HEADER_BAR(h), w)
+#endif
+#endif
     
 void ui_fill_headerbar(UiObject *obj, GtkWidget *headerbar);
 
--- a/ui/gtk/window.c	Sun Oct 13 14:34:12 2024 +0200
+++ b/ui/gtk/window.c	Sun Oct 13 16:05:06 2024 +0200
@@ -122,6 +122,7 @@
 
     GtkWidget *headerbar = adw_header_bar_new();
     adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar);
+    g_object_set_data(G_OBJECT(obj->widget), "ui_headerbar", headerbar);
     
     if(!simple) {
         ui_fill_headerbar(obj, headerbar);
@@ -167,7 +168,7 @@
     obj->container = ui_box_container(obj, content_box);
     */
     GtkWidget *content_box = ui_gtk_vbox_new(0);
-    BOX_ADD(GTK_BOX(vbox), content_box);
+    BOX_ADD_EXPAND(GTK_BOX(vbox), content_box);
     obj->container = ui_box_container(obj, content_box, UI_CONTAINER_VBOX);
     
     nwindows++;
--- a/ui/ui/container.h	Sun Oct 13 14:34:12 2024 +0200
+++ b/ui/ui/container.h	Sun Oct 13 16:05:06 2024 +0200
@@ -50,6 +50,12 @@
     UI_TABVIEW_INVISIBLE
 } UiTabViewType;
 
+typedef enum UiHeaderbarAlternative {
+    UI_HEADERBAR_ALTERNATIVE_DEFAULT = 0,
+    UI_HEADERBAR_ALTERNATIVE_TOOLBAR,
+    UI_HEADERBAR_ALTERNATIVE_BOX
+} UiHeaderbarAlternative;
+
 typedef struct UiContainerArgs {
     UiTri fill;
     UiBool hexpand;
@@ -110,6 +116,22 @@
     UiBool isexpanded;
 } UiTabViewArgs;
 
+typedef struct UiHeaderbarArgs {
+    UiTri fill;
+    UiBool hexpand;
+    UiBool vexpand;
+    int colspan;
+    int rowspan;
+    const char *name;
+    const char *style_class;
+    
+    UiBool showtitle;
+    UiBool showwindowbuttons;
+    
+    UiHeaderbarAlternative alternative;
+    int alt_spacing;
+} UiHeaderbarArgs;
+
 
 
 #define UI_CTN(obj, ctn) for(ctn;ui_container_finish(obj);ui_container_begin_close(obj))
@@ -121,6 +143,7 @@
 #define ui_expander(obj, ...) for(ui_expander_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_scrolledwindow(obj, ...) for(ui_scrolledwindow_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_tabview(obj, ...) for(ui_tabview_create(obj, (UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_headerbar(obj, ...) for(ui_headerbar_create(obj, (UiHeaderbarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
 
 #define ui_vbox0(obj) for(ui_vbox_create(obj, (UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_hbox0(obj) for(ui_hbox_create(obj, (UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
@@ -129,32 +152,43 @@
 #define ui_expander0(obj) for(ui_expande_create(obj, (UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_scrolledwindow0(obj) for(ui_scrolledwindow_create(obj, (UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_tabview0(obj) for(ui_tabview_create(obj, (UiTabViewArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_headerbar0(obj) for(ui_headerbar_create(obj, (UiHeaderbarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
 
 #define ui_tab(obj, label) for(ui_tab_create(obj, label);ui_container_finish(obj);ui_container_begin_close(obj))
 
+#define ui_headerbar_start(obj) for(ui_headerbar_start_create(obj);ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_headerbar_center(obj) for(ui_headerbar_center_create(obj);ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_headerbar_end(obj) for(ui_headerbar_end_create(obj);ui_container_finish(obj);ui_container_begin_close(obj))
+
 UIEXPORT void ui_end(UiObject *obj);
     
 UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args);
 UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args);
 UIEXPORT UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args);
-UIEXPORT UIWIDGET ui_frame_create(UiObject* obj, UiFrameArgs args);
-UIEXPORT UIWIDGET ui_expander_create(UiObject* obj, UiFrameArgs args);
-UIEXPORT UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs args);
-UIEXPORT UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args);
-
-UIEXPORT void ui_tab_create(UiObject* obj, const char* title);
+UIEXPORT UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs args);
+UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs args);
+UIEXPORT UIWIDGET ui_scrolledwindow_create(UiObject *obj, UiFrameArgs args);
 
-UIEXPORT UIWIDGET ui_scrolledwindow_deprecated(UiObject *obj);
-
-UIEXPORT UIWIDGET ui_sidebar(UiObject *obj);
-
-UIEXPORT UIWIDGET ui_hsplitpane(UiObject *obj, int max);
-UIEXPORT UIWIDGET ui_vsplitpane(UiObject *obj, int max);
-
+UIEXPORT UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs args);
+UIEXPORT void ui_tab_create(UiObject *obj, const char* title);
 UIEXPORT void ui_tabview_select(UIWIDGET tabview, int tab);
 UIEXPORT void ui_tabview_remove(UIWIDGET tabview, int tab);
 UIEXPORT UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index);
 
+UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args);
+UIEXPORT void ui_headerbar_start_create(UiObject *obj);
+UIEXPORT void ui_headerbar_center_create(UiObject *obj);
+UIEXPORT void ui_headerbar_end_create(UiObject *obj);
+
+
+UIEXPORT UIWIDGET ui_scrolledwindow_deprecated(UiObject *obj); // TODO
+
+UIEXPORT UIWIDGET ui_sidebar(UiObject *obj); // TODO
+
+UIEXPORT UIWIDGET ui_hsplitpane(UiObject *obj, int max); // TODO
+UIEXPORT UIWIDGET ui_vsplitpane(UiObject *obj, int max); // TODO
+
+
 // box container layout functions
 UIEXPORT void ui_layout_fill(UiObject *obj, UiBool fill);
 // grid container layout functions
@@ -166,9 +200,8 @@
 UIEXPORT void ui_layout_rowspan(UiObject* obj, int rows);
 UIEXPORT void ui_newline(UiObject *obj);
 
-
+// TODO
 UIEXPORT UiTabbedPane* ui_tabbed_document_view(UiObject *obj);
-
 UIEXPORT UiObject* ui_document_tab(UiTabbedPane *view);
 
 

mercurial