ui/gtk/window.c

changeset 110
c00e968d018b
parent 109
c3dfcb8f0be7
child 112
c3f2f16fa4b8
equal deleted inserted replaced
109:c3dfcb8f0be7 110:c00e968d018b
47 static int nwindows = 0; 47 static int nwindows = 0;
48 48
49 static int window_default_width = 650; 49 static int window_default_width = 650;
50 static int window_default_height = 550; 50 static int window_default_height = 550;
51 51
52 static int splitview_window_default_pos = -1;
53 static UiBool splitview_window_use_prop = TRUE;
54
52 static gboolean ui_window_destroy(void *data) { 55 static gboolean ui_window_destroy(void *data) {
53 UiObject *obj = data; 56 UiObject *obj = data;
54 uic_object_destroy(obj); 57 uic_object_destroy(obj);
55 58
56 nwindows--; 59 nwindows--;
75 // delay exit handler 78 // delay exit handler
76 g_idle_add(ui_window_destroy, data); 79 g_idle_add(ui_window_destroy, data);
77 } 80 }
78 81
79 static gboolean ui_window_close_request(UiObject *obj) { 82 static gboolean ui_window_close_request(UiObject *obj) {
83 if(obj->widget) {
84 void *appwindow = g_object_get_data(G_OBJECT(obj->widget), "ui.appwindow");
85 if(appwindow) {
86 int width = 0;
87 int height = 0;
88 #if GTK_CHECK_VERSION(4, 10, 0)
89 graphene_rect_t bounds;
90 if(gtk_widget_compute_bounds(obj->widget, obj->widget, &bounds)) {
91 width = bounds.size.width;
92 height = bounds.size.height;
93 }
94 #elif GTK_CHECK_VERSION(4, 0, 0)
95 GtkAllocation alloc;
96 gtk_widget_get_allocation(GTK_WIDGET(obj->widget), &alloc);
97 width = alloc.width;
98 height = alloc.height;
99 #else
100 gtk_window_get_size(GTK_WINDOW(obj->widget), &width, &height);
101 #endif
102 if(width > 0 && height > 0) {
103 char width_str[32];
104 char height_str[32];
105 snprintf(width_str, 32, "%d", width);
106 snprintf(height_str, 32, "%d", height);
107 ui_set_property("ui.window.width", width_str);
108 ui_set_property("ui.window.height", height_str);
109 }
110 }
111 }
112
80 uic_context_prepare_close(obj->ctx); 113 uic_context_prepare_close(obj->ctx);
81 obj->ref--; 114 obj->ref--;
82 if(obj->ref > 0) { 115 if(obj->ref > 0) {
83 #if GTK_CHECK_VERSION(2, 18, 0) 116 #if GTK_CHECK_VERSION(2, 18, 0)
84 gtk_widget_set_visible(obj->widget, FALSE); 117 gtk_widget_set_visible(obj->widget, FALSE);
99 static gboolean close_request(GtkWidget* self, GdkEvent* event, UiObject *obj) { 132 static gboolean close_request(GtkWidget* self, GdkEvent* event, UiObject *obj) {
100 return ui_window_close_request(obj); 133 return ui_window_close_request(obj);
101 } 134 }
102 #endif 135 #endif
103 136
104 static UiObject* create_window(const char *title, void *window_data, UiBool sidebar, UiBool simple) { 137 static void save_window_splitview_pos(GtkWidget *widget, void *unused) {
138 int pos = gtk_paned_get_position(GTK_PANED(widget));
139 char buf[32];
140 snprintf(buf, 32, "%d", pos);
141 ui_set_property("ui.window.splitview.pos", buf);
142 }
143
144 static UiObject* create_window(const char *title, void *window_data, UiBool sidebar, UiBool splitview, UiBool simple) {
105 UiObject *obj = uic_object_new_toplevel(); 145 UiObject *obj = uic_object_new_toplevel();
106 146
107 #ifdef UI_LIBADWAITA 147 #ifdef UI_LIBADWAITA
108 obj->widget = adw_application_window_new(ui_get_application()); 148 obj->widget = adw_application_window_new(ui_get_application());
109 #elif !defined(UI_GTK2) 149 #elif !defined(UI_GTK2)
120 160
121 if(title != NULL) { 161 if(title != NULL) {
122 gtk_window_set_title(GTK_WINDOW(obj->widget), title); 162 gtk_window_set_title(GTK_WINDOW(obj->widget), title);
123 } 163 }
124 164
125 const char *width = ui_get_property("ui.window.width"); 165 if(!simple) {
126 const char *height = ui_get_property("ui.window.height"); 166 g_object_set_data(G_OBJECT(obj->widget), "ui.appwindow", obj);
127 if(width && height) { 167 }
128 gtk_window_set_default_size( 168
169 int window_width = window_default_width;
170 int window_height = window_default_height;
171 if(!simple) {
172 const char *width = ui_get_property("ui.window.width");
173 const char *height = ui_get_property("ui.window.height");
174 if(width && height) {
175 int w = atoi(width);
176 int h = atoi(height);
177 if(w > 0 && h > 0) {
178 window_width = w;
179 window_height = h;
180 }
181 }
182 }
183 gtk_window_set_default_size(
129 GTK_WINDOW(obj->widget), 184 GTK_WINDOW(obj->widget),
130 atoi(width), 185 window_width,
131 atoi(height)); 186 window_height);
132 } else {
133 gtk_window_set_default_size(
134 GTK_WINDOW(obj->widget),
135 window_default_width + sidebar*250,
136 window_default_height);
137 }
138 187
139 obj->destroy = ui_window_widget_destroy; 188 obj->destroy = ui_window_widget_destroy;
140 g_signal_connect( 189 g_signal_connect(
141 obj->widget, 190 obj->widget,
142 "destroy", 191 "destroy",
159 GtkWidget *vbox = ui_gtk_vbox_new(0); 208 GtkWidget *vbox = ui_gtk_vbox_new(0);
160 #ifdef UI_LIBADWAITA 209 #ifdef UI_LIBADWAITA
161 GtkWidget *toolbar_view = adw_toolbar_view_new(); 210 GtkWidget *toolbar_view = adw_toolbar_view_new();
162 adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(toolbar_view), vbox); 211 adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(toolbar_view), vbox);
163 212
164 GtkWidget *content_box = ui_gtk_vbox_new(0); 213 GtkWidget *headerbar_sidebar = NULL;
165 BOX_ADD_EXPAND(GTK_BOX(vbox), content_box); 214 GtkWidget *headerbar_main = adw_header_bar_new();
166 215 GtkWidget *headerbar_right = NULL;
167 GtkWidget *sidebar_headerbar = NULL; 216
217 GtkWidget *content = toolbar_view;
218 if(splitview) {
219 content = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
220 g_signal_connect(
221 content,
222 "destroy",
223 G_CALLBACK(save_window_splitview_pos),
224 NULL);
225
226 const char *splitview_pos_str = ui_get_property("ui.window.splitview.pos");
227 int pos = splitview_window_default_pos;
228 if(pos < 0) {
229 pos = window_width / 2;
230 }
231 if(splitview_pos_str && splitview_window_use_prop) {
232 int splitview_pos = atoi(splitview_pos_str);
233 if(splitview_pos > 0) {
234 pos = splitview_pos;
235 }
236 }
237 gtk_paned_set_position(GTK_PANED(content), pos);
238
239 GtkWidget *right_panel = adw_toolbar_view_new();
240 GtkWidget *right_vbox = ui_gtk_vbox_new(0);
241 adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(right_panel), right_vbox);
242
243 headerbar_right = adw_header_bar_new();
244 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_right), FALSE);
245 adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(right_panel), headerbar_right);
246
247 adw_header_bar_set_show_end_title_buttons(ADW_HEADER_BAR(headerbar_main), FALSE);
248
249 gtk_paned_set_start_child(GTK_PANED(content), toolbar_view);
250 gtk_paned_set_end_child(GTK_PANED(content), right_panel);
251
252 g_object_set_data(G_OBJECT(obj->widget), "ui_window_splitview", content);
253 g_object_set_data(G_OBJECT(obj->widget), "ui_left_panel", vbox);
254 g_object_set_data(G_OBJECT(obj->widget), "ui_right_panel", right_vbox);
255 }
256
257 GtkWidget *content_box = vbox;
258
168 if(sidebar) { 259 if(sidebar) {
169 GtkWidget *splitview = adw_overlay_split_view_new(); 260 GtkWidget *splitview = adw_overlay_split_view_new();
170 adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), splitview); 261 adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), splitview);
171 262
172 GtkWidget *sidebar_toolbar_view = adw_toolbar_view_new(); 263 GtkWidget *sidebar_toolbar_view = adw_toolbar_view_new();
173 adw_overlay_split_view_set_sidebar(ADW_OVERLAY_SPLIT_VIEW(splitview), sidebar_toolbar_view); 264 adw_overlay_split_view_set_sidebar(ADW_OVERLAY_SPLIT_VIEW(splitview), sidebar_toolbar_view);
174 sidebar_headerbar = adw_header_bar_new(); 265 headerbar_sidebar = adw_header_bar_new();
175 adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), sidebar_headerbar); 266 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
176 267 adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), headerbar_sidebar);
177 adw_overlay_split_view_set_content(ADW_OVERLAY_SPLIT_VIEW(splitview), toolbar_view); 268
269 adw_overlay_split_view_set_content(ADW_OVERLAY_SPLIT_VIEW(splitview), content);
178 270
179 g_object_set_data(G_OBJECT(obj->widget), "ui_sidebar", sidebar_toolbar_view); 271 g_object_set_data(G_OBJECT(obj->widget), "ui_sidebar", sidebar_toolbar_view);
180 } else { 272 } else {
181 adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), toolbar_view); 273 adw_application_window_set_content(ADW_APPLICATION_WINDOW(obj->widget), content);
182 } 274 }
183
184 GtkWidget *headerbar = adw_header_bar_new();
185 275
186 const char *show_title = ui_get_property("ui.gtk.window.showtitle"); 276 const char *show_title = ui_get_property("ui.gtk.window.showtitle");
187 if(show_title) { 277 if(show_title) {
188 if(!strcmp(show_title, "main") && sidebar) { 278 if(!strcmp(show_title, "main") && sidebar) {
189 adw_header_bar_set_show_title(ADW_HEADER_BAR(sidebar_headerbar), FALSE); 279 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
190 } else if(!strcmp(show_title, "sidebar")) { 280 } else if(!strcmp(show_title, "sidebar")) {
191 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar), FALSE); 281 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
282 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
192 } else if(!strcmp(show_title, "false")) { 283 } else if(!strcmp(show_title, "false")) {
193 adw_header_bar_set_show_title(ADW_HEADER_BAR(sidebar_headerbar), FALSE); 284 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
194 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar), FALSE); 285 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
195 } else { 286 } else {
196 fprintf(stderr, "Unknown value '%s' for property ui.gtk.window.showtitle\n", show_title); 287 fprintf(stderr, "Unknown value '%s' for property ui.gtk.window.showtitle\n", show_title);
197 adw_header_bar_set_show_title(ADW_HEADER_BAR(sidebar_headerbar), FALSE); 288 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
198 } 289 }
199 } else { 290 } else {
200 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar), FALSE); 291 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
201 } 292 if(sidebar) {
202 293 adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
203 adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar); 294 }
204 g_object_set_data(G_OBJECT(obj->widget), "ui_headerbar", headerbar); 295 }
296
297 adw_toolbar_view_add_top_bar(ADW_TOOLBAR_VIEW(toolbar_view), headerbar_main);
298 g_object_set_data(G_OBJECT(obj->widget), "ui_headerbar", headerbar_main);
205 299
206 if(!simple) { 300 if(!simple) {
207 ui_fill_headerbar(obj, headerbar); 301 ui_fill_headerbar(obj, headerbar_sidebar, headerbar_main, headerbar_right);
208 } 302 }
209 #elif GTK_MAJOR_VERSION >= 4 303 #elif GTK_MAJOR_VERSION >= 4
210 GtkWidget *content_box = ui_gtk_vbox_new(0); 304 GtkWidget *content_box = ui_gtk_vbox_new(0);
211 WINDOW_SET_CONTENT(obj->widget, vbox); 305 WINDOW_SET_CONTENT(obj->widget, vbox);
212 if(!simple) { 306 if(!simple) {
284 return obj; 378 return obj;
285 } 379 }
286 380
287 381
288 UiObject* ui_window(const char *title, void *window_data) { 382 UiObject* ui_window(const char *title, void *window_data) {
289 return create_window(title, window_data, FALSE, FALSE); 383 return create_window(title, window_data, FALSE, FALSE, FALSE);
290 } 384 }
291 385
292 UiObject *ui_sidebar_window(const char *title, void *window_data) { 386 UiObject *ui_sidebar_window(const char *title, void *window_data) {
293 return create_window(title, window_data, TRUE, FALSE); 387 return create_window(title, window_data, TRUE, FALSE, FALSE);
388 }
389
390 UIEXPORT UiObject *ui_splitview_window(const char *title, UiBool sidebar) {
391 return create_window(title, NULL, sidebar, TRUE, FALSE);
294 } 392 }
295 393
296 UiObject* ui_simple_window(const char *title, void *window_data) { 394 UiObject* ui_simple_window(const char *title, void *window_data) {
297 return create_window(title, window_data, FALSE, TRUE); 395 return create_window(title, window_data, FALSE, FALSE, TRUE);
298 } 396 }
299 397
300 void ui_window_size(UiObject *obj, int width, int height) { 398 void ui_window_size(UiObject *obj, int width, int height) {
301 gtk_window_set_default_size( 399 gtk_window_set_default_size(
302 GTK_WINDOW(obj->widget), 400 GTK_WINDOW(obj->widget),
303 width, 401 width,
304 height); 402 height);
403 }
404
405 void ui_window_default_size(int width, int height) {
406 window_default_width = width;
407 window_default_height = height;
408 }
409
410 void ui_splitview_window_set_pos(UiObject *obj, int pos) {
411 GtkWidget *splitview = g_object_get_data(G_OBJECT(obj->widget), "ui_window_splitview");
412 if(splitview) {
413 gtk_paned_set_position(GTK_PANED(splitview), pos);
414 } else {
415 fprintf(stderr, "Error: window has no splitview\n");
416 }
417 }
418
419 int ui_splitview_window_get_pos(UiObject *obj) {
420 GtkWidget *splitview = g_object_get_data(G_OBJECT(obj->widget), "ui_window_splitview");
421 if(splitview) {
422 return gtk_paned_get_position(GTK_PANED(splitview));
423 } else {
424 fprintf(stderr, "Error: window has no splitview\n");
425 }
426 return 0;
427 }
428
429 void ui_splitview_window_set_default_pos(int pos) {
430 splitview_window_default_pos = pos;
431 }
432
433 void ui_splitview_window_use_property(UiBool enable) {
434 splitview_window_use_prop = enable;
305 } 435 }
306 436
307 #ifdef UI_LIBADWAITA 437 #ifdef UI_LIBADWAITA
308 438
309 static void dialog_response(AdwAlertDialog *self, gchar *response, UiEventData *data) { 439 static void dialog_response(AdwAlertDialog *self, gchar *response, UiEventData *data) {
691 dialog, 821 dialog,
692 "destroy", 822 "destroy",
693 G_CALLBACK(ui_destroy_userdata), 823 G_CALLBACK(ui_destroy_userdata),
694 event); 824 event);
695 825
696
697 UiEvent evt;
698 evt.obj = obj;
699 evt.document = evt.obj->ctx->document;
700 evt.window = evt.obj->window;
701 evt.intval = 0;
702
703 UiFileList flist;
704 flist.files = NULL;
705 flist.nfiles = 0;
706 evt.eventdata = &flist;
707
708 gtk_widget_show(dialog); 826 gtk_widget_show(dialog);
709 } 827 }
710 #endif 828 #endif
711 829
712 void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) { 830 void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {

mercurial