[gtk+/wip/cosimoc/menuitem-gadget: 6/7] menuitem: convert arrow rendering to GtkCssGadget
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/cosimoc/menuitem-gadget: 6/7] menuitem: convert arrow rendering to GtkCssGadget
- Date: Fri, 18 Dec 2015 05:58:30 +0000 (UTC)
commit 77e2ffe1dfc0d610ad16eb449456c934ec7cc703
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Thu Dec 17 21:41:40 2015 -0800
menuitem: convert arrow rendering to GtkCssGadget
This also deprecates the arrow-spacing style property, which can be now
replaced with a simple margin.
gtk/gtkmenuitem.c | 178 ++++++++++++++++++++----------
gtk/gtkmenuitemprivate.h | 1 +
gtk/theme/Adwaita/_common.scss | 10 ++-
gtk/theme/Adwaita/gtk-contained-dark.css | 6 +-
gtk/theme/Adwaita/gtk-contained.css | 6 +-
gtk/theme/HighContrast/_common.scss | 6 +
gtk/theme/HighContrast/gtk.css | 6 +
7 files changed, 149 insertions(+), 64 deletions(-)
---
diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c
index 0d19be6..6a51c12 100644
--- a/gtk/gtkmenuitem.c
+++ b/gtk/gtkmenuitem.c
@@ -27,6 +27,7 @@
#include <string.h>
#include "gtkaccellabel.h"
+#include "gtkcontainerprivate.h"
#include "gtkcsscustomgadgetprivate.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
@@ -276,39 +277,71 @@ gtk_menu_item_actionable_interface_init (GtkActionableInterface *iface)
iface->get_action_target_value = gtk_menu_item_get_action_target_value;
}
+static gboolean
+gtk_menu_item_render_arrow (GtkCssGadget *gadget,
+ cairo_t *cr,
+ int x,
+ int y,
+ int width,
+ int height,
+ gpointer data)
+{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
+ GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
+ GtkMenuItemPrivate *priv = menu_item->priv;
+ GtkStyleContext *context;
+ GtkTextDirection direction;
+ gdouble angle;
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_save_to_node (context, priv->arrow_node);
+ direction = gtk_widget_get_direction (widget);
+
+ if (direction == GTK_TEXT_DIR_LTR)
+ angle = G_PI / 2;
+ else
+ angle = (3 * G_PI) / 2;
+
+ gtk_render_arrow (context, cr, angle, x, y, width);
+
+ gtk_style_context_restore (context);
+
+ return FALSE;
+}
+
static void
-get_arrow_size (GtkWidget *widget,
- GtkWidget *child,
- gint *size,
- gint *spacing)
+gtk_menu_item_measure_arrow (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline,
+ gpointer data)
{
- PangoContext *context;
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
+ PangoContext *context;
PangoFontMetrics *metrics;
- gfloat arrow_scaling;
- gint arrow_spacing;
-
- g_assert (size);
+ gfloat arrow_scaling;
+ gint size;
gtk_widget_style_get (widget,
"arrow-scaling", &arrow_scaling,
- "arrow-spacing", &arrow_spacing,
NULL);
- if (spacing != NULL)
- *spacing = arrow_spacing;
-
- context = gtk_widget_get_pango_context (child);
+ context = gtk_widget_get_pango_context (widget);
metrics = pango_context_get_metrics (context,
pango_context_get_font_description (context),
pango_context_get_language (context));
- *size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
- pango_font_metrics_get_descent (metrics)));
+ size = arrow_scaling *
+ (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
+ pango_font_metrics_get_descent (metrics)));
pango_font_metrics_unref (metrics);
- *size = *size * arrow_scaling;
+ *minimum = *natural = size;
}
static gboolean
@@ -333,32 +366,7 @@ gtk_menu_item_render (GtkCssGadget *gadget,
if (priv->submenu && !GTK_IS_MENU_BAR (parent))
{
- gint arrow_x, arrow_y;
- gint arrow_size;
- GtkTextDirection direction;
- gdouble angle;
-
- gtk_style_context_save_to_node (context, priv->arrow_node);
-
- direction = gtk_widget_get_direction (widget);
- get_arrow_size (widget, child, &arrow_size, NULL);
-
- if (direction == GTK_TEXT_DIR_LTR)
- {
- arrow_x = width - arrow_size;
- angle = G_PI / 2;
- }
- else
- {
- arrow_x = 0;
- angle = (3 * G_PI) / 2;
- }
-
- arrow_y = (height - arrow_size) / 2;
-
- gtk_render_arrow (context, cr, angle, arrow_x, arrow_y, arrow_size);
-
- gtk_style_context_restore (context);
+ gtk_css_gadget_draw (priv->arrow_gadget, cr);
}
else if (!child)
{
@@ -404,6 +412,7 @@ gtk_menu_item_allocate (GtkCssGadget *gadget,
GtkMenuItem *menu_item = GTK_MENU_ITEM (widget);
GtkMenuItemPrivate *priv = menu_item->priv;
GtkAllocation child_allocation;
+ GtkAllocation arrow_clip = { 0 };
GtkTextDirection direction;
GtkPackDirection child_pack_dir;
GtkWidget *child;
@@ -445,19 +454,46 @@ gtk_menu_item_allocate (GtkCssGadget *gadget,
if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
{
- gint arrow_spacing, arrow_size;
+ GtkAllocation arrow_alloc;
+
+ gtk_css_gadget_get_preferred_size (priv->arrow_gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ &arrow_alloc.width, NULL,
+ NULL, NULL);
+ gtk_css_gadget_get_preferred_size (priv->arrow_gadget,
+ GTK_ORIENTATION_VERTICAL,
+ -1,
+ &arrow_alloc.height, NULL,
+ NULL, NULL);
- get_arrow_size (widget, child, &arrow_size, &arrow_spacing);
+ if (direction == GTK_TEXT_DIR_LTR)
+ {
+ arrow_alloc.x = child_allocation.x +
+ child_allocation.width - arrow_alloc.width;
+ }
+ else
+ {
+ arrow_alloc.x = 0;
+ child_allocation.x += arrow_alloc.width;
+ }
+
+ child_allocation.width -= arrow_alloc.width;
+ arrow_alloc.y = child_allocation.y +
+ (child_allocation.height - arrow_alloc.height) / 2;
- if (direction == GTK_TEXT_DIR_RTL)
- child_allocation.x += arrow_size + arrow_spacing;
- child_allocation.width -= arrow_size + arrow_spacing;
+ gtk_css_gadget_allocate (priv->arrow_gadget,
+ &arrow_alloc,
+ baseline,
+ &arrow_clip);
}
- if (child_allocation.width < 1)
- child_allocation.width = 1;
+ child_allocation.width = MAX (1, child_allocation.width);
gtk_widget_size_allocate (child, &child_allocation);
+
+ gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip);
+ gdk_rectangle_union (out_clip, &arrow_clip, out_clip);
}
if (gtk_widget_get_realized (widget))
@@ -529,14 +565,17 @@ gtk_menu_item_real_get_width (GtkWidget *widget,
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
- if ((menu_item->priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
+ if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
{
- gint arrow_spacing, arrow_size;
+ gint arrow_size;
- get_arrow_size (widget, child, &arrow_size, &arrow_spacing);
+ gtk_css_gadget_get_preferred_size (priv->arrow_gadget,
+ GTK_ORIENTATION_HORIZONTAL,
+ -1,
+ &arrow_size, NULL,
+ NULL, NULL);
min_width += arrow_size;
- min_width += arrow_spacing;
nat_width = min_width;
}
@@ -579,14 +618,18 @@ gtk_menu_item_real_get_height (GtkWidget *widget,
if (child != NULL && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
- gint arrow_size = 0, arrow_spacing = 0;
+ gint arrow_size = 0;
if ((priv->submenu && !GTK_IS_MENU_BAR (parent)) || priv->reserve_indicator)
- get_arrow_size (widget, child, &arrow_size, &arrow_spacing);
+ gtk_css_gadget_get_preferred_size (priv->arrow_gadget,
+ GTK_ORIENTATION_VERTICAL,
+ -1,
+ &arrow_size, NULL,
+ NULL, NULL);
if (for_size != -1)
{
- avail_size -= (arrow_size + arrow_spacing);
+ avail_size -= arrow_size;
gtk_widget_get_preferred_height_for_width (child,
avail_size,
&child_min,
@@ -935,6 +978,14 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
5,
GTK_PARAM_READABLE));
+ /**
+ * GtkMenuItem:arrow-spacing:
+ *
+ * Spacing between menu item label and submenu arrow.
+ *
+ * Deprecated: 3.20: use the standard padding CSS property; the value of this
+ * style property is ignored.
+ */
gtk_widget_class_install_style_property (widget_class,
g_param_spec_int ("arrow-spacing",
"Arrow Spacing",
@@ -942,7 +993,7 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
0,
G_MAXINT,
10,
- GTK_PARAM_READABLE));
+ GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
gtk_widget_class_install_style_property (widget_class,
g_param_spec_float ("arrow-scaling",
@@ -1078,6 +1129,7 @@ gtk_menu_item_dispose (GObject *object)
priv->action = NULL;
}
+ g_clear_object (&priv->arrow_gadget);
g_clear_object (&priv->gadget);
G_OBJECT_CLASS (gtk_menu_item_parent_class)->dispose (object);
@@ -1214,6 +1266,8 @@ gtk_menu_item_detacher (GtkWidget *widget,
gtk_css_node_set_parent (priv->arrow_node, NULL);
priv->arrow_node = NULL;
}
+
+ g_clear_object (&priv->arrow_gadget);
}
static void
@@ -1571,6 +1625,14 @@ gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
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);
+ priv->arrow_gadget =
+ gtk_css_custom_gadget_new_for_node (priv->arrow_node,
+ GTK_WIDGET (menu_item),
+ gtk_menu_item_measure_arrow,
+ NULL,
+ gtk_menu_item_render_arrow,
+ NULL, NULL);
+
update_node_classes (menu_item);
g_object_unref (priv->arrow_node);
diff --git a/gtk/gtkmenuitemprivate.h b/gtk/gtkmenuitemprivate.h
index f8069cd..5f3a6da 100644
--- a/gtk/gtkmenuitemprivate.h
+++ b/gtk/gtkmenuitemprivate.h
@@ -42,6 +42,7 @@ struct _GtkMenuItemPrivate
GtkActionHelper *action_helper;
GtkCssGadget *gadget;
+ GtkCssGadget *arrow_gadget;
GtkCssNode *arrow_node;
guint submenu_placement : 1;
diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss
index 1032e3c..a70aa1a 100644
--- a/gtk/theme/Adwaita/_common.scss
+++ b/gtk/theme/Adwaita/_common.scss
@@ -1514,8 +1514,14 @@ menu,
background-color: transparent;
}
//submenu indicators
- & arrow { -gtk-icon-source: -gtk-icontheme('pan-end-symbolic'); }
- & arrow:dir(rtl) {-gtk-icon-source:-gtk-icontheme('pan-end-symbolic-rtl'); }
+ & arrow {
+ -gtk-icon-source: -gtk-icontheme('pan-end-symbolic');
+ margin-left: 10px;
+ }
+ & arrow:dir(rtl) {
+ -gtk-icon-source:-gtk-icontheme('pan-end-symbolic-rtl');
+ margin-right: 10px;
+ }
}
& arrow { // overlow buttons
@extend %undecorated_button;
diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css
index b304fde..839682b 100644
--- a/gtk/theme/Adwaita/gtk-contained-dark.css
+++ b/gtk/theme/Adwaita/gtk-contained-dark.css
@@ -2119,10 +2119,12 @@ menu,
background-color: transparent; }
menu menuitem arrow,
.menu menuitem arrow {
- -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); }
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic");
+ margin-left: 10px; }
menu menuitem arrow:dir(rtl),
.menu menuitem arrow:dir(rtl) {
- -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); }
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl");
+ margin-right: 10px; }
menu arrow,
.menu arrow {
border-style: none;
diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css
index 0902716..db985f4 100644
--- a/gtk/theme/Adwaita/gtk-contained.css
+++ b/gtk/theme/Adwaita/gtk-contained.css
@@ -2125,10 +2125,12 @@ menu,
background-color: transparent; }
menu menuitem arrow,
.menu menuitem arrow {
- -gtk-icon-source: -gtk-icontheme("pan-end-symbolic"); }
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic");
+ margin-left: 10px; }
menu menuitem arrow:dir(rtl),
.menu menuitem arrow:dir(rtl) {
- -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl"); }
+ -gtk-icon-source: -gtk-icontheme("pan-end-symbolic-rtl");
+ margin-right: 10px; }
menu arrow,
.menu arrow {
border-style: none;
diff --git a/gtk/theme/HighContrast/_common.scss b/gtk/theme/HighContrast/_common.scss
index 9e243cb..fa2aece 100644
--- a/gtk/theme/HighContrast/_common.scss
+++ b/gtk/theme/HighContrast/_common.scss
@@ -1176,6 +1176,12 @@ menu,
menuitem {
min-width: 40px;
+ & arrow {
+ margin-left: 10px;
+ }
+ & arrow:dir(rtl) {
+ margin-right: 10px;
+ }
}
}
diff --git a/gtk/theme/HighContrast/gtk.css b/gtk/theme/HighContrast/gtk.css
index 7744f91..10fa379 100644
--- a/gtk/theme/HighContrast/gtk.css
+++ b/gtk/theme/HighContrast/gtk.css
@@ -1304,6 +1304,12 @@ menu,
menu menuitem,
.menu menuitem {
min-width: 40px; }
+ menu menuitem arrow,
+ .menu menuitem arrow {
+ margin-left: 10px; }
+ menu menuitem arrow:dir(rtl),
+ .menu menuitem arrow:dir(rtl) {
+ margin-right: 10px; }
/***************
* Popovers *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]