ui/gtk/window.c

changeset 110
c00e968d018b
parent 109
c3dfcb8f0be7
child 112
c3f2f16fa4b8
--- a/ui/gtk/window.c	Sun Aug 24 15:24:16 2025 +0200
+++ b/ui/gtk/window.c	Sat Oct 04 14:52:59 2025 +0200
@@ -49,6 +49,9 @@
 static int window_default_width = 650;
 static int window_default_height = 550;
 
+static int splitview_window_default_pos = -1;
+static UiBool splitview_window_use_prop = TRUE;
+
 static gboolean ui_window_destroy(void *data)  {
     UiObject *obj = data;
     uic_object_destroy(obj);
@@ -77,6 +80,36 @@
 }
 
 static gboolean ui_window_close_request(UiObject *obj) {
+    if(obj->widget) {
+        void *appwindow = g_object_get_data(G_OBJECT(obj->widget), "ui.appwindow");
+        if(appwindow) {
+            int width = 0;
+            int height = 0;
+#if GTK_CHECK_VERSION(4, 10, 0)
+            graphene_rect_t bounds;
+            if(gtk_widget_compute_bounds(obj->widget, obj->widget, &bounds)) {
+                width = bounds.size.width;
+                height = bounds.size.height;
+            }
+#elif GTK_CHECK_VERSION(4, 0, 0)
+            GtkAllocation alloc;
+            gtk_widget_get_allocation(GTK_WIDGET(obj->widget), &alloc);
+            width = alloc.width;
+            height = alloc.height;
+#else
+            gtk_window_get_size(GTK_WINDOW(obj->widget), &width, &height);
+#endif
+            if(width > 0 && height > 0) {
+                char width_str[32];
+                char height_str[32];
+                snprintf(width_str, 32, "%d", width);
+                snprintf(height_str, 32, "%d", height);
+                ui_set_property("ui.window.width", width_str);
+                ui_set_property("ui.window.height", height_str);
+            }
+        }
+    }
+    
     uic_context_prepare_close(obj->ctx);
     obj->ref--;
     if(obj->ref > 0) {
@@ -101,7 +134,14 @@
 }
 #endif
 
-static UiObject* create_window(const char *title, void *window_data, UiBool sidebar, UiBool simple) {
+static void save_window_splitview_pos(GtkWidget *widget, void *unused) {
+    int pos = gtk_paned_get_position(GTK_PANED(widget));
+    char buf[32];
+    snprintf(buf, 32, "%d", pos);
+    ui_set_property("ui.window.splitview.pos", buf);
+}
+
+static UiObject* create_window(const char *title, void *window_data, UiBool sidebar, UiBool splitview, UiBool simple) {
     UiObject *obj = uic_object_new_toplevel();
    
 #ifdef UI_LIBADWAITA
@@ -122,19 +162,28 @@
         gtk_window_set_title(GTK_WINDOW(obj->widget), title);
     }
     
-    const char *width = ui_get_property("ui.window.width");
-    const char *height = ui_get_property("ui.window.height");
-    if(width && height) {
-        gtk_window_set_default_size(
+    if(!simple) {
+        g_object_set_data(G_OBJECT(obj->widget), "ui.appwindow", obj);
+    }
+    
+    int window_width = window_default_width;
+    int window_height = window_default_height;
+    if(!simple) {
+        const char *width = ui_get_property("ui.window.width");
+        const char *height = ui_get_property("ui.window.height");
+        if(width && height) {
+            int w = atoi(width);
+            int h = atoi(height);
+            if(w > 0 && h > 0) {
+                window_width = w;
+                window_height = h;
+            }
+        }
+    }
+    gtk_window_set_default_size(
                 GTK_WINDOW(obj->widget),
-                atoi(width),
-                atoi(height));
-    } else {
-        gtk_window_set_default_size(
-                GTK_WINDOW(obj->widget),
-                window_default_width + sidebar*250,
-                window_default_height);
-    }
+                window_width,
+                window_height);
     
     obj->destroy = ui_window_widget_destroy;
     g_signal_connect(
@@ -161,50 +210,95 @@
     GtkWidget *toolbar_view = adw_toolbar_view_new();
     adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(toolbar_view), vbox);
     
-    GtkWidget *content_box = ui_gtk_vbox_new(0);
-    BOX_ADD_EXPAND(GTK_BOX(vbox), content_box);
+    GtkWidget *headerbar_sidebar = NULL;
+    GtkWidget *headerbar_main = adw_header_bar_new();
+    GtkWidget *headerbar_right = NULL;
     
-    GtkWidget *sidebar_headerbar = NULL; 
+    GtkWidget *content = toolbar_view;
+    if(splitview) {
+        content = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
+        g_signal_connect(
+                content,
+                "destroy",
+                G_CALLBACK(save_window_splitview_pos),
+                NULL);
+        
+        const char *splitview_pos_str = ui_get_property("ui.window.splitview.pos");
+        int pos = splitview_window_default_pos;
+        if(pos < 0) {
+            pos = window_width / 2;
+        }
+        if(splitview_pos_str && splitview_window_use_prop) {
+            int splitview_pos = atoi(splitview_pos_str);
+            if(splitview_pos > 0) {
+                pos = splitview_pos;
+            }
+        }
+        gtk_paned_set_position(GTK_PANED(content), pos);
+        
+        GtkWidget *right_panel = adw_toolbar_view_new();
+        GtkWidget *right_vbox = ui_gtk_vbox_new(0);
+        adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(right_panel), right_vbox);
+        
+        headerbar_right = adw_header_bar_new();
+        adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_right), FALSE);
+        adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(right_panel), headerbar_right);
+        
+        adw_header_bar_set_show_end_title_buttons(ADW_HEADER_BAR(headerbar_main), FALSE);
+        
+        gtk_paned_set_start_child(GTK_PANED(content), toolbar_view);
+        gtk_paned_set_end_child(GTK_PANED(content), right_panel);
+        
+        g_object_set_data(G_OBJECT(obj->widget), "ui_window_splitview", content);
+        g_object_set_data(G_OBJECT(obj->widget), "ui_left_panel", vbox);
+        g_object_set_data(G_OBJECT(obj->widget), "ui_right_panel", right_vbox);
+    }
+    
+    GtkWidget *content_box = vbox;
+    
     if(sidebar) {
         GtkWidget *splitview = adw_overlay_split_view_new();
         adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), splitview);
         
         GtkWidget *sidebar_toolbar_view = adw_toolbar_view_new();
         adw_overlay_split_view_set_sidebar(ADW_OVERLAY_SPLIT_VIEW(splitview), sidebar_toolbar_view);
