diff --git a/src/menu.cpp b/src/menu.cpp index f6f7a78..7d8a3d5 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -45,8 +45,6 @@ Menu::Menu(GMenu2X *gmenu2x, Touchscreen &ts) : gmenu2x(gmenu2x) , ts(ts) { - iFirstDispSection = 0; - readSections(GMENU2X_SYSTEM_DIR "/sections"); readSections(GMenu2X::getHome() + "/sections"); @@ -131,6 +129,19 @@ void Menu::skinUpdated() { } } +void Menu::calcSectionRange(int &leftSection, int &rightSection) { + ConfIntHash &skinConfInt = gmenu2x->skinConfInt; + const int linkWidth = skinConfInt["linkWidth"]; + const int screenWidth = gmenu2x->resX; + const int numSections = sections.size(); + rightSection = min( + max(1, (screenWidth - 20 - linkWidth) / (2 * linkWidth)), + numSections / 2); + leftSection = max( + -rightSection, + rightSection - numSections + 1); +} + void Menu::paint(Surface &s) { const uint width = s.width(), height = s.height(); Font &font = *gmenu2x->font; @@ -143,34 +154,25 @@ void Menu::paint(Surface &s) { const int linkHeight = skinConfInt["linkHeight"]; RGBAColor &selectionBgColor = gmenu2x->skinConfColors[COLOR_SELECTION_BG]; - //Sections + // Paint section headers. + int leftSection, rightSection; + calcSectionRange(leftSection, rightSection); + s.box(width / 2 - linkWidth / 2, 0, linkWidth, topBarHeight, selectionBgColor); const uint sectionLinkPadding = (topBarHeight - 32 - font.getHeight()) / 3; - const uint sectionsCoordX = - (width - constrain((uint)sections.size(), 0 , linkColumns) * linkWidth) / 2; - if (iFirstDispSection > 0) { - sc.skinRes("imgs/l_enabled.png")->blit(&s, 0, 0); - } else { - sc.skinRes("imgs/l_disabled.png")->blit(&s, 0, 0); - } - if (iFirstDispSection + linkColumns < sections.size()) { - sc.skinRes("imgs/r_enabled.png")->blit(&s, width - 10, 0); - } else { - sc.skinRes("imgs/r_disabled.png")->blit(&s, width - 10, 0); - } - for (uint i = iFirstDispSection; i < sections.size() && i < iFirstDispSection + linkColumns; i++) { - string sectionIcon = "skin:sections/" + sections[i] + ".png"; - int x = (i - iFirstDispSection) * linkWidth + sectionsCoordX; - if (i == (uint)iSection) { - s.box(x, 0, linkWidth, topBarHeight, selectionBgColor); - } - x += linkWidth / 2; - if (sc.exists(sectionIcon)) { - sc[sectionIcon]->blit(&s, x - 16, sectionLinkPadding, 32, 32); - } else { - sc.skinRes("icons/section.png")->blit(&s, x - 16, sectionLinkPadding); - } - s.write(&font, sections[i], x, topBarHeight - sectionLinkPadding, Font::HAlignCenter, Font::VAlignBottom); + const uint numSections = sections.size(); + for (int i = leftSection; i <= rightSection; i++) { + uint j = (iSection + numSections + i) % numSections; + string sectionIcon = "skin:sections/" + sections[j] + ".png"; + Surface *icon = sc.exists(sectionIcon) + ? sc[sectionIcon] + : sc.skinRes("icons/section.png"); + const int x = width / 2 + i * linkWidth; + icon->blit(&s, x - 16, sectionLinkPadding, 32, 32); + s.write(&font, sections[j], x, topBarHeight - sectionLinkPadding, + Font::HAlignCenter, Font::VAlignBottom); } + sc.skinRes("imgs/l_enabled.png")->blit(&s, 0, 0); + sc.skinRes("imgs/r_enabled.png")->blit(&s, width - 10, 0); vector §ionLinks = links[iSection]; const uint numLinks = sectionLinks.size(); @@ -208,24 +210,21 @@ void Menu::paint(Surface &s) { void Menu::handleTS() { ConfIntHash &skinConfInt = gmenu2x->skinConfInt; const int topBarHeight = skinConfInt["topBarHeight"]; - const int linkWidth = skinConfInt["linkWidth"]; const int screenWidth = gmenu2x->resX; - SDL_Rect re = { - 0, 0, - static_cast(screenWidth), static_cast(topBarHeight) - }; - if (ts.pressed() && ts.inRect(re)) { - re.w = linkWidth; - uint sectionsCoordX = (screenWidth - constrain((uint)sections.size(), 0, linkColumns) * linkWidth) / 2; - for (uint i = iFirstDispSection; !ts.handled() && i < sections.size() && i < iFirstDispSection + linkColumns; i++) { - re.x = (i - iFirstDispSection) * re.w + sectionsCoordX; + if (ts.pressed() && ts.getY() < topBarHeight) { + int leftSection, rightSection; + calcSectionRange(leftSection, rightSection); - if (ts.inRect(re)) { - setSectionIndex(i); - ts.setHandled(); - } - } + const int linkWidth = skinConfInt["linkWidth"]; + const int leftSectionX = screenWidth / 2 + leftSection * linkWidth; + const int i = min( + leftSection + max((ts.getX() - leftSectionX) / linkWidth, 0), + rightSection); + const uint numSections = sections.size(); + setSectionIndex((iSection + numSections + i) % numSections); + + ts.setHandled(); } const uint linksPerPage = linkColumns * linkRows; @@ -283,11 +282,6 @@ void Menu::setSectionIndex(int i) { i=0; iSection = i; - if (i>(int)iFirstDispSection+2) - iFirstDispSection = i-2; - else if (i<(int)iFirstDispSection) - iFirstDispSection = i; - iLink = 0; iFirstDispRow = 0; } diff --git a/src/menu.h b/src/menu.h index 102357d..bb0cd1a 100644 --- a/src/menu.h +++ b/src/menu.h @@ -42,12 +42,18 @@ private: GMenu2X *gmenu2x; Touchscreen &ts; int iSection, iLink; - uint iFirstDispSection, iFirstDispRow; + uint iFirstDispRow; std::vector sections; std::vector< std::vector > links; uint linkColumns, linkRows; + /** + * Determine which section headers are visible. + * The output values are relative to the middle section at 0. + */ + void calcSectionRange(int &leftSection, int &rightSection); + std::vector *sectionLinks(int i = -1); void readLinks();