changeset 368:080aca2b7c47

Move the animated menu to the MBAF layer
author wycc
date Mon, 16 Mar 2009 08:45:54 +0800
parents e21e9447f545
children 74f079aee083
files examples/menu/Makefile.am examples/menu/animated_menu.c examples/menu/animated_menu.h include/animated_menu.h src/Makefile.am src/mbaf/animated_menu.c
diffstat 6 files changed, 425 insertions(+), 425 deletions(-) [+]
line wrap: on
line diff
--- a/examples/menu/Makefile.am	Sun Mar 15 17:17:06 2009 +0800
+++ b/examples/menu/Makefile.am	Mon Mar 16 08:45:54 2009 +0800
@@ -32,7 +32,7 @@
 noinst_PROGRAMS = menu filebrowser list.so browser.so
 EXTRA_DIST = 
 
-menu_SOURCES = main.c animated_menu.c animated_menu.h
+menu_SOURCES = main.c
 nodist_menu_SOURCES = 
 CFLAGS = @pangocairo_CFLAGS@ -g
 menu_CFLAGS = @pangocairo_CFLAGS@ 
@@ -42,7 +42,7 @@
 	list.mb list.c list.h \
 	browser.mb browser.c browser.h
 
-filebrowser_SOURCES = filebrowser.c animated_menu.c animated_menu.h
+filebrowser_SOURCES = filebrowser.c
 filebrowser_CFLAGS = @pangocairo_CFLAGS@ 
 filebrowser_LDFLAGS = @pangocairo_LIBS@ 
 filebrowser_LDADD = $(top_builddir)/src/libmbfly.la
