2009-09-29 19:08:01 +00:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
2009-09-10 08:39:27 +00:00
|
|
|
/*
|
|
|
|
* st-entry.c: Plain entry actor
|
|
|
|
*
|
|
|
|
* Copyright 2008, 2009 Intel Corporation
|
2010-11-10 22:00:45 +00:00
|
|
|
* Copyright 2009, 2010 Red Hat, Inc.
|
|
|
|
* Copyright 2010 Florian Müllner
|
2009-09-10 08:39:27 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU Lesser General Public License,
|
|
|
|
* version 2.1, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
|
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public License
|
2010-11-10 22:00:45 +00:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2009-09-10 08:39:27 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* SECTION:st-entry
|
|
|
|
* @short_description: Widget for displaying text
|
|
|
|
*
|
|
|
|
* #StEntry is a simple widget for displaying text. It derives from
|
|
|
|
* #StWidget to add extra style and placement functionality over
|
|
|
|
* #ClutterText. The internal #ClutterText is publicly accessibly to allow
|
|
|
|
* applications to set further properties.
|
|
|
|
*
|
|
|
|
* #StEntry supports the following pseudo style states:
|
|
|
|
* <itemizedlist>
|
|
|
|
* <listitem>
|
|
|
|
* <para>focus: the widget has focus</para>
|
|
|
|
* </listitem>
|
|
|
|
* <listitem>
|
|
|
|
* <para>indeterminate: the widget is showing the hint text</para>
|
|
|
|
* </listitem>
|
2010-02-27 19:51:15 +00:00
|
|
|
* <listitem>
|
|
|
|
* <para>hover: the widget is showing the hint text and is underneath the
|
|
|
|
* pointer</para>
|
|
|
|
* </listitem>
|
2009-09-10 08:39:27 +00:00
|
|
|
* </itemizedlist>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include <clutter/clutter.h>
|
|
|
|
|
|
|
|
#include "st-entry.h"
|
|
|
|
|
2009-10-05 20:33:19 +00:00
|
|
|
#include "st-im-text.h"
|
2009-09-10 08:39:27 +00:00
|
|
|
#include "st-widget.h"
|
|
|
|
#include "st-texture-cache.h"
|
|
|
|
#include "st-marshal.h"
|
|
|
|
#include "st-clipboard.h"
|
2010-06-10 12:15:02 +00:00
|
|
|
#include "st-private.h"
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
#define HAS_FOCUS(actor) (clutter_actor_get_stage (actor) && clutter_stage_get_key_focus ((ClutterStage *) clutter_actor_get_stage (actor)) == actor)
|
|
|
|
|
|
|
|
|
|
|
|
/* properties */
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
|
2009-09-21 23:22:31 +00:00
|
|
|
PROP_CLUTTER_TEXT,
|
|
|
|
PROP_HINT_TEXT,
|
|
|
|
PROP_TEXT,
|
2009-09-10 08:39:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* signals */
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PRIMARY_ICON_CLICKED,
|
|
|
|
SECONDARY_ICON_CLICKED,
|
|
|
|
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
#define ST_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_ENTRY, StEntryPrivate))
|
|
|
|
#define ST_ENTRY_PRIV(x) ((StEntry *) x)->priv
|
|
|
|
|
|
|
|
|
|
|
|
struct _StEntryPrivate
|
|
|
|
{
|
|
|
|
ClutterActor *entry;
|
|
|
|
gchar *hint;
|
|
|
|
|
|
|
|
ClutterActor *primary_icon;
|
|
|
|
ClutterActor *secondary_icon;
|
|
|
|
|
|
|
|
gfloat spacing;
|
2009-10-20 13:22:17 +00:00
|
|
|
|
|
|
|
gboolean hint_visible;
|
2009-09-10 08:39:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static guint entry_signals[LAST_SIGNAL] = { 0, };
|
|
|
|
|
2009-09-20 01:10:15 +00:00
|
|
|
G_DEFINE_TYPE (StEntry, st_entry, ST_TYPE_WIDGET);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_set_property (GObject *gobject,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
StEntry *entry = ST_ENTRY (gobject);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
2009-09-21 23:22:31 +00:00
|
|
|
case PROP_HINT_TEXT:
|
|
|
|
st_entry_set_hint_text (entry, g_value_get_string (value));
|
2009-09-10 08:39:27 +00:00
|
|
|
break;
|
|
|
|
|
2009-09-21 23:22:31 +00:00
|
|
|
case PROP_TEXT:
|
|
|
|
st_entry_set_text (entry, g_value_get_string (value));
|
2009-09-10 08:39:27 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_get_property (GObject *gobject,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (gobject);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
2009-09-21 23:22:31 +00:00
|
|
|
case PROP_CLUTTER_TEXT:
|
|
|
|
g_value_set_object (value, priv->entry);
|
2009-09-10 08:39:27 +00:00
|
|
|
break;
|
|
|
|
|
2009-09-21 23:22:31 +00:00
|
|
|
case PROP_HINT_TEXT:
|
2009-09-10 08:39:27 +00:00
|
|
|
g_value_set_string (value, priv->hint);
|
2009-09-21 23:22:31 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_TEXT:
|
|
|
|
g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->entry)));
|
|
|
|
break;
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (object);
|
|
|
|
|
|
|
|
if (priv->entry)
|
|
|
|
{
|
2009-10-08 18:53:46 +00:00
|
|
|
clutter_actor_destroy (priv->entry);
|
2009-09-10 08:39:27 +00:00
|
|
|
priv->entry = NULL;
|
|
|
|
}
|
2010-03-10 23:22:06 +00:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (st_entry_parent_class)->dispose (object);
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (object);
|
|
|
|
|
|
|
|
g_free (priv->hint);
|
|
|
|
priv->hint = NULL;
|
2010-03-10 23:22:06 +00:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (st_entry_parent_class)->finalize (object);
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_style_changed (StWidget *self)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (self);
|
2009-09-20 01:10:15 +00:00
|
|
|
StThemeNode *theme_node;
|
|
|
|
ClutterColor color;
|
|
|
|
const PangoFontDescription *font;
|
2009-09-10 08:39:27 +00:00
|
|
|
gchar *font_string;
|
2010-02-27 22:19:24 +00:00
|
|
|
gdouble size;
|
2009-09-10 08:39:27 +00:00
|
|
|
|
2009-09-20 01:10:15 +00:00
|
|
|
theme_node = st_widget_get_theme_node (self);
|
|
|
|
|
|
|
|
st_theme_node_get_foreground_color (theme_node, &color);
|
|
|
|
clutter_text_set_color (CLUTTER_TEXT (priv->entry), &color);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
StThemeNode: simplify use of get_color/get_double/get_length
Although within St itself there are situations where the semantics of
these functions (return TRUE or FALSE and return the actual value in
an out parameter) is useful, it's mostly just annoying at the
application level, where you generally know that the CSS property is
going to specified, and there is no especially sane fallback if it's
not.
So rename the current methods to lookup_color, lookup_double, and
lookup_length, and add new get_color, get_double, and get_length
methods that don't take an "inherit" parameter, and return their
values directly. (Well, except for get_color, due to the lack of (out
caller-allocates) in gjs.)
And update the code to use either the old or new methods as appropriate.
https://bugzilla.gnome.org/show_bug.cgi?id=632590
2010-09-26 21:38:36 +00:00
|
|
|
if (st_theme_node_lookup_length (theme_node, "caret-size", FALSE, &size))
|
2010-02-27 22:19:24 +00:00
|
|
|
clutter_text_set_cursor_size (CLUTTER_TEXT (priv->entry), (int)(.5 + size));
|
|
|
|
|
StThemeNode: simplify use of get_color/get_double/get_length
Although within St itself there are situations where the semantics of
these functions (return TRUE or FALSE and return the actual value in
an out parameter) is useful, it's mostly just annoying at the
application level, where you generally know that the CSS property is
going to specified, and there is no especially sane fallback if it's
not.
So rename the current methods to lookup_color, lookup_double, and
lookup_length, and add new get_color, get_double, and get_length
methods that don't take an "inherit" parameter, and return their
values directly. (Well, except for get_color, due to the lack of (out
caller-allocates) in gjs.)
And update the code to use either the old or new methods as appropriate.
https://bugzilla.gnome.org/show_bug.cgi?id=632590
2010-09-26 21:38:36 +00:00
|
|
|
if (st_theme_node_lookup_color (theme_node, "caret-color", FALSE, &color))
|
2009-09-20 01:10:15 +00:00
|
|
|
clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), &color);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
StThemeNode: simplify use of get_color/get_double/get_length
Although within St itself there are situations where the semantics of
these functions (return TRUE or FALSE and return the actual value in
an out parameter) is useful, it's mostly just annoying at the
application level, where you generally know that the CSS property is
going to specified, and there is no especially sane fallback if it's
not.
So rename the current methods to lookup_color, lookup_double, and
lookup_length, and add new get_color, get_double, and get_length
methods that don't take an "inherit" parameter, and return their
values directly. (Well, except for get_color, due to the lack of (out
caller-allocates) in gjs.)
And update the code to use either the old or new methods as appropriate.
https://bugzilla.gnome.org/show_bug.cgi?id=632590
2010-09-26 21:38:36 +00:00
|
|
|
if (st_theme_node_lookup_color (theme_node, "selection-background-color", FALSE, &color))
|
2009-09-20 01:10:15 +00:00
|
|
|
clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry), &color);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
2009-09-20 01:10:15 +00:00
|
|
|
font = st_theme_node_get_font (theme_node);
|
|
|
|
font_string = pango_font_description_to_string (font);
|
|
|
|
clutter_text_set_font_name (CLUTTER_TEXT (priv->entry), font_string);
|
|
|
|
g_free (font_string);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
2009-09-20 01:10:15 +00:00
|
|
|
ST_WIDGET_CLASS (st_entry_parent_class)->style_changed (self);
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
|
2010-06-15 16:11:39 +00:00
|
|
|
static gboolean
|
|
|
|
st_entry_navigate_focus (StWidget *widget,
|
|
|
|
ClutterActor *from,
|
|
|
|
GtkDirectionType direction)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (widget);
|
|
|
|
|
|
|
|
/* This is basically the same as st_widget_real_navigate_focus(),
|
|
|
|
* except that widget is behaving as a proxy for priv->entry (which
|
|
|
|
* isn't an StWidget and so has no can-focus flag of its own).
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (from == priv->entry)
|
|
|
|
return FALSE;
|
|
|
|
else if (st_widget_get_can_focus (widget))
|
|
|
|
{
|
|
|
|
clutter_actor_grab_key_focus (priv->entry);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2009-09-10 08:39:27 +00:00
|
|
|
static void
|
|
|
|
st_entry_get_preferred_width (ClutterActor *actor,
|
|
|
|
gfloat for_height,
|
|
|
|
gfloat *min_width_p,
|
|
|
|
gfloat *natural_width_p)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
2009-09-20 17:41:13 +00:00
|
|
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
|
2009-09-10 08:39:27 +00:00
|
|
|
gfloat icon_w;
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
st_theme_node_adjust_for_height (theme_node, &for_height);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
clutter_actor_get_preferred_width (priv->entry, for_height,
|
|
|
|
min_width_p,
|
|
|
|
natural_width_p);
|
|
|
|
|
|
|
|
if (priv->primary_icon)
|
|
|
|
{
|
|
|
|
clutter_actor_get_preferred_width (priv->primary_icon, -1, NULL, &icon_w);
|
|
|
|
|
|
|
|
if (min_width_p)
|
|
|
|
*min_width_p += icon_w + priv->spacing;
|
|
|
|
|
|
|
|
if (natural_width_p)
|
|
|
|
*natural_width_p += icon_w + priv->spacing;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->secondary_icon)
|
|
|
|
{
|
|
|
|
clutter_actor_get_preferred_width (priv->secondary_icon,
|
|
|
|
-1, NULL, &icon_w);
|
|
|
|
|
|
|
|
if (min_width_p)
|
|
|
|
*min_width_p += icon_w + priv->spacing;
|
|
|
|
|
|
|
|
if (natural_width_p)
|
|
|
|
*natural_width_p += icon_w + priv->spacing;
|
|
|
|
}
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_get_preferred_height (ClutterActor *actor,
|
|
|
|
gfloat for_width,
|
|
|
|
gfloat *min_height_p,
|
|
|
|
gfloat *natural_height_p)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
2009-09-20 17:41:13 +00:00
|
|
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
|
2009-09-10 08:39:27 +00:00
|
|
|
gfloat icon_h;
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
st_theme_node_adjust_for_width (theme_node, &for_width);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
clutter_actor_get_preferred_height (priv->entry, for_width,
|
|
|
|
min_height_p,
|
|
|
|
natural_height_p);
|
|
|
|
|
|
|
|
if (priv->primary_icon)
|
|
|
|
{
|
|
|
|
clutter_actor_get_preferred_height (priv->primary_icon,
|
|
|
|
-1, NULL, &icon_h);
|
|
|
|
|
|
|
|
if (min_height_p && icon_h > *min_height_p)
|
|
|
|
*min_height_p = icon_h;
|
|
|
|
|
|
|
|
if (natural_height_p && icon_h > *natural_height_p)
|
|
|
|
*natural_height_p = icon_h;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->secondary_icon)
|
|
|
|
{
|
|
|
|
clutter_actor_get_preferred_height (priv->secondary_icon,
|
|
|
|
-1, NULL, &icon_h);
|
|
|
|
|
|
|
|
if (min_height_p && icon_h > *min_height_p)
|
|
|
|
*min_height_p = icon_h;
|
|
|
|
|
|
|
|
if (natural_height_p && icon_h > *natural_height_p)
|
|
|
|
*natural_height_p = icon_h;
|
|
|
|
}
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_allocate (ClutterActor *actor,
|
|
|
|
const ClutterActorBox *box,
|
|
|
|
ClutterAllocationFlags flags)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
2009-09-20 17:41:13 +00:00
|
|
|
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
|
2009-09-10 08:39:27 +00:00
|
|
|
ClutterActorClass *parent_class;
|
2009-09-20 17:41:13 +00:00
|
|
|
ClutterActorBox content_box, child_box, icon_box;
|
2009-09-10 08:39:27 +00:00
|
|
|
gfloat icon_w, icon_h;
|
|
|
|
gfloat entry_h, min_h, pref_h, avail_h;
|
|
|
|
|
|
|
|
parent_class = CLUTTER_ACTOR_CLASS (st_entry_parent_class);
|
|
|
|
parent_class->allocate (actor, box, flags);
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
st_theme_node_get_content_box (theme_node, box, &content_box);
|
|
|
|
|
|
|
|
avail_h = content_box.y2 - content_box.y1;
|
2009-09-10 08:39:27 +00:00
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
child_box.x1 = content_box.x1;
|
|
|
|
child_box.x2 = content_box.x2;
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
if (priv->primary_icon)
|
|
|
|
{
|
|
|
|
clutter_actor_get_preferred_width (priv->primary_icon,
|
|
|
|
-1, NULL, &icon_w);
|
|
|
|
clutter_actor_get_preferred_height (priv->primary_icon,
|
|
|
|
-1, NULL, &icon_h);
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
icon_box.x1 = content_box.x1;
|
2009-09-10 08:39:27 +00:00
|
|
|
icon_box.x2 = icon_box.x1 + icon_w;
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2);
|
2009-09-10 08:39:27 +00:00
|
|
|
icon_box.y2 = icon_box.y1 + icon_h;
|
|
|
|
|
|
|
|
clutter_actor_allocate (priv->primary_icon,
|
|
|
|
&icon_box,
|
|
|
|
flags);
|
|
|
|
|
|
|
|
/* reduce the size for the entry */
|
|
|
|
child_box.x1 += icon_w + priv->spacing;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->secondary_icon)
|
|
|
|
{
|
|
|
|
clutter_actor_get_preferred_width (priv->secondary_icon,
|
|
|
|
-1, NULL, &icon_w);
|
|
|
|
clutter_actor_get_preferred_height (priv->secondary_icon,
|
|
|
|
-1, NULL, &icon_h);
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
icon_box.x2 = content_box.x2;
|
2009-09-10 08:39:27 +00:00
|
|
|
icon_box.x1 = icon_box.x2 - icon_w;
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2);
|
2009-09-10 08:39:27 +00:00
|
|
|
icon_box.y2 = icon_box.y1 + icon_h;
|
|
|
|
|
|
|
|
clutter_actor_allocate (priv->secondary_icon,
|
|
|
|
&icon_box,
|
|
|
|
flags);
|
|
|
|
|
|
|
|
/* reduce the size for the entry */
|
|
|
|
child_box.x2 -= icon_w - priv->spacing;
|
|
|
|
}
|
|
|
|
|
|
|
|
clutter_actor_get_preferred_height (priv->entry, child_box.x2 - child_box.x1,
|
|
|
|
&min_h, &pref_h);
|
|
|
|
|
|
|
|
entry_h = CLAMP (pref_h, min_h, avail_h);
|
|
|
|
|
2009-09-20 17:41:13 +00:00
|
|
|
child_box.y1 = (int) (content_box.y1 + avail_h / 2 - entry_h / 2);
|
2009-09-10 08:39:27 +00:00
|
|
|
child_box.y2 = child_box.y1 + entry_h;
|
|
|
|
|
|
|
|
clutter_actor_allocate (priv->entry, &child_box, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
clutter_text_focus_in_cb (ClutterText *text,
|
|
|
|
ClutterActor *actor)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
|
|
|
|
|
|
|
/* remove the hint if visible */
|
2009-10-20 13:22:17 +00:00
|
|
|
if (priv->hint && priv->hint_visible)
|
2009-09-10 08:39:27 +00:00
|
|
|
{
|
2009-10-20 13:22:17 +00:00
|
|
|
priv->hint_visible = FALSE;
|
|
|
|
|
2009-09-10 08:39:27 +00:00
|
|
|
clutter_text_set_text (text, "");
|
|
|
|
}
|
2010-03-19 15:37:04 +00:00
|
|
|
st_widget_remove_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
|
|
|
|
st_widget_add_style_pseudo_class (ST_WIDGET (actor), "focus");
|
2009-09-10 08:39:27 +00:00
|
|
|
clutter_text_set_cursor_visible (text, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
clutter_text_focus_out_cb (ClutterText *text,
|
|
|
|
ClutterActor *actor)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
|
|
|
|
2010-03-19 15:37:04 +00:00
|
|
|
st_widget_remove_style_pseudo_class (ST_WIDGET (actor), "focus");
|
|
|
|
|
2009-09-10 08:39:27 +00:00
|
|
|
/* add a hint if the entry is empty */
|
|
|
|
if (priv->hint && !strcmp (clutter_text_get_text (text), ""))
|
|
|
|
{
|
2009-10-20 13:22:17 +00:00
|
|
|
priv->hint_visible = TRUE;
|
|
|
|
|
2009-09-10 08:39:27 +00:00
|
|
|
clutter_text_set_text (text, priv->hint);
|
2010-03-19 15:37:04 +00:00
|
|
|
st_widget_add_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
clutter_text_set_cursor_visible (text, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_paint (ClutterActor *actor)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
|
|
|
ClutterActorClass *parent_class;
|
|
|
|
|
|
|
|
parent_class = CLUTTER_ACTOR_CLASS (st_entry_parent_class);
|
|
|
|
parent_class->paint (actor);
|
|
|
|
|
|
|
|
clutter_actor_paint (priv->entry);
|
|
|
|
|
|
|
|
if (priv->primary_icon)
|
|
|
|
clutter_actor_paint (priv->primary_icon);
|
|
|
|
|
|
|
|
if (priv->secondary_icon)
|
|
|
|
clutter_actor_paint (priv->secondary_icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_pick (ClutterActor *actor,
|
|
|
|
const ClutterColor *c)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
|
|
|
|
|
|
|
CLUTTER_ACTOR_CLASS (st_entry_parent_class)->pick (actor, c);
|
|
|
|
|
|
|
|
clutter_actor_paint (priv->entry);
|
|
|
|
|
|
|
|
if (priv->primary_icon)
|
|
|
|
clutter_actor_paint (priv->primary_icon);
|
|
|
|
|
|
|
|
if (priv->secondary_icon)
|
|
|
|
clutter_actor_paint (priv->secondary_icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_map (ClutterActor *actor)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY (actor)->priv;
|
|
|
|
|
|
|
|
CLUTTER_ACTOR_CLASS (st_entry_parent_class)->map (actor);
|
|
|
|
|
|
|
|
clutter_actor_map (priv->entry);
|
|
|
|
|
|
|
|
if (priv->primary_icon)
|
|
|
|
clutter_actor_map (priv->primary_icon);
|
|
|
|
|
|
|
|
if (priv->secondary_icon)
|
|
|
|
clutter_actor_map (priv->secondary_icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_unmap (ClutterActor *actor)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY (actor)->priv;
|
|
|
|
|
|
|
|
CLUTTER_ACTOR_CLASS (st_entry_parent_class)->unmap (actor);
|
|
|
|
|
|
|
|
clutter_actor_unmap (priv->entry);
|
|
|
|
|
|
|
|
if (priv->primary_icon)
|
|
|
|
clutter_actor_unmap (priv->primary_icon);
|
|
|
|
|
|
|
|
if (priv->secondary_icon)
|
|
|
|
clutter_actor_unmap (priv->secondary_icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_clipboard_callback (StClipboard *clipboard,
|
|
|
|
const gchar *text,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
ClutterText *ctext = (ClutterText*)((StEntry *) data)->priv->entry;
|
|
|
|
gint cursor_pos;
|
|
|
|
|
|
|
|
if (!text)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* delete the current selection before pasting */
|
|
|
|
clutter_text_delete_selection (ctext);
|
|
|
|
|
|
|
|
/* "paste" the clipboard text into the entry */
|
|
|
|
cursor_pos = clutter_text_get_cursor_position (ctext);
|
|
|
|
clutter_text_insert_text (ctext, text, cursor_pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
st_entry_key_press_event (ClutterActor *actor,
|
|
|
|
ClutterKeyEvent *event)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
|
|
|
|
|
|
|
/* This is expected to handle events that were emitted for the inner
|
|
|
|
ClutterText. They only reach this function if the ClutterText
|
|
|
|
didn't handle them */
|
|
|
|
|
|
|
|
/* paste */
|
|
|
|
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
|
|
|
|
&& event->keyval == CLUTTER_v)
|
|
|
|
{
|
|
|
|
StClipboard *clipboard;
|
|
|
|
|
|
|
|
clipboard = st_clipboard_get_default ();
|
|
|
|
|
|
|
|
st_clipboard_get_text (clipboard, st_entry_clipboard_callback, actor);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy */
|
|
|
|
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
|
|
|
|
&& event->keyval == CLUTTER_c)
|
|
|
|
{
|
|
|
|
StClipboard *clipboard;
|
|
|
|
gchar *text;
|
|
|
|
|
|
|
|
clipboard = st_clipboard_get_default ();
|
|
|
|
|
|
|
|
text = clutter_text_get_selection ((ClutterText*) priv->entry);
|
|
|
|
|
|
|
|
if (text && strlen (text))
|
|
|
|
st_clipboard_set_text (clipboard, text);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* cut */
|
|
|
|
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
|
|
|
|
&& event->keyval == CLUTTER_x)
|
|
|
|
{
|
|
|
|
StClipboard *clipboard;
|
|
|
|
gchar *text;
|
|
|
|
|
|
|
|
clipboard = st_clipboard_get_default ();
|
|
|
|
|
|
|
|
text = clutter_text_get_selection ((ClutterText*) priv->entry);
|
|
|
|
|
|
|
|
if (text && strlen (text))
|
|
|
|
{
|
|
|
|
st_clipboard_set_text (clipboard, text);
|
|
|
|
|
|
|
|
/* now delete the text */
|
|
|
|
clutter_text_delete_selection ((ClutterText *) priv->entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_key_focus_in (ClutterActor *actor)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
|
|
|
|
|
|
|
/* We never want key focus. The ClutterText should be given first
|
|
|
|
pass for all key events */
|
|
|
|
clutter_actor_grab_key_focus (priv->entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_class_init (StEntryClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
2009-09-20 01:10:15 +00:00
|
|
|
StWidgetClass *widget_class = ST_WIDGET_CLASS (klass);
|
2009-09-10 08:39:27 +00:00
|
|
|
GParamSpec *pspec;
|
|
|
|
|
|
|
|
g_type_class_add_private (klass, sizeof (StEntryPrivate));
|
|
|
|
|
|
|
|
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;
|
|
|
|
actor_class->get_preferred_height = st_entry_get_preferred_height;
|
|
|
|
actor_class->allocate = st_entry_allocate;
|
|
|
|
actor_class->paint = st_entry_paint;
|
|
|
|
actor_class->pick = st_entry_pick;
|
|
|
|
actor_class->map = st_entry_map;
|
|
|
|
actor_class->unmap = st_entry_unmap;
|
|
|
|
|
|
|
|
actor_class->key_press_event = st_entry_key_press_event;
|
|
|
|
actor_class->key_focus_in = st_entry_key_focus_in;
|
|
|
|
|
2009-09-20 01:10:15 +00:00
|
|
|
widget_class->style_changed = st_entry_style_changed;
|
2010-06-15 16:11:39 +00:00
|
|
|
widget_class->navigate_focus = st_entry_navigate_focus;
|
2009-09-20 01:10:15 +00:00
|
|
|
|
2009-09-21 23:22:31 +00:00
|
|
|
pspec = g_param_spec_object ("clutter-text",
|
|
|
|
"Clutter Text",
|
|
|
|
"Internal ClutterText actor",
|
|
|
|
CLUTTER_TYPE_TEXT,
|
|
|
|
G_PARAM_READABLE);
|
|
|
|
g_object_class_install_property (gobject_class, PROP_CLUTTER_TEXT, pspec);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
pspec = g_param_spec_string ("hint-text",
|
|
|
|
"Hint Text",
|
|
|
|
"Text to display when the entry is not focused "
|
|
|
|
"and the text property is empty",
|
|
|
|
NULL, G_PARAM_READWRITE);
|
2009-09-21 23:22:31 +00:00
|
|
|
g_object_class_install_property (gobject_class, PROP_HINT_TEXT, pspec);
|
|
|
|
|
|
|
|
pspec = g_param_spec_string ("text",
|
|
|
|
"Text",
|
|
|
|
"Text of the entry",
|
|
|
|
NULL, G_PARAM_READWRITE);
|
|
|
|
g_object_class_install_property (gobject_class, PROP_TEXT, pspec);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
/* signals */
|
|
|
|
/**
|
|
|
|
* StEntry::primary-icon-clicked:
|
|
|
|
*
|
|
|
|
* Emitted when the primary icon is clicked
|
|
|
|
*/
|
|
|
|
entry_signals[PRIMARY_ICON_CLICKED] =
|
|
|
|
g_signal_new ("primary-icon-clicked",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
G_STRUCT_OFFSET (StEntryClass, primary_icon_clicked),
|
|
|
|
NULL, NULL,
|
|
|
|
_st_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
/**
|
|
|
|
* StEntry::secondary-icon-clicked:
|
|
|
|
*
|
|
|
|
* Emitted when the secondary icon is clicked
|
|
|
|
*/
|
|
|
|
entry_signals[SECONDARY_ICON_CLICKED] =
|
|
|
|
g_signal_new ("secondary-icon-clicked",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
G_STRUCT_OFFSET (StEntryClass, secondary_icon_clicked),
|
|
|
|
NULL, NULL,
|
|
|
|
_st_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_entry_init (StEntry *entry)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv;
|
|
|
|
|
|
|
|
priv = entry->priv = ST_ENTRY_GET_PRIVATE (entry);
|
|
|
|
|
2009-10-05 20:33:19 +00:00
|
|
|
priv->entry = g_object_new (ST_TYPE_IM_TEXT,
|
2009-09-10 08:39:27 +00:00
|
|
|
"line-alignment", PANGO_ALIGN_LEFT,
|
|
|
|
"editable", TRUE,
|
|
|
|
"reactive", TRUE,
|
|
|
|
"single-line-mode", TRUE,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
g_signal_connect (priv->entry, "key-focus-in",
|
|
|
|
G_CALLBACK (clutter_text_focus_in_cb), entry);
|
|
|
|
|
|
|
|
g_signal_connect (priv->entry, "key-focus-out",
|
|
|
|
G_CALLBACK (clutter_text_focus_out_cb), entry);
|
|
|
|
|
|
|
|
priv->spacing = 6.0f;
|
|
|
|
|
|
|
|
clutter_actor_set_parent (priv->entry, CLUTTER_ACTOR (entry));
|
|
|
|
clutter_actor_set_reactive ((ClutterActor *) entry, TRUE);
|
|
|
|
|
|
|
|
/* set cursor hidden until we receive focus */
|
|
|
|
clutter_text_set_cursor_visible ((ClutterText *) priv->entry, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_new:
|
|
|
|
* @text: text to set the entry to
|
|
|
|
*
|
|
|
|
* Create a new #StEntry with the specified entry
|
|
|
|
*
|
|
|
|
* Returns: a new #StEntry
|
|
|
|
*/
|
|
|
|
StWidget *
|
|
|
|
st_entry_new (const gchar *text)
|
|
|
|
{
|
|
|
|
StWidget *entry;
|
|
|
|
|
|
|
|
/* add the entry to the stage, but don't allow it to be visible */
|
|
|
|
entry = g_object_new (ST_TYPE_ENTRY,
|
|
|
|
"text", text,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_get_text:
|
|
|
|
* @entry: a #StEntry
|
|
|
|
*
|
|
|
|
* Get the text displayed on the entry
|
|
|
|
*
|
|
|
|
* Returns: the text for the entry. This must not be freed by the application
|
|
|
|
*/
|
|
|
|
G_CONST_RETURN gchar *
|
|
|
|
st_entry_get_text (StEntry *entry)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
|
|
|
|
|
2009-10-20 13:22:17 +00:00
|
|
|
if (entry->priv->hint_visible)
|
|
|
|
return "";
|
|
|
|
else
|
|
|
|
return clutter_text_get_text (CLUTTER_TEXT (entry->priv->entry));
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_set_text:
|
|
|
|
* @entry: a #StEntry
|
2010-02-27 14:46:41 +00:00
|
|
|
* @text: (allow-none): text to set the entry to
|
2009-09-10 08:39:27 +00:00
|
|
|
*
|
|
|
|
* Sets the text displayed on the entry
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
st_entry_set_text (StEntry *entry,
|
|
|
|
const gchar *text)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv;
|
|
|
|
|
|
|
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
|
|
|
|
|
|
|
priv = entry->priv;
|
|
|
|
|
|
|
|
/* set a hint if we are blanking the entry */
|
|
|
|
if (priv->hint
|
|
|
|
&& text && !strcmp ("", text)
|
|
|
|
&& !HAS_FOCUS (priv->entry))
|
|
|
|
{
|
|
|
|
text = priv->hint;
|
2009-10-20 13:22:17 +00:00
|
|
|
priv->hint_visible = TRUE;
|
2010-03-19 15:37:04 +00:00
|
|
|
st_widget_add_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-19 15:37:04 +00:00
|
|
|
st_widget_remove_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
|
2009-10-20 13:22:17 +00:00
|
|
|
|
|
|
|
priv->hint_visible = FALSE;
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
clutter_text_set_text (CLUTTER_TEXT (priv->entry), text);
|
|
|
|
|
|
|
|
g_object_notify (G_OBJECT (entry), "text");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_get_clutter_text:
|
|
|
|
* @entry: a #StEntry
|
|
|
|
*
|
|
|
|
* Retrieve the internal #ClutterText so that extra parameters can be set
|
|
|
|
*
|
2009-09-21 23:22:31 +00:00
|
|
|
* Returns: (transfer none): the #ClutterText used by #StEntry. The entry is
|
2009-09-16 23:07:23 +00:00
|
|
|
* owned by the #StEntry and should not be unref'ed by the application.
|
2009-09-10 08:39:27 +00:00
|
|
|
*/
|
|
|
|
ClutterActor*
|
|
|
|
st_entry_get_clutter_text (StEntry *entry)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (ST_ENTRY (entry), NULL);
|
|
|
|
|
|
|
|
return entry->priv->entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_set_hint_text:
|
|
|
|
* @entry: a #StEntry
|
2010-02-27 14:46:41 +00:00
|
|
|
* @text: (allow-none): text to set as the entry hint
|
2009-09-10 08:39:27 +00:00
|
|
|
*
|
|
|
|
* Sets the text to display when the entry is empty and unfocused. When the
|
|
|
|
* entry is displaying the hint, it has a pseudo class of "indeterminate".
|
|
|
|
* A value of NULL unsets the hint.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
st_entry_set_hint_text (StEntry *entry,
|
|
|
|
const gchar *text)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv;
|
|
|
|
|
|
|
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
|
|
|
|
|
|
|
priv = entry->priv;
|
|
|
|
|
|
|
|
g_free (priv->hint);
|
|
|
|
|
|
|
|
priv->hint = g_strdup (text);
|
|
|
|
|
2009-10-20 13:22:17 +00:00
|
|
|
if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), "")
|
|
|
|
&& !HAS_FOCUS (priv->entry))
|
2009-09-10 08:39:27 +00:00
|
|
|
{
|
2009-10-20 13:22:17 +00:00
|
|
|
priv->hint_visible = TRUE;
|
|
|
|
|
2009-09-10 08:39:27 +00:00
|
|
|
clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint);
|
2010-03-19 15:37:04 +00:00
|
|
|
st_widget_add_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
|
2009-09-10 08:39:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_get_hint_text:
|
|
|
|
* @entry: a #StEntry
|
|
|
|
*
|
|
|
|
* Gets the text that is displayed when the entry is empty and unfocused
|
|
|
|
*
|
|
|
|
* Returns: the current value of the hint property. This string is owned by the
|
|
|
|
* #StEntry and should not be freed or modified.
|
|
|
|
*/
|
|
|
|
G_CONST_RETURN
|
|
|
|
gchar *
|
|
|
|
st_entry_get_hint_text (StEntry *entry)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (ST_IS_ENTRY (entry), NULL);
|
|
|
|
|
|
|
|
return entry->priv->hint;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
_st_entry_icon_press_cb (ClutterActor *actor,
|
|
|
|
ClutterButtonEvent *event,
|
|
|
|
StEntry *entry)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv = entry->priv;
|
|
|
|
|
|
|
|
if (actor == priv->primary_icon)
|
|
|
|
g_signal_emit (entry, entry_signals[PRIMARY_ICON_CLICKED], 0);
|
|
|
|
else
|
|
|
|
g_signal_emit (entry, entry_signals[SECONDARY_ICON_CLICKED], 0);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-02-10 18:40:01 +00:00
|
|
|
_st_entry_set_icon (StEntry *entry,
|
|
|
|
ClutterActor **icon,
|
|
|
|
ClutterActor *new_icon)
|
2009-09-10 08:39:27 +00:00
|
|
|
{
|
|
|
|
if (*icon)
|
|
|
|
{
|
|
|
|
g_signal_handlers_disconnect_by_func (*icon,
|
|
|
|
_st_entry_icon_press_cb,
|
|
|
|
entry);
|
|
|
|
clutter_actor_unparent (*icon);
|
|
|
|
*icon = NULL;
|
|
|
|
}
|
|
|
|
|
2011-02-10 18:40:01 +00:00
|
|
|
if (new_icon)
|
2009-09-10 08:39:27 +00:00
|
|
|
{
|
2011-02-10 18:40:01 +00:00
|
|
|
*icon = g_object_ref (new_icon);
|
2009-09-10 08:39:27 +00:00
|
|
|
|
|
|
|
clutter_actor_set_reactive (*icon, TRUE);
|
|
|
|
clutter_actor_set_parent (*icon, CLUTTER_ACTOR (entry));
|
|
|
|
g_signal_connect (*icon, "button-release-event",
|
|
|
|
G_CALLBACK (_st_entry_icon_press_cb), entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
|
|
|
|
}
|
|
|
|
|
2011-02-10 18:40:01 +00:00
|
|
|
static void
|
|
|
|
_st_entry_set_icon_from_file (StEntry *entry,
|
|
|
|
ClutterActor **icon,
|
|
|
|
const gchar *filename)
|
|
|
|
{
|
|
|
|
ClutterActor *new_icon = NULL;
|
|
|
|
|
|
|
|
if (filename)
|
|
|
|
{
|
|
|
|
StTextureCache *cache;
|
|
|
|
|
|
|
|
cache = st_texture_cache_get_default ();
|
|
|
|
|
|
|
|
new_icon = (ClutterActor*) st_texture_cache_load_file_simple (cache, filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
_st_entry_set_icon (entry, icon, new_icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_set_primary_icon:
|
|
|
|
* @entry: a #StEntry
|
|
|
|
* @icon: (allow-none): a #ClutterActor
|
|
|
|
*
|
|
|
|
* Set the primary icon of the entry to @icon
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
st_entry_set_primary_icon (StEntry *entry,
|
|
|
|
ClutterActor *icon)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv;
|
|
|
|
|
|
|
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
|
|
|
|
|
|
|
priv = entry->priv;
|
|
|
|
|
|
|
|
_st_entry_set_icon (entry, &priv->primary_icon, icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_set_secondary_icon:
|
|
|
|
* @entry: a #StEntry
|
|
|
|
* @icon: (allow-none): an #ClutterActor
|
|
|
|
*
|
|
|
|
* Set the secondary icon of the entry to @icon
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
st_entry_set_secondary_icon (StEntry *entry,
|
|
|
|
ClutterActor *icon)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv;
|
|
|
|
|
|
|
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
|
|
|
|
|
|
|
priv = entry->priv;
|
|
|
|
|
|
|
|
_st_entry_set_icon (entry, &priv->secondary_icon, icon);
|
|
|
|
}
|
|
|
|
|
2009-09-10 08:39:27 +00:00
|
|
|
/**
|
|
|
|
* st_entry_set_primary_icon_from_file:
|
|
|
|
* @entry: a #StEntry
|
2010-02-27 14:46:41 +00:00
|
|
|
* @filename: (allow-none): filename of an icon
|
2009-09-10 08:39:27 +00:00
|
|
|
*
|
|
|
|
* Set the primary icon of the entry to the given filename
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
st_entry_set_primary_icon_from_file (StEntry *entry,
|
|
|
|
const gchar *filename)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv;
|
|
|
|
|
|
|
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
|
|
|
|
|
|
|
priv = entry->priv;
|
|
|
|
|
|
|
|
_st_entry_set_icon_from_file (entry, &priv->primary_icon, filename);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* st_entry_set_secondary_icon_from_file:
|
|
|
|
* @entry: a #StEntry
|
2010-02-27 14:46:41 +00:00
|
|
|
* @filename: (allow-none): filename of an icon
|
2009-09-10 08:39:27 +00:00
|
|
|
*
|
|
|
|
* Set the primary icon of the entry to the given filename
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
st_entry_set_secondary_icon_from_file (StEntry *entry,
|
|
|
|
const gchar *filename)
|
|
|
|
{
|
|
|
|
StEntryPrivate *priv;
|
|
|
|
|
|
|
|
g_return_if_fail (ST_IS_ENTRY (entry));
|
|
|
|
|
|
|
|
priv = entry->priv;
|
|
|
|
|
|
|
|
_st_entry_set_icon_from_file (entry, &priv->secondary_icon, filename);
|
|
|
|
|
|
|
|
}
|
|
|
|
|