Import MxEntry, MxLabel, MxClipboard
For now this commit introduces an external dependency on clutter-imcontext. https://bugzilla.gnome.org/show_bug.cgi?id=591245
This commit is contained in:
parent
48085dd428
commit
0315a6e4a8
@ -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
|
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
|
||||||
gobject-introspection-1.0 >= 0.6.5)
|
gobject-introspection-1.0 >= 0.6.5)
|
||||||
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
PKG_CHECK_MODULES(TIDY, clutter-1.0)
|
||||||
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libccss-1 >= 0.3.1)
|
PKG_CHECK_MODULES(ST, 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(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
|
||||||
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
|
||||||
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
|
||||||
|
@ -70,6 +70,9 @@ st_source_h = \
|
|||||||
st/st-box-layout.h \
|
st/st-box-layout.h \
|
||||||
st/st-box-layout-child.h \
|
st/st-box-layout-child.h \
|
||||||
st/st-button.h \
|
st/st-button.h \
|
||||||
|
st/st-clipboard.h \
|
||||||
|
st/st-entry.h \
|
||||||
|
st/st-label.h \
|
||||||
st/st-private.h \
|
st/st-private.h \
|
||||||
st/st-stylable.h \
|
st/st-stylable.h \
|
||||||
st/st-style.h \
|
st/st-style.h \
|
||||||
@ -91,6 +94,9 @@ st_source_c = \
|
|||||||
st/st-box-layout.c \
|
st/st-box-layout.c \
|
||||||
st/st-box-layout-child.c \
|
st/st-box-layout-child.c \
|
||||||
st/st-button.c \
|
st/st-button.c \
|
||||||
|
st/st-clipboard.c \
|
||||||
|
st/st-entry.c \
|
||||||
|
st/st-label.c \
|
||||||
st/st-private.c \
|
st/st-private.c \
|
||||||
st/st-scrollable.c \
|
st/st-scrollable.c \
|
||||||
st/st-scroll-bar.c \
|
st/st-scroll-bar.c \
|
||||||
|
380
src/st/st-clipboard.c
Normal file
380
src/st/st-clipboard.c
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
/*
|
||||||
|
* st-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>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:st-clipboard
|
||||||
|
* @short_description: a simple representation of the X clipboard
|
||||||
|
*
|
||||||
|
* #StCliboard is a very simple object representation of the clipboard
|
||||||
|
* available to applications. Text is always assumed to be UTF-8 and non-text
|
||||||
|
* items are not handled.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "st-clipboard.h"
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <clutter/x11/clutter-x11.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StClipboard, st_clipboard, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
#define CLIPBOARD_PRIVATE(o) \
|
||||||
|
(G_TYPE_INSTANCE_GET_PRIVATE ((o), ST_TYPE_CLIPBOARD, StClipboardPrivate))
|
||||||
|
|
||||||
|
struct _StClipboardPrivate
|
||||||
|
{
|
||||||
|
Window clipboard_window;
|
||||||
|
gchar *clipboard_text;
|
||||||
|
|
||||||
|
Atom *supported_targets;
|
||||||
|
gint n_targets;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _EventFilterData EventFilterData;
|
||||||
|
struct _EventFilterData
|
||||||
|
{
|
||||||
|
StClipboard *clipboard;
|
||||||
|
StClipboardCallbackFunc callback;
|
||||||
|
gpointer user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Atom __atom_clip = None;
|
||||||
|
static Atom __utf8_string = None;
|
||||||
|
static Atom __atom_targets = None;
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_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
|
||||||
|
st_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
|
||||||
|
st_clipboard_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (st_clipboard_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_clipboard_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
StClipboardPrivate *priv = ((StClipboard *) 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 (st_clipboard_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterX11FilterReturn
|
||||||
|
st_clipboard_provider (XEvent *xev,
|
||||||
|
ClutterEvent *cev,
|
||||||
|
StClipboard *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
|
||||||
|
st_clipboard_class_init (StClipboardClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (StClipboardPrivate));
|
||||||
|
|
||||||
|
object_class->get_property = st_clipboard_get_property;
|
||||||
|
object_class->set_property = st_clipboard_set_property;
|
||||||
|
object_class->dispose = st_clipboard_dispose;
|
||||||
|
object_class->finalize = st_clipboard_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_clipboard_init (StClipboard *self)
|
||||||
|
{
|
||||||
|
Display *dpy;
|
||||||
|
StClipboardPrivate *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) st_clipboard_provider,
|
||||||
|
self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterX11FilterReturn
|
||||||
|
st_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) st_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) st_clipboard_x11_event_filter,
|
||||||
|
filter_data);
|
||||||
|
|
||||||
|
g_free (filter_data);
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
XFree (data);
|
||||||
|
|
||||||
|
return CLUTTER_X11_FILTER_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_clipboard_get_default:
|
||||||
|
*
|
||||||
|
* Get the global #StClipboard object that represents the clipboard.
|
||||||
|
*
|
||||||
|
* Returns: a #StClipboard owned by St and must not be unrefferenced or
|
||||||
|
* freed.
|
||||||
|
*/
|
||||||
|
StClipboard*
|
||||||
|
st_clipboard_get_default (void)
|
||||||
|
{
|
||||||
|
static StClipboard *default_clipboard = NULL;
|
||||||
|
|
||||||
|
if (!default_clipboard)
|
||||||
|
{
|
||||||
|
default_clipboard = g_object_new (ST_TYPE_CLIPBOARD, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_clipboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_clipboard_get_text:
|
||||||
|
* @clipboard: A #StCliboard
|
||||||
|
* @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
|
||||||
|
st_clipboard_get_text (StClipboard *clipboard,
|
||||||
|
StClipboardCallbackFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
EventFilterData *data;
|
||||||
|
|
||||||
|
Display *dpy;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_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) st_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 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_clipboard_set_text:
|
||||||
|
* @clipboard: A #StClipboard
|
||||||
|
* @text: text to copy to the clipboard
|
||||||
|
*
|
||||||
|
* Sets text as the current contents of the clipboard.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_clipboard_set_text (StClipboard *clipboard,
|
||||||
|
const gchar *text)
|
||||||
|
{
|
||||||
|
StClipboardPrivate *priv;
|
||||||
|
Display *dpy;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_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 ();
|
||||||
|
}
|
102
src/st/st-clipboard.h
Normal file
102
src/st/st-clipboard.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* st-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>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _ST_CLIPBOARD_H
|
||||||
|
#define _ST_CLIPBOARD_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define ST_TYPE_CLIPBOARD st_clipboard_get_type()
|
||||||
|
|
||||||
|
#define ST_CLIPBOARD(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||||
|
ST_TYPE_CLIPBOARD, StClipboard))
|
||||||
|
|
||||||
|
#define ST_CLIPBOARD_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||||
|
ST_TYPE_CLIPBOARD, StClipboardClass))
|
||||||
|
|
||||||
|
#define ST_IS_CLIPBOARD(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||||
|
ST_TYPE_CLIPBOARD))
|
||||||
|
|
||||||
|
#define ST_IS_CLIPBOARD_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||||
|
ST_TYPE_CLIPBOARD))
|
||||||
|
|
||||||
|
#define ST_CLIPBOARD_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||||
|
ST_TYPE_CLIPBOARD, StClipboardClass))
|
||||||
|
|
||||||
|
typedef struct _StClipboard StClipboard;
|
||||||
|
typedef struct _StClipboardClass StClipboardClass;
|
||||||
|
typedef struct _StClipboardPrivate StClipboardPrivate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StClipboard:
|
||||||
|
*
|
||||||
|
* The contents of this structure is private and should only be accessed using
|
||||||
|
* the provided API.
|
||||||
|
*/
|
||||||
|
struct _StClipboard
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
GObject parent;
|
||||||
|
StClipboardPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StClipboardClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StClipboardCallbackFunc:
|
||||||
|
* @clipboard: A #StClipboard
|
||||||
|
* @text: text from the clipboard
|
||||||
|
* @user_data: user data
|
||||||
|
*
|
||||||
|
* Callback function called when text is retrieved from the clipboard.
|
||||||
|
*/
|
||||||
|
typedef void (*StClipboardCallbackFunc) (StClipboard *clipboard,
|
||||||
|
const gchar *text,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GType st_clipboard_get_type (void);
|
||||||
|
|
||||||
|
StClipboard* st_clipboard_get_default (void);
|
||||||
|
|
||||||
|
void st_clipboard_get_text (StClipboard *clipboard,
|
||||||
|
StClipboardCallbackFunc callback,
|
||||||
|
gpointer user_data);
|
||||||
|
void st_clipboard_set_text (StClipboard *clipboard,
|
||||||
|
const gchar *text);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* _ST_CLIPBOARD_H */
|
961
src/st/st-entry.c
Normal file
961
src/st/st-entry.c
Normal file
@ -0,0 +1,961 @@
|
|||||||
|
/*
|
||||||
|
* st-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: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>
|
||||||
|
* </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 "st-entry.h"
|
||||||
|
|
||||||
|
#include "st-widget.h"
|
||||||
|
#include "st-stylable.h"
|
||||||
|
#include "st-texture-cache.h"
|
||||||
|
#include "st-marshal.h"
|
||||||
|
#include "st-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 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint entry_signals[LAST_SIGNAL] = { 0, };
|
||||||
|
|
||||||
|
static void st_stylable_iface_init (StStylableIface *iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (StEntry, st_entry, ST_TYPE_WIDGET,
|
||||||
|
G_IMPLEMENT_INTERFACE (ST_TYPE_STYLABLE,
|
||||||
|
st_stylable_iface_init));
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StEntry *entry = ST_ENTRY (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_ENTRY:
|
||||||
|
st_entry_set_text (entry, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PROP_HINT:
|
||||||
|
st_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
|
||||||
|
st_entry_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_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
|
||||||
|
st_entry_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (object);
|
||||||
|
|
||||||
|
if (priv->entry)
|
||||||
|
{
|
||||||
|
clutter_actor_unparent (priv->entry);
|
||||||
|
priv->entry = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (object);
|
||||||
|
|
||||||
|
g_free (priv->hint);
|
||||||
|
priv->hint = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_stylable_iface_init (StStylableIface *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);
|
||||||
|
st_stylable_iface_install_property (iface, ST_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);
|
||||||
|
st_stylable_iface_install_property (iface, ST_TYPE_ENTRY, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_entry_style_changed (StWidget *self)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (self);
|
||||||
|
ClutterColor *color = NULL;
|
||||||
|
ClutterColor *caret_color = NULL;
|
||||||
|
ClutterColor *selection_background_color = NULL;
|
||||||
|
gchar *font_name;
|
||||||
|
gchar *font_string;
|
||||||
|
gint font_size;
|
||||||
|
|
||||||
|
st_stylable_get (ST_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
|
||||||
|
st_entry_get_preferred_width (ClutterActor *actor,
|
||||||
|
gfloat for_height,
|
||||||
|
gfloat *min_width_p,
|
||||||
|
gfloat *natural_width_p)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
StPadding padding;
|
||||||
|
gfloat icon_w;
|
||||||
|
|
||||||
|
st_widget_get_padding (ST_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
|
||||||
|
st_entry_get_preferred_height (ClutterActor *actor,
|
||||||
|
gfloat for_width,
|
||||||
|
gfloat *min_height_p,
|
||||||
|
gfloat *natural_height_p)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
StPadding padding;
|
||||||
|
gfloat icon_h;
|
||||||
|
|
||||||
|
st_widget_get_padding (ST_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
|
||||||
|
st_entry_allocate (ClutterActor *actor,
|
||||||
|
const ClutterActorBox *box,
|
||||||
|
ClutterAllocationFlags flags)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
ClutterActorClass *parent_class;
|
||||||
|
ClutterActorBox child_box, icon_box;
|
||||||
|
StPadding padding;
|
||||||
|
gfloat icon_w, icon_h;
|
||||||
|
gfloat entry_h, min_h, pref_h, avail_h;
|
||||||
|
|
||||||
|
st_widget_get_padding (ST_WIDGET (actor), &padding);
|
||||||
|
|
||||||
|
parent_class = CLUTTER_ACTOR_CLASS (st_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)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_ENTRY_PRIV (actor);
|
||||||
|
|
||||||
|
/* remove the hint if visible */
|
||||||
|
if (priv->hint
|
||||||
|
&& !strcmp (clutter_text_get_text (text), priv->hint))
|
||||||
|
{
|
||||||
|
clutter_text_set_text (text, "");
|
||||||
|
}
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (actor), "focus");
|
||||||
|
clutter_text_set_cursor_visible (text, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_text_focus_out_cb (ClutterText *text,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StEntryPrivate *priv = ST_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);
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (actor), "indeterminate");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (actor), NULL);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 */
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
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 (st_entry_style_changed), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
return clutter_text_get_text (CLUTTER_TEXT (entry->priv->entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_set_text:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
* @text: text to set the entry to
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (HAS_FOCUS (priv->entry))
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (entry), "focus");
|
||||||
|
else
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (entry), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
*
|
||||||
|
* Returns: the #ClutterText used by #StEntry. The entry is owned by the
|
||||||
|
* #StEntry and should not be unref'ed by the application.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* @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
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), ""))
|
||||||
|
{
|
||||||
|
clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint);
|
||||||
|
st_widget_set_style_pseudo_class (ST_WIDGET (entry), "indeterminate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
_st_entry_set_icon_from_file (StEntry *entry,
|
||||||
|
ClutterActor **icon,
|
||||||
|
const gchar *filename)
|
||||||
|
{
|
||||||
|
if (*icon)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (*icon,
|
||||||
|
_st_entry_icon_press_cb,
|
||||||
|
entry);
|
||||||
|
clutter_actor_unparent (*icon);
|
||||||
|
*icon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename)
|
||||||
|
{
|
||||||
|
StTextureCache *cache;
|
||||||
|
|
||||||
|
cache = st_texture_cache_get_default ();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*icon = (ClutterActor*) st_texture_cache_get_texture (cache, filename);
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_entry_set_primary_icon_from_file:
|
||||||
|
* @entry: a #StEntry
|
||||||
|
* @filename: filename of an icon
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* @filename: filename of an icon
|
||||||
|
*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
88
src/st/st-entry.h
Normal file
88
src/st/st-entry.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* st-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(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ST_ENTRY_H__
|
||||||
|
#define __ST_ENTRY_H__
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <st/st-widget.h>
|
||||||
|
|
||||||
|
#define ST_TYPE_ENTRY (st_entry_get_type ())
|
||||||
|
#define ST_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_ENTRY, StEntry))
|
||||||
|
#define ST_IS_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_ENTRY))
|
||||||
|
#define ST_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_ENTRY, StEntryClass))
|
||||||
|
#define ST_IS_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_ENTRY))
|
||||||
|
#define ST_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_ENTRY, StEntryClass))
|
||||||
|
|
||||||
|
typedef struct _StEntry StEntry;
|
||||||
|
typedef struct _StEntryPrivate StEntryPrivate;
|
||||||
|
typedef struct _StEntryClass StEntryClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StEntry:
|
||||||
|
*
|
||||||
|
* The contents of this structure is private and should only be accessed using
|
||||||
|
* the provided API.
|
||||||
|
*/
|
||||||
|
struct _StEntry
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
StWidget parent_instance;
|
||||||
|
|
||||||
|
StEntryPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StEntryClass
|
||||||
|
{
|
||||||
|
StWidgetClass parent_class;
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
void (*primary_icon_clicked) (StEntry *entry);
|
||||||
|
void (*secondary_icon_clicked) (StEntry *entry);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType st_entry_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
StWidget * st_entry_new (const gchar *text);
|
||||||
|
G_CONST_RETURN gchar *st_entry_get_text (StEntry *entry);
|
||||||
|
void st_entry_set_text (StEntry *entry,
|
||||||
|
const gchar *text);
|
||||||
|
ClutterActor* st_entry_get_clutter_text (StEntry *entry);
|
||||||
|
|
||||||
|
void st_entry_set_hint_text (StEntry *entry,
|
||||||
|
const gchar *text);
|
||||||
|
G_CONST_RETURN gchar *st_entry_get_hint_text (StEntry *entry);
|
||||||
|
|
||||||
|
void st_entry_set_primary_icon_from_file (StEntry *entry,
|
||||||
|
const gchar *filename);
|
||||||
|
void st_entry_set_secondary_icon_from_file (StEntry *entry,
|
||||||
|
const gchar *filename);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_ENTRY_H__ */
|
363
src/st/st-label.c
Normal file
363
src/st/st-label.c
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
/*
|
||||||
|
* st-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:st-label
|
||||||
|
* @short_description: Widget for displaying text
|
||||||
|
*
|
||||||
|
* #StLabel 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#include "st-label.h"
|
||||||
|
|
||||||
|
#include "st-widget.h"
|
||||||
|
#include "st-stylable.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_LABEL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ST_LABEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_LABEL, StLabelPrivate))
|
||||||
|
|
||||||
|
struct _StLabelPrivate
|
||||||
|
{
|
||||||
|
ClutterActor *label;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (StLabel, st_label, ST_TYPE_WIDGET);
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_label_set_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StLabel *label = ST_LABEL (gobject);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_LABEL:
|
||||||
|
st_label_set_text (label, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_label_get_property (GObject *gobject,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv = ST_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
|
||||||
|
st_label_style_changed (StWidget *self)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv = ST_LABEL (self)->priv;
|
||||||
|
ClutterColor *color = NULL;
|
||||||
|
gchar *font_name;
|
||||||
|
gchar *font_string;
|
||||||
|
gint font_size;
|
||||||
|
|
||||||
|
st_stylable_get (ST_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
|
||||||
|
st_label_get_preferred_width (ClutterActor *actor,
|
||||||
|
gfloat for_height,
|
||||||
|
gfloat *min_width_p,
|
||||||
|
gfloat *natural_width_p)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv = ST_LABEL (actor)->priv;
|
||||||
|
StPadding padding = { 0, };
|
||||||
|
|
||||||
|
st_widget_get_padding (ST_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
|
||||||
|
st_label_get_preferred_height (ClutterActor *actor,
|
||||||
|
gfloat for_width,
|
||||||
|
gfloat *min_height_p,
|
||||||
|
gfloat *natural_height_p)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv = ST_LABEL (actor)->priv;
|
||||||
|
StPadding padding = { 0, };
|
||||||
|
|
||||||
|
st_widget_get_padding (ST_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
|
||||||
|
st_label_allocate (ClutterActor *actor,
|
||||||
|
const ClutterActorBox *box,
|
||||||
|
ClutterAllocationFlags flags)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv = ST_LABEL (actor)->priv;
|
||||||
|
ClutterActorClass *parent_class;
|
||||||
|
ClutterActorBox child_box;
|
||||||
|
StPadding padding = { 0, };
|
||||||
|
|
||||||
|
st_widget_get_padding (ST_WIDGET (actor), &padding);
|
||||||
|
|
||||||
|
parent_class = CLUTTER_ACTOR_CLASS (st_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
|
||||||
|
st_label_paint (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv = ST_LABEL (actor)->priv;
|
||||||
|
ClutterActorClass *parent_class;
|
||||||
|
|
||||||
|
parent_class = CLUTTER_ACTOR_CLASS (st_label_parent_class);
|
||||||
|
parent_class->paint (actor);
|
||||||
|
|
||||||
|
clutter_actor_paint (priv->label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_label_map (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv = ST_LABEL (actor)->priv;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (st_label_parent_class)->map (actor);
|
||||||
|
|
||||||
|
clutter_actor_map (priv->label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_label_unmap (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv = ST_LABEL (actor)->priv;
|
||||||
|
|
||||||
|
CLUTTER_ACTOR_CLASS (st_label_parent_class)->unmap (actor);
|
||||||
|
|
||||||
|
clutter_actor_unmap (priv->label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
st_label_class_init (StLabelClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (StLabelPrivate));
|
||||||
|
|
||||||
|
gobject_class->set_property = st_label_set_property;
|
||||||
|
gobject_class->get_property = st_label_get_property;
|
||||||
|
|
||||||
|
actor_class->paint = st_label_paint;
|
||||||
|
actor_class->allocate = st_label_allocate;
|
||||||
|
actor_class->get_preferred_width = st_label_get_preferred_width;
|
||||||
|
actor_class->get_preferred_height = st_label_get_preferred_height;
|
||||||
|
actor_class->map = st_label_map;
|
||||||
|
actor_class->unmap = st_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
|
||||||
|
st_label_init (StLabel *label)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv;
|
||||||
|
|
||||||
|
label->priv = priv = ST_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 (st_label_style_changed), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_label_new:
|
||||||
|
* @text: text to set the label to
|
||||||
|
*
|
||||||
|
* Create a new #StLabel with the specified label
|
||||||
|
*
|
||||||
|
* Returns: a new #StLabel
|
||||||
|
*/
|
||||||
|
StWidget *
|
||||||
|
st_label_new (const gchar *text)
|
||||||
|
{
|
||||||
|
if (text == NULL || *text == '\0')
|
||||||
|
return g_object_new (ST_TYPE_LABEL, NULL);
|
||||||
|
else
|
||||||
|
return g_object_new (ST_TYPE_LABEL,
|
||||||
|
"text", text,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_label_get_text:
|
||||||
|
* @label: a #StLabel
|
||||||
|
*
|
||||||
|
* 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 *
|
||||||
|
st_label_get_text (StLabel *label)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_IS_LABEL (label), NULL);
|
||||||
|
|
||||||
|
return clutter_text_get_text (CLUTTER_TEXT (label->priv->label));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_label_set_text:
|
||||||
|
* @label: a #StLabel
|
||||||
|
* @text: text to set the label to
|
||||||
|
*
|
||||||
|
* Sets the text displayed on the label
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
st_label_set_text (StLabel *label,
|
||||||
|
const gchar *text)
|
||||||
|
{
|
||||||
|
StLabelPrivate *priv;
|
||||||
|
|
||||||
|
g_return_if_fail (ST_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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* st_label_get_clutter_text:
|
||||||
|
* @label: a #StLabel
|
||||||
|
*
|
||||||
|
* Retrieve the internal #ClutterText so that extra parameters can be set
|
||||||
|
*
|
||||||
|
* Returns: the #ClutterText used by #StLabel. The label is owned by the
|
||||||
|
* #StLabel and should not be unref'ed by the application.
|
||||||
|
*/
|
||||||
|
ClutterActor*
|
||||||
|
st_label_get_clutter_text (StLabel *label)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (ST_LABEL (label), NULL);
|
||||||
|
|
||||||
|
return label->priv->label;
|
||||||
|
}
|
75
src/st/st-label.h
Normal file
75
src/st/st-label.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* st-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(ST_H_INSIDE) && !defined(ST_COMPILATION)
|
||||||
|
#error "Only <st/st.h> can be included directly.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ST_LABEL_H__
|
||||||
|
#define __ST_LABEL_H__
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <st/st-widget.h>
|
||||||
|
|
||||||
|
#define ST_TYPE_LABEL (st_label_get_type ())
|
||||||
|
#define ST_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ST_TYPE_LABEL, StLabel))
|
||||||
|
#define ST_IS_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ST_TYPE_LABEL))
|
||||||
|
#define ST_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ST_TYPE_LABEL, StLabelClass))
|
||||||
|
#define ST_IS_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ST_TYPE_LABEL))
|
||||||
|
#define ST_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ST_TYPE_LABEL, StLabelClass))
|
||||||
|
|
||||||
|
typedef struct _StLabel StLabel;
|
||||||
|
typedef struct _StLabelPrivate StLabelPrivate;
|
||||||
|
typedef struct _StLabelClass StLabelClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StLabel:
|
||||||
|
*
|
||||||
|
* The contents of this structure is private and should only be accessed using
|
||||||
|
* the provided API.
|
||||||
|
*/
|
||||||
|
struct _StLabel
|
||||||
|
{
|
||||||
|
/*< private >*/
|
||||||
|
StWidget parent_instance;
|
||||||
|
|
||||||
|
StLabelPrivate *priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _StLabelClass
|
||||||
|
{
|
||||||
|
StWidgetClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType st_label_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
StWidget * st_label_new (const gchar *text);
|
||||||
|
G_CONST_RETURN gchar *st_label_get_text (StLabel *label);
|
||||||
|
void st_label_set_text (StLabel *label,
|
||||||
|
const gchar *text);
|
||||||
|
ClutterActor * st_label_get_clutter_text (StLabel *label);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __ST_LABEL_H__ */
|
@ -7,6 +7,8 @@
|
|||||||
href="git://git.clutter-project.org/"/>
|
href="git://git.clutter-project.org/"/>
|
||||||
<repository type="git" name="git.gnome.org"
|
<repository type="git" name="git.gnome.org"
|
||||||
href="git://git.gnome.org/"/>
|
href="git://git.gnome.org/"/>
|
||||||
|
<repository type="git" name="git.moblin.org"
|
||||||
|
href="git://git.moblin.org"/>
|
||||||
|
|
||||||
<autotools id="gobject-introspection">
|
<autotools id="gobject-introspection">
|
||||||
<branch repo="git.gnome.org" module="gobject-introspection"/>
|
<branch repo="git.gnome.org" module="gobject-introspection"/>
|
||||||
@ -36,6 +38,13 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
</autotools>
|
</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">
|
<autotools id="gconf" autogenargs="--disable-defaults-service">
|
||||||
<branch repo="git.gnome.org" module="gconf"/>
|
<branch repo="git.gnome.org" module="gconf"/>
|
||||||
</autotools>
|
</autotools>
|
||||||
|
Loading…
Reference in New Issue
Block a user