gnome-shell/src/st/st-label.c
Owen W. Taylor 2077485827 Port our imported parts of Mx to ShellTheme
ShellTheme replaces both StStyle and ccss_stylesheet_t.

The interface StStylable is replaced by usage of ShellThemeNode.
A concrete node class allows some significant optimizations of property
inheritance that would have been much more difficult to achieve with
the highly abstract pair of StStylable and ccss_node_t.

Some operations that were previously on StStylable (like the
::style-changed signal) are directly on NtkWidget.

Custom properties are no longer registered as param-specs; instead you
call directly into shell theme node to look up a length or color:

shell_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing);

The dependency on libccss is dropped, while preserving all existing
functionality and adding proper parsing and inheritance of font properties
and proper inheritance for the 'color' property.

Some more javascript tests for CSS functionality are added; workarounds for
a CSS bug where *.some-class was needed instead of .some-class are removed.

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-09-29 19:58:29 -04:00

344 lines
8.9 KiB
C

/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* 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"
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;
StThemeNode *theme_node;
ClutterColor color;
const PangoFontDescription *font;
gchar *font_string;
priv = ST_LABEL (self)->priv;
theme_node = st_widget_get_theme_node (self);
st_theme_node_get_foreground_color (theme_node, &color);
clutter_text_set_color (CLUTTER_TEXT (priv->label), &color);
font = st_theme_node_get_font (theme_node);
font_string = pango_font_description_to_string (font);
clutter_text_set_font_name (CLUTTER_TEXT (priv->label), font_string);
g_free (font_string);
ST_WIDGET_CLASS (st_label_parent_class)->style_changed (self);
}
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);
StWidgetClass *widget_class = ST_WIDGET_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;
widget_class->style_changed = st_label_style_changed;
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));
}
/**
* 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: (transfer none): ethe #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;
}