blob: 8deb9e081ef7933e6fe7b3179a673a4083153974 [file] [log] [blame]
Matt Mowere04eee72016-12-31 00:38:57 -06001/*
bigbiffd58ba182020-03-23 10:02:29 -04002 Copyright 2012 to 2020 TeamWin
Matt Mowere04eee72016-12-31 00:38:57 -06003 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
18
Vojtech Bocek85932342013-04-01 22:11:33 +020019// slidervalue.cpp - GUISliderValue object
20
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <fcntl.h>
26#include <sys/reboot.h>
27#include <sys/stat.h>
28#include <sys/time.h>
29#include <sys/mman.h>
30#include <sys/types.h>
31#include <sys/ioctl.h>
32#include <time.h>
33#include <unistd.h>
34#include <stdlib.h>
35
36#include <string>
37
38extern "C" {
39#include "../twcommon.h"
Vojtech Bocek85932342013-04-01 22:11:33 +020040}
bigbiffd81833a2021-01-17 11:06:57 -050041#include "minuitwrp/minui.h"
42#include "minuitwrp/truetype.hpp"
Vojtech Bocek85932342013-04-01 22:11:33 +020043
44#include "rapidxml.hpp"
45#include "objects.hpp"
46
Vojtech Bocekede51c52014-02-07 23:58:09 +010047GUISliderValue::GUISliderValue(xml_node<>* node) : GUIObject(node)
Vojtech Bocek85932342013-04-01 22:11:33 +020048{
49 xml_attribute<>* attr;
50 xml_node<>* child;
51
52 mMin = 0;
53 mMax = 100;
54 mValue = 0;
55 mLineH = 2;
56 mLinePadding = 10;
57 mSliderW = 5;
58 mSliderH = 30;
59 mLineX = 0;
60 mLineY = 0;
61 mValueStr = NULL;
62 mAction = NULL;
63 mShowCurr = true;
64 mShowRange = false;
65 mChangeOnDrag = false;
66 mRendered = false;
Vojtech Bocek18d7c982014-08-04 17:19:28 +020067 mBackgroundImage = NULL;
68 mHandleImage = NULL;
69 mHandleHoverImage = NULL;
70 mDragging = false;
Vojtech Bocek85932342013-04-01 22:11:33 +020071
72 mLabel = NULL;
73 ConvertStrToColor("white", &mTextColor);
74 ConvertStrToColor("white", &mLineColor);
75 ConvertStrToColor("blue", &mSliderColor);
76
77 if (!node)
78 {
79 LOGERR("GUISliderValue created without XML node\n");
80 return;
81 }
82
83 mLabel = new GUIText(node);
Matt Mowera8a89d12016-12-30 18:10:37 -060084 if (mLabel->Render() < 0)
Vojtech Bocek85932342013-04-01 22:11:33 +020085 {
86 delete mLabel;
87 mLabel = NULL;
88 }
89
90 mAction = new GUIAction(node);
91
Ethan Yonker21ff02a2015-02-18 14:35:00 -060092 child = FindNode(node, "font");
Vojtech Bocek85932342013-04-01 22:11:33 +020093 if (child)
94 {
thatf6ed8fc2015-02-14 20:23:16 +010095 mFont = LoadAttrFont(child, "resource");
96 mTextColor = LoadAttrColor(child, "color", mTextColor);
Vojtech Bocek85932342013-04-01 22:11:33 +020097 }
98
99 // Load the placement
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600100 LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW);
Vojtech Bocek85932342013-04-01 22:11:33 +0200101
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600102 child = FindNode(node, "colors");
Vojtech Bocek85932342013-04-01 22:11:33 +0200103 if (child)
104 {
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600105 mLineColor = LoadAttrColor(child, "line");
106 mSliderColor = LoadAttrColor(child, "slider");
Vojtech Bocek85932342013-04-01 22:11:33 +0200107 }
108
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600109 child = FindNode(node, "resource");
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200110 if (child)
111 {
thatf6ed8fc2015-02-14 20:23:16 +0100112 mBackgroundImage = LoadAttrImage(child, "background");
113 mHandleImage = LoadAttrImage(child, "handle");
114 mHandleHoverImage = LoadAttrImage(child, "handlehover");
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200115 }
116
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600117 child = FindNode(node, "data");
Vojtech Bocek85932342013-04-01 22:11:33 +0200118 if (child)
119 {
120 attr = child->first_attribute("variable");
121 if (attr)
122 mVariable = attr->value();
123
124 attr = child->first_attribute("min");
125 if (attr)
126 {
127 mMinStr = gui_parse_text(attr->value());
128 mMin = atoi(mMinStr.c_str());
129 }
130
131 attr = child->first_attribute("max");
132 if (attr)
133 {
134 mMaxStr = gui_parse_text(attr->value());
135 mMax = atoi(mMaxStr.c_str());
136 }
137
138 if (mMin > mMax)
139 mMin = mMax;
140
141 attr = child->first_attribute("default");
142 if (attr)
143 {
144 string parsevalue = gui_parse_text(attr->value());
145 int def = atoi(parsevalue.c_str());
146
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500147 if (def < mMin)
148 def = mMin;
149 else if (def > mMax)
150 def = mMax;
Vojtech Bocek85932342013-04-01 22:11:33 +0200151 DataManager::SetValue(mVariable, def);
152 }
153
154 attr = child->first_attribute("showrange");
155 if (attr)
156 mShowRange = atoi(attr->value());
157
158 attr = child->first_attribute("showcurr");
159 if (attr)
160 mShowCurr = atoi(attr->value());
161
162 attr = child->first_attribute("changeondrag");
163 if (attr)
164 mChangeOnDrag = atoi(attr->value());
165 }
166
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600167 child = FindNode(node, "dimensions");
Vojtech Bocek85932342013-04-01 22:11:33 +0200168 if (child)
169 {
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600170 mLineH = LoadAttrIntScaleY(child, "lineh", mLineH);
171 mLinePadding = LoadAttrIntScaleX(child, "linepadding", mLinePadding);
172 mSliderW = LoadAttrIntScaleX(child, "sliderw", mSliderW);
173 mSliderH = LoadAttrIntScaleY(child, "sliderh", mSliderH);
Vojtech Bocek85932342013-04-01 22:11:33 +0200174 }
175
Ethan Yonker58f21322018-08-24 11:17:36 -0500176 if (mFont && mFont->GetResource())
177 mFontHeight = mFont->GetHeight();
178 else
179 mFontHeight = 0;
Vojtech Bocek85932342013-04-01 22:11:33 +0200180
Matt Mowera8a89d12016-12-30 18:10:37 -0600181 if (mShowCurr)
Vojtech Bocek85932342013-04-01 22:11:33 +0200182 {
183 int maxLen = std::max(strlen(mMinStr.c_str()), strlen(mMaxStr.c_str()));
184 mValueStr = new char[maxLen+1];
185 }
186
187 loadValue(true);
188
Vojtech Bocek85932342013-04-01 22:11:33 +0200189 if (mShowRange)
190 {
191 int textW = std::max(measureText(mMaxStr), measureText(mMinStr));
192 mLinePadding += textW;
193 }
194
195 SetRenderPos(mRenderX, mRenderY, mRenderW);
196}
197
198GUISliderValue::~GUISliderValue()
199{
200 delete mLabel;
201 delete mAction;
202 delete[] mValueStr;
203}
204
205void GUISliderValue::loadValue(bool force)
206{
Matt Mowera8a89d12016-12-30 18:10:37 -0600207 if (!mVariable.empty())
Vojtech Bocek85932342013-04-01 22:11:33 +0200208 {
209 int value = DataManager::GetIntValue(mVariable);
Matt Mowera8a89d12016-12-30 18:10:37 -0600210 if (mValue == value && !force)
Vojtech Bocek85932342013-04-01 22:11:33 +0200211 return;
212
213 mValue = value;
214 }
215
216 mValue = std::max(mValue, mMin);
217 mValue = std::min(mValue, mMax);
218 mValuePct = pctFromValue(mValue);
219 mRendered = false;
220}
221
222int GUISliderValue::SetRenderPos(int x, int y, int w, int h)
223{
224 mRenderX = x;
225 mRenderY = y;
226 if (w || h)
227 {
228 mRenderW = w;
229 mRenderH = h;
230 }
231
232 mRenderH = mSliderH;
Matt Mowera8a89d12016-12-30 18:10:37 -0600233 if (mShowCurr)
Vojtech Bocek85932342013-04-01 22:11:33 +0200234 mRenderH += mFontHeight;
235
236 if (mLabel)
237 {
238 int lw, lh;
239 mLabel->GetCurrentBounds(lw, lh);
240 int textX = mRenderX + (mRenderW/2 - lw/2);
241
242 mLabel->SetRenderPos(textX, mRenderY);
243
244 y += lh;
245 mRenderH += lh;
246 }
247
248 mSliderY = y;
Vojtech Bocek85932342013-04-01 22:11:33 +0200249
250 mActionX = mRenderX;
251 mActionY = mRenderY;
252 mActionW = mRenderW;
253 mActionH = mRenderH;
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200254
Matt Mowera8a89d12016-12-30 18:10:37 -0600255 if (mBackgroundImage && mBackgroundImage->GetResource())
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200256 {
thatf6ed8fc2015-02-14 20:23:16 +0100257 mLineW = mBackgroundImage->GetWidth();
258 mLineH = mBackgroundImage->GetHeight();
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200259 }
260 else
261 mLineW = mRenderW - (mLinePadding * 2);
262
263 mLineY = y + (mSliderH/2 - mLineH/2);
264 mLineX = mRenderX + (mRenderW/2 - mLineW/2);
Vojtech Bocek85932342013-04-01 22:11:33 +0200265
266 return 0;
267}
268
269int GUISliderValue::measureText(const std::string& str)
270{
271 void* fontResource = NULL;
272 if (mFont) fontResource = mFont->GetResource();
273
bigbiffd58ba182020-03-23 10:02:29 -0400274 return twrpTruetype::gr_ttf_measureEx(str.c_str(), fontResource);
Vojtech Bocek85932342013-04-01 22:11:33 +0200275}
276
277int GUISliderValue::Render(void)
278{
279 if (!isConditionTrue())
280 {
281 mRendered = false;
282 return 0;
283 }
284
Matt Mowera8a89d12016-12-30 18:10:37 -0600285 if (mLabel)
Vojtech Bocek85932342013-04-01 22:11:33 +0200286 {
287 int w, h;
288 mLabel->GetCurrentBounds(w, h);
289 if (w != mLabelW) {
290 mLabelW = w;
291 int textX = mRenderX + (mRenderW/2 - mLabelW/2);
292 mLabel->SetRenderPos(textX, mRenderY);
293 }
294 int res = mLabel->Render();
Matt Mowera8a89d12016-12-30 18:10:37 -0600295 if (res < 0)
Vojtech Bocek85932342013-04-01 22:11:33 +0200296 return res;
297 }
298
299 // line
Matt Mowera8a89d12016-12-30 18:10:37 -0600300 if (mBackgroundImage && mBackgroundImage->GetResource())
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200301 {
302 gr_blit(mBackgroundImage->GetResource(), 0, 0, mLineW, mLineH, mLineX, mLineY);
303 }
304 else
305 {
306 gr_color(mLineColor.red, mLineColor.green, mLineColor.blue, mLineColor.alpha);
307 gr_fill(mLineX, mLineY, mLineW, mLineH);
308 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200309
310 // slider
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200311 uint32_t sliderX = mLineX + (mValuePct*(mLineW - mSliderW))/100;
Vojtech Bocek85932342013-04-01 22:11:33 +0200312
Matt Mowera8a89d12016-12-30 18:10:37 -0600313 if (mHandleImage && mHandleImage->GetResource())
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200314 {
315 gr_surface s = mHandleImage->GetResource();
Matt Mowera8a89d12016-12-30 18:10:37 -0600316 if (mDragging && mHandleHoverImage && mHandleHoverImage->GetResource())
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200317 s = mHandleHoverImage->GetResource();
318 gr_blit(s, 0, 0, mSliderW, mSliderH, sliderX, mLineY + (mLineH/2 - mSliderH/2));
319 }
320 else
321 {
322 gr_color(mSliderColor.red, mSliderColor.green, mSliderColor.blue, mSliderColor.alpha);
323 gr_fill(sliderX, mSliderY, mSliderW, mSliderH);
324 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200325
326 void *fontResource = NULL;
Matt Mowera8a89d12016-12-30 18:10:37 -0600327 if (mFont) fontResource = mFont->GetResource();
Vojtech Bocek85932342013-04-01 22:11:33 +0200328 gr_color(mTextColor.red, mTextColor.green, mTextColor.blue, mTextColor.alpha);
Matt Mowera8a89d12016-12-30 18:10:37 -0600329 if (mShowRange)
Vojtech Bocek85932342013-04-01 22:11:33 +0200330 {
331 int rangeY = (mLineY - mLineH/2) - mFontHeight/2;
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500332 gr_textEx_scaleW(mRenderX + mPadding/2, rangeY, mMinStr.c_str(), fontResource, mRenderW, TOP_LEFT, 0);
333 gr_textEx_scaleW(mLineX + mLineW + mPadding/2, rangeY, mMaxStr.c_str(), fontResource, mRenderW, TOP_LEFT, 0);
Vojtech Bocek85932342013-04-01 22:11:33 +0200334 }
335
Matt Mowera8a89d12016-12-30 18:10:37 -0600336 if (mValueStr && mShowCurr)
Vojtech Bocek85932342013-04-01 22:11:33 +0200337 {
338 sprintf(mValueStr, "%d", mValue);
339 int textW = measureText(mValueStr);
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500340 gr_textEx_scaleW(mRenderX + (mRenderW/2 - textW/2), mSliderY+mSliderH, mValueStr, fontResource, mRenderW, TOP_LEFT, 0);
Vojtech Bocek85932342013-04-01 22:11:33 +0200341 }
342
343 mRendered = true;
344 return 0;
345}
346
347int GUISliderValue::Update(void)
348{
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500349 if (!isConditionTrue())
350 return mRendered ? 2 : 0;
351 if (!mRendered)
352 return 2;
Vojtech Bocek85932342013-04-01 22:11:33 +0200353
Matt Mowera8a89d12016-12-30 18:10:37 -0600354 if (mLabel)
Vojtech Bocek85932342013-04-01 22:11:33 +0200355 return mLabel->Update();
356 return 0;
357}
358
359int GUISliderValue::valueFromPct(float pct)
360{
361 int range = abs(mMax - mMin);
362 return mMin + (pct * range) / 100;
363}
364
365float GUISliderValue::pctFromValue(int value)
366{
367 return float((value - mMin) * 100) / abs(mMax - mMin);
368}
369
370int GUISliderValue::NotifyTouch(TOUCH_STATE state, int x, int y)
371{
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500372 if (!isConditionTrue())
373 return -1;
Vojtech Bocek85932342013-04-01 22:11:33 +0200374
Vojtech Bocek85932342013-04-01 22:11:33 +0200375 switch (state)
376 {
377 case TOUCH_START:
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200378 if (x >= mLineX && x <= mLineX + mLineW &&
Vojtech Bocek85932342013-04-01 22:11:33 +0200379 y >= mRenderY && y <= mRenderY + mRenderH)
380 {
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200381 mDragging = true;
Vojtech Bocek85932342013-04-01 22:11:33 +0200382 }
383 // no break
384 case TOUCH_DRAG:
385 {
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200386 if (!mDragging) return 0;
Vojtech Bocek85932342013-04-01 22:11:33 +0200387
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200388 x = std::max(mLineX + mSliderW/2, x);
389 x = std::min(mLineX + mLineW - mSliderW/2, x);
Vojtech Bocek85932342013-04-01 22:11:33 +0200390
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200391 mValuePct = float(((x - (mLineX + mSliderW/2)) * 100) / (mLineW - mSliderW));
Vojtech Bocek85932342013-04-01 22:11:33 +0200392 int newVal = valueFromPct(mValuePct);
393 if (newVal != mValue) {
394 mRendered = false;
395 mValue = newVal;
396 if (mChangeOnDrag) {
397 if (!mVariable.empty())
398 DataManager::SetValue(mVariable, mValue);
399 if (mAction)
400 mAction->doActions();
401 }
402 }
403 break;
404 }
405 case TOUCH_RELEASE:
406 {
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200407 if (!mDragging) return 0;
408 mDragging = false;
Vojtech Bocek85932342013-04-01 22:11:33 +0200409
410 if (!mVariable.empty())
411 DataManager::SetValue(mVariable, mValue);
412 if (mAction)
413 mAction->doActions();
414 break;
415 }
416 case TOUCH_REPEAT:
417 case TOUCH_HOLD:
418 break;
419 }
420 return 0;
421}
422
Vojtech Bocek07220562014-02-08 02:05:33 +0100423int GUISliderValue::NotifyVarChange(const std::string& varName, const std::string& value)
Vojtech Bocek85932342013-04-01 22:11:33 +0200424{
Vojtech Bocek07220562014-02-08 02:05:33 +0100425 GUIObject::NotifyVarChange(varName, value);
426
Vojtech Bocek85932342013-04-01 22:11:33 +0200427 if (mLabel)
428 mLabel->NotifyVarChange(varName, value);
429 if (varName == mVariable) {
430 int newVal = atoi(value.c_str());
Matt Mowera8a89d12016-12-30 18:10:37 -0600431 if (newVal != mValue) {
Vojtech Bocek85932342013-04-01 22:11:33 +0200432 mValue = newVal;
433 mValuePct = pctFromValue(mValue);
434 mRendered = false;
435 }
436 }
437 return 0;
438}
439
440void GUISliderValue::SetPageFocus(int inFocus)
441{
442 if (inFocus)
443 loadValue();
444}