blob: 2bb70e17009a5b56b3eedd767d15e6e1f73222ed [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*/
18// pages.cpp - Source to manage GUI base objects
Dees_Troy51a0e822012-09-05 15:24:24 -040019
20#include <stdarg.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <fcntl.h>
25#include <sys/reboot.h>
26#include <sys/stat.h>
27#include <sys/time.h>
28#include <sys/mman.h>
29#include <sys/types.h>
30#include <sys/ioctl.h>
31#include <time.h>
32#include <unistd.h>
33#include <stdlib.h>
34
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"
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070044#ifndef TW_NO_SCREEN_TIMEOUT
gordon13370d9133d2013-06-08 14:17:07 +020045#include "blanktimer.hpp"
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070046#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040047
48extern int gGuiRunning;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070049#ifndef TW_NO_SCREEN_TIMEOUT
gordon13370d9133d2013-06-08 14:17:07 +020050extern blanktimer blankTimer;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070051#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040052
53std::map<std::string, PageSet*> PageManager::mPageSets;
54PageSet* PageManager::mCurrentSet;
55PageSet* PageManager::mBaseSet = NULL;
56
Dees_Troy51a0e822012-09-05 15:24:24 -040057// Helper routine to convert a string to a color declaration
58int ConvertStrToColor(std::string str, COLOR* color)
59{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020060 // Set the default, solid black
61 memset(color, 0, sizeof(COLOR));
62 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040063
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020064 // Translate variables
65 DataManager::GetValue(str, str);
66
67 // Look for some defaults
68 if (str == "black") return 0;
69 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
70 else if (str == "red") { color->red = 255; return 0; }
71 else if (str == "green") { color->green = 255; return 0; }
72 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040073
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020074 // At this point, we require an RGB(A) color
75 if (str[0] != '#')
76 return -1;
77
78 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040079
Dees_Troy30b962e2012-10-19 20:48:59 -040080 int result;
81 if (str.size() >= 8) {
82 // We have alpha channel
83 string alpha = str.substr(6, 2);
84 result = strtol(alpha.c_str(), NULL, 16);
85 color->alpha = result & 0x000000FF;
86 str.resize(6);
87 result = strtol(str.c_str(), NULL, 16);
88 color->red = (result >> 16) & 0x000000FF;
89 color->green = (result >> 8) & 0x000000FF;
90 color->blue = result & 0x000000FF;
91 } else {
92 result = strtol(str.c_str(), NULL, 16);
93 color->red = (result >> 16) & 0x000000FF;
94 color->green = (result >> 8) & 0x000000FF;
95 color->blue = result & 0x000000FF;
96 }
97 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -040098}
99
100// Helper APIs
101bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
102{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200103 if (!node)
104 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400105
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200106 std::string value;
107 if (node->first_attribute("x"))
108 {
109 value = node->first_attribute("x")->value();
110 DataManager::GetValue(value, value);
111 *x = atol(value.c_str());
112 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400113
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200114 if (node->first_attribute("y"))
115 {
116 value = node->first_attribute("y")->value();
117 DataManager::GetValue(value, value);
118 *y = atol(value.c_str());
119 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400120
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200121 if (w && node->first_attribute("w"))
122 {
123 value = node->first_attribute("w")->value();
124 DataManager::GetValue(value, value);
125 *w = atol(value.c_str());
126 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400127
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200128 if (h && node->first_attribute("h"))
129 {
130 value = node->first_attribute("h")->value();
131 DataManager::GetValue(value, value);
132 *h = atol(value.c_str());
133 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400134
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200135 if (placement && node->first_attribute("placement"))
136 {
137 value = node->first_attribute("placement")->value();
138 DataManager::GetValue(value, value);
139 *placement = (RenderObject::Placement) atol(value.c_str());
140 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400141
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200142 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400143}
144
145int ActionObject::SetActionPos(int x, int y, int w, int h)
146{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200147 if (x < 0 || y < 0)
148 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400149
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200150 mActionX = x;
151 mActionY = y;
152 if (w || h)
153 {
154 mActionW = w;
155 mActionH = h;
156 }
157 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400158}
159
160Page::Page(xml_node<>* page, xml_node<>* templates /* = NULL */)
161{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200162 mTouchStart = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400163
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200164 // We can memset the whole structure, because the alpha channel is ignored
165 memset(&mBackground, 0, sizeof(COLOR));
Dees_Troy51a0e822012-09-05 15:24:24 -0400166
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200167 // With NULL, we make a console-only display
168 if (!page)
169 {
170 mName = "console";
Dees_Troy51a0e822012-09-05 15:24:24 -0400171
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200172 GUIConsole* element = new GUIConsole(NULL);
173 mRenders.push_back(element);
174 mActions.push_back(element);
175 return;
176 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400177
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200178 if (page->first_attribute("name"))
179 mName = page->first_attribute("name")->value();
180 else
181 {
182 LOGERR("No page name attribute found!\n");
183 return;
184 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400185
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200186 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400187
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200188 // This is a recursive routine for template handling
189 ProcessNode(page, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400190
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200191 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400192}
193
194bool Page::ProcessNode(xml_node<>* page, xml_node<>* templates /* = NULL */, int depth /* = 0 */)
195{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200196 if (depth == 10)
197 {
198 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
199 return false;
200 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400201
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200202 // Let's retrieve the background value, if any
203 xml_node<>* bg = page->first_node("background");
204 if (bg)
205 {
206 xml_attribute<>* attr = bg->first_attribute("color");
207 if (attr)
208 {
209 std::string color = attr->value();
210 ConvertStrToColor(color, &mBackground);
211 }
212 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400213
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200214 xml_node<>* child;
215 child = page->first_node("object");
216 while (child)
217 {
218 if (!child->first_attribute("type"))
219 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400220
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200221 std::string type = child->first_attribute("type")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400222
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200223 if (type == "text")
224 {
225 GUIText* element = new GUIText(child);
226 mRenders.push_back(element);
227 mActions.push_back(element);
228 }
229 else if (type == "image")
230 {
231 GUIImage* element = new GUIImage(child);
232 mRenders.push_back(element);
233 }
234 else if (type == "fill")
235 {
236 GUIFill* element = new GUIFill(child);
237 mRenders.push_back(element);
238 }
239 else if (type == "action")
240 {
241 GUIAction* element = new GUIAction(child);
242 mActions.push_back(element);
243 }
244 else if (type == "console")
245 {
246 GUIConsole* element = new GUIConsole(child);
247 mRenders.push_back(element);
248 mActions.push_back(element);
249 }
250 else if (type == "button")
251 {
252 GUIButton* element = new GUIButton(child);
253 mRenders.push_back(element);
254 mActions.push_back(element);
255 }
256 else if (type == "checkbox")
257 {
258 GUICheckbox* element = new GUICheckbox(child);
259 mRenders.push_back(element);
260 mActions.push_back(element);
261 }
262 else if (type == "fileselector")
263 {
264 GUIFileSelector* element = new GUIFileSelector(child);
265 mRenders.push_back(element);
266 mActions.push_back(element);
267 }
268 else if (type == "animation")
269 {
270 GUIAnimation* element = new GUIAnimation(child);
271 mRenders.push_back(element);
272 }
273 else if (type == "progressbar")
274 {
275 GUIProgressBar* element = new GUIProgressBar(child);
276 mRenders.push_back(element);
277 mActions.push_back(element);
278 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400279 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200280 {
281 GUISlider* element = new GUISlider(child);
282 mRenders.push_back(element);
283 mActions.push_back(element);
284 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200285 else if (type == "slidervalue")
286 {
287 GUISliderValue *element = new GUISliderValue(child);
288 mRenders.push_back(element);
289 mActions.push_back(element);
290 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400291 else if (type == "listbox")
292 {
293 GUIListBox* element = new GUIListBox(child);
294 mRenders.push_back(element);
295 mActions.push_back(element);
296 }
297 else if (type == "keyboard")
298 {
299 GUIKeyboard* element = new GUIKeyboard(child);
300 mRenders.push_back(element);
301 mActions.push_back(element);
302 }
303 else if (type == "input")
304 {
305 GUIInput* element = new GUIInput(child);
306 mRenders.push_back(element);
307 mActions.push_back(element);
308 mInputs.push_back(element);
309 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500310 else if (type == "partitionlist")
311 {
312 GUIPartitionList* element = new GUIPartitionList(child);
313 mRenders.push_back(element);
314 mActions.push_back(element);
315 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200316 else if (type == "template")
317 {
318 if (!templates || !child->first_attribute("name"))
319 {
320 LOGERR("Invalid template request.\n");
321 }
322 else
323 {
324 std::string name = child->first_attribute("name")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400325
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200326 // We need to find the correct template
327 xml_node<>* node;
328 node = templates->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400329
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200330 while (node)
331 {
332 if (!node->first_attribute("name"))
333 continue;
Dees_Troy51a0e822012-09-05 15:24:24 -0400334
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200335 if (name == node->first_attribute("name")->value())
336 {
337 if (!ProcessNode(node, templates, depth + 1))
338 return false;
339 else
340 break;
341 }
342 node = node->next_sibling("template");
343 }
344 }
345 }
346 else
347 {
348 LOGERR("Unknown object type.\n");
349 }
350 child = child->next_sibling("object");
351 }
352 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400353}
354
355int Page::Render(void)
356{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200357 // Render background
358 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
359 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400360
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200361 // Render remaining objects
362 std::vector<RenderObject*>::iterator iter;
363 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
364 {
365 if ((*iter)->Render())
366 LOGERR("A render request has failed.\n");
367 }
368 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400369}
370
371int Page::Update(void)
372{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200373 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400374
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200375 std::vector<RenderObject*>::iterator iter;
376 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
377 {
378 int ret = (*iter)->Update();
379 if (ret < 0)
380 LOGERR("An update request has failed.\n");
381 else if (ret > retCode)
382 retCode = ret;
383 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400384
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200385 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400386}
387
388int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
389{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200390 // By default, return 1 to ignore further touches if nobody is listening
391 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400392
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200393 // Don't try to handle a lack of handlers
394 if (mActions.size() == 0)
395 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400396
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200397 // We record mTouchStart so we can pass all the touch stream to the same handler
398 if (state == TOUCH_START)
399 {
400 std::vector<ActionObject*>::reverse_iterator iter;
401 // We work backwards, from top-most element to bottom-most element
402 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
403 {
404 if ((*iter)->IsInRegion(x, y))
405 {
406 mTouchStart = (*iter);
407 ret = mTouchStart->NotifyTouch(state, x, y);
408 if (ret >= 0)
409 break;
410 mTouchStart = NULL;
411 }
412 }
413 }
414 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
415 {
416 ret = mTouchStart->NotifyTouch(state, x, y);
417 mTouchStart = NULL;
418 }
419 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
420 {
421 ret = mTouchStart->NotifyTouch(state, x, y);
422 }
423 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400424}
425
426int Page::NotifyKey(int key)
427{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200428 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400429
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200430 // Don't try to handle a lack of handlers
431 if (mActions.size() == 0)
432 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400433
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200434 // We work backwards, from top-most element to bottom-most element
435 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
436 {
437 int ret = (*iter)->NotifyKey(key);
438 if (ret == 0)
439 return 0;
440 else if (ret < 0)
441 LOGERR("An action handler has returned an error");
442 }
443 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400444}
445
446int Page::NotifyKeyboard(int key)
447{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200448 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400449
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200450 // Don't try to handle a lack of handlers
451 if (mInputs.size() == 0)
452 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400453
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200454 // We work backwards, from top-most element to bottom-most element
455 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
456 {
457 int ret = (*iter)->NotifyKeyboard(key);
458 if (ret == 0)
459 return 0;
460 else if (ret < 0)
461 LOGERR("A keyboard handler has returned an error");
462 }
463 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400464}
465
466int Page::SetKeyBoardFocus(int inFocus)
467{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200468 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400469
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200470 // Don't try to handle a lack of handlers
471 if (mInputs.size() == 0)
472 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400473
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200474 // We work backwards, from top-most element to bottom-most element
475 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
476 {
477 int ret = (*iter)->SetInputFocus(inFocus);
478 if (ret == 0)
479 return 0;
480 else if (ret < 0)
481 LOGERR("An input focus handler has returned an error");
482 }
483 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400484}
485
486void Page::SetPageFocus(int inFocus)
487{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200488 // Render remaining objects
489 std::vector<RenderObject*>::iterator iter;
490 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
491 (*iter)->SetPageFocus(inFocus);
492
493 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400494}
495
496int Page::NotifyVarChange(std::string varName, std::string value)
497{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200498 std::vector<ActionObject*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400499
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200500 // Don't try to handle a lack of handlers
501 if (mActions.size() == 0)
502 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400503
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200504 for (iter = mActions.begin(); iter != mActions.end(); ++iter)
505 {
506 if ((*iter)->NotifyVarChange(varName, value))
507 LOGERR("An action handler errored on NotifyVarChange.\n");
508 }
509 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400510}
511
512PageSet::PageSet(char* xmlFile)
513{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200514 mResources = NULL;
515 mCurrentPage = NULL;
516 mOverlayPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400517
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200518 mXmlFile = xmlFile;
519 if (xmlFile)
520 mDoc.parse<0>(mXmlFile);
521 else
522 mCurrentPage = new Page(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400523}
524
525PageSet::~PageSet()
526{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200527 delete mResources;
528 free(mXmlFile);
Dees_Troy51a0e822012-09-05 15:24:24 -0400529}
530
531int PageSet::Load(ZipArchive* package)
532{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200533 xml_node<>* parent;
534 xml_node<>* child;
535 xml_node<>* templates;
Dees_Troy51a0e822012-09-05 15:24:24 -0400536
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200537 parent = mDoc.first_node("recovery");
538 if (!parent)
539 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400540
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200541 // Now, let's parse the XML
542 LOGINFO("Loading resources...\n");
543 child = parent->first_node("resources");
544 if (child)
545 mResources = new ResourceManager(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400546
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200547 LOGINFO("Loading variables...\n");
548 child = parent->first_node("variables");
549 if (child)
550 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400551
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200552 LOGINFO("Loading pages...\n");
553 // This may be NULL if no templates are present
554 templates = parent->first_node("templates");
Dees_Troy51a0e822012-09-05 15:24:24 -0400555
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200556 child = parent->first_node("pages");
557 if (!child)
558 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400559
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200560 return LoadPages(child, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400561}
562
563int PageSet::SetPage(std::string page)
564{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200565 Page* tmp = FindPage(page);
566 if (tmp)
567 {
568 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
569 mCurrentPage = tmp;
570 mCurrentPage->SetPageFocus(1);
571 mCurrentPage->NotifyVarChange("", "");
572 return 0;
573 }
574 else
575 {
576 LOGERR("Unable to locate page (%s)\n", page.c_str());
577 }
578 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400579}
580
581int PageSet::SetOverlay(Page* page)
582{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200583 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
584 mOverlayPage = page;
585 if (mOverlayPage)
586 {
587 mOverlayPage->SetPageFocus(1);
588 mOverlayPage->NotifyVarChange("", "");
589 }
590 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400591}
592
593Resource* PageSet::FindResource(std::string name)
594{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200595 return mResources ? mResources->FindResource(name) : NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400596}
597
598Page* PageSet::FindPage(std::string name)
599{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200600 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400601
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200602 for (iter = mPages.begin(); iter != mPages.end(); iter++)
603 {
604 if (name == (*iter)->GetName())
605 return (*iter);
606 }
607 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400608}
609
610int PageSet::LoadVariables(xml_node<>* vars)
611{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200612 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400613
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200614 child = vars->first_node("variable");
615 while (child)
616 {
617 if (!child->first_attribute("name"))
618 break;
619 if (!child->first_attribute("value"))
620 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400621
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200622 DataManager::SetValue(child->first_attribute("name")->value(), child->first_attribute("value")->value());
623 child = child->next_sibling("variable");
624 }
625 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400626}
627
628int PageSet::LoadPages(xml_node<>* pages, xml_node<>* templates /* = NULL */)
629{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200630 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400631
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200632 if (!pages)
633 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400634
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200635 child = pages->first_node("page");
636 while (child != NULL)
637 {
638 Page* page = new Page(child, templates);
639 if (page->GetName().empty())
640 {
641 LOGERR("Unable to process load page\n");
642 delete page;
643 }
644 else
645 {
646 mPages.push_back(page);
647 }
648 child = child->next_sibling("page");
649 }
650 if (mPages.size() > 0)
651 return 0;
652 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400653}
654
655int PageSet::IsCurrentPage(Page* page)
656{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200657 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400658}
659
660int PageSet::Render(void)
661{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200662 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400663
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200664 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
665 if (ret < 0)
666 return ret;
667 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
668 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400669}
670
671int PageSet::Update(void)
672{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200673 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400674
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200675 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
676 if (ret < 0 || ret > 1)
677 return ret;
678 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
679 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400680}
681
682int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
683{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200684 if (mOverlayPage)
685 return (mOverlayPage->NotifyTouch(state, x, y));
686
687 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400688}
689
690int PageSet::NotifyKey(int key)
691{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200692 if (mOverlayPage)
693 return (mOverlayPage->NotifyKey(key));
694
695 return (mCurrentPage ? mCurrentPage->NotifyKey(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400696}
697
698int PageSet::NotifyKeyboard(int key)
699{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200700 if (mOverlayPage)
701 return (mOverlayPage->NotifyKeyboard(key));
702
703 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400704}
705
706int PageSet::SetKeyBoardFocus(int inFocus)
707{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200708 if (mOverlayPage)
709 return (mOverlayPage->SetKeyBoardFocus(inFocus));
710
711 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400712}
713
714int PageSet::NotifyVarChange(std::string varName, std::string value)
715{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200716 if (mOverlayPage)
717 mOverlayPage->NotifyVarChange(varName, value);
718
719 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400720}
721
722int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
723{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200724 int fd;
725 ZipArchive zip, *pZip = NULL;
726 long len;
727 char* xmlFile = NULL;
728 PageSet* pageSet = NULL;
729 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400730
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200731 // Open the XML file
732 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
733 if (mzOpenZipArchive(package.c_str(), &zip))
734 {
735 // We can try to load the XML directly...
736 struct stat st;
737 if(stat(package.c_str(),&st) != 0)
738 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400739
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200740 len = st.st_size;
741 xmlFile = (char*) malloc(len + 1);
742 if (!xmlFile)
743 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400744
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200745 fd = open(package.c_str(), O_RDONLY);
746 if (fd == -1)
747 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400748
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200749 read(fd, xmlFile, len);
750 close(fd);
751 }
752 else
753 {
754 pZip = &zip;
755 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
756 if (ui_xml == NULL)
757 {
758 LOGERR("Unable to locate ui.xml in zip file\n");
759 goto error;
760 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400761
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200762 // Allocate the buffer for the file
763 len = mzGetZipEntryUncompLen(ui_xml);
764 xmlFile = (char*) malloc(len + 1);
765 if (!xmlFile)
766 goto error;
767
768 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
769 {
770 LOGERR("Unable to extract ui.xml\n");
771 goto error;
772 }
773 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400774
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200775 // NULL-terminate the string
776 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -0400777
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200778 // Before loading, mCurrentSet must be the loading package so we can find resources
779 pageSet = mCurrentSet;
780 mCurrentSet = new PageSet(xmlFile);
781
782 ret = mCurrentSet->Load(pZip);
783 if (ret == 0)
784 {
785 mCurrentSet->SetPage(startpage);
786 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
787 }
788 else
789 {
790 LOGERR("Package %s failed to load.\n", name.c_str());
791 }
792
793 // The first successful package we loaded is the base
794 if (mBaseSet == NULL)
795 mBaseSet = mCurrentSet;
796
797 mCurrentSet = pageSet;
798
799 if (pZip)
800 mzCloseZipArchive(pZip);
801 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400802
803error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200804 LOGERR("An internal error has occurred.\n");
805 if (pZip)
806 mzCloseZipArchive(pZip);
807 if (xmlFile)
808 free(xmlFile);
809 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400810}
811
812PageSet* PageManager::FindPackage(std::string name)
813{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200814 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400815
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200816 iter = mPageSets.find(name);
817 if (iter != mPageSets.end())
818 return (*iter).second;
819
820 LOGERR("Unable to locate package %s\n", name.c_str());
821 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400822}
823
824PageSet* PageManager::SelectPackage(std::string name)
825{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200826 LOGINFO("Switching packages (%s)\n", name.c_str());
827 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -0400828
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200829 tmp = FindPackage(name);
830 if (tmp)
831 mCurrentSet = tmp;
832 else
833 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400834
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200835 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -0400836}
837
838int PageManager::ReloadPackage(std::string name, std::string package)
839{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200840 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400841
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200842 iter = mPageSets.find(name);
843 if (iter == mPageSets.end())
844 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400845
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200846 PageSet* set = (*iter).second;
847 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -0400848
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200849 if (LoadPackage(name, package, "main") != 0)
850 {
851 LOGERR("Failed to load package.\n");
852 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
853 return -1;
854 }
855 if (mCurrentSet == set)
856 SelectPackage(name);
857 delete set;
858 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400859}
860
861void PageManager::ReleasePackage(std::string name)
862{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200863 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400864
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200865 iter = mPageSets.find(name);
866 if (iter == mPageSets.end())
867 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400868
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200869 PageSet* set = (*iter).second;
870 mPageSets.erase(iter);
871 delete set;
872 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400873}
874
875int PageManager::ChangePage(std::string name)
876{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200877 DataManager::SetValue("tw_operation_state", 0);
878 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
879 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400880}
881
882int PageManager::ChangeOverlay(std::string name)
883{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200884 if (name.empty())
885 return mCurrentSet->SetOverlay(NULL);
886 else
887 {
888 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
889 return mCurrentSet->SetOverlay(page);
890 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400891}
892
893Resource* PageManager::FindResource(std::string name)
894{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200895 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400896}
897
898Resource* PageManager::FindResource(std::string package, std::string name)
899{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200900 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -0400901
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200902 tmp = FindPackage(name);
903 return (tmp ? tmp->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400904}
905
906int PageManager::SwitchToConsole(void)
907{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200908 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400909
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200910 mCurrentSet = console;
911 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400912}
913
914int PageManager::IsCurrentPage(Page* page)
915{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200916 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400917}
918
919int PageManager::Render(void)
920{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200921 return (mCurrentSet ? mCurrentSet->Render() : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400922}
923
924int PageManager::Update(void)
925{
Ricardo Gomezc9ecd442013-07-05 16:13:52 -0700926#ifndef TW_NO_SCREEN_TIMEOUT
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200927 if(blankTimer.IsScreenOff())
928 return 0;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -0700929#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200930 return (mCurrentSet ? mCurrentSet->Update() : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400931}
932
933int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
934{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200935 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400936}
937
938int PageManager::NotifyKey(int key)
939{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200940 return (mCurrentSet ? mCurrentSet->NotifyKey(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400941}
942
943int PageManager::NotifyKeyboard(int key)
944{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200945 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400946}
947
948int PageManager::SetKeyBoardFocus(int inFocus)
949{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200950 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400951}
952
953int PageManager::NotifyVarChange(std::string varName, std::string value)
954{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200955 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400956}
957
958extern "C" void gui_notifyVarChange(const char *name, const char* value)
959{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200960 if (!gGuiRunning)
961 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400962
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200963 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -0400964}