Files
android_bootable_recovery/gui/slidervalue.cpp
bigbiff d58ba18272 AOSP10 TWRP Merge: fix conflicts and update libraries needed
This allows flame to boot TWRP. Still will need to work on
super partition for vendor and system access.

The plan will be to cherry-pick any updates to android-9.0
through gerrit.twrp.me to this branch as a WIP.
2020-03-23 11:18:29 -04:00

445 lines
9.4 KiB
C++
Executable File

/*
Copyright 2012 to 2020 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 "../minuitwrp/truetype.hpp"
#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 twrpTruetype::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();
}