summaryrefslogtreecommitdiffstats
path: root/gui/listbox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gui/listbox.cpp')
-rw-r--r--gui/listbox.cpp381
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;
+ }
+}
+