Allow text to scale to fit

Change-Id: Iacd4bb78f551b51d092ecde09521b5541e7dadcd
diff --git a/gui/button.cpp b/gui/button.cpp
index 18b5560..601a516 100644
--- a/gui/button.cpp
+++ b/gui/button.cpp
@@ -93,6 +93,23 @@
 		LoadPlacement(FindNode(node, "placement"), &x, &y, &w, &h, &TextPlacement);
 	}
 	SetRenderPos(x, y, w, h);
+	if (mButtonLabel) {
+		TextPlacement = (Placement)LoadAttrInt(FindNode(node, "placement"), "textplacement", TOP_LEFT);
+		if (TextPlacement != TEXT_ONLY_RIGHT) {
+			mButtonLabel->scaleWidth = 1;
+			mButtonLabel->SetMaxWidth(w);
+			mButtonLabel->SetPlacement(CENTER);
+			mTextX = ((mRenderW / 2) + mRenderX);
+			mTextY = mRenderY + (mRenderH / 2);
+			mButtonLabel->SetRenderPos(mTextX, mTextY);
+		} else {
+			mTextX = mRenderW + mRenderX + 5;
+			mRenderW += mTextW + 5;
+			mButtonLabel->GetCurrentBounds(mTextW, mTextH);
+			mTextY = mRenderY + (mRenderH / 2) - (mTextH / 2);
+			mButtonLabel->SetRenderPos(mTextX, mTextY);
+		}
+	}
 }
 
 GUIButton::~GUIButton()
@@ -125,15 +142,6 @@
 		mButtonLabel->GetCurrentBounds(w, h);
 		if (w != mTextW) {
 			mTextW = w;
-			if (TextPlacement == CENTER_X_ONLY) {
-				mTextX = ((mRenderW - mRenderX) / 2);
-			} else if (mTextW > mRenderW) { // As a special case, we'll allow large text which automatically moves it to the right.
-				mTextX = mRenderW + mRenderX + 5;
-				mRenderW += mTextW + 5;
-			} else {
-				mTextX = mRenderX + ((mRenderW - mTextW) / 2);
-			}
-			mButtonLabel->SetRenderPos(mTextX, mTextY);
 		}
 		ret = mButtonLabel->Render();
 		if (ret < 0)		return ret;
@@ -198,28 +206,19 @@
 	mTextW = 0;
 	mIconX = mRenderX + ((mRenderW - mIconW) / 2);
 	if (mButtonLabel)   mButtonLabel->GetCurrentBounds(mTextW, mTextH);
-	if (mTextW)
+	if (mTextW && TextPlacement == TEXT_ONLY_RIGHT)
 	{
-		if (TextPlacement == CENTER_X_ONLY) {
-			mTextX = ((mRenderW - mRenderX) / 2);
-		} else if (mTextW > mRenderW) { // As a special case, we'll allow large text which automatically moves it to the right.
-			mTextX = mRenderW + mRenderX + 5;
-			mRenderW += mTextW + 5;
-		} else {
-			mTextX = mRenderX + ((mRenderW - mTextW) / 2);
-		}
+		mRenderW += mTextW + 5;
 	}
 
 	if (mIconH == 0 || mTextH == 0 || mIconH + mTextH > mRenderH)
 	{
 		mIconY = mRenderY + (mRenderH / 2) - (mIconH / 2);
-		mTextY = mRenderY + (mRenderH / 2) - (mTextH / 2);
 	}
 	else
 	{
 		int divisor = mRenderH - (mIconH + mTextH);
 		mIconY = mRenderY + (divisor / 3);
-		mTextY = mRenderY + (divisor * 2 / 3) + mIconH;
 	}
 
 	if (mButtonLabel)   mButtonLabel->SetRenderPos(mTextX, mTextY);
diff --git a/gui/checkbox.cpp b/gui/checkbox.cpp
index 46a7708..8eb0f52 100644
--- a/gui/checkbox.cpp
+++ b/gui/checkbox.cpp
@@ -139,9 +139,11 @@
 	mRenderH = mCheckH;
 
 	mTextX = mRenderX + mCheckW + 5;
-	mTextY = mRenderY + ((mCheckH / 2) - (textH / 2));
+	mTextY = mRenderY + (mCheckH / 2);
 
 	mLabel->SetRenderPos(mTextX, mTextY, 0, 0);
+	mLabel->SetPlacement(TEXT_ONLY_RIGHT);
+	mLabel->SetMaxWidth(gr_fb_width() - mTextX);
 	SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
 	return 0;
 }
