[gtk+/popover-menu-buttons] Improvements to display-hint handling
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/popover-menu-buttons] Improvements to display-hint handling
- Date: Tue, 22 Apr 2014 11:41:14 +0000 (UTC)
commit 4648e73f60b11000dcf0f96f8e120c687f79a56d
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Apr 22 07:39:26 2014 -0400
Improvements to display-hint handling
Reuse GtkModelButton for the iconic rendering. Once we have that,
we can allow check and radio actions for iconic rendering. Add
tests that show this.
As a further refinement, iconic model buttons will fall back to
showing the label if no icon is set.
gtk/gtkmodelbutton.c | 96 +++++++++++++++++++++++++++++++++++++++-----------
gtk/gtkpopover.c | 33 +++++++----------
tests/popover.ui | 39 ++++++++++++++------
tests/testpopover.c | 9 +++--
4 files changed, 120 insertions(+), 57 deletions(-)
---
diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c
index 0787e04..3a7a738 100644
--- a/gtk/gtkmodelbutton.c
+++ b/gtk/gtkmodelbutton.c
@@ -41,6 +41,7 @@ struct _GtkModelButton
gboolean has_submenu;
gboolean center;
gboolean inverted;
+ gboolean iconic;
GtkMenuTrackerItemRole role;
};
@@ -58,7 +59,8 @@ enum
PROP_ACCEL,
PROP_HAS_SUBMENU,
PROP_INVERTED,
- PROP_CENTERED
+ PROP_CENTERED,
+ PROP_ICONIC
};
static void
@@ -97,20 +99,32 @@ gtk_model_button_set_action_role (GtkModelButton *button,
}
static void
+update_visibility (GtkModelButton *button)
+{
+ gboolean has_icon;
+ gboolean has_text;
+
+ has_icon = gtk_image_get_storage_type (GTK_IMAGE (button->image)) != GTK_IMAGE_EMPTY;
+ has_text = gtk_label_get_text (GTK_LABEL (button->label))[0] != '\0';
+
+ gtk_widget_set_visible (button->image, has_icon);
+ gtk_widget_set_visible (button->label, has_text && (!button->iconic || !has_icon));
+}
+
+static void
gtk_model_button_set_icon (GtkModelButton *button,
GIcon *icon)
{
gtk_image_set_from_gicon (GTK_IMAGE (button->image), icon, GTK_ICON_SIZE_MENU);
- gtk_widget_set_visible (button->image, icon != NULL);
+ update_visibility (button);
}
static void
gtk_model_button_set_text (GtkModelButton *button,
const gchar *text)
{
- if (text != NULL)
- gtk_label_set_text_with_mnemonic (GTK_LABEL (button->label), text);
- gtk_widget_set_visible (button->label, text != NULL);
+ gtk_label_set_text_with_mnemonic (GTK_LABEL (button->label), text);
+ update_visibility (button);
}
static void
@@ -154,6 +168,26 @@ gtk_model_button_set_centered (GtkModelButton *button,
}
static void
+gtk_model_button_set_iconic (GtkModelButton *button,
+ gboolean iconic)
+{
+ button->iconic = iconic;
+ if (iconic)
+ {
+ gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (button)), "modelbutton");
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NORMAL);
+ }
+ else
+ {
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (button)), "modelbutton");
+ gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
+ }
+
+ update_visibility (button);
+ gtk_widget_queue_resize (GTK_WIDGET (button));
+}
+
+static void
gtk_model_button_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -195,6 +229,10 @@ gtk_model_button_set_property (GObject *object,
gtk_model_button_set_centered (button, g_value_get_boolean (value));
break;
+ case PROP_ICONIC:
+ gtk_model_button_set_iconic (button, g_value_get_boolean (value));
+ break;
+
default:
g_assert_not_reached ();
}
@@ -223,7 +261,10 @@ gtk_model_button_get_full_border (GtkModelButton *button,
border->top = border_width + focus_width + focus_pad;
border->bottom = border_width + focus_width + focus_pad;
- *indicator = indicator_size + 2 * indicator_spacing;
+ if (button->iconic)
+ *indicator = 0;
+ else
+ *indicator = indicator_size + 2 * indicator_spacing;
}
static void
@@ -448,12 +489,22 @@ gtk_model_button_draw (GtkWidget *widget,
gint focus_width, focus_pad;
gint baseline;
+ state = get_button_state (model_button);
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, state);
+
+ if (model_button->iconic)
+ {
+ GTK_WIDGET_CLASS (gtk_model_button_parent_class)->draw (widget, cr);
+ goto out;
+ }
+
width = gtk_widget_get_allocated_width (widget);
height = gtk_widget_get_allocated_height (widget);
border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
- context = gtk_widget_get_style_context (widget);
baseline = gtk_widget_get_allocated_baseline (widget);
- state = get_button_state (model_button);
gtk_widget_style_get (widget,
"focus-line-width", &focus_width,
@@ -474,9 +525,6 @@ gtk_model_button_draw (GtkWidget *widget,
y = CLAMP (baseline - indicator_size * button->priv->baseline_align,
0, height - indicator_size);
- gtk_style_context_save (context);
- gtk_style_context_set_state (context, state);
-
gtk_render_background (context, cr,
border_width, border_width,
width - 2 * border_width,
@@ -522,12 +570,13 @@ gtk_model_button_draw (GtkWidget *widget,
height - 2 * (border_width + focus_pad) - border.top - border.bottom);
}
- gtk_style_context_restore (context);
-
child = gtk_bin_get_child (GTK_BIN (widget));
if (child)
gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
+out:
+ gtk_style_context_restore (context);
+
return FALSE;
}
@@ -548,30 +597,34 @@ gtk_model_button_class_init (GtkModelButtonClass *class)
widget_class->draw = gtk_model_button_draw;
g_object_class_install_property (object_class, PROP_ACTION_ROLE,
- g_param_spec_enum ("action-role", "action role", "action role",
+ g_param_spec_enum ("action-role", "", "",
GTK_TYPE_MENU_TRACKER_ITEM_ROLE,
GTK_MENU_TRACKER_ITEM_ROLE_NORMAL,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_ICON,
- g_param_spec_object ("icon", "icon", "icon", G_TYPE_ICON,
+ g_param_spec_object ("icon", "", "", G_TYPE_ICON,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_TEXT,
- g_param_spec_string ("text", "text", "text", NULL,
+ g_param_spec_string ("text", "", "", NULL,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_TOGGLED,
- g_param_spec_boolean ("toggled", "toggled", "toggled", FALSE,
+ g_param_spec_boolean ("toggled", "", "", FALSE,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_ACCEL,
- g_param_spec_string ("accel", "accel", "accel", NULL,
+ g_param_spec_string ("accel", "", "", NULL,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_HAS_SUBMENU,
- g_param_spec_boolean ("has-submenu", "has-submenu", "has-submenu", FALSE,
+ g_param_spec_boolean ("has-submenu", "", "", FALSE,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_INVERTED,
- g_param_spec_boolean ("inverted", "inverted", "inverted", FALSE,
+ g_param_spec_boolean ("inverted", "", "", FALSE,
+
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_CENTERED,
- g_param_spec_boolean ("centered", "centered", "centered", FALSE,
+ g_param_spec_boolean ("centered", "", "", FALSE,
+ G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (object_class, PROP_ICONIC,
+ g_param_spec_boolean ("iconic", "", "", TRUE,
G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
gtk_widget_class_set_accessible_role (GTK_WIDGET_CLASS (class), ATK_ROLE_PUSH_BUTTON);
@@ -595,6 +648,7 @@ gtk_model_button_init (GtkModelButton *button)
gtk_container_add (GTK_CONTAINER (button->box), button->image);
gtk_container_add (GTK_CONTAINER (button->box), button->label);
gtk_container_add (GTK_CONTAINER (button), button->box);
+ gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (button)), "modelbutton");
}
GtkWidget *
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index 82c3880..9a4f458 100644
--- a/gtk/gtkpopover.c
+++ b/gtk/gtkpopover.c
@@ -2095,6 +2095,7 @@ gtk_popover_tracker_insert_func (GtkMenuTrackerItem *item,
{
const gchar *hint;
GtkWidget *icon_box = NULL;
+ GtkWidget *button;
hint = gtk_menu_tracker_item_get_display_hint (item);
if (g_strcmp0 (hint, "iconic") == 0)
@@ -2123,33 +2124,25 @@ gtk_popover_tracker_insert_func (GtkMenuTrackerItem *item,
}
}
+ button = gtk_model_button_new ();
+ g_object_bind_property (item, "label", button, "text", G_BINDING_SYNC_CREATE);
+ g_object_bind_property (item, "icon", button, "icon", G_BINDING_SYNC_CREATE);
+ g_object_bind_property (item, "sensitive", button, "sensitive", G_BINDING_SYNC_CREATE);
+ g_object_bind_property (item, "visible", button, "visible", G_BINDING_SYNC_CREATE);
+ g_object_bind_property (item, "role", button, "action-role", G_BINDING_SYNC_CREATE);
+ g_object_bind_property (item, "toggled", button, "toggled", G_BINDING_SYNC_CREATE);
+ g_object_bind_property (item, "accel", button, "accel", G_BINDING_SYNC_CREATE);
+ g_signal_connect (button, "clicked", G_CALLBACK (gtk_popover_item_activate), item);
if (icon_box)
{
- GtkWidget *button;
-
- if (gtk_menu_tracker_item_get_role (item) != GTK_MENU_TRACKER_ITEM_ROLE_NORMAL)
- g_warning ("Only normal actions supported in icon section");
-
- button = gtk_button_new_from_icon_name ("process-stop-symbolic", GTK_ICON_SIZE_MENU);
- g_object_bind_property (item, "icon", gtk_button_get_image (GTK_BUTTON (button)), "gicon",
G_BINDING_SYNC_CREATE);
- g_object_bind_property (item, "sensitive", button, "sensitive", G_BINDING_SYNC_CREATE);
- g_object_bind_property (item, "visible", button, "visible", G_BINDING_SYNC_CREATE);
- g_signal_connect (button, "clicked", G_CALLBACK (gtk_popover_item_activate), item);
+ g_object_set (button, "iconic", TRUE, "centered", TRUE, NULL);
g_object_set_data_full (G_OBJECT (button), "GtkMenuTrackerItem", g_object_ref (item),
g_object_unref);
+
gtk_box_pack_end (GTK_BOX (icon_box), button, TRUE, TRUE, 0);
}
else
{
- widget = gtk_model_button_new ();
- g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
- g_object_bind_property (item, "icon", widget, "icon", G_BINDING_SYNC_CREATE);
- g_object_bind_property (item, "sensitive", widget, "sensitive", G_BINDING_SYNC_CREATE);
- g_object_bind_property (item, "visible", widget, "visible", G_BINDING_SYNC_CREATE);
- g_object_bind_property (item, "role", widget, "action-role", G_BINDING_SYNC_CREATE);
- g_object_bind_property (item, "toggled", widget, "toggled", G_BINDING_SYNC_CREATE);
- g_object_bind_property (item, "accel", widget, "accel", G_BINDING_SYNC_CREATE);
-
- g_signal_connect (widget, "clicked", G_CALLBACK (gtk_popover_item_activate), item);
+ widget = button;
}
}
g_object_set_data_full (G_OBJECT (widget), "GtkMenuTrackerItem", g_object_ref (item), g_object_unref);
diff --git a/tests/popover.ui b/tests/popover.ui
index 5bc154d..5f0a6c5 100644
--- a/tests/popover.ui
+++ b/tests/popover.ui
@@ -62,6 +62,21 @@
<attribute name="label">Item 5b</attribute>
<attribute name="action">top.action5</attribute>
</item>
+ <section>
+ <attribute name="display-hint">iconic</attribute>
+ <item>
+ <attribute name="label">List</attribute>
+ <attribute name="action">top.set-view</attribute>
+ <attribute name="target">list</attribute>
+ <attribute name="icon">view-list-symbolic</attribute>
+ </item>
+ <item>
+ <attribute name="label">Grid</attribute>
+ <attribute name="action">top.set-view</attribute>
+ <attribute name="target">grid</attribute>
+ <attribute name="icon">view-grid-symbolic</attribute>
+ </item>
+ </section>
<item>
<attribute name="label">Item 5c</attribute>
<attribute name="action">top.action5</attribute>
@@ -73,25 +88,25 @@
</section>
<section>
<attribute name="display-hint">iconic</attribute>
+ <attribute name="label">Edit</attribute>
<item>
- <attribute name="label">Left</attribute>
- <attribute name="action">top.justify-left</attribute>
- <attribute name="icon">format-justify-left-symbolic</attribute>
+ <attribute name="label">Bold</attribute>
+ <attribute name="action">top.bold</attribute>
</item>
<item>
- <attribute name="label">Center</attribute>
- <attribute name="action">top.justify-center</attribute>
- <attribute name="icon">format-justify-center-symbolic</attribute>
+ <attribute name="label">Italic</attribute>
+ <attribute name="action">top.italic</attribute>
+ <attribute name="icon">format-text-italic-symbolic</attribute>
</item>
<item>
- <attribute name="label">Right</attribute>
- <attribute name="action">top.justify-right</attribute>
- <attribute name="icon">format-justify-right-symbolic</attribute>
+ <attribute name="label">Strikethrough</attribute>
+ <attribute name="action">top.strikethrough</attribute>
+ <attribute name="icon">format-text-strikethrough-symbolic</attribute>
</item>
<item>
- <attribute name="label">Fill</attribute>
- <attribute name="action">top.justify-fill</attribute>
- <attribute name="icon">format-justify-fill-symbolic</attribute>
+ <attribute name="label">Underline</attribute>
+ <attribute name="action">top.underline</attribute>
+ <attribute name="icon">format-text-underline-symbolic</attribute>
</item>
</section>
<section>
diff --git a/tests/testpopover.c b/tests/testpopover.c
index b33e042..2f80e31 100644
--- a/tests/testpopover.c
+++ b/tests/testpopover.c
@@ -12,10 +12,11 @@ static GActionEntry entries[] = {
{ "cut", activate, NULL, NULL, NULL },
{ "copy", activate, NULL, NULL, NULL },
{ "paste", activate, NULL, NULL, NULL },
- { "justify-left", activate, NULL, NULL, NULL },
- { "justify-center", activate, NULL, NULL, NULL },
- { "justify-right", activate, NULL, NULL, NULL },
- { "justify-fill", activate, NULL, NULL, NULL },
+ { "bold", NULL, NULL, "false", NULL },
+ { "italic", NULL, NULL, "false", NULL },
+ { "strikethrough", NULL, NULL, "false", NULL },
+ { "underline", NULL, NULL, "false", NULL },
+ { "set-view", NULL, "s", "'list'", NULL },
{ "action1", activate, NULL, NULL, NULL },
{ "action2", NULL, NULL, "true", NULL },
{ "action2a", NULL, NULL, "false", NULL },
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]