First step towards context sensitive and configurable menus, by Brent Coutts


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4370 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/menu.c b/apps/menu.c
index 0bd21b9..f187b5d 100644
--- a/apps/menu.c
+++ b/apps/menu.c
@@ -17,6 +17,7 @@
  *
  ****************************************************************************/
 #include <stdbool.h>
+#include <stdlib.h>
 
 #include "hwcompat.h"
 #include "lcd.h"
@@ -42,6 +43,7 @@
     int cursor;
     struct menu_items* items;
     int itemcount;
+    int (*callback)(int, int);
 };
 
 #define MAX_MENUS 5
@@ -123,7 +125,7 @@
     }
 }
 
-static void menu_draw(int m)
+void menu_draw(int m)
 {
     int i = 0;
 #ifdef HAVE_LCD_BITMAP
@@ -216,7 +218,7 @@
 
 }
 
-int menu_init(struct menu_items* mitems, int count)
+int menu_init(struct menu_items* mitems, int count, int (*callback)(int, int))
 {
     int i;
 
@@ -234,6 +236,7 @@
     menus[i].itemcount = count;
     menus[i].top = 0;
     menus[i].cursor = 0;
+    menus[i].callback = callback;
 
     return i;
 }
@@ -246,6 +249,7 @@
 int menu_show(int m)
 {
     bool exit = false;
+    int key;
 #ifdef HAVE_LCD_BITMAP
     int fw, fh;
     int menu_lines;
@@ -260,7 +264,16 @@
     menu_draw(m);
 
     while (!exit) {
-        switch( button_get_w_tmo(HZ/2) ) {
+        key = button_get_w_tmo(HZ/2);
+        
+        /*  
+         *   "short-circuit" the default keypresses by running the callback function
+         */
+
+        if( menus[m].callback != NULL )
+            key = menus[m].callback(key, m);            /* make sure there's no match in the switch */
+
+        switch( key ) {
 #ifdef HAVE_RECORDER_KEYPAD
             case BUTTON_UP:
             case BUTTON_UP | BUTTON_REPEAT:
@@ -326,20 +339,6 @@
                 exit = true;
                 break;
 
-#ifdef HAVE_RECORDER_KEYPAD
-            case BUTTON_F2:
-                if (f2_screen())
-                    return MENU_ATTACHED_USB;
-                menu_draw(m);
-                break;
-
-            case BUTTON_F3:
-                if (f3_screen())
-                    return MENU_ATTACHED_USB;
-                menu_draw(m);
-                break;
-#endif
-
             case SYS_USB_CONNECTED:
                 usb_screen();
 #ifdef HAVE_LCD_CHARCELLS
@@ -369,3 +368,92 @@
   }
   return false;
 }
+
+/*  
+ *  Property function - return the current cursor for "menu"
+ */
+
+int menu_cursor(int menu)
+{
+    return menus[menu].cursor;
+}
+
+/*  
+ *  Property function - return the "menu" description at "position"
+ */
+
+char* menu_description(int menu, int position)
+{
+    return menus[menu].items[position].desc;
+}
+
+/*  
+ *  Delete the element "position" from the menu items in "menu"
+ */
+
+void menu_delete(int menu, int position)
+{
+    int i;
+    
+    /* copy the menu item from the one below */
+    for( i = position; i < (menus[menu].itemcount - 1); i++)
+        menus[menu].items[i] = menus[menu].items[i + 1];
+ 
+    /* reduce the count */       
+    menus[menu].itemcount--;
+    
+    /* adjust if this was the last menu item and the cursor was on it */
+    if( menus[menu].itemcount <= menus[menu].cursor)
+        menus[menu].cursor = menus[menu].itemcount - 1;
+}
+
+/*  
+ *  Property function - return the "count" of menu items in "menu" 
+ */
+
+int menu_count(int menu)
+{
+    return menus[menu].itemcount;
+}
+
+/*  
+ *  Allows a menu item at the current cursor position in "menu" to be moved up the list
+ */
+
+bool menu_moveup(int menu)
+{
+    struct menu_items swap;
+    
+    /* can't be the first item ! */
+    if( menus[menu].cursor == 0)
+        return false;
+    
+    /* use a temporary variable to do the swap */    
+    swap = menus[menu].items[menus[menu].cursor - 1];
+    menus[menu].items[menus[menu].cursor - 1] = menus[menu].items[menus[menu].cursor];
+    menus[menu].items[menus[menu].cursor] = swap;
+    menus[menu].cursor--;
+    
+    return true;
+}
+
+/*  
+ *  Allows a menu item at the current cursor position in "menu" to be moved down the list
+ */
+
+bool menu_movedown(int menu)
+{
+    struct menu_items swap;
+    
+    /* can't be the last item ! */
+    if( menus[menu].cursor == menus[menu].itemcount - 1)
+        return false;
+    
+    /* use a temporary variable to do the swap */    
+    swap = menus[menu].items[menus[menu].cursor + 1];
+    menus[menu].items[menus[menu].cursor + 1] = menus[menu].items[menus[menu].cursor];
+    menus[menu].items[menus[menu].cursor] = swap;
+    menus[menu].cursor++;
+    
+    return true;
+}