-        sidebar_headerbar = adw_header_bar_new();
-        adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), sidebar_headerbar);
+        headerbar_sidebar = adw_header_bar_new();
+        adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+        adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), headerbar_sidebar);
         
-        adw_overlay_split_view_set_content(ADW_OVERLAY_SPLIT_VIEW(splitview), toolbar_view);
+        adw_overlay_split_view_set_content(ADW_OVERLAY_SPLIT_VIEW(splitview), content);
         
         g_object_set_data(G_OBJECT(obj->widget), "ui_sidebar", sidebar_toolbar_view);
     } else {
-        adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), toolbar_view);
+        adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), content);
     }
     
-    GtkWidget *headerbar = adw_header_bar_new();
-    
     const char *show_title = ui_get_property("ui.gtk.window.showtitle");
     if(show_title) {
         if(!strcmp(show_title, "main") && sidebar) {
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(sidebar_headerbar), FALSE);
+            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
         } else if(!strcmp(show_title, "sidebar")) {
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar), FALSE);
+            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
+            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
         } else if(!strcmp(show_title, "false")) {
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(sidebar_headerbar), FALSE);
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar), FALSE);
+            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
         } else {
             fprintf(stderr, "Unknown value '%s' for property ui.gtk.window.showtitle\n", show_title);
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(sidebar_headerbar), FALSE);
+            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
         }
     } else {
-        adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar), FALSE);
+        adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
+        if(sidebar) {
+            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
+        }
     }
     
-    adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar);
-    g_object_set_data(G_OBJECT(obj->widget), "ui_headerbar", headerbar);
+    adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar_main);
+    g_object_set_data(G_OBJECT(obj->widget), "ui_headerbar", headerbar_main);
     
     if(!simple) {
-        ui_fill_headerbar(obj, headerbar);
+        ui_fill_headerbar(obj, headerbar_sidebar, headerbar_main, headerbar_right);
     }
 #elif GTK_MAJOR_VERSION >= 4
     GtkWidget *content_box = ui_gtk_vbox_new(0);
@@ -286,15 +380,19 @@
 
 
 UiObject* ui_window(const char *title, void *window_data) {
-    return create_window(title, window_data, FALSE, FALSE);
+    return create_window(title, window_data, FALSE, FALSE, FALSE);
 }
 
 UiObject *ui_sidebar_window(const char *title, void *window_data) {
-    return create_window(title, window_data, TRUE, FALSE);
+    return create_window(title, window_data, TRUE, FALSE, FALSE);
+}
+
+UIEXPORT UiObject *ui_splitview_window(const char *title, UiBool sidebar) {
+    return create_window(title, NULL, sidebar, TRUE, FALSE);
 }
 
 UiObject* ui_simple_window(const char *title, void *window_data) {
-    return create_window(title, window_data, FALSE, TRUE);
+    return create_window(title, window_data, FALSE, FALSE, TRUE);
 }
 
 void ui_window_size(UiObject *obj, int width, int height) {
@@ -304,6 +402,38 @@
                 height);
 }
 
+void ui_window_default_size(int width, int height) {
+    window_default_width = width;
+    window_default_height = height;
+}
+
+void ui_splitview_window_set_pos(UiObject *obj, int pos) {
+    GtkWidget *splitview = g_object_get_data(G_OBJECT(obj->widget), "ui_window_splitview");
+    if(splitview) {
+        gtk_paned_set_position(GTK_PANED(splitview), pos);
+    } else {
+        fprintf(stderr, "Error: window has no splitview\n");
+    }
+}
+
+int ui_splitview_window_get_pos(UiObject *obj) {
+    GtkWidget *splitview = g_object_get_data(G_OBJECT(obj->widget), "ui_window_splitview");
+    if(splitview) {
+        return gtk_paned_get_position(GTK_PANED(splitview));
+    } else {
+        fprintf(stderr, "Error: window has no splitview\n");
+    }
+    return 0;
+}
+
+void ui_splitview_window_set_default_pos(int pos) {
+    splitview_window_default_pos = pos;
+}
+
+void ui_splitview_window_use_property(UiBool enable) {
+    splitview_window_use_prop = enable;
+}
+
 #ifdef UI_LIBADWAITA
 
 static void dialog_response(AdwAlertDialog *self, gchar *response, UiEventData *data) {
@@ -693,18 +823,6 @@
                 G_CALLBACK(ui_destroy_userdata),
                 event);
     
-    
-    UiEvent evt;
-    evt.obj = obj;
-    evt.document = evt.obj->ctx->document;
-    evt.window = evt.obj->window;
-    evt.intval = 0;
-    
-    UiFileList flist;
-    flist.files = NULL;
-    flist.nfiles = 0;
-    evt.eventdata = &flist;
-    
     gtk_widget_show(dialog);
 }
 #endif

mercurial