// ListBox.cpp - GUIListBox object #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" { #include "../common.h" #include "../roots.h" #include "../minuitwrp/minui.h" #include "../recovery_ui.h" } #include "rapidxml.hpp" #include "objects.hpp" #include "../data.hpp" GUIListBox::GUIListBox(xml_node<>* node) { xml_attribute<>* attr; xml_node<>* child; mStart = mLineSpacing = mIconWidth = mIconHeight = 0; mIconSelected = mIconUnselected = mBackground = mFont = NULL; mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = 0; mUpdate = 0; ConvertStrToColor("black", &mBackgroundColor); ConvertStrToColor("white", &mFontColor); child = node->first_node("icon"); if (child) { attr = child->first_attribute("selected"); if (attr) mIconSelected = PageManager::FindResource(attr->value()); attr = child->first_attribute("unselected"); if (attr) mIconUnselected = PageManager::FindResource(attr->value()); } child = node->first_node("background"); if (child) { attr = child->first_attribute("resource"); if (attr) mBackground = PageManager::FindResource(attr->value()); attr = child->first_attribute("color"); if (attr) { std::string color = attr->value(); ConvertStrToColor(color, &mBackgroundColor); } } // Load the placement LoadPlacement(node->first_node("placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH); SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH); // Load the font, and possibly override the color child = node->first_node("font"); if (child) { attr = child->first_attribute("resource"); if (attr) mFont = PageManager::FindResource(attr->value()); attr = child->first_attribute("color"); if (attr) { std::string color = attr->value(); ConvertStrToColor(color, &mFontColor); } attr = child->first_attribute("spacing"); if (attr) { string parsevalue = gui_parse_text(attr->value()); mLineSpacing = atoi(parsevalue.c_str()); } } // Handle the result variable child = node->first_node("data"); if (child) { attr = child->first_attribute("name"); if (attr) mVariable = attr->value(); attr = child->first_attribute("default"); if (attr) DataManager::SetValue(mVariable, attr->value()); } // Retrieve the line height gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL); mLineHeight = mFontHeight; if (mIconSelected && mIconSelected->GetResource()) { if (gr_get_height(mIconSelected->GetResource()) > mLineHeight) mLineHeight = gr_get_height(mIconSelected->GetResource()); mIconWidth = gr_get_width(mIconSelected->GetResource()); mIconHeight = gr_get_height(mIconSelected->GetResource()); } if (mIconUnselected && mIconUnselected->GetResource()) { if (gr_get_height(mIconUnselected->GetResource()) > mLineHeight) mLineHeight = gr_get_height(mIconUnselected->GetResource()); mIconWidth = gr_get_width(mIconUnselected->GetResource()); mIconHeight = gr_get_height(mIconUnselected->GetResource()); } if (mBackground && mBackground->GetResource()) { mBackgroundW = gr_get_width(mBackground->GetResource()); mBackgroundH = gr_get_height(mBackground->GetResource()); } // Get the currently selected value for the list DataManager::GetValue(mVariable, currentValue); // Get the data for the list child = node->first_node("listitem"); if (!child) return; while (child) { ListData data; attr = child->first_attribute("name"); if (!attr) return; data.displayName = attr->value(); data.variableValue = child->value(); if (child->value() == currentValue) data.selected = 1; else data.selected = 0; mList.push_back(data); child = child->next_sibling("listitem"); } // Call this to get the selected item to be shown in the list on first render NotifyVarChange(mVariable, currentValue); } GUIListBox::~GUIListBox() { } int GUIListBox::Render(void) { // First step, fill background gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255); gr_fill(mRenderX, mRenderY, mRenderW, mRenderH); // Next, render the background resource (if it exists) if (mBackground && mBackground->GetResource()) { mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2); mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2); gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY); } // Now, we need the lines (icon + text) gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha); // This tells us how many lines we can actually render int lines = mRenderH / (mLineHeight + mLineSpacing); int line; int listSize = mList.size(); if (listSize < lines) lines = listSize; void* fontResource = NULL; if (mFont) fontResource = mFont->GetResource(); int yPos = mRenderY + (mLineSpacing / 2); for (line = 0; line < lines; line++) { Resource* icon; std::string label; label = mList.at(line + mStart).displayName; if (mList.at(line + mStart).selected != 0) { icon = mIconSelected; } else { icon = mIconUnselected; } if (icon && icon->GetResource()) { gr_blit(icon->GetResource(), 0, 0, mIconWidth, mIconHeight, mRenderX, (yPos + (int)((mLineHeight - mIconHeight) / 2))); } gr_textExW(mRenderX + mIconWidth + 5, yPos, label.c_str(), fontResource, mRenderX + mRenderW - mIconWidth - 5); // Move the yPos yPos += mLineHeight + mLineSpacing; } mUpdate = 0; return 0; } int GUIListBox::Update(void) { if (mUpdate) { mUpdate = 0; if (Render() == 0) return 2; } return 0; } int GUIListBox::GetSelection(int x, int y) { // We only care about y position return (y - mRenderY) / (mLineHeight + mLineSpacing); } int GUIListBox::NotifyTouch(TOUCH_STATE state, int x, int y) { static int startSelection = -1; static int startY = 0; int selection = 0; switch (state) { case TOUCH_START: startSelection = GetSelection(x,y); startY = y; break; case TOUCH_DRAG: // Check if we dragged out of the selection window selection = GetSelection(x,y); if (startSelection != selection) { startSelection = -1; // Handle scrolling if (y > (int) (startY + (mLineHeight + mLineSpacing))) { if (mStart) mStart--; mUpdate = 1; startY = y; } else if (y < (int) (startY - (mLineHeight + mLineSpacing))) { int listSize = mList.size(); int lines = mRenderH / (mLineHeight + mLineSpacing); if (mStart + lines < listSize) mStart++; mUpdate = 1; startY = y; } } break; case TOUCH_RELEASE: if (startSelection >= 0) { // We've selected an item! std::string str; int listSize = mList.size(); // Move the selection to the proper place in the array startSelection += mStart; if (startSelection < listSize) { if (!mVariable.empty()) { int i; for (i=0; i mStart + lines - 1) mStart = selected_index; if (mStart > listSize - lines) { mStart = listSize - lines; } else if (selected_index < mStart) { mStart = selected_index; } mUpdate = 1; return 0; } return 0; } int GUIListBox::SetRenderPos(int x, int y, int w /* = 0 */, int h /* = 0 */) { mRenderX = x; mRenderY = y; if (w || h) { mRenderW = w; mRenderH = h; } SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH); mUpdate = 1; return 0; } void GUIListBox::SetPageFocus(int inFocus) { if (inFocus) { mUpdate = 1; } }