1
0
mirror of git://projects.qi-hardware.com/gmenu2x.git synced 2024-10-04 02:23:15 +03:00
gmenu2x/src/contextmenu.cpp
Maarten ter Huurne de30b3f98f Define LinkApp::isOpk() also when OPK support is disabled
This reduces the number of required preprocessor directives, leading to
more readable code and more code being examined by the compiler (useful
to spot problems). Since the method is inlined, the compiler should be
able to eliminate the same amount of code that the preprocessor would,
only at a later stage of the compilation.
2013-08-12 00:13:18 +02:00

183 lines
4.6 KiB
C++

// Various authors.
// License: GPL version 2 or later.
#include "contextmenu.h"
#include "delegate.h"
#include "gmenu2x.h"
#include "linkapp.h"
#include "menu.h"
#include "utilities.h"
#include <algorithm>
struct ContextMenu::MenuOption {
MenuOption(std::string text, function_t action)
: text(text), action(action) {}
std::string text;
function_t action;
};
ContextMenu::ContextMenu(GMenu2X &gmenu2x, Menu &menu)
: gmenu2x(gmenu2x)
, menu(menu)
, fadeAlpha(0)
, selected(0)
{
Translator &tr = gmenu2x.tr;
Font *font = gmenu2x.font;
LinkApp* app = menu.selLinkApp();
// Init menu options:
options.push_back(std::make_shared<MenuOption>(
tr.translate("Add link in $1", menu.selSection().c_str(), NULL),
std::bind(&GMenu2X::addLink, &gmenu2x)));
if (app && !app->getManual().empty()) {
options.push_back(std::make_shared<MenuOption>(
tr.translate("Show manual of $1", app->getTitle().c_str(), NULL),
std::bind(&GMenu2X::showManual, &gmenu2x)));
}
if (app && app->isEditable()) {
/* FIXME(percuei): This permits to mask the "Edit link" entry
* on the contextual menu in case CPUFREQ support is
* not compiled in and the link corresponds to an OPK.
* This is not a good idea as it'll break things if
* a new config option is added to the contextual menu.
*/
if (!app->isOpk()
#if defined(ENABLE_CPUFREQ)
|| true
#endif
|| !app->getSelectorDir().empty()
) {
options.push_back(std::make_shared<MenuOption>(
tr.translate("Edit $1", app->getTitle().c_str(), NULL),
std::bind(&GMenu2X::editLink, &gmenu2x)));
}
if (!app->isOpk()) {
options.push_back(std::make_shared<MenuOption>(
tr.translate("Delete $1 link", app->getTitle().c_str(), NULL),
std::bind(&GMenu2X::deleteLink, &gmenu2x)));
}
}
options.push_back(std::make_shared<MenuOption>(
tr["Add section"],
std::bind(&GMenu2X::addSection, &gmenu2x)));
options.push_back(std::make_shared<MenuOption>(
tr["Rename section"],
std::bind(&GMenu2X::renameSection, &gmenu2x)));
options.push_back(std::make_shared<MenuOption>(
tr["Delete section"],
std::bind(&GMenu2X::deleteSection, &gmenu2x)));
options.push_back(std::make_shared<MenuOption>(
tr["Scan for applications and games"],
std::bind(&GMenu2X::scanner, &gmenu2x)));
// Compute bounding box.
int w = 0;
for (auto option : options) {
w = std::max(w, font->getTextWidth(option->text));
}
w += 23;
const int h = (font->getHeight() + 2) * options.size() + 8;
box = {
static_cast<Sint16>((gmenu2x.resX - w) / 2),
static_cast<Sint16>((gmenu2x.resY - h) / 2),
static_cast<Uint16>(w),
static_cast<Uint16>(h)
};
// Init background fade animation.
tickStart = SDL_GetTicks();
startAnimating();
}
void ContextMenu::runAnimations()
{
if (fadeAlpha < 200) {
const long tickNow = SDL_GetTicks();
fadeAlpha = intTransition(0, 200, tickStart, 500, tickNow);
if (fadeAlpha == 200) {
stopAnimating();
}
}
}
void ContextMenu::paint(Surface &s)
{
runAnimations();
Font *font = gmenu2x.font;
// Darken background.
s.box(0, 0, gmenu2x.resX, gmenu2x.resY, 0, 0, 0, fadeAlpha);
// Draw popup box.
s.box(box, gmenu2x.skinConfColors[COLOR_MESSAGE_BOX_BG]);
s.rectangle(box.x + 2, box.y + 2, box.w - 4, box.h - 4,
gmenu2x.skinConfColors[COLOR_MESSAGE_BOX_BORDER]);
// Draw selection background.
const int h = font->getHeight();
SDL_Rect selbox = {
static_cast<Sint16>(box.x + 4),
static_cast<Sint16>(box.y + 4 + (h + 2) * selected),
static_cast<Uint16>(box.w - 8),
static_cast<Uint16>(h + 2)
};
s.box(selbox, gmenu2x.skinConfColors[COLOR_MESSAGE_BOX_SELECTION]);
// List options.
for (uint i = 0; i < options.size(); i++) {
s.write(font, options[i]->text, box.x + 12, box.y + 5 + (h + 2) * i,
Font::HAlignLeft, Font::VAlignTop);
}
}
bool ContextMenu::handleButtonPress(InputManager::Button button) {
switch (button) {
case InputManager::MENU:
dismiss();
break;
case InputManager::UP:
selected--;
if (selected < 0) selected = options.size() - 1;
break;
case InputManager::DOWN:
selected++;
if (selected >= static_cast<int>(options.size())) selected = 0;
break;
case InputManager::ACCEPT:
options[selected]->action();
dismiss();
break;
default:
break;
}
return true;
}
bool ContextMenu::handleTouchscreen(Touchscreen &ts) {
if (ts.inRect(box)) {
int i = std::max(0, std::min(static_cast<int>(options.size()) - 1,
(ts.getY() - (box.y + 4)) / (gmenu2x.font->getHeight() + 2)));
if (ts.released()) {
options[i]->action();
dismiss();
} else if (ts.pressed()) {
selected = i;
}
} else {
if (ts.released()) {
dismiss();
}
}
return true;
}