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
- Committer:
- WiredHome
- Date:
- 2015-01-03
- Revision:
- 1:d7a34c7f775b
- Parent:
- 0:905736afd672
File content as of revision 1:d7a34c7f775b:
#include "menu.h" //#define DEBUG "menu" // ... // INFO("Stuff to show %d", var); // new-line is automatically appended // #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); #else #define INFO(x, ...) #define WARN(x, ...) #define ERR(x, ...) #define HexDump(a, b, c) #endif Menu::~Menu() { } Menu::Menu(RA8875 & _lcd, menu_item_t * _menu, color_t fg, color_t bg, color_t hl) : lcd(_lcd), pTopMenu(_menu), pExpanded(0), isShowing(false), menuForeground(fg), menuBackground(bg), menuHighlight(hl) { } void Menu::init() { lcd.SetLayerMode(RA8875::TransparentMode); lcd.SetLayerTransparency(0, 7); Show(); } void Menu::SetColors(color_t fg, color_t bg, color_t hl) { menuForeground = fg; menuBackground = bg; menuHighlight = hl; } bool Menu::_isTouched(menu_item_t * pMenu, rect_t r, point_t p, menu_item_t ** menuTouched) { while (pMenu->menuText) { r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" ")); 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); if (lcd.Intersect(r, p)) { *menuTouched = pMenu; return true; } // if (!isShowing) // Activating this traps the menu activation to the first entry only. // break; // Disabling this permits anything on the top-line if (isShowing && pMenu->child && pExpanded == pMenu) { rect_t rectChild = r; INFO(" to child %s", pExpanded->child->menuText); rectChild.p1.x += lcd.fontwidth(); rectChild.p1.y += lcd.fontheight(); rectChild.p2.x = rectChild.p1.x; rectChild.p2.y = rectChild.p1.y + lcd.fontheight(); if(_isTouched(pMenu->child, rectChild, p, menuTouched)) // walk the child items return true; } r.p1.x = r.p2.x; pMenu++; } return false; } bool Menu::HandledTouch(point_t p, TouchCode_t touchcode) { rect_t r; menu_item_t * pTouchedMenu = NULL; bool handled = false; r.p1.x = r.p1.y = r.p2.x = 0; r.p2.y = lcd.fontheight(); if (_isTouched(pTopMenu, r, p, &pTouchedMenu)) { INFO("Touched %s. touchcode:%d", pTouchedMenu->menuText, touchcode); if (!isShowing && touchcode == touch) { Show(); } post_fnc_action_t action = no_action; switch (touchcode) { case touch: if (pTouchedMenu->fncPress) { action = pTouchedMenu->fncPress(pTouchedMenu->param); } if (pTouchedMenu->child) { Expand(pTouchedMenu); } break; case held: if (pTouchedMenu->fncHeld) { action = pTouchedMenu->fncHeld(pTouchedMenu->param); } break; case release: if (pTouchedMenu->fncRelease) { action = pTouchedMenu->fncRelease(pTouchedMenu->param); } break; default: break; } if (action == close_menu) { INFO("Hide it"); Hide(); } handled = true; } return handled; } bool Menu::_GetMenuRect(menu_item_t * pMenu, menu_item_t * needle, rect_t * pRect) { rect_t r; if (needle->menuText == NULL) return false; r.p1.x = r.p1.y = r.p2.x = 0; r.p2.y = lcd.fontheight(); while (pMenu->menuText) { r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" ")); if (pMenu == needle) { *pRect = r; return true; } r.p1.x = r.p2.x; pMenu++; } return false; } void Menu::_Rect(rect_t r, color_t c, fill_t fill) { r.p2.x--; r.p2.y--; lcd.rect(r, c, fill); } void Menu::Expand(menu_item_t * thisMenu) { rect_t r; bool same = (pExpanded == thisMenu) ? true : false; INFO("Expand(%s)", thisMenu->menuText); if (pExpanded) { // need to hide this one first INFO(" Hiding children of %s. this=%s, same=%d", pExpanded->menuText, thisMenu->menuText, same); _GetMenuRect(pTopMenu, pExpanded, &r); _Rect(r, menuForeground); r.p1.x += lcd.fontwidth(); r.p1.y += lcd.fontheight(); r.p2.x = r.p1.x; r.p2.y = r.p1.y + lcd.fontheight(); _ShowMenu_Helper(pExpanded->child, r, false); pExpanded = NULL; } if (!same && _GetMenuRect(pTopMenu, thisMenu, &r)) { INFO(" Expanding to children of %s.", thisMenu->menuText); _Rect(r, menuHighlight); // index in a little, then down a row r.p1.x += lcd.fontwidth(); r.p1.y += lcd.fontheight(); r.p2.x = r.p1.x; r.p2.y = r.p1.y + lcd.fontheight(); _ShowMenu_Helper(thisMenu->child, r); pExpanded = thisMenu; } } void Menu::Show() { rect_t r; INFO("Show()"); lcd.SelectDrawingLayer(MENUS); lcd.SetLayerTransparency(7, 0); // emphasize the menu lcd.SetTextCursor(0,0); r.p1.x = r.p1.y = r.p2.x = 0; r.p2.y = lcd.fontheight(); menu_item_t * pMenu = pTopMenu; _ShowMenu_Helper(pMenu, r); isShowing = true; } void Menu::_ShowMenu_Helper(menu_item_t * pMenu, rect_t r, bool show) { while (pMenu->menuText) { lcd.SetTextCursor(r.p1.x, r.p1.y); r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen(" ")); if (show) { INFO("(%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText); lcd.foreground(menuForeground); lcd.printf(" %s ", pMenu->menuText); _Rect(r, menuForeground); } else { INFO("HIDE (%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText); _Rect(r, menuBackground, FILL); } r.p1.x = r.p2.x; pMenu++; } isShowing = true; } void Menu::Hide() { INFO("Hide()"); if (pExpanded) Expand(pExpanded); // hides this menu lcd.SelectDrawingLayer(CANVAS); isShowing = false; lcd.SetLayerTransparency(0, 7); // emphasize the canvas }