/* * Copyright (C) 2008 Pierre-Luc Beaudoin * Copyright (C) 2011-2013 Jiri Techet * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION:champlain-label * @short_description: A label to identify points of interest on a map * * Markers reprensent points of interest on a map. Markers need to be placed on * a layer (a #ChamplainMarkerLayer). Layers have to be added to a #ChamplainView for * the markers to show on the map. * * A marker is nothing more than a regular #ClutterActor. You can draw on it * what ever you want. Set the markers position on the map * using #champlain_location_set_location. * * Champlain has a default type of markers with text. To create one, * use #champlain_label_new_with_text. */ #include "config.h" #include "champlain-label.h" #include "champlain.h" #include "champlain-defines.h" #include "champlain-private.h" #include "champlain-tile.h" #include #include #include #include #include #include #include #define DEFAULT_FONT_NAME "Sans 11" #define SLOPE -0.3 #define SCALING 0.65 static ClutterColor DEFAULT_COLOR = { 0x33, 0x33, 0x33, 0xff }; static ClutterColor DEFAULT_TEXT_COLOR = { 0xee, 0xee, 0xee, 0xff }; enum { /* normal signals */ LAST_SIGNAL }; enum { PROP_0, PROP_IMAGE, PROP_TEXT, PROP_USE_MARKUP, PROP_ALIGNMENT, PROP_ATTRIBUTES, PROP_ELLIPSIZE, PROP_COLOR, PROP_TEXT_COLOR, PROP_FONT_NAME, PROP_WRAP, PROP_WRAP_MODE, PROP_SINGLE_LINE_MODE, PROP_DRAW_BACKGROUND, PROP_DRAW_SHADOW }; /* static guint champlain_label_signals[LAST_SIGNAL] = { 0, }; */ struct _ChamplainLabelPrivate { gchar *text; ClutterActor *image; gboolean use_markup; PangoAlignment alignment; PangoAttrList *attributes; ClutterColor *color; ClutterColor *text_color; gchar *font_name; gboolean wrap; PangoWrapMode wrap_mode; gboolean single_line_mode; PangoEllipsizeMode ellipsize; gboolean draw_background; gboolean draw_shadow; guint redraw_id; gint total_width; gint total_height; gint point; }; G_DEFINE_TYPE_WITH_PRIVATE (ChamplainLabel, champlain_label, CHAMPLAIN_TYPE_MARKER) static void draw_label (ChamplainLabel *label); static void champlain_label_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { ChamplainLabelPrivate *priv = CHAMPLAIN_LABEL (object)->priv; switch (prop_id) { case PROP_TEXT: g_value_set_string (value, priv->text); break; case PROP_IMAGE: g_value_set_object (value, priv->image); break; case PROP_USE_MARKUP: g_value_set_boolean (value, priv->use_markup); break; case PROP_ALIGNMENT: g_value_set_enum (value, priv->alignment); break; case PROP_COLOR: clutter_value_set_color (value, priv->color); break; case PROP_TEXT_COLOR: clutter_value_set_color (value, priv->text_color); break; case PROP_FONT_NAME: g_value_set_string (value, priv->font_name); break; case PROP_WRAP: g_value_set_boolean (value, priv->wrap); break; case PROP_WRAP_MODE: g_value_set_enum (value, priv->wrap_mode); break; case PROP_DRAW_BACKGROUND: g_value_set_boolean (value, priv->draw_background); break; case PROP_DRAW_SHADOW: g_value_set_boolean (value, priv->draw_shadow); break; case PROP_ELLIPSIZE: g_value_set_enum (value, priv->ellipsize); break; case PROP_SINGLE_LINE_MODE: g_value_set_enum (value, priv->single_line_mode); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void champlain_label_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { ChamplainLabel *label = CHAMPLAIN_LABEL (object); switch (prop_id) { case PROP_TEXT: champlain_label_set_text (label, g_value_get_string (value)); break; case PROP_IMAGE: champlain_label_set_image (label, g_value_get_object (value)); break; case PROP_USE_MARKUP: champlain_label_set_use_markup (label, g_value_get_boolean (value)); break; case PROP_ALIGNMENT: champlain_label_set_alignment (label, g_value_get_enum (value)); break; case PROP_COLOR: champlain_label_set_color (label, clutter_value_get_color (value)); break; case PROP_TEXT_COLOR: champlain_label_set_text_color (label, clutter_value_get_color (value)); break; case PROP_FONT_NAME: champlain_label_set_font_name (label, g_value_get_string (value)); break; case PROP_WRAP: champlain_label_set_wrap (label, g_value_get_boolean (value)); break; case PROP_WRAP_MODE: champlain_label_set_wrap_mode (label, g_value_get_enum (value)); break; case PROP_ELLIPSIZE: champlain_label_set_ellipsize (label, g_value_get_enum (value)); break; case PROP_DRAW_BACKGROUND: champlain_label_set_draw_background (label, g_value_get_boolean (value)); break; case PROP_DRAW_SHADOW: champlain_label_set_draw_shadow (label, g_value_get_boolean (value)); break; case PROP_SINGLE_LINE_MODE: champlain_label_set_single_line_mode (label, g_value_get_boolean (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } #define RADIUS 10 #define PADDING (RADIUS / 2) static void pick (ClutterActor *self, const ClutterColor *color) { ChamplainLabelPrivate *priv = CHAMPLAIN_LABEL (self)->priv; gfloat width, height; if (!clutter_actor_should_pick_paint (self)) return; width = priv->total_width; height = priv->total_height; cogl_path_new (); cogl_set_source_color4ub (color->red, color->green, color->blue, color->alpha); cogl_path_move_to (RADIUS, 0); cogl_path_line_to (width - RADIUS, 0); cogl_path_arc (width - RADIUS, RADIUS, RADIUS, RADIUS, -90, 0); cogl_path_line_to (width, height - RADIUS); cogl_path_arc (width - RADIUS, height - RADIUS, RADIUS, RADIUS, 0, 90); cogl_path_line_to (RADIUS, height); cogl_path_arc (RADIUS, height - RADIUS, RADIUS, RADIUS, 90, 180); cogl_path_line_to (0, RADIUS); cogl_path_arc (RADIUS, RADIUS, RADIUS, RADIUS, 180, 270); cogl_path_close (); cogl_path_fill (); } static void champlain_label_dispose (GObject *object) { ChamplainLabelPrivate *priv = CHAMPLAIN_LABEL (object)->priv; if (priv->image) { clutter_actor_destroy (priv->image); priv->image = NULL; } if (priv->attributes) { pango_attr_list_unref (priv->attributes); priv->attributes = NULL; } G_OBJECT_CLASS (champlain_label_parent_class)->dispose (object); } static void champlain_label_finalize (GObject *object) { ChamplainLabelPrivate *priv = CHAMPLAIN_LABEL (object)->priv; if (priv->text) { g_free (priv->text); priv->text = NULL; } if (priv->font_name) { g_free (priv->font_name); priv->font_name = NULL; } if (priv->color) { clutter_color_free (priv->color); priv->color = NULL; } if (priv->text_color) { clutter_color_free (priv->text_color); priv->text_color = NULL; } if (priv->redraw_id) { g_source_remove (priv->redraw_id); priv->redraw_id = 0; } G_OBJECT_CLASS (champlain_label_parent_class)->finalize (object); } static void champlain_label_class_init (ChamplainLabelClass *klass) { ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = champlain_label_finalize; object_class->dispose = champlain_label_dispose; object_class->get_property = champlain_label_get_property; object_class->set_property = champlain_label_set_property; actor_class->pick = pick; /** * ChamplainLabel:text: * * The text of the label * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_TEXT, g_param_spec_string ("text", "Text", "The text of the label", "", CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:image: * * The image of the label * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_IMAGE, g_param_spec_object ("image", "Image", "The image of the label", CLUTTER_TYPE_ACTOR, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:use-markup: * * If the label's text uses markup * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_USE_MARKUP, g_param_spec_boolean ("use-markup", "Use Markup", "The text uses markup", FALSE, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:alignment: * * The label's alignment * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_ALIGNMENT, g_param_spec_enum ("alignment", "Alignment", "The label's alignment", PANGO_TYPE_ALIGNMENT, PANGO_ALIGN_LEFT, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:color: * * The label's color * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_COLOR, clutter_param_spec_color ("color", "Color", "The label's color", &DEFAULT_COLOR, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:text-color: * * The label's text color * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_TEXT_COLOR, clutter_param_spec_color ("text-color", "Text Color", "The label's text color", &DEFAULT_TEXT_COLOR, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:font-name: * * The label's text font name * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_FONT_NAME, g_param_spec_string ("font-name", "Font Name", "The label's text font name", "Sans 11", CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:wrap: * * If the label's text wrap is set * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_WRAP, g_param_spec_boolean ("wrap", "Wrap", "The label's text wrap", FALSE, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:wrap-mode: * * The label's text wrap mode * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_WRAP_MODE, g_param_spec_enum ("wrap-mode", "Wrap Mode", "The label's text wrap mode", PANGO_TYPE_WRAP_MODE, PANGO_WRAP_WORD, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:ellipsize: * * The label's ellipsize mode * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_ELLIPSIZE, g_param_spec_enum ("ellipsize", "Ellipsize Mode", "The label's text ellipsize mode", PANGO_TYPE_ELLIPSIZE_MODE, PANGO_ELLIPSIZE_NONE, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:draw-background: * * If the label has a background * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_DRAW_BACKGROUND, g_param_spec_boolean ("draw-background", "Draw Background", "The label has a background", TRUE, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:draw-shadow: * * If the label background has a shadow * * Since: 0.12.10 */ g_object_class_install_property (object_class, PROP_DRAW_SHADOW, g_param_spec_boolean ("draw-shadow", "Draw Shadow", "The label background has a shadow", TRUE, CHAMPLAIN_PARAM_READWRITE)); /** * ChamplainLabel:single-line-mode: * * If the label is in single line mode * * Since: 0.10 */ g_object_class_install_property (object_class, PROP_SINGLE_LINE_MODE, g_param_spec_boolean ("single-line-mode", "Single Line Mode", "The label's single line mode", TRUE, CHAMPLAIN_PARAM_READWRITE)); } static void draw_box (cairo_t *cr, gint width, gint height, gint point, gboolean mirror) { if (mirror) { cairo_move_to (cr, RADIUS, 0); cairo_line_to (cr, width - RADIUS, 0); cairo_arc (cr, width - RADIUS, RADIUS, RADIUS - 1, 3 * M_PI / 2.0, 0); cairo_line_to (cr, width, height - RADIUS); cairo_arc (cr, width - RADIUS, height - RADIUS, RADIUS - 1, 0, M_PI / 2.0); cairo_line_to (cr, point, height); cairo_line_to (cr, 0, height + point); cairo_arc (cr, RADIUS, RADIUS, RADIUS - 1, M_PI, 3 * M_PI / 2.0); cairo_close_path (cr); } else { cairo_move_to (cr, RADIUS, 0); cairo_line_to (cr, width - RADIUS, 0); cairo_arc (cr, width - RADIUS, RADIUS, RADIUS - 1, 3 * M_PI / 2.0, 0); cairo_line_to (cr, width, height + point); cairo_line_to (cr, width - point, height); cairo_line_to (cr, RADIUS, height); cairo_arc (cr, RADIUS, height - RADIUS, RADIUS - 1, M_PI / 2.0, M_PI); cairo_line_to (cr, 0, RADIUS); cairo_arc (cr, RADIUS, RADIUS, RADIUS - 1, M_PI, 3 * M_PI / 2.0); cairo_close_path (cr); } } static gint get_shadow_slope_width (ChamplainLabel *label) { ChamplainLabelPrivate *priv = label->priv; gint x; if (priv->alignment == PANGO_ALIGN_LEFT) x = -40 * SLOPE; else x = -58 * SLOPE; return x; } static gboolean draw_shadow (ClutterCanvas *canvas, cairo_t *cr, int width, int height, ChamplainLabel *label) { ChamplainLabelPrivate *priv = label->priv; gint x; cairo_matrix_t matrix; x = get_shadow_slope_width (label); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_matrix_init (&matrix, 1, 0, SLOPE, SCALING, x, 0); cairo_set_matrix (cr, &matrix); draw_box (cr, width - x, height - priv->point, priv->point, priv->alignment == PANGO_ALIGN_LEFT); cairo_set_source_rgba (cr, 0, 0, 0, 0.15); cairo_fill (cr); return TRUE; } static gboolean draw_background (ClutterCanvas *canvas, cairo_t *cr, int width, int height, ChamplainLabel *label) { ChamplainLabelPrivate *priv = label->priv; ChamplainMarker *marker = CHAMPLAIN_MARKER (label); const ClutterColor *color; ClutterColor darker_color; cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); /* If selected, add the selection color to the marker's color */ if (champlain_marker_get_selected (marker)) color = champlain_marker_get_selection_color (); else color = priv->color; draw_box (cr, width, height - priv->point, priv->point, priv->alignment == PANGO_ALIGN_LEFT); clutter_color_darken (color, &darker_color); cairo_set_source_rgba (cr, color->red / 255.0, color->green / 255.0, color->blue / 255.0, color->alpha / 255.0); cairo_fill_preserve (cr); cairo_set_line_width (cr, 1.0); cairo_set_source_rgba (cr, darker_color.red / 255.0, darker_color.green / 255.0, darker_color.blue / 255.0, darker_color.alpha / 255.0); cairo_stroke (cr); return TRUE; } static void draw_label (ChamplainLabel *label) { ChamplainLabelPrivate *priv = label->priv; ChamplainMarker *marker = CHAMPLAIN_MARKER (label); gint height = 0; gint total_width = 0, total_height = 0; ClutterActor *text_actor, *shadow, *background; text_actor = NULL; shadow = NULL; background = NULL; clutter_actor_remove_all_children (CLUTTER_ACTOR (label)); if (priv->image != NULL) { clutter_actor_set_position (priv->image, PADDING, PADDING); total_width = clutter_actor_get_width (priv->image) + 2 * PADDING; total_height = clutter_actor_get_height (priv->image) + 2 * PADDING; clutter_actor_add_child (CLUTTER_ACTOR (label), priv->image); } if (priv->text != NULL && strlen (priv->text) > 0) { ClutterText *text; text_actor = clutter_text_new_with_text (priv->font_name, priv->text); text = CLUTTER_TEXT (text_actor); clutter_text_set_font_name (text, priv->font_name); clutter_text_set_text (text, priv->text); clutter_text_set_line_alignment (text, priv->alignment); clutter_text_set_line_wrap (text, priv->wrap); clutter_text_set_line_wrap_mode (text, priv->wrap_mode); clutter_text_set_ellipsize (text, priv->ellipsize); clutter_text_set_attributes (text, priv->attributes); clutter_text_set_use_markup (text, priv->use_markup); height = clutter_actor_get_height (text_actor); if (priv->image != NULL) { clutter_actor_set_position (text_actor, total_width, (total_height - height) / 2.0); total_width += clutter_actor_get_width (text_actor) + 2 * PADDING; } else { clutter_actor_set_position (text_actor, 2 * PADDING, PADDING); total_width += clutter_actor_get_width (text_actor) + 4 * PADDING; } height += 2 * PADDING; total_height = MAX (total_height, height); clutter_text_set_color (text, (champlain_marker_get_selected (marker) ? champlain_marker_get_selection_text_color () : priv->text_color)); clutter_actor_add_child (CLUTTER_ACTOR (label), text_actor); } if (text_actor == NULL && priv->image == NULL) { total_width = 6 * PADDING; total_height = 6 * PADDING; } priv->point = (total_height + 2 * PADDING) / 4.0; priv->total_width = total_width; priv->total_height = total_height; if (priv->draw_background) { ClutterContent *canvas; canvas = clutter_canvas_new (); clutter_canvas_set_size (CLUTTER_CANVAS (canvas), total_width, total_height + priv->point); g_signal_connect (canvas, "draw", G_CALLBACK (draw_background), label); background = clutter_actor_new (); clutter_actor_set_size (background, total_width, total_height + priv->point); clutter_actor_set_content (background, canvas); clutter_actor_add_child (CLUTTER_ACTOR (label), background); clutter_content_invalidate (canvas); g_object_unref (canvas); if (priv->draw_shadow) { canvas = clutter_canvas_new (); clutter_canvas_set_size (CLUTTER_CANVAS (canvas), total_width + get_shadow_slope_width (label), total_height + priv->point); g_signal_connect (canvas, "draw", G_CALLBACK (draw_shadow), label); shadow = clutter_actor_new (); clutter_actor_set_size (shadow, total_width + get_shadow_slope_width (label), total_height + priv->point); clutter_actor_set_content (shadow, canvas); clutter_actor_add_child (CLUTTER_ACTOR (label), shadow); clutter_actor_set_position (shadow, 0, total_height / 2.0); clutter_content_invalidate (canvas); g_object_unref (canvas); } } if (text_actor != NULL && background != NULL) clutter_actor_set_child_above_sibling (CLUTTER_ACTOR (label), text_actor, background); if (priv->image != NULL && background != NULL) clutter_actor_set_child_above_sibling (CLUTTER_ACTOR (label), priv->image, background); if (priv->draw_background) { if (priv->alignment == PANGO_ALIGN_RIGHT) clutter_actor_set_translation (CLUTTER_ACTOR (label), -total_width, -total_height - priv->point, 0); else clutter_actor_set_translation (CLUTTER_ACTOR (label), 0, -total_height - priv->point, 0); } else if (priv->image != NULL) clutter_actor_set_translation (CLUTTER_ACTOR (label), -clutter_actor_get_width (priv->image) / 2.0 - PADDING, -clutter_actor_get_height (priv->image) / 2.0 - PADDING, 0); else if (text_actor != NULL) clutter_actor_set_translation (CLUTTER_ACTOR (label), 0, -clutter_actor_get_height (text_actor) / 2.0, 0); } static gboolean redraw_on_idle (gpointer gobject) { ChamplainLabel *label = CHAMPLAIN_LABEL (gobject); draw_label (label); label->priv->redraw_id = 0; return FALSE; } /* * champlain_label_queue_redraw: * @label: a #ChamplainLabel * * Queue a redraw of the label as soon as possible. This function should not * be used unless you are subclassing ChamplainLabel and adding new properties * that affect the aspect of the label. When they change, call this function * to update the label. * * Since: 0.10 */ static void champlain_label_queue_redraw (ChamplainLabel *label) { ChamplainLabelPrivate *priv = label->priv; if (!priv->redraw_id) { priv->redraw_id = g_idle_add_full (CLUTTER_PRIORITY_REDRAW, (GSourceFunc) redraw_on_idle, g_object_ref (label), (GDestroyNotify) g_object_unref); } } static void notify_selected (GObject *gobject, G_GNUC_UNUSED GParamSpec *pspec, G_GNUC_UNUSED gpointer user_data) { champlain_label_queue_redraw (CHAMPLAIN_LABEL (gobject)); } static void champlain_label_init (ChamplainLabel *label) { ChamplainLabelPrivate *priv = champlain_label_get_instance_private (label); label->priv = priv; priv->text = NULL; priv->image = NULL; priv->use_markup = FALSE; priv->alignment = PANGO_ALIGN_LEFT; priv->attributes = NULL; priv->color = clutter_color_copy (&DEFAULT_COLOR); priv->text_color = clutter_color_copy (&DEFAULT_TEXT_COLOR); priv->font_name = g_strdup (DEFAULT_FONT_NAME); priv->wrap = FALSE; priv->wrap_mode = PANGO_WRAP_WORD; priv->single_line_mode = TRUE; priv->ellipsize = PANGO_ELLIPSIZE_NONE; priv->draw_background = TRUE; priv->draw_shadow = TRUE; priv->redraw_id = 0; priv->total_width = 0; priv->total_height = 0; g_signal_connect (label, "notify::selected", G_CALLBACK (notify_selected), NULL); champlain_label_queue_redraw (label); } /** * champlain_label_new: * * Creates a new instance of #ChamplainLabel. * * Returns: a new #ChamplainLabel ready to be used as a #ClutterActor. * * Since: 0.10 */ ClutterActor * champlain_label_new (void) { return CLUTTER_ACTOR (g_object_new (CHAMPLAIN_TYPE_LABEL, NULL)); } /** * champlain_label_new_with_text: * @text: the text of the label * @font: (allow-none): the font to use to draw the text, for example "Courrier Bold 11", can be NULL * @text_color: (allow-none): a #ClutterColor, the color of the text, can be NULL * @label_color: (allow-none): a #ClutterColor, the color of the label, can be NULL * * Creates a new instance of #ChamplainLabel with text value. * * Returns: a new #ChamplainLabel with a drawn label containing the given text. * * Since: 0.10 */ ClutterActor * champlain_label_new_with_text (const gchar *text, const gchar *font, ClutterColor *text_color, ClutterColor *label_color) { ChamplainLabel *label = CHAMPLAIN_LABEL (champlain_label_new ()); champlain_label_set_text (label, text); if (font != NULL) champlain_label_set_font_name (label, font); if (text_color != NULL) champlain_label_set_text_color (label, text_color); if (label_color != NULL) champlain_label_set_color (label, label_color); return CLUTTER_ACTOR (label); } /** * champlain_label_new_with_image: * @actor: The image as a @ClutterActor. * * Creates a new instance of #ChamplainLabel with image. * * Returns: a new #ChamplainLabel with a drawn label containing the given * image. * * Since: 0.10 */ ClutterActor * champlain_label_new_with_image (ClutterActor *actor) { ChamplainLabel *label = CHAMPLAIN_LABEL (champlain_label_new ()); if (actor != NULL) champlain_label_set_image (label, actor); return CLUTTER_ACTOR (label); } /** * champlain_label_new_from_file: * @filename: The filename of the image. * @error: Return location for an error. * * Creates a new instance of #ChamplainLabel with image loaded from file. * * Returns: a new #ChamplainLabel with a drawn label containing the given * image. * * Since: 0.10 */ ClutterActor * champlain_label_new_from_file (const gchar *filename, GError **error) { ChamplainLabel *label = CHAMPLAIN_LABEL (champlain_label_new ()); ClutterActor *actor; GdkPixbuf *pixbuf; ClutterContent *content; gfloat width, height; if (filename == NULL) return CLUTTER_ACTOR (label); pixbuf = gdk_pixbuf_new_from_file (filename, error); if (pixbuf == NULL) return CLUTTER_ACTOR (label); content = clutter_image_new (); clutter_image_set_data (CLUTTER_IMAGE (content), gdk_pixbuf_get_pixels (pixbuf), gdk_pixbuf_get_has_alpha (pixbuf) ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), gdk_pixbuf_get_rowstride (pixbuf), error); g_object_unref (pixbuf); actor = clutter_actor_new (); clutter_content_get_preferred_size (content, &width, &height); clutter_actor_set_size (actor, width, height); clutter_actor_set_content (actor, content); clutter_content_invalidate (content); g_object_unref (content); champlain_label_set_image (label, actor); return CLUTTER_ACTOR (label); } /** * champlain_label_new_full: * @text: The text of the label * @actor: The image as a @ClutterActor * * Creates a new instance of #ChamplainLabel consisting of a custom #ClutterActor. * * Returns: a new #ChamplainLabel with a drawn label containing the given * image. * * Since: 0.10 */ ClutterActor * champlain_label_new_full (const gchar *text, ClutterActor *actor) { ChamplainLabel *label = CHAMPLAIN_LABEL (champlain_label_new ()); if (actor != NULL) { champlain_label_set_image (label, actor); } champlain_label_set_text (label, text); return CLUTTER_ACTOR (label); } /** * champlain_label_set_text: * @label: a #ChamplainLabel * @text: The new text of the label * * Sets the label's text. * * Since: 0.10 */ void champlain_label_set_text (ChamplainLabel *label, const gchar *text) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); ChamplainLabelPrivate *priv = label->priv; if (priv->text != NULL) g_free (priv->text); priv->text = g_strdup (text); g_object_notify (G_OBJECT (label), "text"); champlain_label_queue_redraw (label); } /** * champlain_label_set_image: * @label: a #ChamplainLabel * @image: (allow-none): The image as a @ClutterActor or NULL to remove the current image. * * Sets the label's image. * * Since: 0.10 */ void champlain_label_set_image (ChamplainLabel *label, ClutterActor *image) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); ChamplainLabelPrivate *priv = label->priv; if (priv->image != NULL) clutter_actor_destroy (priv->image); if (image != NULL) { g_return_if_fail (CLUTTER_IS_ACTOR (image)); priv->image = g_object_ref (image); } else priv->image = image; g_object_notify (G_OBJECT (label), "image"); champlain_label_queue_redraw (label); } /** * champlain_label_set_use_markup: * @label: a #ChamplainLabel * @use_markup: The value * * Sets if the label's text uses markup. * * Since: 0.10 */ void champlain_label_set_use_markup (ChamplainLabel *label, gboolean markup) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); label->priv->use_markup = markup; g_object_notify (G_OBJECT (label), "use-markup"); champlain_label_queue_redraw (label); } /** * champlain_label_set_alignment: * @label: a #ChamplainLabel * @alignment: The label's alignment * * Sets the label's text alignment. * * Since: 0.10 */ void champlain_label_set_alignment (ChamplainLabel *label, PangoAlignment alignment) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); label->priv->alignment = alignment; g_object_notify (G_OBJECT (label), "alignment"); champlain_label_queue_redraw (label); } /** * champlain_label_set_color: * @label: a #ChamplainLabel * @color: (allow-none): The label's background color or NULL to reset the background to the * default color. The color parameter is copied. * * Sets the label's background color. * * Since: 0.10 */ void champlain_label_set_color (ChamplainLabel *label, const ClutterColor *color) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); ChamplainLabelPrivate *priv = label->priv; if (priv->color != NULL) clutter_color_free (priv->color); if (color == NULL) color = &DEFAULT_COLOR; priv->color = clutter_color_copy (color); g_object_notify (G_OBJECT (label), "color"); champlain_label_queue_redraw (label); } /** * champlain_label_set_text_color: * @label: a #ChamplainLabel * @color: (allow-none): The label's text color or NULL to reset the text to the default * color. The color parameter is copied. * * Sets the label's text color. * * Since: 0.10 */ void champlain_label_set_text_color (ChamplainLabel *label, const ClutterColor *color) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); ChamplainLabelPrivate *priv = label->priv; if (priv->text_color != NULL) clutter_color_free (priv->text_color); if (color == NULL) color = &DEFAULT_TEXT_COLOR; priv->text_color = clutter_color_copy (color); g_object_notify (G_OBJECT (label), "text-color"); champlain_label_queue_redraw (label); } /** * champlain_label_set_font_name: * @label: a #ChamplainLabel * @font_name: (allow-none): The label's font name or NULL to reset the font to the default * value. * * Sets the label's font name such as "Sans 12". * * Since: 0.10 */ void champlain_label_set_font_name (ChamplainLabel *label, const gchar *font_name) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); ChamplainLabelPrivate *priv = label->priv; if (priv->font_name != NULL) g_free (priv->font_name); if (font_name == NULL) font_name = DEFAULT_FONT_NAME; priv->font_name = g_strdup (font_name); g_object_notify (G_OBJECT (label), "font-name"); champlain_label_queue_redraw (label); } /** * champlain_label_set_wrap: * @label: a #ChamplainLabel * @wrap: The label's wrap. * * Sets if the label's text wrap. * * Since: 0.10 */ void champlain_label_set_wrap (ChamplainLabel *label, gboolean wrap) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); label->priv->wrap = wrap; g_object_notify (G_OBJECT (label), "wrap"); champlain_label_queue_redraw (label); } /** * champlain_label_set_wrap_mode: * @label: a #ChamplainLabel * @wrap_mode: The label's wrap mode. * * Sets the label's text wrap mode. * * Since: 0.10 */ void champlain_label_set_wrap_mode (ChamplainLabel *label, PangoWrapMode wrap_mode) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); label->priv->wrap_mode = wrap_mode; g_object_notify (G_OBJECT (label), "wrap-mode"); champlain_label_queue_redraw (label); } /** * champlain_label_set_attributes: * @label: a #ChamplainLabel * @list: The label's text attributes. * * Sets the label's text attributes. * * Since: 0.10 */ void champlain_label_set_attributes (ChamplainLabel *label, PangoAttrList *attributes) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); ChamplainLabelPrivate *priv = label->priv; if (attributes) pango_attr_list_ref (attributes); if (priv->attributes) pango_attr_list_unref (priv->attributes); priv->attributes = attributes; g_object_notify (G_OBJECT (label), "attributes"); champlain_label_queue_redraw (label); } /** * champlain_label_set_ellipsize: * @label: a #ChamplainLabel * @mode: The label's ellipsize mode. * * Sets the label's text ellipsize mode. * * Since: 0.10 */ void champlain_label_set_ellipsize (ChamplainLabel *label, PangoEllipsizeMode ellipsize) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); label->priv->ellipsize = ellipsize; g_object_notify (G_OBJECT (label), "ellipsize"); champlain_label_queue_redraw (label); } /** * champlain_label_set_single_line_mode: * @label: a #ChamplainLabel * @mode: The label's single line mode * * Sets if the label's text is on a single line. * * Since: 0.10 */ void champlain_label_set_single_line_mode (ChamplainLabel *label, gboolean mode) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); label->priv->single_line_mode = mode; g_object_notify (G_OBJECT (label), "single-line-mode"); champlain_label_queue_redraw (label); } /** * champlain_label_set_draw_background: * @label: a #ChamplainLabel * @background: value. * * Sets if the label has a background. * * Since: 0.10 */ void champlain_label_set_draw_background (ChamplainLabel *label, gboolean background) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); label->priv->draw_background = background; g_object_notify (G_OBJECT (label), "draw-background"); champlain_label_queue_redraw (label); } /** * champlain_label_set_draw_shadow: * @label: a #ChamplainLabel * @shadow: value. * * Sets if the label's background has a shadow. * * Since: 0.12.10 */ void champlain_label_set_draw_shadow (ChamplainLabel *label, gboolean shadow) { g_return_if_fail (CHAMPLAIN_IS_LABEL (label)); label->priv->draw_shadow = shadow; g_object_notify (G_OBJECT (label), "draw-shadow"); champlain_label_queue_redraw (label); } /** * champlain_label_get_image: * @label: a #ChamplainLabel * * Get the label's image. * * Returns: (transfer none): the label's image. * * Since: 0.10 */ ClutterActor * champlain_label_get_image (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), NULL); return label->priv->image; } /** * champlain_label_get_use_markup: * @label: a #ChamplainLabel * * Check whether the label uses markup. * * Returns: if the label's text contains markup. * * Since: 0.10 */ gboolean champlain_label_get_use_markup (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->use_markup; } /** * champlain_label_get_text: * @label: a #ChamplainLabel * * Get the label's text. * * Returns: the label's text. * * Since: 0.10 */ const gchar * champlain_label_get_text (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->text; } /** * champlain_label_get_alignment: * @label: a #ChamplainLabel * * Get the label's text alignment. * * Returns: the label's text alignment. * * Since: 0.10 */ PangoAlignment champlain_label_get_alignment (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->alignment; } /** * champlain_label_get_color: * @label: a #ChamplainLabel * * Gets the label's background color. * * Returns: the label's background color. * * Since: 0.10 */ ClutterColor * champlain_label_get_color (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), NULL); return label->priv->color; } /** * champlain_label_get_text_color: * @label: a #ChamplainLabel * * Gets the label's text color. * * Returns: the label's text color. * * Since: 0.10 */ ClutterColor * champlain_label_get_text_color (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), NULL); return label->priv->text_color; } /** * champlain_label_get_font_name: * @label: a #ChamplainLabel * * Gets the label's font name. * * Returns: the label's font name. * * Since: 0.10 */ const gchar * champlain_label_get_font_name (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->font_name; } /** * champlain_label_get_wrap: * @label: a #ChamplainLabel * * Checks whether the label text wraps. * * Returns: if the label's text wraps. * * Since: 0.10 */ gboolean champlain_label_get_wrap (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->wrap; } /** * champlain_label_get_wrap_mode: * @label: a #ChamplainLabel * * Gets the label's text wrap mode. * * Returns: the label's text wrap mode. * * Since: 0.10 */ PangoWrapMode champlain_label_get_wrap_mode (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->wrap_mode; } /** * champlain_label_get_ellipsize: * @label: a #ChamplainLabel * * Gets the label's text ellipsize mode. * * Returns: the label's text ellipsize mode. * * Since: 0.10 */ PangoEllipsizeMode champlain_label_get_ellipsize (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->ellipsize; } /** * champlain_label_get_single_line_mode: * @label: a #ChamplainLabel * * Checks the label's single line mode. * * Returns: the label's text single line mode. * * Since: 0.10 */ gboolean champlain_label_get_single_line_mode (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->single_line_mode; } /** * champlain_label_get_draw_background: * @label: a #ChamplainLabel * * Checks whether the label has a background. * * Returns: if the label has a background. * * Since: 0.10 */ gboolean champlain_label_get_draw_background (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->draw_background; } /** * champlain_label_get_draw_shadow: * @label: a #ChamplainLabel * * Checks whether the label's background has a shadow. * * Returns: if the label's background has a shadow. * * Since: 0.12.10 */ gboolean champlain_label_get_draw_shadow (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), FALSE); return label->priv->draw_shadow; } /** * champlain_label_get_attributes: * @label: a #ChamplainLabel * * Gets the label's text attributes. * * Returns: the label's text attributes. * * Since: 0.10 */ PangoAttrList * champlain_label_get_attributes (ChamplainLabel *label) { g_return_val_if_fail (CHAMPLAIN_IS_LABEL (label), NULL); return label->priv->attributes; }