[gnome-shell/nbtk-introduction: 8/8] Import NbtkEntry, NbtkLabel, NbtkClipboard
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-shell/nbtk-introduction: 8/8] Import NbtkEntry, NbtkLabel, NbtkClipboard
- Date: Wed, 16 Sep 2009 22:08:22 +0000 (UTC)
commit c60a6a49de9f7676c52e323c48fda33aeb969593
Author: Colin Walters <walters verbum org>
Date: Thu Sep 10 04:39:27 2009 -0400
Import NbtkEntry, NbtkLabel, NbtkClipboard
For now this commit introduces an external dependency on clutter-imcontext.
https://bugzilla.gnome.org/show_bug.cgi?id=591245
configure.ac | 2 +-
src/Makefile-nbtk.am | 6 +
src/nbtk/nbtk-clipboard.c | 367 +++++++++++++++
src/nbtk/nbtk-clipboard.h | 94 ++++
src/nbtk/nbtk-entry.c | 960 +++++++++++++++++++++++++++++++++++++++
src/nbtk/nbtk-entry.h | 88 ++++
src/nbtk/nbtk-label.c | 363 +++++++++++++++
src/nbtk/nbtk-label.h | 75 +++
tools/build/gnome-shell.modules | 9 +
9 files changed, 1963 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index edb9603..b65b117 100644
--- a/configure.ac
+++ b/configure.ac
@@ -57,7 +57,7 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
gobject-introspection-1.0 >= 0.6.5)
PKG_CHECK_MODULES(TIDY, clutter-1.0)
-PKG_CHECK_MODULES(NBTK, clutter-1.0 gtk+-2.0 libccss-1 >= 0.3.1)
+PKG_CHECK_MODULES(NBTK, clutter-1.0 gtk+-2.0 libccss-1 >= 0.3.1 clutter-imcontext-0.1)
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
diff --git a/src/Makefile-nbtk.am b/src/Makefile-nbtk.am
index b9b6a7d..d08e0b5 100644
--- a/src/Makefile-nbtk.am
+++ b/src/Makefile-nbtk.am
@@ -69,6 +69,9 @@ nbtk_source_h = \
nbtk/nbtk-box-layout.h \
nbtk/nbtk-box-layout-child.h \
nbtk/nbtk-button.h \
+ nbtk/nbtk-clipboard.h \
+ nbtk/nbtk-entry.h \
+ nbtk/nbtk-label.h \
nbtk/nbtk-private.h \
nbtk/nbtk-scrollable.h \
nbtk/nbtk-scroll-bar.h \
@@ -91,6 +94,9 @@ nbtk_source_c = \
nbtk/nbtk-box-layout.c \
nbtk/nbtk-box-layout-child.c \
nbtk/nbtk-button.c \
+ nbtk/nbtk-clipboard.c \
+ nbtk/nbtk-entry.c \
+ nbtk/nbtk-label.c \
nbtk/nbtk-private.c \
nbtk/nbtk-scrollable.c \
nbtk/nbtk-scroll-bar.c \
diff --git a/src/nbtk/nbtk-clipboard.c b/src/nbtk/nbtk-clipboard.c
new file mode 100644
index 0000000..f103372
--- /dev/null
+++ b/src/nbtk/nbtk-clipboard.c
@@ -0,0 +1,367 @@
+/*
+ * nbtk-clipboard.c: clipboard object
+ *
+ * Copyright 2009 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>
+ *
+ */
+
+
+#include "nbtk-clipboard.h"
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <clutter/x11/clutter-x11.h>
+#include <string.h>
+
+G_DEFINE_TYPE (NbtkClipboard, nbtk_clipboard, G_TYPE_OBJECT)
+
+#define CLIPBOARD_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_CLIPBOARD, NbtkClipboardPrivate))
+
+struct _NbtkClipboardPrivate
+{
+ Window clipboard_window;
+ gchar *clipboard_text;
+
+ Atom *supported_targets;
+ gint n_targets;
+};
+
+typedef struct _EventFilterData EventFilterData;
+struct _EventFilterData
+{
+ NbtkClipboard *clipboard;
+ NbtkClipboardCallbackFunc callback;
+ gpointer user_data;
+};
+
+static Atom __atom_clip = None;
+static Atom __utf8_string = None;
+static Atom __atom_targets = None;
+
+static void
+nbtk_clipboard_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+nbtk_clipboard_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ switch (property_id)
+ {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+}
+
+static void
+nbtk_clipboard_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (nbtk_clipboard_parent_class)->dispose (object);
+}
+
+static void
+nbtk_clipboard_finalize (GObject *object)
+{
+ NbtkClipboardPrivate *priv = ((NbtkClipboard *) object)->priv;
+
+ g_free (priv->clipboard_text);
+ priv->clipboard_text = NULL;
+
+ g_free (priv->supported_targets);
+ priv->supported_targets = NULL;
+ priv->n_targets = 0;
+
+ G_OBJECT_CLASS (nbtk_clipboard_parent_class)->finalize (object);
+}
+
+static ClutterX11FilterReturn
+nbtk_clipboard_provider (XEvent *xev,
+ ClutterEvent *cev,
+ NbtkClipboard *clipboard)
+{
+ XSelectionEvent notify_event;
+ XSelectionRequestEvent *req_event;
+
+ if (xev->type != SelectionRequest)
+ return CLUTTER_X11_FILTER_CONTINUE;
+
+ req_event = &xev->xselectionrequest;
+
+ clutter_x11_trap_x_errors ();
+
+ if (req_event->target == __atom_targets)
+ {
+ XChangeProperty (req_event->display,
+ req_event->requestor,
+ req_event->property,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ (guchar*) clipboard->priv->supported_targets,
+ clipboard->priv->n_targets);
+ }
+ else
+ {
+ XChangeProperty (req_event->display,
+ req_event->requestor,
+ req_event->property,
+ req_event->target,
+ 8,
+ PropModeReplace,
+ (guchar*) clipboard->priv->clipboard_text,
+ strlen (clipboard->priv->clipboard_text));
+ }
+
+ notify_event.type = SelectionNotify;
+ notify_event.display = req_event->display;
+ notify_event.requestor = req_event->requestor;
+ notify_event.selection = req_event->selection;
+ notify_event.target = req_event->target;
+ notify_event.time = req_event->time;
+
+ if (req_event->property == None)
+ notify_event.property = req_event->target;
+ else
+ notify_event.property = req_event->property;
+
+ /* notify the requestor that they have a copy of the selection */
+ XSendEvent (req_event->display, req_event->requestor, False, 0,
+ (XEvent *) ¬ify_event);
+ /* Make it happen non async */
+ XSync (clutter_x11_get_default_display(), FALSE);
+
+ clutter_x11_untrap_x_errors (); /* FIXME: Warn here on fail ? */
+
+ return CLUTTER_X11_FILTER_REMOVE;
+}
+
+
+static void
+nbtk_clipboard_class_init (NbtkClipboardClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (NbtkClipboardPrivate));
+
+ object_class->get_property = nbtk_clipboard_get_property;
+ object_class->set_property = nbtk_clipboard_set_property;
+ object_class->dispose = nbtk_clipboard_dispose;
+ object_class->finalize = nbtk_clipboard_finalize;
+}
+
+static void
+nbtk_clipboard_init (NbtkClipboard *self)
+{
+ Display *dpy;
+ NbtkClipboardPrivate *priv;
+
+ priv = self->priv = CLIPBOARD_PRIVATE (self);
+
+ priv->clipboard_window =
+ XCreateSimpleWindow (clutter_x11_get_default_display (),
+ clutter_x11_get_root_window (),
+ -1, -1, 1, 1, 0, 0, 0);
+
+ dpy = clutter_x11_get_default_display ();
+
+ /* Only create once */
+ if (__atom_clip == None)
+ __atom_clip = XInternAtom (dpy, "CLIPBOARD", 0);
+
+ if (__utf8_string == None)
+ __utf8_string = XInternAtom (dpy, "UTF8_STRING", 0);
+
+ if (__atom_targets == None)
+ __atom_targets = XInternAtom (dpy, "TARGETS", 0);
+
+ priv->n_targets = 2;
+ priv->supported_targets = g_new (Atom, priv->n_targets);
+
+ priv->supported_targets[0] = __utf8_string;
+ priv->supported_targets[1] = __atom_targets;
+
+ clutter_x11_add_filter ((ClutterX11FilterFunc) nbtk_clipboard_provider,
+ self);
+}
+
+static ClutterX11FilterReturn
+nbtk_clipboard_x11_event_filter (XEvent *xev,
+ ClutterEvent *cev,
+ EventFilterData *filter_data)
+{
+ Atom actual_type;
+ int actual_format, result;
+ unsigned long nitems, bytes_after;
+ unsigned char *data = NULL;
+
+ if(xev->type != SelectionNotify)
+ return CLUTTER_X11_FILTER_CONTINUE;
+
+ if (xev->xselection.property == None)
+ {
+ /* clipboard empty */
+ filter_data->callback (filter_data->clipboard,
+ NULL,
+ filter_data->user_data);
+
+ clutter_x11_remove_filter ((ClutterX11FilterFunc) nbtk_clipboard_x11_event_filter,
+ filter_data);
+ g_free (filter_data);
+ return CLUTTER_X11_FILTER_REMOVE;
+ }
+
+ clutter_x11_trap_x_errors ();
+
+ result = XGetWindowProperty (xev->xselection.display,
+ xev->xselection.requestor,
+ xev->xselection.property,
+ 0L, G_MAXINT,
+ True,
+ AnyPropertyType,
+ &actual_type,
+ &actual_format,
+ &nitems,
+ &bytes_after,
+ &data);
+
+ if (clutter_x11_untrap_x_errors () || result != Success)
+ {
+ /* FIXME: handle failure better */
+ g_warning ("Clipboard: prop retrival failed");
+ }
+
+ filter_data->callback (filter_data->clipboard, (char*) data,
+ filter_data->user_data);
+
+ clutter_x11_remove_filter
+ ((ClutterX11FilterFunc) nbtk_clipboard_x11_event_filter,
+ filter_data);
+
+ g_free (filter_data);
+
+ if (data)
+ XFree (data);
+
+ return CLUTTER_X11_FILTER_REMOVE;
+}
+
+/**
+ * nbtk_clipboard_get_default:
+ *
+ * Get the global #NbtkClipboard object that represents the clipboard.
+ *
+ * Returns: a #NbtkClipboard owned by Nbtk and must not be unrefferenced or
+ * freed.
+ */
+NbtkClipboard*
+nbtk_clipboard_get_default ()
+{
+ static NbtkClipboard *default_clipboard = NULL;
+
+ if (!default_clipboard)
+ {
+ default_clipboard = g_object_new (NBTK_TYPE_CLIPBOARD, NULL);
+ }
+
+ return default_clipboard;
+}
+
+/**
+ * nbtk_clipboard_get_text:
+ * @clipboard: A #NbtkCliboard
+ * @callback: function to be called when the text is retreived
+ * @user_data: data to be passed to the callback
+ *
+ * Request the data from the clipboard in text form. @callback is executed
+ * when the data is retreived.
+ *
+ */
+void
+nbtk_clipboard_get_text (NbtkClipboard *clipboard,
+ NbtkClipboardCallbackFunc callback,
+ gpointer user_data)
+{
+ EventFilterData *data;
+
+ Display *dpy;
+
+ g_return_if_fail (NBTK_IS_CLIPBOARD (clipboard));
+ g_return_if_fail (callback != NULL);
+
+ data = g_new0 (EventFilterData, 1);
+ data->clipboard = clipboard;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ clutter_x11_add_filter ((ClutterX11FilterFunc)nbtk_clipboard_x11_event_filter,
+ data);
+
+ dpy = clutter_x11_get_default_display ();
+
+ clutter_x11_trap_x_errors (); /* safety on */
+
+ XConvertSelection (dpy,
+ __atom_clip,
+ __utf8_string, __utf8_string,
+ clipboard->priv->clipboard_window,
+ CurrentTime);
+
+ clutter_x11_untrap_x_errors ();
+}
+
+/**
+ * nbtk_clipboard_set_text:
+ * @clipboard: A #NbtkClipboard
+ * @text: text to copy to the clipboard
+ *
+ * Sets text as the current contents of the clipboard.
+ *
+ */
+void
+nbtk_clipboard_set_text (NbtkClipboard *clipboard,
+ const gchar *text)
+{
+ NbtkClipboardPrivate *priv;
+ Display *dpy;
+
+ g_return_if_fail (NBTK_IS_CLIPBOARD (clipboard));
+ g_return_if_fail (text != NULL);
+
+ priv = clipboard->priv;
+
+ /* make a copy of the text */
+ g_free (priv->clipboard_text);
+ priv->clipboard_text = g_strdup (text);
+
+ /* tell X we own the clipboard selection */
+ dpy = clutter_x11_get_default_display ();
+
+ clutter_x11_trap_x_errors ();
+
+ XSetSelectionOwner (dpy, __atom_clip, priv->clipboard_window, CurrentTime);
+ XSync (dpy, FALSE);
+
+ clutter_x11_untrap_x_errors ();
+}
diff --git a/src/nbtk/nbtk-clipboard.h b/src/nbtk/nbtk-clipboard.h
new file mode 100644
index 0000000..7592548
--- /dev/null
+++ b/src/nbtk/nbtk-clipboard.h
@@ -0,0 +1,94 @@
+/*
+ * nbtk-clipboard.h: clipboard object
+ *
+ * Copyright 2009 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>
+ *
+ */
+
+#ifndef _NBTK_CLIPBOARD_H
+#define _NBTK_CLIPBOARD_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define NBTK_TYPE_CLIPBOARD nbtk_clipboard_get_type()
+
+#define NBTK_CLIPBOARD(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ NBTK_TYPE_CLIPBOARD, NbtkClipboard))
+
+#define NBTK_CLIPBOARD_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ NBTK_TYPE_CLIPBOARD, NbtkClipboardClass))
+
+#define NBTK_IS_CLIPBOARD(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ NBTK_TYPE_CLIPBOARD))
+
+#define NBTK_IS_CLIPBOARD_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ NBTK_TYPE_CLIPBOARD))
+
+#define NBTK_CLIPBOARD_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ NBTK_TYPE_CLIPBOARD, NbtkClipboardClass))
+
+typedef struct _NbtkClipboard NbtkClipboard;
+typedef struct _NbtkClipboardClass NbtkClipboardClass;
+typedef struct _NbtkClipboardPrivate NbtkClipboardPrivate;
+
+/**
+ * NbtkClipboard:
+ *
+ * The contents of this structure is private and should only be accessed using
+ * the provided API.
+ */
+struct _NbtkClipboard
+{
+ /*< private >*/
+ GObject parent;
+ NbtkClipboardPrivate *priv;
+};
+
+struct _NbtkClipboardClass
+{
+ GObjectClass parent_class;
+};
+
+/**
+ * NbtkClipboardCallbackFunc:
+ * @clipboard: A #NbtkClipboard
+ * @text: text from the clipboard
+ * @user_data: user data
+ *
+ * Callback function called when text is retrieved from the clipboard.
+ */
+typedef void (*NbtkClipboardCallbackFunc) (NbtkClipboard *clipboard,
+ const gchar *text,
+ gpointer user_data);
+
+GType nbtk_clipboard_get_type (void);
+
+NbtkClipboard* nbtk_clipboard_get_default ();
+void nbtk_clipboard_get_text (NbtkClipboard *clipboard, NbtkClipboardCallbackFunc callback, gpointer user_data);
+void nbtk_clipboard_set_text (NbtkClipboard *clipboard, const gchar *text);
+
+G_END_DECLS
+
+#endif /* _NBTK_CLIPBOARD_H */
diff --git a/src/nbtk/nbtk-entry.c b/src/nbtk/nbtk-entry.c
new file mode 100644
index 0000000..9cc762a
--- /dev/null
+++ b/src/nbtk/nbtk-entry.c
@@ -0,0 +1,960 @@
+/*
+ * nbtk-entry.c: Plain entry actor
+ *
+ * Copyright 2008, 2009 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>
+ *
+ */
+
+/**
+ * SECTION:nbtk-entry
+ * @short_description: Widget for displaying text
+ *
+ * #NbtkEntry is a simple widget for displaying text. It derives from
+ * #NbtkWidget to add extra style and placement functionality over
+ * #ClutterText. The internal #ClutterText is publicly accessibly to allow
+ * applications to set further properties.
+ *
+ * #NbtkEntry 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>
+ * </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 <clutter-imcontext/clutter-imtext.h>
+
+#include "nbtk-entry.h"
+
+#include "nbtk-widget.h"
+#include "nbtk-stylable.h"
+#include "nbtk-texture-cache.h"
+#include "nbtk-marshal.h"
+#include "nbtk-clipboard.h"
+
+#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,
+
+ PROP_ENTRY,
+ PROP_HINT
+};
+
+/* signals */
+enum
+{
+ PRIMARY_ICON_CLICKED,
+ SECONDARY_ICON_CLICKED,
+
+ LAST_SIGNAL
+};
+
+#define NBTK_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_ENTRY, NbtkEntryPrivate))
+#define NBTK_ENTRY_PRIV(x) ((NbtkEntry *) x)->priv
+
+
+struct _NbtkEntryPrivate
+{
+ ClutterActor *entry;
+ gchar *hint;
+
+ ClutterActor *primary_icon;
+ ClutterActor *secondary_icon;
+
+ gfloat spacing;
+};
+
+static guint entry_signals[LAST_SIGNAL] = { 0, };
+
+static void nbtk_stylable_iface_init (NbtkStylableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NbtkEntry, nbtk_entry, NBTK_TYPE_WIDGET,
+ G_IMPLEMENT_INTERFACE (NBTK_TYPE_STYLABLE,
+ nbtk_stylable_iface_init));
+
+static void
+nbtk_entry_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NbtkEntry *entry = NBTK_ENTRY (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_ENTRY:
+ nbtk_entry_set_text (entry, g_value_get_string (value));
+ break;
+
+ case PROP_HINT:
+ nbtk_entry_set_hint_text (entry, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nbtk_entry_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_ENTRY:
+ g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->entry)));
+ break;
+
+ case PROP_HINT:
+ g_value_set_string (value, priv->hint);
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nbtk_entry_dispose (GObject *object)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (object);
+
+ if (priv->entry)
+ {
+ clutter_actor_unparent (priv->entry);
+ priv->entry = NULL;
+ }
+}
+
+static void
+nbtk_entry_finalize (GObject *object)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (object);
+
+ g_free (priv->hint);
+ priv->hint = NULL;
+}
+
+static void
+nbtk_stylable_iface_init (NbtkStylableIface *iface)
+{
+ static gboolean is_initialized = FALSE;
+
+ if (!is_initialized)
+ {
+ GParamSpec *pspec;
+ static const ClutterColor default_color
+ = { 0x0, 0x9c, 0xcf, 0xff };
+
+ is_initialized = TRUE;
+
+ pspec = clutter_param_spec_color ("caret-color",
+ "Caret Color",
+ "Color of the entry's caret",
+ &default_color,
+ G_PARAM_READWRITE);
+ nbtk_stylable_iface_install_property (iface, NBTK_TYPE_ENTRY, pspec);
+
+ pspec = clutter_param_spec_color ("selection-background-color",
+ "Selection Background Color",
+ "Color of the entry's selection",
+ &default_color,
+ G_PARAM_READWRITE);
+ nbtk_stylable_iface_install_property (iface, NBTK_TYPE_ENTRY, pspec);
+ }
+}
+
+static void
+nbtk_entry_style_changed (NbtkWidget *self)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (self);
+ ClutterColor *color = NULL;
+ ClutterColor *caret_color = NULL;
+ ClutterColor *selection_background_color = NULL;
+ gchar *font_name;
+ gchar *font_string;
+ gint font_size;
+
+ nbtk_stylable_get (NBTK_STYLABLE (self),
+ "color", &color,
+ "caret-color", &caret_color,
+ "selection-background-color", &selection_background_color,
+ "font-family", &font_name,
+ "font-size", &font_size,
+ NULL);
+
+ if (color)
+ {
+ clutter_text_set_color (CLUTTER_TEXT (priv->entry), color);
+ clutter_color_free (color);
+ }
+
+ if (caret_color)
+ {
+ clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), caret_color);
+ clutter_color_free (caret_color);
+ }
+
+ if (selection_background_color)
+ {
+ clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry),
+ selection_background_color);
+ clutter_color_free (selection_background_color);
+ }
+
+ if (font_name || font_size)
+ {
+ if (font_name && font_size)
+ {
+ font_string = g_strdup_printf ("%s %dpx", font_name, font_size);
+ g_free (font_name);
+ }
+ else
+ {
+ if (font_size)
+ font_string = g_strdup_printf ("%dpx", font_size);
+ else
+ font_string = font_name;
+ }
+
+ clutter_text_set_font_name (CLUTTER_TEXT (priv->entry), font_string);
+ g_free (font_string);
+ }
+}
+
+static void
+nbtk_entry_get_preferred_width (ClutterActor *actor,
+ gfloat for_height,
+ gfloat *min_width_p,
+ gfloat *natural_width_p)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
+ NbtkPadding padding;
+ gfloat icon_w;
+
+ nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding);
+
+ for_height -= padding.top + padding.bottom;
+
+ 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;
+ }
+
+ if (min_width_p)
+ *min_width_p += padding.left + padding.right;
+
+ if (natural_width_p)
+ *natural_width_p += padding.left + padding.right;
+}
+
+static void
+nbtk_entry_get_preferred_height (ClutterActor *actor,
+ gfloat for_width,
+ gfloat *min_height_p,
+ gfloat *natural_height_p)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
+ NbtkPadding padding;
+ gfloat icon_h;
+
+ nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding);
+
+ for_width -= padding.left + padding.right;
+
+ 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;
+ }
+
+ if (min_height_p)
+ *min_height_p += padding.top + padding.bottom;
+
+ if (natural_height_p)
+ *natural_height_p += padding.top + padding.bottom;
+}
+
+static void
+nbtk_entry_allocate (ClutterActor *actor,
+ const ClutterActorBox *box,
+ ClutterAllocationFlags flags)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
+ ClutterActorClass *parent_class;
+ ClutterActorBox child_box, icon_box;
+ NbtkPadding padding;
+ gfloat icon_w, icon_h;
+ gfloat entry_h, min_h, pref_h, avail_h;
+
+ nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding);
+
+ parent_class = CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class);
+ parent_class->allocate (actor, box, flags);
+
+ avail_h = (box->y2 - box->y1) - padding.top - padding.bottom;
+
+ child_box.x1 = padding.left;
+ child_box.x2 = box->x2 - box->x1 - padding.right;
+
+ 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);
+
+ icon_box.x1 = padding.left;
+ icon_box.x2 = icon_box.x1 + icon_w;
+
+ icon_box.y1 = (int) (padding.top + avail_h / 2 - icon_h / 2);
+ 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);
+
+ icon_box.x2 = (box->x2 - box->x1) - padding.right;
+ icon_box.x1 = icon_box.x2 - icon_w;
+
+ icon_box.y1 = (int) (padding.top + avail_h / 2 - icon_h / 2);
+ 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);
+
+ child_box.y1 = (int) (padding.top + avail_h / 2 - entry_h / 2);
+ 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)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
+
+ /* remove the hint if visible */
+ if (priv->hint
+ && !strcmp (clutter_text_get_text (text), priv->hint))
+ {
+ clutter_text_set_text (text, "");
+ }
+ nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), "focus");
+ clutter_text_set_cursor_visible (text, TRUE);
+}
+
+static void
+clutter_text_focus_out_cb (ClutterText *text,
+ ClutterActor *actor)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
+
+ /* add a hint if the entry is empty */
+ if (priv->hint && !strcmp (clutter_text_get_text (text), ""))
+ {
+ clutter_text_set_text (text, priv->hint);
+ nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), "indeterminate");
+ }
+ else
+ {
+ nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), NULL);
+ }
+ clutter_text_set_cursor_visible (text, FALSE);
+}
+
+static void
+nbtk_entry_paint (ClutterActor *actor)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
+ ClutterActorClass *parent_class;
+
+ parent_class = CLUTTER_ACTOR_CLASS (nbtk_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
+nbtk_entry_pick (ClutterActor *actor,
+ const ClutterColor *c)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
+
+ CLUTTER_ACTOR_CLASS (nbtk_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
+nbtk_entry_map (ClutterActor *actor)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY (actor)->priv;
+
+ CLUTTER_ACTOR_CLASS (nbtk_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
+nbtk_entry_unmap (ClutterActor *actor)
+{
+ NbtkEntryPrivate *priv = NBTK_ENTRY (actor)->priv;
+
+ CLUTTER_ACTOR_CLASS (nbtk_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
+nbtk_entry_clipboard_callback (NbtkClipboard *clipboard,
+ const gchar *text,
+ gpointer data)
+{
+ ClutterText *ctext = (ClutterText*) ((NbtkEntry *) 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
+nbtk_entry_key_press_event (ClutterActor *actor,
+ ClutterKeyEvent *event)
+{
+ NbtkEntryPrivate *priv = NBTK_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)
+ {
+ NbtkClipboard *clipboard;
+
+ clipboard = nbtk_clipboard_get_default ();
+
+ nbtk_clipboard_get_text (clipboard, nbtk_entry_clipboard_callback, actor);
+
+ return TRUE;
+ }
+
+ /* copy */
+ if ((event->modifier_state & CLUTTER_CONTROL_MASK)
+ && event->keyval == CLUTTER_c)
+ {
+ NbtkClipboard *clipboard;
+ gchar *text;
+
+ clipboard = nbtk_clipboard_get_default ();
+
+ text = clutter_text_get_selection ((ClutterText*) priv->entry);
+
+ if (text && strlen (text))
+ nbtk_clipboard_set_text (clipboard, text);
+
+ return TRUE;
+ }
+
+
+ /* cut */
+ if ((event->modifier_state & CLUTTER_CONTROL_MASK)
+ && event->keyval == CLUTTER_x)
+ {
+ NbtkClipboard *clipboard;
+ gchar *text;
+
+ clipboard = nbtk_clipboard_get_default ();
+
+ text = clutter_text_get_selection ((ClutterText*) priv->entry);
+
+ if (text && strlen (text))
+ {
+ nbtk_clipboard_set_text (clipboard, text);
+
+ /* now delete the text */
+ clutter_text_delete_selection ((ClutterText *) priv->entry);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+nbtk_entry_key_focus_in (ClutterActor *actor)
+{
+ NbtkEntryPrivate *priv = NBTK_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
+nbtk_entry_class_init (NbtkEntryClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+ GParamSpec *pspec;
+
+ g_type_class_add_private (klass, sizeof (NbtkEntryPrivate));
+
+ gobject_class->set_property = nbtk_entry_set_property;
+ gobject_class->get_property = nbtk_entry_get_property;
+ gobject_class->finalize = nbtk_entry_finalize;
+ gobject_class->dispose = nbtk_entry_dispose;
+
+ actor_class->get_preferred_width = nbtk_entry_get_preferred_width;
+ actor_class->get_preferred_height = nbtk_entry_get_preferred_height;
+ actor_class->allocate = nbtk_entry_allocate;
+ actor_class->paint = nbtk_entry_paint;
+ actor_class->pick = nbtk_entry_pick;
+ actor_class->map = nbtk_entry_map;
+ actor_class->unmap = nbtk_entry_unmap;
+
+ actor_class->key_press_event = nbtk_entry_key_press_event;
+ actor_class->key_focus_in = nbtk_entry_key_focus_in;
+
+ pspec = g_param_spec_string ("text",
+ "Text",
+ "Text of the entry",
+ NULL, G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_ENTRY, pspec);
+
+ 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);
+ g_object_class_install_property (gobject_class, PROP_ENTRY, pspec);
+
+ /* signals */
+ /**
+ * NbtkEntry::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 (NbtkEntryClass, primary_icon_clicked),
+ NULL, NULL,
+ _nbtk_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ /**
+ * NbtkEntry::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 (NbtkEntryClass, secondary_icon_clicked),
+ NULL, NULL,
+ _nbtk_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+static void
+nbtk_entry_init (NbtkEntry *entry)
+{
+ NbtkEntryPrivate *priv;
+
+ priv = entry->priv = NBTK_ENTRY_GET_PRIVATE (entry);
+
+ priv->entry = g_object_new (CLUTTER_TYPE_IMTEXT,
+ "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);
+
+ g_signal_connect (entry, "style-changed",
+ G_CALLBACK (nbtk_entry_style_changed), NULL);
+}
+
+/**
+ * nbtk_entry_new:
+ * @text: text to set the entry to
+ *
+ * Create a new #NbtkEntry with the specified entry
+ *
+ * Returns: a new #NbtkEntry
+ */
+NbtkWidget *
+nbtk_entry_new (const gchar *text)
+{
+ NbtkWidget *entry;
+
+ /* add the entry to the stage, but don't allow it to be visible */
+ entry = g_object_new (NBTK_TYPE_ENTRY,
+ "text", text,
+ NULL);
+
+ return entry;
+}
+
+/**
+ * nbtk_entry_get_text:
+ * @entry: a #NbtkEntry
+ *
+ * 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 *
+nbtk_entry_get_text (NbtkEntry *entry)
+{
+ g_return_val_if_fail (NBTK_IS_ENTRY (entry), NULL);
+
+ return clutter_text_get_text (CLUTTER_TEXT (entry->priv->entry));
+}
+
+/**
+ * nbtk_entry_set_text:
+ * @entry: a #NbtkEntry
+ * @text: text to set the entry to
+ *
+ * Sets the text displayed on the entry
+ */
+void
+nbtk_entry_set_text (NbtkEntry *entry,
+ const gchar *text)
+{
+ NbtkEntryPrivate *priv;
+
+ g_return_if_fail (NBTK_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;
+ nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "indeterminate");
+ }
+ else
+ {
+ if (HAS_FOCUS (priv->entry))
+ nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "focus");
+ else
+ nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), NULL);
+ }
+
+ clutter_text_set_text (CLUTTER_TEXT (priv->entry), text);
+
+ g_object_notify (G_OBJECT (entry), "text");
+}
+
+/**
+ * nbtk_entry_get_clutter_text:
+ * @entry: a #NbtkEntry
+ *
+ * Retrieve the internal #ClutterText so that extra parameters can be set
+ *
+ * Returns: the #ClutterText used by #NbtkEntry. The entry is owned by the
+ * #NbtkEntry and should not be unref'ed by the application.
+ */
+ClutterActor*
+nbtk_entry_get_clutter_text (NbtkEntry *entry)
+{
+ g_return_val_if_fail (NBTK_ENTRY (entry), NULL);
+
+ return entry->priv->entry;
+}
+
+/**
+ * nbtk_entry_set_hint_text:
+ * @entry: a #NbtkEntry
+ * @text: text to set as the entry hint
+ *
+ * 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
+nbtk_entry_set_hint_text (NbtkEntry *entry,
+ const gchar *text)
+{
+ NbtkEntryPrivate *priv;
+
+ g_return_if_fail (NBTK_IS_ENTRY (entry));
+
+ priv = entry->priv;
+
+ g_free (priv->hint);
+
+ priv->hint = g_strdup (text);
+
+ if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), ""))
+ {
+ clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint);
+ nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "indeterminate");
+ }
+}
+
+/**
+ * nbtk_entry_get_hint_text:
+ * @entry: a #NbtkEntry
+ *
+ * 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
+ * #NbtkEntry and should not be freed or modified.
+ */
+G_CONST_RETURN
+gchar *
+nbtk_entry_get_hint_text (NbtkEntry *entry)
+{
+ g_return_val_if_fail (NBTK_IS_ENTRY (entry), NULL);
+
+ return entry->priv->hint;
+}
+
+static gboolean
+_nbtk_entry_icon_press_cb (ClutterActor *actor,
+ ClutterButtonEvent *event,
+ NbtkEntry *entry)
+{
+ NbtkEntryPrivate *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
+_nbtk_entry_set_icon_from_file (NbtkEntry *entry,
+ ClutterActor **icon,
+ const gchar *filename)
+{
+ if (*icon)
+ {
+ g_signal_handlers_disconnect_by_func (*icon,
+ _nbtk_entry_icon_press_cb,
+ entry);
+ clutter_actor_unparent (*icon);
+ *icon = NULL;
+ }
+
+ if (filename)
+ {
+ NbtkTextureCache *cache;
+
+ cache = nbtk_texture_cache_get_default ();
+
+
+
+ *icon = (ClutterActor*) nbtk_texture_cache_get_texture (cache, filename, FALSE);
+
+ clutter_actor_set_reactive (*icon, TRUE);
+ clutter_actor_set_parent (*icon, CLUTTER_ACTOR (entry));
+ g_signal_connect (*icon, "button-release-event",
+ G_CALLBACK (_nbtk_entry_icon_press_cb), entry);
+ }
+
+ clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
+}
+
+/**
+ * nbtk_entry_set_primary_icon_from_file:
+ * @entry: a #NbtkEntry
+ * @filename: filename of an icon
+ *
+ * Set the primary icon of the entry to the given filename
+ */
+void
+nbtk_entry_set_primary_icon_from_file (NbtkEntry *entry,
+ const gchar *filename)
+{
+ NbtkEntryPrivate *priv;
+
+ g_return_if_fail (NBTK_IS_ENTRY (entry));
+
+ priv = entry->priv;
+
+ _nbtk_entry_set_icon_from_file (entry, &priv->primary_icon, filename);
+
+}
+
+/**
+ * nbtk_entry_set_secondary_icon_from_file:
+ * @entry: a #NbtkEntry
+ * @filename: filename of an icon
+ *
+ * Set the primary icon of the entry to the given filename
+ */
+void
+nbtk_entry_set_secondary_icon_from_file (NbtkEntry *entry,
+ const gchar *filename)
+{
+ NbtkEntryPrivate *priv;
+
+ g_return_if_fail (NBTK_IS_ENTRY (entry));
+
+ priv = entry->priv;
+
+ _nbtk_entry_set_icon_from_file (entry, &priv->secondary_icon, filename);
+
+}
diff --git a/src/nbtk/nbtk-entry.h b/src/nbtk/nbtk-entry.h
new file mode 100644
index 0000000..aca4c8c
--- /dev/null
+++ b/src/nbtk/nbtk-entry.h
@@ -0,0 +1,88 @@
+/*
+ * nbtk-entry.h: Plain entry actor
+ *
+ * Copyright 2008, 2009 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.
+ * Boston, MA 02111-1307, USA.
+ *
+ * Written by: Thomas Wood <thomas linux intel com>
+ *
+ */
+
+#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
+#error "Only <nbtk/nbtk.h> can be included directly.h"
+#endif
+
+#ifndef __NBTK_ENTRY_H__
+#define __NBTK_ENTRY_H__
+
+G_BEGIN_DECLS
+
+#include <nbtk/nbtk-widget.h>
+
+#define NBTK_TYPE_ENTRY (nbtk_entry_get_type ())
+#define NBTK_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_ENTRY, NbtkEntry))
+#define NBTK_IS_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_ENTRY))
+#define NBTK_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_ENTRY, NbtkEntryClass))
+#define NBTK_IS_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_ENTRY))
+#define NBTK_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_ENTRY, NbtkEntryClass))
+
+typedef struct _NbtkEntry NbtkEntry;
+typedef struct _NbtkEntryPrivate NbtkEntryPrivate;
+typedef struct _NbtkEntryClass NbtkEntryClass;
+
+/**
+ * NbtkEntry:
+ *
+ * The contents of this structure is private and should only be accessed using
+ * the provided API.
+ */
+struct _NbtkEntry
+{
+ /*< private >*/
+ NbtkWidget parent_instance;
+
+ NbtkEntryPrivate *priv;
+};
+
+struct _NbtkEntryClass
+{
+ NbtkWidgetClass parent_class;
+
+ /* signals */
+ void (*primary_icon_clicked) (NbtkEntry *entry);
+ void (*secondary_icon_clicked) (NbtkEntry *entry);
+};
+
+GType nbtk_entry_get_type (void) G_GNUC_CONST;
+
+NbtkWidget * nbtk_entry_new (const gchar *text);
+G_CONST_RETURN gchar *nbtk_entry_get_text (NbtkEntry *entry);
+void nbtk_entry_set_text (NbtkEntry *entry,
+ const gchar *text);
+ClutterActor* nbtk_entry_get_clutter_text (NbtkEntry *entry);
+
+void nbtk_entry_set_hint_text (NbtkEntry *entry,
+ const gchar *text);
+G_CONST_RETURN gchar *nbtk_entry_get_hint_text (NbtkEntry *entry);
+
+void nbtk_entry_set_primary_icon_from_file (NbtkEntry *entry,
+ const gchar *filename);
+void nbtk_entry_set_secondary_icon_from_file (NbtkEntry *entry,
+ const gchar *filename);
+
+G_END_DECLS
+
+#endif /* __NBTK_ENTRY_H__ */
diff --git a/src/nbtk/nbtk-label.c b/src/nbtk/nbtk-label.c
new file mode 100644
index 0000000..3763724
--- /dev/null
+++ b/src/nbtk/nbtk-label.c
@@ -0,0 +1,363 @@
+/*
+ * nbtk-label.c: Plain label actor
+ *
+ * Copyright 2008,2009 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 linux intel com>
+ *
+ */
+
+/**
+ * SECTION:nbtk-label
+ * @short_description: Widget for displaying text
+ *
+ * #NbtkLabel is a simple widget for displaying text. It derives from
+ * #NbtkWidget to add extra style and placement functionality over
+ * #ClutterText. The internal #ClutterText is publicly accessibly to allow
+ * applications to set further properties.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include <clutter/clutter.h>
+
+#include "nbtk-label.h"
+
+#include "nbtk-widget.h"
+#include "nbtk-stylable.h"
+
+enum
+{
+ PROP_0,
+
+ PROP_LABEL
+};
+
+#define NBTK_LABEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_LABEL, NbtkLabelPrivate))
+
+struct _NbtkLabelPrivate
+{
+ ClutterActor *label;
+};
+
+G_DEFINE_TYPE (NbtkLabel, nbtk_label, NBTK_TYPE_WIDGET);
+
+static void
+nbtk_label_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NbtkLabel *label = NBTK_LABEL (gobject);
+
+ switch (prop_id)
+ {
+ case PROP_LABEL:
+ nbtk_label_set_text (label, g_value_get_string (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nbtk_label_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NbtkLabelPrivate *priv = NBTK_LABEL (gobject)->priv;
+
+ switch (prop_id)
+ {
+ case PROP_LABEL:
+ g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->label)));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nbtk_label_style_changed (NbtkWidget *self)
+{
+ NbtkLabelPrivate *priv = NBTK_LABEL (self)->priv;
+ ClutterColor *color = NULL;
+ gchar *font_name;
+ gchar *font_string;
+ gint font_size;
+
+ nbtk_stylable_get (NBTK_STYLABLE (self),
+ "color", &color,
+ "font-family", &font_name,
+ "font-size", &font_size,
+ NULL);
+
+ if (color)
+ {
+ clutter_text_set_color (CLUTTER_TEXT (priv->label), color);
+ clutter_color_free (color);
+ }
+
+ if (font_name || font_size)
+ {
+ if (font_name && font_size)
+ {
+ font_string = g_strdup_printf ("%s %dpx", font_name, font_size);
+ g_free (font_name);
+ }
+ else
+ {
+ if (font_size)
+ font_string = g_strdup_printf ("%dpx", font_size);
+ else
+ font_string = font_name;
+ }
+
+ clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string);
+ g_free (font_string);
+ }
+
+}
+
+static void
+nbtk_label_get_preferred_width (ClutterActor *actor,
+ gfloat for_height,
+ gfloat *min_width_p,
+ gfloat *natural_width_p)
+{
+ NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
+ NbtkPadding padding = { 0, };
+
+ nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding);
+
+ clutter_actor_get_preferred_width (priv->label, for_height,
+ min_width_p,
+ natural_width_p);
+
+ if (min_width_p)
+ *min_width_p += padding.left + padding.right;
+
+ if (natural_width_p)
+ *natural_width_p += padding.left + padding.right;
+}
+
+static void
+nbtk_label_get_preferred_height (ClutterActor *actor,
+ gfloat for_width,
+ gfloat *min_height_p,
+ gfloat *natural_height_p)
+{
+ NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
+ NbtkPadding padding = { 0, };
+
+ nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding);
+
+ clutter_actor_get_preferred_height (priv->label, for_width,
+ min_height_p,
+ natural_height_p);
+
+ if (min_height_p)
+ *min_height_p += padding.top + padding.bottom;
+
+ if (natural_height_p)
+ *natural_height_p += padding.top + padding.bottom;
+}
+
+static void
+nbtk_label_allocate (ClutterActor *actor,
+ const ClutterActorBox *box,
+ ClutterAllocationFlags flags)
+{
+ NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
+ ClutterActorClass *parent_class;
+ ClutterActorBox child_box;
+ NbtkPadding padding = { 0, };
+
+ nbtk_widget_get_padding (NBTK_WIDGET (actor), &padding);
+
+ parent_class = CLUTTER_ACTOR_CLASS (nbtk_label_parent_class);
+ parent_class->allocate (actor, box, flags);
+
+ 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->label, &child_box, flags);
+}
+
+static void
+nbtk_label_paint (ClutterActor *actor)
+{
+ NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
+ ClutterActorClass *parent_class;
+
+ parent_class = CLUTTER_ACTOR_CLASS (nbtk_label_parent_class);
+ parent_class->paint (actor);
+
+ clutter_actor_paint (priv->label);
+}
+
+static void
+nbtk_label_map (ClutterActor *actor)
+{
+ NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
+
+ CLUTTER_ACTOR_CLASS (nbtk_label_parent_class)->map (actor);
+
+ clutter_actor_map (priv->label);
+}
+
+static void
+nbtk_label_unmap (ClutterActor *actor)
+{
+ NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
+
+ CLUTTER_ACTOR_CLASS (nbtk_label_parent_class)->unmap (actor);
+
+ clutter_actor_unmap (priv->label);
+}
+
+static void
+nbtk_label_class_init (NbtkLabelClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+ GParamSpec *pspec;
+
+ g_type_class_add_private (klass, sizeof (NbtkLabelPrivate));
+
+ gobject_class->set_property = nbtk_label_set_property;
+ gobject_class->get_property = nbtk_label_get_property;
+
+ actor_class->paint = nbtk_label_paint;
+ actor_class->allocate = nbtk_label_allocate;
+ actor_class->get_preferred_width = nbtk_label_get_preferred_width;
+ actor_class->get_preferred_height = nbtk_label_get_preferred_height;
+ actor_class->map = nbtk_label_map;
+ actor_class->unmap = nbtk_label_unmap;
+
+ pspec = g_param_spec_string ("text",
+ "Text",
+ "Text of the label",
+ NULL, G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
+
+}
+
+static void
+nbtk_label_init (NbtkLabel *label)
+{
+ NbtkLabelPrivate *priv;
+
+ label->priv = priv = NBTK_LABEL_GET_PRIVATE (label);
+
+ label->priv->label = g_object_new (CLUTTER_TYPE_TEXT,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+
+ clutter_actor_set_parent (priv->label, CLUTTER_ACTOR (label));
+
+ g_signal_connect (label, "style-changed",
+ G_CALLBACK (nbtk_label_style_changed), NULL);
+}
+
+/**
+ * nbtk_label_new:
+ * @text: text to set the label to
+ *
+ * Create a new #NbtkLabel with the specified label
+ *
+ * Returns: a new #NbtkLabel
+ */
+NbtkWidget *
+nbtk_label_new (const gchar *text)
+{
+ if (text == NULL || *text == '\0')
+ return g_object_new (NBTK_TYPE_LABEL, NULL);
+ else
+ return g_object_new (NBTK_TYPE_LABEL,
+ "text", text,
+ NULL);
+}
+
+/**
+ * nbtk_label_get_text:
+ * @label: a #NbtkLabel
+ *
+ * Get the text displayed on the label
+ *
+ * Returns: the text for the label. This must not be freed by the application
+ */
+G_CONST_RETURN gchar *
+nbtk_label_get_text (NbtkLabel *label)
+{
+ g_return_val_if_fail (NBTK_IS_LABEL (label), NULL);
+
+ return clutter_text_get_text (CLUTTER_TEXT (label->priv->label));
+}
+
+/**
+ * nbtk_label_set_text:
+ * @label: a #NbtkLabel
+ * @text: text to set the label to
+ *
+ * Sets the text displayed on the label
+ */
+void
+nbtk_label_set_text (NbtkLabel *label,
+ const gchar *text)
+{
+ NbtkLabelPrivate *priv;
+
+ g_return_if_fail (NBTK_IS_LABEL (label));
+ g_return_if_fail (text != NULL);
+
+ priv = label->priv;
+
+ clutter_text_set_text (CLUTTER_TEXT (priv->label), text);
+
+ g_object_notify (G_OBJECT (label), "text");
+}
+
+/**
+ * nbtk_label_get_clutter_text:
+ * @label: a #NbtkLabel
+ *
+ * Retrieve the internal #ClutterText so that extra parameters can be set
+ *
+ * Returns: the #ClutterText used by #NbtkLabel. The label is owned by the
+ * #NbtkLabel and should not be unref'ed by the application.
+ */
+ClutterActor*
+nbtk_label_get_clutter_text (NbtkLabel *label)
+{
+ g_return_val_if_fail (NBTK_LABEL (label), NULL);
+
+ return label->priv->label;
+}
diff --git a/src/nbtk/nbtk-label.h b/src/nbtk/nbtk-label.h
new file mode 100644
index 0000000..613e0fd
--- /dev/null
+++ b/src/nbtk/nbtk-label.h
@@ -0,0 +1,75 @@
+/*
+ * nbtk-label.h: Plain label actor
+ *
+ * Copyright 2008, 2009 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.
+ * Boston, MA 02111-1307, USA.
+ *
+ * Written by: Thomas Wood <thomas linux intel com>
+ *
+ */
+
+#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
+#error "Only <nbtk/nbtk.h> can be included directly.h"
+#endif
+
+#ifndef __NBTK_LABEL_H__
+#define __NBTK_LABEL_H__
+
+G_BEGIN_DECLS
+
+#include <nbtk/nbtk-widget.h>
+
+#define NBTK_TYPE_LABEL (nbtk_label_get_type ())
+#define NBTK_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_LABEL, NbtkLabel))
+#define NBTK_IS_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_LABEL))
+#define NBTK_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_LABEL, NbtkLabelClass))
+#define NBTK_IS_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_LABEL))
+#define NBTK_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_LABEL, NbtkLabelClass))
+
+typedef struct _NbtkLabel NbtkLabel;
+typedef struct _NbtkLabelPrivate NbtkLabelPrivate;
+typedef struct _NbtkLabelClass NbtkLabelClass;
+
+/**
+ * NbtkLabel:
+ *
+ * The contents of this structure is private and should only be accessed using
+ * the provided API.
+ */
+struct _NbtkLabel
+{
+ /*< private >*/
+ NbtkWidget parent_instance;
+
+ NbtkLabelPrivate *priv;
+};
+
+struct _NbtkLabelClass
+{
+ NbtkWidgetClass parent_class;
+};
+
+GType nbtk_label_get_type (void) G_GNUC_CONST;
+
+NbtkWidget * nbtk_label_new (const gchar *text);
+G_CONST_RETURN gchar *nbtk_label_get_text (NbtkLabel *label);
+void nbtk_label_set_text (NbtkLabel *label,
+ const gchar *text);
+ClutterActor * nbtk_label_get_clutter_text (NbtkLabel *label);
+
+G_END_DECLS
+
+#endif /* __NBTK_LABEL_H__ */
diff --git a/tools/build/gnome-shell.modules b/tools/build/gnome-shell.modules
index 095bc9d..6395eb5 100644
--- a/tools/build/gnome-shell.modules
+++ b/tools/build/gnome-shell.modules
@@ -7,6 +7,8 @@
href="git://git.clutter-project.org/"/>
<repository type="git" name="git.gnome.org"
href="git://git.gnome.org/"/>
+ <repository type="git" name="git.moblin.org"
+ href="git://git.moblin.org"/>
<autotools id="gobject-introspection">
<branch repo="git.gnome.org" module="gobject-introspection"/>
@@ -36,6 +38,13 @@
</dependencies>
</autotools>
+ <autotools id="clutter-imcontext">
+ <branch repo="git.moblin.org" module="clutter-imcontext"/>
+ <dependencies>
+ <dep package="clutter"/>
+ </dependencies>
+ </autotools>
+
<autotools id="gconf" autogenargs="--disable-defaults-service">
<branch repo="git.gnome.org" module="gconf"/>
</autotools>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]