diff options
author | Sebastien Lafargue <slafargue@gnome.org> | 2014-10-18 11:19:26 +0200 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2014-10-27 07:08:37 -0400 |
commit | 17f9eed14e6aa36cc10fd56b221fb544ad809b1f (patch) | |
tree | 9aa899eebc51ebb123f85071db9552d3af32b0f3 | |
parent | fc6f22c3ce0e628d955e23c131d0b16b2939b2eb (diff) | |
download | gtk+-17f9eed14e6aa36cc10fd56b221fb544ad809b1f.tar.gz |
popover menus: Take iconic into account
We don't want separators in both side of an iconic section
and use a 10px margin to separate two iconic sections.
Separators are also updated in case of dynamic insertion
( often used with menu items for plugins )
https://bugzilla.gnome.org/show_bug.cgi?id=738650
-rw-r--r-- | gtk/gtkmenusectionbox.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/gtk/gtkmenusectionbox.c b/gtk/gtkmenusectionbox.c index be6a8c6c22..8256aea97e 100644 --- a/gtk/gtkmenusectionbox.c +++ b/gtk/gtkmenusectionbox.c @@ -48,10 +48,16 @@ struct _GtkMenuSectionBox gint depth; }; +typedef struct +{ + gint n_items; + gboolean previous_is_iconic; +} MenuData; + G_DEFINE_TYPE (GtkMenuSectionBox, gtk_menu_section_box, GTK_TYPE_BOX) void gtk_menu_section_box_sync_separators (GtkMenuSectionBox *box, - gint *n_items); + MenuData *data); void gtk_menu_section_box_new_submenu (GtkMenuTrackerItem *item, GtkMenuSectionBox *toplevel, GtkWidget *focus); @@ -62,12 +68,12 @@ static void gtk_menu_section_box_sync_item (GtkWidget *widget, gpointer user_data) { - gint *n_items = user_data; + MenuData *data = (MenuData *)user_data; if (GTK_IS_MENU_SECTION_BOX (widget)) - gtk_menu_section_box_sync_separators (GTK_MENU_SECTION_BOX (widget), n_items); + gtk_menu_section_box_sync_separators (GTK_MENU_SECTION_BOX (widget), data); else - (*n_items)++; + data->n_items++; } /* We are trying to implement the following rules here: @@ -77,26 +83,32 @@ gtk_menu_section_box_sync_item (GtkWidget *widget, * rule 3: don't show a separator for the first section * rule 4: don't show a separator for the following sections if there are * no items before it - * (rule 5: these rules don't apply exactly the same way for subsections) + * rule 5: never show separators directly above or below an iconic box + * (rule 6: these rules don't apply exactly the same way for subsections) */ void gtk_menu_section_box_sync_separators (GtkMenuSectionBox *box, - gint *n_items) + MenuData *data) { + GtkWidget *parent_widget; + gboolean previous_section_is_iconic; gboolean should_have_separator; + gboolean should_have_top_margin = FALSE; + gboolean is_not_empty_item; gboolean has_separator; gboolean has_label; - gint n_items_before = *n_items; + gboolean separator_condition; + gint n_items_before; - gtk_container_foreach (GTK_CONTAINER (box->item_box), gtk_menu_section_box_sync_item, n_items); + n_items_before = data->n_items; + previous_section_is_iconic = data->previous_is_iconic; - if (box->iconic) - { - if (n_items_before > 0) - gtk_widget_set_margin_top (GTK_WIDGET (box->item_box), 10); - else - gtk_widget_set_margin_top (GTK_WIDGET (box->item_box), 0); - } + gtk_container_foreach (GTK_CONTAINER (box->item_box), gtk_menu_section_box_sync_item, data); + + is_not_empty_item = (data->n_items > n_items_before); + + if (is_not_empty_item) + data->previous_is_iconic = box->iconic; if (box->separator == NULL) return; @@ -104,7 +116,19 @@ gtk_menu_section_box_sync_separators (GtkMenuSectionBox *box, has_separator = gtk_widget_get_parent (box->separator) != NULL; has_label = !GTK_IS_SEPARATOR (box->separator); - should_have_separator = (has_label || (n_items_before > 0 && box->depth <= 1)) && *n_items > n_items_before; + separator_condition = has_label ? TRUE : n_items_before > 0 && + box->depth <= 1 && + !previous_section_is_iconic && + !box->iconic; + + should_have_separator = separator_condition && is_not_empty_item; + + should_have_top_margin = !should_have_separator && + (box->depth <= 1 || box->iconic) && + n_items_before > 0 && + is_not_empty_item; + + gtk_widget_set_margin_top (GTK_WIDGET (box->item_box), should_have_top_margin ? 10 : 0); if (should_have_separator == has_separator) return; @@ -119,9 +143,11 @@ static gboolean gtk_menu_section_box_handle_sync_separators (gpointer user_data) { GtkMenuSectionBox *box = user_data; - gint n_items = 0; + MenuData data; - gtk_menu_section_box_sync_separators (box, &n_items); + data.n_items = 0; + data.previous_is_iconic = FALSE; + gtk_menu_section_box_sync_separators (box, &data); box->separator_sync_idle = 0; @@ -328,11 +354,7 @@ gtk_menu_section_box_dispose (GObject *object) box->separator_sync_idle = 0; } - if (box->separator) - { - gtk_widget_destroy (box->separator); - box->separator = NULL; - } + g_clear_object (&box->separator); if (box->tracker) { @@ -436,7 +458,10 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item, g_object_bind_property (item, "label", title, "label", G_BINDING_SYNC_CREATE); gtk_style_context_add_class (gtk_widget_get_style_context (title), GTK_STYLE_CLASS_SEPARATOR); gtk_widget_set_halign (title, GTK_ALIGN_START); + box->separator = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + g_object_ref_sink (box->separator); + g_object_set (box->separator, "margin-start", 12, "margin-end", 12, @@ -450,6 +475,8 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item, else { box->separator = separator; + g_object_ref_sink (box->separator); + g_object_set (box->separator, "margin-start", 12, "margin-end", 12, @@ -459,8 +486,6 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item, gtk_widget_show (box->separator); } - g_object_add_weak_pointer (G_OBJECT (box->separator), (gpointer *)&(box->separator)); - box->tracker = gtk_menu_tracker_new_for_item_link (item, G_MENU_LINK_SECTION, FALSE, gtk_menu_section_box_insert_func, gtk_menu_section_box_remove_func, |