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 17:24:55 2015 +0000
Revision:
3:b59d6f7c1e68
Parent:
1:d7a34c7f775b
Tiny documentation fix.

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 1:d7a34c7f775b 33 Show();
WiredHome 0:905736afd672 34 }
WiredHome 0:905736afd672 35
WiredHome 0:905736afd672 36 void Menu::SetColors(color_t fg, color_t bg, color_t hl)
WiredHome 0:905736afd672 37 {
WiredHome 0:905736afd672 38 menuForeground = fg;
WiredHome 0:905736afd672 39 menuBackground = bg;
WiredHome 0:905736afd672 40 menuHighlight = hl;
WiredHome 0:905736afd672 41 }
WiredHome 0:905736afd672 42
WiredHome 0:905736afd672 43 bool Menu::_isTouched(menu_item_t * pMenu, rect_t r, point_t p, menu_item_t ** menuTouched)
WiredHome 0:905736afd672 44 {
WiredHome 0:905736afd672 45 while (pMenu->menuText) {
WiredHome 0:905736afd672 46 r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" "));
WiredHome 1:d7a34c7f775b 47 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);
WiredHome 0:905736afd672 48 if (lcd.Intersect(r, p)) {
WiredHome 0:905736afd672 49 *menuTouched = pMenu;
WiredHome 0:905736afd672 50 return true;
WiredHome 0:905736afd672 51 }
WiredHome 1:d7a34c7f775b 52 // if (!isShowing) // Activating this traps the menu activation to the first entry only.
WiredHome 1:d7a34c7f775b 53 // break; // Disabling this permits anything on the top-line
WiredHome 0:905736afd672 54 if (isShowing && pMenu->child && pExpanded == pMenu) {
WiredHome 1:d7a34c7f775b 55 rect_t rectChild = r;
WiredHome 1:d7a34c7f775b 56 INFO(" to child %s", pExpanded->child->menuText);
WiredHome 1:d7a34c7f775b 57 rectChild.p1.x += lcd.fontwidth();
WiredHome 1:d7a34c7f775b 58 rectChild.p1.y += lcd.fontheight();
WiredHome 1:d7a34c7f775b 59 rectChild.p2.x = rectChild.p1.x;
WiredHome 1:d7a34c7f775b 60 rectChild.p2.y = rectChild.p1.y + lcd.fontheight();
WiredHome 1:d7a34c7f775b 61 if(_isTouched(pMenu->child, rectChild, p, menuTouched)) // walk the child items
WiredHome 0:905736afd672 62 return true;
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 1:d7a34c7f775b 80 INFO("Touched %s. touchcode:%d", pTouchedMenu->menuText, touchcode);
WiredHome 1:d7a34c7f775b 81 if (!isShowing && touchcode == touch) {
WiredHome 0:905736afd672 82 Show();
WiredHome 1:d7a34c7f775b 83 }
WiredHome 1:d7a34c7f775b 84 post_fnc_action_t action = no_action;
WiredHome 1:d7a34c7f775b 85 switch (touchcode) {
WiredHome 1:d7a34c7f775b 86 case touch:
WiredHome 1:d7a34c7f775b 87 if (pTouchedMenu->fncPress) {
WiredHome 1:d7a34c7f775b 88 action = pTouchedMenu->fncPress(pTouchedMenu->param);
WiredHome 1:d7a34c7f775b 89 }
WiredHome 1:d7a34c7f775b 90 if (pTouchedMenu->child) {
WiredHome 1:d7a34c7f775b 91 Expand(pTouchedMenu);
WiredHome 1:d7a34c7f775b 92 }
WiredHome 1:d7a34c7f775b 93 break;
WiredHome 1:d7a34c7f775b 94 case held:
WiredHome 1:d7a34c7f775b 95 if (pTouchedMenu->fncHeld) {
WiredHome 1:d7a34c7f775b 96 action = pTouchedMenu->fncHeld(pTouchedMenu->param);
WiredHome 1:d7a34c7f775b 97 }
WiredHome 1:d7a34c7f775b 98 break;
WiredHome 1:d7a34c7f775b 99 case release:
WiredHome 1:d7a34c7f775b 100 if (pTouchedMenu->fncRelease) {
WiredHome 1:d7a34c7f775b 101 action = pTouchedMenu->fncRelease(pTouchedMenu->param);
WiredHome 1:d7a34c7f775b 102 }
WiredHome 1:d7a34c7f775b 103 break;
WiredHome 1:d7a34c7f775b 104 default:
WiredHome 1:d7a34c7f775b 105 break;
WiredHome 1:d7a34c7f775b 106 }
WiredHome 1:d7a34c7f775b 107 if (action == close_menu) {
WiredHome 1:d7a34c7f775b 108 INFO("Hide it");
WiredHome 1:d7a34c7f775b 109 Hide();
WiredHome 0:905736afd672 110 }
WiredHome 0:905736afd672 111 handled = true;
WiredHome 0:905736afd672 112 }
WiredHome 0:905736afd672 113 return handled;
WiredHome 0:905736afd672 114 }
WiredHome 0:905736afd672 115
WiredHome 0:905736afd672 116 bool Menu::_GetMenuRect(menu_item_t * pMenu, menu_item_t * needle, rect_t * pRect)
WiredHome 0:905736afd672 117 {
WiredHome 0:905736afd672 118 rect_t r;
WiredHome 0:905736afd672 119
WiredHome 0:905736afd672 120 if (needle->menuText == NULL)
WiredHome 0:905736afd672 121 return false;
WiredHome 0:905736afd672 122 r.p1.x = r.p1.y = r.p2.x = 0;
WiredHome 0:905736afd672 123 r.p2.y = lcd.fontheight();
WiredHome 0:905736afd672 124 while (pMenu->menuText) {
WiredHome 0:905736afd672 125 r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" "));
WiredHome 0:905736afd672 126 if (pMenu == needle) {
WiredHome 0:905736afd672 127 *pRect = r;
WiredHome 0:905736afd672 128 return true;
WiredHome 0:905736afd672 129 }
WiredHome 0:905736afd672 130 r.p1.x = r.p2.x;
WiredHome 0:905736afd672 131 pMenu++;
WiredHome 0:905736afd672 132 }
WiredHome 0:905736afd672 133 return false;
WiredHome 0:905736afd672 134 }
WiredHome 0:905736afd672 135
WiredHome 0:905736afd672 136 void Menu::_Rect(rect_t r, color_t c, fill_t fill)
WiredHome 0:905736afd672 137 {
WiredHome 0:905736afd672 138 r.p2.x--;
WiredHome 0:905736afd672 139 r.p2.y--;
WiredHome 0:905736afd672 140 lcd.rect(r, c, fill);
WiredHome 0:905736afd672 141 }
WiredHome 0:905736afd672 142
WiredHome 0:905736afd672 143
WiredHome 0:905736afd672 144 void Menu::Expand(menu_item_t * thisMenu)
WiredHome 0:905736afd672 145 {
WiredHome 0:905736afd672 146 rect_t r;
WiredHome 0:905736afd672 147 bool same = (pExpanded == thisMenu) ? true : false;
WiredHome 1:d7a34c7f775b 148 INFO("Expand(%s)", thisMenu->menuText);
WiredHome 0:905736afd672 149 if (pExpanded) { // need to hide this one first
WiredHome 1:d7a34c7f775b 150 INFO(" Hiding children of %s. this=%s, same=%d", pExpanded->menuText, thisMenu->menuText, same);
WiredHome 0:905736afd672 151 _GetMenuRect(pTopMenu, pExpanded, &r);
WiredHome 0:905736afd672 152 _Rect(r, menuForeground);
WiredHome 0:905736afd672 153 r.p1.x += lcd.fontwidth();
WiredHome 0:905736afd672 154 r.p1.y += lcd.fontheight();
WiredHome 0:905736afd672 155 r.p2.x = r.p1.x;
WiredHome 0:905736afd672 156 r.p2.y = r.p1.y + lcd.fontheight();
WiredHome 0:905736afd672 157 _ShowMenu_Helper(pExpanded->child, r, false);
WiredHome 0:905736afd672 158 pExpanded = NULL;
WiredHome 0:905736afd672 159 }
WiredHome 0:905736afd672 160 if (!same && _GetMenuRect(pTopMenu, thisMenu, &r)) {
WiredHome 0:905736afd672 161 INFO(" Expanding to children of %s.", thisMenu->menuText);
WiredHome 0:905736afd672 162 _Rect(r, menuHighlight);
WiredHome 0:905736afd672 163 // index in a little, then down a row
WiredHome 0:905736afd672 164 r.p1.x += lcd.fontwidth();
WiredHome 0:905736afd672 165 r.p1.y += lcd.fontheight();
WiredHome 0:905736afd672 166 r.p2.x = r.p1.x;
WiredHome 0:905736afd672 167 r.p2.y = r.p1.y + lcd.fontheight();
WiredHome 0:905736afd672 168 _ShowMenu_Helper(thisMenu->child, r);
WiredHome 0:905736afd672 169 pExpanded = thisMenu;
WiredHome 0:905736afd672 170 }
WiredHome 0:905736afd672 171 }
WiredHome 0:905736afd672 172
WiredHome 0:905736afd672 173 void Menu::Show()
WiredHome 0:905736afd672 174 {
WiredHome 0:905736afd672 175 rect_t r;
WiredHome 0:905736afd672 176 INFO("Show()");
WiredHome 0:905736afd672 177 lcd.SelectDrawingLayer(MENUS);
WiredHome 1:d7a34c7f775b 178 lcd.SetLayerTransparency(7, 0); // emphasize the menu
WiredHome 0:905736afd672 179 lcd.SetTextCursor(0,0);
WiredHome 0:905736afd672 180 r.p1.x = r.p1.y = r.p2.x = 0;
WiredHome 0:905736afd672 181 r.p2.y = lcd.fontheight();
WiredHome 0:905736afd672 182 menu_item_t * pMenu = pTopMenu;
WiredHome 0:905736afd672 183 _ShowMenu_Helper(pMenu, r);
WiredHome 0:905736afd672 184 isShowing = true;
WiredHome 0:905736afd672 185 }
WiredHome 0:905736afd672 186
WiredHome 0:905736afd672 187 void Menu::_ShowMenu_Helper(menu_item_t * pMenu, rect_t r, bool show)
WiredHome 0:905736afd672 188 {
WiredHome 0:905736afd672 189 while (pMenu->menuText) {
WiredHome 0:905736afd672 190 lcd.SetTextCursor(r.p1.x, r.p1.y);
WiredHome 0:905736afd672 191 r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" "));
WiredHome 0:905736afd672 192 if (show) {
WiredHome 0:905736afd672 193 INFO("(%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
WiredHome 0:905736afd672 194 lcd.foreground(menuForeground);
WiredHome 0:905736afd672 195 lcd.printf(" %s ", pMenu->menuText);
WiredHome 0:905736afd672 196 _Rect(r, menuForeground);
WiredHome 0:905736afd672 197 } else {
WiredHome 0:905736afd672 198 INFO("HIDE (%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
WiredHome 0:905736afd672 199 _Rect(r, menuBackground, FILL);
WiredHome 0:905736afd672 200 }
WiredHome 0:905736afd672 201 r.p1.x = r.p2.x;
WiredHome 0:905736afd672 202 pMenu++;
WiredHome 0:905736afd672 203 }
WiredHome 0:905736afd672 204 isShowing = true;
WiredHome 0:905736afd672 205 }
WiredHome 0:905736afd672 206
WiredHome 0:905736afd672 207 void Menu::Hide()
WiredHome 0:905736afd672 208 {
WiredHome 0:905736afd672 209 INFO("Hide()");
WiredHome 0:905736afd672 210 if (pExpanded)
WiredHome 0:905736afd672 211 Expand(pExpanded); // hides this menu
WiredHome 0:905736afd672 212 lcd.SelectDrawingLayer(CANVAS);
WiredHome 0:905736afd672 213 isShowing = false;
WiredHome 1:d7a34c7f775b 214 lcd.SetLayerTransparency(0, 7); // emphasize the canvas
WiredHome 0:905736afd672 215 }
WiredHome 0:905736afd672 216