blob: 6f007e23b1ab53a72c514644d7a79372813a705a [file] [log] [blame]
Matt Mowere04eee72016-12-31 00:38:57 -06001/*
2 Copyright 2017 TeamWin
3 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}
Ethan Yonkerfbb43532015-12-28 21:54:50 +010041#include "../minuitwrp/minui.h"
Vojtech Bocek85932342013-04-01 22:11:33 +020042
43#include "rapidxml.hpp"
44#include "objects.hpp"
45
Vojtech Bocekede51c52014-02-07 23:58:09 +010046GUISliderValue::GUISliderValue(xml_node<>* node) : GUIObject(node)
Vojtech Bocek85932342013-04-01 22:11:33 +020047{
48 xml_attribute<>* attr;
49 xml_node<>* child;
50
51 mMin = 0;
52 mMax = 100;
53 mValue = 0;
54 mLineH = 2;
55 mLinePadding = 10;
56 mSliderW = 5;
57 mSliderH = 30;
58 mLineX = 0;
59 mLineY = 0;
60 mValueStr = NULL;
61 mAction = NULL;
62 mShowCurr = true;
63 mShowRange = false;
64 mChangeOnDrag = false;
65 mRendered = false;
Vojtech Bocek18d7c982014-08-04 17:19:28 +020066 mBackgroundImage = NULL;
67 mHandleImage = NULL;
68 mHandleHoverImage = NULL;
69 mDragging = false;
Vojtech Bocek85932342013-04-01 22:11:33 +020070
71 mLabel = NULL;
72 ConvertStrToColor("white", &mTextColor);
73 ConvertStrToColor("white", &mLineColor);
74 ConvertStrToColor("blue", &mSliderColor);
75
76 if (!node)
77 {
78 LOGERR("GUISliderValue created without XML node\n");
79 return;
80 }
81
82 mLabel = new GUIText(node);
Matt Mowera8a89d12016-12-30 18:10:37 -060083 if (mLabel->Render() < 0)
Vojtech Bocek85932342013-04-01 22:11:33 +020084 {
85 delete mLabel;
86 mLabel = NULL;
87 }
88
89 mAction = new GUIAction(node);
90
Ethan Yonker21ff02a2015-02-18 14:35:00 -060091 child = FindNode(node, "font");
Vojtech Bocek85932342013-04-01 22:11:33 +020092 if (child)
93 {
thatf6ed8fc2015-02-14 20:23:16 +010094 mFont = LoadAttrFont(child, "resource");
95 mTextColor = LoadAttrColor(child, "color", mTextColor);
Vojtech Bocek85932342013-04-01 22:11:33 +020096 }
97
98 // Load the placement
Ethan Yonker21ff02a2015-02-18 14:35:00 -060099 LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW);
Vojtech Bocek85932342013-04-01 22:11:33 +0200100
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600101 child = FindNode(node, "colors");
Vojtech Bocek85932342013-04-01 22:11:33 +0200102 if (child)
103 {
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600104 mLineColor = LoadAttrColor(child, "line");
105 mSliderColor = LoadAttrColor(child, "slider");
Vojtech Bocek85932342013-04-01 22:11:33 +0200106 }
107
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600108 child = FindNode(node, "resource");
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200109 if (child)
110 {
thatf6ed8fc2015-02-14 20:23:16 +0100111 mBackgroundImage = LoadAttrImage(child, "background");
112 mHandleImage = LoadAttrImage(child, "handle");
113 mHandleHoverImage = LoadAttrImage(child, "handlehover");
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200114 }
115
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600116 child = FindNode(node, "data");
Vojtech Bocek85932342013-04-01 22:11:33 +0200117 if (child)
118 {
119 attr = child->first_attribute("variable");
120 if (attr)
121 mVariable = attr->value();
122
123 attr = child->first_attribute("min");
124 if (attr)
125 {
126 mMinStr = gui_parse_text(attr->value());
127 mMin = atoi(mMinStr.c_str());
128 }
129
130 attr = child->first_attribute("max");
131 if (attr)
132 {
133 mMaxStr = gui_parse_text(attr->value());
134 mMax = atoi(mMaxStr.c_str());
135 }
136
137 if (mMin > mMax)
138 mMin = mMax;
139
140 attr = child->first_attribute("default");
141 if (attr)
142 {
143 string parsevalue = gui_parse_text(attr->value());
144 int def = atoi(parsevalue.c_str());
145
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500146 if (def < mMin)
147 def = mMin;
148 else if (def > mMax)
149 def = mMax;
Vojtech Bocek85932342013-04-01 22:11:33 +0200150 DataManager::SetValue(mVariable, def);
151 }
152
153 attr = child->first_attribute("showrange");
154 if (attr)
155 mShowRange = atoi(attr->value());
156
157 attr = child->first_attribute("showcurr");
158 if (attr)
159 mShowCurr = atoi(attr->value());
160
161 attr = child->first_attribute("changeondrag");
162 if (attr)
163 mChangeOnDrag = atoi(attr->value());
164 }
165
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600166 child = FindNode(node, "dimensions");
Vojtech Bocek85932342013-04-01 22:11:33 +0200167 if (child)
168 {
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600169 mLineH = LoadAttrIntScaleY(child, "lineh", mLineH);
170 mLinePadding = LoadAttrIntScaleX(child, "linepadding", mLinePadding);
171 mSliderW = LoadAttrIntScaleX(child, "sliderw", mSliderW);
172 mSliderH = LoadAttrIntScaleY(child, "sliderh", mSliderH);
Vojtech Bocek85932342013-04-01 22:11:33 +0200173 }
174
thatf6ed8fc2015-02-14 20:23:16 +0100175 mFontHeight = mFont->GetHeight();
Vojtech Bocek85932342013-04-01 22:11:33 +0200176
Matt Mowera8a89d12016-12-30 18:10:37 -0600177 if (mShowCurr)
Vojtech Bocek85932342013-04-01 22:11:33 +0200178 {
179 int maxLen = std::max(strlen(mMinStr.c_str()), strlen(mMaxStr.c_str()));
180 mValueStr = new char[maxLen+1];
181 }
182
183 loadValue(true);
184
Vojtech Bocek85932342013-04-01 22:11:33 +0200185 if (mShowRange)
186 {
187 int textW = std::max(measureText(mMaxStr), measureText(mMinStr));
188 mLinePadding += textW;
189 }
190
191 SetRenderPos(mRenderX, mRenderY, mRenderW);
192}
193
194GUISliderValue::~GUISliderValue()
195{
196 delete mLabel;
197 delete mAction;
198 delete[] mValueStr;
199}
200
201void GUISliderValue::loadValue(bool force)
202{
Matt Mowera8a89d12016-12-30 18:10:37 -0600203 if (!mVariable.empty())
Vojtech Bocek85932342013-04-01 22:11:33 +0200204 {
205 int value = DataManager::GetIntValue(mVariable);
Matt Mowera8a89d12016-12-30 18:10:37 -0600206 if (mValue == value && !force)
Vojtech Bocek85932342013-04-01 22:11:33 +0200207 return;
208
209 mValue = value;
210 }
211
212 mValue = std::max(mValue, mMin);
213 mValue = std::min(mValue, mMax);
214 mValuePct = pctFromValue(mValue);
215 mRendered = false;
216}
217
218int GUISliderValue::SetRenderPos(int x, int y, int w, int h)
219{
220 mRenderX = x;
221 mRenderY = y;
222 if (w || h)
223 {
224 mRenderW = w;
225 mRenderH = h;
226 }
227
228 mRenderH = mSliderH;
Matt Mowera8a89d12016-12-30 18:10:37 -0600229 if (mShowCurr)
Vojtech Bocek85932342013-04-01 22:11:33 +0200230 mRenderH += mFontHeight;
231
232 if (mLabel)
233 {
234 int lw, lh;
235 mLabel->GetCurrentBounds(lw, lh);
236 int textX = mRenderX + (mRenderW/2 - lw/2);
237
238 mLabel->SetRenderPos(textX, mRenderY);
239
240 y += lh;
241 mRenderH += lh;
242 }
243
244 mSliderY = y;
Vojtech Bocek85932342013-04-01 22:11:33 +0200245
246 mActionX = mRenderX;
247 mActionY = mRenderY;
248 mActionW = mRenderW;
249 mActionH = mRenderH;
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200250
Matt Mowera8a89d12016-12-30 18:10:37 -0600251 if (mBackgroundImage && mBackgroundImage->GetResource())
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200252 {
thatf6ed8fc2015-02-14 20:23:16 +0100253 mLineW = mBackgroundImage->GetWidth();
254 mLineH = mBackgroundImage->GetHeight();
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200255 }
256 else
257 mLineW = mRenderW - (mLinePadding * 2);
258
259 mLineY = y + (mSliderH/2 - mLineH/2);
260 mLineX = mRenderX + (mRenderW/2 - mLineW/2);
Vojtech Bocek85932342013-04-01 22:11:33 +0200261
262 return 0;
263}
264
265int GUISliderValue::measureText(const std::string& str)
266{
267 void* fontResource = NULL;
268 if (mFont) fontResource = mFont->GetResource();
269
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100270 return gr_ttf_measureEx(str.c_str(), fontResource);
Vojtech Bocek85932342013-04-01 22:11:33 +0200271}
272
273int GUISliderValue::Render(void)
274{
275 if (!isConditionTrue())
276 {
277 mRendered = false;
278 return 0;
279 }
280
Matt Mowera8a89d12016-12-30 18:10:37 -0600281 if (mLabel)
Vojtech Bocek85932342013-04-01 22:11:33 +0200282 {
283 int w, h;
284 mLabel->GetCurrentBounds(w, h);
285 if (w != mLabelW) {
286 mLabelW = w;
287 int textX = mRenderX + (mRenderW/2 - mLabelW/2);
288 mLabel->SetRenderPos(textX, mRenderY);
289 }
290 int res = mLabel->Render();
Matt Mowera8a89d12016-12-30 18:10:37 -0600291 if (res < 0)
Vojtech Bocek85932342013-04-01 22:11:33 +0200292 return res;
293 }
294
295 // line
Matt Mowera8a89d12016-12-30 18:10:37 -0600296 if (mBackgroundImage && mBackgroundImage->GetResource())
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200297 {
298 gr_blit(mBackgroundImage->GetResource(), 0, 0, mLineW, mLineH, mLineX, mLineY);
299 }
300 else
301 {
302 gr_color(mLineColor.red, mLineColor.green, mLineColor.blue, mLineColor.alpha);
303 gr_fill(mLineX, mLineY, mLineW, mLineH);
304 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200305
306 // slider
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200307 uint32_t sliderX = mLineX + (mValuePct*(mLineW - mSliderW))/100;
Vojtech Bocek85932342013-04-01 22:11:33 +0200308
Matt Mowera8a89d12016-12-30 18:10:37 -0600309 if (mHandleImage && mHandleImage->GetResource())
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200310 {
311 gr_surface s = mHandleImage->GetResource();
Matt Mowera8a89d12016-12-30 18:10:37 -0600312 if (mDragging && mHandleHoverImage && mHandleHoverImage->GetResource())
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200313 s = mHandleHoverImage->GetResource();
314 gr_blit(s, 0, 0, mSliderW, mSliderH, sliderX, mLineY + (mLineH/2 - mSliderH/2));
315 }
316 else
317 {
318 gr_color(mSliderColor.red, mSliderColor.green, mSliderColor.blue, mSliderColor.alpha);
319 gr_fill(sliderX, mSliderY, mSliderW, mSliderH);
320 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200321
322 void *fontResource = NULL;
Matt Mowera8a89d12016-12-30 18:10:37 -0600323 if (mFont) fontResource = mFont->GetResource();
Vojtech Bocek85932342013-04-01 22:11:33 +0200324 gr_color(mTextColor.red, mTextColor.green, mTextColor.blue, mTextColor.alpha);
Matt Mowera8a89d12016-12-30 18:10:37 -0600325 if (mShowRange)
Vojtech Bocek85932342013-04-01 22:11:33 +0200326 {
327 int rangeY = (mLineY - mLineH/2) - mFontHeight/2;
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500328 gr_textEx_scaleW(mRenderX + mPadding/2, rangeY, mMinStr.c_str(), fontResource, mRenderW, TOP_LEFT, 0);
329 gr_textEx_scaleW(mLineX + mLineW + mPadding/2, rangeY, mMaxStr.c_str(), fontResource, mRenderW, TOP_LEFT, 0);
Vojtech Bocek85932342013-04-01 22:11:33 +0200330 }
331
Matt Mowera8a89d12016-12-30 18:10:37 -0600332 if (mValueStr && mShowCurr)
Vojtech Bocek85932342013-04-01 22:11:33 +0200333 {
334 sprintf(mValueStr, "%d", mValue);
335 int textW = measureText(mValueStr);
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500336 gr_textEx_scaleW(mRenderX + (mRenderW/2 - textW/2), mSliderY+mSliderH, mValueStr, fontResource, mRenderW, TOP_LEFT, 0);
Vojtech Bocek85932342013-04-01 22:11:33 +0200337 }
338
339 mRendered = true;
340 return 0;
341}
342
343int GUISliderValue::Update(void)
344{
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500345 if (!isConditionTrue())
346 return mRendered ? 2 : 0;
347 if (!mRendered)
348 return 2;
Vojtech Bocek85932342013-04-01 22:11:33 +0200349
Matt Mowera8a89d12016-12-30 18:10:37 -0600350 if (mLabel)
Vojtech Bocek85932342013-04-01 22:11:33 +0200351 return mLabel->Update();
352 return 0;
353}
354
355int GUISliderValue::valueFromPct(float pct)
356{
357 int range = abs(mMax - mMin);
358 return mMin + (pct * range) / 100;
359}
360
361float GUISliderValue::pctFromValue(int value)
362{
363 return float((value - mMin) * 100) / abs(mMax - mMin);
364}
365
366int GUISliderValue::NotifyTouch(TOUCH_STATE state, int x, int y)
367{
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500368 if (!isConditionTrue())
369 return -1;
Vojtech Bocek85932342013-04-01 22:11:33 +0200370
Vojtech Bocek85932342013-04-01 22:11:33 +0200371 switch (state)
372 {
373 case TOUCH_START:
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200374 if (x >= mLineX && x <= mLineX + mLineW &&
Vojtech Bocek85932342013-04-01 22:11:33 +0200375 y >= mRenderY && y <= mRenderY + mRenderH)
376 {
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200377 mDragging = true;
Vojtech Bocek85932342013-04-01 22:11:33 +0200378 }
379 // no break
380 case TOUCH_DRAG:
381 {
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200382 if (!mDragging) return 0;
Vojtech Bocek85932342013-04-01 22:11:33 +0200383
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200384 x = std::max(mLineX + mSliderW/2, x);
385 x = std::min(mLineX + mLineW - mSliderW/2, x);
Vojtech Bocek85932342013-04-01 22:11:33 +0200386
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200387 mValuePct = float(((x - (mLineX + mSliderW/2)) * 100) / (mLineW - mSliderW));
Vojtech Bocek85932342013-04-01 22:11:33 +0200388 int newVal = valueFromPct(mValuePct);
389 if (newVal != mValue) {
390 mRendered = false;
391 mValue = newVal;
392 if (mChangeOnDrag) {
393 if (!mVariable.empty())
394 DataManager::SetValue(mVariable, mValue);
395 if (mAction)
396 mAction->doActions();
397 }
398 }
399 break;
400 }
401 case TOUCH_RELEASE:
402 {
Vojtech Bocek18d7c982014-08-04 17:19:28 +0200403 if (!mDragging) return 0;
404 mDragging = false;
Vojtech Bocek85932342013-04-01 22:11:33 +0200405
406 if (!mVariable.empty())
407 DataManager::SetValue(mVariable, mValue);
408 if (mAction)
409 mAction->doActions();
410 break;
411 }
412 case TOUCH_REPEAT:
413 case TOUCH_HOLD:
414 break;
415 }
416 return 0;
417}
418
Vojtech Bocek07220562014-02-08 02:05:33 +0100419int GUISliderValue::NotifyVarChange(const std::string& varName, const std::string& value)
Vojtech Bocek85932342013-04-01 22:11:33 +0200420{
Vojtech Bocek07220562014-02-08 02:05:33 +0100421 GUIObject::NotifyVarChange(varName, value);
422
Vojtech Bocek85932342013-04-01 22:11:33 +0200423 if (mLabel)
424 mLabel->NotifyVarChange(varName, value);
425 if (varName == mVariable) {
426 int newVal = atoi(value.c_str());
Matt Mowera8a89d12016-12-30 18:10:37 -0600427 if (newVal != mValue) {
Vojtech Bocek85932342013-04-01 22:11:33 +0200428 mValue = newVal;
429 mValuePct = pctFromValue(mValue);
430 mRendered = false;
431 }
432 }
433 return 0;
434}
435
436void GUISliderValue::SetPageFocus(int inFocus)
437{
438 if (inFocus)
439 loadValue();
440}