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

Committer:
WiredHome
Date:
Sat Jan 03 15:35:20 2015 +0000
Revision:
0:905736afd672
Child:
1:d7a34c7f775b
Fixed a warning - caused by code-blindness of knowing what it should do and not seeing what it was doing...

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:905736afd672 1
WiredHome 0:905736afd672 2 #include "menu.h"
WiredHome 0:905736afd672 3
WiredHome 0:905736afd672 4 //#define DEBUG "menu"
WiredHome 0:905736afd672 5 // ...
WiredHome 0:905736afd672 6 // INFO("Stuff to show %d", var); // new-line is automatically appended
WiredHome 0:905736afd672 7 //
WiredHome 0:905736afd672 8 #if (defined(DEBUG) && !defined(TARGET_LPC11U24))
WiredHome 0:905736afd672 9 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:905736afd672 10 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:905736afd672 11 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 0:905736afd672 12 #else
WiredHome 0:905736afd672 13 #define INFO(x, ...)
WiredHome 0:905736afd672 14 #define WARN(x, ...)
WiredHome 0:905736afd672 15 #define ERR(x, ...)
WiredHome 0:905736afd672 16 #define HexDump(a, b, c)
WiredHome 0:905736afd672 17 #endif
WiredHome 0:905736afd672 18
WiredHome 0:905736afd672 19 Menu::~Menu()
WiredHome 0:905736afd672 20 {
WiredHome 0:905736afd672 21 }
WiredHome 0:905736afd672 22
WiredHome 0:905736afd672 23 Menu::Menu(RA8875 & _lcd, menu_item_t * _menu, color_t fg, color_t bg, color_t hl)
WiredHome 0:905736afd672 24 : lcd(_lcd), pTopMenu(_menu), pExpanded(0), isShowing(false),
WiredHome 0:905736afd672 25 menuForeground(fg), menuBackground(bg), menuHighlight(hl)
WiredHome 0:905736afd672 26 {
WiredHome 0:905736afd672 27 }
WiredHome 0:905736afd672 28
WiredHome 0:905736afd672 29 void Menu::init()
WiredHome 0:905736afd672 30 {
WiredHome 0:905736afd672 31 lcd.SetLayerMode(RA8875::TransparentMode);
WiredHome 0:905736afd672 32 lcd.SetLayerTransparency(0, 7);
WiredHome 0:905736afd672 33 }
WiredHome 0:905736afd672 34
WiredHome 0:905736afd672 35 void Menu::SetColors(color_t fg, color_t bg, color_t hl)
WiredHome 0:905736afd672 36 {
WiredHome 0:905736afd672 37 menuForeground = fg;
WiredHome 0:905736afd672 38 menuBackground = bg;
WiredHome 0:905736afd672 39 menuHighlight = hl;
WiredHome 0:905736afd672 40 }
WiredHome 0:905736afd672 41
WiredHome 0:905736afd672 42 bool Menu::_isTouched(menu_item_t * pMenu, rect_t r, point_t p, menu_item_t ** menuTouched)
WiredHome 0:905736afd672 43 {
WiredHome 0:905736afd672 44 while (pMenu->menuText) {
WiredHome 0:905736afd672 45 r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" "));
WiredHome 0:905736afd672 46 INFO("Is (%3d,%3d) in (%3d,%3d)-(%3d,%3d) %s [%s]",
WiredHome 0:905736afd672 47 p.x, p.y, r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText,
WiredHome 0:905736afd672 48 pExpanded ? pExpanded->child->menuText : "");
WiredHome 0:905736afd672 49 if (lcd.Intersect(r, p)) {
WiredHome 0:905736afd672 50 *menuTouched = pMenu;
WiredHome 0:905736afd672 51 return true;
WiredHome 0:905736afd672 52 }
WiredHome 0:905736afd672 53 if (!isShowing) // Activating this traps the menu activation to the first entry only.
WiredHome 0:905736afd672 54 break; // Disabling this permits anything on the top-line
WiredHome 0:905736afd672 55 if (isShowing && pMenu->child && pExpanded == pMenu) {
WiredHome 0:905736afd672 56 r.p1.x += lcd.fontwidth();
WiredHome 0:905736afd672 57 r.p1.y += lcd.fontheight();
WiredHome 0:905736afd672 58 r.p2.x = r.p1.x;
WiredHome 0:905736afd672 59 r.p2.y = r.p1.y + lcd.fontheight();
WiredHome 0:905736afd672 60 if (_isTouched(pMenu->child, r, p, menuTouched)) {
WiredHome 0:905736afd672 61 return true;
WiredHome 0:905736afd672 62 }
WiredHome 0:905736afd672 63 }
WiredHome 0:905736afd672 64 r.p1.x = r.p2.x;
WiredHome 0:905736afd672 65 pMenu++;
WiredHome 0:905736afd672 66 }
WiredHome 0:905736afd672 67 return false;
WiredHome 0:905736afd672 68 }
WiredHome 0:905736afd672 69
WiredHome 0:905736afd672 70 bool Menu::HandledTouch(point_t p, TouchCode_t touchcode)
WiredHome 0:905736afd672 71 {
WiredHome 0:905736afd672 72 rect_t r;
WiredHome 0:905736afd672 73 menu_item_t * pTouchedMenu = NULL;
WiredHome 0:905736afd672 74 bool handled = false;
WiredHome 0:905736afd672 75
WiredHome 0:905736afd672 76 r.p1.x = r.p1.y = r.p2.x = 0;
WiredHome 0:905736afd672 77 r.p2.y = lcd.fontheight();
WiredHome 0:905736afd672 78
WiredHome 0:905736afd672 79 if (_isTouched(pTopMenu, r, p, &pTouchedMenu)) {
WiredHome 0:905736afd672 80 INFO("Touched %s.\r\n", pTouchedMenu->menuText);
WiredHome 0:905736afd672 81 if (pTouchedMenu == pTopMenu && !isShowing && touchcode == touch) {
WiredHome 0:905736afd672 82 INFO("Show menu...\r\n");
WiredHome 0:905736afd672 83 Show();
WiredHome 0:905736afd672 84 INFO(" show done.\r\n");
WiredHome 0:905736afd672 85 } else {
WiredHome 0:905736afd672 86 post_fnc_action_t action = no_action;
WiredHome 0:905736afd672 87
WiredHome 0:905736afd672 88 switch (touchcode) {
WiredHome 0:905736afd672 89 case touch:
WiredHome 0:905736afd672 90 if (pTouchedMenu->fncPress) {
WiredHome 0:905736afd672 91 action = pTouchedMenu->fncPress(pTouchedMenu->param);
WiredHome 0:905736afd672 92 }
WiredHome 0:905736afd672 93 if (pTouchedMenu->child) {
WiredHome 0:905736afd672 94 INFO(" Expand %s.\r\n", pTouchedMenu->menuText);
WiredHome 0:905736afd672 95 Expand(pTouchedMenu);
WiredHome 0:905736afd672 96 INFO(" done.\r\n");
WiredHome 0:905736afd672 97 }
WiredHome 0:905736afd672 98 break;
WiredHome 0:905736afd672 99 case held:
WiredHome 0:905736afd672 100 if (pTouchedMenu->fncHeld) {
WiredHome 0:905736afd672 101 action = pTouchedMenu->fncHeld(pTouchedMenu->param);
WiredHome 0:905736afd672 102 }
WiredHome 0:905736afd672 103 break;
WiredHome 0:905736afd672 104 case release:
WiredHome 0:905736afd672 105 if (pTouchedMenu->fncRelease) {
WiredHome 0:905736afd672 106 action = pTouchedMenu->fncRelease(pTouchedMenu->param);
WiredHome 0:905736afd672 107 }
WiredHome 0:905736afd672 108 break;
WiredHome 0:905736afd672 109 default:
WiredHome 0:905736afd672 110 break;
WiredHome 0:905736afd672 111 }
WiredHome 0:905736afd672 112 if (action == close_menu) {
WiredHome 0:905736afd672 113 Hide();
WiredHome 0:905736afd672 114 }
WiredHome 0:905736afd672 115 }
WiredHome 0:905736afd672 116 handled = true;
WiredHome 0:905736afd672 117 }
WiredHome 0:905736afd672 118 return handled;
WiredHome 0:905736afd672 119 }
WiredHome 0:905736afd672 120
WiredHome 0:905736afd672 121 bool Menu::_GetMenuRect(menu_item_t * pMenu, menu_item_t * needle, rect_t * pRect)
WiredHome 0:905736afd672 122 {
WiredHome 0:905736afd672 123 rect_t r;
WiredHome 0:905736afd672 124
WiredHome 0:905736afd672 125 if (needle->menuText == NULL)
WiredHome 0:905736afd672 126 return false;
WiredHome 0:905736afd672 127 r.p1.x = r.p1.y = r.p2.x = 0;
WiredHome 0:905736afd672 128 r.p2.y = lcd.fontheight();
WiredHome 0:905736afd672 129 while (pMenu->menuText) {
WiredHome 0:905736afd672 130 r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" "));
WiredHome 0:905736afd672 131 if (pMenu == needle) {
WiredHome 0:905736afd672 132 *pRect = r;
WiredHome 0:905736afd672 133 return true;
WiredHome 0:905736afd672 134 }
WiredHome 0:905736afd672 135 r.p1.x = r.p2.x;
WiredHome 0:905736afd672 136 pMenu++;
WiredHome 0:905736afd672 137 }
WiredHome 0:905736afd672 138 return false;
WiredHome 0:905736afd672 139 }
WiredHome 0:905736afd672 140
WiredHome 0:905736afd672 141 void Menu::_Rect(rect_t r, color_t c, fill_t fill)
WiredHome 0:905736afd672 142 {
WiredHome 0:905736afd672 143 r.p2.x--;
WiredHome 0:905736afd672 144 r.p2.y--;
WiredHome 0:905736afd672 145 lcd.rect(r, c, fill);
WiredHome 0:905736afd672 146 }
WiredHome 0:905736afd672 147
WiredHome 0:905736afd672 148
WiredHome 0:905736afd672 149 void Menu::Expand(menu_item_t * thisMenu)
WiredHome 0:905736afd672 150 {
WiredHome 0:905736afd672 151 rect_t r;
WiredHome 0:905736afd672 152 bool same = (pExpanded == thisMenu) ? true : false;
WiredHome 0:905736afd672 153
WiredHome 0:905736afd672 154 if (pExpanded) { // need to hide this one first
WiredHome 0:905736afd672 155 INFO(" Hiding children of %s.", pExpanded->menuText);
WiredHome 0:905736afd672 156 _GetMenuRect(pTopMenu, pExpanded, &r);
WiredHome 0:905736afd672 157 _Rect(r, menuForeground);
WiredHome 0:905736afd672 158 r.p1.x += lcd.fontwidth();
WiredHome 0:905736afd672 159 r.p1.y += lcd.fontheight();
WiredHome 0:905736afd672 160 r.p2.x = r.p1.x;
WiredHome 0:905736afd672 161 r.p2.y = r.p1.y + lcd.fontheight();
WiredHome 0:905736afd672 162 _ShowMenu_Helper(pExpanded->child, r, false);
WiredHome 0:905736afd672 163 pExpanded = NULL;
WiredHome 0:905736afd672 164 }
WiredHome 0:905736afd672 165 if (!same && _GetMenuRect(pTopMenu, thisMenu, &r)) {
WiredHome 0:905736afd672 166 INFO(" Expanding to children of %s.", thisMenu->menuText);
WiredHome 0:905736afd672 167 _Rect(r, menuHighlight);
WiredHome 0:905736afd672 168 // index in a little, then down a row
WiredHome 0:905736afd672 169 r.p1.x += lcd.fontwidth();
WiredHome 0:905736afd672 170 r.p1.y += lcd.fontheight();
WiredHome 0:905736afd672 171 r.p2.x = r.p1.x;
WiredHome 0:905736afd672 172 r.p2.y = r.p1.y + lcd.fontheight();
WiredHome 0:905736afd672 173 _ShowMenu_Helper(thisMenu->child, r);
WiredHome 0:905736afd672 174 pExpanded = thisMenu;
WiredHome 0:905736afd672 175 }
WiredHome 0:905736afd672 176 }
WiredHome 0:905736afd672 177
WiredHome 0:905736afd672 178 void Menu::Show()
WiredHome 0:905736afd672 179 {
WiredHome 0:905736afd672 180 rect_t r;
WiredHome 0:905736afd672 181 INFO("Show()");
WiredHome 0:905736afd672 182 lcd.SelectDrawingLayer(MENUS);
WiredHome 0:905736afd672 183 lcd.SetLayerTransparency(7, 0);
WiredHome 0:905736afd672 184 //lcd.cls();
WiredHome 0:905736afd672 185 lcd.SetTextCursor(0,0);
WiredHome 0:905736afd672 186 r.p1.x = r.p1.y = r.p2.x = 0;
WiredHome 0:905736afd672 187 r.p2.y = lcd.fontheight();
WiredHome 0:905736afd672 188 menu_item_t * pMenu = pTopMenu;
WiredHome 0:905736afd672 189 _ShowMenu_Helper(pMenu, r);
WiredHome 0:905736afd672 190 isShowing = true;
WiredHome 0:905736afd672 191 }
WiredHome 0:905736afd672 192
WiredHome 0:905736afd672 193 void Menu::_ShowMenu_Helper(menu_item_t * pMenu, rect_t r, bool show)
WiredHome 0:905736afd672 194 {
WiredHome 0:905736afd672 195 while (pMenu->menuText) {
WiredHome 0:905736afd672 196 lcd.SetTextCursor(r.p1.x, r.p1.y);
WiredHome 0:905736afd672 197 r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" "));
WiredHome 0:905736afd672 198 if (show) {
WiredHome 0:905736afd672 199 INFO("(%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
WiredHome 0:905736afd672 200 lcd.foreground(menuForeground);
WiredHome 0:905736afd672 201 lcd.printf(" %s ", pMenu->menuText);
WiredHome 0:905736afd672 202 _Rect(r, menuForeground);
WiredHome 0:905736afd672 203 } else {
WiredHome 0:905736afd672 204 INFO("HIDE (%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
WiredHome 0:905736afd672 205 _Rect(r, menuBackground, FILL);
WiredHome 0:905736afd672 206 }
WiredHome 0:905736afd672 207 r.p1.x = r.p2.x;
WiredHome 0:905736afd672 208 pMenu++;
WiredHome 0:905736afd672 209 }
WiredHome 0:905736afd672 210 isShowing = true;
WiredHome 0:905736afd672 211 }
WiredHome 0:905736afd672 212
WiredHome 0:905736afd672 213 void Menu::Hide()
WiredHome 0:905736afd672 214 {
WiredHome 0:905736afd672 215 INFO("Hide()");
WiredHome 0:905736afd672 216 if (pExpanded)
WiredHome 0:905736afd672 217 Expand(pExpanded); // hides this menu
WiredHome 0:905736afd672 218 lcd.SelectDrawingLayer(CANVAS);
WiredHome 0:905736afd672 219 isShowing = false;
WiredHome 0:905736afd672 220 lcd.SetLayerTransparency(0, 7);
WiredHome 0:905736afd672 221 }
WiredHome 0:905736afd672 222