From 9876ac3361c77a28a55e7843d6db1dc781f93d95 Mon Sep 17 00:00:00 2001 From: that Date: Sun, 15 Feb 2015 21:40:59 +0100 Subject: gui: support scrollable lists without headers If the
element doesn't exist, the header is not drawn. - minuitwrp: add function for clipping all drawing to a rectangle ...and another one to cancel it. Change-Id: If0f688a5debee6ebd9c457999fe571705a42c5cc --- gui/objects.hpp | 9 +- gui/scrolllist.cpp | 243 ++++++++++++++++----------------------------------- minuitwrp/graphics.c | 14 +++ minuitwrp/minui.h | 2 + 4 files changed, 93 insertions(+), 175 deletions(-) diff --git a/gui/objects.hpp b/gui/objects.hpp index 537de208e..b6937a215 100644 --- a/gui/objects.hpp +++ b/gui/objects.hpp @@ -552,7 +552,7 @@ protected: // Handle scrolling changes for drags and kinetic scrolling void HandleScrolling(); - // Returns many rows the list is capable of displaying + // Returns many full rows the list is capable of displaying int GetDisplayItemCount(); // Returns the size in pixels of a partial item or row size @@ -569,7 +569,7 @@ protected: COLOR mHeaderFontColor; std::string mHeaderText; // Original header text without parsing any variables std::string mLastHeaderValue; // Header text after parsing variables - int mHeaderIsStatic; // indicates if the header is static (no need to check for changes in NotifyVarChange) + bool mHeaderIsStatic; // indicates if the header is static (no need to check for changes in NotifyVarChange) int mHeaderH; // actual header height including font, icon, padding, and separator heights ImageResource* mHeaderIcon; int mHeaderIconHeight, mHeaderIconWidth; // width and height of the header icon if present @@ -579,9 +579,8 @@ protected: // Per-item layout FontResource* mFont; COLOR mFontColor; - bool hasHighlightColor; // indicates if a hightlight color was set - bool hasFontHighlightColor; // indicates if the font hightlight color is set - COLOR mHighlightColor; // background row hightlight color + bool hasHighlightColor; // indicates if a highlight color was set + COLOR mHighlightColor; // background row highlight color COLOR mFontHighlightColor; int mFontHeight; int actualItemHeight; // Actual height of each item in pixels including max icon size, font size, and padding diff --git a/gui/scrolllist.cpp b/gui/scrolllist.cpp index 822fa7644..05141b1cf 100644 --- a/gui/scrolllist.cpp +++ b/gui/scrolllist.cpp @@ -36,11 +36,11 @@ GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(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; firstDisplayedItem = mItemSpacing = mFontHeight = mSeparatorH = y_offset = scrollingSpeed = 0; maxIconWidth = maxIconHeight = mHeaderIconHeight = mHeaderIconWidth = 0; - mHeaderSeparatorH = mHeaderIsStatic = mHeaderH = actualItemHeight = 0; + mHeaderSeparatorH = mHeaderH = actualItemHeight = 0; + mHeaderIsStatic = false; mBackground = mHeaderIcon = NULL; mFont = NULL; mBackgroundW = mBackgroundH = 0; @@ -57,45 +57,14 @@ GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(node) ConvertStrToColor("white", &mFastScrollLineColor); ConvertStrToColor("white", &mFastScrollRectColor); hasHighlightColor = false; - hasFontHighlightColor = false; selectedItem = NO_ITEM; // Load header text - child = node->first_node("header"); - if (child) - { - mHeaderIcon = LoadAttrImage(child, "icon"); - - 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 = scale_theme_y(atoi(parsevalue.c_str())); - header_separator_height_specified = -1; - } - } child = node->first_node("text"); if (child) mHeaderText = child->value(); + // Simple way to check for static state + mLastHeaderValue = gui_parse_text(mHeaderText); + mHeaderIsStatic = (mLastHeaderValue == mHeaderText); memset(&mHighlightColor, 0, sizeof(COLOR)); child = node->first_node("highlight"); @@ -108,25 +77,11 @@ GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(node) } } - // Simple way to check for static state - mLastHeaderValue = gui_parse_text(mHeaderText); - if (mLastHeaderValue != mHeaderText) - mHeaderIsStatic = 0; - else - mHeaderIsStatic = -1; - child = node->first_node("background"); if (child) { mBackground = LoadAttrImage(child, "resource"); - attr = child->first_attribute("color"); - if (attr) - { - std::string color = attr->value(); - ConvertStrToColor(color, &mBackgroundColor); - if (!header_background_color_specified) - ConvertStrToColor(color, &mHeaderBackgroundColor); - } + mBackgroundColor = LoadAttrColor(child, "color"); } // Load the placement @@ -138,109 +93,61 @@ GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(node) if (child) { mFont = LoadAttrFont(child, "resource"); - - 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()); - mItemSpacing = scale_theme_y(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; - } + mFontColor = LoadAttrColor(child, "color"); + mFontHighlightColor = LoadAttrColor(child, "highlightcolor", mFontColor); + mItemSpacing = LoadAttrIntScaleY(child, "spacing"); } // 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 = scale_theme_y(atoi(parsevalue.c_str())); - if (!header_separator_height_specified) - mHeaderSeparatorH = mSeparatorH; - } + mSeparatorColor = LoadAttrColor(child, "color"); + mSeparatorH = LoadAttrIntScaleY(child, "height"); } - // Fast scroll colors + // Fast scroll 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); + mFastScrollLineColor = LoadAttrColor(child, "linecolor"); + mFastScrollRectColor = LoadAttrColor(child, "rectcolor"); - attr = child->first_attribute("w"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mFastScrollW = scale_theme_x(atoi(parsevalue.c_str())); - } - - attr = child->first_attribute("linew"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mFastScrollLineW = scale_theme_x(atoi(parsevalue.c_str())); - } - - attr = child->first_attribute("rectw"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mFastScrollRectW = scale_theme_x(atoi(parsevalue.c_str())); - } - - attr = child->first_attribute("recth"); - if (attr) { - string parsevalue = gui_parse_text(attr->value()); - mFastScrollRectH = scale_theme_y(atoi(parsevalue.c_str())); - } + mFastScrollW = LoadAttrIntScaleX(child, "w"); + mFastScrollLineW = LoadAttrIntScaleX(child, "linew"); + mFastScrollRectW = LoadAttrIntScaleX(child, "rectw"); + mFastScrollRectH = LoadAttrIntScaleY(child, "recth"); } // Retrieve the line height mFontHeight = mFont->GetHeight(); - mHeaderH = mFontHeight; + actualItemHeight = mFontHeight + mItemSpacing + mSeparatorH; - if (mHeaderIcon && mHeaderIcon->GetResource()) + // Load the header if it exists + child = node->first_node("header"); + if (child) { - mHeaderIconWidth = mHeaderIcon->GetWidth(); - mHeaderIconHeight = mHeaderIcon->GetHeight(); - if (mHeaderIconHeight > mHeaderH) - mHeaderH = mHeaderIconHeight; - if (mHeaderIconWidth > maxIconWidth) - maxIconWidth = mHeaderIconWidth; - } + mHeaderH = mFontHeight; + mHeaderIcon = LoadAttrImage(child, "icon"); + mHeaderBackgroundColor = LoadAttrColor(child, "background", mBackgroundColor); + mHeaderFontColor = LoadAttrColor(child, "textcolor", mFontColor); + mHeaderSeparatorColor = LoadAttrColor(child, "separatorcolor", mSeparatorColor); + mHeaderSeparatorH = LoadAttrIntScaleY(child, "separatorheight", mSeparatorH); - mHeaderH += mItemSpacing + mHeaderSeparatorH; - actualItemHeight = mFontHeight + mItemSpacing + mSeparatorH; - if (mHeaderH < actualItemHeight) - mHeaderH = actualItemHeight; + if (mHeaderIcon && mHeaderIcon->GetResource()) + { + mHeaderIconWidth = mHeaderIcon->GetWidth(); + mHeaderIconHeight = mHeaderIcon->GetHeight(); + if (mHeaderIconHeight > mHeaderH) + mHeaderH = mHeaderIconHeight; + if (mHeaderIconWidth > maxIconWidth) + maxIconWidth = mHeaderIconWidth; + } + + mHeaderH += mItemSpacing + mHeaderSeparatorH; + if (mHeaderH < actualItemHeight) + mHeaderH = actualItemHeight; + } if (actualItemHeight / 3 > 6) touchDebounce = actualItemHeight / 3; @@ -264,7 +171,7 @@ void GUIScrollList::SetMaxIconSize(int w, int h) maxIconHeight = h; if (maxIconHeight > mFontHeight) { actualItemHeight = maxIconHeight + mItemSpacing + mSeparatorH; - if (actualItemHeight > mHeaderH) + if (mHeaderH > 0 && actualItemHeight > mHeaderH) mHeaderH = actualItemHeight; } } @@ -300,9 +207,12 @@ int GUIScrollList::Render(void) return 0; // First step, fill background - gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255); + gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha); gr_fill(mRenderX, mRenderY + mHeaderH, mRenderW, mRenderH - mHeaderH); + // don't paint outside of the box + gr_clip(mRenderX, mRenderY, mRenderW, mRenderH); + // Next, render the background resource (if it exists) if (mBackground && mBackground->GetResource()) { @@ -311,7 +221,7 @@ int GUIScrollList::Render(void) gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY); } - // This tells us how many lines we can actually render + // This tells us how many full lines we can actually render size_t lines = GetDisplayItemCount(); size_t listSize = GetItemCount(); @@ -351,55 +261,46 @@ int GUIScrollList::Render(void) if (hasHighlightColor && itemindex == selectedItem) { // Highlight the item background of the selected item - gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, 255); - int HighlightHeight = actualItemHeight; - if (yPos + HighlightHeight > mRenderY + mRenderH) { - HighlightHeight = mRenderY + mRenderH - yPos; - } - gr_fill(mRenderX, yPos, mRenderW, HighlightHeight); + gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha); + gr_fill(mRenderX, yPos, mRenderW, actualItemHeight); } - if (hasFontHighlightColor && itemindex == selectedItem) { + if (itemindex == selectedItem) { // Use the highlight color for the font - gr_color(mFontHighlightColor.red, mFontHighlightColor.green, mFontHighlightColor.blue, 255); + gr_color(mFontHighlightColor.red, mFontHighlightColor.green, mFontHighlightColor.blue, mFontHighlightColor.alpha); } else { // Set the color for the font - gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, 255); + gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha); } + // render icon if (icon && icon->GetResource()) { int currentIconHeight = icon->GetHeight(); int currentIconWidth = icon->GetWidth(); - int currentIconOffsetY = (int)((actualItemHeight - currentIconHeight) / 2); + int currentIconOffsetY = (actualItemHeight - currentIconHeight) / 2; int currentIconOffsetX = (maxIconWidth - currentIconWidth) / 2; - 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); + int image_y = (yPos + currentIconOffsetY); + gr_blit(icon->GetResource(), 0, 0, currentIconWidth, currentIconHeight, mRenderX + currentIconOffsetX, image_y); } - gr_textExWH(mRenderX + maxIconWidth + 5, yPos + fontOffsetY, label.c_str(), fontResource, mRenderX + listW, mRenderY + mRenderH); + // render label text + gr_textEx(mRenderX + maxIconWidth + 5, yPos + fontOffsetY, label.c_str(), fontResource); // Add the separator - if (yPos + actualItemHeight < mRenderH + mRenderY) { - gr_color(mSeparatorColor.red, mSeparatorColor.green, mSeparatorColor.blue, 255); - gr_fill(mRenderX, yPos + actualItemHeight - mSeparatorH, listW, mSeparatorH); - } + gr_color(mSeparatorColor.red, mSeparatorColor.green, mSeparatorColor.blue, mSeparatorColor.alpha); + gr_fill(mRenderX, yPos + actualItemHeight - mSeparatorH, listW, mSeparatorH); // Move the yPos yPos += actualItemHeight; } // 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; - { + if (mHeaderH > 0) { + // First step, fill background + gr_color(mHeaderBackgroundColor.red, mHeaderBackgroundColor.green, mHeaderBackgroundColor.blue, mHeaderBackgroundColor.alpha); + gr_fill(mRenderX, mRenderY, mRenderW, mHeaderH); + int mIconOffsetX = 0; // render the icon if it exists @@ -411,11 +312,11 @@ int GUIScrollList::Render(void) } // render the text - gr_color(mHeaderFontColor.red, mHeaderFontColor.green, mHeaderFontColor.blue, 255); - gr_textExWH(mRenderX + mIconOffsetX + 5, yPos + (int)((mHeaderH - mFontHeight) / 2), mLastHeaderValue.c_str(), fontResource, mRenderX + mRenderW, mRenderY + mRenderH); + gr_color(mHeaderFontColor.red, mHeaderFontColor.green, mHeaderFontColor.blue, mHeaderFontColor.alpha); + gr_textEx(mRenderX + mIconOffsetX + 5, yPos + (int)((mHeaderH - mFontHeight) / 2), mLastHeaderValue.c_str(), fontResource); // Add the separator - gr_color(mHeaderSeparatorColor.red, mHeaderSeparatorColor.green, mHeaderSeparatorColor.blue, 255); + gr_color(mHeaderSeparatorColor.red, mHeaderSeparatorColor.green, mHeaderSeparatorColor.blue, mHeaderSeparatorColor.alpha); gr_fill(mRenderX, yPos + mHeaderH - mHeaderSeparatorH, mRenderW, mHeaderSeparatorH); } @@ -427,7 +328,7 @@ int GUIScrollList::Render(void) int fHeight = mRenderH - mHeaderH; // line - gr_color(mFastScrollLineColor.red, mFastScrollLineColor.green, mFastScrollLineColor.blue, 255); + gr_color(mFastScrollLineColor.red, mFastScrollLineColor.green, mFastScrollLineColor.blue, mFastScrollLineColor.alpha); gr_fill(startX + fWidth/2, mRenderY + mHeaderH, mFastScrollLineW, mRenderH - mHeaderH); // rect @@ -442,10 +343,12 @@ int GUIScrollList::Render(void) int mFastScrollRectX = startX + (fWidth - mFastScrollRectW)/2; int mFastScrollRectY = mRenderY+mHeaderH + ((fHeight - mFastScrollRectH)*pct)/100; - gr_color(mFastScrollRectColor.red, mFastScrollRectColor.green, mFastScrollRectColor.blue, 255); + gr_color(mFastScrollRectColor.red, mFastScrollRectColor.green, mFastScrollRectColor.blue, mFastScrollRectColor.alpha); gr_fill(mFastScrollRectX, mFastScrollRectY, mFastScrollRectW, mFastScrollRectH); } mUpdate = 0; + // reset clipping + gr_noclip(); return 0; } diff --git a/minuitwrp/graphics.c b/minuitwrp/graphics.c index 93123e40a..7160c7e2e 100644 --- a/minuitwrp/graphics.c +++ b/minuitwrp/graphics.c @@ -558,6 +558,20 @@ int gr_textExWH(int x, int y, const char *s, void* pFont, int max_width, int max return x; } +void gr_clip(int x, int y, int w, int h) +{ + GGLContext *gl = gr_context; + gl->scissor(gl, x, y, w, h); + gl->enable(gl, GGL_SCISSOR_TEST); +} + +void gr_noclip() +{ + GGLContext *gl = gr_context; + gl->scissor(gl, 0, 0, gr_fb_width(), gr_fb_height()); + gl->disable(gl, GGL_SCISSOR_TEST); +} + void gr_fill(int x, int y, int w, int h) { GGLContext *gl = gr_context; diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h index fff7ddb97..8ef04445c 100644 --- a/minuitwrp/minui.h +++ b/minuitwrp/minui.h @@ -36,6 +36,8 @@ void gr_flip(void); int gr_fb_blank(int blank); void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a); +void gr_clip(int x, int y, int w, int h); +void gr_noclip(); void gr_fill(int x, int y, int w, int h); int gr_textEx(int x, int y, const char *s, void* font); -- cgit v1.2.3