summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastien Lafargue <slafargue@gnome.org>2014-10-18 11:19:26 +0200
committerMatthias Clasen <mclasen@redhat.com>2014-10-27 07:08:37 -0400
commit17f9eed14e6aa36cc10fd56b221fb544ad809b1f (patch)
tree9aa899eebc51ebb123f85071db9552d3af32b0f3
parentfc6f22c3ce0e628d955e23c131d0b16b2939b2eb (diff)
downloadgtk+-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.c75
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,