blob: 6ea0beec92238e1175ba985b98d76458b8a1cd2c [file] [log] [blame]
Dees_Troya13d74f2013-03-24 08:54:55 -05001/*
2 Copyright 2012 bigbiff/Dees_Troy 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*/
Dees_Troy51a0e822012-09-05 15:24:24 -040018
19#include <stdarg.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <fcntl.h>
24#include <sys/reboot.h>
25#include <sys/stat.h>
26#include <sys/time.h>
27#include <sys/mman.h>
28#include <sys/types.h>
29#include <sys/ioctl.h>
30#include <time.h>
31#include <unistd.h>
32#include <stdlib.h>
Samer Diab (S.a.M.e.R_d)71e9b042014-01-07 20:18:47 +000033#include "../data.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040034
35#include <string>
36
37extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000038#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040039#include "../minuitwrp/minui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040040}
41
42#include "rapidxml.hpp"
43#include "objects.hpp"
44
45GUIButton::GUIButton(xml_node<>* node)
Vojtech Bocekede51c52014-02-07 23:58:09 +010046 : GUIObject(node)
Dees_Troy51a0e822012-09-05 15:24:24 -040047{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020048 xml_attribute<>* attr;
49 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -040050
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020051 mButtonImg = NULL;
52 mButtonIcon = NULL;
53 mButtonLabel = NULL;
54 mAction = NULL;
55 mRendered = false;
Dees_Troy1a7a6672013-02-15 09:39:07 -060056 hasHighlightColor = false;
57 renderHighlight = false;
Dees_Troya13d74f2013-03-24 08:54:55 -050058 hasFill = false;
Dees_Troy51a0e822012-09-05 15:24:24 -040059
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020060 if (!node) return;
Dees_Troy51a0e822012-09-05 15:24:24 -040061
Dees Troy4168a072013-11-29 05:01:51 +000062 // These can be loaded directly from the node
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020063 mButtonLabel = new GUIText(node);
64 mAction = new GUIAction(node);
Dees_Troy51a0e822012-09-05 15:24:24 -040065
Dees Troy4168a072013-11-29 05:01:51 +000066 child = node->first_node("image");
67 if (child)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020068 {
Dees Troy4168a072013-11-29 05:01:51 +000069 mButtonImg = new GUIImage(node);
70 if (mButtonImg->Render() < 0)
71 {
72 delete mButtonImg;
73 mButtonImg = NULL;
74 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020075 }
76 if (mButtonLabel->Render() < 0)
77 {
78 delete mButtonLabel;
79 mButtonLabel = NULL;
80 }
Dees_Troya13d74f2013-03-24 08:54:55 -050081 // Load fill if it exists
82 memset(&mFillColor, 0, sizeof(COLOR));
83 child = node->first_node("fill");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020084 if (child)
85 {
Dees_Troya13d74f2013-03-24 08:54:55 -050086 attr = child->first_attribute("color");
87 if (attr) {
88 hasFill = true;
89 std::string color = attr->value();
90 ConvertStrToColor(color, &mFillColor);
91 }
92 }
93 if (!hasFill && mButtonImg == NULL) {
Dees_Troy2673cec2013-04-02 20:22:16 +000094 LOGERR("No image resource or fill specified for button.\n");
Dees_Troya13d74f2013-03-24 08:54:55 -050095 }
Dees_Troy51a0e822012-09-05 15:24:24 -040096
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020097 // The icon is a special case
98 child = node->first_node("icon");
99 if (child)
100 {
thatf6ed8fc2015-02-14 20:23:16 +0100101 mButtonIcon = LoadAttrImage(child, "resource");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200102 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400103
Dees_Troy1a7a6672013-02-15 09:39:07 -0600104 memset(&mHighlightColor, 0, sizeof(COLOR));
105 child = node->first_node("highlight");
106 if (child) {
107 attr = child->first_attribute("color");
108 if (attr) {
109 hasHighlightColor = true;
110 std::string color = attr->value();
111 ConvertStrToColor(color, &mHighlightColor);
112 }
113 }
114
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200115 int x, y, w, h;
Dees Troyb21cc642013-09-10 17:36:41 +0000116 TextPlacement = TOP_LEFT;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200117 if (mButtonImg) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500118 mButtonImg->GetRenderPos(x, y, w, h);
119 } else if (hasFill) {
Dees Troyb21cc642013-09-10 17:36:41 +0000120 LoadPlacement(node->first_node("placement"), &x, &y, &w, &h, &TextPlacement);
Dees_Troya13d74f2013-03-24 08:54:55 -0500121 }
122 SetRenderPos(x, y, w, h);
Dees_Troy51a0e822012-09-05 15:24:24 -0400123}
124
125GUIButton::~GUIButton()
126{
thatf6ed8fc2015-02-14 20:23:16 +0100127 delete mButtonImg;
128 delete mButtonLabel;
129 delete mAction;
Dees_Troy51a0e822012-09-05 15:24:24 -0400130}
131
132int GUIButton::Render(void)
133{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200134 if (!isConditionTrue())
135 {
136 mRendered = false;
137 return 0;
138 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400139
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200140 int ret = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400141
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200142 if (mButtonImg) ret = mButtonImg->Render();
143 if (ret < 0) return ret;
Dees_Troya13d74f2013-03-24 08:54:55 -0500144 if (hasFill) {
145 gr_color(mFillColor.red, mFillColor.green, mFillColor.blue, mFillColor.alpha);
146 gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
147 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200148 if (mButtonIcon && mButtonIcon->GetResource())
149 gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY);
150 if (mButtonLabel) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500151 int w, h;
152 mButtonLabel->GetCurrentBounds(w, h);
153 if (w != mTextW) {
154 mTextW = w;
Dees Troyb21cc642013-09-10 17:36:41 +0000155 if (TextPlacement == CENTER_X_ONLY) {
156 mTextX = ((mRenderW - mRenderX) / 2);
157 } else if (mTextW > mRenderW) { // As a special case, we'll allow large text which automatically moves it to the right.
Dees_Troya13d74f2013-03-24 08:54:55 -0500158 mTextX = mRenderW + mRenderX + 5;
159 mRenderW += mTextW + 5;
Dees Troyb21cc642013-09-10 17:36:41 +0000160 } else {
Dees_Troya13d74f2013-03-24 08:54:55 -0500161 mTextX = mRenderX + ((mRenderW - mTextW) / 2);
162 }
163 mButtonLabel->SetRenderPos(mTextX, mTextY);
164 }
165 ret = mButtonLabel->Render();
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200166 if (ret < 0) return ret;
Dees_Troya13d74f2013-03-24 08:54:55 -0500167 }
Dees_Troy1a7a6672013-02-15 09:39:07 -0600168 if (renderHighlight && hasHighlightColor) {
169 gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
170 gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
171 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200172 mRendered = true;
173 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400174}
175
176int GUIButton::Update(void)
177{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200178 if (!isConditionTrue()) return (mRendered ? 2 : 0);
179 if (!mRendered) return 2;
Dees_Troy51a0e822012-09-05 15:24:24 -0400180
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200181 int ret = 0, ret2 = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400182
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200183 if (mButtonImg) ret = mButtonImg->Update();
184 if (ret < 0) return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400185
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200186 if (ret == 0)
187 {
188 if (mButtonLabel) {
Dees_Troya13d74f2013-03-24 08:54:55 -0500189 ret2 = mButtonLabel->Update();
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200190 if (ret2 < 0) return ret2;
191 if (ret2 > ret) ret = ret2;
Dees_Troya13d74f2013-03-24 08:54:55 -0500192 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200193 }
194 else if (ret == 1)
195 {
196 // The button re-rendered, so everyone else is a render
197 if (mButtonIcon && mButtonIcon->GetResource())
198 gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY);
199 if (mButtonLabel) ret = mButtonLabel->Render();
200 if (ret < 0) return ret;
201 ret = 1;
202 }
203 else
204 {
205 // Aparently, the button needs a background update
206 ret = 2;
207 }
208 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400209}
210
211int GUIButton::SetRenderPos(int x, int y, int w, int h)
212{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200213 mRenderX = x;
214 mRenderY = y;
215 if (w || h)
216 {
217 mRenderW = w;
218 mRenderH = h;
219 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400220
thatf6ed8fc2015-02-14 20:23:16 +0100221 mIconW = mButtonIcon->GetWidth();
222 mIconH = mButtonIcon->GetHeight();
Dees_Troy51a0e822012-09-05 15:24:24 -0400223
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200224 mTextH = 0;
225 mTextW = 0;
226 mIconX = mRenderX + ((mRenderW - mIconW) / 2);
227 if (mButtonLabel) mButtonLabel->GetCurrentBounds(mTextW, mTextH);
228 if (mTextW)
229 {
Dees Troyb21cc642013-09-10 17:36:41 +0000230 if (TextPlacement == CENTER_X_ONLY) {
231 mTextX = ((mRenderW - mRenderX) / 2);
232 } else if (mTextW > mRenderW) { // As a special case, we'll allow large text which automatically moves it to the right.
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200233 mTextX = mRenderW + mRenderX + 5;
234 mRenderW += mTextW + 5;
Dees Troyb21cc642013-09-10 17:36:41 +0000235 } else {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200236 mTextX = mRenderX + ((mRenderW - mTextW) / 2);
237 }
238 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400239
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200240 if (mIconH == 0 || mTextH == 0 || mIconH + mTextH > mRenderH)
241 {
242 mIconY = mRenderY + (mRenderH / 2) - (mIconH / 2);
243 mTextY = mRenderY + (mRenderH / 2) - (mTextH / 2);
244 }
245 else
246 {
247 int divisor = mRenderH - (mIconH + mTextH);
248 mIconY = mRenderY + (divisor / 3);
249 mTextY = mRenderY + (divisor * 2 / 3) + mIconH;
250 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400251
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200252 if (mButtonLabel) mButtonLabel->SetRenderPos(mTextX, mTextY);
253 if (mAction) mAction->SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
254 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
255 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400256}
257
258int GUIButton::NotifyTouch(TOUCH_STATE state, int x, int y)
259{
Dees_Troy4d12f962012-10-19 13:13:15 -0400260 static int last_state = 0;
261
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200262 if (!isConditionTrue()) return -1;
Dees_Troy4d12f962012-10-19 13:13:15 -0400263 if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH || state == TOUCH_RELEASE) {
264 if (last_state == 1) {
265 last_state = 0;
266 if (mButtonLabel != NULL)
267 mButtonLabel->isHighlighted = false;
268 if (mButtonImg != NULL)
269 mButtonImg->isHighlighted = false;
Dees_Troy1a7a6672013-02-15 09:39:07 -0600270 renderHighlight = false;
Dees_Troy4d12f962012-10-19 13:13:15 -0400271 mRendered = false;
272 }
273 } else {
274 if (last_state == 0) {
275 last_state = 1;
Ethan Yonker03db3262014-02-05 08:02:06 -0600276 DataManager::Vibrate("tw_button_vibrate");
Dees_Troy4d12f962012-10-19 13:13:15 -0400277 if (mButtonLabel != NULL)
278 mButtonLabel->isHighlighted = true;
279 if (mButtonImg != NULL)
280 mButtonImg->isHighlighted = true;
Dees_Troy1a7a6672013-02-15 09:39:07 -0600281 renderHighlight = true;
Dees_Troy4d12f962012-10-19 13:13:15 -0400282 mRendered = false;
283 }
284 }
285 if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH)
286 return 0;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200287 return (mAction ? mAction->NotifyTouch(state, x, y) : 1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400288}