--- a/examples/menu/animated_menu.c	Sun Mar 15 17:17:06 2009 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,390 +0,0 @@
-#include <stdio.h>
-#include <mb.h>
-#include <string.h>
-//#include "menu.h"
-#include "mbapp.h"
-#include <animated_menu.h>
-static void mb_animated_menu_update(mb_animated_menu_t *m);
-static void set_text(coord_t *g, char *text)
-{
-    geo_t *geo;
-    shape_t *shape;
-
-    FOR_COORD_MEMBERS(g, geo) {
-        shape = geo_get_shape(geo);
-        if(shape->obj.obj_type == MBO_TEXT) {
-		sh_text_set_text(shape, text);
-        }
-    }
-}
-
-static void mb_animated_menu_fillMenuContent(mb_animated_menu_t *m)
-{
-    int i;
-    coord_t *textgroup;
-    shape_t *text;
-    coord_t *group;
-    coord_t *lightbar;
-    int tmp;
-    mb_timeval_t start, playing, now;
-    mb_progm_t *progm;
-    mb_word_t *word;
-
-    printf("max item is %d\n", m->max);
-    // fill new item
-    for(i=0;i<8;i++) {
-        group = (coord_t *) m->objects[m->items[i]];
-	if (i < m->max)
-	        set_text(group, m->titles[m->top+i]);
-	else
-	        set_text(group, "");
-    	rdman_coord_changed(MBAPP_RDMAN(m->app),group);
-    }
-
-
-    textgroup = (coord_t *) m->objects[m->items[i]];
-    coord_hide(textgroup);
-    rdman_coord_changed(MBAPP_RDMAN(m->app),textgroup);
-
-    lightbar = (coord_t *) m->lightbar;
-    group = (coord_t *) m->objects[m->cur];
-    coord_y(lightbar) = coord_y(group);
-    rdman_coord_changed(MBAPP_RDMAN(m->app),lightbar);
-    rdman_redraw_changed(MBAPP_RDMAN(m->app));
-}
-
-static void mb_animated_menu_complete(event_t *ev,void *arg)
-{
-    mb_animated_menu_t *m = (mb_animated_menu_t *) arg;
-
-    m->ready++;
-    printf("animated done ready=%d\n", m->ready);
-}
-
-static void mb_animated_menu_fillMenuContentUp(mb_animated_menu_t *m)
-{
-    int i;
-    coord_t *textgroup;
-    shape_t *text;
-    coord_t *group;
-    coord_t *lightbar;
-    int tmp;
-    mb_timeval_t start, playing, now;
-    mb_progm_t *progm;
-    mb_word_t *word;
-
-
-    // fill new item
-    group = (coord_t *) m->objects[m->items[8]];
-    set_text(group, m->titles[m->top]);
-
-    m->progm = progm = mb_progm_new(2, MBAPP_RDMAN(m->app));
-    MB_TIMEVAL_SET(&start, 0, 0);
-    MB_TIMEVAL_SET(&playing, 0, m->speed);
-    word = mb_progm_next_word(progm, &start, &playing);
-    get_now(&now);
-
-    for(i=0;i<7;i++) {
-	//shift to the next item
-        textgroup = (coord_t *) m->objects[m->items[i]];
-	mb_shift_new(0,m->menus_y[i+1]-coord_y(textgroup), textgroup,word);
-    }
-    // fade out the item[7]
-    textgroup = (coord_t *) m->objects[m->items[7]];
-    mb_shift_new(0,100, textgroup,word);
-
-    // fade in the item[8]
-    textgroup = (coord_t *) m->objects[m->items[8]];
-    group = (coord_t *) m->objects[m->items[0]];
-    coord_y(textgroup) = m->menus_y[0]-100;
-    coord_show(textgroup);
-    mb_shift_new(0,100, textgroup,word);
-
-    lightbar = (coord_t *) m->lightbar;
-    mb_shift_new(0,m->menus_y[m->cur]-coord_y(lightbar),lightbar,word);
-    
-    MB_TIMEVAL_SET(&start, 0, m->speed);
-    MB_TIMEVAL_SET(&playing, 0, 0);
-    word = mb_progm_next_word(progm, &start, &playing);
-    textgroup = (coord_t *) m->objects[m->items[7]];
-    mb_visibility_new(VIS_HIDDEN, textgroup,word);
-
-    mb_progm_free_completed(progm);
-    m->ready--;
-    subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m);
-    mb_progm_start(progm, X_MB_tman(MBAPP_RDMAN(m->app)->rt), &now);
-    rdman_redraw_changed(MBAPP_RDMAN(m->app));
-    tmp = m->items[8];
-    for(i=8;i>0;i--) {
-	m->items[i] = m->items[i-1];
-    }
-    m->items[0] = tmp;
-    printf("fill menu\n");
-}
-
-
-static void mb_animated_menu_fillMenuContentDown(mb_animated_menu_t *m)
-{
-    int i;
-    coord_t *textgroup;
-    shape_t *text;
-    coord_t *group;
-    coord_t *lightbar;
-    char name[255];
-    int tmp;
-    mb_timeval_t start, playing, now;
-    mb_progm_t *progm;
-    mb_word_t *word;
-
-
-    // fill new item
-    set_text((coord_t *)m->objects[m->items[8]], m->titles[m->top+7]);
-
-    m->progm = progm = mb_progm_new(2, MBAPP_RDMAN(m->app));
-    MB_TIMEVAL_SET(&start, 0, 0);
-    MB_TIMEVAL_SET(&playing, 0, m->speed);
-    word = mb_progm_next_word(progm, &start, &playing);
-    get_now(&now);
-
-    for(i=1;i<8;i++) {
-	//shift to the next item
-	mb_shift_new(0,m->menus_y[i-1]-coord_y((coord_t *)m->objects[m->items[i]]), (coord_t *) m->objects[m->items[i]],word);
-    }
-    // fade out the item[0]
-    mb_shift_new(0,-100, (coord_t *)m->objects[m->items[0]],word);
-
-    // fade in the item[8]
-    coord_y((coord_t *)m->objects[m->items[8]]) = m->menus_y[7]+100;
-    coord_show(((coord_t *)(m->objects[m->items[8]])));
-    mb_shift_new(0,-100, (coord_t *)m->objects[m->items[8]],word);
-
-    mb_shift_new(0,m->menus_y[m->cur]-coord_y((coord_t *)m->lightbar),((coord_t *)(m->lightbar)),word);
-
-    MB_TIMEVAL_SET(&start, 0, m->speed);
-    MB_TIMEVAL_SET(&playing, 0, 0);
-    word = mb_progm_next_word(progm, &start, &playing);
-    mb_visibility_new(VIS_VISIBLE, (coord_t *) m->objects[m->items[0]],word);
-
-    mb_progm_free_completed(progm);
-    m->ready--;
-    subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m);
-    mb_progm_start(progm, X_MB_tman(MBAPP_RDMAN(m->app)->rt), &now);
-    rdman_redraw_changed(MBAPP_RDMAN(m->app));
-    tmp = m->items[0];
-    for(i=0;i<8;i++) {
-	m->items[i] = m->items[i+1];
-    }
-    m->items[8] = tmp;
-}
-
-void mb_animated_menu_moveLightBar(mb_animated_menu_t *m)
-{
-    mb_timeval_t start, playing, now;
-    mb_progm_t *progm;
-    mb_word_t *word;
-    coord_t *group;
-    coord_t *lightbar;
-
-    m->progm = progm = mb_progm_new(1, MBAPP_RDMAN(m->app));
-    MB_TIMEVAL_SET(&start, 0, 0);
-    MB_TIMEVAL_SET(&playing, 0, m->speed);
-    word = mb_progm_next_word(progm, &start, &playing);
-    get_now(&now);
-
-    lightbar = (coord_t *) m->lightbar;
-    mb_shift_new(0,m->menus_y[m->cur]-coord_y(lightbar),lightbar,word);
-    mb_progm_free_completed(progm);
-    m->ready--;
-    subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m);
-    mb_progm_start(progm, X_MB_tman(MBAPP_RDMAN(m->app)->rt), &now);
-    rdman_redraw_changed(MBAPP_RDMAN(m->app));
-}
-
-static void mb_animated_menu_up(mb_animated_menu_t *m)
-{
-    if (m->cur > 5) {
-	m->cur--;
-        mb_animated_menu_moveLightBar(m);
-	mb_animated_menu_update(m);
-    } else {
-        if (m->top > 0) {
-	    m->top--;
-            mb_animated_menu_fillMenuContentUp(m);
-	    mb_animated_menu_update(m);
-        } else {
-	    if (m->cur == 0) 
-	        return;
-	    m->cur--;
-            mb_animated_menu_moveLightBar(m);
-	    mb_animated_menu_update(m);
-	}
-    }
-}
-static void mb_animated_menu_down(mb_animated_menu_t *m)
-{
-
-    if (m->cur < 5) {
-	if (m->top+m->cur <= m->max) {
-	    m->cur++;
-            mb_animated_menu_moveLightBar(m);
-	    mb_animated_menu_update(m);
-	}
-    } else  {
-        if ((m->top+8) < m->max-1) {
-	    m->top++;
-            mb_animated_menu_fillMenuContentDown(m);
-	    mb_animated_menu_update(m);
-        } else {
-   	    if (m->cur+m->top < m->max-1) {
-	        m->cur++;
-                mb_animated_menu_moveLightBar(m);
-	        mb_animated_menu_update(m);
-	    } else
-	        return;
-	}
-    }
-}
-
-void mb_animated_menu_set_update_callback(mb_animated_menu_t *m, void (*f)(mb_animated_menu_t *m, int sel))
-{
-   m->update_callback = f;
-}
-void mb_animated_menu_set_callback(mb_animated_menu_t *m, void (*f)(mb_animated_menu_t *m, int sel))
-{
-   m->callback = f;
-}
-static void mb_animated_menu_update(mb_animated_menu_t *m)
-{
-   if (m->update_callback)
-	   m->update_callback(m,m->top+m->cur);
-
-}
-static void mb_animated_menu_select(mb_animated_menu_t *m)
-{
-   if (m->callback)
-	   m->callback(m,m->top+m->cur);
-}
-
-// Send the pending key in the animation progm complete callback
-static void mb_animated_menu_keyHandler(event_t *ev, void *arg);
-static void mb_animated_menu_send_pending_key(event_t *ev,void *arg)
-{
-    mb_animated_menu_t *m = (mb_animated_menu_t *) arg;
-
-    if (m->ready<=0) 
-	    mb_animated_menu_keyHandler((event_t *) &m->pending_key,m);
-}
-static void mb_animated_menu_keyHandler(event_t *ev, void *arg)
-{
-    mb_animated_menu_t *m = (mb_animated_menu_t *) arg;
-    X_kb_event_t *xkey = (X_kb_event_t *)ev;
-    if(xkey->event.type != EVT_KB_PRESS) {
-        return;
-    }
-    printf("read=%d\n",m->ready);
-    if (m->ready<=0) {
-    	    subject_add_observer(mb_progm_get_complete(m->progm), mb_animated_menu_send_pending_key,m);
-	    mb_progm_finish(m->progm);
-	    m->pending_key = *xkey;
-	    return;
-    }
-    switch(xkey->sym) {
-    case 0xff51:		/* left */
-	break;
-
-    case 0xff52:		/* up */
-	mb_animated_menu_up(m);
-	break;
-
-    case 0xff53:		/* right */
-	break;
-
-    case 0xff54:		/* down */
-	mb_animated_menu_down(m);
-	break;
-
-    case 0xff0d:		/* enter */
-	mb_animated_menu_select(m);
-	break;
-    default:
-	return;
-    }
-}
-
-/** \brief Create an instace of animated menu. 
- *
- *   The objectnames is used to extract symbols from the SVG file. 
- *         ${objectnames}0 - ${objectnames}8 is the text object.
- *         ${objectnames}_lightbar is the lightbar.
- *
- */
-mb_animated_menu_t *mb_animated_menu_new(MBApp *app,mb_sprite_t *sp,char *objnames,char *menus[])
-{
-    mb_animated_menu_t *m;
-    int i,len;
-    char name[255];
-    mb_obj_t *l;
-    int ii;
-
-    if (menus == NULL)
-	    i=0;
-    else
-	    for(i=0;menus[i];i++);
-    ii=9;
-    
-    m = (mb_animated_menu_t *) malloc(sizeof(mb_animated_menu_t));
-    m->items = (int *) malloc(sizeof(int)*ii*2+sizeof(mb_obj_t *)*ii);
-    m->app = app;
-    m->sprite = sp;
-    m->top = 0;
-    m->cur = 0;
-    m->ready = 1;
-    m->max = i;
-    m->menus_y = (int *) (m->items+ii);
-    m->objects = (mb_obj_t **) (m->menus_y+ii);
-    m->callback = NULL;
-    m->update_callback = NULL;
-    m->speed = 300000;
-    for(i=0;i<9;i++) {
-        m->items[i] = i;
-	snprintf(name,sizeof(name),"%s%d", objnames, i+1);
-	l = MB_SPRITE_GET_OBJ(sp,name);
-	if (l == NULL) {
-		fprintf(stderr,"Can not find symbol %s\n",name);
-	}
-	m->objects[i] = (mb_obj_t *) l;
-	m->menus_y[i] = coord_y((coord_t*)l);
-    }
-    m->titles = menus;
-    snprintf(name,sizeof(name), "%s_lightbar", objnames);
-    m->lightbar = (mb_obj_t *) MB_SPRITE_GET_OBJ(sp,name);
-    if (m->lightbar==NULL)
-	    fprintf(stderr,"Can not find object %s\n",name);
-    mb_animated_menu_fillMenuContent(m);
-    subject_add_observer(MBAPP_keySubject(app), mb_animated_menu_keyHandler,m);
-    return m;
-}
-
-void mb_animated_menu_set_titles(mb_animated_menu_t *m, char *menus[])
-{
-    int i;
-    for(i=0;menus[i];i++);
-
-    m->max = i;
-    m->top = 0;
-    m->cur = 0;
-    m->titles = menus;
-    mb_animated_menu_fillMenuContent(m);
-    mb_animated_menu_moveLightBar(m);
-}
-
-
-void mb_animated_menu_set_speed(mb_animated_menu_t *m,int speed)
-{
-    m->speed = speed*1000;
-}
-
-int mb_animated_menu_get_speed(mb_animated_menu_t *m)
-{
-    return m->speed/1000;
-}
--- a/examples/menu/animated_menu.h	Sun Mar 15 17:17:06 2009 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#ifndef __ANIMATED_MENU_H
-#define __ANIMATED_MENU_H
-typedef struct _mb_animated_menu {
-	char **titles;
-	int *menus_y;
-	int *items;
-	int top;
-	int cur;
-	int max;
-	int ready;
-	int speed;
-	MBApp *app;
-	mb_sprite_t *sprite;
-	mb_obj_t **objects;
-	mb_obj_t *lightbar;
-	void (*callback)(struct _mb_animated_menu *m, int sel);
-	void (*update_callback)(struct _mb_animated_menu *m, int sel);
-	mb_progm_t *progm;
-	X_kb_event_t pending_key;
-} mb_animated_menu_t;
-/** \brief Create an instace of animated menu. 
- *
- *   The objectnames is used to extract symbols from the SVG file. 
- *         ${objectnames}0 - ${objectnames}8 is the text object.
- *         ${objectnames}_lightbar is the lightbar.
- *
- */
-mb_animated_menu_t *mb_animated_menu_new(MBApp *app,mb_sprite_t *sp,char *objnames,char *menus[]);
-void mb_animated_menu_set_speed(mb_animated_menu_t *m,int speed);
-int mb_animated_menu_get_speed(mb_animated_menu_t *m);
-void mb_animated_menu_set_callback(mb_animated_menu_t *m, void (*f)(mb_animated_menu_t *m, int sel));
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/animated_menu.h	Mon Mar 16 08:45:54 2009 +0800
@@ -0,0 +1,32 @@
+#ifndef __ANIMATED_MENU_H
+#define __ANIMATED_MENU_H
+typedef struct _mb_animated_menu {
+	char **titles;
+	int *menus_y;
+	int *items;
+	int top;
+	int cur;
+	int max;
+	int ready;
+	int speed;
+	MBApp *app;
+	mb_sprite_t *sprite;
+	mb_obj_t **objects;
+	mb_obj_t *lightbar;
+	void (*callback)(struct _mb_animated_menu *m, int sel);
+	void (*update_callback)(struct _mb_animated_menu *m, int sel);
+	mb_progm_t *progm;
+	X_kb_event_t pending_key;
+} mb_animated_menu_t;
+/** \brief Create an instace of animated menu. 
+ *
+ *   The objectnames is used to extract symbols from the SVG file. 
+ *         ${objectnames}0 - ${objectnames}8 is the text object.
+ *         ${objectnames}_lightbar is the lightbar.
+ *
+ */
+mb_animated_menu_t *mb_animated_menu_new(MBApp *app,mb_sprite_t *sp,char *objnames,char *menus[]);
+void mb_animated_menu_set_speed(mb_animated_menu_t *m,int speed);
+int mb_animated_menu_get_speed(mb_animated_menu_t *m);
+void mb_animated_menu_set_callback(mb_animated_menu_t *m, void (*f)(mb_animated_menu_t *m, int sel));
+#endif
--- a/src/Makefile.am	Sun Mar 15 17:17:06 2009 +0800
+++ b/src/Makefile.am	Mon Mar 16 08:45:54 2009 +0800
@@ -3,7 +3,7 @@
 lib_LTLIBRARIES = libmbfly.la
 
 noinst_PROGRAMS = X_main
