a9fd350396
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
691 lines
19 KiB
C
691 lines
19 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
/*
|
|
* st-tooltip.c: Plain tooltip 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>
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* SECTION:st-tooltip
|
|
* @short_description: A tooltip widget
|
|
*
|
|
* #StTooltip implements a single tooltip. It should not normally be created
|
|
* by the application but by the widget implementing tooltip capabilities, for
|
|
* example, #st_button_set_tooltip().
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include <clutter/clutter.h>
|
|
|
|
#include "st-tooltip.h"
|
|
|
|
#include "st-widget.h"
|
|
#include "st-private.h"
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
|
|
PROP_LABEL,
|
|
PROP_TIP_AREA
|
|
};
|
|
|
|
#define ST_TOOLTIP_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_TOOLTIP, StTooltipPrivate))
|
|
|
|
struct _StTooltipPrivate
|
|
{
|
|
ClutterActor *label;
|
|
|
|
gfloat arrow_offset;
|
|
gboolean actor_below;
|
|
|
|
ClutterGeometry *tip_area;
|
|
};
|
|
|
|
G_DEFINE_TYPE (StTooltip, st_tooltip, ST_TYPE_WIDGET);
|
|
|
|
static void
|
|
st_tooltip_set_property (GObject *gobject,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
StTooltip *tooltip = ST_TOOLTIP (gobject);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_LABEL:
|
|
st_tooltip_set_label (tooltip, g_value_get_string (value));
|
|
break;
|
|
|
|
case PROP_TIP_AREA:
|
|
st_tooltip_set_tip_area (tooltip, g_value_get_boxed (value));
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
st_tooltip_get_property (GObject *gobject,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
StTooltipPrivate *priv = ST_TOOLTIP (gobject)->priv;
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_LABEL:
|
|
g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->label)));
|
|
break;
|
|
|
|
case PROP_TIP_AREA:
|
|
g_value_set_boxed (value, priv->tip_area);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
st_tooltip_style_changed (StWidget *self)
|
|
{
|
|
StTooltipPrivate *priv;
|
|
StThemeNode *theme_node;
|
|
ClutterColor color;
|
|
const PangoFontDescription *font;
|
|
gchar *font_string;
|
|
|
|
priv = ST_TOOLTIP (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_tooltip_parent_class)->style_changed (self);
|
|
}
|
|
|
|
static void
|
|
st_tooltip_get_preferred_width (ClutterActor *self,
|
|
gfloat for_height,
|
|
gfloat *min_width_p,
|
|
gfloat *natural_width_p)
|
|
{
|
|
StTooltipPrivate *priv = ST_TOOLTIP (self)->priv;
|
|
gfloat min_label_w, natural_label_w;
|
|
gfloat label_height, arrow_height;
|
|
ClutterActor *arrow_image;
|
|
StPadding padding;
|
|
|
|
st_widget_get_padding (ST_WIDGET (self), &padding);
|
|
|
|
arrow_image = st_widget_get_background_image (ST_WIDGET (self));
|
|
if (arrow_image)
|
|
{
|
|
clutter_actor_get_preferred_height (arrow_image,
|
|
-1,
|
|
NULL,
|
|
&arrow_height);
|
|
}
|
|
else
|
|
{
|
|
arrow_height = 0;
|
|
}
|
|
|
|
if (for_height > -1)
|
|
{
|
|
label_height = for_height - arrow_height - padding.top - padding.bottom;
|
|
}
|
|
else
|
|
{
|
|
label_height = -1;
|
|
}
|
|
|
|
if (priv->label)
|
|
{
|
|
clutter_actor_get_preferred_width (priv->label,
|
|
label_height,
|
|
&min_label_w,
|
|
&natural_label_w);
|
|
}
|
|
else
|
|
{
|
|
min_label_w = 0;
|
|
natural_label_w = 0;
|
|
}
|
|
|
|
|
|
if (min_width_p)
|
|
{
|
|
*min_width_p = padding.left + padding.right + min_label_w;
|
|
}
|
|
|
|
if (natural_width_p)
|
|
{
|
|
*natural_width_p = padding.left + padding.right + natural_label_w;
|
|
}
|
|
}
|
|
|
|
static void
|
|
st_tooltip_get_preferred_height (ClutterActor *self,
|
|
gfloat for_width,
|
|
gfloat *min_height_p,
|
|
gfloat *natural_height_p)
|
|
{
|
|
StTooltipPrivate *priv = ST_TOOLTIP (self)->priv;
|
|
gfloat arrow_height;
|
|
gfloat min_label_h, natural_label_h;
|
|
gfloat label_width;
|
|
ClutterActor *arrow_image;
|
|
StPadding padding;
|
|
|
|
arrow_image = st_widget_get_background_image (ST_WIDGET (self));
|
|
|
|
if (arrow_image && !priv->actor_below)
|
|
{
|
|
clutter_actor_get_preferred_height (arrow_image,
|
|
-1,
|
|
NULL,
|
|
&arrow_height);
|
|
}
|
|
else
|
|
{
|
|
arrow_height = 0;
|
|
}
|
|
st_widget_get_padding (ST_WIDGET (self), &padding);
|
|
|
|
if (for_width > -1)
|
|
{
|
|
label_width = for_width - padding.left - padding.right;
|
|
}
|
|
else
|
|
{
|
|
label_width = -1;
|
|
}
|
|
|
|
if (priv->label)
|
|
{
|
|
clutter_actor_get_preferred_height (priv->label,
|
|
label_width,
|
|
&min_label_h,
|
|
&natural_label_h);
|
|
}
|
|
else
|
|
{
|
|
min_label_h = 0;
|
|
natural_label_h = 0;
|
|
}
|
|
|
|
if (min_height_p)
|
|
{
|
|
*min_height_p = padding.top + padding.bottom
|
|
+ arrow_height + min_label_h;
|
|
}
|
|
|
|
if (natural_height_p)
|
|
{
|
|
*natural_height_p = padding.top + padding.bottom
|
|
+ arrow_height + natural_label_h;
|
|
}
|
|
}
|
|
|
|
static void
|
|
st_tooltip_allocate (ClutterActor *self,
|
|
const ClutterActorBox *box,
|
|
ClutterAllocationFlags flags)
|
|
{
|
|
StTooltipPrivate *priv = ST_TOOLTIP (self)->priv;
|
|
ClutterActorBox child_box, arrow_box;
|
|
gfloat arrow_height, arrow_width;
|
|
ClutterActor *border_image, *arrow_image;
|
|
StPadding padding;
|
|
|
|
CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->allocate (self,
|
|
box,
|
|
flags);
|
|
|
|
st_widget_get_padding (ST_WIDGET (self), &padding);
|
|
|
|
arrow_image = st_widget_get_background_image (ST_WIDGET (self));
|
|
|
|
if (arrow_image && !priv->actor_below)
|
|
{
|
|
clutter_actor_get_preferred_height (arrow_image, -1, NULL, &arrow_height);
|
|
clutter_actor_get_preferred_width (arrow_image, -1, NULL, &arrow_width);
|
|
|
|
arrow_box.x1 = (float)(priv->arrow_offset) - (int)(arrow_width / 2);
|
|
arrow_box.y1 = 0;
|
|
arrow_box.x2 = arrow_box.x1 + arrow_width;
|
|
arrow_box.y2 = arrow_box.y1 + arrow_height;
|
|
|
|
clutter_actor_allocate (arrow_image, &arrow_box, flags);
|
|
}
|
|
else
|
|
{
|
|
arrow_height = 0;
|
|
arrow_width = 0;
|
|
}
|
|
|
|
child_box.x1 = child_box.y1 = 0;
|
|
child_box.x2 = (box->x2 - box->x1);
|
|
child_box.y2 = (box->y2 - box->y1);
|
|
|
|
/* remove the space that is used by the arrow */
|
|
child_box.y1 += arrow_height;
|
|
|
|
border_image = st_widget_get_border_image (ST_WIDGET (self));
|
|
if (border_image)
|
|
clutter_actor_allocate (border_image, &child_box, flags);
|
|
|
|
if (priv->label)
|
|
{
|
|
/* now remove the padding */
|
|
child_box.y1 += padding.top;
|
|
child_box.x1 += padding.left;
|
|
child_box.x2 -= padding.right;
|
|
child_box.y2 -= padding.bottom;
|
|
|
|
clutter_actor_allocate (priv->label, &child_box, flags);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
st_tooltip_paint (ClutterActor *self)
|
|
{
|
|
ClutterActor *border_image, *arrow_image;
|
|
StTooltipPrivate *priv = ST_TOOLTIP (self)->priv;
|
|
|
|
border_image = st_widget_get_border_image (ST_WIDGET (self));
|
|
if (border_image)
|
|
clutter_actor_paint (border_image);
|
|
|
|
arrow_image = st_widget_get_background_image (ST_WIDGET (self));
|
|
if (arrow_image && !priv->actor_below)
|
|
clutter_actor_paint (arrow_image);
|
|
|
|
clutter_actor_paint (priv->label);
|
|
}
|
|
|
|
static void
|
|
st_tooltip_map (ClutterActor *self)
|
|
{
|
|
StTooltipPrivate *priv = ST_TOOLTIP (self)->priv;
|
|
ClutterActor *border_image, *arrow_image;
|
|
|
|
CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->map (self);
|
|
|
|
border_image = st_widget_get_border_image (ST_WIDGET (self));
|
|
if (border_image)
|
|
clutter_actor_map (border_image);
|
|
|
|
arrow_image = st_widget_get_background_image (ST_WIDGET (self));
|
|
if (arrow_image)
|
|
clutter_actor_map (arrow_image);
|
|
|
|
clutter_actor_map (priv->label);
|
|
}
|
|
|
|
static void
|
|
st_tooltip_unmap (ClutterActor *self)
|
|
{
|
|
StTooltipPrivate *priv = ST_TOOLTIP (self)->priv;
|
|
ClutterActor *border_image, *arrow_image;
|
|
|
|
CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->unmap (self);
|
|
|
|
border_image = st_widget_get_border_image (ST_WIDGET (self));
|
|
if (border_image)
|
|
clutter_actor_unmap (border_image);
|
|
|
|
arrow_image = st_widget_get_background_image (ST_WIDGET (self));
|
|
if (arrow_image)
|
|
clutter_actor_unmap (arrow_image);
|
|
|
|
clutter_actor_unmap (priv->label);
|
|
}
|
|
|
|
static void
|
|
st_tooltip_class_init (StTooltipClass *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 (StTooltipPrivate));
|
|
|
|
gobject_class->set_property = st_tooltip_set_property;
|
|
gobject_class->get_property = st_tooltip_get_property;
|
|
|
|
actor_class->get_preferred_width = st_tooltip_get_preferred_width;
|
|
actor_class->get_preferred_height = st_tooltip_get_preferred_height;
|
|
actor_class->allocate = st_tooltip_allocate;
|
|
actor_class->paint = st_tooltip_paint;
|
|
actor_class->map = st_tooltip_map;
|
|
actor_class->unmap = st_tooltip_unmap;
|
|
|
|
widget_class->style_changed = st_tooltip_style_changed;
|
|
|
|
pspec = g_param_spec_string ("label",
|
|
"Label",
|
|
"Label of the tooltip",
|
|
NULL, G_PARAM_READWRITE);
|
|
g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
|
|
|
|
pspec = g_param_spec_boxed ("tip-area",
|
|
"Tip Area",
|
|
"Area on the stage the tooltip applies to",
|
|
CLUTTER_TYPE_GEOMETRY,
|
|
ST_PARAM_READWRITE);
|
|
g_object_class_install_property (gobject_class, PROP_TIP_AREA, pspec);
|
|
}
|
|
|
|
static void
|
|
st_tooltip_init (StTooltip *tooltip)
|
|
{
|
|
tooltip->priv = ST_TOOLTIP_GET_PRIVATE (tooltip);
|
|
|
|
tooltip->priv->label = g_object_new (CLUTTER_TYPE_TEXT,
|
|
"line-alignment", PANGO_ALIGN_CENTER,
|
|
"ellipsize", PANGO_ELLIPSIZE_END,
|
|
"use-markup", TRUE,
|
|
NULL);
|
|
|
|
tooltip->priv->tip_area = NULL;
|
|
|
|
clutter_actor_set_parent (CLUTTER_ACTOR (tooltip->priv->label),
|
|
CLUTTER_ACTOR (tooltip));
|
|
|
|
g_object_set (tooltip, "show-on-set-parent", FALSE, NULL);
|
|
|
|
clutter_actor_set_reactive (CLUTTER_ACTOR (tooltip), FALSE);
|
|
}
|
|
|
|
static void
|
|
st_tooltip_update_position (StTooltip *tooltip)
|
|
{
|
|
StTooltipPrivate *priv = tooltip->priv;
|
|
ClutterGeometry *tip_area = tooltip->priv->tip_area;
|
|
gfloat tooltip_w, tooltip_h, tooltip_x, tooltip_y;
|
|
gfloat stage_w, stage_h;
|
|
ClutterActor *stage;
|
|
|
|
/* ensure the tooltip with is not fixed size */
|
|
clutter_actor_set_size ((ClutterActor*) tooltip, -1, -1);
|
|
|
|
/* if no area set, just position ourselves top left */
|
|
if (!priv->tip_area)
|
|
{
|
|
clutter_actor_set_position ((ClutterActor*) tooltip, 0, 0);
|
|
return;
|
|
}
|
|
|
|
/* we need to have a style in case there are padding values to take into
|
|
* account when calculating width/height */
|
|
st_widget_ensure_style ((StWidget *) tooltip);
|
|
|
|
/* find out the tooltip's size */
|
|
clutter_actor_get_size ((ClutterActor*) tooltip, &tooltip_w, &tooltip_h);
|
|
|
|
/* attempt to place the tooltip */
|
|
tooltip_x = (int)(tip_area->x + (tip_area->width / 2) - (tooltip_w / 2));
|
|
tooltip_y = (int)(tip_area->y + tip_area->height);
|
|
|
|
stage = clutter_actor_get_stage ((ClutterActor *) tooltip);
|
|
if (!stage)
|
|
{
|
|
return;
|
|
}
|
|
clutter_actor_get_size (stage, &stage_w, &stage_h);
|
|
|
|
/* make sure the tooltip is not off screen vertically */
|
|
if (tooltip_w > stage_w)
|
|
{
|
|
tooltip_x = 0;
|
|
clutter_actor_set_width ((ClutterActor*) tooltip, stage_w);
|
|
}
|
|
else if (tooltip_x < 0)
|
|
{
|
|
tooltip_x = 0;
|
|
}
|
|
else if (tooltip_x + tooltip_w > stage_w)
|
|
{
|
|
tooltip_x = (int)(stage_w) - tooltip_w;
|
|
}
|
|
|
|
/* make sure the tooltip is not off screen horizontally */
|
|
if (tooltip_y + tooltip_h > stage_h)
|
|
{
|
|
priv->actor_below = TRUE;
|
|
|
|
/* re-query size as may have changed */
|
|
clutter_actor_get_preferred_height ((ClutterActor*) tooltip,
|
|
-1, NULL, &tooltip_h);
|
|
tooltip_y = tip_area->y - tooltip_h;
|
|
}
|
|
else
|
|
{
|
|
priv->actor_below = FALSE;
|
|
}
|
|
|
|
/* calculate the arrow offset */
|
|
priv->arrow_offset = tip_area->x + tip_area->width / 2 - tooltip_x;
|
|
|
|
clutter_actor_set_position ((ClutterActor*) tooltip, tooltip_x, tooltip_y);
|
|
}
|
|
|
|
/**
|
|
* st_tooltip_get_label:
|
|
* @tooltip: a #StTooltip
|
|
*
|
|
* Get the text displayed on the tooltip
|
|
*
|
|
* Returns: the text for the tooltip. This must not be freed by the application
|
|
*/
|
|
G_CONST_RETURN gchar *
|
|
st_tooltip_get_label (StTooltip *tooltip)
|
|
{
|
|
g_return_val_if_fail (ST_IS_TOOLTIP (tooltip), NULL);
|
|
|
|
return clutter_text_get_text (CLUTTER_TEXT (tooltip->priv->label));
|
|
}
|
|
|
|
/**
|
|
* st_tooltip_set_label:
|
|
* @tooltip: a #StTooltip
|
|
* @text: text to set the label to
|
|
*
|
|
* Sets the text displayed on the tooltip
|
|
*/
|
|
void
|
|
st_tooltip_set_label (StTooltip *tooltip,
|
|
const gchar *text)
|
|
{
|
|
StTooltipPrivate *priv;
|
|
|
|
g_return_if_fail (ST_IS_TOOLTIP (tooltip));
|
|
|
|
priv = tooltip->priv;
|
|
|
|
clutter_text_set_text (CLUTTER_TEXT (priv->label), text);
|
|
|
|
g_object_notify (G_OBJECT (tooltip), "label");
|
|
}
|
|
|
|
/**
|
|
* st_tooltip_show:
|
|
* @tooltip: a #StTooltip
|
|
*
|
|
* Show the tooltip relative to the associated widget.
|
|
*/
|
|
void
|
|
st_tooltip_show (StTooltip *tooltip)
|
|
{
|
|
StTooltipPrivate *priv;
|
|
ClutterActor *parent;
|
|
ClutterActor *stage;
|
|
ClutterActor *self = CLUTTER_ACTOR (tooltip);
|
|
ClutterAnimation *animation;
|
|
|
|
/* make sure we're not currently already animating (e.g. hiding) */
|
|
animation = clutter_actor_get_animation (CLUTTER_ACTOR (tooltip));
|
|
if (animation)
|
|
clutter_animation_completed (animation);
|
|
|
|
priv = tooltip->priv;
|
|
parent = clutter_actor_get_parent (self);
|
|
stage = clutter_actor_get_stage (self);
|
|
|
|
if (!stage)
|
|
{
|
|
g_warning ("StTooltip is not on any stage.");
|
|
return;
|
|
}
|
|
|
|
/* make sure we're parented on the stage */
|
|
if (G_UNLIKELY (parent != stage))
|
|
{
|
|
g_object_ref (self);
|
|
clutter_actor_unparent (self);
|
|
clutter_actor_set_parent (self, stage);
|
|
g_object_unref (self);
|
|
parent = stage;
|
|
}
|
|
|
|
/* raise the tooltip to the top */
|
|
clutter_container_raise_child (CLUTTER_CONTAINER (stage),
|
|
CLUTTER_ACTOR (tooltip),
|
|
NULL);
|
|
|
|
st_tooltip_update_position (tooltip);
|
|
|
|
/* finally show the tooltip... */
|
|
CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->show (self);
|
|
|
|
/* and give it some bounce! */
|
|
g_object_set (G_OBJECT (self),
|
|
"scale-center-x", priv->arrow_offset,
|
|
"scale-center-y", (priv->actor_below) ? clutter_actor_get_height (self) : 0,
|
|
NULL);
|
|
clutter_actor_set_scale (self, 0.0, 0.0);
|
|
clutter_actor_animate (self, CLUTTER_EASE_OUT_ELASTIC,
|
|
500,
|
|
"scale-x", 1.0,
|
|
"scale-y", 1.0,
|
|
NULL);
|
|
}
|
|
|
|
static void
|
|
st_tooltip_hide_complete (ClutterAnimation *animation,
|
|
ClutterActor *actor)
|
|
{
|
|
CLUTTER_ACTOR_CLASS (st_tooltip_parent_class)->hide (actor);
|
|
g_signal_handlers_disconnect_by_func (actor,
|
|
st_tooltip_hide_complete,
|
|
actor);
|
|
}
|
|
|
|
/**
|
|
* st_tooltip_hide:
|
|
* @tooltip: a #StTooltip
|
|
*
|
|
* Hide the tooltip
|
|
*/
|
|
void
|
|
st_tooltip_hide (StTooltip *tooltip)
|
|
{
|
|
ClutterAnimation *animation;
|
|
|
|
g_return_if_fail (ST_TOOLTIP (tooltip));
|
|
|
|
/* make sure we're not currently already animating (e.g. hiding) */
|
|
animation = clutter_actor_get_animation (CLUTTER_ACTOR (tooltip));
|
|
if (animation)
|
|
clutter_animation_completed (animation);
|
|
|
|
g_object_set (G_OBJECT (tooltip),
|
|
"scale-center-x", tooltip->priv->arrow_offset,
|
|
NULL);
|
|
animation =
|
|
clutter_actor_animate (CLUTTER_ACTOR (tooltip), CLUTTER_EASE_IN_SINE,
|
|
150,
|
|
"scale-x", 0.0,
|
|
"scale-y", 0.0,
|
|
NULL);
|
|
g_signal_connect (animation, "completed",
|
|
G_CALLBACK (st_tooltip_hide_complete), tooltip);
|
|
}
|
|
|
|
/**
|
|
* st_tooltip_set_tip_area:
|
|
* @tooltip: A #StTooltip
|
|
* @area: A #ClutterGeometry
|
|
*
|
|
* Set the area on the stage that the tooltip applies to.
|
|
*/
|
|
void
|
|
st_tooltip_set_tip_area (StTooltip *tooltip,
|
|
const ClutterGeometry *area)
|
|
{
|
|
g_return_if_fail (ST_IS_TOOLTIP (tooltip));
|
|
|
|
if (tooltip->priv->tip_area)
|
|
g_boxed_free (CLUTTER_TYPE_GEOMETRY, tooltip->priv->tip_area);
|
|
tooltip->priv->tip_area = g_boxed_copy (CLUTTER_TYPE_GEOMETRY, area);
|
|
|
|
st_tooltip_update_position (tooltip);
|
|
}
|
|
|
|
/**
|
|
* st_tooltip_get_tip_area:
|
|
* @tooltip: A #StTooltip
|
|
*
|
|
* Retrieve the area on the stage that the tooltip currently applies to
|
|
*
|
|
* Returns: the #ClutterGeometry, owned by the tooltip which must not be freed
|
|
* by the application.
|
|
*/
|
|
G_CONST_RETURN ClutterGeometry*
|
|
st_tooltip_get_tip_area (StTooltip *tooltip)
|
|
{
|
|
g_return_val_if_fail (ST_IS_TOOLTIP (tooltip), NULL);
|
|
|
|
return tooltip->priv->tip_area;
|
|
}
|