From eead985c5729bbd53c70b902e99754b350390be2 Mon Sep 17 00:00:00 2001 From: Dees_Troy Date: Fri, 15 Feb 2013 14:31:06 -0600 Subject: Update listbox code --- gui/devices/1024x600/res/ui.xml | 6 +- gui/devices/1024x768/res/ui.xml | 6 +- gui/devices/1280x800/res/ui.xml | 6 +- gui/devices/1920x1200/res/ui.xml | 6 +- gui/devices/2560x1600/res/ui.xml | 6 +- gui/devices/320x480/res/ui.xml | 16 +- gui/devices/480x800/res/ui.xml | 16 +- gui/devices/480x854/res/ui.xml | 16 +- gui/devices/540x960/res/ui.xml | 16 +- gui/devices/720x1280/res/ui.xml | 16 +- gui/devices/800x1280/res/ui.xml | 16 +- gui/devices/800x480/res/ui.xml | 6 +- gui/listbox.cpp | 797 +++++++++++++++++++++++++++------------ gui/objects.hpp | 24 +- 14 files changed, 656 insertions(+), 297 deletions(-) (limited to 'gui') diff --git a/gui/devices/1024x600/res/ui.xml b/gui/devices/1024x600/res/ui.xml index 76d7d7339..9d66a9021 100755 --- a/gui/devices/1024x600/res/ui.xml +++ b/gui/devices/1024x600/res/ui.xml @@ -2497,10 +2497,14 @@ + +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/1024x768/res/ui.xml b/gui/devices/1024x768/res/ui.xml index 7f856de37..cf74e0a35 100644 --- a/gui/devices/1024x768/res/ui.xml +++ b/gui/devices/1024x768/res/ui.xml @@ -2497,10 +2497,14 @@
+ +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/1280x800/res/ui.xml b/gui/devices/1280x800/res/ui.xml index 3d0821499..8e96c7bf6 100644 --- a/gui/devices/1280x800/res/ui.xml +++ b/gui/devices/1280x800/res/ui.xml @@ -2497,10 +2497,14 @@
+ +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/1920x1200/res/ui.xml b/gui/devices/1920x1200/res/ui.xml index 95237faec..cbe6353a8 100644 --- a/gui/devices/1920x1200/res/ui.xml +++ b/gui/devices/1920x1200/res/ui.xml @@ -2497,10 +2497,14 @@
+ +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/2560x1600/res/ui.xml b/gui/devices/2560x1600/res/ui.xml index 45209bb7d..834aa2a45 100644 --- a/gui/devices/2560x1600/res/ui.xml +++ b/gui/devices/2560x1600/res/ui.xml @@ -2497,10 +2497,14 @@
+ +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/320x480/res/ui.xml b/gui/devices/320x480/res/ui.xml index 406187e4d..c8ff2fbba 100644 --- a/gui/devices/320x480/res/ui.xml +++ b/gui/devices/320x480/res/ui.xml @@ -137,7 +137,7 @@ - + @@ -2462,17 +2462,15 @@ - - - - Select Time Zone - - - + + +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/480x800/res/ui.xml b/gui/devices/480x800/res/ui.xml index b2acb237f..718921d76 100644 --- a/gui/devices/480x800/res/ui.xml +++ b/gui/devices/480x800/res/ui.xml @@ -136,7 +136,7 @@ - + @@ -2461,17 +2461,15 @@ - - - - Select Time Zone - - - + + +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/480x854/res/ui.xml b/gui/devices/480x854/res/ui.xml index 20895f82d..b8bd53f9c 100644 --- a/gui/devices/480x854/res/ui.xml +++ b/gui/devices/480x854/res/ui.xml @@ -135,7 +135,7 @@ - + @@ -2460,17 +2460,15 @@ - - - - Select Time Zone - - - + + +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/540x960/res/ui.xml b/gui/devices/540x960/res/ui.xml index d3cb57418..01e7f7ae8 100644 --- a/gui/devices/540x960/res/ui.xml +++ b/gui/devices/540x960/res/ui.xml @@ -136,7 +136,7 @@ - + @@ -2461,17 +2461,15 @@ - - - - Select Time Zone - - - + + +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/720x1280/res/ui.xml b/gui/devices/720x1280/res/ui.xml index 217564fdb..fa51706ff 100644 --- a/gui/devices/720x1280/res/ui.xml +++ b/gui/devices/720x1280/res/ui.xml @@ -141,7 +141,7 @@ - + @@ -2474,17 +2474,15 @@ - - - - Select Time Zone - - - + + +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/800x1280/res/ui.xml b/gui/devices/800x1280/res/ui.xml index 1b9560478..4fb039d2a 100755 --- a/gui/devices/800x1280/res/ui.xml +++ b/gui/devices/800x1280/res/ui.xml @@ -137,7 +137,7 @@ - + @@ -2462,17 +2462,15 @@ - - - - Select Time Zone - - - + + +
+ Select Time Zone: + - + BST11;BDT HST10;HDT diff --git a/gui/devices/800x480/res/ui.xml b/gui/devices/800x480/res/ui.xml index 342b14e8e..9d6abf9a8 100755 --- a/gui/devices/800x480/res/ui.xml +++ b/gui/devices/800x480/res/ui.xml @@ -2505,10 +2505,14 @@
+ +
+ Select Time Zone: + - + BST11;BDT HST10;HDT 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 #include @@ -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 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 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; + } } - diff --git a/gui/objects.hpp b/gui/objects.hpp index 3925a2757..2ddeb88c7 100644 --- a/gui/objects.hpp +++ b/gui/objects.hpp @@ -533,20 +533,40 @@ protected: std::string mVariable; std::string mSelection; std::string currentValue; + std::string mHeaderText; + std::string mLastValue; + int actualLineHeight; int mStart; + int startY; + int mSeparatorH, mHeaderSeparatorH; int mLineSpacing; int mUpdate; - int mBackgroundX, mBackgroundY, mBackgroundW, mBackgroundH; + int mBackgroundX, mBackgroundY, mBackgroundW, mBackgroundH, mHeaderH; + int mIconWidth, mIconHeight, mSelectedIconWidth, mSelectedIconHeight, mUnselectedIconWidth, mUnselectedIconHeight, mHeaderIconHeight, mHeaderIconWidth; + int scrollingSpeed; + int scrollingY; static int mSortOrder; unsigned mFontHeight; unsigned mLineHeight; - int mIconWidth, mIconHeight; + Resource* mHeaderIcon; Resource* mIconSelected; Resource* mIconUnselected; Resource* mBackground; Resource* mFont; COLOR mBackgroundColor; COLOR mFontColor; + COLOR mHeaderBackgroundColor; + COLOR mHeaderFontColor; + COLOR mSeparatorColor; + COLOR mHeaderSeparatorColor; + bool hasHighlightColor; + bool hasFontHighlightColor; + bool isHighlighted; + COLOR mHighlightColor; + COLOR mFontHighlightColor; + int mHeaderIsStatic; + int startSelection; + int touchDebounce; }; // GUIAnimation - Used for animations -- cgit v1.2.3