diff options
Diffstat (limited to 'gui/listbox.cpp')
-rw-r--r-- | gui/listbox.cpp | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/gui/listbox.cpp b/gui/listbox.cpp new file mode 100644 index 000000000..888947b29 --- /dev/null +++ b/gui/listbox.cpp @@ -0,0 +1,381 @@ +// ListBox.cpp - GUIListBox object + +#include <linux/input.h> +#include <pthread.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/reboot.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <time.h> +#include <unistd.h> +#include <stdlib.h> +#include <dirent.h> +#include <ctype.h> + +#include <algorithm> + +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<listSize; i++) + mList.at(i).selected = 0; + + str = mList.at(startSelection).variableValue; + mList.at(startSelection).selected = 1; + DataManager::SetValue(mVariable, str); + mUpdate = 1; + } + } + } + case TOUCH_HOLD: + case TOUCH_REPEAT: + break; + } + return 0; +} + +int GUIListBox::NotifyVarChange(std::string varName, std::string value) +{ + string checkValue; + int var_changed = 0; + + if (varName.empty()) + { + DataManager::GetValue(mVariable, checkValue); + if (checkValue != currentValue) { + varName = mVariable; + value = checkValue; + currentValue = checkValue; + var_changed = 1; + } + } + if (varName == mVariable || var_changed != 0) + { + int i, listSize = mList.size(), selected_index = 0; + + currentValue = value; + + for (i=0; i<listSize; i++) { + if (mList.at(i).variableValue == currentValue) { + mList.at(i).selected = 1; + selected_index = i; + } else + mList.at(i).selected = 0; + } + + int lines = mRenderH / (mLineHeight + mLineSpacing); + int line; + + if (selected_index > 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; + } +} + |