-MBAF_SOURCES=mbaf/mbapp.c mbaf/mbbutton.c mbaf/mbobject.c
+MBAF_SOURCES=mbaf/mbapp.c mbaf/mbbutton.c mbaf/mbobject.c mbaf/animated_menu.c
 libmbfly_la_SOURCES = animate.c chgcolor.c coord.c event.c geo.c	\
 	observer.c paint.c redraw_man.c rotate.c shape_path.c		\
 	shape_rect.c shape_text.c shift.c subtree_free.c timer.c 	\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mbaf/animated_menu.c	Mon Mar 16 08:45:54 2009 +0800
@@ -0,0 +1,390 @@
+#include <stdio.h>
+#include <mb.h>
+#include <string.h>
+//#include "menu.h"
+#include "mbapp.h"
+#include <animated_menu.h>
+static void mb_animated_menu_update(mb_animated_menu_t *m);
+static void set_text(coord_t *g, char *text)
+{
+    geo_t *geo;
+    shape_t *shape;
+
+    FOR_COORD_MEMBERS(g, geo) {
+        shape = geo_get_shape(geo);
+        if(shape->obj.obj_type == MBO_TEXT) {
+		sh_text_set_text(shape, text);
+        }
+    }
+}
+
+static void mb_animated_menu_fillMenuContent(mb_animated_menu_t *m)
+{
+    int i;
+    coord_t *textgroup;
+    shape_t *text;
+    coord_t *group;
+    coord_t *lightbar;
+    int tmp;
+    mb_timeval_t start, playing, now;
+    mb_progm_t *progm;
+    mb_word_t *word;
+
+    printf("max item is %d\n", m->max);
+    // fill new item
+    for(i=0;i<8;i++) {
+        group = (coord_t *) m->objects[m->items[i]];
+	if (i < m->max)
+	        set_text(group, m->titles[m->top+i]);
+	else
+	        set_text(group, "");
+    	rdman_coord_changed(MBAPP_RDMAN(m->app),group);
+    }
+
+
+    textgroup = (coord_t *) m->objects[m->items[i]];
+    coord_hide(textgroup);
+    rdman_coord_changed(MBAPP_RDMAN(m->app),textgroup);
+
+    lightbar = (coord_t *) m->lightbar;
+    group = (coord_t *) m->objects[m->cur];
+    coord_y(lightbar) = coord_y(group);
+    rdman_coord_changed(MBAPP_RDMAN(m->app),lightbar);
+    rdman_redraw_changed(MBAPP_RDMAN(m->app));
+}
+
+static void mb_animated_menu_complete(event_t *ev,void *arg)
+{
+    mb_animated_menu_t *m = (mb_animated_menu_t *) arg;
+
+    m->ready++;
+    printf("animated done ready=%d\n", m->ready);
+}
+
+static void mb_animated_menu_fillMenuContentUp(mb_animated_menu_t *m)
+{
+    int i;
+    coord_t *textgroup;
+    shape_t *text;
+    coord_t *group;
+    coord_t *lightbar;
+    int tmp;
+    mb_timeval_t start, playing, now;
+    mb_progm_t *progm;
+    mb_word_t *word;
+
+
+    // fill new item
+    group = (coord_t *) m->objects[m->items[8]];
+    set_text(group, m->titles[m->top]);
+
+    m->progm = progm = mb_progm_new(2, MBAPP_RDMAN(m->app));
+    MB_TIMEVAL_SET(&start, 0, 0);
+    MB_TIMEVAL_SET(&playing, 0, m->speed);
+    word = mb_progm_next_word(progm, &start, &playing);
+    get_now(&now);
+
+    for(i=0;i<7;i++) {
+	//shift to the next item
+        textgroup = (coord_t *) m->objects[m->items[i]];
+	mb_shift_new(0,m->menus_y[i+1]-coord_y(textgroup), textgroup,word);
+    }
+    // fade out the item[7]
+    textgroup = (coord_t *) m->objects[m->items[7]];
+    mb_shift_new(0,100, textgroup,word);
+
+    // fade in the item[8]
+    textgroup = (coord_t *) m->objects[m->items[8]];
+    group = (coord_t *) m->objects[m->items[0]];
+    coord_y(textgroup) = m->menus_y[0]-100;
+    coord_show(textgroup);
+    mb_shift_new(0,100, textgroup,word);
+
+    lightbar = (coord_t *) m->lightbar;
+    mb_shift_new(0,m->menus_y[m->cur]-coord_y(lightbar),lightbar,word);
+    
+    MB_TIMEVAL_SET(&start, 0, m->speed);
+    MB_TIMEVAL_SET(&playing, 0, 0);
+    word = mb_progm_next_word(progm, &start, &playing);
+    textgroup = (coord_t *) m->objects[m->items[7]];
+    mb_visibility_new(VIS_HIDDEN, textgroup,word);
+
+    mb_progm_free_completed(progm);
+    m->ready--;
+    subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m);
+    mb_progm_start(progm, X_MB_tman(MBAPP_RDMAN(m->app)->rt), &now);
+    rdman_redraw_changed(MBAPP_RDMAN(m->app));
+    tmp = m->items[8];
+    for(i=8;i>0;i--) {
+	m->items[i] = m->items[i-1];
+    }
+    m->items[0] = tmp;
+    printf("fill menu\n");
+}
+
+
+static void mb_animated_menu_fillMenuContentDown(mb_animated_menu_t *m)
+{
+    int i;
+    coord_t *textgroup;
+    shape_t *text;
+    coord_t *group;
+    coord_t *lightbar;
+    char name[255];
+    int tmp;
+    mb_timeval_t start, playing, now;
+    mb_progm_t *progm;
+    mb_word_t *word;
+
+
+    // fill new item
+    set_text((coord_t *)m->objects[m->items[8]], m->titles[m->top+7]);
+
+    m->progm = progm = mb_progm_new(2, MBAPP_RDMAN(m->app));
+    MB_TIMEVAL_SET(&start, 0, 0);
+    MB_TIMEVAL_SET(&playing, 0, m->speed);
+    word = mb_progm_next_word(progm, &start, &playing);
+    get_now(&now);
+
+    for(i=1;i<8;i++) {
+	//shift to the next item
+	mb_shift_new(0,m->menus_y[i-1]-coord_y((coord_t *)m->objects[m->items[i]]), (coord_t *) m->objects[m->items[i]],word);
+    }
+    // fade out the item[0]
+    mb_shift_new(0,-100, (coord_t *)m->objects[m->items[0]],word);
+
+    // fade in the item[8]
+    coord_y((coord_t *)m->objects[m->items[8]]) = m->menus_y[7]+100;
+    coord_show(((coord_t *)(m->objects[m->items[8]])));
+    mb_shift_new(0,-100, (coord_t *)m->objects[m->items[8]],word);
+
+    mb_shift_new(0,m->menus_y[m->cur]-coord_y((coord_t *)m->lightbar),((coord_t *)(m->lightbar)),word);
+
+    MB_TIMEVAL_SET(&start, 0, m->speed);
+    MB_TIMEVAL_SET(&playing, 0, 0);
+    word = mb_progm_next_word(progm, &start, &playing);
+    mb_visibility_new(VIS_VISIBLE, (coord_t *) m->objects[m->items[0]],word);
+
+    mb_progm_free_completed(progm);
+    m->ready--;
+    subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m);
+    mb_progm_start(progm, X_MB_tman(MBAPP_RDMAN(m->app)->rt), &now);
+    rdman_redraw_changed(MBAPP_RDMAN(m->app));
+    tmp = m->items[0];
+    for(i=0;i<8;i++) {
+	m->items[i] = m->items[i+1];
+    }
+    m->items[8] = tmp;
+}
+
+void mb_animated_menu_moveLightBar(mb_animated_menu_t *m)
+{
+    mb_timeval_t start, playing, now;
+    mb_progm_t *progm;
+    mb_word_t *word;
+    coord_t *group;
+    coord_t *lightbar;
+
+    m->progm = progm = mb_progm_new(1, MBAPP_RDMAN(m->app));
+    MB_TIMEVAL_SET(&start, 0, 0);
+    MB_TIMEVAL_SET(&playing, 0, m->speed);
+    word = mb_progm_next_word(progm, &start, &playing);
+    get_now(&now);
+
+    lightbar = (coord_t *) m->lightbar;
+    mb_shift_new(0,m->menus_y[m->cur]-coord_y(lightbar),lightbar,word);
+    mb_progm_free_completed(progm);
+    m->ready--;
+    subject_add_observer(mb_progm_get_complete(progm), mb_animated_menu_complete,m);
+    mb_progm_start(progm, X_MB_tman(MBAPP_RDMAN(m->app)->rt), &now);
+    rdman_redraw_changed(MBAPP_RDMAN(m->app));
+}
+
+static void mb_animated_menu_up(mb_animated_menu_t *m)
+{
+    if (m->cur > 5) {
+	m->cur--;
+        mb_animated_menu_moveLightBar(m);
+	mb_animated_menu_update(m);
+    } else {
+        if (m->top > 0) {
+	    m->top--;
+            mb_animated_menu_fillMenuContentUp(m);
+	    mb_animated_menu_update(m);
+        } else {
+	    if (m->cur == 0) 
+	        return;
+	    m->cur--;
+            mb_animated_menu_moveLightBar(m);
+	    mb_animated_menu_update(m);
+	}
+    }
+}
+static void mb_animated_menu_down(mb_animated_menu_t *m)
+{
+
+    if (m->cur < 5) {
+	if (m->top+m->cur <= m->max) {
+	    m->cur++;
+            mb_animated_menu_moveLightBar(m);
+	    mb_animated_menu_update(m);
+	}
+    } else  {
+        if ((m->top+8) < m->max-1) {
+	    m->top++;
+            mb_animated_menu_fillMenuContentDown(m);
+	    mb_animated_menu_update(m);
+        } else {
+   	    if (m->cur+m->top < m->max-1) {
+	        m->cur++;
+                mb_animated_menu_moveLightBar(m);
+	        mb_animated_menu_update(m);
+	    } else
+	        return;
+	}
+    }
+}
+
+void mb_animated_menu_set_update_callback(mb_animated_menu_t *m, void (*f)(mb_animated_menu_t *m, int sel))
+{
+   m->update_callback = f;
+}
+void mb_animated_menu_set_callback(mb_animated_menu_t *m, void (*f)(mb_animated_menu_t *m, int sel))
+{
+   m->callback = f;
+}
+static void mb_animated_menu_update(mb_animated_menu_t *m)
+{
+   if (m->update_callback)
+	   m->update_callback(m,m->top+m->cur);
+
+}
+static void mb_animated_menu_select(mb_animated_menu_t *m)
+{
+   if (m->callback)
+	   m->callback(m,m->top+m->cur);
+}
+
+// Send the pending key in the animation progm complete callback
+static void mb_animated_menu_keyHandler(event_t *ev, void *arg);
+static void mb_animated_menu_send_pending_key(event_t *ev,void *arg)
+{
+    mb_animated_menu_t *m = (mb_animated_menu_t *) arg;
+
+    if (m->ready<=0) 
+	    mb_animated_menu_keyHandler((event_t *) &m->pending_key,m);
+}
+static void mb_animated_menu_keyHandler(event_t *ev, void *arg)
+{
+    mb_animated_menu_t *m = (mb_animated_menu_t *) arg;
+    X_kb_event_t *xkey = (X_kb_event_t *)ev;
+    if(xkey->event.type != EVT_KB_PRESS) {
+        return;
+    }
+    printf("read=%d\n",m->ready);
+    if (m->ready<=0) {
+    	    subject_add_observer(mb_progm_get_complete(m->progm), mb_animated_menu_send_pending_key,m);
+	    mb_progm_finish(m->progm);
+	    m->pending_key = *xkey;
+	    return;
+    }
+    switch(xkey->sym) {
+    case 0xff51:		/* left */
+	break;
+
+    case 0xff52:		/* up */
+	mb_animated_menu_up(m);
+	break;
+
+    case 0xff53:		/* right */
+	break;
+
+    case 0xff54:		/* down */
+	mb_animated_menu_down(m);
+	break;
+
+    case 0xff0d:		/* enter */
+	mb_animated_menu_select(m);
+	break;
+    default:
+	return;
+    }
+}
+
+/** \brief Create an instace of animated menu. 
+ *
+ *   The objectnames is used to extract symbols from the SVG file. 
+ *         ${objectnames}0 - ${objectnames}8 is the text object.
+ *         ${objectnames}_lightbar is the lightbar.
+ *
+ */
+mb_animated_menu_t *mb_animated_menu_new(MBApp *app,mb_sprite_t *sp,char *objnames,char *menus[])
+{
+    mb_animated_menu_t *m;
+    int i,len;
+    char name[255];
+    mb_obj_t *l;
+    int ii;
+
+    if (menus == NULL)
+	    i=0;
+    else
+	    for(i=0;menus[i];i++);
+    ii=9;
+    
+    m = (mb_animated_menu_t *) malloc(sizeof(mb_animated_menu_t));
+    m->items = (int *) malloc(sizeof(int)*ii*2+sizeof(mb_obj_t *)*ii);
+    m->app = app;
+    m->sprite = sp;
+    m->top = 0;
+    m->cur = 0;
+    m->ready = 1;
+    m->max = i;
+    m->menus_y = (int *) (m->items+ii);
+    m->objects = (mb_obj_t **) (m->menus_y+ii);
+    m->callback = NULL;
+    m->update_callback = NULL;
+    m->speed = 300000;
+    for(i=0;i<9;i++) {
+        m->items[i] = i;
+	snprintf(name,sizeof(name),"%s%d", objnames, i+1);
+	l = MB_SPRITE_GET_OBJ(sp,name);
+	if (l == NULL) {
+		fprintf(stderr,"Can not find symbol %s\n",name);
+	}
+	m->objects[i] = (mb_obj_t *) l;
+	m->menus_y[i] = coord_y((coord_t*)l);
+    }
+    m->titles = menus;
+    snprintf(name,sizeof(name), "%s_lightbar", objnames);
+    m->lightbar = (mb_obj_t *) MB_SPRITE_GET_OBJ(sp,name);
+    if (m->lightbar==NULL)
+	    fprintf(stderr,"Can not find object %s\n",name);
+    mb_animated_menu_fillMenuContent(m);
+    subject_add_observer(MBAPP_keySubject(app), mb_animated_menu_keyHandler,m);
+    return m;
+}
+
+void mb_animated_menu_set_titles(mb_animated_menu_t *m, char *menus[])
+{
+    int i;
+    for(i=0;menus[i];i++);
+
+    m->max = i;
+    m->top = 0;
+    m->cur = 0;
+    m->titles = menus;
+    mb_animated_menu_fillMenuContent(m);
+    mb_animated_menu_moveLightBar(m);
+}
+
+
+void mb_animated_menu_set_speed(mb_animated_menu_t *m,int speed)
+{
+    m->speed = speed*1000;
+}
+
+int mb_animated_menu_get_speed(mb_animated_menu_t *m)
+{
+    return m->speed/1000;
+}