gui: support scrollable lists without headers
If the <header> 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
This commit is contained in:
+4
-5
@@ -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
|
||||
|
||||
+75
-172
@@ -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);
|
||||
mFastScrollLineColor = LoadAttrColor(child, "linecolor");
|
||||
mFastScrollRectColor = LoadAttrColor(child, "rectcolor");
|
||||
|
||||
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 = 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;
|
||||
|
||||
if (mHeaderIcon && mHeaderIcon->GetResource())
|
||||
{
|
||||
mHeaderIconWidth = mHeaderIcon->GetWidth();
|
||||
mHeaderIconHeight = mHeaderIcon->GetHeight();
|
||||
if (mHeaderIconHeight > mHeaderH)
|
||||
mHeaderH = mHeaderIconHeight;
|
||||
if (mHeaderIconWidth > maxIconWidth)
|
||||
maxIconWidth = mHeaderIconWidth;
|
||||
}
|
||||
|
||||
mHeaderH += mItemSpacing + mHeaderSeparatorH;
|
||||
actualItemHeight = mFontHeight + mItemSpacing + mSeparatorH;
|
||||
if (mHeaderH < actualItemHeight)
|
||||
mHeaderH = actualItemHeight;
|
||||
|
||||
// Load the header if it exists
|
||||
child = node->first_node("header");
|
||||
if (child)
|
||||
{
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user