diff options
author | Matthias Clasen <mclasen@redhat.com> | 2015-11-02 23:42:14 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2015-11-02 23:42:14 -0500 |
commit | aede5c65d336e288f3054f7ada888031f68b366d (patch) | |
tree | fba14885423ed156731f1624df2738f2f90efed1 /gtk/gtkmenuitem.c | |
parent | ac553d7e44f44e161c204a04ab8480a9b619304c (diff) | |
download | gtk+-aede5c65d336e288f3054f7ada888031f68b366d.tar.gz |
menu item: Use CSS nodes
Use the element name menuitem for GtkMenuItem, GtkCheckMenuItem
and GtkRadioMenuItem. GtkSeparatorMenuItem gets the name separator.
Add a subnode with name arrow if a submenu is attached.
Give the radio and check menu items a subnode with name check or
radio.
Diffstat (limited to 'gtk/gtkmenuitem.c')
-rw-r--r-- | gtk/gtkmenuitem.c | 125 |
1 files changed, 105 insertions, 20 deletions
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c index 600b0eb907..450fb70e5a 100644 --- a/gtk/gtkmenuitem.c +++ b/gtk/gtkmenuitem.c @@ -44,6 +44,8 @@ #include "gtktypebuiltins.h" #include "a11y/gtkmenuitemaccessible.h" #include "deprecated/gtktearoffmenuitem.h" +#include "gtkstylecontextprivate.h" +#include "gtkcssstylepropertyprivate.h" #define MENU_POPUP_DELAY 225 @@ -85,6 +87,12 @@ * </child> * </object> * ]| + * + * # CSS nodes + * + * GtkMenuItem has a single CSS node with name menuitem. If the menuitem + * has a submenu, it gets another CSS node with name arrow, which has + * the .left or .right style class. */ @@ -141,6 +149,8 @@ static gboolean gtk_menu_item_draw (GtkWidget *widget, cairo_t *cr); static void gtk_menu_item_parent_set (GtkWidget *widget, GtkWidget *previous_parent); +static void gtk_menu_item_direction_changed (GtkWidget *widget, + GtkTextDirection previous_dir); static void gtk_real_menu_item_select (GtkMenuItem *item); @@ -162,10 +172,12 @@ static void gtk_menu_item_position_menu (GtkMenu *menu, gboolean *push_in, gpointer user_data); static void gtk_menu_item_show_all (GtkWidget *widget); + static void gtk_menu_item_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); + static gboolean gtk_menu_item_can_activate_accel (GtkWidget *widget, guint signal_id); @@ -299,8 +311,7 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass) widget_class->get_preferred_width = gtk_menu_item_get_preferred_width; widget_class->get_preferred_height = gtk_menu_item_get_preferred_height; widget_class->get_preferred_height_for_width = gtk_menu_item_get_preferred_height_for_width; - - gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_MENU_ITEM_ACCESSIBLE); + widget_class->direction_changed = gtk_menu_item_direction_changed; container_class->forall = gtk_menu_item_forall; @@ -534,12 +545,14 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass) P_("The minimum desired width of the menu item in characters"), 0, G_MAXINT, 12, GTK_PARAM_READABLE)); + + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_MENU_ITEM_ACCESSIBLE); + gtk_widget_class_set_css_name (widget_class, "menuitem"); } static void gtk_menu_item_init (GtkMenuItem *menu_item) { - GtkStyleContext *context; GtkMenuItemPrivate *priv; priv = gtk_menu_item_get_instance_private (menu_item); @@ -562,9 +575,6 @@ gtk_menu_item_init (GtkMenuItem *menu_item) priv->use_action_appearance = TRUE; priv->timer = 0; priv->action = NULL; - - context = gtk_widget_get_style_context (GTK_WIDGET (menu_item)); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_MENUITEM); } /** @@ -762,6 +772,12 @@ gtk_menu_item_detacher (GtkWidget *widget, g_return_if_fail (priv->submenu == (GtkWidget*) menu); priv->submenu = NULL; + + if (priv->arrow_node) + { + gtk_css_node_set_parent (priv->arrow_node, NULL); + priv->arrow_node = NULL; + } } static void @@ -979,9 +995,6 @@ gtk_menu_item_real_get_height (GtkWidget *widget, gboolean wide_separators; gint separator_height; - gtk_style_context_save (context); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_SEPARATOR); - gtk_widget_style_get (widget, "wide-separators", &wide_separators, "separator-height", &separator_height, @@ -1002,8 +1015,6 @@ gtk_menu_item_real_get_height (GtkWidget *widget, if (nat_height % 2 == 0) nat_height += 1; } - - gtk_style_context_restore (context); } accel_width = 0; @@ -1306,6 +1317,59 @@ gtk_menu_item_set_use_action_appearance (GtkMenuItem *menu_item, } } +static void +node_style_changed_cb (GtkCssNode *node, + GtkCssStyle *old_style, + GtkCssStyle *new_style, + GtkWidget *widget) +{ + GtkBitmask *changes; + static GtkBitmask *affects_size = NULL; + + if (G_UNLIKELY (affects_size == NULL)) + affects_size = _gtk_css_style_property_get_mask_affecting (GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_CLIP); + + changes = _gtk_bitmask_new (); + changes = gtk_css_style_add_difference (changes, old_style, new_style); + + if (_gtk_bitmask_intersects (changes, affects_size)) + gtk_widget_queue_resize (widget); + else + gtk_widget_queue_draw (widget); + + _gtk_bitmask_free (changes); +} + +static void +update_node_classes (GtkMenuItem *menu_item) +{ + GtkMenuItemPrivate *priv = menu_item->priv; + GtkCssNode *widget_node, *node; + + if (!priv->arrow_node) + return; + + widget_node = gtk_widget_get_css_node (GTK_WIDGET (menu_item)); + + if (gtk_widget_get_direction (GTK_WIDGET (menu_item)) == GTK_TEXT_DIR_RTL) + { + gtk_css_node_add_class (priv->arrow_node, g_quark_from_static_string (GTK_STYLE_CLASS_LEFT)); + gtk_css_node_remove_class (priv->arrow_node, g_quark_from_static_string (GTK_STYLE_CLASS_RIGHT)); + + node = gtk_css_node_get_first_child (widget_node); + if (node != priv->arrow_node) + gtk_css_node_insert_before (widget_node, priv->arrow_node, node); + } + else + { + gtk_css_node_remove_class (priv->arrow_node, g_quark_from_static_string (GTK_STYLE_CLASS_LEFT)); + gtk_css_node_add_class (priv->arrow_node, g_quark_from_static_string (GTK_STYLE_CLASS_RIGHT)); + + node = gtk_css_node_get_last_child (widget_node); + if (node != priv->arrow_node) + gtk_css_node_insert_after (widget_node, priv->arrow_node, node); + } +} /** * gtk_menu_item_set_submenu: @@ -1335,6 +1399,22 @@ gtk_menu_item_set_submenu (GtkMenuItem *menu_item, gtk_menu_attach_to_widget (GTK_MENU (submenu), GTK_WIDGET (menu_item), gtk_menu_item_detacher); + + if (!GTK_IS_MENU_BAR (gtk_widget_get_parent (GTK_WIDGET (menu_item)))) + { + GtkCssNode *widget_node; + + widget_node = gtk_widget_get_css_node (GTK_WIDGET (menu_item)); + priv->arrow_node = gtk_css_node_new (); + gtk_css_node_set_name (priv->arrow_node, I_("arrow")); + gtk_css_node_set_parent (priv->arrow_node, widget_node); + gtk_css_node_set_state (priv->arrow_node, gtk_css_node_get_state (widget_node)); + g_signal_connect_object (priv->arrow_node, "style-changed", G_CALLBACK (node_style_changed_cb), menu_item, 0); + + update_node_classes (menu_item); + + g_object_unref (priv->arrow_node); + } } if (gtk_widget_get_parent (GTK_WIDGET (menu_item))) @@ -1672,8 +1752,7 @@ gtk_menu_item_draw (GtkWidget *widget, GtkTextDirection direction; gdouble angle; - gtk_style_context_save (context); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_ARROW); + gtk_style_context_save_to_node (context, priv->arrow_node); direction = gtk_widget_get_direction (widget); get_arrow_size (widget, child, &arrow_size, NULL); @@ -1700,12 +1779,9 @@ gtk_menu_item_draw (GtkWidget *widget, gboolean wide_separators; gint separator_height; - gtk_style_context_save (context); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_SEPARATOR); - gtk_widget_style_get (widget, - "wide-separators", &wide_separators, - "separator-height", &separator_height, + "wide-separators", &wide_separators, + "separator-height", &separator_height, NULL); if (wide_separators) gtk_render_frame (context, cr, @@ -1719,8 +1795,6 @@ gtk_menu_item_draw (GtkWidget *widget, y + padding.top, x + w - padding.right - 1, y + padding.top); - - gtk_style_context_restore (context); } GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->draw (widget, cr); @@ -2343,6 +2417,17 @@ gtk_menu_item_parent_set (GtkWidget *widget, GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->parent_set (widget, previous_parent); } +static void +gtk_menu_item_direction_changed (GtkWidget *widget, + GtkTextDirection previous_dir) +{ + GtkMenuItem *menu_item = GTK_MENU_ITEM (widget); + + update_node_classes (menu_item); + + GTK_WIDGET_CLASS (gtk_menu_item_parent_class)->direction_changed (widget, previous_dir); +} + void _gtk_menu_item_refresh_accel_path (GtkMenuItem *menu_item, const gchar *prefix, |