From 0a3a98f8927210ab4700a7b4ab2a09664c00d331 Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Thu, 5 Feb 2015 00:48:28 +0100 Subject: Unify scrollable list code The goal of this patch set is to eliminate the code duplication caused by copy/paste of the code in the file selector, listbox, and partition list GUI elements. Those classes will now utilize a single GUIScrollList class that will handle rendering and scrolling. Change-Id: I0cb98ab36cf47178296034293435225658c779cd --- gui/fileselector.cpp | 900 +++++++-------------------------------------------- 1 file changed, 125 insertions(+), 775 deletions(-) (limited to 'gui/fileselector.cpp') diff --git a/gui/fileselector.cpp b/gui/fileselector.cpp index cf7a9a908..c7805c42a 100644 --- a/gui/fileselector.cpp +++ b/gui/fileselector.cpp @@ -16,25 +16,9 @@ along with TWRP. If not, see . */ -#include -#include -#include -#include -#include #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include - #include extern "C" { @@ -49,188 +33,23 @@ extern "C" { #define TW_FILESELECTOR_UP_A_LEVEL "(Up A Level)" -#define SCROLLING_SPEED_DECREMENT 6 -#define SCROLLING_FLOOR 10 -#define SCROLLING_MULTIPLIER 6 - int GUIFileSelector::mSortOrder = 0; -GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIObject(node) +GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIScrollList(node) { 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 = mFolderIconHeight = mFileIconHeight = mFolderIconWidth = mFileIconWidth = mHeaderIconHeight = mHeaderIconWidth = 0; - mHeaderSeparatorH = mLineHeight = mHeaderIsStatic = mHeaderH = actualLineHeight = 0; - mFolderIcon = mFileIcon = mBackground = mFont = mHeaderIcon = NULL; - mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = 0; + int mIconWidth = 0, mIconHeight = 0, mFolderIconHeight = 0, mFileIconHeight = 0, mFolderIconWidth = 0, mFileIconWidth = 0; + mFolderIcon = mFileIcon = NULL; mShowFolders = mShowFiles = mShowNavFolders = 1; - mFastScrollW = mFastScrollLineW = mFastScrollRectW = mFastScrollRectH = 0; - mFastScrollRectX = mFastScrollRectY = -1; mUpdate = 0; - touchDebounce = 6; mPathVar = "cwd"; - ConvertStrToColor("black", &mBackgroundColor); - ConvertStrToColor("black", &mHeaderBackgroundColor); - ConvertStrToColor("black", &mSeparatorColor); - ConvertStrToColor("black", &mHeaderSeparatorColor); - ConvertStrToColor("white", &mFontColor); - ConvertStrToColor("white", &mHeaderFontColor); - ConvertStrToColor("white", &mFastScrollLineColor); - ConvertStrToColor("white", &mFastScrollRectColor); - hasHighlightColor = false; - hasFontHighlightColor = false; - isHighlighted = false; updateFileList = 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("folder"); - if (attr) - mFolderIcon = PageManager::FindResource(attr->value()); - attr = child->first_attribute("file"); - if (attr) - mFileIcon = 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); - } - - attr = child->first_attribute("spacing"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mLineSpacing = atoi(parsevalue.c_str()); - } - - attr = child->first_attribute("highlightcolor"); - memset(&mFontHighlightColor, 0, sizeof(COLOR)); - if (attr) - { - std::string color = attr->value(); - 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("height"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mSeparatorH = atoi(parsevalue.c_str()); - if (!header_separator_height_specified) - mHeaderSeparatorH = mSeparatorH; - } - } + // Load filter for filtering files (e.g. *.zip for only zips) child = node->first_node("filter"); - if (child) - { + if (child) { attr = child->first_attribute("extn"); if (attr) mExtn = attr->value(); @@ -247,8 +66,7 @@ GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIObject(node) // Handle the path variable child = node->first_node("path"); - if (child) - { + if (child) { attr = child->first_attribute("name"); if (attr) mPathVar = attr->value(); @@ -259,8 +77,7 @@ GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIObject(node) // Handle the result variable child = node->first_node("data"); - if (child) - { + if (child) { attr = child->first_attribute("name"); if (attr) mVariable = attr->value(); @@ -271,8 +88,7 @@ GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIObject(node) // Handle the sort variable child = node->first_node("sort"); - if (child) - { + if (child) { attr = child->first_attribute("name"); if (attr) mSortVariable = attr->value(); @@ -285,100 +101,37 @@ GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIObject(node) // Handle the selection variable child = node->first_node("selection"); - if (child) - { - attr = child->first_attribute("name"); - if (attr) - mSelection = attr->value(); - else - mSelection = "0"; - } else + if (child && (attr = child->first_attribute("name"))) + mSelection = attr->value(); + else mSelection = "0"; - // Fast scroll colors - child = node->first_node("fastscroll"); - if (child) - { - attr = child->first_attribute("linecolor"); - if(attr) - ConvertStrToColor(attr->value(), &mFastScrollLineColor); - - attr = child->first_attribute("rectcolor"); - if(attr) - ConvertStrToColor(attr->value(), &mFastScrollRectColor); - - attr = child->first_attribute("w"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mFastScrollW = atoi(parsevalue.c_str()); - } - - attr = child->first_attribute("linew"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mFastScrollLineW = atoi(parsevalue.c_str()); - } - - attr = child->first_attribute("rectw"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mFastScrollRectW = atoi(parsevalue.c_str()); - } - - attr = child->first_attribute("recth"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mFastScrollRectH = atoi(parsevalue.c_str()); - } + // Get folder and file icons if present + child = node->first_node("icon"); + if (child) { + attr = child->first_attribute("folder"); + if (attr) + mFolderIcon = PageManager::FindResource(attr->value()); + attr = child->first_attribute("file"); + if (attr) + mFileIcon = PageManager::FindResource(attr->value()); } - - // Retrieve the line height - mFontHeight = gr_getMaxFontHeight(mFont ? mFont->GetResource() : NULL); - mLineHeight = mFontHeight; - mHeaderH = mFontHeight; - - if (mFolderIcon && mFolderIcon->GetResource()) - { + if (mFolderIcon && mFolderIcon->GetResource()) { mFolderIconWidth = gr_get_width(mFolderIcon->GetResource()); mFolderIconHeight = gr_get_height(mFolderIcon->GetResource()); - if (mFolderIconHeight > (int)mLineHeight) - mLineHeight = mFolderIconHeight; + if (mFolderIconHeight > mIconHeight) + mIconHeight = mFolderIconHeight; mIconWidth = mFolderIconWidth; } - - if (mFileIcon && mFileIcon->GetResource()) - { + if (mFileIcon && mFileIcon->GetResource()) { mFileIconWidth = gr_get_width(mFileIcon->GetResource()); mFileIconHeight = gr_get_height(mFileIcon->GetResource()); - if (mFileIconHeight > (int)mLineHeight) - mLineHeight = mFileIconHeight; + if (mFileIconHeight > mIconHeight) + mIconHeight = mFileIconHeight; if (mFileIconWidth > mIconWidth) mIconWidth = mFileIconWidth; } - - 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()); - } + SetMaxIconSize(mIconWidth, mIconHeight); // Fetch the file/folder list std::string value; @@ -388,533 +141,61 @@ GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIObject(node) GUIFileSelector::~GUIFileSelector() { + delete mFileIcon; + delete mFolderIcon; } -int GUIFileSelector::Render(void) +int GUIFileSelector::Update(void) { if(!isConditionTrue()) return 0; - // First step, fill background - 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); - } + GUIScrollList::Update(); // Update the file list if needed if (updateFileList) { string value; DataManager::GetValue(mPathVar, value); - if (GetFileList(value) == 0) + if (GetFileList(value) == 0) { updateFileList = false; - else - return 0; - } - - // This tells us how many lines we can actually render - int lines = (mRenderH - mHeaderH) / (actualLineHeight); - int line; - - int folderSize = mShowFolders ? mFolderList.size() : 0; - int fileSize = mShowFiles ? mFileList.size() : 0; - - int listW = mRenderW; - - if (folderSize + fileSize < lines) { - lines = folderSize + fileSize; - scrollingY = 0; - mFastScrollRectX = mFastScrollRectY = -1; - } else { - listW -= mFastScrollW; // space for fast scroll - lines++; - if (lines < folderSize + fileSize) - 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 folderIconOffsetY = (int)((actualLineHeight - mFolderIconHeight) / 2), fileIconOffsetY = (int)((actualLineHeight - mFileIconHeight) / 2); - int folderIconOffsetX = (mIconWidth - mFolderIconWidth) / 2, fileIconOffsetX = (mIconWidth - mFileIconWidth) / 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 (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); - } - - if (line + mStart < folderSize) - { - icon = mFolderIcon; - label = mFolderList.at(line + mStart).fileName; - currentIconHeight = mFolderIconHeight; - currentIconWidth = mFolderIconWidth; - currentIconOffsetY = folderIconOffsetY; - currentIconOffsetX = folderIconOffsetX; - } - else if (line + mStart < folderSize + fileSize) - { - icon = mFileIcon; - label = mFileList.at((line + mStart) - folderSize).fileName; - currentIconHeight = mFileIconHeight; - currentIconWidth = mFileIconWidth; - currentIconOffsetY = fileIconOffsetY; - currentIconOffsetX = fileIconOffsetX; - } else { - continue; - } - - 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 + listW, mRenderY + mRenderH); - - // Add the separator - if (yPos + actualLineHeight < mRenderH + mRenderY) { - gr_color(mSeparatorColor.red, mSeparatorColor.green, mSeparatorColor.blue, 255); - gr_fill(mRenderX, yPos + actualLineHeight - mSeparatorH, listW, mSeparatorH); - } - - // 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); - } - - // render fast scroll - lines = (mRenderH - mHeaderH) / (actualLineHeight); - if(mFastScrollW > 0 && folderSize + fileSize > lines) - { - int startX = listW + mRenderX; - int fWidth = mRenderW - listW; - int fHeight = mRenderH - mHeaderH; - - // line - gr_color(mFastScrollLineColor.red, mFastScrollLineColor.green, mFastScrollLineColor.blue, 255); - gr_fill(startX + fWidth/2, mRenderY + mHeaderH, mFastScrollLineW, mRenderH - mHeaderH); - - // rect - int pct = ((mStart*actualLineHeight - scrollingY)*100)/((folderSize + fileSize)*actualLineHeight-lines*actualLineHeight); - mFastScrollRectX = startX + (fWidth - mFastScrollRectW)/2; - mFastScrollRectY = mRenderY+mHeaderH + ((fHeight - mFastScrollRectH)*pct)/100; - - gr_color(mFastScrollRectColor.red, mFastScrollRectColor.green, mFastScrollRectColor.blue, 255); - gr_fill(mFastScrollRectX, mFastScrollRectY, mFastScrollRectW, mFastScrollRectH); - } - - // If a change came in during the render then we need to do another redraw so leave mUpdate alone if updateFileList is true. - if (!updateFileList) { - mUpdate = 0; - } - return 0; -} - -int GUIFileSelector::Update(void) -{ - if(!isConditionTrue()) - return 0; - - if (!mHeaderIsStatic) { - std::string newValue = gui_parse_text(mHeaderText); - if (mLastValue != newValue) { - mLastValue = newValue; mUpdate = 1; - } + } else + return 0; } - if (mUpdate) - { + if (mUpdate) { mUpdate = 0; if (Render() == 0) return 2; } - - // 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 = (mShowFolders ? mFolderList.size() : 0) + (mShowFiles ? mFileList.size() : 0); - 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 GUIFileSelector::GetSelection(int x, int y) -{ - // We only care about y position - if (y < mRenderY || y - mRenderY <= mHeaderH || y - mRenderY > mRenderH) - return -1; - - return (y - mRenderY - mHeaderH); -} - -int GUIFileSelector::NotifyTouch(TOUCH_STATE state, int x, int y) -{ - if(!isConditionTrue()) - return -1; - - static int lastY = 0, last2Y = 0, fastScroll = 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; - - if(mFastScrollRectX != -1 && x >= mRenderX + mRenderW - mFastScrollW) - fastScroll = 1; - 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; - } - - // Fast scroll - if(fastScroll) - { - int pct = ((y-mRenderY-mHeaderH)*100)/(mRenderH-mHeaderH); - int totalSize = (mShowFolders ? mFolderList.size() : 0) + (mShowFiles ? mFileList.size() : 0); - int lines = (mRenderH - mHeaderH) / (actualLineHeight); - - float l = float((totalSize-lines)*pct)/100; - if(l + lines >= totalSize) - { - mStart = totalSize - lines; - scrollingY = 0; - } - else - { - mStart = l; - scrollingY = -(l - int(l))*actualLineHeight; - } - - startSelection = -1; - mUpdate = 1; - scrollingSpeed = 0; - isHighlighted = false; - break; - } - - // Provide some debounce on initial touches - if (startSelection != -1 && abs(y - startY) < touchDebounce) { - isHighlighted = true; - mUpdate = 1; - break; - } - - 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 = (mShowFolders ? mFolderList.size() : 0) + (mShowFiles ? mFileList.size() : 0); - 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; - fastScroll = 0; - if (startSelection >= 0) - { - // We've selected an item! - std::string str; - - int folderSize = mShowFolders ? mFolderList.size() : 0; - int fileSize = mShowFiles ? mFileList.size() : 0; - int selectY = scrollingY, actualSelection = mStart; - - // Move the selection to the proper place in the array - while (selectY + actualLineHeight < startSelection) { - selectY += actualLineHeight; - actualSelection++; - } - startSelection = actualSelection; - - if (startSelection < folderSize + fileSize) - { - DataManager::Vibrate("tw_button_vibrate"); - - if (startSelection < folderSize) - { - std::string oldcwd; - std::string cwd; - - str = mFolderList.at(startSelection).fileName; - if (mSelection != "0") - DataManager::SetValue(mSelection, str); - DataManager::GetValue(mPathVar, cwd); - - oldcwd = cwd; - // Ignore requests to do nothing - if (str == ".") return 0; - if (str == TW_FILESELECTOR_UP_A_LEVEL) - { - if (cwd != "/") - { - size_t found; - found = cwd.find_last_of('/'); - cwd = cwd.substr(0,found); - - if (cwd.length() < 2) cwd = "/"; - } - } - else - { - // Add a slash if we're not the root folder - if (cwd != "/") cwd += "/"; - cwd += str; - } - - if (mShowNavFolders == 0 && mShowFiles == 0) - { - // This is a "folder" selection - DataManager::SetValue(mVariable, cwd); - } - else - { - DataManager::SetValue(mPathVar, cwd); - mStart = 0; - scrollingY = 0; - mUpdate = 1; - } - } - else if (!mVariable.empty()) - { - str = mFileList.at(startSelection - folderSize).fileName; - if (mSelection != "0") - DataManager::SetValue(mSelection, str); - - std::string cwd; - DataManager::GetValue(mPathVar, cwd); - if (cwd != "/") cwd += "/"; - DataManager::SetValue(mVariable, cwd + str); - } - } - } else { - // This is for kinetic scrolling - scrollingSpeed = lastY - last2Y; - if (abs(scrollingSpeed) > SCROLLING_FLOOR) - scrollingSpeed *= SCROLLING_MULTIPLIER; - else - scrollingSpeed = 0; - } - case TOUCH_REPEAT: - case TOUCH_HOLD: - break; - } return 0; } int GUIFileSelector::NotifyVarChange(const std::string& varName, const std::string& value) { - GUIObject::NotifyVarChange(varName, value); - if(!isConditionTrue()) return 0; + GUIScrollList::NotifyVarChange(varName, value); + if (varName.empty()) { // Always clear the data variable so we know to use it DataManager::SetValue(mVariable, ""); } - if (!mHeaderIsStatic) { - std::string newValue = gui_parse_text(mHeaderText); - if (mLastValue != newValue) { - mLastValue = newValue; - mStart = 0; - scrollingY = 0; - scrollingSpeed = 0; - mUpdate = 1; - } - } - if (varName == mPathVar || varName == mSortVariable) - { + if (varName == mPathVar || varName == mSortVariable) { if (varName == mSortVariable) { DataManager::GetValue(mSortVariable, mSortOrder); + } else { + // Reset the list to the top + SetVisibleListLocation(0); } updateFileList = true; - mStart = 0; - scrollingY = 0; - scrollingSpeed = 0; mUpdate = 1; return 0; } return 0; } -int GUIFileSelector::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; -} - bool GUIFileSelector::fileSort(FileData d1, FileData d2) { if (d1.fileName == ".") @@ -948,6 +229,7 @@ bool GUIFileSelector::fileSort(FileData d1, FileData d2) default: // should be a 1 - sort by name ascending return (strcasecmp(d1.fileName.c_str(), d2.fileName.c_str()) < 0); } + return 0; } int GUIFileSelector::GetFileList(const std::string folder) @@ -961,8 +243,7 @@ int GUIFileSelector::GetFileList(const std::string folder) mFileList.clear(); d = opendir(folder.c_str()); - if (d == NULL) - { + if (d == NULL) { LOGINFO("Unable to open '%s'\n", folder.c_str()); if (folder != "/" && (mShowNavFolders != 0 || mShowFiles != 0)) { size_t found; @@ -978,8 +259,7 @@ int GUIFileSelector::GetFileList(const std::string folder) return -1; } - while ((de = readdir(d)) != NULL) - { + while ((de = readdir(d)) != NULL) { FileData data; data.fileName = de->d_name; @@ -1007,15 +287,11 @@ int GUIFileSelector::GetFileList(const std::string folder) if (data.fileType == DT_UNKNOWN) { data.fileType = TWFunc::Get_D_Type_From_Stat(path); } - if (data.fileType == DT_DIR) - { + if (data.fileType == DT_DIR) { if (mShowNavFolders || (data.fileName != "." && data.fileName != TW_FILESELECTOR_UP_A_LEVEL)) mFolderList.push_back(data); - } - else if (data.fileType == DT_REG || data.fileType == DT_LNK || data.fileType == DT_BLK) - { - if (mExtn.empty() || (data.fileName.length() > mExtn.length() && data.fileName.substr(data.fileName.length() - mExtn.length()) == mExtn)) - { + } else if (data.fileType == DT_REG || data.fileType == DT_LNK || data.fileType == DT_BLK) { + if (mExtn.empty() || (data.fileName.length() > mExtn.length() && data.fileName.substr(data.fileName.length() - mExtn.length()) == mExtn)) { mFileList.push_back(data); } } @@ -1030,11 +306,85 @@ int GUIFileSelector::GetFileList(const std::string folder) void GUIFileSelector::SetPageFocus(int inFocus) { - if (inFocus) - { + GUIScrollList::SetPageFocus(inFocus); + if (inFocus) { updateFileList = true; - scrollingY = 0; - scrollingSpeed = 0; mUpdate = 1; } } + +size_t GUIFileSelector::GetItemCount() +{ + size_t folderSize = mShowFolders ? mFolderList.size() : 0; + size_t fileSize = mShowFiles ? mFileList.size() : 0; + return folderSize + fileSize; +} + +int GUIFileSelector::GetListItem(size_t item_index, Resource*& icon, std::string &text) +{ + size_t folderSize = mShowFolders ? mFolderList.size() : 0; + size_t fileSize = mShowFiles ? mFileList.size() : 0; + + if (item_index < folderSize) { + text = mFolderList.at(item_index).fileName; + icon = mFolderIcon; + } else { + text = mFileList.at(item_index - folderSize).fileName; + icon = mFileIcon; + } + return 0; +} + +void GUIFileSelector::NotifySelect(size_t item_selected) +{ + size_t folderSize = mShowFolders ? mFolderList.size() : 0; + size_t fileSize = mShowFiles ? mFileList.size() : 0; + + if (item_selected < folderSize + fileSize) { + // We've selected an item! + std::string str; + if (item_selected < folderSize) { + std::string cwd; + + str = mFolderList.at(item_selected).fileName; + if (mSelection != "0") + DataManager::SetValue(mSelection, str); + DataManager::GetValue(mPathVar, cwd); + + // Ignore requests to do nothing + if (str == ".") return; + if (str == TW_FILESELECTOR_UP_A_LEVEL) { + if (cwd != "/") { + size_t found; + found = cwd.find_last_of('/'); + cwd = cwd.substr(0,found); + + if (cwd.length() < 2) cwd = "/"; + } + } else { + // Add a slash if we're not the root folder + if (cwd != "/") cwd += "/"; + cwd += str; + } + + if (mShowNavFolders == 0 && mShowFiles == 0) { + // nav folders and files are disabled, this is probably the restore list and we need to save chosen location to mVariable instead of mPathVar + DataManager::SetValue(mVariable, cwd); + } else { + // We are changing paths, so we need to set mPathVar + DataManager::SetValue(mPathVar, cwd); + } + } else if (!mVariable.empty()) { + str = mFileList.at(item_selected - folderSize).fileName; + if (mSelection != "0") + DataManager::SetValue(mSelection, str); + + std::string cwd; + DataManager::GetValue(mPathVar, cwd); + if (cwd != "/") + cwd += "/"; + DataManager::SetValue(mVariable, cwd + str); + } + } + mUpdate = 1; +} -- cgit v1.2.3