
Import the core MxWidget/MxBin and their dependencies; we use the namespace "St" (Shell Toolkit) because it is the same length as Mx so enabling easy sharing of code, but makes it clear that this is a friendly fork and not a literal import. Based on a patch by Colin Walters <walters@verbum.org> https://bugzilla.gnome.org/show_bug.cgi?id=591245
850 lines
23 KiB
C
850 lines
23 KiB
C
/*
|
|
* st-stylable.c: Interface for stylable objects
|
|
*
|
|
* Copyright 2008 Intel Corporation
|
|
* 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: Emmanuele Bassi <ebassi@openedhand.com>
|
|
* Thomas Wood <thomas@linux.intel.com>
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* SECTION:st-stylable
|
|
* @short_description: Interface for stylable objects
|
|
*
|
|
* Stylable objects are classes that can have "style properties", that is
|
|
* properties that can be changed by attaching a #StStyle to them.
|
|
*
|
|
* Objects can choose to subclass #StWidget, and thus inherit all the
|
|
* #StWidget style properties; or they can subclass #StWidget and
|
|
* reimplement the #StStylable interface to add new style properties
|
|
* specific for them (and their subclasses); or, finally, they can simply
|
|
* subclass #GObject and implement #StStylable to install new properties.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <glib-object.h>
|
|
#include <gobject/gvaluecollector.h>
|
|
#include <gobject/gobjectnotifyqueue.c>
|
|
|
|
#include "st-marshal.h"
|
|
#include "st-private.h"
|
|
#include "st-stylable.h"
|
|
|
|
enum
|
|
{
|
|
STYLE_CHANGED,
|
|
STYLE_NOTIFY,
|
|
CHANGED,
|
|
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static GObjectNotifyContext property_notify_context = { 0, };
|
|
|
|
static GParamSpecPool *style_property_spec_pool = NULL;
|
|
|
|
static GQuark quark_real_owner = 0;
|
|
static GQuark quark_style = 0;
|
|
|
|
static guint stylable_signals[LAST_SIGNAL] = { 0, };
|
|
|
|
static void
|
|
st_stylable_notify_dispatcher (GObject *gobject,
|
|
guint n_pspecs,
|
|
GParamSpec **pspecs)
|
|
{
|
|
guint i;
|
|
|
|
for (i = 0; i < n_pspecs; i++)
|
|
g_signal_emit (gobject, stylable_signals[STYLE_NOTIFY],
|
|
g_quark_from_string (pspecs[i]->name),
|
|
pspecs[i]);
|
|
}
|
|
|
|
static void
|
|
st_stylable_base_finalize (gpointer g_iface)
|
|
{
|
|
GList *list, *node;
|
|
|
|
list = g_param_spec_pool_list_owned (style_property_spec_pool,
|
|
G_TYPE_FROM_INTERFACE (g_iface));
|
|
|
|
for (node = list; node; node = node->next)
|
|
{
|
|
GParamSpec *pspec = node->data;
|
|
|
|
g_param_spec_pool_remove (style_property_spec_pool, pspec);
|
|
g_param_spec_unref (pspec);
|
|
}
|
|
|
|
g_list_free (list);
|
|
}
|
|
|
|
static void
|
|
st_stylable_base_init (gpointer g_iface)
|
|
{
|
|
static gboolean initialised = FALSE;
|
|
|
|
if (G_UNLIKELY (!initialised))
|
|
{
|
|
GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
|
|
|
|
initialised = TRUE;
|
|
|
|
quark_real_owner = g_quark_from_static_string ("st-stylable-real-owner-quark");
|
|
quark_style = g_quark_from_static_string ("st-stylable-style-quark");
|
|
|
|
style_property_spec_pool = g_param_spec_pool_new (FALSE);
|
|
|
|
property_notify_context.quark_notify_queue = g_quark_from_static_string ("StStylable-style-property-notify-queue");
|
|
property_notify_context.dispatcher = st_stylable_notify_dispatcher;
|
|
|
|
/**
|
|
* StStylable:style:
|
|
*
|
|
* The #StStyle attached to a stylable object.
|
|
*/
|
|
g_object_interface_install_property (g_iface,
|
|
g_param_spec_object ("style",
|
|
"Style",
|
|
"A style object",
|
|
ST_TYPE_STYLE,
|
|
ST_PARAM_READWRITE));
|
|
|
|
/**
|
|
* StStylable::style-changed:
|
|
* @stylable: the #StStylable that received the signal
|
|
* @old_style: the previously set #StStyle for @stylable
|
|
*
|
|
* The ::style-changed signal is emitted each time one of the style
|
|
* properties have changed.
|
|
*/
|
|
stylable_signals[STYLE_CHANGED] =
|
|
g_signal_new (I_("style-changed"),
|
|
iface_type,
|
|
G_SIGNAL_RUN_FIRST,
|
|
G_STRUCT_OFFSET (StStylableIface, style_changed),
|
|
NULL, NULL,
|
|
_st_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
/**
|
|
* StStylable::stylable-changed:
|
|
* @actor: the actor that received the signal
|
|
*
|
|
* The ::changed signal is emitted each time any of the properties of the
|
|
* stylable has changed.
|
|
*/
|
|
stylable_signals[CHANGED] =
|
|
g_signal_new (I_("stylable-changed"),
|
|
iface_type,
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (StStylableIface, stylable_changed),
|
|
NULL, NULL,
|
|
_st_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
stylable_signals[STYLE_NOTIFY] =
|
|
g_signal_new (I_("style-notify"),
|
|
iface_type,
|
|
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS | G_SIGNAL_ACTION,
|
|
G_STRUCT_OFFSET (StStylableIface, style_notify),
|
|
NULL, NULL,
|
|
_st_marshal_VOID__PARAM,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_PARAM);
|
|
}
|
|
}
|
|
|
|
GType
|
|
st_stylable_get_type (void)
|
|
{
|
|
static GType our_type = 0;
|
|
|
|
if (G_UNLIKELY (our_type == 0))
|
|
{
|
|
GTypeInfo stylable_info = {
|
|
sizeof (StStylableIface),
|
|
st_stylable_base_init,
|
|
st_stylable_base_finalize
|
|
};
|
|
|
|
our_type = g_type_register_static (G_TYPE_INTERFACE,
|
|
I_("StStylable"),
|
|
&stylable_info, 0);
|
|
}
|
|
|
|
return our_type;
|
|
}
|
|
|
|
void
|
|
st_stylable_freeze_notify (StStylable *stylable)
|
|
{
|
|
g_return_if_fail (ST_IS_STYLABLE (stylable));
|
|
|
|
g_object_ref (stylable);
|
|
g_object_notify_queue_freeze (G_OBJECT (stylable), &property_notify_context);
|
|
g_object_unref (stylable);
|
|
}
|
|
|
|
void
|
|
st_stylable_thaw_notify (StStylable *stylable)
|
|
{
|
|
GObjectNotifyQueue *nqueue;
|
|
|
|
g_return_if_fail (ST_IS_STYLABLE (stylable));
|
|
|
|
g_object_ref (stylable);
|
|
|
|
nqueue = g_object_notify_queue_from_object (G_OBJECT (stylable),
|
|
&property_notify_context);
|
|
|
|
if (!nqueue || !nqueue->freeze_count)
|
|
g_warning ("%s: property-changed notification for %s(%p) is not frozen",
|
|
G_STRFUNC, G_OBJECT_TYPE_NAME (stylable), stylable);
|
|
else
|
|
g_object_notify_queue_thaw (G_OBJECT (stylable), nqueue);
|
|
|
|
g_object_unref (stylable);
|
|
}
|
|
|
|
void
|
|
st_stylable_notify (StStylable *stylable,
|
|
const gchar *property_name)
|
|
{
|
|
GParamSpec *pspec;
|
|
|
|
g_return_if_fail (ST_IS_STYLABLE (stylable));
|
|
g_return_if_fail (property_name != NULL);
|
|
|
|
g_object_ref (stylable);
|
|
|
|
pspec = g_param_spec_pool_lookup (style_property_spec_pool,
|
|
property_name,
|
|
G_OBJECT_TYPE (stylable),
|
|
TRUE);
|
|
|
|
if (!pspec)
|
|
g_warning ("%s: object class `%s' has no style property named `%s'",
|
|
G_STRFUNC,
|
|
G_OBJECT_TYPE_NAME (stylable),
|
|
property_name);
|
|
else
|
|
{
|
|
GObjectNotifyQueue *nqueue;
|
|
|
|
nqueue = g_object_notify_queue_freeze (G_OBJECT (stylable),
|
|
&property_notify_context);
|
|
g_object_notify_queue_add (G_OBJECT (stylable), nqueue, pspec);
|
|
g_object_notify_queue_thaw (G_OBJECT (stylable), nqueue);
|
|
}
|
|
|
|
g_object_unref (stylable);
|
|
}
|
|
|
|
/**
|
|
* st_stylable_iface_install_property:
|
|
* @iface: a #StStylableIface
|
|
* @owner_type: #GType of the style property owner
|
|
* @pspec: a #GParamSpec
|
|
*
|
|
* Installs a property for @owner_type using @pspec as the property
|
|
* description.
|
|
*
|
|
* This function should be used inside the #StStylableIface initialization
|
|
* function of a class, for instance:
|
|
*
|
|
* <informalexample><programlisting>
|
|
* G_DEFINE_TYPE_WITH_CODE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR,
|
|
* G_IMPLEMENT_INTERFACE (ST_TYPE_STYLABLE,
|
|
* st_stylable_init));
|
|
* ...
|
|
* static void
|
|
* st_stylable_init (StStylableIface *iface)
|
|
* {
|
|
* static gboolean is_initialized = FALSE;
|
|
*
|
|
* if (!is_initialized)
|
|
* {
|
|
* ...
|
|
* st_stylable_iface_install_property (stylable,
|
|
* FOO_TYPE_ACTOR,
|
|
* g_param_spec_int ("x-spacing",
|
|
* "X Spacing",
|
|
* "Horizontal spacing",
|
|
* -1, G_MAXINT,
|
|
* 2,
|
|
* G_PARAM_READWRITE));
|
|
* ...
|
|
* }
|
|
* }
|
|
* </programlisting></informalexample>
|
|
*/
|
|
void
|
|
st_stylable_iface_install_property (StStylableIface *iface,
|
|
GType owner_type,
|
|
GParamSpec *pspec)
|
|
{
|
|
g_return_if_fail (ST_IS_STYLABLE_IFACE (iface));
|
|
g_return_if_fail (owner_type != G_TYPE_INVALID);
|
|
g_return_if_fail (G_IS_PARAM_SPEC (pspec));
|
|
g_return_if_fail (pspec->flags & G_PARAM_READABLE);
|
|
g_return_if_fail (!(pspec->flags & (G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT
|
|
)));
|
|
|
|
if (g_param_spec_pool_lookup (style_property_spec_pool, pspec->name,
|
|
owner_type,
|
|
FALSE))
|
|
{
|
|
g_warning ("%s: class `%s' already contains a style property named `%s'",
|
|
G_STRLOC,
|
|
g_type_name (owner_type),
|
|
pspec->name);
|
|
return;
|
|
}
|
|
|
|
g_param_spec_ref_sink (pspec);
|
|
g_param_spec_set_qdata_full (pspec, quark_real_owner,
|
|
g_strdup (g_type_name (owner_type)),
|
|
g_free);
|
|
|
|
g_param_spec_pool_insert (style_property_spec_pool,
|
|
pspec,
|
|
owner_type);
|
|
}
|
|
|
|
/**
|
|
* st_stylable_list_properties:
|
|
* @stylable: a #StStylable
|
|
* @n_props: return location for the number of properties, or %NULL
|
|
*
|
|
* Retrieves all the #GParamSpec<!-- -->s installed by @stylable.
|
|
*
|
|
* Return value: an array of #GParamSpec<!-- -->s. Free it with
|
|
* g_free() when done.
|
|
*/
|
|
GParamSpec **
|
|
st_stylable_list_properties (StStylable *stylable,
|
|
guint *n_props)
|
|
{
|
|
GParamSpec **pspecs = NULL;
|
|
guint n;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
pspecs = g_param_spec_pool_list (style_property_spec_pool,
|
|
G_OBJECT_TYPE (stylable),
|
|
&n);
|
|
if (n_props)
|
|
*n_props = n;
|
|
|
|
return pspecs;
|
|
}
|
|
|
|
/**
|
|
* st_stylable_find_property:
|
|
* @stylable: a #StStylable
|
|
* @property_name: the name of the property to find
|
|
*
|
|
* Finds the #GParamSpec installed by @stylable for the property
|
|
* with @property_name.
|
|
*
|
|
* Return value: a #GParamSpec for the given property, or %NULL if
|
|
* no property with that name was found
|
|
*/
|
|
GParamSpec *
|
|
st_stylable_find_property (StStylable *stylable,
|
|
const gchar *property_name)
|
|
{
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
g_return_val_if_fail (property_name != NULL, NULL);
|
|
|
|
return g_param_spec_pool_lookup (style_property_spec_pool,
|
|
property_name,
|
|
G_OBJECT_TYPE (stylable),
|
|
TRUE);
|
|
}
|
|
|
|
static inline void
|
|
st_stylable_get_property_internal (StStylable *stylable,
|
|
GParamSpec *pspec,
|
|
GValue *value)
|
|
{
|
|
StStyle *style;
|
|
GValue real_value = { 0, };
|
|
|
|
style = st_stylable_get_style (stylable);
|
|
|
|
if (!style)
|
|
{
|
|
g_value_reset (value);
|
|
return;
|
|
}
|
|
|
|
st_style_get_property (style, stylable, pspec, &real_value);
|
|
|
|
g_value_copy (&real_value, value);
|
|
g_value_unset (&real_value);
|
|
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_property:
|
|
* @stylable: a #StStylable
|
|
* @property_name: the name of the property
|
|
* @value: return location for an empty #GValue
|
|
*
|
|
* Retrieves the value of @property_name for @stylable, and puts it
|
|
* into @value.
|
|
*/
|
|
void
|
|
st_stylable_get_property (StStylable *stylable,
|
|
const gchar *property_name,
|
|
GValue *value)
|
|
{
|
|
GParamSpec *pspec;
|
|
|
|
g_return_if_fail (ST_IS_STYLABLE (stylable));
|
|
g_return_if_fail (property_name != NULL);
|
|
g_return_if_fail (value != NULL);
|
|
|
|
pspec = st_stylable_find_property (stylable, property_name);
|
|
if (!pspec)
|
|
{
|
|
g_warning ("Stylable class `%s' doesn't have a property named `%s'",
|
|
g_type_name (G_OBJECT_TYPE (stylable)),
|
|
property_name);
|
|
return;
|
|
}
|
|
|
|
if (!(pspec->flags & G_PARAM_READABLE))
|
|
{
|
|
g_warning ("Style property `%s' of class `%s' is not readable",
|
|
pspec->name,
|
|
g_type_name (G_OBJECT_TYPE (stylable)));
|
|
return;
|
|
}
|
|
|
|
if (G_VALUE_TYPE (value) != G_PARAM_SPEC_VALUE_TYPE (pspec))
|
|
{
|
|
g_warning ("Passed value is not of the requested type `%s' for "
|
|
"the style property `%s' of class `%s'",
|
|
g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
|
|
pspec->name,
|
|
g_type_name (G_OBJECT_TYPE (stylable)));
|
|
return;
|
|
}
|
|
|
|
st_stylable_get_property_internal (stylable, pspec, value);
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get:
|
|
* @stylable: a #StStylable
|
|
* @first_property_name: name of the first property to get
|
|
* @Varargs: return location for the first property, followed optionally
|
|
* by more name/return location pairs, followed by %NULL
|
|
*
|
|
* Gets the style properties for @stylable.
|
|
*
|
|
* In general, a copy is made of the property contents and the called
|
|
* is responsible for freeing the memory in the appropriate manner for
|
|
* the property type.
|
|
*
|
|
* <example>
|
|
* <title>Using st_stylable_get(<!-- -->)</title>
|
|
* <para>An example of using st_stylable_get() to get the contents of
|
|
* two style properties - one of type #G_TYPE_INT and one of type
|
|
* #CLUTTER_TYPE_COLOR:</para>
|
|
* <programlisting>
|
|
* gint x_spacing;
|
|
* ClutterColor *bg_color;
|
|
*
|
|
* st_stylable_get (stylable,
|
|
* "x-spacing", &x_spacing,
|
|
* "bg-color", &bg_color,
|
|
* NULL);
|
|
*
|
|
* /<!-- -->* do something with x_spacing and bg_color *<!-- -->/
|
|
*
|
|
* clutter_color_free (bg_color);
|
|
* </programlisting>
|
|
* </example>
|
|
*/
|
|
void
|
|
st_stylable_get (StStylable *stylable,
|
|
const gchar *first_property_name,
|
|
...)
|
|
{
|
|
StStyle *style;
|
|
va_list args;
|
|
|
|
g_return_if_fail (ST_IS_STYLABLE (stylable));
|
|
g_return_if_fail (first_property_name != NULL);
|
|
|
|
style = st_stylable_get_style (stylable);
|
|
|
|
va_start (args, first_property_name);
|
|
st_style_get_valist (style, stylable, first_property_name, args);
|
|
va_end (args);
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_default_value:
|
|
* @stylable: a #StStylable
|
|
* @property_name: name of the property to query
|
|
* @value_out: return location for the default value
|
|
*
|
|
* Query @stylable for the default value of property @property_name and
|
|
* fill @value_out with the result.
|
|
*
|
|
* Returns: %TRUE if property @property_name exists and the default value has
|
|
* been returned.
|
|
*/
|
|
gboolean
|
|
st_stylable_get_default_value (StStylable *stylable,
|
|
const gchar *property_name,
|
|
GValue *value_out)
|
|
{
|
|
GParamSpec *pspec;
|
|
|
|
pspec = st_stylable_find_property (stylable, property_name);
|
|
if (!pspec)
|
|
{
|
|
g_warning ("%s: no style property named `%s' found for class `%s'",
|
|
G_STRLOC,
|
|
property_name,
|
|
g_type_name (G_OBJECT_TYPE (stylable)));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(pspec->flags & G_PARAM_READABLE))
|
|
{
|
|
g_warning ("Style property `%s' of class `%s' is not readable",
|
|
pspec->name,
|
|
g_type_name (G_OBJECT_TYPE (stylable)));
|
|
return FALSE;
|
|
}
|
|
|
|
g_value_init (value_out, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
|
g_param_value_set_default (pspec, value_out);
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_style:
|
|
* @stylable: a #StStylable
|
|
*
|
|
* Retrieves the #StStyle used by @stylable. This function does not
|
|
* alter the reference count of the returned object.
|
|
*
|
|
* Return value: a #StStyle
|
|
*/
|
|
StStyle *
|
|
st_stylable_get_style (StStylable *stylable)
|
|
{
|
|
StStylableIface *iface;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
if (iface->get_style)
|
|
return iface->get_style (stylable);
|
|
|
|
return g_object_get_data (G_OBJECT (stylable), "st-stylable-style");
|
|
}
|
|
|
|
/**
|
|
* st_stylable_set_style:
|
|
* @stylable: a #StStylable
|
|
* @style: a #StStyle
|
|
*
|
|
* Sets @style as the new #StStyle to be used by @stylable.
|
|
*
|
|
* The #StStylable will take ownership of the passed #StStyle.
|
|
*
|
|
* After the #StStle has been set, the StStylable::style-set signal
|
|
* will be emitted.
|
|
*/
|
|
void
|
|
st_stylable_set_style (StStylable *stylable,
|
|
StStyle *style)
|
|
{
|
|
StStylableIface *iface;
|
|
StStyle *old_style;
|
|
|
|
g_return_if_fail (ST_IS_STYLABLE (stylable));
|
|
g_return_if_fail (ST_IS_STYLE (style));
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
|
|
old_style = st_stylable_get_style (stylable);
|
|
g_object_ref (old_style);
|
|
|
|
if (iface->set_style)
|
|
iface->set_style (stylable, style);
|
|
else
|
|
{
|
|
g_object_set_qdata_full (G_OBJECT (stylable),
|
|
quark_style,
|
|
g_object_ref_sink (style),
|
|
g_object_unref);
|
|
}
|
|
|
|
g_signal_emit (stylable, stylable_signals[STYLE_CHANGED], 0, old_style);
|
|
g_object_unref (old_style);
|
|
|
|
g_object_notify (G_OBJECT (stylable), "style");
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_container:
|
|
* @stylable: a #StStylable
|
|
*
|
|
* Obtain the parent #StStylable that contains @stylable.
|
|
*
|
|
* Return value: The parent #StStylable
|
|
*/
|
|
StStylable*
|
|
st_stylable_get_container (StStylable *stylable)
|
|
{
|
|
StStylableIface *iface;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
|
|
if (iface->get_container)
|
|
return iface->get_container (stylable);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_base_style:
|
|
* @stylable: a #StStylable
|
|
*
|
|
* Get the parent ancestor #StStylable of @stylable.
|
|
*
|
|
* Return value: the parent #StStylable
|
|
*/
|
|
StStylable*
|
|
st_stylable_get_base_style (StStylable *stylable)
|
|
{
|
|
StStylableIface *iface;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
|
|
if (iface->get_base_style)
|
|
return iface->get_base_style (stylable);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* st_stylable_get_style_id:
|
|
* @stylable: a #StStylable
|
|
*
|
|
* Get the ID value of @stylable
|
|
*
|
|
* Return value: the id of @stylable
|
|
*/
|
|
const gchar*
|
|
st_stylable_get_style_id (StStylable *stylable)
|
|
{
|
|
StStylableIface *iface;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
|
|
if (iface->get_style_id)
|
|
return iface->get_style_id (stylable);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_style_type:
|
|
* @stylable: a #StStylable
|
|
*
|
|
* Get the type name of @stylable
|
|
*
|
|
* Return value: the type name of @stylable
|
|
*/
|
|
const gchar*
|
|
st_stylable_get_style_type (StStylable *stylable)
|
|
{
|
|
StStylableIface *iface;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
|
|
if (iface->get_style_type)
|
|
return iface->get_style_type (stylable);
|
|
else
|
|
return G_OBJECT_TYPE_NAME (stylable);
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_style_class:
|
|
* @stylable: a #StStylable
|
|
*
|
|
* Get the style class name of @stylable
|
|
*
|
|
* Return value: the type name of @stylable
|
|
*/
|
|
const gchar*
|
|
st_stylable_get_style_class (StStylable *stylable)
|
|
{
|
|
StStylableIface *iface;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
|
|
if (iface->get_style_class)
|
|
return iface->get_style_class (stylable);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_pseudo_class:
|
|
* @stylable: a #StStylable
|
|
*
|
|
* Get the pseudo class name of @stylable
|
|
*
|
|
* Return value: the pseudo class name of @stylable
|
|
*/
|
|
const gchar*
|
|
st_stylable_get_pseudo_class (StStylable *stylable)
|
|
{
|
|
StStylableIface *iface;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
|
|
if (iface->get_pseudo_class)
|
|
return iface->get_pseudo_class (stylable);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_attribute:
|
|
* @stylable: a #StStylable
|
|
* @name: attribute name
|
|
*
|
|
* Get the named attribute from @stylable
|
|
*
|
|
* Return value: the value of the attribute
|
|
*/
|
|
gchar*
|
|
st_stylable_get_attribute (StStylable *stylable,
|
|
const gchar *name)
|
|
{
|
|
StStylableIface *iface;
|
|
GValue value = { 0, };
|
|
GValue string_value = { 0, };
|
|
gchar *ret;
|
|
GParamSpec *pspec;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), NULL);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
|
|
if (iface->get_attribute)
|
|
return iface->get_attribute (stylable, name);
|
|
|
|
/* look up a generic gobject property */
|
|
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (stylable), name);
|
|
|
|
/* if no such property exists, return NULL */
|
|
if (pspec == NULL)
|
|
return NULL;
|
|
|
|
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
|
g_object_get_property (G_OBJECT (stylable), name, &value);
|
|
|
|
g_value_init (&string_value, G_TYPE_STRING);
|
|
if (g_value_transform (&value, &string_value))
|
|
ret = g_strdup (g_value_get_string (&string_value));
|
|
else
|
|
ret = NULL;
|
|
|
|
g_value_unset (&value);
|
|
g_value_unset (&string_value);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* st_stylable_get_viewport:
|
|
* @stylable: a #StStylable
|
|
* @x: location to store X coordinate
|
|
* @y: location to store Y coordinate
|
|
* @width: location to store width
|
|
* @height: location to store height
|
|
*
|
|
* Obtain the position and dimensions of @stylable.
|
|
*
|
|
* Return value: true if the function succeeded
|
|
*/
|
|
gboolean
|
|
st_stylable_get_viewport (StStylable *stylable,
|
|
gint *x,
|
|
gint *y,
|
|
gint *width,
|
|
gint *height)
|
|
{
|
|
StStylableIface *iface;
|
|
|
|
g_return_val_if_fail (ST_IS_STYLABLE (stylable), FALSE);
|
|
|
|
iface = ST_STYLABLE_GET_IFACE (stylable);
|
|
if (iface->get_viewport)
|
|
return iface->get_viewport (stylable, x, y, width, height);
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/**
|
|
* st_stylable_changed:
|
|
* @stylable: A #StStylable
|
|
*
|
|
* Emit the "stylable-changed" signal on @stylable
|
|
*/
|
|
void
|
|
st_stylable_changed (StStylable *stylable)
|
|
{
|
|
g_signal_emit (stylable, stylable_signals[CHANGED], 0, NULL);
|
|
}
|