blob: 9aea1b85abfeffcace02b023241a0d806f97f3ae [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"
gordon13370d9133d2013-06-08 14:17:07 +020044#include "blanktimer.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040045
46extern int gGuiRunning;
gordon13370d9133d2013-06-08 14:17:07 +020047extern blanktimer blankTimer;
Dees_Troy51a0e822012-09-05 15:24:24 -040048
49std::map<std::string, PageSet*> PageManager::mPageSets;
50PageSet* PageManager::mCurrentSet;
51PageSet* PageManager::mBaseSet = NULL;
52
Dees_Troy51a0e822012-09-05 15:24:24 -040053// Helper routine to convert a string to a color declaration
54int ConvertStrToColor(std::string str, COLOR* color)
55{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020056 // Set the default, solid black
57 memset(color, 0, sizeof(COLOR));
58 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040059
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020060 // Translate variables
61 DataManager::GetValue(str, str);
62
63 // Look for some defaults
64 if (str == "black") return 0;
65 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
66 else if (str == "red") { color->red = 255; return 0; }
67 else if (str == "green") { color->green = 255; return 0; }
68 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040069
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020070 // At this point, we require an RGB(A) color
71 if (str[0] != '#')
72 return -1;
73
74 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040075
Dees_Troy30b962e2012-10-19 20:48:59 -040076 int result;
77 if (str.size() >= 8) {
78 // We have alpha channel
79 string alpha = str.substr(6, 2);
80 result = strtol(alpha.c_str(), NULL, 16);
81 color->alpha = result & 0x000000FF;
82 str.resize(6);
83 result = strtol(str.c_str(), NULL, 16);
84 color->red = (result >> 16) & 0x000000FF;
85 color->green = (result >> 8) & 0x000000FF;
86 color->blue = result & 0x000000FF;
87 } else {
88 result = strtol(str.c_str(), NULL, 16);
89 color->red = (result >> 16) & 0x000000FF;
90 color->green = (result >> 8) & 0x000000FF;
91 color->blue = result & 0x000000FF;
92 }
93 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -040094}
95
96// Helper APIs
97bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
98{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020099 if (!node)
100 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400101
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200102 std::string value;
103 if (node->first_attribute("x"))
104 {
105 value = node->first_attribute("x")->value();
106 DataManager::GetValue(value, value);
107 *x = atol(value.c_str());
108 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400109
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200110 if (node->first_attribute("y"))
111 {
112 value = node->first_attribute("y")->value();
113 DataManager::GetValue(value, value);
114 *y = atol(value.c_str());
115 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400116
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200117 if (w && node->first_attribute("w"))
118 {
119 value = node->first_attribute("w")->value();
120 DataManager::GetValue(value, value);
121 *w = atol(value.c_str());
122 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400123
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200124 if (h && node->first_attribute("h"))
125 {
126 value = node->first_attribute("h")->value();
127 DataManager::GetValue(value, value);
128 *h = atol(value.c_str());
129 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400130
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200131 if (placement && node->first_attribute("placement"))
132 {
133 value = node->first_attribute("placement")->value();
134 DataManager::GetValue(value, value);
135 *placement = (RenderObject::Placement) atol(value.c_str());
136 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400137
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200138 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400139}
140
141int ActionObject::SetActionPos(int x, int y, int w, int h)
142{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200143 if (x < 0 || y < 0)
144 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400145
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200146 mActionX = x;
147 mActionY = y;
148 if (w || h)
149 {
150 mActionW = w;
151 mActionH = h;
152 }
153 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400154}
155
156Page::Page(xml_node<>* page, xml_node<>* templates /* = NULL */)
157{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200158 mTouchStart = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400159
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200160 // We can memset the whole structure, because the alpha channel is ignored
161 memset(&mBackground, 0, sizeof(COLOR));
Dees_Troy51a0e822012-09-05 15:24:24 -0400162
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200163 // With NULL, we make a console-only display
164 if (!page)
165 {
166 mName = "console";
Dees_Troy51a0e822012-09-05 15:24:24 -0400167
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200168 GUIConsole* element = new GUIConsole(NULL);
169 mRenders.push_back(element);
170 mActions.push_back(element);
171 return;
172 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400173
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200174 if (page->first_attribute("name"))
175 mName = page->first_attribute("name")->value();
176 else
177 {
178 LOGERR("No page name attribute found!\n");
179 return;
180 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400181
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200182 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400183
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200184 // This is a recursive routine for template handling
185 ProcessNode(page, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400186
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200187 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400188}
189
190bool Page::ProcessNode(xml_node<>* page, xml_node<>* templates /* = NULL */, int depth /* = 0 */)
191{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200192 if (depth == 10)
193 {
194 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
195 return false;
196 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400197
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200198 // Let's retrieve the background value, if any
199 xml_node<>* bg = page->first_node("background");
200 if (bg)
201 {
202 xml_attribute<>* attr = bg->first_attribute("color");
203 if (attr)
204 {
205 std::string color = attr->value();
206 ConvertStrToColor(color, &mBackground);
207 }
208 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400209
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200210 xml_node<>* child;
211 child = page->first_node("object");
212 while (child)
213 {
214 if (!child->first_attribute("type"))
215 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400216
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200217 std::string type = child->first_attribute("type")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400218
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200219 if (type == "text")
220 {
221 GUIText* element = new GUIText(child);
222 mRenders.push_back(element);
223 mActions.push_back(element);
224 }
225 else if (type == "image")
226 {
227 GUIImage* element = new GUIImage(child);
228 mRenders.push_back(element);
229 }
230 else if (type == "fill")
231 {
232 GUIFill* element = new GUIFill(child);
233 mRenders.push_back(element);
234 }
235 else if (type == "action")
236 {
237 GUIAction* element = new GUIAction(child);
238 mActions.push_back(element);
239 }
240 else if (type == "console")
241 {
242 GUIConsole* element = new GUIConsole(child);
243 mRenders.push_back(element);
244 mActions.push_back(element);
245 }
246 else if (type == "button")
247 {
248 GUIButton* element = new GUIButton(child);
249 mRenders.push_back(element);
250 mActions.push_back(element);
251 }
252 else if (type == "checkbox")
253 {
254 GUICheckbox* element = new GUICheckbox(child);
255 mRenders.push_back(element);
256 mActions.push_back(element);
257 }
258 else if (type == "fileselector")
259 {
260 GUIFileSelector* element = new GUIFileSelector(child);
261 mRenders.push_back(element);
262 mActions.push_back(element);
263 }
264 else if (type == "animation")
265 {
266 GUIAnimation* element = new GUIAnimation(child);
267 mRenders.push_back(element);
268 }
269 else if (type == "progressbar")
270 {
271 GUIProgressBar* element = new GUIProgressBar(child);
272 mRenders.push_back(element);
273 mActions.push_back(element);
274 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400275 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200276 {
277 GUISlider* element = new GUISlider(child);
278 mRenders.push_back(element);
279 mActions.push_back(element);
280 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200281 else if (type == "slidervalue")
282 {
283 GUISliderValue *element = new GUISliderValue(child);
284 mRenders.push_back(element);
285 mActions.push_back(element);
286 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400287 else if (type == "listbox")
288 {
289 GUIListBox* element = new GUIListBox(child);
290 mRenders.push_back(element);
291 mActions.push_back(element);
292 }
293 else if (type == "keyboard")
294 {
295 GUIKeyboard* element = new GUIKeyboard(child);
296 mRenders.push_back(element);
297 mActions.push_back(element);
298 }
299 else if (type == "input")
300 {
301 GUIInput* element = new GUIInput(child);
302 mRenders.push_back(element);
303 mActions.push_back(element);
304 mInputs.push_back(element);
305 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500306 else if (type == "partitionlist")
307 {
308 GUIPartitionList* element = new GUIPartitionList(child);
309 mRenders.push_back(element);
310 mActions.push_back(element);
311 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200312 else if (type == "template")
313 {
314 if (!templates || !child->first_attribute("name"))
315 {
316 LOGERR("Invalid template request.\n");
317 }
318 else
319 {
320 std::string name = child->first_attribute("name")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400321
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200322 // We need to find the correct template
323 xml_node<>* node;
324 node = templates->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400325
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200326 while (node)
327 {
328 if (!node->first_attribute("name"))
329 continue;
Dees_Troy51a0e822012-09-05 15:24:24 -0400330
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200331 if (name == node->first_attribute("name")->value())
332 {
333 if (!ProcessNode(node, templates, depth + 1))
334 return false;
335 else
336 break;
337 }
338 node = node->next_sibling("template");
339 }
340 }
341 }
342 else
343 {
344 LOGERR("Unknown object type.\n");
345 }
346 child = child->next_sibling("object");
347 }
348 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400349}
350
351int Page::Render(void)
352{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200353 // Render background
354 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
355 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400356
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200357 // Render remaining objects
358 std::vector<RenderObject*>::iterator iter;
359 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
360 {
361 if ((*iter)->Render())
362 LOGERR("A render request has failed.\n");
363 }
364 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400365}
366
367int Page::Update(void)
368{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200369 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400370
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200371 std::vector<RenderObject*>::iterator iter;
372 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
373 {
374 int ret = (*iter)->Update();
375 if (ret < 0)
376 LOGERR("An update request has failed.\n");
377 else if (ret > retCode)
378 retCode = ret;
379 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400380
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200381 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400382}
383
384int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
385{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200386 // By default, return 1 to ignore further touches if nobody is listening
387 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400388
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200389 // Don't try to handle a lack of handlers
390 if (mActions.size() == 0)
391 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400392
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200393 // We record mTouchStart so we can pass all the touch stream to the same handler
394 if (state == TOUCH_START)
395 {
396 std::vector<ActionObject*>::reverse_iterator iter;
397 // We work backwards, from top-most element to bottom-most element
398 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
399 {
400 if ((*iter)->IsInRegion(x, y))
401 {
402 mTouchStart = (*iter);
403 ret = mTouchStart->NotifyTouch(state, x, y);
404 if (ret >= 0)
405 break;
406 mTouchStart = NULL;
407 }
408 }
409 }
410 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
411 {
412 ret = mTouchStart->NotifyTouch(state, x, y);
413 mTouchStart = NULL;
414 }
415 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
416 {
417 ret = mTouchStart->NotifyTouch(state, x, y);
418 }
419 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400420}
421
422int Page::NotifyKey(int key)
423{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200424 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400425
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200426 // Don't try to handle a lack of handlers
427 if (mActions.size() == 0)
428 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400429
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200430 // We work backwards, from top-most element to bottom-most element
431 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
432 {
433 int ret = (*iter)->NotifyKey(key);
434 if (ret == 0)
435 return 0;
436 else if (ret < 0)
437 LOGERR("An action handler has returned an error");
438 }
439 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400440}
441
442int Page::NotifyKeyboard(int key)
443{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200444 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400445
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200446 // Don't try to handle a lack of handlers
447 if (mInputs.size() == 0)
448 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400449
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200450 // We work backwards, from top-most element to bottom-most element
451 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
452 {
453 int ret = (*iter)->NotifyKeyboard(key);
454 if (ret == 0)
455 return 0;
456 else if (ret < 0)
457 LOGERR("A keyboard handler has returned an error");
458 }
459 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400460}
461
462int Page::SetKeyBoardFocus(int inFocus)
463{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200464 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400465
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200466 // Don't try to handle a lack of handlers
467 if (mInputs.size() == 0)
468 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400469
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200470 // We work backwards, from top-most element to bottom-most element
471 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
472 {
473 int ret = (*iter)->SetInputFocus(inFocus);
474 if (ret == 0)
475 return 0;
476 else if (ret < 0)
477 LOGERR("An input focus handler has returned an error");
478 }
479 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400480}
481
482void Page::SetPageFocus(int inFocus)
483{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200484 // Render remaining objects
485 std::vector<RenderObject*>::iterator iter;
486 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
487 (*iter)->SetPageFocus(inFocus);
488
489 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400490}
491
492int Page::NotifyVarChange(std::string varName, std::string value)
493{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200494 std::vector<ActionObject*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400495
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200496 // Don't try to handle a lack of handlers
497 if (mActions.size() == 0)
498 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400499
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200500 for (iter = mActions.begin(); iter != mActions.end(); ++iter)
501 {
502 if ((*iter)->NotifyVarChange(varName, value))
503 LOGERR("An action handler errored on NotifyVarChange.\n");
504 }
505 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400506}
507
508PageSet::PageSet(char* xmlFile)
509{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200510 mResources = NULL;
511 mCurrentPage = NULL;
512 mOverlayPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400513
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200514 mXmlFile = xmlFile;
515 if (xmlFile)
516 mDoc.parse<0>(mXmlFile);
517 else
518 mCurrentPage = new Page(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400519}
520
521PageSet::~PageSet()
522{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200523 delete mResources;
524 free(mXmlFile);
Dees_Troy51a0e822012-09-05 15:24:24 -0400525}
526
527int PageSet::Load(ZipArchive* package)
528{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200529 xml_node<>* parent;
530 xml_node<>* child;
531 xml_node<>* templates;
Dees_Troy51a0e822012-09-05 15:24:24 -0400532
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200533 parent = mDoc.first_node("recovery");
534 if (!parent)
535 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400536
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200537 // Now, let's parse the XML
538 LOGINFO("Loading resources...\n");
539 child = parent->first_node("resources");
540 if (child)
541 mResources = new ResourceManager(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400542
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200543 LOGINFO("Loading variables...\n");
544 child = parent->first_node("variables");
545 if (child)
546 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400547
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200548 LOGINFO("Loading pages...\n");
549 // This may be NULL if no templates are present
550 templates = parent->first_node("templates");
Dees_Troy51a0e822012-09-05 15:24:24 -0400551
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200552 child = parent->first_node("pages");
553 if (!child)
554 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400555
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200556 return LoadPages(child, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400557}
558
559int PageSet::SetPage(std::string page)
560{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200561 Page* tmp = FindPage(page);
562 if (tmp)
563 {
564 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
565 mCurrentPage = tmp;
566 mCurrentPage->SetPageFocus(1);
567 mCurrentPage->NotifyVarChange("", "");
568 return 0;
569 }
570 else
571 {
572 LOGERR("Unable to locate page (%s)\n", page.c_str());
573 }
574 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400575}
576
577int PageSet::SetOverlay(Page* page)
578{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200579 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
580 mOverlayPage = page;
581 if (mOverlayPage)
582 {
583 mOverlayPage->SetPageFocus(1);
584 mOverlayPage->NotifyVarChange("", "");
585 }
586 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400587}
588
589Resource* PageSet::FindResource(std::string name)
590{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200591 return mResources ? mResources->FindResource(name) : NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400592}
593
594Page* PageSet::FindPage(std::string name)
595{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200596 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400597
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200598 for (iter = mPages.begin(); iter != mPages.end(); iter++)
599 {
600 if (name == (*iter)->GetName())
601 return (*iter);
602 }
603 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400604}
605
606int PageSet::LoadVariables(xml_node<>* vars)
607{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200608 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400609
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200610 child = vars->first_node("variable");
611 while (child)
612 {
613 if (!child->first_attribute("name"))
614 break;
615 if (!child->first_attribute("value"))
616 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400617
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200618 DataManager::SetValue(child->first_attribute("name")->value(), child->first_attribute("value")->value());
619 child = child->next_sibling("variable");
620 }
621 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400622}
623
624int PageSet::LoadPages(xml_node<>* pages, xml_node<>* templates /* = NULL */)
625{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200626 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400627
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200628 if (!pages)
629 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400630
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200631 child = pages->first_node("page");
632 while (child != NULL)
633 {
634 Page* page = new Page(child, templates);
635 if (page->GetName().empty())
636 {
637 LOGERR("Unable to process load page\n");
638 delete page;
639 }
640 else
641 {
642 mPages.push_back(page);
643 }
644 child = child->next_sibling("page");
645 }
646 if (mPages.size() > 0)
647 return 0;
648 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400649}
650
651int PageSet::IsCurrentPage(Page* page)
652{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200653 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400654}
655
656int PageSet::Render(void)
657{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200658 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400659
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200660 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
661 if (ret < 0)
662 return ret;
663 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
664 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400665}
666
667int PageSet::Update(void)
668{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200669 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400670
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200671 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
672 if (ret < 0 || ret > 1)
673 return ret;
674 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
675 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400676}
677
678int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
679{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200680 if (mOverlayPage)
681 return (mOverlayPage->NotifyTouch(state, x, y));
682
683 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400684}
685
686int PageSet::NotifyKey(int key)
687{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200688 if (mOverlayPage)
689 return (mOverlayPage->NotifyKey(key));
690
691 return (mCurrentPage ? mCurrentPage->NotifyKey(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400692}
693
694int PageSet::NotifyKeyboard(int key)
695{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200696 if (mOverlayPage)
697 return (mOverlayPage->NotifyKeyboard(key));
698
699 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400700}
701
702int PageSet::SetKeyBoardFocus(int inFocus)
703{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200704 if (mOverlayPage)
705 return (mOverlayPage->SetKeyBoardFocus(inFocus));
706
707 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400708}
709
710int PageSet::NotifyVarChange(std::string varName, std::string value)
711{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200712 if (mOverlayPage)
713 mOverlayPage->NotifyVarChange(varName, value);
714
715 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400716}
717
718int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
719{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200720 int fd;
721 ZipArchive zip, *pZip = NULL;
722 long len;
723 char* xmlFile = NULL;
724 PageSet* pageSet = NULL;
725 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400726
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200727 // Open the XML file
728 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
729 if (mzOpenZipArchive(package.c_str(), &zip))
730 {
731 // We can try to load the XML directly...
732 struct stat st;
733 if(stat(package.c_str(),&st) != 0)
734 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400735
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200736 len = st.st_size;
737 xmlFile = (char*) malloc(len + 1);
738 if (!xmlFile)
739 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400740
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200741 fd = open(package.c_str(), O_RDONLY);
742 if (fd == -1)
743 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400744
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200745 read(fd, xmlFile, len);
746 close(fd);
747 }
748 else
749 {
750 pZip = &zip;
751 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
752 if (ui_xml == NULL)
753 {
754 LOGERR("Unable to locate ui.xml in zip file\n");
755 goto error;
756 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400757
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200758 // Allocate the buffer for the file
759 len = mzGetZipEntryUncompLen(ui_xml);
760 xmlFile = (char*) malloc(len + 1);
761 if (!xmlFile)
762 goto error;
763
764 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
765 {
766 LOGERR("Unable to extract ui.xml\n");
767 goto error;
768 }
769 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400770
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200771 // NULL-terminate the string
772 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -0400773
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200774 // Before loading, mCurrentSet must be the loading package so we can find resources
775 pageSet = mCurrentSet;
776 mCurrentSet = new PageSet(xmlFile);
777
778 ret = mCurrentSet->Load(pZip);
779 if (ret == 0)
780 {
781 mCurrentSet->SetPage(startpage);
782 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
783 }
784 else
785 {
786 LOGERR("Package %s failed to load.\n", name.c_str());
787 }
788
789 // The first successful package we loaded is the base
790 if (mBaseSet == NULL)
791 mBaseSet = mCurrentSet;
792
793 mCurrentSet = pageSet;
794
795 if (pZip)
796 mzCloseZipArchive(pZip);
797 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400798
799error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200800 LOGERR("An internal error has occurred.\n");
801 if (pZip)
802 mzCloseZipArchive(pZip);
803 if (xmlFile)
804 free(xmlFile);
805 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400806}
807
808PageSet* PageManager::FindPackage(std::string name)
809{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200810 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400811
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200812 iter = mPageSets.find(name);
813 if (iter != mPageSets.end())
814 return (*iter).second;
815
816 LOGERR("Unable to locate package %s\n", name.c_str());
817 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400818}
819
820PageSet* PageManager::SelectPackage(std::string name)
821{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200822 LOGINFO("Switching packages (%s)\n", name.c_str());
823 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -0400824
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200825 tmp = FindPackage(name);
826 if (tmp)
827 mCurrentSet = tmp;
828 else
829 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400830
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200831 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -0400832}
833
834int PageManager::ReloadPackage(std::string name, std::string package)
835{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200836 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400837
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200838 iter = mPageSets.find(name);
839 if (iter == mPageSets.end())
840 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400841
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200842 PageSet* set = (*iter).second;
843 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -0400844
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200845 if (LoadPackage(name, package, "main") != 0)
846 {
847 LOGERR("Failed to load package.\n");
848 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
849 return -1;
850 }
851 if (mCurrentSet == set)
852 SelectPackage(name);
853 delete set;
854 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400855}
856
857void PageManager::ReleasePackage(std::string name)
858{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200859 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400860
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200861 iter = mPageSets.find(name);
862 if (iter == mPageSets.end())
863 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400864
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200865 PageSet* set = (*iter).second;
866 mPageSets.erase(iter);
867 delete set;
868 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400869}
870
871int PageManager::ChangePage(std::string name)
872{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200873 DataManager::SetValue("tw_operation_state", 0);
874 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
875 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400876}
877
878int PageManager::ChangeOverlay(std::string name)
879{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200880 if (name.empty())
881 return mCurrentSet->SetOverlay(NULL);
882 else
883 {
884 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
885 return mCurrentSet->SetOverlay(page);
886 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400887}
888
889Resource* PageManager::FindResource(std::string name)
890{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200891 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400892}
893
894Resource* PageManager::FindResource(std::string package, std::string name)
895{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200896 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -0400897
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200898 tmp = FindPackage(name);
899 return (tmp ? tmp->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400900}
901
902int PageManager::SwitchToConsole(void)
903{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200904 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400905
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200906 mCurrentSet = console;
907 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400908}
909
910int PageManager::IsCurrentPage(Page* page)
911{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200912 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400913}
914
915int PageManager::Render(void)
916{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200917 return (mCurrentSet ? mCurrentSet->Render() : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400918}
919
920int PageManager::Update(void)
921{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200922 if(blankTimer.IsScreenOff())
923 return 0;
gordon13370d9133d2013-06-08 14:17:07 +0200924
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200925 return (mCurrentSet ? mCurrentSet->Update() : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400926}
927
928int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
929{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200930 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400931}
932
933int PageManager::NotifyKey(int key)
934{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200935 return (mCurrentSet ? mCurrentSet->NotifyKey(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400936}
937
938int PageManager::NotifyKeyboard(int key)
939{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200940 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400941}
942
943int PageManager::SetKeyBoardFocus(int inFocus)
944{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200945 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400946}
947
948int PageManager::NotifyVarChange(std::string varName, std::string value)
949{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200950 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400951}
952
953extern "C" void gui_notifyVarChange(const char *name, const char* value)
954{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200955 if (!gGuiRunning)
956 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400957
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200958 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -0400959}