From: bernie Date: Mon, 15 May 2006 07:25:29 +0000 (+0000) Subject: Move menu to gui/. X-Git-Tag: 1.0.0~638 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=969f9a6fd4c736973771e39a7516ba56d9453216;p=bertos.git Move menu to gui/. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@603 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/app/demo/demo.c b/app/demo/demo.c index dc0f79a2..f94496b6 100755 --- a/app/demo/demo.c +++ b/app/demo/demo.c @@ -14,6 +14,9 @@ /*#* *#* $Log$ + *#* Revision 1.5 2006/05/15 07:25:29 bernie + *#* Move menu to gui/. + *#* *#* Revision 1.4 2006/04/27 05:43:07 bernie *#* Fix naming conventions. *#* @@ -41,8 +44,8 @@ #include #include #include +#include #include -#include #include diff --git a/gui/menu.c b/gui/menu.c new file mode 100755 index 00000000..8a08fe8d --- /dev/null +++ b/gui/menu.c @@ -0,0 +1,532 @@ +/*! + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief General pourpose menu handling functions + */ + +/*#* + *#* $Log$ + *#* Revision 1.1 2006/05/15 07:20:54 bernie + *#* Move menu to gui/. + *#* + *#* Revision 1.7 2006/04/27 05:39:24 bernie + *#* Enhance text rendering to arbitrary x,y coords. + *#* + *#* Revision 1.6 2006/04/11 00:07:32 bernie + *#* Implemenent MF_SAVESEL flag. + *#* + *#* Revision 1.5 2006/03/22 09:49:51 bernie + *#* Simplifications from project_grl. + *#* + *#* Revision 1.4 2006/03/20 17:48:35 bernie + *#* Implement support for ROM menus. + *#* + *#* Revision 1.3 2006/02/20 14:34:32 bernie + *#* Include appconfig.h before using its definitions. + *#* + *#* Revision 1.2 2006/02/15 09:10:51 bernie + *#* Make title bold; Fix height when we have no menubar. + *#* + *#* Revision 1.1 2006/02/10 12:29:36 bernie + *#* Add menu system. + *#* + *#* Revision 1.48 2005/11/27 23:02:55 bernie + *#* Move graphics modules from mware/ to gfx/. + *#* + *#* Revision 1.47 2005/11/16 18:10:19 bernie + *#* Move top-level headers to cfg/ as in DevLib. + *#* + *#* Revision 1.46 2005/02/17 03:49:21 bernie + *#* Update to new PGM api. + *#* + *#* Revision 1.45 2005/02/11 19:11:32 aleph + *#* Move menu_displaymsg() in new displaymsg module + *#* + *#* Revision 1.44 2005/01/21 20:05:57 aleph + *#* Fix build warning with debug off + *#* + *#* Revision 1.43 2005/01/13 16:56:36 aleph + *#* Fix progmem includes. + *#* + *#* Revision 1.42 2004/10/31 11:02:15 aleph + *#* Rename functions with correct codying conventions; Simplify version display + *#* + *#* Revision 1.41 2004/10/15 17:34:33 customer_pw + *#* Fix menuitem max length + *#* + *#* Revision 1.40 2004/10/06 12:55:08 customer_pw + *#* Declare unused (if !_DEBUG) menu_count() + *#* + *#* Revision 1.39 2004/10/01 14:04:59 customer_pw + *#* Add accessor functions for menu flags + *#* + *#* Revision 1.38 2004/09/27 12:05:46 customer_pw + *#* Use sel label for toggle menus and remove it + *#* + *#* Revision 1.37 2004/09/27 10:05:33 customer_pw + *#* Menu cosmetic fixes + *#* + *#* Revision 1.36 2004/09/14 22:18:03 bernie + *#* Adapt to stricter casting rules. + *#* + *#* Revision 1.35 2004/09/12 17:56:03 aleph + *#* Include debug.h instead of drv/kdebug.h + *#*/ + +#include "menu.h" +#include +#include +#include +#include +#include +#include +#include +#include /* strcpy() */ + +#if CPU_HARVARD +#include /* strncpy_P() */ +#endif + +#if CONFIG_MENU_SMOOTH +#include +#endif + +#if CONFIG_MENU_MENUBAR +#include "menubar.h" +#endif + +#if defined(CONFIG_LOCALE) && (CONFIG_LOCALE == 1) +#include "msg.h" +#else +#define PTRMSG(x) ((const char *)x) +#endif + +/* Temporary fake defines for ABORT stuff... */ +#define abort_top 0 +#define PUSH_ABORT false +#define POP_ABORT do {} while(0) +#define DO_ABORT do {} while(0) + + +/** + * Count the items present in a menu. + */ +static int menu_count(const struct Menu *menu) +{ + int cnt = 0; + + for (cnt = 0; /*NOP*/; ++cnt) + { + const MenuItem *item = &menu->items[cnt]; +#if CPU_HARVARD + MenuItem ram_item; + if (menu->flags & MF_ROMITEMS) + { + memcpy_P(&ram_item, item, sizeof(ram_item)); + item = &ram_item; + } +#endif + if (!(item->label || item->hook)) + break; + } + + return cnt; +} + +#if CONFIG_MENU_MENUBAR + +/*! + * Update the menu bar according to the selected item + * and redraw it. + */ +static void menu_update_menubar( + const struct Menu *menu, + struct MenuBar *mb, + int selected) +{ + int item_flags; +#if CPU_HARVARD + if (menu->flags & MF_ROMITEMS) + { + ASSERT(sizeof(menu->items[selected].flags) == sizeof(int)); + item_flags = pgm_read_int(&menu->items[selected].flags); + } + else +#endif + item_flags = menu->items[selected].flags; + + const_iptr_t newlabel = (const_iptr_t)LABEL_OK; + + if (item_flags & MIF_DISABLED) + newlabel = (const_iptr_t)LABEL_EMPTY; + else if (item_flags & MIF_TOGGLE) + newlabel = (const_iptr_t)LABEL_SEL; + else if (item_flags & MIF_CHECKIT) + { + newlabel = (item_flags & MIF_CHECKED) ? + (const_iptr_t)LABEL_EMPTY : (const_iptr_t)LABEL_SEL; + } + + mb->labels[3] = newlabel; + mbar_draw(mb); +} +#endif /* CONFIG_MENU_MENUBAR */ + + +/** + * Show a menu on the display. + */ +static void menu_layout( + const struct Menu *menu, + int first_item, + int items_per_page, + int selected) +{ + int ypos, cnt; + const char * PROGMEM title = PTRMSG(menu->title); + Bitmap *bm = menu->bitmap; + + ypos = bm->cr.ymin; + + if (title) + { + text_xyprintf(bm, 0, ypos, STYLEF_UNDERLINE | STYLEF_BOLD | TEXT_CENTER | TEXT_FILL, title); + ypos += bm->font->height; + } + +#if CONFIG_MENU_SMOOTH + static coord_t yoffset = 0; + static int old_first_item = 0; + static mtime_t old_time = 0; //UNUSED + static int speed; + coord_t old_ymin = bm->cr.ymin; + + gfx_setClipRect(bm, + bm->cr.xmin, bm->cr.ymin + ypos, + bm->cr.xmax, bm->cr.ymax); + + if (old_first_item != first_item) + { + speed = ABS(old_first_item - first_item) * 3; + + if (old_first_item > first_item) + { + yoffset += speed; + if (yoffset > bm->font->height) + { + yoffset = 0; + --old_first_item; + } + } + else + { + yoffset -= speed; + if (yoffset < -bm->font->height) + { + yoffset = 0; + ++old_first_item; + } + } + first_item = old_first_item; + } + ypos += yoffset; +#endif + + for (cnt = 0; cnt < items_per_page; ++cnt) + { + const MenuItem *item = &menu->items[first_item + cnt]; +#if CPU_HARVARD + MenuItem ram_item; + if (menu->flags & MF_ROMITEMS) + { + memcpy_P(&ram_item, item, sizeof(ram_item)); + item = &ram_item; + } +#endif + + /* Check for end of menu */ + if (!(item->label || item->hook)) + break; + + /* Only print visible items */ + if (!(item->flags & MIF_HIDDEN)) + { +#if CPU_HARVARD + text_xyprintf_P +#else + text_xyprintf +#endif + ( + bm, 0, ypos, + (first_item + cnt == selected) ? (STYLEF_INVERT | TEXT_FILL) : TEXT_FILL, + (item->flags & MIF_RAMLABEL) ? PSTR("%s%S") : PSTR("%S%S"), + PTRMSG(item->label), + (item->flags & MIF_TOGGLE) ? + ( (item->flags & MIF_CHECKED) ? PSTR(":ON") : PSTR(":OFF") ) + : ( (item->flags & MIF_CHECKED) ? PSTR("\04") : PSTR("") ) + ); + ypos += bm->font->height; + } + } + +#if CONFIG_MENU_SMOOTH + /* Restore old cliprect */ + gfx_setClipRect(bm, + bm->cr.xmin, old_ymin, + bm->cr.xmax, bm->cr.ymax); + + lcd_blitBitmap(&lcd_bitmap); +#endif +} + + +/*! + * Handle menu item selection + */ +static void menu_doselect(const struct Menu *menu, struct MenuItem *item) +{ + /* Exclude other items */ + int mask, i; + for (mask = item->flags & MIF_EXCLUDE_MASK, i = 0; mask; mask >>= 1, ++i) + { + if (mask & 1) + menu->items[i].flags &= ~MIF_CHECKED; + } + + if (item->flags & MIF_DISABLED) + return; + + /* Handle checkable items */ + if (item->flags & MIF_TOGGLE) + item->flags ^= MIF_CHECKED; + else if (item->flags & MIF_CHECKIT) + item->flags |= MIF_CHECKED; + + /* Handle items with callback hooks */ + if (item->hook) + { + /* Push a jmp buffer to abort the operation with the STOP key */ + if (!PUSH_ABORT) + { + item->hook(item->userdata); + POP_ABORT; + } + } +} + + +/** + * Return the next visible item (rolls back to the first item) + */ +static int menu_next_visible_item(const struct Menu *menu, int index) +{ + int total = menu_count(menu); + int item_flags; + + do + { + if (++index >= total) + index = 0; + +#if CPU_HARVARD + if (menu->flags & MF_ROMITEMS) + { + ASSERT(sizeof(menu->items[index].flags) == sizeof(int)); + item_flags = pgm_read_int(&menu->items[index].flags); + } + else +#endif + item_flags = menu->items[index].flags; + } + while (item_flags & MIF_HIDDEN); + + return index; +} + + +/** + * Return the previous visible item (rolls back to the last item) + */ +static int menu_prev_visible_item(const struct Menu *menu, int index) +{ + int total = menu_count(menu); + int item_flags; + + do + { + if (--index < 0) + index = total - 1; + +#if CPU_HARVARD + if (menu->flags & MF_ROMITEMS) + { + ASSERT(sizeof(menu->items[index].flags) == sizeof(int)); + item_flags = pgm_read_int(&menu->items[index].flags); + } + else +#endif + item_flags = menu->items[index].flags; + } + while (item_flags & MIF_HIDDEN); + + return index; +} + + +/*! + * Handle a menu and invoke hook functions for the selected menu items. + */ +iptr_t menu_handle(const struct Menu *menu) +{ + uint8_t items_per_page; + uint8_t first_item, selected; + +#if CONFIG_MENU_MENUBAR + struct MenuBar mb; + const_iptr_t labels[] = + { + (const_iptr_t)LABEL_BACK, + (const_iptr_t)LABEL_UPARROW, + (const_iptr_t)LABEL_DOWNARROW, + (const_iptr_t)0 + }; + + /* + * Initialize menu bar + */ + if (menu->flags & MF_TOPLEVEL) + labels[0] = (const_iptr_t)LABEL_EMPTY; + + mbar_init(&mb, menu->bitmap, labels, countof(labels)); +#endif /* CONFIG_MENU_MENUBAR */ + + + items_per_page = + (menu->bitmap->height / menu->bitmap->font->height) +#if CONFIG_MENU_MENUBAR + - 1 /* menu bar labels */ +#endif + - (menu->title ? 1 : 0); + + /* Selected item should be a visible entry */ + first_item = selected = menu_next_visible_item(menu, menu->selected - 1); + + /* Clear screen */ + text_clear(menu->bitmap); + + for(;;) + { + keymask_t key; + + /* + * Keep selected item visible + */ + while (selected < first_item) + first_item = menu_prev_visible_item(menu, first_item); + while (selected >= first_item + items_per_page) + first_item = menu_next_visible_item(menu, first_item); + + menu_layout(menu, first_item, items_per_page, selected); + + #if CONFIG_MENU_MENUBAR + menu_update_menubar(menu, &mb, selected); + #endif + +#if CONFIG_MENU_SMOOTH + key = kbd_peek(); +#else + key = kbd_get(); +#endif + + if (key & K_OK) + { + struct MenuItem *item = &(menu->items[selected]); +#if CPU_HARVARD + MenuItem ram_item; + if (menu->flags & MF_ROMITEMS) + { + memcpy_P(&ram_item, item, sizeof(ram_item)); + item = &ram_item; + } +#endif + menu_doselect(menu, item); + + /* Return userdata as result */ + if (!menu->flags & MF_STICKY) + { + /* Store currently selected item before leaving. */ + if (menu->flags & MF_SAVESEL) + CONST_CAST(struct Menu *, menu)->selected = selected; + return item->userdata; + } + + /* Clear screen */ + text_clear(menu->bitmap); + } + else if (key & K_UP) + { + selected = menu_prev_visible_item(menu, selected); + } + else if (key & K_DOWN) + { + selected = menu_next_visible_item(menu, selected); + } + else if (key & K_CANCEL && !(menu->flags & MF_TOPLEVEL)) + { + /* Store currently selected item before leaving. */ + if (menu->flags & MF_SAVESEL) + CONST_CAST(struct Menu *, menu)->selected = selected; + return 0; + } + } +} + + +/*! + * Set flags on a menuitem. + * + * \param menu Menu owner of the item to change. + * \param idx Index of the menu item. + * \param flags Bit mask of the flags to set. + * + * \return Old flags. + */ +int menu_setFlags(struct Menu *menu, int idx, int flags) +{ + ASSERT(idx < menu_count(menu)); + ASSERT(!(menu->flags & MF_ROMITEMS)); + + int old = menu->items[idx].flags; + menu->items[idx].flags |= flags; + return old; +} + + +/*! + * Clear flags on a menuitem. + * + * \param menu Menu owner of the item to change. + * \param idx Index of the menu item. + * \param flags Bit mask of the flags to clear. + * + * \return Old flags. + */ +int menu_clearFlags(struct Menu *menu, int idx, int flags) +{ + ASSERT(idx < menu_count(menu)); + ASSERT(!(menu->flags & MF_ROMITEMS)); + + int old = menu->items[idx].flags; + menu->items[idx].flags &= ~flags; + return old; +} diff --git a/gui/menu.h b/gui/menu.h new file mode 100755 index 00000000..06b90a8b --- /dev/null +++ b/gui/menu.h @@ -0,0 +1,133 @@ +/*! + * \file + * + * + * \version $Id$ + * + * \author Bernardo Innocenti + * \author Stefano Fedrigo + * + * \brief Common menu handling API + */ + +/*#* + *#* $Log$ + *#* Revision 1.1 2006/05/15 07:20:54 bernie + *#* Move menu to gui/. + *#* + *#* Revision 1.4 2006/04/11 00:07:32 bernie + *#* Implemenent MF_SAVESEL flag. + *#* + *#* Revision 1.3 2006/03/22 09:49:51 bernie + *#* Simplifications from project_grl. + *#* + *#* Revision 1.2 2006/03/20 17:48:35 bernie + *#* Implement support for ROM menus. + *#* + *#* Revision 1.1 2006/02/10 12:29:36 bernie + *#* Add menu system. + *#* + *#* Revision 1.20 2005/11/16 18:10:19 bernie + *#* Move top-level headers to cfg/ as in DevLib. + *#* + *#* Revision 1.19 2005/02/11 19:11:38 aleph + *#* Move menu_displaymsg() in new displaymsg module + *#* + *#* Revision 1.18 2005/01/13 16:56:36 aleph + *#* Fix progmem includes. + *#* + *#* Revision 1.17 2004/12/14 12:52:45 aleph + *#* Add exclude menu flags + *#* + *#* Revision 1.16 2004/10/01 14:04:59 customer_pw + *#* Add accessor functions for menu flags + *#* + *#* Revision 1.15 2004/09/09 08:31:36 customer_pw + *#* Add disabled item type + *#* + *#* Revision 1.14 2004/08/29 21:46:12 bernie + *#* CVSSILENT: Mark CVS log blocks. + *#* + *#* Revision 1.13 2004/08/25 15:35:23 customer_pw + *#* IPTR -> iptr_t conversion. + *#* + *#* Revision 1.12 2004/08/25 13:23:45 bernie + *#* IPTR -> iptr_t conversion. + *#*/ +#ifndef MWARE_MENU_H +#define MWARE_MENU_H + +#include + +/* Fwd decl */ +struct Bitmap; + +/** Menu callback function */ +typedef void (*MenuHook)(iptr_t userdata); + +/** + * Menu item description. + */ +typedef struct MenuItem +{ + const_iptr_t label; /*!< Item label (ID or ptr to string, 0 to disable) */ + int flags; /*!< See MIF_#? definitions below */ + MenuHook hook; /*!< Callback function (NULL to terminate item list) */ + iptr_t userdata; /*!< User data to be passed back to the hook */ +} MenuItem; + +/** + * \name Flags for MenuItem.flags. + * \{ + */ +#define MIF_EXCLUDE_MASK 0x00FF /**< Mask for mutual exclusion map (shared with priority). */ +#define MIF_PRI_MASK 0x00FF /**< Mask for priority value (shared with mutual exclusion). */ +#define MIF_PRI(x) ((x) & MIF_PRI_MASK) /**< Set menu item priority. */ +#define MIF_EXCLUDE_0 BV(0) /*!< Exclude item 0 when this item is checked */ +#define MIF_EXCLUDE_1 BV(1) /*!< Exclude item 1 when this item is checked */ +#define MIF_EXCLUDE_2 BV(2) /*!< Exclude item 2 when this item is checked */ +#define MIF_EXCLUDE_3 BV(3) /*!< Exclude item 3 when this item is checked */ +#define MIF_EXCLUDE_4 BV(4) /*!< Exclude item 4 when this item is checked */ +#define MIF_EXCLUDE_5 BV(5) /*!< Exclude item 5 when this item is checked */ +#define MIF_EXCLUDE_6 BV(6) /*!< Exclude item 6 when this item is checked */ +#define MIF_EXCLUDE_7 BV(7) /*!< Exclude item 7 when this item is checked */ +#define MIF_CHECKED BV(8) /*!< Item is currently checked */ +#define MIF_CHECKIT BV(9) /*!< Automatically check this item when selected */ +#define MIF_TOGGLE BV(10) /*!< Toggle MIF_CHECKED when item is selected */ +#define MIF_HIDDEN BV(11) /*!< This menu item is not visible */ +#define MIF_DISABLED BV(12) /*!< This menu item is not visible */ +#define MIF_RAMLABEL BV(13) /*!< Item label is stored in RAM, not in program memory */ +/* \} */ + +/** + * Menu description. + */ +typedef struct Menu +{ + MenuItem *items; /*!< Array of items (end with a NULL hook) */ + const_iptr_t title; /*!< Menu title (ID or ptr to string, 0 to disable) */ + int flags; /*!< See MF_#? definitions below */ + struct Bitmap *bitmap; /*!< Bitmap where the menu is rendered */ + int selected; /*!< Initial selection (written to if #MF_SAVESEL is set). */ +} Menu; + +/** + * \name Flags for Menu.flags. + * \{ + */ +#define MF_STICKY BV(0) /**< Stay in the menu when the items called return */ +#define MF_TOPLEVEL BV(1) /**< Top-level menu (do not display "back" label) */ +#define MF_ROMITEMS BV(2) /**< Menu items are stored in ROM (default is RAM) */ +#define MF_SAVESEL BV(3) /**< Remember the selected item across invocations. */ +/* \} */ + +/* Function prototypes */ +iptr_t menu_handle(const struct Menu *menu); +int menu_setFlags(struct Menu *menu, int idx, int flags); +int menu_clearFlags(struct Menu *menu, int idx, int flags); + +#endif /* MWARE_MENU_H */ diff --git a/mware/menu.c b/mware/menu.c deleted file mode 100755 index 9c1149db..00000000 --- a/mware/menu.c +++ /dev/null @@ -1,529 +0,0 @@ -/*! - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief General pourpose menu handling functions - */ - -/*#* - *#* $Log$ - *#* Revision 1.7 2006/04/27 05:39:24 bernie - *#* Enhance text rendering to arbitrary x,y coords. - *#* - *#* Revision 1.6 2006/04/11 00:07:32 bernie - *#* Implemenent MF_SAVESEL flag. - *#* - *#* Revision 1.5 2006/03/22 09:49:51 bernie - *#* Simplifications from project_grl. - *#* - *#* Revision 1.4 2006/03/20 17:48:35 bernie - *#* Implement support for ROM menus. - *#* - *#* Revision 1.3 2006/02/20 14:34:32 bernie - *#* Include appconfig.h before using its definitions. - *#* - *#* Revision 1.2 2006/02/15 09:10:51 bernie - *#* Make title bold; Fix height when we have no menubar. - *#* - *#* Revision 1.1 2006/02/10 12:29:36 bernie - *#* Add menu system. - *#* - *#* Revision 1.48 2005/11/27 23:02:55 bernie - *#* Move graphics modules from mware/ to gfx/. - *#* - *#* Revision 1.47 2005/11/16 18:10:19 bernie - *#* Move top-level headers to cfg/ as in DevLib. - *#* - *#* Revision 1.46 2005/02/17 03:49:21 bernie - *#* Update to new PGM api. - *#* - *#* Revision 1.45 2005/02/11 19:11:32 aleph - *#* Move menu_displaymsg() in new displaymsg module - *#* - *#* Revision 1.44 2005/01/21 20:05:57 aleph - *#* Fix build warning with debug off - *#* - *#* Revision 1.43 2005/01/13 16:56:36 aleph - *#* Fix progmem includes. - *#* - *#* Revision 1.42 2004/10/31 11:02:15 aleph - *#* Rename functions with correct codying conventions; Simplify version display - *#* - *#* Revision 1.41 2004/10/15 17:34:33 customer_pw - *#* Fix menuitem max length - *#* - *#* Revision 1.40 2004/10/06 12:55:08 customer_pw - *#* Declare unused (if !_DEBUG) menu_count() - *#* - *#* Revision 1.39 2004/10/01 14:04:59 customer_pw - *#* Add accessor functions for menu flags - *#* - *#* Revision 1.38 2004/09/27 12:05:46 customer_pw - *#* Use sel label for toggle menus and remove it - *#* - *#* Revision 1.37 2004/09/27 10:05:33 customer_pw - *#* Menu cosmetic fixes - *#* - *#* Revision 1.36 2004/09/14 22:18:03 bernie - *#* Adapt to stricter casting rules. - *#* - *#* Revision 1.35 2004/09/12 17:56:03 aleph - *#* Include debug.h instead of drv/kdebug.h - *#*/ - -#include "menu.h" -#include -#include -#include -#include -#include -#include -#include -#include /* strcpy() */ - -#if CPU_HARVARD -#include /* strncpy_P() */ -#endif - -#if CONFIG_MENU_SMOOTH -#include -#endif - -#if CONFIG_MENU_MENUBAR -#include "menubar.h" -#endif - -#if defined(CONFIG_LOCALE) && (CONFIG_LOCALE == 1) -#include "msg.h" -#else -#define PTRMSG(x) ((const char *)x) -#endif - -/* Temporary fake defines for ABORT stuff... */ -#define abort_top 0 -#define PUSH_ABORT false -#define POP_ABORT do {} while(0) -#define DO_ABORT do {} while(0) - - -/** - * Count the items present in a menu. - */ -static int menu_count(const struct Menu *menu) -{ - int cnt = 0; - - for (cnt = 0; /*NOP*/; ++cnt) - { - const MenuItem *item = &menu->items[cnt]; -#if CPU_HARVARD - MenuItem ram_item; - if (menu->flags & MF_ROMITEMS) - { - memcpy_P(&ram_item, item, sizeof(ram_item)); - item = &ram_item; - } -#endif - if (!(item->label || item->hook)) - break; - } - - return cnt; -} - -#if CONFIG_MENU_MENUBAR - -/*! - * Update the menu bar according to the selected item - * and redraw it. - */ -static void menu_update_menubar( - const struct Menu *menu, - struct MenuBar *mb, - int selected) -{ - int item_flags; -#if CPU_HARVARD - if (menu->flags & MF_ROMITEMS) - { - ASSERT(sizeof(menu->items[selected].flags) == sizeof(int)); - item_flags = pgm_read_int(&menu->items[selected].flags); - } - else -#endif - item_flags = menu->items[selected].flags; - - const_iptr_t newlabel = (const_iptr_t)LABEL_OK; - - if (item_flags & MIF_DISABLED) - newlabel = (const_iptr_t)LABEL_EMPTY; - else if (item_flags & MIF_TOGGLE) - newlabel = (const_iptr_t)LABEL_SEL; - else if (item_flags & MIF_CHECKIT) - { - newlabel = (item_flags & MIF_CHECKED) ? - (const_iptr_t)LABEL_EMPTY : (const_iptr_t)LABEL_SEL; - } - - mb->labels[3] = newlabel; - mbar_draw(mb); -} -#endif /* CONFIG_MENU_MENUBAR */ - - -/** - * Show a menu on the display. - */ -static void menu_layout( - const struct Menu *menu, - int first_item, - int items_per_page, - int selected) -{ - int ypos, cnt; - const char * PROGMEM title = PTRMSG(menu->title); - Bitmap *bm = menu->bitmap; - - ypos = bm->cr.ymin; - - if (title) - { - text_xyprintf(bm, 0, ypos, STYLEF_UNDERLINE | STYLEF_BOLD | TEXT_CENTER | TEXT_FILL, title); - ypos += bm->font->height; - } - -#if CONFIG_MENU_SMOOTH - static coord_t yoffset = 0; - static int old_first_item = 0; - static mtime_t old_time = 0; //UNUSED - static int speed; - coord_t old_ymin = bm->cr.ymin; - - gfx_setClipRect(bm, - bm->cr.xmin, bm->cr.ymin + ypos, - bm->cr.xmax, bm->cr.ymax); - - if (old_first_item != first_item) - { - speed = ABS(old_first_item - first_item) * 3; - - if (old_first_item > first_item) - { - yoffset += speed; - if (yoffset > bm->font->height) - { - yoffset = 0; - --old_first_item; - } - } - else - { - yoffset -= speed; - if (yoffset < -bm->font->height) - { - yoffset = 0; - ++old_first_item; - } - } - first_item = old_first_item; - } - ypos += yoffset; -#endif - - for (cnt = 0; cnt < items_per_page; ++cnt) - { - const MenuItem *item = &menu->items[first_item + cnt]; -#if CPU_HARVARD - MenuItem ram_item; - if (menu->flags & MF_ROMITEMS) - { - memcpy_P(&ram_item, item, sizeof(ram_item)); - item = &ram_item; - } -#endif - - /* Check for end of menu */ - if (!(item->label || item->hook)) - break; - - /* Only print visible items */ - if (!(item->flags & MIF_HIDDEN)) - { -#if CPU_HARVARD - text_xyprintf_P -#else - text_xyprintf -#endif - ( - bm, 0, ypos, - (first_item + cnt == selected) ? (STYLEF_INVERT | TEXT_FILL) : TEXT_FILL, - (item->flags & MIF_RAMLABEL) ? PSTR("%s%S") : PSTR("%S%S"), - PTRMSG(item->label), - (item->flags & MIF_TOGGLE) ? - ( (item->flags & MIF_CHECKED) ? PSTR(":ON") : PSTR(":OFF") ) - : ( (item->flags & MIF_CHECKED) ? PSTR("\04") : PSTR("") ) - ); - ypos += bm->font->height; - } - } - -#if CONFIG_MENU_SMOOTH - /* Restore old cliprect */ - gfx_setClipRect(bm, - bm->cr.xmin, old_ymin, - bm->cr.xmax, bm->cr.ymax); - - lcd_blitBitmap(&lcd_bitmap); -#endif -} - - -/*! - * Handle menu item selection - */ -static void menu_doselect(const struct Menu *menu, struct MenuItem *item) -{ - /* Exclude other items */ - int mask, i; - for (mask = item->flags & MIF_EXCLUDE_MASK, i = 0; mask; mask >>= 1, ++i) - { - if (mask & 1) - menu->items[i].flags &= ~MIF_CHECKED; - } - - if (item->flags & MIF_DISABLED) - return; - - /* Handle checkable items */ - if (item->flags & MIF_TOGGLE) - item->flags ^= MIF_CHECKED; - else if (item->flags & MIF_CHECKIT) - item->flags |= MIF_CHECKED; - - /* Handle items with callback hooks */ - if (item->hook) - { - /* Push a jmp buffer to abort the operation with the STOP key */ - if (!PUSH_ABORT) - { - item->hook(item->userdata); - POP_ABORT; - } - } -} - - -/** - * Return the next visible item (rolls back to the first item) - */ -static int menu_next_visible_item(const struct Menu *menu, int index) -{ - int total = menu_count(menu); - int item_flags; - - do - { - if (++index >= total) - index = 0; - -#if CPU_HARVARD - if (menu->flags & MF_ROMITEMS) - { - ASSERT(sizeof(menu->items[index].flags) == sizeof(int)); - item_flags = pgm_read_int(&menu->items[index].flags); - } - else -#endif - item_flags = menu->items[index].flags; - } - while (item_flags & MIF_HIDDEN); - - return index; -} - - -/** - * Return the previous visible item (rolls back to the last item) - */ -static int menu_prev_visible_item(const struct Menu *menu, int index) -{ - int total = menu_count(menu); - int item_flags; - - do - { - if (--index < 0) - index = total - 1; - -#if CPU_HARVARD - if (menu->flags & MF_ROMITEMS) - { - ASSERT(sizeof(menu->items[index].flags) == sizeof(int)); - item_flags = pgm_read_int(&menu->items[index].flags); - } - else -#endif - item_flags = menu->items[index].flags; - } - while (item_flags & MIF_HIDDEN); - - return index; -} - - -/*! - * Handle a menu and invoke hook functions for the selected menu items. - */ -iptr_t menu_handle(const struct Menu *menu) -{ - uint8_t items_per_page; - uint8_t first_item, selected; - -#if CONFIG_MENU_MENUBAR - struct MenuBar mb; - const_iptr_t labels[] = - { - (const_iptr_t)LABEL_BACK, - (const_iptr_t)LABEL_UPARROW, - (const_iptr_t)LABEL_DOWNARROW, - (const_iptr_t)0 - }; - - /* - * Initialize menu bar - */ - if (menu->flags & MF_TOPLEVEL) - labels[0] = (const_iptr_t)LABEL_EMPTY; - - mbar_init(&mb, menu->bitmap, labels, countof(labels)); -#endif /* CONFIG_MENU_MENUBAR */ - - - items_per_page = - (menu->bitmap->height / menu->bitmap->font->height) -#if CONFIG_MENU_MENUBAR - - 1 /* menu bar labels */ -#endif - - (menu->title ? 1 : 0); - - /* Selected item should be a visible entry */ - first_item = selected = menu_next_visible_item(menu, menu->selected - 1); - - /* Clear screen */ - text_clear(menu->bitmap); - - for(;;) - { - keymask_t key; - - /* - * Keep selected item visible - */ - while (selected < first_item) - first_item = menu_prev_visible_item(menu, first_item); - while (selected >= first_item + items_per_page) - first_item = menu_next_visible_item(menu, first_item); - - menu_layout(menu, first_item, items_per_page, selected); - - #if CONFIG_MENU_MENUBAR - menu_update_menubar(menu, &mb, selected); - #endif - -#if CONFIG_MENU_SMOOTH - key = kbd_peek(); -#else - key = kbd_get(); -#endif - - if (key & K_OK) - { - struct MenuItem *item = &(menu->items[selected]); -#if CPU_HARVARD - MenuItem ram_item; - if (menu->flags & MF_ROMITEMS) - { - memcpy_P(&ram_item, item, sizeof(ram_item)); - item = &ram_item; - } -#endif - menu_doselect(menu, item); - - /* Return userdata as result */ - if (!menu->flags & MF_STICKY) - { - /* Store currently selected item before leaving. */ - if (menu->flags & MF_SAVESEL) - CONST_CAST(struct Menu *, menu)->selected = selected; - return item->userdata; - } - - /* Clear screen */ - text_clear(menu->bitmap); - } - else if (key & K_UP) - { - selected = menu_prev_visible_item(menu, selected); - } - else if (key & K_DOWN) - { - selected = menu_next_visible_item(menu, selected); - } - else if (key & K_CANCEL && !(menu->flags & MF_TOPLEVEL)) - { - /* Store currently selected item before leaving. */ - if (menu->flags & MF_SAVESEL) - CONST_CAST(struct Menu *, menu)->selected = selected; - return 0; - } - } -} - - -/*! - * Set flags on a menuitem. - * - * \param menu Menu owner of the item to change. - * \param idx Index of the menu item. - * \param flags Bit mask of the flags to set. - * - * \return Old flags. - */ -int menu_setFlags(struct Menu *menu, int idx, int flags) -{ - ASSERT(idx < menu_count(menu)); - ASSERT(!(menu->flags & MF_ROMITEMS)); - - int old = menu->items[idx].flags; - menu->items[idx].flags |= flags; - return old; -} - - -/*! - * Clear flags on a menuitem. - * - * \param menu Menu owner of the item to change. - * \param idx Index of the menu item. - * \param flags Bit mask of the flags to clear. - * - * \return Old flags. - */ -int menu_clearFlags(struct Menu *menu, int idx, int flags) -{ - ASSERT(idx < menu_count(menu)); - ASSERT(!(menu->flags & MF_ROMITEMS)); - - int old = menu->items[idx].flags; - menu->items[idx].flags &= ~flags; - return old; -} diff --git a/mware/menu.h b/mware/menu.h deleted file mode 100755 index 63aa0e8d..00000000 --- a/mware/menu.h +++ /dev/null @@ -1,130 +0,0 @@ -/*! - * \file - * - * - * \version $Id$ - * - * \author Bernardo Innocenti - * \author Stefano Fedrigo - * - * \brief Common menu handling API - */ - -/*#* - *#* $Log$ - *#* Revision 1.4 2006/04/11 00:07:32 bernie - *#* Implemenent MF_SAVESEL flag. - *#* - *#* Revision 1.3 2006/03/22 09:49:51 bernie - *#* Simplifications from project_grl. - *#* - *#* Revision 1.2 2006/03/20 17:48:35 bernie - *#* Implement support for ROM menus. - *#* - *#* Revision 1.1 2006/02/10 12:29:36 bernie - *#* Add menu system. - *#* - *#* Revision 1.20 2005/11/16 18:10:19 bernie - *#* Move top-level headers to cfg/ as in DevLib. - *#* - *#* Revision 1.19 2005/02/11 19:11:38 aleph - *#* Move menu_displaymsg() in new displaymsg module - *#* - *#* Revision 1.18 2005/01/13 16:56:36 aleph - *#* Fix progmem includes. - *#* - *#* Revision 1.17 2004/12/14 12:52:45 aleph - *#* Add exclude menu flags - *#* - *#* Revision 1.16 2004/10/01 14:04:59 customer_pw - *#* Add accessor functions for menu flags - *#* - *#* Revision 1.15 2004/09/09 08:31:36 customer_pw - *#* Add disabled item type - *#* - *#* Revision 1.14 2004/08/29 21:46:12 bernie - *#* CVSSILENT: Mark CVS log blocks. - *#* - *#* Revision 1.13 2004/08/25 15:35:23 customer_pw - *#* IPTR -> iptr_t conversion. - *#* - *#* Revision 1.12 2004/08/25 13:23:45 bernie - *#* IPTR -> iptr_t conversion. - *#*/ -#ifndef MWARE_MENU_H -#define MWARE_MENU_H - -#include - -/* Fwd decl */ -struct Bitmap; - -/** Menu callback function */ -typedef void (*MenuHook)(iptr_t userdata); - -/** - * Menu item description. - */ -typedef struct MenuItem -{ - const_iptr_t label; /*!< Item label (ID or ptr to string, 0 to disable) */ - int flags; /*!< See MIF_#? definitions below */ - MenuHook hook; /*!< Callback function (NULL to terminate item list) */ - iptr_t userdata; /*!< User data to be passed back to the hook */ -} MenuItem; - -/** - * \name Flags for MenuItem.flags. - * \{ - */ -#define MIF_EXCLUDE_MASK 0x00FF /**< Mask for mutual exclusion map (shared with priority). */ -#define MIF_PRI_MASK 0x00FF /**< Mask for priority value (shared with mutual exclusion). */ -#define MIF_PRI(x) ((x) & MIF_PRI_MASK) /**< Set menu item priority. */ -#define MIF_EXCLUDE_0 BV(0) /*!< Exclude item 0 when this item is checked */ -#define MIF_EXCLUDE_1 BV(1) /*!< Exclude item 1 when this item is checked */ -#define MIF_EXCLUDE_2 BV(2) /*!< Exclude item 2 when this item is checked */ -#define MIF_EXCLUDE_3 BV(3) /*!< Exclude item 3 when this item is checked */ -#define MIF_EXCLUDE_4 BV(4) /*!< Exclude item 4 when this item is checked */ -#define MIF_EXCLUDE_5 BV(5) /*!< Exclude item 5 when this item is checked */ -#define MIF_EXCLUDE_6 BV(6) /*!< Exclude item 6 when this item is checked */ -#define MIF_EXCLUDE_7 BV(7) /*!< Exclude item 7 when this item is checked */ -#define MIF_CHECKED BV(8) /*!< Item is currently checked */ -#define MIF_CHECKIT BV(9) /*!< Automatically check this item when selected */ -#define MIF_TOGGLE BV(10) /*!< Toggle MIF_CHECKED when item is selected */ -#define MIF_HIDDEN BV(11) /*!< This menu item is not visible */ -#define MIF_DISABLED BV(12) /*!< This menu item is not visible */ -#define MIF_RAMLABEL BV(13) /*!< Item label is stored in RAM, not in program memory */ -/* \} */ - -/** - * Menu description. - */ -typedef struct Menu -{ - MenuItem *items; /*!< Array of items (end with a NULL hook) */ - const_iptr_t title; /*!< Menu title (ID or ptr to string, 0 to disable) */ - int flags; /*!< See MF_#? definitions below */ - struct Bitmap *bitmap; /*!< Bitmap where the menu is rendered */ - int selected; /*!< Initial selection (written to if #MF_SAVESEL is set). */ -} Menu; - -/** - * \name Flags for Menu.flags. - * \{ - */ -#define MF_STICKY BV(0) /**< Stay in the menu when the items called return */ -#define MF_TOPLEVEL BV(1) /**< Top-level menu (do not display "back" label) */ -#define MF_ROMITEMS BV(2) /**< Menu items are stored in ROM (default is RAM) */ -#define MF_SAVESEL BV(3) /**< Remember the selected item across invocations. */ -/* \} */ - -/* Function prototypes */ -iptr_t menu_handle(const struct Menu *menu); -int menu_setFlags(struct Menu *menu, int idx, int flags); -int menu_clearFlags(struct Menu *menu, int idx, int flags); - -#endif /* MWARE_MENU_H */