diff --git a/gui/console.cpp b/gui/console.cpp
index 1544d77..2d6414e 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -319,7 +319,7 @@
 
 	// render text
 	const char* text = rConsole[itemindex].c_str();
-	gr_textEx(mRenderX, yPos, text, mFont->GetResource());
+	gr_textEx_scaleW(mRenderX, yPos, text, mFont->GetResource(), mRenderW, TOP_LEFT, 0);
 }
 
 void GUIConsole::NotifySelect(size_t item_selected)
diff --git a/gui/devices/landscape/res/landscape.xml b/gui/devices/landscape/res/landscape.xml
index c75be3c..57406d9 100644
--- a/gui/devices/landscape/res/landscape.xml
+++ b/gui/devices/landscape/res/landscape.xml
@@ -990,7 +990,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col3_x%" y="%row10_text_y%" />
+				<placement x="%col3_x%" y="%row10_text_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_mount_system_ro" op="=" var2="0" />
 				<text>Only mount system read-only</text>
@@ -999,7 +999,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col3_x%" y="%row10_text_y%" />
+				<placement x="%col3_x%" y="%row10_text_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_mount_system_ro" op="!=" var2="0" />
 				<text>Only mount system read-only</text>
diff --git a/gui/devices/portrait/res/portrait.xml b/gui/devices/portrait/res/portrait.xml
index 969044c..db54e55 100644
--- a/gui/devices/portrait/res/portrait.xml
+++ b/gui/devices/portrait/res/portrait.xml
@@ -2125,7 +2125,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col1_x%" y="%system_ro_y%" />
+				<placement x="%col1_x%" y="%system_ro_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_mount_system_ro" op="=" var2="0" />
 				<text>Only mount system read-only</text>
@@ -2134,7 +2134,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col1_x%" y="%system_ro_y%" />
+				<placement x="%col1_x%" y="%system_ro_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_mount_system_ro" op="!=" var2="0" />
 				<text>Only mount system read-only</text>
diff --git a/gui/devices/watch/res/watch.xml b/gui/devices/watch/res/watch.xml
index 28198fb..00780d0 100644
--- a/gui/devices/watch/res/watch.xml
+++ b/gui/devices/watch/res/watch.xml
@@ -2133,7 +2133,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col1_x%" y="%system_ro_y%" />
+				<placement x="%col1_x%" y="%system_ro_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_mount_system_ro" op="=" var2="0" />
 				<text>Only mount system read-only</text>
@@ -2142,7 +2142,7 @@
 			</object>
 
 			<object type="button">
-				<placement x="%col1_x%" y="%system_ro_y%" />
+				<placement x="%col1_x%" y="%system_ro_y%" textplacement="6" />
 				<font resource="font" color="%text_color%" />
 				<condition var1="tw_mount_system_ro" op="!=" var2="0" />
 				<text>Only mount system read-only</text>
diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp
index f35a5d3..e55fb1b 100644
--- a/gui/keyboard.cpp
+++ b/gui/keyboard.cpp
@@ -326,7 +326,7 @@
 		int textH = labelFont->GetHeight();
 		int textX = keyX + (keyW - textW) / 2;
 		int textY = keyY + (keyH - textH) / 2;
-		gr_textEx(textX, textY, labelText.c_str(), fontResource);
+		gr_textEx_scaleW(textX, textY, labelText.c_str(), fontResource, keyW, TOP_LEFT, 0);
 	}
 
 	// longpress key label (only if font is defined)
@@ -339,7 +339,7 @@
 		int textW = gr_measureEx(text.c_str(), fontResource);
 		int textX = keyX + keyW - longpressOffsetX - textW;
 		int textY = keyY + longpressOffsetY;
-		gr_textEx(textX, textY, text.c_str(), fontResource);
+		gr_textEx_scaleW(textX, textY, text.c_str(), fontResource, keyW, TOP_LEFT, 0);
 	}
 }
 
diff --git a/gui/objects.hpp b/gui/objects.hpp
index 7028956..cf92024 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -34,6 +34,7 @@
 #include "resources.hpp"
 #include "pages.hpp"
 #include "../partitions.hpp"
+#include "placement.h"
 
 #ifndef TW_X_OFFSET
 #define TW_X_OFFSET 0
