[gnome-shell] st-entry: Add support for a "hint actor"
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] st-entry: Add support for a "hint actor"
- Date: Wed, 14 Jun 2017 22:16:26 +0000 (UTC)
commit 6ed7034a6bb5afa1acb003183eb5bdd1ca1542f6
Author: Mario Sanchez Prada <mario endlessm com>
Date: Mon Jun 5 18:36:41 2017 +0100
st-entry: Add support for a "hint actor"
This allows a full ClutterActor to be used as hint in the entry, instead
of a simple string.
The string case has been now re-implemented on top of the hint actor.
https://bugzilla.gnome.org/show_bug.cgi?id=783484
src/st/st-entry.c | 214 +++++++++++++++++++++++++++++++++++++----------------
src/st/st-entry.h | 4 +
2 files changed, 154 insertions(+), 64 deletions(-)
---
diff --git a/src/st/st-entry.c b/src/st/st-entry.c
index c92991e..fc9ffbf 100644
--- a/src/st/st-entry.c
+++ b/src/st/st-entry.c
@@ -34,7 +34,7 @@
* <para>focus: the widget has focus</para>
* </listitem>
* <listitem>
- * <para>indeterminate: the widget is showing the hint text</para>
+ * <para>indeterminate: the widget is showing the hint text or actor</para>
* </listitem>
* </itemizedlist>
*/
@@ -56,6 +56,7 @@
#include "st-im-text.h"
#include "st-icon.h"
+#include "st-label.h"
#include "st-widget.h"
#include "st-texture-cache.h"
#include "st-clipboard.h"
@@ -75,6 +76,7 @@ enum
PROP_PRIMARY_ICON,
PROP_SECONDARY_ICON,
PROP_HINT_TEXT,
+ PROP_HINT_ACTOR,
PROP_TEXT,
PROP_INPUT_PURPOSE,
PROP_INPUT_HINTS,
@@ -96,14 +98,14 @@ typedef struct _StEntryPrivate StEntryPrivate;
struct _StEntryPrivate
{
ClutterActor *entry;
- gchar *hint;
ClutterActor *primary_icon;
ClutterActor *secondary_icon;
+ ClutterActor *hint_actor;
+
gfloat spacing;
- gboolean hint_visible;
gboolean capslock_warning_shown;
gboolean has_ibeam;
@@ -140,6 +142,10 @@ st_entry_set_property (GObject *gobject,
st_entry_set_hint_text (entry, g_value_get_string (value));
break;
+ case PROP_HINT_ACTOR:
+ st_entry_set_hint_actor (entry, g_value_get_object (value));
+ break;
+
case PROP_TEXT:
st_entry_set_text (entry, g_value_get_string (value));
break;
@@ -181,7 +187,11 @@ st_entry_get_property (GObject *gobject,
break;
case PROP_HINT_TEXT:
- g_value_set_string (value, priv->hint);
+ g_value_set_string (value, st_entry_get_hint_text (ST_ENTRY (gobject)));
+ break;
+
+ case PROP_HINT_ACTOR:
+ g_value_set_object (value, priv->hint_actor);
break;
case PROP_TEXT:
@@ -265,14 +275,21 @@ st_entry_dispose (GObject *object)
}
static void
-st_entry_finalize (GObject *object)
+st_entry_update_hint_visibility (StEntry *self)
{
- StEntryPrivate *priv = ST_ENTRY_PRIV (object);
+ StEntryPrivate *priv = ST_ENTRY_PRIV (self);
+ gboolean hint_visible =
+ priv->hint_actor != NULL &&
+ strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), "") == 0 &&
+ !HAS_FOCUS (priv->entry);
- g_free (priv->hint);
- priv->hint = NULL;
+ if (priv->hint_actor)
+ g_object_set (priv->hint_actor, "visible", hint_visible, NULL);
- G_OBJECT_CLASS (st_entry_parent_class)->finalize (object);
+ if (hint_visible)
+ st_widget_add_style_pseudo_class (ST_WIDGET (self), "indeterminate");
+ else
+ st_widget_remove_style_pseudo_class (ST_WIDGET (self), "indeterminate");
}
static void
@@ -352,7 +369,7 @@ st_entry_get_preferred_width (ClutterActor *actor,
{
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
- gfloat icon_w;
+ gfloat hint_w, icon_w;
st_theme_node_adjust_for_height (theme_node, &for_height);
@@ -360,6 +377,17 @@ st_entry_get_preferred_width (ClutterActor *actor,
min_width_p,
natural_width_p);
+ if (priv->hint_actor)
+ {
+ clutter_actor_get_preferred_width (priv->hint_actor, -1, NULL, &hint_w);
+
+ if (min_width_p && hint_w > *min_width_p)
+ *min_width_p = hint_w;
+
+ if (natural_width_p && hint_w > *natural_width_p)
+ *natural_width_p = hint_w;
+ }
+
if (priv->primary_icon)
{
clutter_actor_get_preferred_width (priv->primary_icon, -1, NULL, &icon_w);
@@ -394,7 +422,7 @@ st_entry_get_preferred_height (ClutterActor *actor,
{
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
- gfloat icon_h;
+ gfloat hint_h, icon_h;
st_theme_node_adjust_for_width (theme_node, &for_width);
@@ -402,6 +430,17 @@ st_entry_get_preferred_height (ClutterActor *actor,
min_height_p,
natural_height_p);
+ if (priv->hint_actor)
+ {
+ clutter_actor_get_preferred_height (priv->hint_actor, -1, NULL, &hint_h);
+
+ if (min_height_p && hint_h > *min_height_p)
+ *min_height_p = hint_h;
+
+ if (natural_height_p && hint_h > *natural_height_p)
+ *natural_height_p = hint_h;
+ }
+
if (priv->primary_icon)
{
clutter_actor_get_preferred_height (priv->primary_icon,
@@ -436,12 +475,16 @@ st_entry_allocate (ClutterActor *actor,
{
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
- ClutterActorBox content_box, child_box, icon_box;
+ ClutterActorBox content_box, child_box, icon_box, hint_box;
gfloat icon_w, icon_h;
+ gfloat hint_w, hint_h;
gfloat entry_h, min_h, pref_h, avail_h;
ClutterActor *left_icon, *right_icon;
+ gboolean is_rtl;
+
+ is_rtl = clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL;
- if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL)
+ if (is_rtl)
{
right_icon = priv->primary_icon;
left_icon = priv->secondary_icon;
@@ -495,6 +538,25 @@ st_entry_allocate (ClutterActor *actor,
child_box.x2 = MAX (child_box.x1, child_box.x2 - icon_w - priv->spacing);
}
+ if (priv->hint_actor)
+ {
+ /* now allocate the hint actor */
+ hint_box = child_box;
+
+ clutter_actor_get_preferred_width (priv->hint_actor, -1, NULL, &hint_w);
+ clutter_actor_get_preferred_height (priv->hint_actor, -1, NULL, &hint_h);
+
+ if (is_rtl)
+ hint_box.x1 = hint_box.x2 - hint_w;
+ else
+ hint_box.x2 = hint_box.x1 + hint_w;
+
+ hint_box.y1 = ceil (content_box.y1 + avail_h / 2 - hint_h / 2);
+ hint_box.y2 = hint_box.y1 + hint_h;
+
+ clutter_actor_allocate (priv->hint_actor, &hint_box, flags);
+ }
+
clutter_actor_get_preferred_height (priv->entry, child_box.x2 - child_box.x1,
&min_h, &pref_h);
@@ -511,23 +573,15 @@ clutter_text_focus_in_cb (ClutterText *text,
ClutterActor *actor)
{
StEntry *entry = ST_ENTRY (actor);
- StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
GdkKeymap *keymap;
- /* remove the hint if visible */
- if (priv->hint && priv->hint_visible)
- {
- priv->hint_visible = FALSE;
-
- clutter_text_set_text (text, "");
- }
+ st_entry_update_hint_visibility (entry);
keymap = gdk_keymap_get_for_display (gdk_display_get_default ());
keymap_state_changed (keymap, entry);
g_signal_connect (keymap, "state-changed",
G_CALLBACK (keymap_state_changed), entry);
- st_widget_remove_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
st_widget_add_style_pseudo_class (ST_WIDGET (actor), "focus");
clutter_text_set_cursor_visible (text, TRUE);
}
@@ -537,19 +591,12 @@ clutter_text_focus_out_cb (ClutterText *text,
ClutterActor *actor)
{
StEntry *entry = ST_ENTRY (actor);
- StEntryPrivate *priv = ST_ENTRY_PRIV (entry);
GdkKeymap *keymap;
st_widget_remove_style_pseudo_class (ST_WIDGET (actor), "focus");
- /* add a hint if the entry is empty */
- if (priv->hint && !strcmp (clutter_text_get_text (text), ""))
- {
- priv->hint_visible = TRUE;
+ st_entry_update_hint_visibility (entry);
- clutter_text_set_text (text, priv->hint);
- st_widget_add_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
- }
clutter_text_set_cursor_visible (text, FALSE);
remove_capslock_feedback (entry);
@@ -870,7 +917,6 @@ st_entry_class_init (StEntryClass *klass)
gobject_class->set_property = st_entry_set_property;
gobject_class->get_property = st_entry_get_property;
- gobject_class->finalize = st_entry_finalize;
gobject_class->dispose = st_entry_dispose;
actor_class->get_preferred_width = st_entry_get_preferred_width;
@@ -917,6 +963,14 @@ st_entry_class_init (StEntryClass *klass)
NULL, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_HINT_TEXT, pspec);
+ pspec = g_param_spec_object ("hint-actor",
+ "Hint Actor",
+ "An actor to display when the entry is not focused "
+ "and the text property is empty",
+ CLUTTER_TYPE_ACTOR,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_HINT_ACTOR, pspec);
+
pspec = g_param_spec_string ("text",
"Text",
"Text of the entry",
@@ -1052,7 +1106,7 @@ st_entry_get_text (StEntry *entry)
g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
priv = st_entry_get_instance_private (entry);
- if (priv->hint_visible)
+ if (clutter_actor_is_visible (priv->hint_actor))
return "";
else
return clutter_text_get_text (CLUTTER_TEXT (priv->entry));
@@ -1075,24 +1129,10 @@ st_entry_set_text (StEntry *entry,
priv = st_entry_get_instance_private (entry);
- /* set a hint if we are blanking the entry */
- if (priv->hint
- && text && !strcmp ("", text)
- && !HAS_FOCUS (priv->entry))
- {
- text = priv->hint;
- priv->hint_visible = TRUE;
- st_widget_add_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
- }
- else
- {
- st_widget_remove_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
-
- priv->hint_visible = FALSE;
- }
-
clutter_text_set_text (CLUTTER_TEXT (priv->entry), text);
+ st_entry_update_hint_visibility (entry);
+
g_object_notify (G_OBJECT (entry), "text");
}
@@ -1126,24 +1166,12 @@ void
st_entry_set_hint_text (StEntry *entry,
const gchar *text)
{
- StEntryPrivate *priv;
+ StWidget *label;
g_return_if_fail (ST_IS_ENTRY (entry));
- priv = st_entry_get_instance_private (entry);
-
- g_free (priv->hint);
-
- priv->hint = g_strdup (text);
-
- if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), "")
- && !HAS_FOCUS (priv->entry))
- {
- priv->hint_visible = TRUE;
-
- clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint);
- st_widget_add_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
- }
+ label = st_label_new (text);
+ st_entry_set_hint_actor (ST_ENTRY (entry), CLUTTER_ACTOR (label));
}
/**
@@ -1158,9 +1186,16 @@ st_entry_set_hint_text (StEntry *entry,
const gchar *
st_entry_get_hint_text (StEntry *entry)
{
+ StEntryPrivate *priv;
+
g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
- return ((StEntryPrivate *)ST_ENTRY_PRIV (entry))->hint;
+ priv = ST_ENTRY_PRIV (entry);
+
+ if (priv->hint_actor != NULL && ST_IS_LABEL (priv->hint_actor))
+ return st_label_get_text (ST_LABEL (priv->hint_actor));
+
+ return NULL;
}
/**
@@ -1370,6 +1405,57 @@ st_entry_get_secondary_icon (StEntry *entry)
return priv->secondary_icon;
}
+/**
+ * st_entry_set_hint_actor:
+ * @entry: a #StEntry
+ * @hint_actor: (allow-none): a #ClutterActor
+ *
+ * Set the hint actor of the entry to @hint_actor
+ */
+void
+st_entry_set_hint_actor (StEntry *entry,
+ ClutterActor *hint_actor)
+{
+ StEntryPrivate *priv;
+
+ g_return_if_fail (ST_IS_ENTRY (entry));
+
+ priv = ST_ENTRY_PRIV (entry);
+
+ if (priv->hint_actor != NULL)
+ {
+ clutter_actor_remove_child (CLUTTER_ACTOR (entry), priv->hint_actor);
+ priv->hint_actor = NULL;
+ }
+
+ if (hint_actor != NULL)
+ {
+ priv->hint_actor = hint_actor;
+ clutter_actor_add_child (CLUTTER_ACTOR (entry), priv->hint_actor);
+ }
+
+ st_entry_update_hint_visibility (entry);
+
+ clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
+}
+
+/**
+ * st_entry_get_hint_actor:
+ * @entry: a #StEntry
+ *
+ * Returns: (transfer none): a #ClutterActor
+ */
+ClutterActor *
+st_entry_get_hint_actor (StEntry *entry)
+{
+ StEntryPrivate *priv;
+
+ g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
+
+ priv = ST_ENTRY_PRIV (entry);
+ return priv->hint_actor;
+}
+
/******************************************************************************/
/*************************** ACCESSIBILITY SUPPORT ****************************/
/******************************************************************************/
diff --git a/src/st/st-entry.h b/src/st/st-entry.h
index 1fbc556..43ae0fa 100644
--- a/src/st/st-entry.h
+++ b/src/st/st-entry.h
@@ -65,6 +65,10 @@ void st_entry_set_secondary_icon (StEntry *entry,
ClutterActor *icon);
ClutterActor * st_entry_get_secondary_icon (StEntry *entry);
+void st_entry_set_hint_actor (StEntry *entry,
+ ClutterActor *hint_actor);
+ClutterActor * st_entry_get_hint_actor (StEntry *entry);
+
typedef void (*StEntryCursorFunc) (StEntry *entry, gboolean use_ibeam, gpointer data);
void st_entry_set_cursor_func (StEntryCursorFunc func,
gpointer user_data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]