2 * Copyright (C) 2007 OpenedHand Limited
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Author: Neil Jagdish Patel <njp@o-hand.com>
23 #include "astro-songs.h"
25 #include <libastro-desktop/astro-defines.h>
26 #include <libastro-desktop/astro-application.h>
27 #include <libastro-desktop/astro-window.h>
29 #include "astro-music-window.h"
31 G_DEFINE_TYPE (AstroSongs, astro_songs, CLUTTER_TYPE_GROUP);
33 #define ASTRO_SONGS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj),\
34 ASTRO_TYPE_SONGS, AstroSongsPrivate))
36 struct _AstroSongsPrivate
47 ClutterEffectTemplate *temp;
48 ClutterTimeline *timeline;
51 static gchar *song_names[] = {
72 static gboolean on_event (AstroSongs *songs, ClutterEvent *event);
74 /* Public Functions */
76 astro_songs_set_active (AstroSongs *songs, gboolean active)
78 AstroSongsPrivate *priv;
80 g_return_if_fail (ASTRO_IS_SONGS (songs));
85 g_signal_connect (songs, "event", G_CALLBACK (on_event), NULL);
89 g_signal_handlers_disconnect_by_func (songs, on_event, NULL);
90 priv->mousedown = FALSE;
95 /* Private functions */
97 bounds_check (ClutterActor *group, AstroSongs *songs)
99 AstroSongsPrivate *priv;
102 g_return_if_fail (ASTRO_IS_SONGS (songs));
105 height = clutter_actor_get_height (group);
106 y = clutter_actor_get_y (group);
108 if (y < 0 && y < (-1*height+(ALBUM_SIZE/2)))
110 y = (-1*height) + ALBUM_SIZE/2;
113 if ( y > 0 && y > (ALBUM_SIZE/2))
118 priv->timeline = clutter_effect_move (priv->temp, priv->group,
119 clutter_actor_get_x (priv->group),
125 on_event (AstroSongs *songs, ClutterEvent *event)
128 #define SPEED_FACTOR 1.5
129 AstroSongsPrivate *priv = songs->priv;
131 if (event->type == CLUTTER_BUTTON_PRESS)
133 priv->starty = priv->lasty = event->button.y;
135 priv->start_time = event->button.time;
137 if (clutter_timeline_is_playing (priv->timeline))
138 clutter_timeline_stop (priv->timeline);
141 else if (event->type == CLUTTER_BUTTON_RELEASE)
143 gint endy = clutter_actor_get_y (priv->group);
144 guint32 time = event->button.time - priv->start_time;
147 factor = 2.0 - (time/event->button.time);
153 else if (event->button.y > priv->starty)
156 * The mouse from left to right, so we have to *add* pixels to the
157 * current group position to make it move to the right
159 endy += (event->motion.y - priv->starty) * SPEED_FACTOR * factor;
162 else if (event->button.y < priv->starty)
165 * The mouse from right to left, so we have to *minus* p.yels to the
166 * current group position to make it move to the left
168 endy -= (priv->starty - event->button.y) * SPEED_FACTOR * factor;
173 /* If the click was fast, treat it as a standard 'clicked' event */
175 g_debug ("Song clicked\n");
176 priv->starty = priv->lasty = 0;
180 priv->timeline = clutter_effect_move (priv->temp, priv->group,
181 clutter_actor_get_x (priv->group),
183 (ClutterEffectCompleteFunc)bounds_check,
186 priv->starty = priv->lasty = 0;
188 else if (event->type == CLUTTER_MOTION)
194 if (event->motion.y > priv->lasty)
196 offset = event->motion.y - priv->lasty;
200 offset = priv->lasty - event->motion.y;
203 priv->lasty = event->motion.y;
204 clutter_actor_set_position (priv->group,
205 clutter_actor_get_x (priv->group),
206 clutter_actor_get_y (priv->group)+ offset);
214 astro_songs_class_init (AstroSongsClass *klass)
216 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
218 g_type_class_add_private (gobject_class, sizeof (AstroSongsPrivate));
222 astro_songs_init (AstroSongs *songs)
224 #define FONT_SIZE (ALBUM_SIZE/8)
225 #define ROW_SPACING (FONT_SIZE*1.3)
227 AstroSongsPrivate *priv;
228 ClutterColor white = { 0xff, 0xff, 0xff, 0xff };
230 gint i, offset = ROW_SPACING/2;
232 priv = songs->priv = ASTRO_SONGS_GET_PRIVATE (songs);
234 priv->mousedown = FALSE;
236 priv->group = clutter_group_new ();
237 clutter_container_add_actor (CLUTTER_CONTAINER (songs), priv->group);
238 clutter_actor_set_position (priv->group, 0, 0);
240 font = g_strdup_printf ("Sans %d", FONT_SIZE);
242 for (i = 0; i < 10; i++)
246 row = clutter_label_new_full (font, song_names[i], &white);
248 clutter_container_add_actor (CLUTTER_CONTAINER (priv->group), row);
249 clutter_actor_set_anchor_point_from_gravity (row,
250 CLUTTER_GRAVITY_WEST);
251 clutter_actor_set_position (row, 10, offset);
252 clutter_actor_set_scale (row, 1/ALBUM_SCALE, 1/ALBUM_SCALE);
253 clutter_actor_set_opacity (row, i%2 ? 200: 255);
255 offset += ROW_SPACING;
258 priv->timeline = clutter_timeline_new_for_duration (1000);
259 priv->temp = clutter_effect_template_new (priv->timeline,
260 clutter_sine_inc_func);
262 clutter_actor_set_reactive (CLUTTER_ACTOR (songs), TRUE);
264 clutter_actor_set_clip (CLUTTER_ACTOR (songs),
265 PAD, PAD, ALBUM_SIZE-(2*PAD), ALBUM_SIZE-(2*PAD));
267 clutter_actor_show_all (CLUTTER_ACTOR (priv->group));
268 clutter_actor_show_all (CLUTTER_ACTOR (songs));
273 astro_songs_new (void)
275 ClutterActor *songs = g_object_new (ASTRO_TYPE_SONGS,