blob: 0511b1ab51f578855b32e78413224b8fc673f85e [file] [log] [blame]
Dees_Troya13d74f2013-03-24 08:54:55 -05001/*
2 Copyright 2013 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 Troy3be70a82013-10-22 14:25:12 +000018
Dees_Troya13d74f2013-03-24 08:54:55 -050019// pages.cpp - Source to manage GUI base objects
Dees_Troy51a0e822012-09-05 15:24:24 -040020
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>
Ethan Yonkera2dc2f22014-11-08 08:13:40 -060035#include "../twrp-functions.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040036
37#include <string>
38
39extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000040#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040041#include "../minuitwrp/minui.h"
Ethan Yonkera2dc2f22014-11-08 08:13:40 -060042#include "../minzip/SysUtil.h"
43#include "../minzip/Zip.h"
Ethan Yonker63e414f2015-02-06 15:44:39 -060044#include "gui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040045}
46
47#include "rapidxml.hpp"
48#include "objects.hpp"
gordon13370d9133d2013-06-08 14:17:07 +020049#include "blanktimer.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040050
51extern int gGuiRunning;
52
53std::map<std::string, PageSet*> PageManager::mPageSets;
54PageSet* PageManager::mCurrentSet;
55PageSet* PageManager::mBaseSet = NULL;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +010056MouseCursor *PageManager::mMouseCursor = NULL;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +010057HardwareKeyboard *PageManager::mHardwareKeyboard = NULL;
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -050058bool PageManager::mReloadTheme = false;
59std::string PageManager::mStartPage = "main";
Dees_Troy51a0e822012-09-05 15:24:24 -040060
Ethan Yonker751a85e2014-12-12 16:59:10 -060061int tw_x_offset = 0;
62int tw_y_offset = 0;
63
Dees_Troy51a0e822012-09-05 15:24:24 -040064// Helper routine to convert a string to a color declaration
65int ConvertStrToColor(std::string str, COLOR* color)
66{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020067 // Set the default, solid black
68 memset(color, 0, sizeof(COLOR));
69 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040070
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020071 // Translate variables
72 DataManager::GetValue(str, str);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -050073
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020074 // Look for some defaults
thatf6ed8fc2015-02-14 20:23:16 +010075 if (str == "black") return 0;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020076 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
77 else if (str == "red") { color->red = 255; return 0; }
78 else if (str == "green") { color->green = 255; return 0; }
79 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040080
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020081 // At this point, we require an RGB(A) color
82 if (str[0] != '#')
83 return -1;
84
85 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040086
Dees_Troy30b962e2012-10-19 20:48:59 -040087 int result;
88 if (str.size() >= 8) {
89 // We have alpha channel
90 string alpha = str.substr(6, 2);
91 result = strtol(alpha.c_str(), NULL, 16);
92 color->alpha = result & 0x000000FF;
93 str.resize(6);
94 result = strtol(str.c_str(), NULL, 16);
95 color->red = (result >> 16) & 0x000000FF;
96 color->green = (result >> 8) & 0x000000FF;
97 color->blue = result & 0x000000FF;
98 } else {
99 result = strtol(str.c_str(), NULL, 16);
100 color->red = (result >> 16) & 0x000000FF;
101 color->green = (result >> 8) & 0x000000FF;
102 color->blue = result & 0x000000FF;
103 }
104 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400105}
106
107// Helper APIs
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600108xml_node<>* FindNode(xml_node<>* parent, const char* nodename, int depth /* = 0 */)
109{
that8d46c092015-02-26 01:30:04 +0100110 if (!parent)
111 return NULL;
112
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600113 xml_node<>* child = parent->first_node(nodename);
114 if (child)
115 return child;
116
117 if (depth == 10) {
118 LOGERR("Too many style loops detected.\n");
119 return NULL;
120 }
121
122 xml_node<>* style = parent->first_node("style");
123 if (style) {
124 while (style) {
125 if (!style->first_attribute("name")) {
126 LOGERR("No name given for style.\n");
127 continue;
128 } else {
129 std::string name = style->first_attribute("name")->value();
130 xml_node<>* node = PageManager::FindStyle(name);
131
132 if (node) {
133 // We found the style that was named
134 xml_node<>* stylenode = FindNode(node, nodename, depth + 1);
135 if (stylenode)
136 return stylenode;
137 }
138 }
139 style = style->next_sibling("style");
140 }
141 } else {
that54e9c832015-11-04 21:46:01 +0100142 // Search for stylename in the parent node <object type="foo" style="foo2">
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600143 xml_attribute<>* attr = parent->first_attribute("style");
144 // If no style is found anywhere else and the node wasn't found in the object itself
145 // as a special case we will search for a style that uses the same style name as the
146 // object type, so <object type="button"> would search for a style named "button"
147 if (!attr)
148 attr = parent->first_attribute("type");
that54e9c832015-11-04 21:46:01 +0100149 // if there's no attribute type, the object type must be the element name
150 std::string stylename = attr ? attr->value() : parent->name();
151 xml_node<>* node = PageManager::FindStyle(stylename);
152 if (node) {
153 xml_node<>* stylenode = FindNode(node, nodename, depth + 1);
154 if (stylenode)
155 return stylenode;
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600156 }
157 }
158 return NULL;
159}
160
thatf6ed8fc2015-02-14 20:23:16 +0100161std::string LoadAttrString(xml_node<>* element, const char* attrname, const char* defaultvalue)
162{
163 if (!element)
164 return defaultvalue;
165
166 xml_attribute<>* attr = element->first_attribute(attrname);
167 return attr ? attr->value() : defaultvalue;
168}
169
170int LoadAttrInt(xml_node<>* element, const char* attrname, int defaultvalue)
171{
172 string value = LoadAttrString(element, attrname);
173 // resolve variables
174 DataManager::GetValue(value, value);
175 return value.empty() ? defaultvalue : atoi(value.c_str());
176}
177
178int LoadAttrIntScaleX(xml_node<>* element, const char* attrname, int defaultvalue)
179{
180 return scale_theme_x(LoadAttrInt(element, attrname, defaultvalue));
181}
182
183int LoadAttrIntScaleY(xml_node<>* element, const char* attrname, int defaultvalue)
184{
185 return scale_theme_y(LoadAttrInt(element, attrname, defaultvalue));
186}
187
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600188COLOR LoadAttrColor(xml_node<>* element, const char* attrname, bool* found_color, COLOR defaultvalue)
thatf6ed8fc2015-02-14 20:23:16 +0100189{
190 string value = LoadAttrString(element, attrname);
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600191 *found_color = !value.empty();
thatf6ed8fc2015-02-14 20:23:16 +0100192 // resolve variables
193 DataManager::GetValue(value, value);
194 COLOR ret = defaultvalue;
195 if (ConvertStrToColor(value, &ret) == 0)
196 return ret;
197 else
198 return defaultvalue;
199}
200
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600201COLOR LoadAttrColor(xml_node<>* element, const char* attrname, COLOR defaultvalue)
202{
203 bool found_color = false;
204 return LoadAttrColor(element, attrname, &found_color, defaultvalue);
205}
206
thatf6ed8fc2015-02-14 20:23:16 +0100207FontResource* LoadAttrFont(xml_node<>* element, const char* attrname)
208{
209 std::string name = LoadAttrString(element, attrname, "");
210 if (name.empty())
211 return NULL;
212 else
that74ac6062015-03-04 22:39:34 +0100213 return PageManager::GetResources()->FindFont(name);
thatf6ed8fc2015-02-14 20:23:16 +0100214}
215
216ImageResource* LoadAttrImage(xml_node<>* element, const char* attrname)
217{
218 std::string name = LoadAttrString(element, attrname, "");
219 if (name.empty())
220 return NULL;
221 else
that74ac6062015-03-04 22:39:34 +0100222 return PageManager::GetResources()->FindImage(name);
thatf6ed8fc2015-02-14 20:23:16 +0100223}
224
225AnimationResource* LoadAttrAnimation(xml_node<>* element, const char* attrname)
226{
227 std::string name = LoadAttrString(element, attrname, "");
228 if (name.empty())
229 return NULL;
230 else
that74ac6062015-03-04 22:39:34 +0100231 return PageManager::GetResources()->FindAnimation(name);
thatf6ed8fc2015-02-14 20:23:16 +0100232}
233
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500234bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, Placement* placement /* = NULL */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400235{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200236 if (!node)
237 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400238
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200239 if (node->first_attribute("x"))
thatf6ed8fc2015-02-14 20:23:16 +0100240 *x = LoadAttrIntScaleX(node, "x") + tw_x_offset;
Dees_Troy51a0e822012-09-05 15:24:24 -0400241
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200242 if (node->first_attribute("y"))
thatf6ed8fc2015-02-14 20:23:16 +0100243 *y = LoadAttrIntScaleY(node, "y") + tw_y_offset;
Dees_Troy51a0e822012-09-05 15:24:24 -0400244
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200245 if (w && node->first_attribute("w"))
thatf6ed8fc2015-02-14 20:23:16 +0100246 *w = LoadAttrIntScaleX(node, "w");
Dees_Troy51a0e822012-09-05 15:24:24 -0400247
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200248 if (h && node->first_attribute("h"))
thatf6ed8fc2015-02-14 20:23:16 +0100249 *h = LoadAttrIntScaleY(node, "h");
Dees_Troy51a0e822012-09-05 15:24:24 -0400250
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200251 if (placement && node->first_attribute("placement"))
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500252 *placement = (Placement) LoadAttrInt(node, "placement");
Dees_Troy51a0e822012-09-05 15:24:24 -0400253
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200254 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400255}
256
257int ActionObject::SetActionPos(int x, int y, int w, int h)
258{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200259 if (x < 0 || y < 0)
260 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400261
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500262 mActionX = x;
263 mActionY = y;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200264 if (w || h)
265 {
266 mActionW = w;
267 mActionH = h;
268 }
269 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400270}
271
thatb63e2f92015-06-27 21:35:11 +0200272Page::Page(xml_node<>* page, std::vector<xml_node<>*> *templates)
Dees_Troy51a0e822012-09-05 15:24:24 -0400273{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200274 mTouchStart = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400275
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200276 // We can memset the whole structure, because the alpha channel is ignored
277 memset(&mBackground, 0, sizeof(COLOR));
Dees_Troy51a0e822012-09-05 15:24:24 -0400278
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200279 // With NULL, we make a console-only display
280 if (!page)
281 {
282 mName = "console";
Dees_Troy51a0e822012-09-05 15:24:24 -0400283
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200284 GUIConsole* element = new GUIConsole(NULL);
285 mRenders.push_back(element);
286 mActions.push_back(element);
287 return;
288 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400289
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200290 if (page->first_attribute("name"))
291 mName = page->first_attribute("name")->value();
292 else
293 {
294 LOGERR("No page name attribute found!\n");
295 return;
296 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400297
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200298 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400299
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200300 // This is a recursive routine for template handling
thatb63e2f92015-06-27 21:35:11 +0200301 ProcessNode(page, templates, 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400302}
303
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100304Page::~Page()
305{
306 for (std::vector<GUIObject*>::iterator itr = mObjects.begin(); itr != mObjects.end(); ++itr)
307 delete *itr;
308}
309
thatb63e2f92015-06-27 21:35:11 +0200310bool Page::ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates, int depth)
Dees_Troy51a0e822012-09-05 15:24:24 -0400311{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200312 if (depth == 10)
313 {
314 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
315 return false;
316 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400317
thatb63e2f92015-06-27 21:35:11 +0200318 for (xml_node<>* child = page->first_node(); child; child = child->next_sibling())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200319 {
thatb63e2f92015-06-27 21:35:11 +0200320 std::string type = child->name();
321
322 if (type == "background") {
323 mBackground = LoadAttrColor(child, "color", COLOR(0,0,0,0));
324 continue;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200325 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400326
thatb63e2f92015-06-27 21:35:11 +0200327 if (type == "object") {
328 // legacy format : <object type="...">
329 xml_attribute<>* attr = child->first_attribute("type");
330 type = attr ? attr->value() : "*unspecified*";
331 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400332
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200333 if (type == "text")
334 {
335 GUIText* element = new GUIText(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100336 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200337 mRenders.push_back(element);
338 mActions.push_back(element);
339 }
340 else if (type == "image")
341 {
342 GUIImage* element = new GUIImage(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100343 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200344 mRenders.push_back(element);
345 }
346 else if (type == "fill")
347 {
348 GUIFill* element = new GUIFill(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100349 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200350 mRenders.push_back(element);
351 }
352 else if (type == "action")
353 {
354 GUIAction* element = new GUIAction(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100355 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200356 mActions.push_back(element);
357 }
358 else if (type == "console")
359 {
360 GUIConsole* element = new GUIConsole(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100361 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200362 mRenders.push_back(element);
363 mActions.push_back(element);
364 }
365 else if (type == "button")
366 {
367 GUIButton* element = new GUIButton(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100368 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200369 mRenders.push_back(element);
370 mActions.push_back(element);
371 }
372 else if (type == "checkbox")
373 {
374 GUICheckbox* element = new GUICheckbox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100375 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200376 mRenders.push_back(element);
377 mActions.push_back(element);
378 }
379 else if (type == "fileselector")
380 {
381 GUIFileSelector* element = new GUIFileSelector(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100382 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200383 mRenders.push_back(element);
384 mActions.push_back(element);
385 }
386 else if (type == "animation")
387 {
388 GUIAnimation* element = new GUIAnimation(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100389 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200390 mRenders.push_back(element);
391 }
392 else if (type == "progressbar")
393 {
394 GUIProgressBar* element = new GUIProgressBar(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100395 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200396 mRenders.push_back(element);
397 mActions.push_back(element);
398 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400399 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200400 {
401 GUISlider* element = new GUISlider(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100402 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200403 mRenders.push_back(element);
404 mActions.push_back(element);
405 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200406 else if (type == "slidervalue")
407 {
408 GUISliderValue *element = new GUISliderValue(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100409 mObjects.push_back(element);
Vojtech Bocek85932342013-04-01 22:11:33 +0200410 mRenders.push_back(element);
411 mActions.push_back(element);
412 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400413 else if (type == "listbox")
414 {
415 GUIListBox* element = new GUIListBox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100416 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400417 mRenders.push_back(element);
418 mActions.push_back(element);
419 }
420 else if (type == "keyboard")
421 {
422 GUIKeyboard* element = new GUIKeyboard(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100423 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400424 mRenders.push_back(element);
425 mActions.push_back(element);
426 }
427 else if (type == "input")
428 {
429 GUIInput* element = new GUIInput(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100430 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400431 mRenders.push_back(element);
432 mActions.push_back(element);
433 mInputs.push_back(element);
434 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500435 else if (type == "partitionlist")
436 {
437 GUIPartitionList* element = new GUIPartitionList(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100438 mObjects.push_back(element);
Dees_Troya13d74f2013-03-24 08:54:55 -0500439 mRenders.push_back(element);
440 mActions.push_back(element);
441 }
Vojtech Bocek7e11ac52015-03-05 23:21:49 +0100442 else if (type == "patternpassword")
443 {
444 GUIPatternPassword* element = new GUIPatternPassword(child);
445 mObjects.push_back(element);
446 mRenders.push_back(element);
447 mActions.push_back(element);
448 }
Ethan Yonker44925ad2015-07-22 12:33:59 -0500449 else if (type == "textbox")
450 {
451 GUITextBox* element = new GUITextBox(child);
452 mObjects.push_back(element);
453 mRenders.push_back(element);
454 mActions.push_back(element);
455 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200456 else if (type == "template")
457 {
458 if (!templates || !child->first_attribute("name"))
459 {
460 LOGERR("Invalid template request.\n");
461 }
462 else
463 {
464 std::string name = child->first_attribute("name")->value();
Ethan Yonker780cd392014-07-21 15:24:39 -0500465 xml_node<>* node;
466 bool node_found = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400467
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200468 // We need to find the correct template
Ethan Yonker780cd392014-07-21 15:24:39 -0500469 for (std::vector<xml_node<>*>::iterator itr = templates->begin(); itr != templates->end(); itr++) {
470 node = (*itr)->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400471
Ethan Yonker780cd392014-07-21 15:24:39 -0500472 while (node)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200473 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500474 if (!node->first_attribute("name"))
475 continue;
476
477 if (name == node->first_attribute("name")->value())
478 {
479 if (!ProcessNode(node, templates, depth + 1))
480 return false;
481 else {
482 node_found = true;
483 break;
484 }
485 }
486 if (node_found)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200487 break;
Ethan Yonker780cd392014-07-21 15:24:39 -0500488 node = node->next_sibling("template");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200489 }
thatb63e2f92015-06-27 21:35:11 +0200490 // [check] why is there no if (node_found) here too?
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200491 }
492 }
493 }
494 else
495 {
thatb63e2f92015-06-27 21:35:11 +0200496 LOGERR("Unknown object type: %s.\n", type.c_str());
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200497 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200498 }
499 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400500}
501
502int Page::Render(void)
503{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200504 // Render background
505 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
506 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400507
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200508 // Render remaining objects
509 std::vector<RenderObject*>::iterator iter;
510 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
511 {
512 if ((*iter)->Render())
513 LOGERR("A render request has failed.\n");
514 }
515 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400516}
517
518int Page::Update(void)
519{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200520 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400521
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200522 std::vector<RenderObject*>::iterator iter;
523 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
524 {
525 int ret = (*iter)->Update();
526 if (ret < 0)
527 LOGERR("An update request has failed.\n");
528 else if (ret > retCode)
529 retCode = ret;
530 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400531
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200532 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400533}
534
535int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
536{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200537 // By default, return 1 to ignore further touches if nobody is listening
538 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400539
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200540 // Don't try to handle a lack of handlers
541 if (mActions.size() == 0)
542 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400543
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200544 // We record mTouchStart so we can pass all the touch stream to the same handler
545 if (state == TOUCH_START)
546 {
547 std::vector<ActionObject*>::reverse_iterator iter;
548 // We work backwards, from top-most element to bottom-most element
549 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
550 {
551 if ((*iter)->IsInRegion(x, y))
552 {
553 mTouchStart = (*iter);
554 ret = mTouchStart->NotifyTouch(state, x, y);
555 if (ret >= 0)
556 break;
557 mTouchStart = NULL;
558 }
559 }
560 }
561 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
562 {
563 ret = mTouchStart->NotifyTouch(state, x, y);
564 mTouchStart = NULL;
565 }
566 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
567 {
568 ret = mTouchStart->NotifyTouch(state, x, y);
569 }
570 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400571}
572
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100573int Page::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400574{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200575 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400576
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200577 // Don't try to handle a lack of handlers
578 if (mActions.size() == 0)
579 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400580
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100581 int ret = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200582 // We work backwards, from top-most element to bottom-most element
583 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
584 {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100585 ret = (*iter)->NotifyKey(key, down);
586 if (ret < 0) {
587 LOGERR("An action handler has returned an error\n");
588 ret = 1;
589 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200590 }
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100591 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400592}
593
594int Page::NotifyKeyboard(int key)
595{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200596 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400597
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200598 // Don't try to handle a lack of handlers
599 if (mInputs.size() == 0)
600 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400601
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200602 // We work backwards, from top-most element to bottom-most element
603 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
604 {
605 int ret = (*iter)->NotifyKeyboard(key);
606 if (ret == 0)
607 return 0;
608 else if (ret < 0)
609 LOGERR("A keyboard handler has returned an error");
610 }
611 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400612}
613
614int Page::SetKeyBoardFocus(int inFocus)
615{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200616 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400617
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200618 // Don't try to handle a lack of handlers
619 if (mInputs.size() == 0)
620 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400621
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200622 // We work backwards, from top-most element to bottom-most element
623 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
624 {
625 int ret = (*iter)->SetInputFocus(inFocus);
626 if (ret == 0)
627 return 0;
628 else if (ret < 0)
629 LOGERR("An input focus handler has returned an error");
630 }
631 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400632}
633
634void Page::SetPageFocus(int inFocus)
635{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200636 // Render remaining objects
637 std::vector<RenderObject*>::iterator iter;
638 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
639 (*iter)->SetPageFocus(inFocus);
640
641 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400642}
643
644int Page::NotifyVarChange(std::string varName, std::string value)
645{
Vojtech Bocek07220562014-02-08 02:05:33 +0100646 std::vector<GUIObject*>::iterator iter;
647 for (iter = mObjects.begin(); iter != mObjects.end(); ++iter)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200648 {
649 if ((*iter)->NotifyVarChange(varName, value))
650 LOGERR("An action handler errored on NotifyVarChange.\n");
651 }
652 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400653}
654
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500655PageSet::PageSet(const char* xmlFile)
Dees_Troy51a0e822012-09-05 15:24:24 -0400656{
that74ac6062015-03-04 22:39:34 +0100657 mResources = new ResourceManager;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200658 mCurrentPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400659
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500660 if (!xmlFile)
thatb63e2f92015-06-27 21:35:11 +0200661 mCurrentPage = new Page(NULL, NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400662}
663
664PageSet::~PageSet()
665{
Ethan Yonker1c273312015-03-16 12:18:56 -0500666 mOverlays.clear();
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100667 for (std::vector<Page*>::iterator itr = mPages.begin(); itr != mPages.end(); ++itr)
668 delete *itr;
669
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200670 delete mResources;
Dees_Troy51a0e822012-09-05 15:24:24 -0400671}
672
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500673int PageSet::Load(ZipArchive* package, char* xmlFile)
Dees_Troy51a0e822012-09-05 15:24:24 -0400674{
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500675 xml_document<> mDoc;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200676 xml_node<>* parent;
677 xml_node<>* child;
Ethan Yonker780cd392014-07-21 15:24:39 -0500678 xml_node<>* xmltemplate;
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600679 xml_node<>* xmlstyle;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500680
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500681 mDoc.parse<0>(xmlFile);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200682 parent = mDoc.first_node("recovery");
683 if (!parent)
684 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400685
Ethan Yonker63e414f2015-02-06 15:44:39 -0600686 set_scale_values(1, 1); // Reset any previous scaling values
687
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200688 // Now, let's parse the XML
Ethan Yonker63e414f2015-02-06 15:44:39 -0600689 LOGINFO("Checking resolution...\n");
690 child = parent->first_node("details");
691 if (child) {
692 xml_node<>* resolution = child->first_node("resolution");
693 if (resolution) {
694 xml_attribute<>* width_attr = resolution->first_attribute("width");
695 xml_attribute<>* height_attr = resolution->first_attribute("height");
696 xml_attribute<>* noscale_attr = resolution->first_attribute("noscaling");
697 if (width_attr && height_attr && !noscale_attr) {
698 int width = atoi(width_attr->value());
699 int height = atoi(height_attr->value());
700 int offx = 0, offy = 0;
701#ifdef TW_ROUND_SCREEN
702 xml_node<>* roundscreen = child->first_node("roundscreen");
703 if (roundscreen) {
704 LOGINFO("TW_ROUND_SCREEN := true, using round screen XML settings.\n");
705 xml_attribute<>* offx_attr = roundscreen->first_attribute("offset_x");
706 xml_attribute<>* offy_attr = roundscreen->first_attribute("offset_y");
707 if (offx_attr) {
708 offx = atoi(offx_attr->value());
709 }
710 if (offy_attr) {
711 offy = atoi(offy_attr->value());
712 }
713 }
714#endif
715 if (width != 0 && height != 0) {
716 float scale_w = ((float)gr_fb_width() - ((float)offx * 2.0)) / (float)width;
717 float scale_h = ((float)gr_fb_height() - ((float)offy * 2.0)) / (float)height;
718#ifdef TW_ROUND_SCREEN
719 float scale_off_w = (float)gr_fb_width() / (float)width;
720 float scale_off_h = (float)gr_fb_height() / (float)height;
721 tw_x_offset = offx * scale_off_w;
722 tw_y_offset = offy * scale_off_h;
723#endif
724 if (scale_w != 1 || scale_h != 1) {
725 LOGINFO("Scaling theme width %fx and height %fx, offsets x: %i y: %i\n", scale_w, scale_h, tw_x_offset, tw_y_offset);
726 set_scale_values(scale_w, scale_h);
727 }
728 }
729 } else {
730 LOGINFO("XML does not contain width and height, no scaling will be applied\n");
731 }
732 } else {
733 LOGINFO("XML contains no resolution tag, no scaling will be applied.\n");
734 }
735 } else {
736 LOGINFO("XML contains no details tag, no scaling will be applied.\n");
737 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200738 LOGINFO("Loading resources...\n");
739 child = parent->first_node("resources");
740 if (child)
that74ac6062015-03-04 22:39:34 +0100741 mResources->LoadResources(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400742
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200743 LOGINFO("Loading variables...\n");
744 child = parent->first_node("variables");
745 if (child)
746 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400747
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100748 LOGINFO("Loading mouse cursor...\n");
749 child = parent->first_node("mousecursor");
750 if(child)
751 PageManager::LoadCursorData(child);
752
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200753 LOGINFO("Loading pages...\n");
754 // This may be NULL if no templates are present
Ethan Yonker780cd392014-07-21 15:24:39 -0500755 xmltemplate = parent->first_node("templates");
756 if (xmltemplate)
757 templates.push_back(xmltemplate);
Dees_Troy51a0e822012-09-05 15:24:24 -0400758
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600759 // Load styles if present
760 xmlstyle = parent->first_node("styles");
761 if (xmlstyle)
762 styles.push_back(xmlstyle);
763
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200764 child = parent->first_node("pages");
Ethan Yonker780cd392014-07-21 15:24:39 -0500765 if (child) {
766 if (LoadPages(child)) {
767 LOGERR("PageSet::Load returning -1\n");
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500768 mDoc.clear();
Ethan Yonker780cd392014-07-21 15:24:39 -0500769 return -1;
770 }
771 }
Vojtech Boceke979abd2015-01-12 18:29:12 +0100772
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500773 int ret = CheckInclude(package, &mDoc);
774 mDoc.clear();
775 templates.clear();
776 return ret;
Ethan Yonker780cd392014-07-21 15:24:39 -0500777}
Dees_Troy51a0e822012-09-05 15:24:24 -0400778
Ethan Yonker780cd392014-07-21 15:24:39 -0500779int PageSet::CheckInclude(ZipArchive* package, xml_document<> *parentDoc)
780{
781 xml_node<>* par;
782 xml_node<>* par2;
783 xml_node<>* chld;
784 xml_node<>* parent;
785 xml_node<>* child;
786 xml_node<>* xmltemplate;
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600787 xml_node<>* xmlstyle;
Ethan Yonker780cd392014-07-21 15:24:39 -0500788 long len;
789 char* xmlFile = NULL;
790 string filename;
Vojtech Boceke979abd2015-01-12 18:29:12 +0100791 xml_document<> *doc = NULL;
Ethan Yonker780cd392014-07-21 15:24:39 -0500792
793 par = parentDoc->first_node("recovery");
794 if (!par) {
795 par = parentDoc->first_node("install");
796 }
797 if (!par) {
798 return 0;
799 }
800
801 par2 = par->first_node("include");
802 if (!par2)
803 return 0;
804 chld = par2->first_node("xmlfile");
805 while (chld != NULL) {
806 xml_attribute<>* attr = chld->first_attribute("name");
807 if (!attr)
808 break;
809
Ethan Yonker780cd392014-07-21 15:24:39 -0500810 if (!package) {
811 // We can try to load the XML directly...
Dees Troy3454ade2015-01-20 19:21:04 +0000812 filename = TWRES;
Ethan Yonker780cd392014-07-21 15:24:39 -0500813 filename += attr->value();
Ethan Yonker780cd392014-07-21 15:24:39 -0500814 } else {
815 filename += attr->value();
Ethan Yonker561c58d2015-10-05 08:48:22 -0500816 }
817 xmlFile = PageManager::LoadFileToBuffer(filename, package);
818 if (xmlFile == NULL) {
819 LOGERR("PageSet::CheckInclude unable to load '%s'\n", filename.c_str());
820 return -1;
Ethan Yonker780cd392014-07-21 15:24:39 -0500821 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500822
Vojtech Boceke979abd2015-01-12 18:29:12 +0100823 doc = new xml_document<>();
824 doc->parse<0>(xmlFile);
825
826 parent = doc->first_node("recovery");
Ethan Yonker780cd392014-07-21 15:24:39 -0500827 if (!parent)
Vojtech Boceke979abd2015-01-12 18:29:12 +0100828 parent = doc->first_node("install");
Ethan Yonker780cd392014-07-21 15:24:39 -0500829
830 // Now, let's parse the XML
831 LOGINFO("Loading included resources...\n");
832 child = parent->first_node("resources");
833 if (child)
834 mResources->LoadResources(child, package);
835
836 LOGINFO("Loading included variables...\n");
837 child = parent->first_node("variables");
838 if (child)
839 LoadVariables(child);
840
841 LOGINFO("Loading mouse cursor...\n");
842 child = parent->first_node("mousecursor");
843 if(child)
844 PageManager::LoadCursorData(child);
845
846 LOGINFO("Loading included pages...\n");
847 // This may be NULL if no templates are present
848 xmltemplate = parent->first_node("templates");
849 if (xmltemplate)
850 templates.push_back(xmltemplate);
851
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600852 // Load styles if present
853 xmlstyle = parent->first_node("styles");
854 if (xmlstyle)
855 styles.push_back(xmlstyle);
856
Ethan Yonker780cd392014-07-21 15:24:39 -0500857 child = parent->first_node("pages");
Vojtech Boceke979abd2015-01-12 18:29:12 +0100858 if (child && LoadPages(child))
859 {
860 templates.pop_back();
861 doc->clear();
862 delete doc;
Ethan Yonker561c58d2015-10-05 08:48:22 -0500863 free(xmlFile);
Vojtech Boceke979abd2015-01-12 18:29:12 +0100864 return -1;
865 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500866
Ethan Yonker561c58d2015-10-05 08:48:22 -0500867 if (CheckInclude(package, doc)) {
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500868 doc->clear();
869 delete doc;
Ethan Yonker561c58d2015-10-05 08:48:22 -0500870 free(xmlFile);
Ethan Yonker780cd392014-07-21 15:24:39 -0500871 return -1;
Ethan Yonker561c58d2015-10-05 08:48:22 -0500872 }
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500873 doc->clear();
874 delete doc;
875 free(xmlFile);
Ethan Yonker780cd392014-07-21 15:24:39 -0500876
877 chld = chld->next_sibling("xmlfile");
878 }
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -0500879
Ethan Yonker780cd392014-07-21 15:24:39 -0500880 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400881}
882
883int PageSet::SetPage(std::string page)
884{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200885 Page* tmp = FindPage(page);
886 if (tmp)
887 {
888 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
889 mCurrentPage = tmp;
890 mCurrentPage->SetPageFocus(1);
891 mCurrentPage->NotifyVarChange("", "");
892 return 0;
893 }
894 else
895 {
896 LOGERR("Unable to locate page (%s)\n", page.c_str());
897 }
898 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400899}
900
901int PageSet::SetOverlay(Page* page)
902{
Ethan Yonker1c273312015-03-16 12:18:56 -0500903 if (page) {
904 if (mOverlays.size() >= 10) {
905 LOGERR("Too many overlays requested, max is 10.\n");
906 return -1;
907 }
Matt Mowerd411f8d2015-04-09 16:04:12 -0500908
909 std::vector<Page*>::iterator iter;
910 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
911 if ((*iter)->GetName() == page->GetName()) {
912 mOverlays.erase(iter);
913 // SetOverlay() is (and should stay) the only function which
914 // adds to mOverlays. Then, each page can appear at most once.
915 break;
916 }
917 }
918
Ethan Yonker1c273312015-03-16 12:18:56 -0500919 page->SetPageFocus(1);
920 page->NotifyVarChange("", "");
921
922 if (!mOverlays.empty())
923 mOverlays.back()->SetPageFocus(0);
924
925 mOverlays.push_back(page);
926 } else {
927 if (!mOverlays.empty()) {
928 mOverlays.back()->SetPageFocus(0);
929 mOverlays.pop_back();
930 if (!mOverlays.empty())
931 mOverlays.back()->SetPageFocus(1);
932 else if (mCurrentPage)
933 mCurrentPage->SetPageFocus(1); // Just in case somehow the regular page lost focus, we'll set it again
934 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200935 }
936 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400937}
938
that74ac6062015-03-04 22:39:34 +0100939const ResourceManager* PageSet::GetResources()
Dees_Troy51a0e822012-09-05 15:24:24 -0400940{
that74ac6062015-03-04 22:39:34 +0100941 return mResources;
Dees_Troy51a0e822012-09-05 15:24:24 -0400942}
943
944Page* PageSet::FindPage(std::string name)
945{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200946 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400947
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200948 for (iter = mPages.begin(); iter != mPages.end(); iter++)
949 {
950 if (name == (*iter)->GetName())
951 return (*iter);
952 }
953 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400954}
955
956int PageSet::LoadVariables(xml_node<>* vars)
957{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200958 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100959 xml_attribute<> *name, *value, *persist;
960 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400961
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200962 child = vars->first_node("variable");
963 while (child)
964 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100965 name = child->first_attribute("name");
966 value = child->first_attribute("value");
967 persist = child->first_attribute("persist");
968 if(name && value)
969 {
Ethan Yonker751a85e2014-12-12 16:59:10 -0600970 if (strcmp(name->value(), "tw_x_offset") == 0) {
971 tw_x_offset = atoi(value->value());
972 child = child->next_sibling("variable");
973 continue;
974 }
975 if (strcmp(name->value(), "tw_y_offset") == 0) {
976 tw_y_offset = atoi(value->value());
977 child = child->next_sibling("variable");
978 continue;
979 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100980 p = persist ? atoi(persist->value()) : 0;
Ethan Yonker96acb3d2014-08-05 09:20:30 -0500981 string temp = value->value();
982 string valstr = gui_parse_text(temp);
983
984 if (valstr.find("+") != string::npos) {
985 string val1str = valstr;
986 val1str = val1str.substr(0, val1str.find('+'));
987 string val2str = valstr;
988 val2str = val2str.substr(val2str.find('+') + 1, string::npos);
989 int val1 = atoi(val1str.c_str());
990 int val2 = atoi(val2str.c_str());
991 int val = val1 + val2;
992
993 DataManager::SetValue(name->value(), val, p);
994 } else if (valstr.find("-") != string::npos) {
995 string val1str = valstr;
996 val1str = val1str.substr(0, val1str.find('-'));
997 string val2str = valstr;
998 val2str = val2str.substr(val2str.find('-') + 1, string::npos);
999 int val1 = atoi(val1str.c_str());
1000 int val2 = atoi(val2str.c_str());
1001 int val = val1 - val2;
1002
1003 DataManager::SetValue(name->value(), val, p);
1004 } else {
1005 DataManager::SetValue(name->value(), valstr, p);
1006 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +01001007 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001008
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001009 child = child->next_sibling("variable");
1010 }
1011 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001012}
1013
Ethan Yonker780cd392014-07-21 15:24:39 -05001014int PageSet::LoadPages(xml_node<>* pages)
Dees_Troy51a0e822012-09-05 15:24:24 -04001015{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001016 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -04001017
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001018 if (!pages)
1019 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001020
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001021 child = pages->first_node("page");
1022 while (child != NULL)
1023 {
Ethan Yonker780cd392014-07-21 15:24:39 -05001024 Page* page = new Page(child, &templates);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001025 if (page->GetName().empty())
1026 {
1027 LOGERR("Unable to process load page\n");
1028 delete page;
1029 }
1030 else
1031 {
1032 mPages.push_back(page);
1033 }
1034 child = child->next_sibling("page");
1035 }
1036 if (mPages.size() > 0)
1037 return 0;
1038 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001039}
1040
1041int PageSet::IsCurrentPage(Page* page)
1042{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001043 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001044}
1045
1046int PageSet::Render(void)
1047{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001048 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001049
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001050 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
1051 if (ret < 0)
1052 return ret;
Ethan Yonker1c273312015-03-16 12:18:56 -05001053
1054 std::vector<Page*>::iterator iter;
1055
1056 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
1057 ret = ((*iter) ? (*iter)->Render() : -1);
1058 if (ret < 0)
1059 return ret;
1060 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001061 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001062}
1063
1064int PageSet::Update(void)
1065{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001066 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001067
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001068 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
1069 if (ret < 0 || ret > 1)
1070 return ret;
Ethan Yonker1c273312015-03-16 12:18:56 -05001071
1072 std::vector<Page*>::iterator iter;
1073
1074 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
1075 ret = ((*iter) ? (*iter)->Update() : -1);
1076 if (ret < 0)
1077 return ret;
1078 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001079 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001080}
1081
1082int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
1083{
Ethan Yonker1c273312015-03-16 12:18:56 -05001084 if (!mOverlays.empty())
1085 return mOverlays.back()->NotifyTouch(state, x, y);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001086
1087 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001088}
1089
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001090int PageSet::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001091{
Ethan Yonker1c273312015-03-16 12:18:56 -05001092 if (!mOverlays.empty())
1093 return mOverlays.back()->NotifyKey(key, down);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001094
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001095 return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001096}
1097
1098int PageSet::NotifyKeyboard(int key)
1099{
Ethan Yonker1c273312015-03-16 12:18:56 -05001100 if (!mOverlays.empty())
1101 return mOverlays.back()->NotifyKeyboard(key);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001102
1103 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001104}
1105
1106int PageSet::SetKeyBoardFocus(int inFocus)
1107{
Ethan Yonker1c273312015-03-16 12:18:56 -05001108 if (!mOverlays.empty())
1109 return mOverlays.back()->SetKeyBoardFocus(inFocus);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001110
1111 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001112}
1113
1114int PageSet::NotifyVarChange(std::string varName, std::string value)
1115{
Ethan Yonker1c273312015-03-16 12:18:56 -05001116 std::vector<Page*>::iterator iter;
1117
1118 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++)
1119 (*iter)->NotifyVarChange(varName, value);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001120
1121 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001122}
1123
Ethan Yonker561c58d2015-10-05 08:48:22 -05001124char* PageManager::LoadFileToBuffer(std::string filename, ZipArchive* package) {
1125 size_t len;
1126 char* buffer = NULL;
1127
1128 if (!package) {
1129 // We can try to load the XML directly...
1130 LOGINFO("PageManager::LoadFileToBuffer loading filename: '%s' directly\n", filename.c_str());
1131 struct stat st;
1132 if(stat(filename.c_str(),&st) != 0) {
1133 // This isn't always an error, sometimes we request files that don't exist.
1134 return NULL;
1135 }
1136
1137 len = (size_t)st.st_size;
1138
1139 buffer = (char*) malloc(len + 1);
1140 if (!buffer) {
1141 LOGERR("PageManager::LoadFileToBuffer failed to malloc\n");
1142 return NULL;
1143 }
1144
1145 int fd = open(filename.c_str(), O_RDONLY);
1146 if (fd == -1) {
1147 LOGERR("PageManager::LoadFileToBuffer failed to open '%s' - (%s)\n", filename.c_str(), strerror(errno));
1148 free(buffer);
1149 return NULL;
1150 }
1151
1152 if (read(fd, buffer, len) < 0) {
1153 LOGERR("PageManager::LoadFileToBuffer failed to read '%s' - (%s)\n", filename.c_str(), strerror(errno));
1154 free(buffer);
1155 close(fd);
1156 return NULL;
1157 }
1158 close(fd);
1159 } else {
1160 LOGINFO("PageManager::LoadFileToBuffer loading filename: '%s' from zip\n", filename.c_str());
1161 const ZipEntry* zipentry = mzFindZipEntry(package, filename.c_str());
1162 if (zipentry == NULL) {
1163 LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
1164 return NULL;
1165 }
1166
1167 // Allocate the buffer for the file
1168 len = mzGetZipEntryUncompLen(zipentry);
1169 buffer = (char*) malloc(len + 1);
1170 if (!buffer)
1171 return NULL;
1172
1173 if (!mzExtractZipEntryToBuffer(package, zipentry, (unsigned char*) buffer)) {
1174 LOGERR("Unable to extract '%s'\n", filename.c_str());
1175 free(buffer);
1176 return NULL;
1177 }
1178 }
1179 // NULL-terminate the string
1180 buffer[len] = 0x00;
1181 return buffer;
1182}
1183
Dees_Troy51a0e822012-09-05 15:24:24 -04001184int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
1185{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001186 int fd;
1187 ZipArchive zip, *pZip = NULL;
1188 long len;
1189 char* xmlFile = NULL;
1190 PageSet* pageSet = NULL;
1191 int ret;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001192 MemMapping map;
Dees_Troy51a0e822012-09-05 15:24:24 -04001193
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -05001194 mReloadTheme = false;
1195 mStartPage = startpage;
1196
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001197 // Open the XML file
1198 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001199 if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001200 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001201 LOGINFO("Load XML directly\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -06001202 tw_x_offset = TW_X_OFFSET;
1203 tw_y_offset = TW_Y_OFFSET;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001204 }
1205 else
1206 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001207 LOGINFO("Loading zip theme\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -06001208 tw_x_offset = 0;
1209 tw_y_offset = 0;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001210 if (!TWFunc::Path_Exists(package))
1211 return -1;
1212 if (sysMapFile(package.c_str(), &map) != 0) {
1213 LOGERR("Failed to map '%s'\n", package.c_str());
Ethan Yonker561c58d2015-10-05 08:48:22 -05001214 goto error;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001215 }
1216 if (mzOpenZipArchive(map.addr, map.length, &zip)) {
1217 LOGERR("Unable to open zip archive '%s'\n", package.c_str());
1218 sysReleaseMap(&map);
Ethan Yonker561c58d2015-10-05 08:48:22 -05001219 goto error;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001220 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001221 pZip = &zip;
Ethan Yonker561c58d2015-10-05 08:48:22 -05001222 package = "ui.xml";
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001223 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001224
Ethan Yonker561c58d2015-10-05 08:48:22 -05001225 xmlFile = LoadFileToBuffer(package, pZip);
1226 if (xmlFile == NULL) {
1227 goto error;
1228 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001229
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001230 // Before loading, mCurrentSet must be the loading package so we can find resources
1231 pageSet = mCurrentSet;
1232 mCurrentSet = new PageSet(xmlFile);
1233
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -05001234 ret = mCurrentSet->Load(pZip, xmlFile);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001235 if (ret == 0)
1236 {
1237 mCurrentSet->SetPage(startpage);
1238 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
1239 }
1240 else
1241 {
1242 LOGERR("Package %s failed to load.\n", name.c_str());
1243 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001244
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001245 // The first successful package we loaded is the base
1246 if (mBaseSet == NULL)
1247 mBaseSet = mCurrentSet;
1248
1249 mCurrentSet = pageSet;
1250
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001251 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001252 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001253 sysReleaseMap(&map);
1254 }
Ethan Yonker561c58d2015-10-05 08:48:22 -05001255 free(xmlFile);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001256 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001257
1258error:
Ethan Yonker561c58d2015-10-05 08:48:22 -05001259 // Sometimes we get here without a real error
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001260 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001261 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001262 sysReleaseMap(&map);
1263 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001264 if (xmlFile)
1265 free(xmlFile);
1266 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001267}
1268
1269PageSet* PageManager::FindPackage(std::string name)
1270{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001271 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001272
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001273 iter = mPageSets.find(name);
1274 if (iter != mPageSets.end())
1275 return (*iter).second;
1276
1277 LOGERR("Unable to locate package %s\n", name.c_str());
1278 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -04001279}
1280
1281PageSet* PageManager::SelectPackage(std::string name)
1282{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001283 LOGINFO("Switching packages (%s)\n", name.c_str());
1284 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001285
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001286 tmp = FindPackage(name);
1287 if (tmp)
Vojtech Bocek07220562014-02-08 02:05:33 +01001288 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001289 mCurrentSet = tmp;
Vojtech Bocek07220562014-02-08 02:05:33 +01001290 mCurrentSet->NotifyVarChange("", "");
1291 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001292 else
1293 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001294
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001295 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -04001296}
1297
1298int PageManager::ReloadPackage(std::string name, std::string package)
1299{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001300 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001301
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -05001302 mReloadTheme = false;
1303
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001304 iter = mPageSets.find(name);
1305 if (iter == mPageSets.end())
1306 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001307
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001308 if(mMouseCursor)
1309 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
1310
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001311 PageSet* set = (*iter).second;
1312 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -04001313
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -05001314 if (LoadPackage(name, package, mStartPage) != 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001315 {
Dees Troy3454ade2015-01-20 19:21:04 +00001316 LOGERR("Failed to load package '%s'.\n", package.c_str());
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001317 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
1318 return -1;
1319 }
1320 if (mCurrentSet == set)
1321 SelectPackage(name);
Vojtech Bocekbfb63342014-02-08 00:32:31 +01001322 if (mBaseSet == set)
1323 mBaseSet = mCurrentSet;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001324 delete set;
1325 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001326}
1327
1328void PageManager::ReleasePackage(std::string name)
1329{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001330 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001331
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001332 iter = mPageSets.find(name);
1333 if (iter == mPageSets.end())
1334 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001335
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001336 PageSet* set = (*iter).second;
1337 mPageSets.erase(iter);
1338 delete set;
1339 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001340}
1341
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -05001342int PageManager::RunReload() {
1343 int ret_val = 0;
1344 std::string theme_path;
1345
1346 if (!mReloadTheme)
1347 return 0;
1348
1349 mReloadTheme = false;
1350 theme_path = DataManager::GetSettingsStoragePath();
1351 if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
1352 LOGERR("Unable to mount %s during gui_reload_theme function.\n", theme_path.c_str());
1353 ret_val = 1;
1354 }
1355
1356 theme_path += "/TWRP/theme/ui.zip";
1357 if (ret_val != 0 || ReloadPackage("TWRP", theme_path) != 0)
1358 {
1359 // Loading the custom theme failed - try loading the stock theme
1360 LOGINFO("Attempting to reload stock theme...\n");
1361 if (ReloadPackage("TWRP", TWRES "ui.xml"))
1362 {
1363 LOGERR("Failed to load base packages.\n");
1364 ret_val = 1;
1365 }
1366 }
1367 return ret_val;
1368}
1369
1370void PageManager::RequestReload() {
1371 mReloadTheme = true;
1372}
1373
Dees_Troy51a0e822012-09-05 15:24:24 -04001374int PageManager::ChangePage(std::string name)
1375{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001376 DataManager::SetValue("tw_operation_state", 0);
1377 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
1378 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001379}
1380
1381int PageManager::ChangeOverlay(std::string name)
1382{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001383 if (name.empty())
1384 return mCurrentSet->SetOverlay(NULL);
1385 else
1386 {
1387 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
1388 return mCurrentSet->SetOverlay(page);
1389 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001390}
1391
that74ac6062015-03-04 22:39:34 +01001392const ResourceManager* PageManager::GetResources()
Dees_Troy51a0e822012-09-05 15:24:24 -04001393{
that74ac6062015-03-04 22:39:34 +01001394 return (mCurrentSet ? mCurrentSet->GetResources() : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001395}
1396
1397int PageManager::SwitchToConsole(void)
1398{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001399 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001400
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001401 mCurrentSet = console;
1402 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001403}
1404
Ethan Yonker03a42f62014-08-08 11:03:51 -05001405int PageManager::EndConsole(void)
1406{
1407 if (mCurrentSet && mBaseSet) {
1408 delete mCurrentSet;
1409 mCurrentSet = mBaseSet;
1410 return 0;
1411 }
1412 return -1;
1413}
1414
Dees_Troy51a0e822012-09-05 15:24:24 -04001415int PageManager::IsCurrentPage(Page* page)
1416{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001417 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001418}
1419
1420int PageManager::Render(void)
1421{
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -05001422 if(blankTimer.isScreenOff())
1423 return 0;
1424
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001425 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
1426 if(mMouseCursor)
1427 mMouseCursor->Render();
1428 return res;
1429}
1430
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001431HardwareKeyboard *PageManager::GetHardwareKeyboard()
1432{
1433 if(!mHardwareKeyboard)
1434 mHardwareKeyboard = new HardwareKeyboard();
1435 return mHardwareKeyboard;
1436}
1437
Ethan Yonker21ff02a2015-02-18 14:35:00 -06001438xml_node<>* PageManager::FindStyle(std::string name)
1439{
1440 for (std::vector<xml_node<>*>::iterator itr = mCurrentSet->styles.begin(); itr != mCurrentSet->styles.end(); itr++) {
1441 xml_node<>* node = (*itr)->first_node("style");
1442
1443 while (node) {
1444 if (!node->first_attribute("name"))
1445 continue;
1446
1447 if (name == node->first_attribute("name")->value())
1448 return node;
1449 node = node->next_sibling("style");
1450 }
1451 }
1452 return NULL;
1453}
1454
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001455MouseCursor *PageManager::GetMouseCursor()
1456{
1457 if(!mMouseCursor)
1458 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1459 return mMouseCursor;
1460}
1461
1462void PageManager::LoadCursorData(xml_node<>* node)
1463{
1464 if(!mMouseCursor)
1465 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1466
1467 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -04001468}
1469
1470int PageManager::Update(void)
1471{
thatfb759d42015-01-11 12:16:53 +01001472 if(blankTimer.isScreenOff())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001473 return 0;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001474
Ethan Yonkere0f1f3b2015-10-27 09:49:01 -05001475 if (RunReload())
1476 return -2;
1477
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001478 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
1479
1480 if(mMouseCursor)
1481 {
1482 int c_res = mMouseCursor->Update();
1483 if(c_res > res)
1484 res = c_res;
1485 }
1486 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -04001487}
1488
1489int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
1490{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001491 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001492}
1493
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001494int PageManager::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001495{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001496 return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001497}
1498
1499int PageManager::NotifyKeyboard(int key)
1500{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001501 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001502}
1503
1504int PageManager::SetKeyBoardFocus(int inFocus)
1505{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001506 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001507}
1508
1509int PageManager::NotifyVarChange(std::string varName, std::string value)
1510{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001511 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001512}
1513
1514extern "C" void gui_notifyVarChange(const char *name, const char* value)
1515{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001516 if (!gGuiRunning)
1517 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001518
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001519 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001520}