[gnome-shell] Import MxIcon as StIcon
- From: Owen Taylor <otaylor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] Import MxIcon as StIcon
- Date: Fri, 12 Nov 2010 22:37:22 +0000 (UTC)
commit 839492f15bc583bfb3b6643f4ae6fc1735acfe93
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Sat Oct 30 19:57:59 2010 -0400
Import MxIcon as StIcon
https://bugzilla.gnome.org/show_bug.cgi?id=633865
src/Makefile-st.am | 2 +
src/st/st-icon.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/st/st-icon.h | 95 +++++++++
3 files changed, 650 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile-st.am b/src/Makefile-st.am
index 71db693..b0272ae 100644
--- a/src/Makefile-st.am
+++ b/src/Makefile-st.am
@@ -79,6 +79,7 @@ st_source_h = \
st/st-entry.h \
st/st-focus-manager.h \
st/st-group.h \
+ st/st-icon.h \
st/st-im-text.h \
st/st-label.h \
st/st-overflow-box.h \
@@ -128,6 +129,7 @@ st_source_c = \
st/st-entry.c \
st/st-focus-manager.c \
st/st-group.c \
+ st/st-icon.c \
st/st-im-text.c \
st/st-label.c \
st/st-overflow-box.c \
diff --git a/src/st/st-icon.c b/src/st/st-icon.c
new file mode 100644
index 0000000..7a8192d
--- /dev/null
+++ b/src/st/st-icon.c
@@ -0,0 +1,553 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * st-icon.c: icon widget
+ *
+ * Copyright 2009, 2010 Intel Corporation.
+ *
+ * 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
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by: Thomas Wood <thomas wood intel com>,
+ * Chris Lord <chris linux intel com>
+ *
+ */
+
+/**
+ * SECTION:st-icon
+ * @short_description: a simple styled icon actor
+ *
+ * #StIcon is a simple styled texture actor that displays an image from
+ * a stylesheet.
+ */
+
+#include "st-icon.h"
+#include "st-icon-theme.h"
+#include "st-stylable.h"
+
+#include "st-private.h"
+
+enum
+{
+ PROP_0,
+
+ PROP_ICON_NAME,
+ PROP_ICON_SIZE
+};
+
+static void st_stylable_iface_init (StStylableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (StIcon, st_icon, ST_TYPE_WIDGET,
+ G_IMPLEMENT_INTERFACE (ST_TYPE_STYLABLE,
+ st_stylable_iface_init))
+
+#define ST_ICON_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_ICON, StIconPrivate))
+
+struct _StIconPrivate
+{
+ ClutterActor *icon_texture;
+ gboolean is_content_image;
+
+ gchar *icon_name;
+ gint icon_size;
+};
+
+static void st_icon_update (StIcon *icon);
+
+static void
+st_stylable_iface_init (StStylableIface *iface)
+{
+ static gboolean is_initialized = FALSE;
+
+ if (G_UNLIKELY (!is_initialized))
+ {
+ GParamSpec *pspec;
+
+ is_initialized = TRUE;
+
+ pspec = g_param_spec_boxed ("x-st-content-image",
+ "Content Image",
+ "Image used as the button",
+ ST_TYPE_BORDER_IMAGE,
+ G_PARAM_READWRITE);
+ st_stylable_iface_install_property (iface, ST_TYPE_ICON, pspec);
+
+ pspec = g_param_spec_string ("x-st-icon-name",
+ "Icon name",
+ "Icon name to load from the theme",
+ NULL,
+ G_PARAM_READWRITE);
+ st_stylable_iface_install_property (iface, ST_TYPE_ICON, pspec);
+
+ pspec = g_param_spec_int ("x-st-icon-size",
+ "Icon size",
+ "Size to use for icon",
+ -1, G_MAXINT, -1,
+ G_PARAM_READWRITE);
+ st_stylable_iface_install_property (iface, ST_TYPE_ICON, pspec);
+ }
+}
+
+static void
+st_icon_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ StIcon *icon = ST_ICON (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_ICON_NAME:
+ st_icon_set_icon_name (icon, g_value_get_string (value));
+ break;
+
+ case PROP_ICON_SIZE:
+ st_icon_set_icon_size (icon, g_value_get_int (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+st_icon_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ StIcon *icon = ST_ICON (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_ICON_NAME:
+ g_value_set_string (value, st_icon_get_icon_name (icon));
+ break;
+
+ case PROP_ICON_SIZE:
+ g_value_set_int (value, st_icon_get_icon_size (icon));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+st_icon_notify_theme_name_cb (StIconTheme *theme,
+ GParamSpec *pspec,
+ StIcon *self)
+{
+ st_icon_update (self);
+}
+
+static void
+st_icon_dispose (GObject *gobject)
+{
+ StIconTheme *theme;
+ StIconPrivate *priv = ST_ICON (gobject)->priv;
+
+ if (priv->icon_texture)
+ {
+ clutter_actor_destroy (priv->icon_texture);
+ priv->icon_texture = NULL;
+ }
+
+ if ((theme = st_icon_theme_get_default ()))
+ {
+ g_signal_handlers_disconnect_by_func (st_icon_theme_get_default (),
+ st_icon_notify_theme_name_cb,
+ gobject);
+ }
+
+ G_OBJECT_CLASS (st_icon_parent_class)->dispose (gobject);
+}
+
+static void
+st_icon_get_preferred_height (ClutterActor *actor,
+ gfloat for_width,
+ gfloat *min_height_p,
+ gfloat *nat_height_p)
+{
+ StPadding padding;
+ gfloat pref_height;
+
+ StIconPrivate *priv = ST_ICON (actor)->priv;
+
+ if (priv->icon_texture)
+ {
+ gint width, height;
+ clutter_texture_get_base_size (CLUTTER_TEXTURE (priv->icon_texture),
+ &width,
+ &height);
+
+ if (!priv->is_content_image)
+ {
+ if (width <= height)
+ pref_height = priv->icon_size;
+ else
+ pref_height = height / (gfloat)width * priv->icon_size;
+ }
+ else
+ pref_height = height;
+ }
+ else
+ pref_height = 0;
+
+ st_widget_get_padding (ST_WIDGET (actor), &padding);
+ pref_height += padding.top + padding.bottom;
+
+ if (min_height_p)
+ *min_height_p = pref_height;
+
+ if (nat_height_p)
+ *nat_height_p = pref_height;
+}
+
+static void
+st_icon_get_preferred_width (ClutterActor *actor,
+ gfloat for_height,
+ gfloat *min_width_p,
+ gfloat *nat_width_p)
+{
+ StPadding padding;
+ gfloat pref_width;
+
+ StIconPrivate *priv = ST_ICON (actor)->priv;
+
+ if (priv->icon_texture)
+ {
+ gint width, height;
+ clutter_texture_get_base_size (CLUTTER_TEXTURE (priv->icon_texture),
+ &width,
+ &height);
+
+ if (!priv->is_content_image)
+ {
+ if (height <= width)
+ pref_width = priv->icon_size;
+ else
+ pref_width = width / (gfloat)height * priv->icon_size;
+ }
+ else
+ pref_width = width;
+ }
+ else
+ pref_width = 0;
+
+ st_widget_get_padding (ST_WIDGET (actor), &padding);
+ pref_width += padding.left + padding.right;
+
+ if (min_width_p)
+ *min_width_p = pref_width;
+
+ if (nat_width_p)
+ *nat_width_p = pref_width;
+}
+
+static void
+st_icon_allocate (ClutterActor *actor,
+ const ClutterActorBox *box,
+ ClutterAllocationFlags flags)
+{
+ StIconPrivate *priv = ST_ICON (actor)->priv;
+
+ CLUTTER_ACTOR_CLASS (st_icon_parent_class)->allocate (actor, box, flags);
+
+ if (priv->icon_texture)
+ {
+ StPadding padding;
+ ClutterActorBox child_box;
+
+ st_widget_get_padding (ST_WIDGET (actor), &padding);
+ child_box.x1 = padding.left;
+ child_box.y1 = padding.top;
+ child_box.x2 = box->x2 - box->x1 - padding.right;
+ child_box.y2 = box->y2 - box->y1 - padding.bottom;
+
+ clutter_actor_allocate (priv->icon_texture, &child_box, flags);
+ }
+}
+
+static void
+st_icon_paint (ClutterActor *actor)
+{
+ StIconPrivate *priv = ST_ICON (actor)->priv;
+
+ /* Chain up to paint background */
+ if (!priv->is_content_image)
+ CLUTTER_ACTOR_CLASS (st_icon_parent_class)->paint (actor);
+
+ if (priv->icon_texture)
+ clutter_actor_paint (priv->icon_texture);
+}
+
+static void
+st_icon_map (ClutterActor *actor)
+{
+ StIconPrivate *priv = ST_ICON (actor)->priv;
+
+ CLUTTER_ACTOR_CLASS (st_icon_parent_class)->map (actor);
+
+ if (priv->icon_texture)
+ clutter_actor_map (priv->icon_texture);
+}
+
+static void
+st_icon_unmap (ClutterActor *actor)
+{
+ StIconPrivate *priv = ST_ICON (actor)->priv;
+
+ CLUTTER_ACTOR_CLASS (st_icon_parent_class)->unmap (actor);
+
+ if (priv->icon_texture)
+ clutter_actor_unmap (priv->icon_texture);
+}
+
+static void
+st_icon_class_init (StIconClass *klass)
+{
+ GParamSpec *pspec;
+
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (StIconPrivate));
+
+ object_class->get_property = st_icon_get_property;
+ object_class->set_property = st_icon_set_property;
+ object_class->dispose = st_icon_dispose;
+
+ actor_class->get_preferred_height = st_icon_get_preferred_height;
+ actor_class->get_preferred_width = st_icon_get_preferred_width;
+ actor_class->allocate = st_icon_allocate;
+ actor_class->paint = st_icon_paint;
+ actor_class->map = st_icon_map;
+ actor_class->unmap = st_icon_unmap;
+
+ pspec = g_param_spec_string ("icon-name",
+ "Icon name",
+ "An icon name",
+ NULL, ST_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_ICON_NAME, pspec);
+
+ pspec = g_param_spec_int ("icon-size",
+ "Icon size",
+ "Size of the icon",
+ 1, G_MAXINT, 48,
+ ST_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_ICON_SIZE, pspec);
+}
+
+static void
+st_icon_update (StIcon *icon)
+{
+ StIconPrivate *priv = icon->priv;
+
+ if (priv->is_content_image)
+ {
+ priv->is_content_image = FALSE;
+ g_signal_connect (st_icon_theme_get_default (), "notify::theme-name",
+ G_CALLBACK (st_icon_notify_theme_name_cb), icon);
+ }
+
+ /* Get rid of the old one */
+ if (priv->icon_texture)
+ {
+ clutter_actor_destroy (priv->icon_texture);
+ priv->icon_texture = NULL;
+ }
+
+ /* Try to lookup the new one */
+ if (priv->icon_name)
+ {
+ StIconTheme *theme = st_icon_theme_get_default ();
+ priv->icon_texture = (ClutterActor *)
+ st_icon_theme_lookup_texture (theme, priv->icon_name, priv->icon_size);
+
+ /* If the icon is missing, use the image-missing icon */
+ if (!priv->icon_texture)
+ priv->icon_texture = (ClutterActor *)
+ st_icon_theme_lookup_texture (theme,
+ "image-missing",
+ priv->icon_size);
+
+ if (priv->icon_texture)
+ clutter_actor_set_parent (priv->icon_texture, CLUTTER_ACTOR (icon));
+ }
+
+ clutter_actor_queue_relayout (CLUTTER_ACTOR (icon));
+}
+
+static void
+st_icon_style_changed_cb (StWidget *widget)
+{
+ StIcon *self = ST_ICON (widget);
+ StIconPrivate *priv = self->priv;
+
+ StBorderImage *content_image = NULL;
+ gboolean changed = FALSE;
+ gchar *icon_name = NULL;
+ gint icon_size = -1;
+
+ st_stylable_get (ST_STYLABLE (widget),
+ "x-st-content-image", &content_image,
+ "x-st-icon-name", &icon_name,
+ "x-st-icon-size", &icon_size,
+ NULL);
+
+ /* Content-image overrides drawing of the icon, so
+ * don't bother reading those properties if it's set.
+ */
+ if (content_image)
+ {
+ GError *error = NULL;
+
+ priv->is_content_image = TRUE;
+ g_signal_handlers_disconnect_by_func (st_icon_theme_get_default (),
+ st_icon_notify_theme_name_cb,
+ self);
+
+ if (priv->icon_texture)
+ clutter_actor_destroy (priv->icon_texture);
+
+ priv->icon_texture = clutter_texture_new_from_file (content_image->uri,
+ &error);
+ if (priv->icon_texture)
+ clutter_actor_set_parent (priv->icon_texture, CLUTTER_ACTOR (widget));
+
+ if (error)
+ {
+ g_warning ("Could not load content image: %s", error->message);
+ g_error_free (error);
+ }
+
+ g_boxed_free (ST_TYPE_BORDER_IMAGE, content_image);
+ g_free (icon_name);
+
+ return;
+ }
+
+ if (icon_name && (!priv->icon_name ||
+ !g_str_equal (icon_name, priv->icon_name)))
+ {
+ g_free (priv->icon_name);
+ priv->icon_name = g_strdup (icon_name);
+ changed = TRUE;
+
+ g_object_notify (G_OBJECT (self), "icon-name");
+ }
+
+ if ((icon_size > 0) && (priv->icon_size != icon_size))
+ {
+ priv->icon_size = icon_size;
+ changed = TRUE;
+
+ g_object_notify (G_OBJECT (self), "icon-size");
+ }
+
+ if (changed)
+ st_icon_update (self);
+}
+
+static void
+st_icon_init (StIcon *self)
+{
+ self->priv = ST_ICON_GET_PRIVATE (self);
+
+ self->priv->icon_size = 48;
+
+ g_signal_connect (self, "style-changed",
+ G_CALLBACK (st_icon_style_changed_cb), NULL);
+
+ /* make sure we are not reactive */
+ clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE);
+
+ /* Reload the icon when the theme changes */
+ g_signal_connect (st_icon_theme_get_default (), "notify::theme-name",
+ G_CALLBACK (st_icon_notify_theme_name_cb), self);
+}
+
+/**
+ * st_icon_new:
+ *
+ * Create a newly allocated #StIcon
+ *
+ * Returns: A newly allocated #StIcon
+ */
+ClutterActor *
+st_icon_new (void)
+{
+ return g_object_new (ST_TYPE_ICON, NULL);
+}
+
+
+const gchar *
+st_icon_get_icon_name (StIcon *icon)
+{
+ g_return_val_if_fail (ST_IS_ICON (icon), NULL);
+
+ return icon->priv->icon_name;
+}
+
+void
+st_icon_set_icon_name (StIcon *icon,
+ const gchar *icon_name)
+{
+ StIconPrivate *priv;
+
+ g_return_if_fail (ST_IS_ICON (icon));
+
+ priv = icon->priv;
+
+ /* Check if there's no change */
+ if ((!priv->icon_name && !icon_name) ||
+ (priv->icon_name && icon_name &&
+ g_str_equal (priv->icon_name, icon_name)))
+ return;
+
+ g_free (priv->icon_name);
+ priv->icon_name = g_strdup (icon_name);
+
+ st_icon_update (icon);
+
+ g_object_notify (G_OBJECT (icon), "icon-name");
+}
+
+gint
+st_icon_get_icon_size (StIcon *icon)
+{
+ g_return_val_if_fail (ST_IS_ICON (icon), -1);
+
+ return icon->priv->icon_size;
+}
+void
+st_icon_set_icon_size (StIcon *icon,
+ gint size)
+{
+ StIconPrivate *priv;
+
+ g_return_if_fail (ST_IS_ICON (icon));
+ g_return_if_fail (size > 0);
+
+ priv = icon->priv;
+ if (priv->icon_size != size)
+ {
+ priv->icon_size = size;
+ st_icon_update (icon);
+ g_object_notify (G_OBJECT (icon), "icon-size");
+ }
+}
diff --git a/src/st/st-icon.h b/src/st/st-icon.h
new file mode 100644
index 0000000..4fcde24
--- /dev/null
+++ b/src/st/st-icon.h
@@ -0,0 +1,95 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/*
+ * st-icon.h: icon widget
+ *
+ * Copyright 2009, 2010 Intel Corporation.
+ *
+ * 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
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by: Thomas Wood <thomas wood intel com>
+ *
+ */
+
+#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
+#error "Only <st/st.h> can be included directly.h"
+#endif
+
+#ifndef _ST_ICON
+#define _ST_ICON
+
+#include <glib-object.h>
+#include "st-widget.h"
+
+G_BEGIN_DECLS
+
+#define ST_TYPE_ICON st_icon_get_type()
+
+#define ST_ICON(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_ICON, StIcon))
+
+#define ST_ICON_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_ICON, StIconClass))
+
+#define ST_IS_ICON(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_ICON))
+
+#define ST_IS_ICON_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_ICON))
+
+#define ST_ICON_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_ICON, StIconClass))
+
+typedef struct _StIconPrivate StIconPrivate;
+
+/**
+ * StIcon:
+ *
+ * The contents of this structure are private and should only be accessed
+ * through the public API.
+ */
+typedef struct {
+ /*< private >*/
+ StWidget parent;
+
+ StIconPrivate *priv;
+} StIcon;
+
+typedef struct {
+ StWidgetClass parent_class;
+
+ /* padding for future expansion */
+ void (*_padding_0) (void);
+ void (*_padding_1) (void);
+ void (*_padding_2) (void);
+ void (*_padding_3) (void);
+ void (*_padding_4) (void);
+} StIconClass;
+
+GType st_icon_get_type (void);
+
+ClutterActor* st_icon_new (void);
+
+
+
+const gchar *st_icon_get_icon_name (StIcon *icon);
+void st_icon_set_icon_name (StIcon *icon, const gchar *icon_name);
+
+gint st_icon_get_icon_size (StIcon *icon);
+void st_icon_set_icon_size (StIcon *icon, gint size);
+
+
+G_END_DECLS
+
+#endif /* _ST_ICON */
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]