X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=gui%2Fmenu.c;h=f02324ecf2c2b02e4738cb500dcc5f8b18a73fdd;hb=07382ad480794063a2d5be63547eb288034d9832;hp=8a08fe8df3afd608576490a0dd0ca3a0f928766d;hpb=969f9a6fd4c736973771e39a7516ba56d9453216;p=bertos.git diff --git a/gui/menu.c b/gui/menu.c old mode 100755 new mode 100644 index 8a08fe8d..f02324ec --- a/gui/menu.c +++ b/gui/menu.c @@ -1,9 +1,34 @@ -/*! +/** * \file * * * \version $Id$ @@ -16,6 +41,27 @@ /*#* *#* $Log$ + *#* Revision 1.8 2006/09/13 13:58:32 bernie + *#* Add RenderHook support. + *#* + *#* Revision 1.7 2006/08/01 12:22:46 bernie + *#* Mention DevLib license. + *#* + *#* Revision 1.6 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.5 2006/06/03 13:58:01 bernie + *#* Fix recursive timeout and add exit status information. + *#* + *#* Revision 1.4 2006/06/02 12:26:18 bernie + *#* Draw graphical checkmarks. + *#* + *#* Revision 1.3 2006/05/28 15:03:31 bernie + *#* Avoid unnecessary rendering. + *#* + *#* Revision 1.2 2006/05/25 23:34:38 bernie + *#* Implement menu timeouts. + *#* *#* Revision 1.1 2006/05/15 07:20:54 bernie *#* Move menu to gui/. *#* @@ -36,54 +82,10 @@ *#* *#* 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 @@ -101,6 +103,10 @@ #include #endif +#if (CONFIG_MENU_TIMEOUT != 0) +#include +#endif + #if CONFIG_MENU_MENUBAR #include "menubar.h" #endif @@ -111,6 +117,7 @@ #define PTRMSG(x) ((const char *)x) #endif + /* Temporary fake defines for ABORT stuff... */ #define abort_top 0 #define PUSH_ABORT false @@ -119,7 +126,7 @@ /** - * Count the items present in a menu. + * Return the total number of items in in a menu. */ static int menu_count(const struct Menu *menu) { @@ -145,9 +152,8 @@ static int menu_count(const struct Menu *menu) #if CONFIG_MENU_MENUBAR -/*! - * Update the menu bar according to the selected item - * and redraw it. +/** + * Update the menu bar according to the selected item and redraw it. */ static void menu_update_menubar( const struct Menu *menu, @@ -183,40 +189,84 @@ static void menu_update_menubar( #endif /* CONFIG_MENU_MENUBAR */ +static void menu_defaultRenderHook(struct Bitmap *bm, int ypos, bool selected, const struct MenuItem *item) +{ + if (item->flags & MIF_CHECKIT) + { + gfx_rectClear(bm, 0, ypos, + bm->font->height, ypos + bm->font->height); + + if (item->flags & MIF_TOGGLE) + gfx_rectDraw(bm, 2, ypos + 2, + bm->font->height - 2, ypos + bm->font->height - 2); + if (item->flags & MIF_CHECKED) + { + gfx_line(bm, + 3, ypos + 3, + bm->font->height - 3, ypos + bm->font->height - 3); + gfx_line(bm, + bm->font->height - 3, ypos + 3, + 3, ypos + bm->font->height - 3); + } + } + +#if CPU_HARVARD + ((item->flags & MIF_RAMLABEL) ? text_xyprintf : text_xyprintf_P) +#else + text_xyprintf +#endif + ( + bm, (item->flags & MIF_CHECKIT) ? bm->font->height : 0, ypos, + selected ? (STYLEF_INVERT | TEXT_FILL) : TEXT_FILL, + PTRMSG(item->label) + ); +} + /** * Show a menu on the display. */ static void menu_layout( const struct Menu *menu, int first_item, - int items_per_page, - int selected) + int selected, + bool redraw) { - int ypos, cnt; + coord_t ypos; + int i; const char * PROGMEM title = PTRMSG(menu->title); Bitmap *bm = menu->bitmap; ypos = bm->cr.ymin; +#if 0 + if (redraw) + { + /* Clear screen */ + text_clear(menu->bitmap); + } +#endif + if (title) { - text_xyprintf(bm, 0, ypos, STYLEF_UNDERLINE | STYLEF_BOLD | TEXT_CENTER | TEXT_FILL, title); + if (redraw) + 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; + /* Clip drawing inside menu items area */ gfx_setClipRect(bm, bm->cr.xmin, bm->cr.ymin + ypos, bm->cr.xmax, bm->cr.ymax); if (old_first_item != first_item) { + /* Speed proportional to distance */ speed = ABS(old_first_item - first_item) * 3; if (old_first_item > first_item) @@ -237,14 +287,16 @@ static void menu_layout( ++old_first_item; } } - first_item = old_first_item; + first_item = MIN(old_first_item, menu_count(menu)); + + ypos += yoffset; + redraw = true; } - ypos += yoffset; -#endif +#endif /* CONFIG_MENU_SMOOTH */ - for (cnt = 0; cnt < items_per_page; ++cnt) + if (redraw) for (i = first_item; /**/; ++i) { - const MenuItem *item = &menu->items[first_item + cnt]; + const MenuItem *item = &menu->items[i]; #if CPU_HARVARD MenuItem ram_item; if (menu->flags & MF_ROMITEMS) @@ -252,7 +304,11 @@ static void menu_layout( memcpy_P(&ram_item, item, sizeof(ram_item)); item = &ram_item; } -#endif +#endif /* CPU_HARVARD */ + + /* Check for end of room */ + if (ypos > bm->cr.ymax) + break; /* Check for end of menu */ if (!(item->label || item->hook)) @@ -261,40 +317,41 @@ static void menu_layout( /* 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("") ) - ); + /* Check if a special render function is supplied, otherwise use defaults */ + RenderHook renderhook = (item->flags & MIF_RENDERHOOK) ? (RenderHook)item->label : menu_defaultRenderHook; + + /* Render menuitem */ + renderhook(menu->bitmap, ypos++, (i == selected), item); + ypos += bm->font->height; } } #if CONFIG_MENU_SMOOTH + if (redraw) + { + /* Clear rest of area */ + gfx_rectClear(bm, bm->cr.xmin, ypos, bm->cr.xmax, bm->cr.ymax); + + lcd_blitBitmap(&lcd_bitmap); + } + /* Restore old cliprect */ gfx_setClipRect(bm, bm->cr.xmin, old_ymin, bm->cr.xmax, bm->cr.ymax); - lcd_blitBitmap(&lcd_bitmap); -#endif +#endif /* CONFIG_MENU_SMOOTH */ } -/*! +/** * Handle menu item selection */ -static void menu_doselect(const struct Menu *menu, struct MenuItem *item) +static iptr_t menu_doselect(const struct Menu *menu, struct MenuItem *item) { + iptr_t result = 0; + /* Exclude other items */ int mask, i; for (mask = item->flags & MIF_EXCLUDE_MASK, i = 0; mask; mask >>= 1, ++i) @@ -304,7 +361,7 @@ static void menu_doselect(const struct Menu *menu, struct MenuItem *item) } if (item->flags & MIF_DISABLED) - return; + return MENU_DISABLED; /* Handle checkable items */ if (item->flags & MIF_TOGGLE) @@ -315,13 +372,17 @@ static void menu_doselect(const struct Menu *menu, struct MenuItem *item) /* Handle items with callback hooks */ if (item->hook) { - /* Push a jmp buffer to abort the operation with the STOP key */ + /* Push a jmp buffer to abort the operation with the STOP/CANCEL key */ if (!PUSH_ABORT) { - item->hook(item->userdata); + result = item->hook(item->userdata); POP_ABORT; } } + else + result = item->userdata; + + return result; } @@ -383,13 +444,20 @@ static int menu_prev_visible_item(const struct Menu *menu, int 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; + uint8_t first_item = 0; + uint8_t selected; + iptr_t result = 0; + bool redraw = true; + +#if (CONFIG_MENU_TIMEOUT != 0) + ticks_t now, menu_idle_time = timer_clock(); +#endif #if CONFIG_MENU_MENUBAR struct MenuBar mb; @@ -419,10 +487,9 @@ iptr_t menu_handle(const struct Menu *menu) - (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); + //first_item = selected = menu_next_visible_item(menu, menu->selected - 1); + selected = menu->selected; + first_item = 0; for(;;) { @@ -436,17 +503,25 @@ iptr_t menu_handle(const struct Menu *menu) 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); + menu_layout(menu, first_item, selected, redraw); + redraw = false; #if CONFIG_MENU_MENUBAR menu_update_menubar(menu, &mb, selected); #endif -#if CONFIG_MENU_SMOOTH - key = kbd_peek(); -#else - key = kbd_get(); -#endif + #if CONFIG_MENU_SMOOTH || (CONFIG_MENU_TIMEOUT != 0) + key = kbd_peek(); + #else + key = kbd_get(); + #endif + + #if (CONFIG_MENU_TIMEOUT != 0) + /* Reset idle timer on key press. */ + now = timer_clock(); + if (key) + menu_idle_time = now; + #endif if (key & K_OK) { @@ -459,40 +534,59 @@ iptr_t menu_handle(const struct Menu *menu) item = &ram_item; } #endif - menu_doselect(menu, item); + result = menu_doselect(menu, item); + redraw = true; - /* 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; - } + /* Return immediately */ + if (!(menu->flags & MF_STICKY)) + break; - /* Clear screen */ - text_clear(menu->bitmap); + #if (CONFIG_MENU_TIMEOUT != 0) + /* Chain timeout */ + if ((result == MENU_TIMEOUT) && !(menu->flags & MF_TOPLEVEL)) + break; + + /* Reset timeout */ + menu_idle_time = timer_clock(); + #endif } else if (key & K_UP) { selected = menu_prev_visible_item(menu, selected); + redraw = true; } else if (key & K_DOWN) { selected = menu_next_visible_item(menu, selected); + redraw = true; } - else if (key & K_CANCEL && !(menu->flags & MF_TOPLEVEL)) + else if (!(menu->flags & MF_TOPLEVEL)) { - /* Store currently selected item before leaving. */ - if (menu->flags & MF_SAVESEL) - CONST_CAST(struct Menu *, menu)->selected = selected; - return 0; + if (key & K_CANCEL) + { + result = MENU_CANCEL; + break; + } + + #if CONFIG_MENU_TIMEOUT != 0 + if (now - menu_idle_time > ms_to_ticks(CONFIG_MENU_TIMEOUT)) + { + result = MENU_TIMEOUT; + break; + } + #endif } } + + /* Store currently selected item before leaving. */ + if (menu->flags & MF_SAVESEL) + CONST_CAST(struct Menu *, menu)->selected = selected; + + return result; } -/*! +/** * Set flags on a menuitem. * * \param menu Menu owner of the item to change. @@ -512,7 +606,7 @@ int menu_setFlags(struct Menu *menu, int idx, int flags) } -/*! +/** * Clear flags on a menuitem. * * \param menu Menu owner of the item to change.