diff --git a/src/Makefile.am b/src/Makefile.am index 46c6bd0..bd765b2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,8 @@ gmenu2x_SOURCES = font.cpp button.cpp cpu.cpp dirdialog.cpp filedialog.cpp \ textdialog.cpp textmanualdialog.cpp touchscreen.cpp translator.cpp \ utilities.cpp wallpaperdialog.cpp \ browsedialog.cpp buttonbox.cpp dialog.cpp \ - imageio.cpp powersaver.cpp monitor.cpp mediamonitor.cpp clock.cpp + imageio.cpp powersaver.cpp monitor.cpp mediamonitor.cpp clock.cpp \ + helppopup.cpp noinst_HEADERS = font.h button.h cpu.h dirdialog.h \ filedialog.h filelister.h gmenu2x.h gp2x.h iconbutton.h imagedialog.h \ @@ -25,7 +26,8 @@ noinst_HEADERS = font.h button.h cpu.h dirdialog.h \ surfacecollection.h surface.h textdialog.h textmanualdialog.h \ touchscreen.h translator.h utilities.h wallpaperdialog.h \ browsedialog.h buttonbox.h dialog.h \ - imageio.h powersaver.h monitor.h mediamonitor.h clock.h + imageio.h powersaver.h monitor.h mediamonitor.h clock.h \ + layer.h helppopup.h AM_CFLAGS= @CFLAGS@ @SDL_CFLAGS@ diff --git a/src/gmenu2x.cpp b/src/gmenu2x.cpp index a90e1eb..7928a78 100644 --- a/src/gmenu2x.cpp +++ b/src/gmenu2x.cpp @@ -27,6 +27,7 @@ #include "filelister.h" #include "font.h" #include "gmenu2x.h" +#include "helppopup.h" #include "iconbutton.h" #include "inputdialog.h" #include "linkapp.h" @@ -231,6 +232,7 @@ GMenu2X::GMenu2X() bg = NULL; font = NULL; menu = NULL; + helpPopup = nullptr; btnContextMenu = nullptr; setSkin(confStr["skin"], !fileExists(confStr["wallpaper"])); initMenu(); @@ -278,6 +280,7 @@ GMenu2X::~GMenu2X() { quit(); delete menu; + delete helpPopup; delete btnContextMenu; delete font; delete monitor; @@ -398,6 +401,8 @@ void GMenu2X::initMenu() { //DEBUG //menu->addLink( CARD_ROOT, "sample.pxml", "applications" ); + + layers.push_back(menu); } void GMenu2X::about() { @@ -603,7 +608,9 @@ void GMenu2X::paint() { //Background sc["bgmain"]->blit(s,0,0); - menu->paint(*s); + for (Layer *layer : layers) { + layer->paint(*s); + } LinkApp *linkApp = menu->selLinkApp(); if (linkApp) { @@ -627,22 +634,6 @@ void GMenu2X::paint() { Font::HAlignCenter, Font::VAlignMiddle); } -void GMenu2X::paintHelp() { - //On Screen Help - int helpBoxHeight = 154; - s->box(10,50,300,helpBoxHeight+4, skinConfColors[COLOR_MESSAGE_BOX_BG]); - s->rectangle( 12,52,296,helpBoxHeight, - skinConfColors[COLOR_MESSAGE_BOX_BORDER] ); - s->write( font, tr["CONTROLS"], 20, 60 ); -#if defined(PLATFORM_A320) || defined(PLATFORM_GCW0) - s->write( font, tr["A: Launch link / Confirm action"], 20, 80 ); - s->write( font, tr["B: Show this help menu"], 20, 95 ); - s->write( font, tr["L, R: Change section"], 20, 110 ); - s->write( font, tr["SELECT: Show contextual menu"], 20, 155 ); - s->write( font, tr["START: Show options menu"], 20, 170 ); -#endif -} - void GMenu2X::main() { batteryIcon = "imgs/battery/0.png"; @@ -651,8 +642,6 @@ void GMenu2X::main() { if (!fileExists(CARD_ROOT)) CARD_ROOT = ""; - bool helpDisplayed = false; - bool quit = false; while (!quit) { //check battery status every 60 seconds @@ -670,27 +659,28 @@ void GMenu2X::main() { } paint(); - if (helpDisplayed) { - paintHelp(); - s->flip(); - while (input.waitForPressedButton() != InputManager::CANCEL) {} - helpDisplayed=false; - continue; - } s->flip(); //touchscreen if (ts.available()) { ts.poll(); btnContextMenu->handleTS(); - menu->handleTS(); + bool handled = false; + for (auto it = layers.rbegin(); !handled && it != layers.rend(); ++it) { + handled = (*it)->handleTouchscreen(ts); + } } InputManager::Button button = input.waitForPressedButton(); - if (!menu->handleButtonPress(button)) { + bool handled = false; + for (auto it = layers.rbegin(); !handled && it != layers.rend(); ++it) { + handled = (*it)->handleButtonPress(button); + } + if (!handled) { switch (button) { case InputManager::CANCEL: - helpDisplayed=true; + helpPopup = new HelpPopup(*this); + layers.push_back(helpPopup); break; case InputManager::SETTINGS: options(); @@ -702,6 +692,19 @@ void GMenu2X::main() { break; } } + + for (auto it = layers.begin(); it != layers.end(); ) { + Layer *layer = *it; + if (layer->wasDismissed()) { + it = layers.erase(it); + if (layer == helpPopup) { + delete helpPopup; + helpPopup = nullptr; + } + } else { + ++it; + } + } } } diff --git a/src/gmenu2x.h b/src/gmenu2x.h index bd3d8b4..4ca7e19 100644 --- a/src/gmenu2x.h +++ b/src/gmenu2x.h @@ -34,7 +34,9 @@ class Button; class Font; +class HelpPopup; class IconButton; +class Layer; class MediaMonitor; class Menu; class Surface; @@ -66,9 +68,12 @@ class GMenu2X { private: Touchscreen ts; Menu *menu; + HelpPopup *helpPopup; MediaMonitor *monitor; std::string batteryIcon; + std::vector layers; + /*! Retrieves the free disk space on the sd @return String containing a human readable representation of the free disk space @@ -123,7 +128,6 @@ private: void initMenu(); void paint(); - void paintHelp(); void showManual(); diff --git a/src/helppopup.cpp b/src/helppopup.cpp new file mode 100644 index 0000000..9bdb24b --- /dev/null +++ b/src/helppopup.cpp @@ -0,0 +1,46 @@ +// Various authors. +// License: GPL version 2 or later. + +#include "helppopup.h" + +#include "gmenu2x.h" + + +HelpPopup::HelpPopup(GMenu2X &gmenu2x) + : gmenu2x(gmenu2x) +{ +} + +void HelpPopup::paint(Surface &s) { + Font *font = gmenu2x.font; + Translator &tr = gmenu2x.tr; + int helpBoxHeight = 154; + + s.box(10, 50, 300, helpBoxHeight + 4, + gmenu2x.skinConfColors[COLOR_MESSAGE_BOX_BG]); + s.rectangle(12, 52, 296, helpBoxHeight, + gmenu2x.skinConfColors[COLOR_MESSAGE_BOX_BORDER]); + s.write(font, tr["CONTROLS"], 20, 60); +#if defined(PLATFORM_A320) || defined(PLATFORM_GCW0) + s.write(font, tr["A: Launch link / Confirm action"], 20, 80); + s.write(font, tr["B: Show this help menu"], 20, 95); + s.write(font, tr["L, R: Change section"], 20, 110); + s.write(font, tr["SELECT: Show contextual menu"], 20, 155); + s.write(font, tr["START: Show options menu"], 20, 170); +#endif +} + +bool HelpPopup::handleButtonPress(InputManager::Button button) { + if (button == InputManager::CANCEL) { + dismissed = true; + } + return true; +} + +bool HelpPopup::handleTouchscreen(Touchscreen &ts) { + if (ts.pressed()) { + dismissed = true; + ts.setHandled(); + } + return true; +} diff --git a/src/helppopup.h b/src/helppopup.h new file mode 100644 index 0000000..c2e64ae --- /dev/null +++ b/src/helppopup.h @@ -0,0 +1,28 @@ +// Various authors. +// License: GPL version 2 or later. + +#ifndef HELPPOPUP_H +#define HELPPOPUP_H + +#include "layer.h" + +class GMenu2X; + + +/** + * A passive dialog containing some helpful text for the user. + */ +class HelpPopup : public Layer { +public: + HelpPopup(GMenu2X &gmenu2x); + + // Layer implementation: + virtual void paint(Surface &s); + virtual bool handleButtonPress(InputManager::Button button); + virtual bool handleTouchscreen(Touchscreen &ts); + +private: + GMenu2X &gmenu2x; +}; + +#endif // HELPPOPUP_H diff --git a/src/layer.h b/src/layer.h new file mode 100644 index 0000000..bac92cc --- /dev/null +++ b/src/layer.h @@ -0,0 +1,48 @@ +// (c) 2013 Maarten ter Huurne +// License: GPL version 2 or later. + +#ifndef LAYER_H +#define LAYER_H + +#include "inputmanager.h" + +class Surface; +class Touchscreen; + + +/** + * Abstract base class for UI layers. + * A layer handles both painting and input events. + */ +class Layer { +public: + virtual ~Layer() {} + + /** + * Paints this layer on the given surface. + */ + virtual void paint(Surface &s) = 0; + + /** + * Handles the pressing of the give button. + * Returns true iff the button press event was fully handled by this layer. + */ + virtual bool handleButtonPress(InputManager::Button button) = 0; + + /** + * Handles the touch screen. + * Only called if there is a touch screen available. + * Returns true iff the touch screen was fully handled by this layer. + */ + virtual bool handleTouchscreen(Touchscreen &ts) = 0; + + bool wasDismissed() { return dismissed; } + +protected: + /** + * Set this to true to request the layer to be removed from the stack. + */ + bool dismissed = false; +}; + +#endif // LAYER_H diff --git a/src/menu.cpp b/src/menu.cpp index 134a62e..15effb5 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -235,7 +235,7 @@ bool Menu::handleButtonPress(InputManager::Button button) { } } -void Menu::handleTS() { +bool Menu::handleTouchscreen(Touchscreen &ts) { ConfIntHash &skinConfInt = gmenu2x->skinConfInt; const int topBarHeight = skinConfInt["topBarHeight"]; const int screenWidth = gmenu2x->resX; @@ -253,6 +253,7 @@ void Menu::handleTS() { setSectionIndex((iSection + numSections + i) % numSections); ts.setHandled(); + return true; } const uint linksPerPage = linkColumns * linkRows; @@ -266,6 +267,7 @@ void Menu::handleTS() { } i++; } + return ts.handled(); } /*==================================== diff --git a/src/menu.h b/src/menu.h index b6cedbc..f434c55 100644 --- a/src/menu.h +++ b/src/menu.h @@ -22,7 +22,7 @@ #define MENU_H #include "delegate.h" -#include "inputmanager.h" +#include "layer.h" #include "link.h" #include @@ -31,14 +31,14 @@ class LinkApp; class GMenu2X; class Monitor; -class Surface; + /** Handles the menu structure @author Massimiliano Torromeo */ -class Menu { +class Menu : public Layer { private: GMenu2X *gmenu2x; Touchscreen &ts; @@ -84,7 +84,7 @@ private: public: Menu(GMenu2X *gmenu2x, Touchscreen &ts); - ~Menu(); + virtual ~Menu(); #ifdef HAVE_LIBOPK void openPackage(std::string path, bool order = true); @@ -107,15 +107,12 @@ public: void deleteSelectedSection(); void skinUpdated(); - void paint(Surface &s); - /** - * Handles the pressing of the give button. - * Returns true iff the event was consumed. - */ - bool handleButtonPress(InputManager::Button button); + // Layer implementation: + virtual void paint(Surface &s); + virtual bool handleButtonPress(InputManager::Button button); + virtual bool handleTouchscreen(Touchscreen &ts); - void handleTS(); bool linkChangeSection(uint linkIndex, uint oldSectionIndex, uint newSectionIndex); int selLinkIndex();