summaryrefslogtreecommitdiffstats
path: root/gui/slidervalue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gui/slidervalue.cpp')
-rw-r--r--gui/slidervalue.cpp443
1 files changed, 443 insertions, 0 deletions
diff --git a/gui/slidervalue.cpp b/gui/slidervalue.cpp
new file mode 100644
index 000000000..3aaffcc05
--- /dev/null
+++ b/gui/slidervalue.cpp
@@ -0,0 +1,443 @@
+/*
+ Copyright 2017 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/>.
+*/
+
+// slidervalue.cpp - GUISliderValue object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+}
+#include "../minuitwrp/minui.h"
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUISliderValue::GUISliderValue(xml_node<>* node) : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ mMin = 0;
+ mMax = 100;
+ mValue = 0;
+ mLineH = 2;
+ mLinePadding = 10;
+ mSliderW = 5;
+ mSliderH = 30;
+ mLineX = 0;
+ mLineY = 0;
+ mValueStr = NULL;
+ mAction = NULL;
+ mShowCurr = true;
+ mShowRange = false;
+ mChangeOnDrag = false;
+ mRendered = false;
+ mBackgroundImage = NULL;
+ mHandleImage = NULL;
+ mHandleHoverImage = NULL;
+ mDragging = false;
+
+ mLabel = NULL;
+ ConvertStrToColor("white", &mTextColor);
+ ConvertStrToColor("white", &mLineColor);
+ ConvertStrToColor("blue", &mSliderColor);
+
+ if (!node)
+ {
+ LOGERR("GUISliderValue created without XML node\n");
+ return;
+ }
+
+ mLabel = new GUIText(node);
+ if (mLabel->Render() < 0)
+ {
+ delete mLabel;
+ mLabel = NULL;
+ }
+
+ mAction = new GUIAction(node);
+
+ child = FindNode(node, "font");
+ if (child)
+ {
+ mFont = LoadAttrFont(child, "resource");
+ mTextColor = LoadAttrColor(child, "color", mTextColor);
+ }
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW);
+
+ child = FindNode(node, "colors");
+ if (child)
+ {
+ mLineColor = LoadAttrColor(child, "line");
+ mSliderColor = LoadAttrColor(child, "slider");
+ }
+
+ child = FindNode(node, "resource");
+ if (child)
+ {
+ mBackgroundImage = LoadAttrImage(child, "background");
+ mHandleImage = LoadAttrImage(child, "handle");
+ mHandleHoverImage = LoadAttrImage(child, "handlehover");
+ }
+
+ child = FindNode(node, "data");
+ if (child)
+ {
+ attr = child->first_attribute("variable");
+ if (attr)
+ mVariable = attr->value();
+
+ attr = child->first_attribute("min");
+ if (attr)
+ {
+ mMinStr = gui_parse_text(attr->value());
+ mMin = atoi(mMinStr.c_str());
+ }
+
+ attr = child->first_attribute("max");
+ if (attr)
+ {
+ mMaxStr = gui_parse_text(attr->value());
+ mMax = atoi(mMaxStr.c_str());
+ }
+
+ if (mMin > mMax)
+ mMin = mMax;
+
+ attr = child->first_attribute("default");
+ if (attr)
+ {
+ string parsevalue = gui_parse_text(attr->value());
+ int def = atoi(parsevalue.c_str());
+
+ if (def < mMin)
+ def = mMin;
+ else if (def > mMax)
+ def = mMax;
+ DataManager::SetValue(mVariable, def);
+ }
+
+ attr = child->first_attribute("showrange");
+ if (attr)
+ mShowRange = atoi(attr->value());
+
+ attr = child->first_attribute("showcurr");
+ if (attr)
+ mShowCurr = atoi(attr->value());
+
+ attr = child->first_attribute("changeondrag");
+ if (attr)
+ mChangeOnDrag = atoi(attr->value());
+ }
+
+ child = FindNode(node, "dimensions");
+ if (child)
+ {
+ mLineH = LoadAttrIntScaleY(child, "lineh", mLineH);
+ mLinePadding = LoadAttrIntScaleX(child, "linepadding", mLinePadding);
+ mSliderW = LoadAttrIntScaleX(child, "sliderw", mSliderW);
+ mSliderH = LoadAttrIntScaleY(child, "sliderh", mSliderH);
+ }
+
+ if (mFont && mFont->GetResource())
+ mFontHeight = mFont->GetHeight();
+ else
+ mFontHeight = 0;
+
+ if (mShowCurr)
+ {
+ int maxLen = std::max(strlen(mMinStr.c_str()), strlen(mMaxStr.c_str()));
+ mValueStr = new char[maxLen+1];
+ }
+
+ loadValue(true);
+
+ if (mShowRange)
+ {
+ int textW = std::max(measureText(mMaxStr), measureText(mMinStr));
+ mLinePadding += textW;
+ }
+
+ SetRenderPos(mRenderX, mRenderY, mRenderW);
+}
+
+GUISliderValue::~GUISliderValue()
+{
+ delete mLabel;
+ delete mAction;
+ delete[] mValueStr;
+}
+
+void GUISliderValue::loadValue(bool force)
+{
+ if (!mVariable.empty())
+ {
+ int value = DataManager::GetIntValue(mVariable);
+ if (mValue == value && !force)
+ return;
+
+ mValue = value;
+ }
+
+ mValue = std::max(mValue, mMin);
+ mValue = std::min(mValue, mMax);
+ mValuePct = pctFromValue(mValue);
+ mRendered = false;
+}
+
+int GUISliderValue::SetRenderPos(int x, int y, int w, int h)
+{
+ mRenderX = x;
+ mRenderY = y;
+ if (w || h)
+ {
+ mRenderW = w;
+ mRenderH = h;
+ }
+
+ mRenderH = mSliderH;
+ if (mShowCurr)
+ mRenderH += mFontHeight;
+
+ if (mLabel)
+ {
+ int lw, lh;
+ mLabel->GetCurrentBounds(lw, lh);
+ int textX = mRenderX + (mRenderW/2 - lw/2);
+
+ mLabel->SetRenderPos(textX, mRenderY);
+
+ y += lh;
+ mRenderH += lh;
+ }
+
+ mSliderY = y;
+
+ mActionX = mRenderX;
+ mActionY = mRenderY;
+ mActionW = mRenderW;
+ mActionH = mRenderH;
+
+ if (mBackgroundImage && mBackgroundImage->GetResource())
+ {
+ mLineW = mBackgroundImage->GetWidth();
+ mLineH = mBackgroundImage->GetHeight();
+ }
+ else
+ mLineW = mRenderW - (mLinePadding * 2);
+
+ mLineY = y + (mSliderH/2 - mLineH/2);
+ mLineX = mRenderX + (mRenderW/2 - mLineW/2);
+
+ return 0;
+}
+
+int GUISliderValue::measureText(const std::string& str)
+{
+ void* fontResource = NULL;
+ if (mFont) fontResource = mFont->GetResource();
+
+ return gr_ttf_measureEx(str.c_str(), fontResource);
+}
+
+int GUISliderValue::Render(void)
+{
+ if (!isConditionTrue())
+ {
+ mRendered = false;
+ return 0;
+ }
+
+ if (mLabel)
+ {
+ int w, h;
+ mLabel->GetCurrentBounds(w, h);
+ if (w != mLabelW) {
+ mLabelW = w;
+ int textX = mRenderX + (mRenderW/2 - mLabelW/2);
+ mLabel->SetRenderPos(textX, mRenderY);
+ }
+ int res = mLabel->Render();
+ if (res < 0)
+ return res;
+ }
+
+ // line
+ if (mBackgroundImage && mBackgroundImage->GetResource())
+ {
+ gr_blit(mBackgroundImage->GetResource(), 0, 0, mLineW, mLineH, mLineX, mLineY);
+ }
+ else
+ {
+ gr_color(mLineColor.red, mLineColor.green, mLineColor.blue, mLineColor.alpha);
+ gr_fill(mLineX, mLineY, mLineW, mLineH);
+ }
+
+ // slider
+ uint32_t sliderX = mLineX + (mValuePct*(mLineW - mSliderW))/100;
+
+ if (mHandleImage && mHandleImage->GetResource())
+ {
+ gr_surface s = mHandleImage->GetResource();
+ if (mDragging && mHandleHoverImage && mHandleHoverImage->GetResource())
+ s = mHandleHoverImage->GetResource();
+ gr_blit(s, 0, 0, mSliderW, mSliderH, sliderX, mLineY + (mLineH/2 - mSliderH/2));
+ }
+ else
+ {
+ gr_color(mSliderColor.red, mSliderColor.green, mSliderColor.blue, mSliderColor.alpha);
+ gr_fill(sliderX, mSliderY, mSliderW, mSliderH);
+ }
+
+ void *fontResource = NULL;
+ if (mFont) fontResource = mFont->GetResource();
+ gr_color(mTextColor.red, mTextColor.green, mTextColor.blue, mTextColor.alpha);
+ if (mShowRange)
+ {
+ int rangeY = (mLineY - mLineH/2) - mFontHeight/2;
+ 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_scaleW(mRenderX + (mRenderW/2 - textW/2), mSliderY+mSliderH, mValueStr, fontResource, mRenderW, TOP_LEFT, 0);
+ }
+
+ mRendered = true;
+ return 0;
+}
+
+int GUISliderValue::Update(void)
+{
+ if (!isConditionTrue())
+ return mRendered ? 2 : 0;
+ if (!mRendered)
+ return 2;
+
+ if (mLabel)
+ return mLabel->Update();
+ return 0;
+}
+
+int GUISliderValue::valueFromPct(float pct)
+{
+ int range = abs(mMax - mMin);
+ return mMin + (pct * range) / 100;
+}
+
+float GUISliderValue::pctFromValue(int value)
+{
+ return float((value - mMin) * 100) / abs(mMax - mMin);
+}
+
+int GUISliderValue::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if (!isConditionTrue())
+ return -1;
+
+ switch (state)
+ {
+ case TOUCH_START:
+ if (x >= mLineX && x <= mLineX + mLineW &&
+ y >= mRenderY && y <= mRenderY + mRenderH)
+ {
+ mDragging = true;
+ }
+ // no break
+ case TOUCH_DRAG:
+ {
+ if (!mDragging) return 0;
+
+ x = std::max(mLineX + mSliderW/2, x);
+ x = std::min(mLineX + mLineW - mSliderW/2, x);
+
+ mValuePct = float(((x - (mLineX + mSliderW/2)) * 100) / (mLineW - mSliderW));
+ int newVal = valueFromPct(mValuePct);
+ if (newVal != mValue) {
+ mRendered = false;
+ mValue = newVal;
+ if (mChangeOnDrag) {
+ if (!mVariable.empty())
+ DataManager::SetValue(mVariable, mValue);
+ if (mAction)
+ mAction->doActions();
+ }
+ }
+ break;
+ }
+ case TOUCH_RELEASE:
+ {
+ if (!mDragging) return 0;
+ mDragging = false;
+
+ if (!mVariable.empty())
+ DataManager::SetValue(mVariable, mValue);
+ if (mAction)
+ mAction->doActions();
+ break;
+ }
+ case TOUCH_REPEAT:
+ case TOUCH_HOLD:
+ break;
+ }
+ return 0;
+}
+
+int GUISliderValue::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIObject::NotifyVarChange(varName, value);
+
+ if (mLabel)
+ mLabel->NotifyVarChange(varName, value);
+ if (varName == mVariable) {
+ int newVal = atoi(value.c_str());
+ if (newVal != mValue) {
+ mValue = newVal;
+ mValuePct = pctFromValue(mValue);
+ mRendered = false;
+ }
+ }
+ return 0;
+}
+
+void GUISliderValue::SetPageFocus(int inFocus)
+{
+ if (inFocus)
+ loadValue();
+}