4
* An OpenGL based 'interactive canvas' library.
6
* Copyright (C) 2012 Intel Corporation
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public
10
* License as published by the Free Software Foundation; either
11
* version 2 of the License, or (at your option) any later version.
13
* This library is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Lesser General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
23
* SECTION:clutter-scroll-actor
24
* @Title: ClutterScrollActor
25
* @Short_Description: An actor for displaying a portion of its children
27
* #ClutterScrollActor is an actor that can be used to display a portion
28
* of the contents of its children.
30
* The extent of the area of a #ClutterScrollActor is defined by the size
31
* of its children; the visible region of the children of a #ClutterScrollActor
32
* is set by using clutter_scroll_actor_scroll_to_point() or by using
33
* clutter_scroll_actor_scroll_to_rect() to define a point or a rectangle
34
* acting as the origin, respectively.
36
* #ClutterScrollActor does not provide pointer or keyboard event handling,
37
* nor does it provide visible scroll handles.
39
* See [scroll-actor.c](https://git.gnome.org/browse/clutter/tree/examples/scroll-actor.c?h=clutter-1.18)
40
* for an example of how to use #ClutterScrollActor.
42
* #ClutterScrollActor is available since Clutter 1.12.
49
#include "clutter-scroll-actor.h"
51
#include "clutter-actor-private.h"
52
#include "clutter-animatable.h"
53
#include "clutter-debug.h"
54
#include "clutter-enum-types.h"
55
#include "clutter-private.h"
56
#include "clutter-property-transition.h"
57
#include "clutter-transition.h"
59
struct _ClutterScrollActorPrivate
61
ClutterPoint scroll_to;
63
ClutterScrollMode scroll_mode;
65
ClutterTransition *transition;
86
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
87
static GParamSpec *animatable_props[ANIM_PROP_LAST] = { NULL, };
89
static ClutterAnimatableIface *parent_animatable_iface = NULL;
91
static void clutter_animatable_iface_init (ClutterAnimatableIface *iface);
93
G_DEFINE_TYPE_WITH_CODE (ClutterScrollActor, clutter_scroll_actor, CLUTTER_TYPE_ACTOR,
94
G_ADD_PRIVATE (ClutterScrollActor)
95
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_ANIMATABLE,
96
clutter_animatable_iface_init))
99
clutter_scroll_actor_set_scroll_to_internal (ClutterScrollActor *self,
100
const ClutterPoint *point)
102
ClutterScrollActorPrivate *priv = self->priv;
103
ClutterActor *actor = CLUTTER_ACTOR (self);
104
ClutterMatrix m = CLUTTER_MATRIX_INIT_IDENTITY;
107
if (clutter_point_equals (&priv->scroll_to, point))
111
clutter_point_init (&priv->scroll_to, 0.f, 0.f);
113
priv->scroll_to = *point;
115
if (priv->scroll_mode & CLUTTER_SCROLL_HORIZONTALLY)
116
dx = -priv->scroll_to.x;
120
if (priv->scroll_mode & CLUTTER_SCROLL_VERTICALLY)
121
dy = -priv->scroll_to.y;
125
cogl_matrix_translate (&m, dx, dy, 0.f);
126
clutter_actor_set_child_transform (actor, &m);
130
clutter_scroll_actor_set_property (GObject *gobject,
135
ClutterScrollActor *actor = CLUTTER_SCROLL_ACTOR (gobject);
139
case PROP_SCROLL_MODE:
140
clutter_scroll_actor_set_scroll_mode (actor, g_value_get_flags (value));
144
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
149
clutter_scroll_actor_get_property (GObject *gobject,
154
ClutterScrollActor *actor = CLUTTER_SCROLL_ACTOR (gobject);
158
case PROP_SCROLL_MODE:
159
g_value_set_flags (value, actor->priv->scroll_mode);
163
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
168
clutter_scroll_actor_class_init (ClutterScrollActorClass *klass)
170
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
172
gobject_class->set_property = clutter_scroll_actor_set_property;
173
gobject_class->get_property = clutter_scroll_actor_get_property;
176
* ClutterScrollActor:scroll-mode:
178
* The scrollin direction.
182
obj_props[PROP_SCROLL_MODE] =
183
g_param_spec_flags ("scroll-mode",
185
P_("The scrolling direction"),
186
CLUTTER_TYPE_SCROLL_MODE,
189
G_PARAM_STATIC_STRINGS);
191
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
195
clutter_scroll_actor_init (ClutterScrollActor *self)
197
self->priv = clutter_scroll_actor_get_instance_private (self);
198
self->priv->scroll_mode = CLUTTER_SCROLL_BOTH;
200
clutter_actor_set_clip_to_allocation (CLUTTER_ACTOR (self), TRUE);
204
clutter_scroll_actor_find_property (ClutterAnimatable *animatable,
205
const char *property_name)
207
if (strcmp (property_name, "scroll-to") == 0)
208
return animatable_props[ANIM_PROP_SCROLL_TO];
210
return parent_animatable_iface->find_property (animatable, property_name);
214
clutter_scroll_actor_set_final_state (ClutterAnimatable *animatable,
215
const char *property_name,
218
if (strcmp (property_name, "scroll-to") == 0)
220
ClutterScrollActor *self = CLUTTER_SCROLL_ACTOR (animatable);
221
const ClutterPoint *point = g_value_get_boxed (value);
223
clutter_scroll_actor_set_scroll_to_internal (self, point);
226
parent_animatable_iface->set_final_state (animatable, property_name, value);
230
clutter_scroll_actor_get_initial_state (ClutterAnimatable *animatable,
231
const char *property_name,
234
if (strcmp (property_name, "scroll-to") == 0)
236
ClutterScrollActor *self = CLUTTER_SCROLL_ACTOR (animatable);
238
g_value_set_boxed (value, &self->priv->scroll_to);
241
parent_animatable_iface->get_initial_state (animatable, property_name, value);
245
clutter_animatable_iface_init (ClutterAnimatableIface *iface)
247
parent_animatable_iface = g_type_interface_peek_parent (iface);
249
animatable_props[ANIM_PROP_SCROLL_TO] =
250
g_param_spec_boxed ("scroll-to",
252
"The point to scroll the actor to",
255
G_PARAM_STATIC_STRINGS |
256
CLUTTER_PARAM_ANIMATABLE);
258
iface->find_property = clutter_scroll_actor_find_property;
259
iface->get_initial_state = clutter_scroll_actor_get_initial_state;
260
iface->set_final_state = clutter_scroll_actor_set_final_state;
264
* clutter_scroll_actor_new:
266
* Creates a new #ClutterScrollActor.
268
* Return value: The newly created #ClutterScrollActor
274
clutter_scroll_actor_new (void)
276
return g_object_new (CLUTTER_TYPE_SCROLL_ACTOR, NULL);
280
* clutter_scroll_actor_set_scroll_mode:
281
* @actor: a #ClutterScrollActor
282
* @mode: a #ClutterScrollMode
284
* Sets the #ClutterScrollActor:scroll-mode property.
289
clutter_scroll_actor_set_scroll_mode (ClutterScrollActor *actor,
290
ClutterScrollMode mode)
292
ClutterScrollActorPrivate *priv;
294
g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor));
298
if (priv->scroll_mode == mode)
301
priv->scroll_mode = mode;
303
g_object_notify_by_pspec (G_OBJECT (actor), obj_props[PROP_SCROLL_MODE]);
307
* clutter_scroll_actor_get_scroll_mode:
308
* @actor: a #ClutterScrollActor
310
* Retrieves the #ClutterScrollActor:scroll-mode property
312
* Return value: the scrolling mode
317
clutter_scroll_actor_get_scroll_mode (ClutterScrollActor *actor)
319
g_return_val_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor), CLUTTER_SCROLL_NONE);
321
return actor->priv->scroll_mode;
325
* clutter_scroll_actor_scroll_to_point:
326
* @actor: a #ClutterScrollActor
327
* @point: a #ClutterPoint
329
* Scrolls the contents of @actor so that @point is the new origin
330
* of the visible area.
332
* The coordinates of @point must be relative to the @actor.
334
* This function will use the currently set easing state of the @actor
335
* to transition from the current scroll origin to the new one.
340
clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
341
const ClutterPoint *point)
343
ClutterScrollActorPrivate *priv;
344
const ClutterAnimationInfo *info;
346
g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor));
347
g_return_if_fail (point != NULL);
351
info = _clutter_actor_get_animation_info (CLUTTER_ACTOR (actor));
353
/* jump to the end if there is no easing state, or if the easing
354
* state has a duration of 0 msecs
356
if (info->cur_state == NULL ||
357
info->cur_state->easing_duration == 0)
359
/* ensure that we remove any currently running transition */
360
if (priv->transition != NULL)
362
clutter_actor_remove_transition (CLUTTER_ACTOR (actor),
364
priv->transition = NULL;
367
clutter_scroll_actor_set_scroll_to_internal (actor, point);
372
if (priv->transition == NULL)
374
priv->transition = clutter_property_transition_new ("scroll-to");
375
clutter_transition_set_animatable (priv->transition,
376
CLUTTER_ANIMATABLE (actor));
377
clutter_transition_set_remove_on_complete (priv->transition, TRUE);
379
/* delay only makes sense if the transition has just been created */
380
clutter_timeline_set_delay (CLUTTER_TIMELINE (priv->transition),
381
info->cur_state->easing_delay);
382
/* we need this to clear the priv->transition pointer */
383
g_object_add_weak_pointer (G_OBJECT (priv->transition), (gpointer *) &priv->transition);
385
clutter_actor_add_transition (CLUTTER_ACTOR (actor),
389
/* the actor now owns the transition */
390
g_object_unref (priv->transition);
393
/* if a transition already exist, update its bounds */
394
clutter_transition_set_from (priv->transition,
397
clutter_transition_set_to (priv->transition,
401
/* always use the current easing state */
402
clutter_timeline_set_duration (CLUTTER_TIMELINE (priv->transition),
403
info->cur_state->easing_duration);
404
clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (priv->transition),
405
info->cur_state->easing_mode);
407
/* ensure that we start from the beginning */
408
clutter_timeline_rewind (CLUTTER_TIMELINE (priv->transition));
409
clutter_timeline_start (CLUTTER_TIMELINE (priv->transition));
413
* clutter_scroll_actor_scroll_to_rect:
414
* @actor: a #ClutterScrollActor
415
* @rect: a #ClutterRect
417
* Scrolls @actor so that @rect is in the visible portion.
422
clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor,
423
const ClutterRect *rect)
427
g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor));
428
g_return_if_fail (rect != NULL);
432
/* normalize, so that we have a valid origin */
433
clutter_rect_normalize (&n_rect);
435
clutter_scroll_actor_scroll_to_point (actor, &n_rect.origin);