mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
Add ClutterScrollActor
ClutterScrollActor is an actor that allows showing a portion of its contents.
This commit is contained in:
parent
4d34a2229d
commit
999bbe20a5
@ -108,6 +108,7 @@ source_h = \
|
||||
$(srcdir)/clutter-property-transition.h \
|
||||
$(srcdir)/clutter-script.h \
|
||||
$(srcdir)/clutter-scriptable.h \
|
||||
$(srcdir)/clutter-scroll-actor.h \
|
||||
$(srcdir)/clutter-settings.h \
|
||||
$(srcdir)/clutter-shader-effect.h \
|
||||
$(srcdir)/clutter-shader-types.h \
|
||||
@ -186,6 +187,7 @@ source_c = \
|
||||
$(srcdir)/clutter-script.c \
|
||||
$(srcdir)/clutter-script-parser.c \
|
||||
$(srcdir)/clutter-scriptable.c \
|
||||
$(srcdir)/clutter-scroll-actor.c \
|
||||
$(srcdir)/clutter-settings.c \
|
||||
$(srcdir)/clutter-shader-effect.c \
|
||||
$(srcdir)/clutter-shader-types.c \
|
||||
|
@ -1213,6 +1213,26 @@ typedef enum {
|
||||
CLUTTER_ORIENTATION_VERTICAL
|
||||
} ClutterOrientation;
|
||||
|
||||
/**
|
||||
* ClutterScrollMode:
|
||||
* @CLUTTER_SCROLL_NONE: Ignore scrolling
|
||||
* @CLUTTER_SCROLL_HORIZONTALLY: Scroll only horizontally
|
||||
* @CLUTTER_SCROLL_VERTICALLY: Scroll only vertically
|
||||
* @CLUTTER_SCROLL_BOTH: Scroll in both directions
|
||||
*
|
||||
* Scroll modes.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
typedef enum { /*< prefix=CLUTTER_SCROLL >*/
|
||||
CLUTTER_SCROLL_NONE = 0,
|
||||
|
||||
CLUTTER_SCROLL_HORIZONTALLY = 1 << 0,
|
||||
CLUTTER_SCROLL_VERTICALLY = 1 << 1,
|
||||
|
||||
CLUTTER_SCROLL_BOTH = CLUTTER_SCROLL_HORIZONTALLY | CLUTTER_SCROLL_VERTICALLY
|
||||
} ClutterScrollMode;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ENUMS_H__ */
|
||||
|
478
clutter/clutter-scroll-actor.c
Normal file
478
clutter/clutter-scroll-actor.c
Normal file
@ -0,0 +1,478 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
*
|
||||
* 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 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-scroll-actor
|
||||
* @Title: ClutterScrollActor
|
||||
* @Short_Description: An actor for displaying a portion of its children
|
||||
*
|
||||
* #ClutterScrollActor is an actor that can be used to display a portion
|
||||
* of the contents of its children.
|
||||
*
|
||||
* The extent of the area of a #ClutterScrollActor is defined by the size
|
||||
* of its children; the visible region of the children of a #ClutterScrollActor
|
||||
* is set by using clutter_scroll_actor_scroll_to_point() or by using
|
||||
* clutter_scroll_actor_scroll_to_rect() to define a point or a rectangle
|
||||
* acting as the origin, respectively.
|
||||
*
|
||||
* #ClutterScrollActor does not provide pointer or keyboard event handling,
|
||||
* nor does it provide visible scroll handles.
|
||||
*
|
||||
* #ClutterScrollActor is available since Clutter 1.12.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-scroll-actor.h"
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-animatable.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-property-transition.h"
|
||||
#include "clutter-transition.h"
|
||||
|
||||
struct _ClutterScrollActorPrivate
|
||||
{
|
||||
ClutterPoint scroll_to;
|
||||
|
||||
ClutterScrollMode scroll_mode;
|
||||
|
||||
ClutterTransition *transition;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_SCROLL_MODE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ANIM_PROP_0,
|
||||
|
||||
ANIM_PROP_SCROLL_TO,
|
||||
|
||||
ANIM_PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
|
||||
static GParamSpec *animatable_props[ANIM_PROP_LAST] = { NULL, };
|
||||
|
||||
static ClutterAnimatableIface *parent_animatable_iface = NULL;
|
||||
|
||||
static void clutter_animatable_iface_init (ClutterAnimatableIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterScrollActor, clutter_scroll_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_ANIMATABLE,
|
||||
clutter_animatable_iface_init))
|
||||
|
||||
static void
|
||||
clutter_scroll_actor_apply_transform (ClutterActor *actor,
|
||||
CoglMatrix *transform)
|
||||
{
|
||||
ClutterScrollActorPrivate *priv = CLUTTER_SCROLL_ACTOR (actor)->priv;
|
||||
float x_factor, y_factor;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_scroll_actor_parent_class)->apply_transform (actor, transform);
|
||||
|
||||
if (priv->scroll_mode & CLUTTER_SCROLL_HORIZONTALLY)
|
||||
x_factor = -priv->scroll_to.x;
|
||||
else
|
||||
x_factor = 0.f;
|
||||
|
||||
if (priv->scroll_mode & CLUTTER_SCROLL_VERTICALLY)
|
||||
y_factor = -priv->scroll_to.y;
|
||||
else
|
||||
y_factor = 0.f;
|
||||
|
||||
cogl_matrix_translate (transform, x_factor, y_factor, 0.0f);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_scroll_actor_paint (ClutterActor *actor)
|
||||
{
|
||||
ClutterScrollActorPrivate *priv = CLUTTER_SCROLL_ACTOR (actor)->priv;
|
||||
ClutterActorBox allocation;
|
||||
float width, height;
|
||||
float x, y;
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &allocation);
|
||||
clutter_actor_box_get_size (&allocation, &width, &height);
|
||||
|
||||
if (priv->scroll_mode & CLUTTER_SCROLL_HORIZONTALLY)
|
||||
x = priv->scroll_to.x;
|
||||
else
|
||||
x = 0.f;
|
||||
|
||||
if (priv->scroll_mode & CLUTTER_SCROLL_VERTICALLY)
|
||||
y = priv->scroll_to.y;
|
||||
else
|
||||
y = 0.f;
|
||||
|
||||
/* offset the clip so that we keep it at the right place */
|
||||
cogl_clip_push_rectangle (x,
|
||||
y,
|
||||
x + width,
|
||||
y + height);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_scroll_actor_parent_class)->paint (actor);
|
||||
|
||||
cogl_clip_pop ();
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_scroll_actor_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterScrollActor *actor = CLUTTER_SCROLL_ACTOR (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCROLL_MODE:
|
||||
clutter_scroll_actor_set_scroll_mode (actor, g_value_get_flags (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_scroll_actor_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterScrollActor *actor = CLUTTER_SCROLL_ACTOR (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SCROLL_MODE:
|
||||
g_value_set_flags (value, actor->priv->scroll_mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_scroll_actor_class_init (ClutterScrollActorClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (ClutterScrollActorPrivate));
|
||||
|
||||
gobject_class->set_property = clutter_scroll_actor_set_property;
|
||||
gobject_class->get_property = clutter_scroll_actor_get_property;
|
||||
|
||||
actor_class->apply_transform = clutter_scroll_actor_apply_transform;
|
||||
actor_class->paint = clutter_scroll_actor_paint;
|
||||
|
||||
/**
|
||||
* ClutterScrollActor:scroll-mode:
|
||||
*
|
||||
* The scrollin direction.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
obj_props[PROP_SCROLL_MODE] =
|
||||
g_param_spec_flags ("scroll-mode",
|
||||
P_("Scroll Mode"),
|
||||
P_("The scrolling direction"),
|
||||
CLUTTER_TYPE_SCROLL_MODE,
|
||||
CLUTTER_SCROLL_BOTH,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_scroll_actor_init (ClutterScrollActor *self)
|
||||
{
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_SCROLL_ACTOR,
|
||||
ClutterScrollActorPrivate);
|
||||
|
||||
self->priv->scroll_mode = CLUTTER_SCROLL_BOTH;
|
||||
}
|
||||
|
||||
static GParamSpec *
|
||||
clutter_scroll_actor_find_property (ClutterAnimatable *animatable,
|
||||
const char *property_name)
|
||||
{
|
||||
if (strcmp (property_name, "scroll-to") == 0)
|
||||
return animatable_props[ANIM_PROP_SCROLL_TO];
|
||||
|
||||
return parent_animatable_iface->find_property (animatable, property_name);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_scroll_actor_set_final_state (ClutterAnimatable *animatable,
|
||||
const char *property_name,
|
||||
const GValue *value)
|
||||
{
|
||||
if (strcmp (property_name, "scroll-to") == 0)
|
||||
{
|
||||
ClutterScrollActor *self = CLUTTER_SCROLL_ACTOR (animatable);
|
||||
const ClutterPoint *point = g_value_get_boxed (value);
|
||||
|
||||
if (point == NULL)
|
||||
clutter_point_init (&self->priv->scroll_to, 0.f, 0.f);
|
||||
else
|
||||
self->priv->scroll_to = *point;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
|
||||
}
|
||||
else
|
||||
parent_animatable_iface->set_final_state (animatable, property_name, value);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_scroll_actor_get_initial_state (ClutterAnimatable *animatable,
|
||||
const char *property_name,
|
||||
GValue *value)
|
||||
{
|
||||
if (strcmp (property_name, "scroll-to") == 0)
|
||||
{
|
||||
ClutterScrollActor *self = CLUTTER_SCROLL_ACTOR (animatable);
|
||||
|
||||
g_value_set_boxed (value, &self->priv->scroll_to);
|
||||
}
|
||||
else
|
||||
parent_animatable_iface->get_initial_state (animatable, property_name, value);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_animatable_iface_init (ClutterAnimatableIface *iface)
|
||||
{
|
||||
parent_animatable_iface = g_type_interface_peek_parent (iface);
|
||||
|
||||
animatable_props[ANIM_PROP_SCROLL_TO] =
|
||||
g_param_spec_boxed ("scroll-to",
|
||||
"Scroll To",
|
||||
"The point to scroll the actor to",
|
||||
CLUTTER_TYPE_POINT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
CLUTTER_PARAM_ANIMATABLE);
|
||||
|
||||
iface->find_property = clutter_scroll_actor_find_property;
|
||||
iface->get_initial_state = clutter_scroll_actor_get_initial_state;
|
||||
iface->set_final_state = clutter_scroll_actor_set_final_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_scroll_actor_new:
|
||||
*
|
||||
* Creates a new #ClutterScrollActor.
|
||||
*
|
||||
* Return value: (transfer full): The newly created #ClutterScrollActor
|
||||
* instance.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_scroll_actor_new (void)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_SCROLL_ACTOR, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_scroll_actor_set_scroll_mode:
|
||||
* @actor: a #ClutterScrollActor
|
||||
* @mode: a #ClutterScrollMode
|
||||
*
|
||||
* Sets the #ClutterScrollActor:scroll-mode property.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
void
|
||||
clutter_scroll_actor_set_scroll_mode (ClutterScrollActor *actor,
|
||||
ClutterScrollMode mode)
|
||||
{
|
||||
ClutterScrollActorPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor));
|
||||
|
||||
priv = actor->priv;
|
||||
|
||||
if (priv->scroll_mode == mode)
|
||||
return;
|
||||
|
||||
priv->scroll_mode = mode;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (actor), obj_props[PROP_SCROLL_MODE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_scroll_actor_get_scroll_mode:
|
||||
* @actor: a #ClutterScrollActor
|
||||
*
|
||||
* Retrieves the #ClutterScrollActor:scroll-mode property
|
||||
*
|
||||
* Return value: the scrolling mode
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterScrollMode
|
||||
clutter_scroll_actor_get_scroll_mode (ClutterScrollActor *actor)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor), CLUTTER_SCROLL_NONE);
|
||||
|
||||
return actor->priv->scroll_mode;
|
||||
}
|
||||
|
||||
static void
|
||||
on_transition_completed (ClutterTimeline *timeline,
|
||||
ClutterScrollActor *actor)
|
||||
{
|
||||
actor->priv->transition = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_scroll_actor_scroll_to_point:
|
||||
* @actor: a #ClutterScrollActor
|
||||
* @point: a #ClutterPoint
|
||||
*
|
||||
* Scrolls the contents of @actor so that @point is the new origin
|
||||
* of the visible area.
|
||||
*
|
||||
* This function will use the currently set easing state of the @actor
|
||||
* to transition from the current scroll origin to the new one.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
void
|
||||
clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
|
||||
const ClutterPoint *point)
|
||||
{
|
||||
ClutterScrollActorPrivate *priv;
|
||||
const ClutterAnimationInfo *info;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor));
|
||||
g_return_if_fail (point != NULL);
|
||||
|
||||
priv = actor->priv;
|
||||
|
||||
if (clutter_point_equals (&priv->scroll_to, point))
|
||||
return;
|
||||
|
||||
info = _clutter_actor_get_animation_info (CLUTTER_ACTOR (actor));
|
||||
|
||||
/* jump to the end if there is no easing state, or if the easing
|
||||
* state has a duration of 0 msecs
|
||||
*/
|
||||
if (info->cur_state == NULL ||
|
||||
info->cur_state->easing_duration == 0)
|
||||
{
|
||||
/* ensure that we remove any currently running transition */
|
||||
if (priv->transition != NULL)
|
||||
{
|
||||
clutter_actor_remove_transition (CLUTTER_ACTOR (actor),
|
||||
"scroll-to");
|
||||
priv->transition = NULL;
|
||||
}
|
||||
|
||||
priv->scroll_to = *point;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->transition == NULL)
|
||||
{
|
||||
priv->transition = clutter_property_transition_new ("scroll-to");
|
||||
clutter_transition_set_animatable (priv->transition,
|
||||
CLUTTER_ANIMATABLE (actor));
|
||||
clutter_transition_set_remove_on_complete (priv->transition, TRUE);
|
||||
|
||||
/* delay only makes sense if the transition has just been created */
|
||||
clutter_timeline_set_delay (CLUTTER_TIMELINE (priv->transition),
|
||||
info->cur_state->easing_delay);
|
||||
/* we need this to clear the priv->transition pointer */
|
||||
g_signal_connect (priv->transition, "completed",
|
||||
G_CALLBACK (on_transition_completed),
|
||||
actor);
|
||||
|
||||
clutter_actor_add_transition (CLUTTER_ACTOR (actor),
|
||||
"scroll-to",
|
||||
priv->transition);
|
||||
|
||||
/* the actor now owns the transition */
|
||||
g_object_unref (priv->transition);
|
||||
}
|
||||
|
||||
/* if a transition already exist, update its bounds */
|
||||
clutter_transition_set_from (priv->transition,
|
||||
CLUTTER_TYPE_POINT,
|
||||
&priv->scroll_to);
|
||||
clutter_transition_set_to (priv->transition,
|
||||
CLUTTER_TYPE_POINT,
|
||||
point);
|
||||
|
||||
/* always use the current easing state */
|
||||
clutter_timeline_set_duration (CLUTTER_TIMELINE (priv->transition),
|
||||
info->cur_state->easing_duration);
|
||||
clutter_timeline_set_progress_mode (CLUTTER_TIMELINE (priv->transition),
|
||||
info->cur_state->easing_mode);
|
||||
|
||||
/* ensure that we start from the beginning */
|
||||
clutter_timeline_rewind (CLUTTER_TIMELINE (priv->transition));
|
||||
clutter_timeline_start (CLUTTER_TIMELINE (priv->transition));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_scroll_actor_scroll_to_rect:
|
||||
* @actor: a #ClutterScrollActor
|
||||
* @rect: a #ClutterRect
|
||||
*
|
||||
* Scrolls @actor so that @rect is in the visible portion.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
void
|
||||
clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor,
|
||||
const ClutterRect *rect)
|
||||
{
|
||||
ClutterRect n_rect;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_SCROLL_ACTOR (actor));
|
||||
g_return_if_fail (rect != NULL);
|
||||
|
||||
n_rect = *rect;
|
||||
|
||||
/* normalize, so that we have a valid origin */
|
||||
clutter_rect_normalize (&n_rect);
|
||||
|
||||
clutter_scroll_actor_scroll_to_point (actor, &n_rect.origin);
|
||||
}
|
97
clutter/clutter-scroll-actor.h
Normal file
97
clutter/clutter-scroll-actor.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
*
|
||||
* 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 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_SCROLL_ACTOR_H__
|
||||
#define __CLUTTER_SCROLL_ACTOR_H__
|
||||
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-actor.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_SCROLL_ACTOR (clutter_scroll_actor_get_type ())
|
||||
#define CLUTTER_SCROLL_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SCROLL_ACTOR, ClutterScrollActor))
|
||||
#define CLUTTER_IS_SCROLL_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SCROLL_ACTOR))
|
||||
#define CLUTTER_SCROLL_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SCROLL_ACTOR, ClutterScrollActorClass))
|
||||
#define CLUTTER_IS_SCROLL_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SCROLL_ACTOR))
|
||||
#define CLUTTER_SCROLL_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SCROLL_ACTOR, ClutterScrollActorClass))
|
||||
|
||||
typedef struct _ClutterScrollActorPrivate ClutterScrollActorPrivate;
|
||||
typedef struct _ClutterScrollActorClass ClutterScrollActorClass;
|
||||
|
||||
/**
|
||||
* ClutterScrollActor:
|
||||
*
|
||||
* The <structname>ClutterScrollActor</structname> structure contains only
|
||||
* private data, and should be accessed using the provided API.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
struct _ClutterScrollActor
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActor parent_instance;
|
||||
|
||||
ClutterScrollActorPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterScrollActorClass:
|
||||
*
|
||||
* The <structname>ClutterScrollActor</structname> structure contains only
|
||||
* private data.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
struct _ClutterScrollActorClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_instance;
|
||||
|
||||
gpointer _padding[8];
|
||||
};
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
GType clutter_scroll_actor_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterActor * clutter_scroll_actor_new (void);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_scroll_actor_set_scroll_mode (ClutterScrollActor *actor,
|
||||
ClutterScrollMode mode);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
ClutterScrollMode clutter_scroll_actor_get_scroll_mode (ClutterScrollActor *actor);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_scroll_actor_scroll_to_point (ClutterScrollActor *actor,
|
||||
const ClutterPoint *point);
|
||||
CLUTTER_AVAILABLE_IN_1_12
|
||||
void clutter_scroll_actor_scroll_to_rect (ClutterScrollActor *actor,
|
||||
const ClutterRect *rect);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_SCROLL_ACTOR_H__ */
|
@ -58,6 +58,7 @@ typedef struct _ClutterLayoutManager ClutterLayoutManager;
|
||||
typedef struct _ClutterActorIter ClutterActorIter;
|
||||
typedef struct _ClutterPaintNode ClutterPaintNode;
|
||||
typedef struct _ClutterContent ClutterContent; /* dummy */
|
||||
typedef struct _ClutterScrollActor ClutterScrollActor;
|
||||
|
||||
typedef struct _ClutterInterval ClutterInterval;
|
||||
typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy */
|
||||
|
@ -88,6 +88,7 @@
|
||||
#include "clutter-property-transition.h"
|
||||
#include "clutter-scriptable.h"
|
||||
#include "clutter-script.h"
|
||||
#include "clutter-scroll-actor.h"
|
||||
#include "clutter-settings.h"
|
||||
#include "clutter-shader-effect.h"
|
||||
#include "clutter-shader-types.h"
|
||||
|
@ -1085,7 +1085,14 @@ clutter_script_lookup_filename
|
||||
clutter_script_new
|
||||
clutter_script_set_translation_domain
|
||||
clutter_script_unmerge_objects
|
||||
clutter_scroll_actor_get_scroll_mode
|
||||
clutter_scroll_actor_get_type
|
||||
clutter_scroll_actor_new
|
||||
clutter_scroll_actor_scroll_to_point
|
||||
clutter_scroll_actor_scroll_to_rect
|
||||
clutter_scroll_actor_set_scroll_mode
|
||||
clutter_scroll_direction_get_type
|
||||
clutter_scroll_mode_get_type
|
||||
clutter_settings_get_default
|
||||
clutter_settings_get_type
|
||||
clutter_set_default_frame_rate
|
||||
|
@ -58,7 +58,8 @@ UNIT_TESTS = \
|
||||
test-transitions.c \
|
||||
test-content.c \
|
||||
test-canvas.c \
|
||||
test-keyframe-transition.c
|
||||
test-keyframe-transition.c \
|
||||
test-scroll-actor.c
|
||||
|
||||
if X11_TESTS
|
||||
UNIT_TESTS += test-pixmap.c
|
||||
|
179
tests/interactive/test-scroll-actor.c
Normal file
179
tests/interactive/test-scroll-actor.c
Normal file
@ -0,0 +1,179 @@
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static const char *menu_items_name[] = {
|
||||
"Option 1",
|
||||
"Option 2",
|
||||
"Option 3",
|
||||
"Option 4",
|
||||
"Option 5",
|
||||
"Option 6",
|
||||
"Option 7",
|
||||
"Option 8",
|
||||
"Option 9",
|
||||
"Option 10",
|
||||
"Option 11",
|
||||
};
|
||||
|
||||
static const guint menu_items_len = G_N_ELEMENTS (menu_items_name);
|
||||
|
||||
static void
|
||||
select_item_at_index (ClutterActor *scroll,
|
||||
int index_)
|
||||
{
|
||||
ClutterPoint point;
|
||||
ClutterActor *menu, *item;
|
||||
gpointer old_selected;
|
||||
|
||||
menu = clutter_actor_get_first_child (scroll);
|
||||
|
||||
old_selected = g_object_get_data (G_OBJECT (scroll), "selected-item");
|
||||
if (old_selected != NULL)
|
||||
{
|
||||
item = clutter_actor_get_child_at_index (menu, GPOINTER_TO_INT (old_selected));
|
||||
clutter_text_set_color (CLUTTER_TEXT (item), CLUTTER_COLOR_White);
|
||||
}
|
||||
|
||||
if (index_ < 0)
|
||||
index_ = clutter_actor_get_n_children (menu) - 1;
|
||||
else if (index_ >= clutter_actor_get_n_children (menu))
|
||||
index_ = 0;
|
||||
|
||||
item = clutter_actor_get_child_at_index (menu, index_);
|
||||
clutter_actor_get_position (item, &point.x, &point.y);
|
||||
|
||||
clutter_actor_save_easing_state (scroll);
|
||||
clutter_scroll_actor_scroll_to_point (CLUTTER_SCROLL_ACTOR (scroll), &point);
|
||||
clutter_actor_restore_easing_state (scroll);
|
||||
|
||||
clutter_text_set_color (CLUTTER_TEXT (item), CLUTTER_COLOR_LightSkyBlue);
|
||||
|
||||
g_object_set_data (G_OBJECT (scroll), "selected-item",
|
||||
GINT_TO_POINTER (index_));
|
||||
}
|
||||
|
||||
static void
|
||||
select_next_item (ClutterActor *scroll)
|
||||
{
|
||||
gpointer selected_ = g_object_get_data (G_OBJECT (scroll), "selected-item");
|
||||
|
||||
select_item_at_index (scroll, GPOINTER_TO_INT (selected_) + 1);
|
||||
}
|
||||
|
||||
static void
|
||||
select_prev_item (ClutterActor *scroll)
|
||||
{
|
||||
gpointer selected_ = g_object_get_data (G_OBJECT (scroll), "selected-item");
|
||||
|
||||
select_item_at_index (scroll, GPOINTER_TO_INT (selected_) - 1);
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
create_menu_item (const char *name)
|
||||
{
|
||||
ClutterActor *text;
|
||||
|
||||
text = clutter_text_new ();
|
||||
clutter_text_set_font_name (CLUTTER_TEXT (text), "Sans Bold 24");
|
||||
clutter_text_set_text (CLUTTER_TEXT (text), name);
|
||||
clutter_text_set_color (CLUTTER_TEXT (text), CLUTTER_COLOR_White);
|
||||
clutter_actor_set_margin_left (text, 12.f);
|
||||
clutter_actor_set_margin_right (text, 12.f);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
create_menu_actor (ClutterActor *scroll)
|
||||
{
|
||||
ClutterActor *menu;
|
||||
ClutterLayoutManager *layout_manager;
|
||||
guint i;
|
||||
|
||||
layout_manager = clutter_box_layout_new ();
|
||||
clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout_manager),
|
||||
CLUTTER_ORIENTATION_VERTICAL);
|
||||
clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout_manager), 12.f);
|
||||
|
||||
menu = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (menu, layout_manager);
|
||||
clutter_actor_set_background_color (menu, CLUTTER_COLOR_Black);
|
||||
|
||||
for (i = 0; i < menu_items_len; i++)
|
||||
clutter_actor_add_child (menu, create_menu_item (menu_items_name[i]));
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
create_scroll_actor (ClutterActor *stage)
|
||||
{
|
||||
ClutterActor *scroll;
|
||||
|
||||
scroll = clutter_scroll_actor_new ();
|
||||
clutter_actor_set_name (scroll, "scroll");
|
||||
|
||||
clutter_actor_set_position (scroll, 0.f, 18.f);
|
||||
clutter_actor_add_constraint (scroll, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
|
||||
clutter_actor_add_constraint (scroll, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -36.f));
|
||||
|
||||
clutter_scroll_actor_set_scroll_mode (CLUTTER_SCROLL_ACTOR (scroll),
|
||||
CLUTTER_SCROLL_VERTICALLY);
|
||||
|
||||
clutter_actor_add_child (scroll, create_menu_actor (scroll));
|
||||
|
||||
select_item_at_index (scroll, 0);
|
||||
|
||||
return scroll;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_key_press (ClutterActor *stage,
|
||||
ClutterEvent *event,
|
||||
gpointer unused)
|
||||
{
|
||||
ClutterActor *scroll;
|
||||
guint key_symbol;
|
||||
|
||||
scroll = clutter_actor_get_first_child (stage);
|
||||
|
||||
key_symbol = clutter_event_get_key_symbol (event);
|
||||
|
||||
if (key_symbol == CLUTTER_KEY_Up)
|
||||
select_prev_item (scroll);
|
||||
else if (key_symbol == CLUTTER_KEY_Down)
|
||||
select_next_item (scroll);
|
||||
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_scroll_actor_describe (void)
|
||||
{
|
||||
return "Scrolling actor example.";
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_scroll_actor_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Scroll Actor");
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
g_signal_connect (stage, "key-press-event", G_CALLBACK (on_key_press), NULL);
|
||||
|
||||
clutter_actor_add_child (stage, create_scroll_actor (stage));
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user