UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2024 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "headerbar.h" 30 31 #include "button.h" 32 #include "menu.h" 33 34 #include "../ui/properties.h" 35 36 #if GTK_CHECK_VERSION(3, 10, 0) 37 38 void ui_fill_headerbar(UiObject *obj, GtkWidget *sidebar_headerbar, GtkWidget *main_headerbar, GtkWidget *right_headerbar) { 39 CxList *sidebar_left_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_SIDEBAR_LEFT); 40 CxList *sidebar_right_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_SIDEBAR_RIGHT); 41 42 CxList *left_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_LEFT); 43 CxList *center_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_CENTER); 44 CxList *right_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_RIGHT); 45 46 CxList *rightpanel_left_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_RIGHTPANEL_LEFT); 47 CxList *rightpanel_center_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_RIGHTPANEL_CENTER); 48 CxList *rightpanel_right_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_RIGHTPANEL_RIGHT); 49 50 UiToolbarMenuItem *appmenu = uic_get_appmenu(); 51 const char *appmenu_pos_str = ui_get_property("ui.gtk.window.appmenu.position"); 52 int appmenu_pos = UI_TOOLBAR_RIGHT; 53 if(sidebar_headerbar) { 54 appmenu_pos = UI_TOOLBAR_SIDEBAR_RIGHT; 55 } else if(right_headerbar) { 56 appmenu_pos = UI_TOOLBAR_RIGHTPANEL_RIGHT; 57 } 58 if(appmenu_pos_str) { 59 if(!strcmp(appmenu_pos_str, "sidebar") && sidebar_headerbar) { 60 appmenu_pos = UI_TOOLBAR_SIDEBAR_RIGHT; 61 } else if(!strcmp(appmenu_pos_str, "main")) { 62 appmenu_pos = UI_TOOLBAR_RIGHT; 63 } else if(!strcmp(appmenu_pos_str, "rightpanel") && right_headerbar) { 64 appmenu_pos = UI_TOOLBAR_RIGHTPANEL_RIGHT; 65 } 66 } 67 68 // main toolbar 69 ui_headerbar_add_items(obj, main_headerbar, left_defaults, UI_TOOLBAR_LEFT); 70 ui_headerbar_add_items(obj, main_headerbar, center_defaults, UI_TOOLBAR_CENTER); 71 72 if(appmenu && appmenu_pos == UI_TOOLBAR_RIGHT) { 73 ui_add_headerbar_menu(main_headerbar, NULL, appmenu, obj, UI_TOOLBAR_RIGHT); 74 } 75 ui_headerbar_add_items(obj, main_headerbar, right_defaults, UI_TOOLBAR_RIGHT); 76 77 // sidebar 78 if(sidebar_headerbar) { 79 // ui_headerbar_add_items pos parameter uses only UI_TOOLBAR_LEFT, UI_TOOLBAR_CENTER, UI_TOOLBAR_RIGHT 80 ui_headerbar_add_items(obj, sidebar_headerbar, sidebar_left_defaults, UI_TOOLBAR_LEFT); 81 82 if(appmenu && appmenu_pos == UI_TOOLBAR_SIDEBAR_RIGHT) { 83 ui_add_headerbar_menu(sidebar_headerbar, NULL, appmenu, obj, UI_TOOLBAR_RIGHT); 84 } 85 ui_headerbar_add_items(obj, sidebar_headerbar, sidebar_right_defaults, UI_TOOLBAR_RIGHT); 86 } 87 88 // right panel 89 if(right_headerbar) { 90 ui_headerbar_add_items(obj, right_headerbar, rightpanel_left_defaults, UI_TOOLBAR_LEFT); 91 ui_headerbar_add_items(obj, right_headerbar, rightpanel_center_defaults, UI_TOOLBAR_CENTER); 92 93 if(appmenu && appmenu_pos == UI_TOOLBAR_RIGHTPANEL_RIGHT) { 94 ui_add_headerbar_menu(right_headerbar, NULL, appmenu, obj, UI_TOOLBAR_RIGHT); 95 } 96 ui_headerbar_add_items(obj, right_headerbar, rightpanel_right_defaults, UI_TOOLBAR_RIGHT); 97 } 98 } 99 100 static void create_item(UiObject *obj, GtkWidget *headerbar, GtkWidget *box, UiToolbarItemI *i, enum UiToolbarPos pos) { 101 switch(i->type) { 102 case UI_TOOLBAR_ITEM: { 103 ui_add_headerbar_item(headerbar, box, (UiToolbarItem*)i, obj, pos); 104 break; 105 } 106 case UI_TOOLBAR_TOGGLEITEM: { 107 ui_add_headerbar_toggleitem(headerbar, box, (UiToolbarToggleItem*)i, obj, pos); 108 break; 109 } 110 case UI_TOOLBAR_MENU: { 111 ui_add_headerbar_menu(headerbar, box, (UiToolbarMenuItem*)i, obj, pos); 112 break; 113 } 114 default: fprintf(stderr, "toolbar item type unimplemented: %d\n", (int)i->type); 115 } 116 } 117 118 static void headerbar_add(GtkWidget *headerbar, GtkWidget *box, GtkWidget *item, enum UiToolbarPos pos) { 119 switch(pos) { 120 case UI_TOOLBAR_LEFT: { 121 UI_HEADERBAR_PACK_START(headerbar, item); 122 break; 123 } 124 case UI_TOOLBAR_CENTER: { 125 126 #if GTK_MAJOR_VERSION >= 4 127 gtk_box_append(GTK_BOX(box), item); 128 #else 129 gtk_box_pack_start(GTK_BOX(box), item, 0, 0, 0); 130 #endif 131 break; 132 } 133 case UI_TOOLBAR_RIGHT: { 134 UI_HEADERBAR_PACK_END(headerbar, item); 135 break; 136 } 137 } 138 } 139 140 void ui_headerbar_add_items(UiObject *obj, GtkWidget *headerbar, CxList *items, enum UiToolbarPos pos) { 141 GtkWidget *box = NULL; 142 143 if(pos == UI_TOOLBAR_CENTER && cxListSize(items) > 0) { 144 box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); 145 UI_HEADERBAR_SET_TITLE_WIDGET(headerbar, box); 146 } 147 148 CxIterator i = pos == UI_TOOLBAR_RIGHT ? cxListBackwardsIterator(items) : cxListIterator(items); 149 cx_foreach(char*, def, i) { 150 UiToolbarItemI* item = uic_toolbar_get_item(def); 151 if (!item) { 152 fprintf(stderr, "unknown toolbar item: %s\n", def); 153 continue; 154 } 155 create_item(obj, headerbar, box, item, pos); 156 } 157 } 158 159 void ui_add_headerbar_item( 160 GtkWidget *headerbar, 161 GtkWidget *box, 162 UiToolbarItem *item, 163 UiObject *obj, 164 enum UiToolbarPos pos) 165 { 166 GtkWidget *button = ui_create_button(obj, item->args.label, item->args.icon, item->args.tooltip, item->args.onclick, item->args.onclickdata, 0, FALSE); 167 ui_set_widget_states(obj->ctx, button, item->args.states); 168 ui_set_widget_visibility_states(obj->ctx, button, item->args.visibility_states); 169 WIDGET_ADD_CSS_CLASS(button, "flat"); 170 headerbar_add(headerbar, box, button, pos); 171 } 172 173 void ui_add_headerbar_toggleitem( 174 GtkWidget *headerbar, 175 GtkWidget *box, 176 UiToolbarToggleItem *item, 177 UiObject *obj, 178 enum UiToolbarPos pos) 179 { 180 GtkWidget *button = gtk_toggle_button_new(); 181 ui_set_widget_states(obj->ctx, button, item->args.states); 182 ui_set_widget_visibility_states(obj->ctx, button, item->args.visibility_states); 183 WIDGET_ADD_CSS_CLASS(button, "flat"); 184 ui_setup_togglebutton(obj, button, item->args.label, item->args.icon, item->args.tooltip, item->args.varname, NULL, item->args.onchange, item->args.onchangedata, 0); 185 headerbar_add(headerbar, box, button, pos); 186 } 187 188 void ui_add_headerbar_menu( 189 GtkWidget *headerbar, 190 GtkWidget *box, 191 UiToolbarMenuItem *item, 192 UiObject *obj, 193 enum UiToolbarPos pos) 194 { 195 196 197 #if GTK_MAJOR_VERSION >= 4 198 GtkWidget *menubutton = gtk_menu_button_new(); 199 ui_set_widget_visibility_states(obj->ctx, menubutton, item->args.visibility_states); 200 if(item->args.label) { 201 gtk_menu_button_set_label(GTK_MENU_BUTTON(menubutton), item->args.label); 202 } 203 if(item->args.icon) { 204 gtk_menu_button_set_icon_name(GTK_MENU_BUTTON(menubutton), item->args.icon); 205 } 206 207 if(!item->args.label && !item->args.icon) { 208 gtk_menu_button_set_icon_name(GTK_MENU_BUTTON(menubutton), "open-menu-symbolic"); 209 } 210 211 GMenu *menu = g_menu_new(); 212 ui_gmenu_add_menu_items(menu, 0, &item->menu, obj); 213 214 gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(menubutton), G_MENU_MODEL(menu)); 215 #else 216 GtkWidget *menubutton = gtk_menu_button_new(); 217 GtkWidget *menu = gtk_menu_new(); 218 ui_add_menu_items(menu, 0, &item->menu, obj); 219 gtk_widget_show_all(menu); 220 gtk_menu_button_set_popup(GTK_MENU_BUTTON(menubutton), menu); 221 222 #endif 223 224 headerbar_add(headerbar, box, menubutton, pos); 225 } 226 227 #endif // GTK_CHECK_VERSION(3, 10, 0) 228