A primitive menu system for touchscreen on the RA8875. This menu is not "finger friendly" and reminds one of the 90's using a Palm.

Dependents:   FRDM_RA8875_mPaint PUB_RA8875_mPaint

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers menu.cpp Source File

menu.cpp

00001 
00002 #include "menu.h"
00003 
00004 //#define DEBUG "menu"
00005 // ...
00006 // INFO("Stuff to show %d", var); // new-line is automatically appended
00007 //
00008 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
00009 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00010 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00011 #define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
00012 #else
00013 #define INFO(x, ...)
00014 #define WARN(x, ...)
00015 #define ERR(x, ...)
00016 #define HexDump(a, b, c)
00017 #endif
00018 
00019 Menu::~Menu()
00020 {
00021 }
00022 
00023 Menu::Menu(RA8875 & _lcd, menu_item_t * _menu, color_t fg, color_t bg, color_t hl) 
00024     : lcd(_lcd), pTopMenu(_menu), pExpanded(0), isShowing(false), 
00025     menuForeground(fg), menuBackground(bg), menuHighlight(hl)
00026 {
00027 }
00028 
00029 void Menu::init()
00030 {
00031     lcd.SetLayerMode(RA8875::TransparentMode);
00032     lcd.SetLayerTransparency(0, 7);
00033     Show();
00034 }
00035 
00036 void Menu::SetColors(color_t fg, color_t bg, color_t hl)
00037 {
00038     menuForeground = fg;
00039     menuBackground = bg;
00040     menuHighlight = hl;
00041 }
00042 
00043 bool Menu::_isTouched(menu_item_t * pMenu, rect_t r, point_t p, menu_item_t ** menuTouched)
00044 {
00045     while (pMenu->menuText) {
00046         r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen("  "));
00047         INFO("Is (%3d,%3d) in (%3d,%3d)-(%3d,%3d) %s", p.x, p.y, r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
00048         if (lcd.Intersect(r, p)) {
00049             *menuTouched = pMenu;
00050             return true;
00051         }
00052 //        if (!isShowing)   // Activating this traps the menu activation to the first entry only.
00053 //            break;        // Disabling this permits anything on the top-line
00054         if (isShowing && pMenu->child && pExpanded == pMenu) {
00055             rect_t rectChild = r;
00056             INFO("    to child %s", pExpanded->child->menuText);
00057             rectChild.p1.x += lcd.fontwidth();
00058             rectChild.p1.y += lcd.fontheight();
00059             rectChild.p2.x = rectChild.p1.x;
00060             rectChild.p2.y = rectChild.p1.y + lcd.fontheight();
00061             if(_isTouched(pMenu->child, rectChild, p, menuTouched)) // walk the child items
00062                 return true;
00063         }
00064         r.p1.x = r.p2.x;
00065         pMenu++;
00066     }
00067     return false;
00068 }
00069 
00070 bool Menu::HandledTouch(point_t p, TouchCode_t touchcode)
00071 {
00072     rect_t r;
00073     menu_item_t * pTouchedMenu = NULL;
00074     bool handled = false;
00075     
00076     r.p1.x = r.p1.y = r.p2.x = 0;
00077     r.p2.y = lcd.fontheight();
00078     
00079     if (_isTouched(pTopMenu, r, p, &pTouchedMenu)) {
00080         INFO("Touched %s. touchcode:%d", pTouchedMenu->menuText, touchcode);
00081         if (!isShowing && touchcode == touch) {
00082             Show();
00083         }
00084         post_fnc_action_t action = no_action;
00085         switch (touchcode) {
00086             case touch:
00087                 if (pTouchedMenu->fncPress) {
00088                     action = pTouchedMenu->fncPress(pTouchedMenu->param);
00089                 }
00090                 if (pTouchedMenu->child) {
00091                     Expand(pTouchedMenu);
00092                 }
00093                 break;
00094             case held:
00095                 if (pTouchedMenu->fncHeld) {
00096                     action = pTouchedMenu->fncHeld(pTouchedMenu->param);
00097                 }
00098                 break;
00099             case release:
00100                 if (pTouchedMenu->fncRelease) {
00101                     action = pTouchedMenu->fncRelease(pTouchedMenu->param);
00102                 }
00103                 break;
00104             default:
00105                 break;
00106         }
00107         if (action == close_menu) {
00108             INFO("Hide it");
00109             Hide();
00110         }
00111         handled = true;
00112     }
00113     return handled;
00114 }
00115 
00116 bool Menu::_GetMenuRect(menu_item_t * pMenu, menu_item_t * needle, rect_t * pRect)
00117 {
00118     rect_t r;
00119     
00120     if (needle->menuText == NULL)
00121         return false;
00122     r.p1.x = r.p1.y = r.p2.x = 0;
00123     r.p2.y = lcd.fontheight();
00124     while (pMenu->menuText) {
00125         r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen("  "));
00126         if (pMenu == needle) {
00127             *pRect = r;
00128             return true;
00129         }
00130         r.p1.x = r.p2.x;
00131         pMenu++;
00132     }
00133     return false;
00134 }
00135 
00136 void Menu::_Rect(rect_t r, color_t c, fill_t fill)
00137 {
00138     r.p2.x--;
00139     r.p2.y--;
00140     lcd.rect(r, c, fill);
00141 }
00142 
00143 
00144 void Menu::Expand(menu_item_t * thisMenu)
00145 {
00146     rect_t r;
00147     bool same = (pExpanded == thisMenu) ? true : false;
00148     INFO("Expand(%s)", thisMenu->menuText);
00149     if (pExpanded) { // need to hide this one first
00150         INFO("  Hiding children of %s. this=%s, same=%d", pExpanded->menuText, thisMenu->menuText, same);
00151         _GetMenuRect(pTopMenu, pExpanded, &r);
00152         _Rect(r, menuForeground);
00153         r.p1.x += lcd.fontwidth();
00154         r.p1.y += lcd.fontheight();
00155         r.p2.x = r.p1.x;
00156         r.p2.y = r.p1.y + lcd.fontheight();
00157         _ShowMenu_Helper(pExpanded->child, r, false);
00158         pExpanded = NULL;
00159     }
00160     if (!same && _GetMenuRect(pTopMenu, thisMenu, &r)) {
00161         INFO("  Expanding to children of %s.", thisMenu->menuText);
00162         _Rect(r, menuHighlight);
00163         // index in a little, then down a row
00164         r.p1.x += lcd.fontwidth();
00165         r.p1.y += lcd.fontheight();
00166         r.p2.x = r.p1.x;
00167         r.p2.y = r.p1.y + lcd.fontheight();
00168         _ShowMenu_Helper(thisMenu->child, r);
00169         pExpanded = thisMenu;
00170     }
00171 }
00172 
00173 void Menu::Show()
00174 {
00175     rect_t r;
00176     INFO("Show()");
00177     lcd.SelectDrawingLayer(MENUS);
00178     lcd.SetLayerTransparency(7, 0);     // emphasize the menu
00179     lcd.SetTextCursor(0,0);
00180     r.p1.x = r.p1.y = r.p2.x = 0;
00181     r.p2.y = lcd.fontheight();
00182     menu_item_t * pMenu = pTopMenu;
00183     _ShowMenu_Helper(pMenu, r);
00184     isShowing = true;
00185 }
00186 
00187 void Menu::_ShowMenu_Helper(menu_item_t * pMenu, rect_t r, bool show)
00188 {
00189     while (pMenu->menuText) {
00190         lcd.SetTextCursor(r.p1.x, r.p1.y);
00191         r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen("  "));
00192         if (show) {
00193             INFO("(%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
00194             lcd.foreground(menuForeground);
00195             lcd.printf(" %s ", pMenu->menuText);
00196             _Rect(r, menuForeground);
00197         } else {
00198             INFO("HIDE (%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
00199             _Rect(r, menuBackground, FILL);
00200         }
00201         r.p1.x = r.p2.x;
00202         pMenu++;
00203     }
00204     isShowing = true;
00205 }
00206 
00207 void Menu::Hide()
00208 {
00209     INFO("Hide()");
00210     if (pExpanded)
00211         Expand(pExpanded); // hides this menu
00212     lcd.SelectDrawingLayer(CANVAS);
00213     isShowing = false;
00214     lcd.SetLayerTransparency(0, 7);     // emphasize the canvas
00215 }
00216