# HG changeset patch # User Olaf Wintermann # Date 1728828306 -7200 # Node ID 56c12f44c2d34464308091e29c966c644f43a7a9 # Parent 91d4f0391282046b1c90cdb5fc02147ecba47278 add custom headerbar (GTK) diff -r 91d4f0391282 -r 56c12f44c2d3 application/main.c --- 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); diff -r 91d4f0391282 -r 56c12f44c2d3 ui/gtk/container.c --- 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) { diff -r 91d4f0391282 -r 56c12f44c2d3 ui/gtk/container.h --- 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 diff -r 91d4f0391282 -r 56c12f44c2d3 ui/gtk/headerbar.c --- 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); diff -r 91d4f0391282 -r 56c12f44c2d3 ui/gtk/headerbar.h --- 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); diff -r 91d4f0391282 -r 56c12f44c2d3 ui/gtk/window.c --- 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++; diff -r 91d4f0391282 -r 56c12f44c2d3 ui/ui/container.h --- 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);