| File: | ctk/ctkmenusectionbox.c |
| Warning: | line 394, column 28 Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* |
| 2 | * Copyright © 2014 Canonical Limited |
| 3 | * Copyright © 2013 Carlos Garnacho |
| 4 | * |
| 5 | * This library is free software; you can redistribute it and/or |
| 6 | * modify it under the terms of the GNU Lesser General Public |
| 7 | * License as published by the Free Software Foundation; either |
| 8 | * version 2 of the licence, or (at your option) any later version. |
| 9 | * |
| 10 | * This library is distributed in the hope that it will be useful, |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | * Lesser General Public License for more details. |
| 14 | * |
| 15 | * You should have received a copy of the GNU Lesser General Public |
| 16 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
| 17 | * |
| 18 | * Author: Ryan Lortie <desrt@desrt.ca> |
| 19 | */ |
| 20 | |
| 21 | #include "config.h" |
| 22 | |
| 23 | #include "ctkmenusectionbox.h" |
| 24 | |
| 25 | #include "ctkwidgetprivate.h" |
| 26 | #include "ctklabel.h" |
| 27 | #include "ctkmenutracker.h" |
| 28 | #include "ctkmodelbutton.h" |
| 29 | #include "ctkseparator.h" |
| 30 | #include "ctksizegroup.h" |
| 31 | #include "ctkstack.h" |
| 32 | #include "ctkstylecontext.h" |
| 33 | #include "ctkpopover.h" |
| 34 | #include "ctkorientable.h" |
| 35 | |
| 36 | typedef CtkBoxClass CtkMenuSectionBoxClass; |
| 37 | |
| 38 | struct _CtkMenuSectionBox |
| 39 | { |
| 40 | CtkBox parent_instance; |
| 41 | |
| 42 | CtkMenuSectionBox *toplevel; |
| 43 | CtkMenuTracker *tracker; |
| 44 | CtkBox *item_box; |
| 45 | CtkWidget *separator; |
| 46 | guint separator_sync_idle; |
| 47 | gboolean iconic; |
| 48 | gint depth; |
| 49 | }; |
| 50 | |
| 51 | typedef struct |
| 52 | { |
| 53 | gint n_items; |
| 54 | gboolean previous_is_iconic; |
| 55 | } MenuData; |
| 56 | |
| 57 | G_DEFINE_TYPE (CtkMenuSectionBox, ctk_menu_section_box, CTK_TYPE_BOX)static void ctk_menu_section_box_init (CtkMenuSectionBox *self ); static void ctk_menu_section_box_class_init (CtkMenuSectionBoxClass *klass); static GType ctk_menu_section_box_get_type_once (void ); static gpointer ctk_menu_section_box_parent_class = ((void *)0); static gint CtkMenuSectionBox_private_offset; static void ctk_menu_section_box_class_intern_init (gpointer klass) { ctk_menu_section_box_parent_class = g_type_class_peek_parent (klass); if (CtkMenuSectionBox_private_offset != 0) g_type_class_adjust_private_offset (klass, &CtkMenuSectionBox_private_offset ); ctk_menu_section_box_class_init ((CtkMenuSectionBoxClass*) klass); } __attribute__ ((__unused__)) static inline gpointer ctk_menu_section_box_get_instance_private (CtkMenuSectionBox *self) { return (((gpointer) ((guint8*) (self) + (glong) (CtkMenuSectionBox_private_offset )))); } GType ctk_menu_section_box_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); (void) (0 ? (gpointer) * ( &static_g_define_type_id) : ((void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = ctk_menu_section_box_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType ctk_menu_section_box_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple ((ctk_box_get_type ()), g_intern_static_string ("CtkMenuSectionBox" ), sizeof (CtkMenuSectionBoxClass), (GClassInitFunc)(void (*) (void)) ctk_menu_section_box_class_intern_init, sizeof (CtkMenuSectionBox ), (GInstanceInitFunc)(void (*)(void)) ctk_menu_section_box_init , (GTypeFlags) 0); { {{};} } return g_define_type_id; } |
| 58 | |
| 59 | static void ctk_menu_section_box_sync_separators (CtkMenuSectionBox *box, |
| 60 | MenuData *data); |
| 61 | static void ctk_menu_section_box_new_submenu (CtkMenuTrackerItem *item, |
| 62 | CtkMenuSectionBox *toplevel, |
| 63 | CtkWidget *focus, |
| 64 | const gchar *name); |
| 65 | static CtkWidget * ctk_menu_section_box_new_section (CtkMenuTrackerItem *item, |
| 66 | CtkMenuSectionBox *parent); |
| 67 | |
| 68 | static void |
| 69 | ctk_menu_section_box_sync_item (CtkWidget *widget, |
| 70 | gpointer user_data) |
| 71 | { |
| 72 | MenuData *data = (MenuData *)user_data; |
| 73 | |
| 74 | if (CTK_IS_MENU_SECTION_BOX (widget)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (widget)); GType __t = ((ctk_menu_section_box_get_type ())); gboolean __r; if (!__inst) __r = (0); else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; }))))) |
| 75 | ctk_menu_section_box_sync_separators (CTK_MENU_SECTION_BOX (widget)((((CtkMenuSectionBox*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((widget)), ((ctk_menu_section_box_get_type ( ))))))), data); |
| 76 | else |
| 77 | data->n_items++; |
| 78 | } |
| 79 | |
| 80 | /* We are trying to implement the following rules here: |
| 81 | * |
| 82 | * rule 1: never ever show separators for empty sections |
| 83 | * rule 2: always show a separator if there is a label |
| 84 | * rule 3: don't show a separator for the first section |
| 85 | * rule 4: don't show a separator for the following sections if there are |
| 86 | * no items before it |
| 87 | * rule 5: never show separators directly above or below an iconic box |
| 88 | * (rule 6: these rules don't apply exactly the same way for subsections) |
| 89 | */ |
| 90 | static void |
| 91 | ctk_menu_section_box_sync_separators (CtkMenuSectionBox *box, |
| 92 | MenuData *data) |
| 93 | { |
| 94 | gboolean previous_section_is_iconic; |
| 95 | gboolean should_have_separator; |
| 96 | gboolean should_have_top_margin = FALSE(0); |
| 97 | gboolean is_not_empty_item; |
| 98 | gboolean has_separator; |
| 99 | gboolean has_label; |
| 100 | gboolean separator_condition; |
| 101 | gint n_items_before; |
| 102 | |
| 103 | n_items_before = data->n_items; |
| 104 | previous_section_is_iconic = data->previous_is_iconic; |
| 105 | |
| 106 | ctk_container_foreach (CTK_CONTAINER (box->item_box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_container_get_type ())))))), ctk_menu_section_box_sync_item, data); |
| 107 | |
| 108 | is_not_empty_item = (data->n_items > n_items_before); |
| 109 | |
| 110 | if (is_not_empty_item) |
| 111 | data->previous_is_iconic = box->iconic; |
| 112 | |
| 113 | if (box->separator == NULL((void*)0)) |
| 114 | return; |
| 115 | |
| 116 | has_separator = ctk_widget_get_parent (box->separator) != NULL((void*)0); |
| 117 | has_label = !CTK_IS_SEPARATOR (box->separator)(((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) ( (box->separator)); GType __t = ((ctk_separator_get_type () )); gboolean __r; if (!__inst) __r = (0); else if (__inst-> g_class && __inst->g_class->g_type == __t) __r = (!(0)); else __r = g_type_check_instance_is_a (__inst, __t); __r; })))); |
| 118 | |
| 119 | separator_condition = has_label ? TRUE(!(0)) : n_items_before > 0 && |
| 120 | box->depth <= 1 && |
| 121 | !previous_section_is_iconic && |
| 122 | !box->iconic; |
| 123 | |
| 124 | should_have_separator = separator_condition && is_not_empty_item; |
| 125 | |
| 126 | should_have_top_margin = !should_have_separator && |
| 127 | (box->depth <= 1 || box->iconic) && |
| 128 | n_items_before > 0 && |
| 129 | is_not_empty_item; |
| 130 | |
| 131 | ctk_widget_set_margin_top (CTK_WIDGET (box->item_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_widget_get_type ())))))), should_have_top_margin ? 10 : 0); |
| 132 | |
| 133 | if (should_have_separator == has_separator) |
| 134 | return; |
| 135 | |
| 136 | if (should_have_separator) |
| 137 | ctk_box_pack_start (CTK_BOX (box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_box_get_type ())))))), box->separator, FALSE(0), FALSE(0), 0); |
| 138 | else |
| 139 | ctk_container_remove (CTK_CONTAINER (box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_container_get_type ())))))), box->separator); |
| 140 | } |
| 141 | |
| 142 | static gboolean |
| 143 | ctk_menu_section_box_handle_sync_separators (gpointer user_data) |
| 144 | { |
| 145 | CtkMenuSectionBox *box = user_data; |
| 146 | MenuData data; |
| 147 | |
| 148 | data.n_items = 0; |
| 149 | data.previous_is_iconic = FALSE(0); |
| 150 | ctk_menu_section_box_sync_separators (box, &data); |
| 151 | |
| 152 | box->separator_sync_idle = 0; |
| 153 | |
| 154 | return G_SOURCE_REMOVE(0); |
| 155 | } |
| 156 | |
| 157 | static void |
| 158 | ctk_menu_section_box_schedule_separator_sync (CtkMenuSectionBox *box) |
| 159 | { |
| 160 | box = box->toplevel; |
| 161 | |
| 162 | if (!box->separator_sync_idle) |
| 163 | box->separator_sync_idle = cdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE100, /* before resize... */ |
| 164 | ctk_menu_section_box_handle_sync_separators, |
| 165 | box, NULL((void*)0)); |
| 166 | } |
| 167 | |
| 168 | static void |
| 169 | ctk_popover_item_activate (CtkWidget *button, |
| 170 | gpointer user_data) |
| 171 | { |
| 172 | CtkMenuTrackerItem *item = user_data; |
| 173 | CtkWidget *popover = NULL((void*)0); |
| 174 | |
| 175 | if (ctk_menu_tracker_item_get_role (item) == CTK_MENU_TRACKER_ITEM_ROLE_NORMAL) |
| 176 | { |
| 177 | /* Activating the item could cause the popover |
| 178 | * to be free'd, for example if it is a Quit item |
| 179 | */ |
| 180 | popover = g_object_ref (ctk_widget_get_ancestor (button,((__typeof__ (ctk_widget_get_ancestor (button, (ctk_popover_get_type ())))) (g_object_ref) (ctk_widget_get_ancestor (button, (ctk_popover_get_type ())))) |
| 181 | CTK_TYPE_POPOVER))((__typeof__ (ctk_widget_get_ancestor (button, (ctk_popover_get_type ())))) (g_object_ref) (ctk_widget_get_ancestor (button, (ctk_popover_get_type ())))); |
| 182 | } |
| 183 | |
| 184 | ctk_menu_tracker_item_activated (item); |
| 185 | |
| 186 | if (popover != NULL((void*)0)) |
| 187 | { |
| 188 | ctk_widget_hide (popover); |
| 189 | g_object_unref (popover); |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | static void |
| 194 | ctk_menu_section_box_remove_func (gint position, |
| 195 | gpointer user_data) |
| 196 | { |
| 197 | CtkMenuSectionBox *box = user_data; |
| 198 | CtkMenuTrackerItem *item; |
| 199 | CtkWidget *widget; |
| 200 | GList *children; |
| 201 | |
| 202 | children = ctk_container_get_children (CTK_CONTAINER (box->item_box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_container_get_type ()))))))); |
| 203 | |
| 204 | widget = g_list_nth_data (children, position); |
| 205 | |
| 206 | item = g_object_get_data (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), (((GType) ((20) << (2)))))))), "CtkMenuTrackerItem"); |
| 207 | if (ctk_menu_tracker_item_get_has_link (item, G_MENU_LINK_SUBMENU"submenu")) |
| 208 | { |
| 209 | CtkWidget *stack, *subbox; |
| 210 | |
| 211 | stack = ctk_widget_get_ancestor (CTK_WIDGET (box->toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->toplevel)), ((ctk_widget_get_type ())))))), CTK_TYPE_STACK(ctk_stack_get_type ())); |
| 212 | subbox = ctk_stack_get_child_by_name (CTK_STACK (stack)((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((stack)), ((ctk_stack_get_type ())))))), ctk_menu_tracker_item_get_label (item)); |
| 213 | if (subbox != NULL((void*)0)) |
| 214 | ctk_container_remove (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((stack)), ((ctk_container_get_type ())))))), subbox); |
| 215 | } |
| 216 | |
| 217 | ctk_widget_destroy (g_list_nth_data (children, position)); |
| 218 | g_list_free (children); |
| 219 | |
| 220 | ctk_menu_section_box_schedule_separator_sync (box); |
| 221 | } |
| 222 | |
| 223 | static gboolean |
| 224 | get_ancestors (CtkWidget *widget, |
| 225 | GType widget_type, |
| 226 | CtkWidget **ancestor, |
| 227 | CtkWidget **below) |
| 228 | { |
| 229 | CtkWidget *a, *b; |
| 230 | |
| 231 | a = NULL((void*)0); |
| 232 | b = widget; |
| 233 | while (b != NULL((void*)0)) |
| 234 | { |
| 235 | a = ctk_widget_get_parent (b); |
| 236 | if (!a) |
| 237 | return FALSE(0); |
| 238 | if (g_type_is_a (G_OBJECT_TYPE (a), widget_type)(((((((GTypeClass*) (((GTypeInstance*) (a))->g_class))-> g_type)))) == (widget_type) || (g_type_is_a) (((((((GTypeClass *) (((GTypeInstance*) (a))->g_class))->g_type)))), (widget_type )))) |
| 239 | break; |
| 240 | b = a; |
| 241 | } |
| 242 | |
| 243 | *below = b; |
| 244 | *ancestor = a; |
| 245 | |
| 246 | return TRUE(!(0)); |
| 247 | } |
| 248 | |
| 249 | static void |
| 250 | close_submenu (CtkWidget *button, |
| 251 | gpointer data) |
| 252 | { |
| 253 | CtkMenuTrackerItem *item = data; |
| 254 | CtkWidget *focus; |
| 255 | |
| 256 | if (ctk_menu_tracker_item_get_should_request_show (item)) |
| 257 | ctk_menu_tracker_item_request_submenu_shown (item, FALSE(0)); |
| 258 | |
| 259 | focus = CTK_WIDGET (g_object_get_data (G_OBJECT (button), "focus"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((button)), (((GType) ((20) << (2))) ))))), "focus"))), ((ctk_widget_get_type ())))))); |
| 260 | ctk_widget_grab_focus (focus); |
| 261 | } |
| 262 | |
| 263 | static void |
| 264 | open_submenu (CtkWidget *button, |
| 265 | gpointer data) |
| 266 | { |
| 267 | CtkMenuTrackerItem *item = data; |
| 268 | CtkWidget *focus; |
| 269 | |
| 270 | if (ctk_menu_tracker_item_get_should_request_show (item)) |
| 271 | ctk_menu_tracker_item_request_submenu_shown (item, TRUE(!(0))); |
| 272 | |
| 273 | focus = CTK_WIDGET (g_object_get_data (G_OBJECT (button), "focus"))((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((g_object_get_data (((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((button)), (((GType) ((20) << (2))) ))))), "focus"))), ((ctk_widget_get_type ())))))); |
| 274 | ctk_widget_grab_focus (focus); |
| 275 | } |
| 276 | |
| 277 | static void |
| 278 | ctk_menu_section_box_insert_func (CtkMenuTrackerItem *item, |
| 279 | gint position, |
| 280 | gpointer user_data) |
| 281 | { |
| 282 | CtkMenuSectionBox *box = user_data; |
| 283 | CtkWidget *widget; |
| 284 | |
| 285 | if (ctk_menu_tracker_item_get_is_separator (item)) |
| 286 | { |
| 287 | widget = ctk_menu_section_box_new_section (item, box); |
| 288 | } |
| 289 | else if (ctk_menu_tracker_item_get_has_link (item, G_MENU_LINK_SUBMENU"submenu")) |
| 290 | { |
| 291 | CtkWidget *stack = NULL((void*)0); |
| 292 | CtkWidget *parent = NULL((void*)0); |
| 293 | gchar *name; |
| 294 | |
| 295 | widget = g_object_new (CTK_TYPE_MODEL_BUTTON(ctk_model_button_get_type ()), |
| 296 | "menu-name", ctk_menu_tracker_item_get_label (item), |
| 297 | NULL((void*)0)); |
| 298 | g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE); |
| 299 | g_object_bind_property (item, "icon", widget, "icon", G_BINDING_SYNC_CREATE); |
| 300 | g_object_bind_property (item, "sensitive", widget, "sensitive", G_BINDING_SYNC_CREATE); |
| 301 | |
| 302 | get_ancestors (CTK_WIDGET (box->toplevel)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->toplevel)), ((ctk_widget_get_type ())))))), CTK_TYPE_STACK(ctk_stack_get_type ()), &stack, &parent); |
| 303 | ctk_container_child_get (CTK_CONTAINER (stack)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((stack)), ((ctk_container_get_type ())))))), parent, "name", &name, NULL((void*)0)); |
| 304 | ctk_menu_section_box_new_submenu (item, box->toplevel, widget, name); |
| 305 | g_free (name); |
| 306 | } |
| 307 | else |
| 308 | { |
| 309 | widget = ctk_model_button_new (); |
| 310 | g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE); |
| 311 | |
| 312 | if (box->iconic) |
| 313 | { |
| 314 | g_object_bind_property (item, "verb-icon", widget, "icon", G_BINDING_SYNC_CREATE); |
| 315 | g_object_set (widget, "iconic", TRUE(!(0)), "centered", TRUE(!(0)), NULL((void*)0)); |
| 316 | } |
| 317 | else |
| 318 | g_object_bind_property (item, "icon", widget, "icon", G_BINDING_SYNC_CREATE); |
| 319 | |
| 320 | g_object_bind_property (item, "sensitive", widget, "sensitive", G_BINDING_SYNC_CREATE); |
| 321 | g_object_bind_property (item, "role", widget, "role", G_BINDING_SYNC_CREATE); |
| 322 | g_object_bind_property (item, "toggled", widget, "active", G_BINDING_SYNC_CREATE); |
| 323 | g_signal_connect (widget, "clicked", G_CALLBACK (ctk_popover_item_activate), item)g_signal_connect_data ((widget), ("clicked"), (((GCallback) ( ctk_popover_item_activate))), (item), ((void*)0), (GConnectFlags ) 0); |
| 324 | } |
| 325 | |
| 326 | ctk_widget_show (widget); |
| 327 | |
| 328 | g_object_set_data_full (G_OBJECT (widget)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((widget)), (((GType) ((20) << (2)))))))), "CtkMenuTrackerItem", g_object_ref (item)((__typeof__ (item)) (g_object_ref) (item)), g_object_unref); |
| 329 | |
| 330 | ctk_widget_set_halign (widget, CTK_ALIGN_FILL); |
| 331 | if (box->iconic) |
| 332 | ctk_box_pack_start (CTK_BOX (box->item_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_box_get_type ())))))), widget, TRUE(!(0)), TRUE(!(0)), 0); |
| 333 | else |
| 334 | ctk_container_add (CTK_CONTAINER (box->item_box)((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_container_get_type ())))))), widget); |
| 335 | ctk_box_reorder_child (CTK_BOX (box->item_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_box_get_type ())))))), widget, position); |
| 336 | |
| 337 | ctk_menu_section_box_schedule_separator_sync (box); |
| 338 | } |
| 339 | |
| 340 | static void |
| 341 | ctk_menu_section_box_init (CtkMenuSectionBox *box) |
| 342 | { |
| 343 | CtkWidget *item_box; |
| 344 | |
| 345 | ctk_orientable_set_orientation (CTK_ORIENTABLE (box)((((CtkOrientable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_orientable_get_type ())))))), CTK_ORIENTATION_VERTICAL); |
| 346 | |
| 347 | box->toplevel = box; |
| 348 | |
| 349 | item_box = ctk_box_new (CTK_ORIENTATION_VERTICAL, 0); |
| 350 | box->item_box = CTK_BOX (item_box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item_box)), ((ctk_box_get_type ())))))); |
| 351 | ctk_box_pack_end (CTK_BOX (box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_box_get_type ())))))), item_box, FALSE(0), FALSE(0), 0); |
| 352 | ctk_widget_set_halign (CTK_WIDGET (item_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((item_box)), ((ctk_widget_get_type ())))))), CTK_ALIGN_FILL); |
| 353 | ctk_widget_show (item_box); |
| 354 | |
| 355 | ctk_widget_set_halign (CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_widget_get_type ())))))), CTK_ALIGN_FILL); |
| 356 | g_object_set (box, "margin", 0, NULL((void*)0)); |
| 357 | |
| 358 | } |
| 359 | |
| 360 | static void |
| 361 | ctk_menu_section_box_dispose (GObject *object) |
| 362 | { |
| 363 | CtkMenuSectionBox *box = CTK_MENU_SECTION_BOX (object)((((CtkMenuSectionBox*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((object)), ((ctk_menu_section_box_get_type ( ))))))); |
| 364 | |
| 365 | if (box->separator_sync_idle) |
| 366 | { |
| 367 | g_source_remove (box->separator_sync_idle); |
| 368 | box->separator_sync_idle = 0; |
| 369 | } |
| 370 | |
| 371 | g_clear_object (&box->separator)do { _Static_assert (sizeof *((&box->separator)) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ ((( &box->separator))) _pp = ((&box->separator)); __typeof__ (*((&box->separator))) _ptr = *_pp; *_pp = ((void*)0) ; if (_ptr) (g_object_unref) (_ptr); } while (0); |
| 372 | |
| 373 | if (box->tracker) |
| 374 | { |
| 375 | ctk_menu_tracker_free (box->tracker); |
| 376 | box->tracker = NULL((void*)0); |
| 377 | } |
| 378 | |
| 379 | G_OBJECT_CLASS (ctk_menu_section_box_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((ctk_menu_section_box_parent_class)), (((GType) ((20) << (2))))))))->dispose (object); |
| 380 | } |
| 381 | |
| 382 | static void |
| 383 | ctk_menu_section_box_class_init (CtkMenuSectionBoxClass *class) |
| 384 | { |
| 385 | G_OBJECT_CLASS (class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((class)), (((GType) ((20) << (2))))))))->dispose = ctk_menu_section_box_dispose; |
| 386 | } |
| 387 | |
| 388 | static void |
| 389 | update_popover_position_cb (GObject *source, |
| 390 | GParamSpec *spec G_GNUC_UNUSED__attribute__ ((__unused__)), |
| 391 | gpointer *user_data) |
| 392 | { |
| 393 | CtkPopover *popover = CTK_POPOVER (source)((((CtkPopover*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((source)), ((ctk_popover_get_type ())))))); |
| 394 | CtkMenuSectionBox *box = CTK_MENU_SECTION_BOX (user_data)((((CtkMenuSectionBox*) (void *) g_type_check_instance_cast ( (GTypeInstance*) ((user_data)), ((ctk_menu_section_box_get_type ())))))); |
Casting a non-structure type to a structure type and accessing a field can lead to memory access errors or data corruption | |
| 395 | |
| 396 | CtkPositionType new_pos = ctk_popover_get_position (popover); |
| 397 | |
| 398 | GList *children = ctk_container_get_children (CTK_CONTAINER (ctk_widget_get_parent (CTK_WIDGET (box)))((((CtkContainer*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((ctk_widget_get_parent (((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((box)), ((ctk_widget_get_type ()))))))))) , ((ctk_container_get_type ()))))))); |
| 399 | GList *l; |
| 400 | |
| 401 | for (l = children; |
| 402 | l != NULL((void*)0); |
| 403 | l = l->next) |
| 404 | { |
| 405 | CtkWidget *w = l->data; |
| 406 | |
| 407 | if (new_pos == CTK_POS_BOTTOM) |
| 408 | ctk_widget_set_valign (w, CTK_ALIGN_START); |
| 409 | else if (new_pos == CTK_POS_TOP) |
| 410 | ctk_widget_set_valign (w, CTK_ALIGN_END); |
| 411 | else |
| 412 | ctk_widget_set_valign (w, CTK_ALIGN_CENTER); |
| 413 | } |
| 414 | |
| 415 | g_list_free (children); |
| 416 | } |
| 417 | |
| 418 | void |
| 419 | ctk_menu_section_box_new_toplevel (CtkStack *stack, |
| 420 | GMenuModel *model, |
| 421 | const gchar *action_namespace, |
| 422 | CtkPopover *popover) |
| 423 | { |
| 424 | CtkMenuSectionBox *box; |
| 425 | |
| 426 | box = g_object_new (CTK_TYPE_MENU_SECTION_BOX(ctk_menu_section_box_get_type ()), "margin", 10, NULL((void*)0)); |
| 427 | ctk_stack_add_named (stack, CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_widget_get_type ())))))), "main"); |
| 428 | |
| 429 | box->tracker = ctk_menu_tracker_new (CTK_ACTION_OBSERVABLE (_ctk_widget_get_action_muxer (CTK_WIDGET (box), TRUE))((((CtkActionObservable*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((_ctk_widget_get_action_muxer (((((CtkWidget *) (void *) g_type_check_instance_cast ((GTypeInstance*) ((box )), ((ctk_widget_get_type ())))))), (!(0))))), ((ctk_action_observable_get_type ())))))), |
| 430 | model, TRUE(!(0)), FALSE(0), FALSE(0), action_namespace, |
| 431 | ctk_menu_section_box_insert_func, |
| 432 | ctk_menu_section_box_remove_func, box); |
| 433 | |
| 434 | g_signal_connect (G_OBJECT (popover), "notify::position", G_CALLBACK (update_popover_position_cb), box)g_signal_connect_data ((((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((popover)), (((GType) ((20) << (2)) ))))))), ("notify::position"), (((GCallback) (update_popover_position_cb ))), (box), ((void*)0), (GConnectFlags) 0); |
| 435 | |
| 436 | |
| 437 | ctk_widget_show (CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_widget_get_type ()))))))); |
| 438 | } |
| 439 | |
| 440 | static void |
| 441 | ctk_menu_section_box_new_submenu (CtkMenuTrackerItem *item, |
| 442 | CtkMenuSectionBox *toplevel, |
| 443 | CtkWidget *focus, |
| 444 | const gchar *name) |
| 445 | { |
| 446 | CtkMenuSectionBox *box; |
| 447 | CtkWidget *button; |
| 448 | |
| 449 | box = g_object_new (CTK_TYPE_MENU_SECTION_BOX(ctk_menu_section_box_get_type ()), "margin", 10, NULL((void*)0)); |
| 450 | |
| 451 | button = g_object_new (CTK_TYPE_MODEL_BUTTON(ctk_model_button_get_type ()), |
| 452 | "menu-name", name, |
| 453 | "inverted", TRUE(!(0)), |
| 454 | "centered", TRUE(!(0)), |
| 455 | NULL((void*)0)); |
| 456 | |
| 457 | g_object_bind_property (item, "label", button, "text", G_BINDING_SYNC_CREATE); |
| 458 | g_object_bind_property (item, "icon", button, "icon", G_BINDING_SYNC_CREATE); |
| 459 | |
| 460 | g_object_set_data (G_OBJECT (button)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((button)), (((GType) ((20) << (2)))))))), "focus", focus); |
| 461 | g_object_set_data (G_OBJECT (focus)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((focus)), (((GType) ((20) << (2)))))))), "focus", button); |
| 462 | |
| 463 | ctk_box_pack_start (CTK_BOX (box)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_box_get_type ())))))), button, FALSE(0), FALSE(0), 0); |
| 464 | ctk_widget_show (button); |
| 465 | |
| 466 | g_signal_connect (focus, "clicked", G_CALLBACK (open_submenu), item)g_signal_connect_data ((focus), ("clicked"), (((GCallback) (open_submenu ))), (item), ((void*)0), (GConnectFlags) 0); |
| 467 | g_signal_connect (button, "clicked", G_CALLBACK (close_submenu), item)g_signal_connect_data ((button), ("clicked"), (((GCallback) ( close_submenu))), (item), ((void*)0), (GConnectFlags) 0); |
| 468 | |
| 469 | ctk_stack_add_named (CTK_STACK (ctk_widget_get_ancestor (CTK_WIDGET (toplevel), CTK_TYPE_STACK))((((CtkStack*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((ctk_widget_get_ancestor (((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance*) ((toplevel)), ((ctk_widget_get_type ())))) )), (ctk_stack_get_type ())))), ((ctk_stack_get_type ())))))), |
| 470 | CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_widget_get_type ())))))), ctk_menu_tracker_item_get_label (item)); |
| 471 | ctk_widget_show (CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_widget_get_type ()))))))); |
| 472 | |
| 473 | box->tracker = ctk_menu_tracker_new_for_item_link (item, G_MENU_LINK_SUBMENU"submenu", FALSE(0), FALSE(0), |
| 474 | ctk_menu_section_box_insert_func, |
| 475 | ctk_menu_section_box_remove_func, |
| 476 | box); |
| 477 | } |
| 478 | |
| 479 | static CtkWidget * |
| 480 | ctk_menu_section_box_new_section (CtkMenuTrackerItem *item, |
| 481 | CtkMenuSectionBox *parent) |
| 482 | { |
| 483 | CtkMenuSectionBox *box; |
| 484 | const gchar *label; |
| 485 | const gchar *hint; |
| 486 | const gchar *text_direction; |
| 487 | |
| 488 | box = g_object_new (CTK_TYPE_MENU_SECTION_BOX(ctk_menu_section_box_get_type ()), NULL((void*)0)); |
| 489 | box->toplevel = parent->toplevel; |
| 490 | box->depth = parent->depth + 1; |
| 491 | |
| 492 | label = ctk_menu_tracker_item_get_label (item); |
| 493 | hint = ctk_menu_tracker_item_get_display_hint (item); |
| 494 | text_direction = ctk_menu_tracker_item_get_text_direction (item); |
| 495 | |
| 496 | if (hint && g_str_equal (hint, "horizontal-buttons")(strcmp ((const char *) (hint), (const char *) ("horizontal-buttons" )) == 0)) |
| 497 | { |
| 498 | ctk_orientable_set_orientation (CTK_ORIENTABLE (box->item_box)((((CtkOrientable*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_orientable_get_type ())))))), CTK_ORIENTATION_HORIZONTAL); |
| 499 | ctk_style_context_add_class (ctk_widget_get_style_context (CTK_WIDGET (box->item_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_widget_get_type ()))))))), CTK_STYLE_CLASS_LINKED"linked"); |
| 500 | box->iconic = TRUE(!(0)); |
| 501 | |
| 502 | if (text_direction) |
| 503 | { |
| 504 | CtkTextDirection dir = CTK_TEXT_DIR_NONE; |
| 505 | |
| 506 | if (g_str_equal (text_direction, "rtl")(strcmp ((const char *) (text_direction), (const char *) ("rtl" )) == 0)) |
| 507 | dir = CTK_TEXT_DIR_RTL; |
| 508 | else if (g_str_equal (text_direction, "ltr")(strcmp ((const char *) (text_direction), (const char *) ("ltr" )) == 0)) |
| 509 | dir = CTK_TEXT_DIR_LTR; |
| 510 | |
| 511 | ctk_widget_set_direction (CTK_WIDGET (box->item_box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->item_box)), ((ctk_widget_get_type ())))))), dir); |
| 512 | } |
| 513 | } |
| 514 | |
| 515 | if (label != NULL((void*)0)) |
| 516 | { |
| 517 | CtkWidget *separator; |
| 518 | CtkWidget *title; |
| 519 | |
| 520 | box->separator = ctk_box_new (CTK_ORIENTATION_HORIZONTAL, 4); |
| 521 | g_object_ref_sink (box->separator)((__typeof__ (box->separator)) (g_object_ref_sink) (box-> separator)); |
| 522 | |
| 523 | separator = ctk_separator_new (CTK_ORIENTATION_HORIZONTAL); |
| 524 | ctk_widget_set_valign (separator, CTK_ALIGN_CENTER); |
| 525 | ctk_box_pack_start (CTK_BOX (box->separator)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->separator)), ((ctk_box_get_type ())))))), separator, TRUE(!(0)), TRUE(!(0)), 0); |
| 526 | |
| 527 | title = ctk_label_new (label); |
| 528 | g_object_bind_property (item, "label", title, "label", G_BINDING_SYNC_CREATE); |
| 529 | ctk_style_context_add_class (ctk_widget_get_style_context (title), CTK_STYLE_CLASS_SEPARATOR"separator"); |
| 530 | ctk_widget_set_halign (title, CTK_ALIGN_START); |
| 531 | ctk_box_pack_start (CTK_BOX (box->separator)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->separator)), ((ctk_box_get_type ())))))), title, FALSE(0), FALSE(0), 0); |
| 532 | |
| 533 | separator = ctk_separator_new (CTK_ORIENTATION_HORIZONTAL); |
| 534 | ctk_widget_set_valign (separator, CTK_ALIGN_CENTER); |
| 535 | ctk_box_pack_start (CTK_BOX (box->separator)((((CtkBox*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box->separator)), ((ctk_box_get_type ())))))), separator, TRUE(!(0)), TRUE(!(0)), 0); |
| 536 | |
| 537 | ctk_widget_show_all (box->separator); |
| 538 | } |
| 539 | else |
| 540 | { |
| 541 | box->separator = ctk_separator_new (CTK_ORIENTATION_HORIZONTAL); |
| 542 | g_object_ref_sink (box->separator)((__typeof__ (box->separator)) (g_object_ref_sink) (box-> separator)); |
| 543 | |
| 544 | ctk_widget_show (box->separator); |
| 545 | } |
| 546 | |
| 547 | box->tracker = ctk_menu_tracker_new_for_item_link (item, G_MENU_LINK_SECTION"section", FALSE(0), FALSE(0), |
| 548 | ctk_menu_section_box_insert_func, |
| 549 | ctk_menu_section_box_remove_func, |
| 550 | box); |
| 551 | |
| 552 | return CTK_WIDGET (box)((((CtkWidget*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((box)), ((ctk_widget_get_type ())))))); |
| 553 | } |