@@ -45,16 +46,6 @@
 class RenderObject
 {
 public:
-	enum Placement {
-		TOP_LEFT = 0,
-		TOP_RIGHT = 1,
-		BOTTOM_LEFT = 2,
-		BOTTOM_RIGHT = 3,
-		CENTER = 4,
-		CENTER_X_ONLY = 5,
-	};
-
-public:
 	RenderObject() { mRenderX = 0; mRenderY = 0; mRenderW = 0; mRenderH = 0; mPlacement = TOP_LEFT; }
 	virtual ~RenderObject() {}
 
@@ -207,6 +198,8 @@
 
 public:
 	bool isHighlighted;
+	bool scaleWidth;
+	unsigned maxWidth;
 
 protected:
 	std::string mText;
@@ -217,7 +210,6 @@
 	int mIsStatic;
 	int mVarChanged;
 	int mFontHeight;
-	unsigned maxWidth;
 	unsigned charSkip;
 };
 
@@ -1157,7 +1149,7 @@
 ImageResource* LoadAttrImage(xml_node<>* element, const char* attrname);
 AnimationResource* LoadAttrAnimation(xml_node<>* element, const char* attrname);
 
-bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w = NULL, int* h = NULL, RenderObject::Placement* placement = NULL);
+bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w = NULL, int* h = NULL, Placement* placement = NULL);
 
 #endif  // _OBJECTS_HEADER
 
diff --git a/gui/pages.cpp b/gui/pages.cpp
index 374a431..9bff289 100644
--- a/gui/pages.cpp
+++ b/gui/pages.cpp
@@ -229,7 +229,7 @@
 		return PageManager::GetResources()->FindAnimation(name);
 }
 
-bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
+bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, Placement* placement /* = NULL */)
 {
 	if (!node)
 		return false;
@@ -247,7 +247,7 @@
 		*h = LoadAttrIntScaleY(node, "h");
 
 	if (placement && node->first_attribute("placement"))
-		*placement = (RenderObject::Placement) LoadAttrInt(node, "placement");
+		*placement = (Placement) LoadAttrInt(node, "placement");
 
 	return true;
 }
