summaryrefslogtreecommitdiffstats
path: root/gui/listbox.cpp
diff options
context:
space:
mode:
authorDees Troy <dees_troy@teamw.in>2013-02-19 15:41:23 +0100
committerGerrit Code Review <gerrit@5.9.244.119>2013-02-19 15:41:23 +0100
commit72394403b98a3990f87e8dbb8cc8e585a3298e09 (patch)
tree7b69ecf13f3d4378f53f0c92b47fb9a7521660f1 /gui/listbox.cpp
parentMerge "Add highlight to file selector" into twrp2.4 (diff)
parentUpdate listbox code (diff)
downloadandroid_bootable_recovery-72394403b98a3990f87e8dbb8cc8e585a3298e09.tar
android_bootable_recovery-72394403b98a3990f87e8dbb8cc8e585a3298e09.tar.gz
android_bootable_recovery-72394403b98a3990f87e8dbb8cc8e585a3298e09.tar.bz2
android_bootable_recovery-72394403b98a3990f87e8dbb8cc8e585a3298e09.tar.lz
android_bootable_recovery-72394403b98a3990f87e8dbb8cc8e585a3298e09.tar.xz
android_bootable_recovery-72394403b98a3990f87e8dbb8cc8e585a3298e09.tar.zst
android_bootable_recovery-72394403b98a3990f87e8dbb8cc8e585a3298e09.zip
Diffstat (limited to 'gui/listbox.cpp')
-rw-r--r--gui/listbox.cpp797
1 files changed, 562 insertions, 235 deletions
diff --git a/gui/listbox.cpp b/gui/listbox.cpp
index 888947b29..5dd2a2db6 100644
--- a/gui/listbox.cpp
+++ b/gui/listbox.cpp
@@ -1,4 +1,4 @@
-// ListBox.cpp - GUIListBox object
+// FileSelector.cpp - GUIFileSelector object
#include <linux/input.h>
#include <pthread.h>
@@ -31,105 +31,238 @@ extern "C" {
#include "rapidxml.hpp"
#include "objects.hpp"
#include "../data.hpp"
+#include "../twrp-functions.hpp"
+
+#define SCROLLING_SPEED_DECREMENT 6
+#define SCROLLING_FLOOR 10
+#define SCROLLING_MULTIPLIER 6
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);
+ xml_attribute<>* attr;
+ xml_node<>* child;
+ int header_separator_color_specified = 0, header_separator_height_specified = 0, header_text_color_specified = 0, header_background_color_specified = 0;
+
+ mStart = mLineSpacing = startY = mFontHeight = mSeparatorH = scrollingY = scrollingSpeed = 0;
+ mIconWidth = mIconHeight = mSelectedIconHeight = mSelectedIconHeight = mUnselectedIconWidth = mUnselectedIconWidth = mHeaderIconHeight = mHeaderIconWidth = 0;
+ mHeaderSeparatorH = mLineHeight = mHeaderIsStatic = mHeaderH = actualLineHeight = 0;
+ mIconSelected = mIconUnselected = mBackground = mFont = mHeaderIcon = NULL;
+ mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = 0;
+ mUpdate = 0;
+ touchDebounce = 6;
+ ConvertStrToColor("black", &mBackgroundColor);
+ ConvertStrToColor("black", &mHeaderBackgroundColor);
+ ConvertStrToColor("black", &mSeparatorColor);
+ ConvertStrToColor("black", &mHeaderSeparatorColor);
+ ConvertStrToColor("white", &mFontColor);
+ ConvertStrToColor("white", &mHeaderFontColor);
+ hasHighlightColor = false;
+ hasFontHighlightColor = false;
+ isHighlighted = false;
+ startSelection = -1;
+
+ // Load header text
+ child = node->first_node("header");
+ if (child)
+ {
+ attr = child->first_attribute("icon");
+ if (attr)
+ mHeaderIcon = PageManager::FindResource(attr->value());
+
+ attr = child->first_attribute("background");
+ if (attr)
+ {
+ std::string color = attr->value();
+ ConvertStrToColor(color, &mHeaderBackgroundColor);
+ header_background_color_specified = -1;
+ }
+ attr = child->first_attribute("textcolor");
+ if (attr)
+ {
+ std::string color = attr->value();
+ ConvertStrToColor(color, &mHeaderFontColor);
+ header_text_color_specified = -1;
+ }
+ attr = child->first_attribute("separatorcolor");
+ if (attr)
+ {
+ std::string color = attr->value();
+ ConvertStrToColor(color, &mHeaderSeparatorColor);
+ header_separator_color_specified = -1;
+ }
+ attr = child->first_attribute("separatorheight");
+ if (attr) {
+ string parsevalue = gui_parse_text(attr->value());
+ mHeaderSeparatorH = atoi(parsevalue.c_str());
+ header_separator_height_specified = -1;
+ }
+ }
+ child = node->first_node("text");
+ if (child) mHeaderText = child->value();
+
+ memset(&mHighlightColor, 0, sizeof(COLOR));
+ child = node->first_node("highlight");
+ if (child) {
+ attr = child->first_attribute("color");
+ if (attr) {
+ hasHighlightColor = true;
+ std::string color = attr->value();
+ ConvertStrToColor(color, &mHighlightColor);
+ }
+ }
+
+ // Simple way to check for static state
+ mLastValue = gui_parse_text(mHeaderText);
+ if (mLastValue != mHeaderText)
+ mHeaderIsStatic = 0;
+ else
+ mHeaderIsStatic = -1;
+
+ 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);
+ if (!header_background_color_specified)
+ ConvertStrToColor(color, &mHeaderBackgroundColor);
+ }
+ }
+
+ // 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);
+ if (!header_text_color_specified)
+ ConvertStrToColor(color, &mHeaderFontColor);
+ }
- // 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("spacing");
+ if (attr) {
+ string parsevalue = gui_parse_text(attr->value());
+ mLineSpacing = atoi(parsevalue.c_str());
+ }
- attr = child->first_attribute("color");
+ attr = child->first_attribute("highlightcolor");
+ memset(&mFontHighlightColor, 0, sizeof(COLOR));
if (attr)
{
std::string color = attr->value();
- ConvertStrToColor(color, &mFontColor);
+ ConvertStrToColor(color, &mFontHighlightColor);
+ hasFontHighlightColor = true;
}
+ }
+
+ // Load the separator if it exists
+ child = node->first_node("separator");
+ if (child)
+ {
+ attr = child->first_attribute("color");
+ if (attr)
+ {
+ std::string color = attr->value();
+ ConvertStrToColor(color, &mSeparatorColor);
+ if (!header_separator_color_specified)
+ ConvertStrToColor(color, &mHeaderSeparatorColor);
+ }
- attr = child->first_attribute("spacing");
- if (attr) {
+ attr = child->first_attribute("height");
+ if (attr) {
string parsevalue = gui_parse_text(attr->value());
- mLineSpacing = atoi(parsevalue.c_str());
+ mSeparatorH = atoi(parsevalue.c_str());
+ if (!header_separator_height_specified)
+ mHeaderSeparatorH = mSeparatorH;
}
- }
+ }
- // 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());
- }
+ // 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;
+ mHeaderH = mFontHeight;
+
+ if (mIconSelected && mIconSelected->GetResource())
+ {
+ mSelectedIconWidth = gr_get_width(mIconSelected->GetResource());
+ mSelectedIconHeight = gr_get_height(mIconSelected->GetResource());
+ if (mSelectedIconHeight > (int)mLineHeight)
+ mLineHeight = mSelectedIconHeight;
+ mIconWidth = mSelectedIconWidth;
+ }
+
+ if (mIconUnselected && mIconUnselected->GetResource())
+ {
+ mUnselectedIconWidth = gr_get_width(mIconUnselected->GetResource());
+ mUnselectedIconHeight = gr_get_height(mIconUnselected->GetResource());
+ if (mUnselectedIconHeight > (int)mLineHeight)
+ mLineHeight = mUnselectedIconHeight;
+ if (mUnselectedIconWidth > mIconWidth)
+ mIconWidth = mUnselectedIconWidth;
+ }
+
+ if (mHeaderIcon && mHeaderIcon->GetResource())
+ {
+ mHeaderIconWidth = gr_get_width(mHeaderIcon->GetResource());
+ mHeaderIconHeight = gr_get_height(mHeaderIcon->GetResource());
+ if (mHeaderIconHeight > mHeaderH)
+ mHeaderH = mHeaderIconHeight;
+ if (mHeaderIconWidth > mIconWidth)
+ mIconWidth = mHeaderIconWidth;
+ }
+
+ mHeaderH += mLineSpacing + mHeaderSeparatorH;
+ actualLineHeight = mLineHeight + mLineSpacing + mSeparatorH;
+ if (mHeaderH < actualLineHeight)
+ mHeaderH = actualLineHeight;
+
+ if (actualLineHeight / 3 > 6)
+ touchDebounce = actualLineHeight / 3;
+
+ if (mBackground && mBackground->GetResource())
+ {
+ mBackgroundW = gr_get_width(mBackground->GetResource());
+ mBackgroundH = gr_get_height(mBackground->GetResource());
+ }
- // 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);
@@ -146,18 +279,16 @@ GUIListBox::GUIListBox(xml_node<>* node)
data.displayName = attr->value();
data.variableValue = child->value();
- if (child->value() == currentValue)
+ if (child->value() == currentValue) {
data.selected = 1;
- else
+ } 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()
@@ -165,168 +296,363 @@ 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;
+ gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
+ gr_fill(mRenderX, mRenderY + mHeaderH, mRenderW, mRenderH - mHeaderH);
+
+ // 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);
+ }
+
+ // This tells us how many lines we can actually render
+ int lines = (mRenderH - mHeaderH) / (actualLineHeight);
+ int line;
+
+ int listSize = mList.size();
+
+ if (listSize < lines) {
+ lines = listSize;
+ scrollingY = 0;
+ } else {
+ lines++;
+ if (lines < listSize)
+ lines++;
+ }
+
+ void* fontResource = NULL;
+ if (mFont) fontResource = mFont->GetResource();
+
+ int yPos = mRenderY + mHeaderH + scrollingY;
+ int fontOffsetY = (int)((actualLineHeight - mFontHeight) / 2);
+ int currentIconHeight = 0, currentIconWidth = 0;
+ int currentIconOffsetY = 0, currentIconOffsetX = 0;
+ int UnselectedIconOffsetY = (int)((actualLineHeight - mUnselectedIconHeight) / 2), SelectedIconOffsetY = (int)((actualLineHeight - mSelectedIconHeight) / 2);
+ int UnselectedIconOffsetX = (mIconWidth - mUnselectedIconWidth) / 2, SelectedIconOffsetX = (mIconWidth - mSelectedIconWidth) / 2;
+ int actualSelection = mStart;
+
+ if (isHighlighted) {
+ int selectY = scrollingY;
+
+ // Locate the correct line for highlighting
+ while (selectY + actualLineHeight < startSelection) {
+ selectY += actualLineHeight;
+ actualSelection++;
+ }
+ if (hasHighlightColor) {
+ // Highlight the area
+ gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, 255);
+ int HighlightHeight = actualLineHeight;
+ if (mRenderY + mHeaderH + selectY + actualLineHeight > mRenderH + mRenderY) {
+ HighlightHeight = actualLineHeight - (mRenderY + mHeaderH + selectY + actualLineHeight - mRenderH - mRenderY);
+ }
+ gr_fill(mRenderX, mRenderY + mHeaderH + selectY, mRenderW, HighlightHeight);
+ }
+ }
+
+ for (line = 0; line < lines; line++)
+ {
+ Resource* icon;
+ std::string label;
+
+ if (line + mStart >= listSize)
+ continue;
+
+ label = mList.at(line + mStart).displayName;
+ if (isHighlighted && hasFontHighlightColor && line + mStart == actualSelection) {
+ // Use the highlight color for the font
+ gr_color(mFontHighlightColor.red, mFontHighlightColor.green, mFontHighlightColor.blue, 255);
+ } else {
+ // Set the color for the font
+ gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, 255);
+ }
- label = mList.at(line + mStart).displayName;
if (mList.at(line + mStart).selected != 0)
{
icon = mIconSelected;
+ currentIconHeight = mSelectedIconHeight;
+ currentIconWidth = mSelectedIconWidth;
+ currentIconOffsetY = SelectedIconOffsetY;
+ currentIconOffsetX = SelectedIconOffsetX;
}
else
{
icon = mIconUnselected;
+ currentIconHeight = mSelectedIconHeight;
+ currentIconWidth = mSelectedIconWidth;
+ currentIconOffsetY = SelectedIconOffsetY;
+ currentIconOffsetX = SelectedIconOffsetX;
}
- 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);
+ if (icon && icon->GetResource())
+ {
+ int rect_y = 0, image_y = (yPos + currentIconOffsetY);
+ if (image_y + currentIconHeight > mRenderY + mRenderH)
+ rect_y = mRenderY + mRenderH - image_y;
+ else
+ rect_y = currentIconHeight;
+ gr_blit(icon->GetResource(), 0, 0, currentIconWidth, rect_y, mRenderX + currentIconOffsetX, image_y);
+ }
+ gr_textExWH(mRenderX + mIconWidth + 5, yPos + fontOffsetY, label.c_str(), fontResource, mRenderX + mRenderW, mRenderY + mRenderH);
- // Move the yPos
- yPos += mLineHeight + mLineSpacing;
- }
+ // Add the separator
+ if (yPos + actualLineHeight < mRenderH + mRenderY) {
+ gr_color(mSeparatorColor.red, mSeparatorColor.green, mSeparatorColor.blue, 255);
+ gr_fill(mRenderX, yPos + actualLineHeight - mSeparatorH, mRenderW, mSeparatorH);
+ }
- mUpdate = 0;
- return 0;
+ // Move the yPos
+ yPos += actualLineHeight;
+ }
+
+ // Render the Header (last so that it overwrites the top most row for per pixel scrolling)
+ // First step, fill background
+ gr_color(mHeaderBackgroundColor.red, mHeaderBackgroundColor.green, mHeaderBackgroundColor.blue, 255);
+ gr_fill(mRenderX, mRenderY, mRenderW, mHeaderH);
+
+ // Now, we need the header (icon + text)
+ yPos = mRenderY;
+ {
+ Resource* headerIcon;
+ int mIconOffsetX = 0;
+
+ // render the icon if it exists
+ headerIcon = mHeaderIcon;
+ if (headerIcon && headerIcon->GetResource())
+ {
+ gr_blit(headerIcon->GetResource(), 0, 0, mHeaderIconWidth, mHeaderIconHeight, mRenderX + ((mHeaderIconWidth - mIconWidth) / 2), (yPos + (int)((mHeaderH - mHeaderIconHeight) / 2)));
+ mIconOffsetX = mIconWidth;
+ }
+
+ // render the text
+ gr_color(mHeaderFontColor.red, mHeaderFontColor.green, mHeaderFontColor.blue, 255);
+ gr_textExWH(mRenderX + mIconOffsetX + 5, yPos + (int)((mHeaderH - mFontHeight) / 2), mLastValue.c_str(), fontResource, mRenderX + mRenderW, mRenderY + mRenderH);
+
+ // Add the separator
+ gr_color(mHeaderSeparatorColor.red, mHeaderSeparatorColor.green, mHeaderSeparatorColor.blue, 255);
+ gr_fill(mRenderX, yPos + mHeaderH - mHeaderSeparatorH, mRenderW, mHeaderSeparatorH);
+ }
+
+ mUpdate = 0;
+ return 0;
}
int GUIListBox::Update(void)
{
- if (mUpdate)
- {
- mUpdate = 0;
- if (Render() == 0)
+ if (!mHeaderIsStatic) {
+ std::string newValue = gui_parse_text(mHeaderText);
+ if (mLastValue != newValue) {
+ mLastValue = newValue;
+ mUpdate = 1;
+ }
+ }
+
+ if (mUpdate)
+ {
+ mUpdate = 0;
+ if (Render() == 0)
return 2;
- }
- return 0;
+ }
+
+ // Handle kinetic scrolling
+ if (scrollingSpeed == 0) {
+ // Do nothing
+ } else if (scrollingSpeed > 0) {
+ if (scrollingSpeed < ((int) (actualLineHeight * 2.5))) {
+ scrollingY += scrollingSpeed;
+ scrollingSpeed -= SCROLLING_SPEED_DECREMENT;
+ } else {
+ scrollingY += ((int) (actualLineHeight * 2.5));
+ scrollingSpeed -= SCROLLING_SPEED_DECREMENT;
+ }
+ while (mStart && scrollingY > 0) {
+ mStart--;
+ scrollingY -= actualLineHeight;
+ }
+ if (mStart == 0 && scrollingY > 0) {
+ scrollingY = 0;
+ scrollingSpeed = 0;
+ } else if (scrollingSpeed < SCROLLING_FLOOR)
+ scrollingSpeed = 0;
+ mUpdate = 1;
+ } else if (scrollingSpeed < 0) {
+ int totalSize = mList.size();
+ int lines = (mRenderH - mHeaderH) / (actualLineHeight);
+
+ if (totalSize > lines) {
+ int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight);
+
+ bottom_offset -= actualLineHeight;
+
+ if (abs(scrollingSpeed) < ((int) (actualLineHeight * 2.5))) {
+ scrollingY += scrollingSpeed;
+ scrollingSpeed += SCROLLING_SPEED_DECREMENT;
+ } else {
+ scrollingY -= ((int) (actualLineHeight * 2.5));
+ scrollingSpeed += SCROLLING_SPEED_DECREMENT;
+ }
+ while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) {
+ mStart++;
+ scrollingY += actualLineHeight;
+ }
+ if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) {
+ mStart = totalSize - lines - 1;
+ scrollingY = bottom_offset;
+ } else if (mStart + lines >= totalSize && scrollingY < 0) {
+ mStart = totalSize - lines;
+ scrollingY = 0;
+ } else if (scrollingSpeed * -1 < SCROLLING_FLOOR)
+ scrollingSpeed = 0;
+ mUpdate = 1;
+ }
+ }
+
+ return 0;
}
int GUIListBox::GetSelection(int x, int y)
{
- // We only care about y position
- return (y - mRenderY) / (mLineHeight + mLineSpacing);
+ // We only care about y position
+ if (y < mRenderY || y - mRenderY <= mHeaderH || y - mRenderY > mRenderH) return -1;
+ return (y - mRenderY - mHeaderH);
}
int GUIListBox::NotifyTouch(TOUCH_STATE state, int x, int y)
{
- static int startSelection = -1;
- static int startY = 0;
- int selection = 0;
+ static int lastY = 0, last2Y = 0;
+ int selection = 0;
+
+ switch (state)
+ {
+ case TOUCH_START:
+ if (scrollingSpeed != 0)
+ startSelection = -1;
+ else
+ startSelection = GetSelection(x,y);
+ isHighlighted = (startSelection > -1);
+ if (isHighlighted)
+ mUpdate = 1;
+ startY = lastY = last2Y = y;
+ scrollingSpeed = 0;
+ break;
+
+ case TOUCH_DRAG:
+ // Check if we dragged out of the selection window
+ if (GetSelection(x, y) == -1) {
+ last2Y = lastY = 0;
+ if (isHighlighted) {
+ isHighlighted = false;
+ mUpdate = 1;
+ }
+ break;
+ }
- 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;
+ // Provide some debounce on initial touches
+ if (startSelection != -1 && abs(y - startY) < touchDebounce) {
+ isHighlighted = true;
+ mUpdate = 1;
+ 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:
+ isHighlighted = false;
+ last2Y = lastY;
+ lastY = y;
+ startSelection = -1;
+
+ // Handle scrolling
+ scrollingY += y - startY;
+ startY = y;
+ while(mStart && scrollingY > 0) {
+ mStart--;
+ scrollingY -= actualLineHeight;
+ }
+ if (mStart == 0 && scrollingY > 0)
+ scrollingY = 0;
+ {
+ int totalSize = mList.size();
+ int lines = (mRenderH - mHeaderH) / (actualLineHeight);
+
+ if (totalSize > lines) {
+ int bottom_offset = ((int)(mRenderH) - mHeaderH) - (lines * actualLineHeight);
+
+ bottom_offset -= actualLineHeight;
+
+ while (mStart + lines + (bottom_offset ? 1 : 0) < totalSize && abs(scrollingY) > actualLineHeight) {
+ mStart++;
+ scrollingY += actualLineHeight;
+ }
+ if (bottom_offset != 0 && mStart + lines + 1 >= totalSize && scrollingY <= bottom_offset) {
+ mStart = totalSize - lines - 1;
+ scrollingY = bottom_offset;
+ } else if (mStart + lines >= totalSize && scrollingY < 0) {
+ mStart = totalSize - lines;
+ scrollingY = 0;
+ }
+ } else
+ scrollingY = 0;
+ }
+ mUpdate = 1;
+ break;
+
+ case TOUCH_RELEASE:
+ isHighlighted = false;
+ if (startSelection >= 0)
+ {
+ // We've selected an item!
+ std::string str;
+
+ int listSize = mList.size();
+ int selectY = scrollingY, actualSelection = mStart;
+
+ // Move the selection to the proper place in the array
+ while (selectY + actualLineHeight < startSelection) {
+ selectY += actualLineHeight;
+ actualSelection++;
+ }
+
+ if (actualSelection < listSize && !mVariable.empty())
+ {
+ int i;
+ for (i=0; i<listSize; i++)
+ mList.at(i).selected = 0;
+
+ str = mList.at(actualSelection).variableValue;
+ mList.at(actualSelection).selected = 1;
+ DataManager::SetValue(mVariable, str);
+ mUpdate = 1;
+ }
+ } else {
+ // This is for kinetic scrolling
+ scrollingSpeed = lastY - last2Y;
+ if (abs(scrollingSpeed) > SCROLLING_FLOOR)
+ scrollingSpeed *= SCROLLING_MULTIPLIER;
+ else
+ scrollingSpeed = 0;
+ }
case TOUCH_REPEAT:
- break;
- }
- return 0;
+ case TOUCH_HOLD:
+ 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 (!mHeaderIsStatic) {
+ std::string newValue = gui_parse_text(mHeaderText);
+ if (mLastValue != newValue) {
+ mLastValue = newValue;
+ mStart = 0;
+ scrollingY = 0;
+ scrollingSpeed = 0;
+ mUpdate = 1;
}
- }
- if (varName == mVariable || var_changed != 0)
+ }
+ if (varName == mVariable)
{
int i, listSize = mList.size(), selected_index = 0;
@@ -354,28 +680,29 @@ int GUIListBox::NotifyVarChange(std::string varName, std::string value)
mUpdate = 1;
return 0;
}
- 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;
+ 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;
- }
+ if (inFocus)
+ {
+ DataManager::GetValue(mVariable, currentValue);
+ NotifyVarChange(mVariable, currentValue);
+ mUpdate = 1;
+ }
}
-