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
menu.cpp@3:b59d6f7c1e68, 2015-01-03 (annotated)
- 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?
User | Revision | Line number | New 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 |