diff --git a/gui/placement.h b/gui/placement.h
new file mode 100644
index 0000000..02079e8
--- /dev/null
+++ b/gui/placement.h
@@ -0,0 +1,32 @@
+/*
+	Copyright 2015 bigbiff/Dees_Troy TeamWin
+	This file is part of TWRP/TeamWin Recovery Project.
+
+	TWRP is free software: you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation, either version 3 of the License, or
+	(at your option) any later version.
+
+	TWRP is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __PLACEMENT_H
+#define __PLACEMENT_H
+
+enum Placement {
+	TOP_LEFT = 0,
+	TOP_RIGHT = 1,
+	BOTTOM_LEFT = 2,
+	BOTTOM_RIGHT = 3,
+	CENTER = 4,
+	CENTER_X_ONLY = 5,
+	TEXT_ONLY_RIGHT = 6,
+};
+
+#endif // __PLACEMENT_H
diff --git a/gui/scrolllist.cpp b/gui/scrolllist.cpp
index ec42fe6..7bd4598 100644
--- a/gui/scrolllist.cpp
+++ b/gui/scrolllist.cpp
@@ -266,7 +266,7 @@
 
 		// render the text
 		gr_color(mHeaderFontColor.red, mHeaderFontColor.green, mHeaderFontColor.blue, mHeaderFontColor.alpha);
-		gr_textEx(mRenderX + IconOffsetX + 5, yPos + (int)((mHeaderH - mFontHeight) / 2), mLastHeaderValue.c_str(), mFont->GetResource());
+		gr_textEx_scaleW(mRenderX + IconOffsetX + 5, yPos + (int)(mHeaderH / 2), mLastHeaderValue.c_str(), mFont->GetResource(), mRenderW, TEXT_ONLY_RIGHT, 0);
 
 		// Add the separator
 		gr_color(mHeaderSeparatorColor.red, mHeaderSeparatorColor.green, mHeaderSeparatorColor.blue, mHeaderSeparatorColor.alpha);
@@ -346,8 +346,8 @@
 
 	// render label text
 	int textX = mRenderX + maxIconWidth + 5;
-	int textY = yPos + (iconAndTextH - mFontHeight) / 2;
-	gr_textEx(textX, textY, text, mFont->GetResource());
+	int textY = yPos + (iconAndTextH / 2);
+	gr_textEx_scaleW(textX, textY, text, mFont->GetResource(), mRenderW, TEXT_ONLY_RIGHT, 0);
 }
 
 int GUIScrollList::Update(void)
diff --git a/gui/slider.cpp b/gui/slider.cpp
index a388447..6ee2024 100644
--- a/gui/slider.cpp
+++ b/gui/slider.cpp
@@ -80,6 +80,7 @@
 		sSliderLabel->GetCurrentBounds(w, h);
 		int sTextY = mRenderY + ((mRenderH - h) / 2);
 		sSliderLabel->SetRenderPos(sTextX, sTextY);
+		sSliderLabel->SetMaxWidth(mRenderW);
 	}
 	if (sTouch && sTouch->GetResource())
 	{
diff --git a/gui/slidervalue.cpp b/gui/slidervalue.cpp
index 3974c37..8a44a3c 100644
--- a/gui/slidervalue.cpp
+++ b/gui/slidervalue.cpp
@@ -307,15 +307,15 @@
 	if(mShowRange)
 	{
 		int rangeY = (mLineY - mLineH/2) - mFontHeight/2;
-		gr_textEx(mRenderX + mPadding/2, rangeY, mMinStr.c_str(), fontResource);
-		gr_textEx(mLineX + mLineW + mPadding/2, rangeY, mMaxStr.c_str(), fontResource);
+		gr_textEx_scaleW(mRenderX + mPadding/2, rangeY, mMinStr.c_str(), fontResource, mRenderW, TOP_LEFT, 0);
+		gr_textEx_scaleW(mLineX + mLineW + mPadding/2, rangeY, mMaxStr.c_str(), fontResource, mRenderW, TOP_LEFT, 0);
 	}
 
 	if(mValueStr && mShowCurr)
 	{
 		sprintf(mValueStr, "%d", mValue);
 		int textW = measureText(mValueStr);
-		gr_textEx(mRenderX + (mRenderW/2 - textW/2), mSliderY+mSliderH, mValueStr, fontResource);
+		gr_textEx_scaleW(mRenderX + (mRenderW/2 - textW/2), mSliderY+mSliderH, mValueStr, fontResource, mRenderW, TOP_LEFT, 0);
 	}
 
 	mRendered = true;
diff --git a/gui/text.cpp b/gui/text.cpp
index effb935..9898e28 100644
--- a/gui/text.cpp
+++ b/gui/text.cpp
@@ -34,7 +34,9 @@
 	mFontHeight = 0;
 	maxWidth = 0;
 	charSkip = 0;
+	scaleWidth = true;
 	isHighlighted = false;
+	mText = "";
 
 	if (!node)
 		return;
@@ -54,6 +56,23 @@
 	xml_node<>* child = FindNode(node, "text");
 	if (child)  mText = child->value();
 
+	child = FindNode(node, "noscaling");
+	if (child) {
+		scaleWidth = false;
+	} else {
+		if (mPlacement == TOP_LEFT || mPlacement == BOTTOM_LEFT) {
+			maxWidth = gr_fb_width() - mRenderX;
+		} else if (mPlacement == TOP_RIGHT || mPlacement == BOTTOM_RIGHT) {
+			maxWidth = mRenderX;
+		} else if (mPlacement == CENTER || mPlacement == CENTER_X_ONLY) {
+			if (mRenderX < gr_fb_width() / 2) {
+				maxWidth = mRenderX * 2;
+			} else {
+				maxWidth = (gr_fb_width() - mRenderX) * 2;
+			}
+		}
+	}
+
 	// Simple way to check for static state
 	mLastValue = gui_parse_text(mText);
 	if (mLastValue != mText)   mIsStatic = 0;
@@ -81,30 +100,13 @@
 	int x = mRenderX, y = mRenderY;
 	int width = gr_measureEx(displayValue.c_str(), fontResource);
 
-	if (mPlacement != TOP_LEFT && mPlacement != BOTTOM_LEFT)
-	{
-		if (mPlacement == CENTER || mPlacement == CENTER_X_ONLY)
-			x -= (width / 2);
-		else
-			x -= width;
-	}
-	if (mPlacement != TOP_LEFT && mPlacement != TOP_RIGHT)
-	{
-		if (mPlacement == CENTER)
-			y -= (mFontHeight / 2);
-		else if (mPlacement == BOTTOM_LEFT || mPlacement == BOTTOM_RIGHT)
-			y -= mFontHeight;
-	}
-
 	if (isHighlighted)
 		gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
 	else
 		gr_color(mColor.red, mColor.green, mColor.blue, mColor.alpha);
 
-	if (maxWidth)
-		gr_textExW(x, y, displayValue.c_str(), fontResource, maxWidth + x);
-	else
-		gr_textEx(x, y, displayValue.c_str(), fontResource);
+	gr_textEx_scaleW(mRenderX, mRenderY, displayValue.c_str(), fontResource, maxWidth, mPlacement, scaleWidth);
+
 	return 0;
 }