blob: dc9edc798afdb411d97d1cfffe10e326ccc702a5 [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>
35
36#include <string>
37
38extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000039#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040040#include "../minuitwrp/minui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040041}
42
43#include "rapidxml.hpp"
44#include "objects.hpp"
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070045#ifndef TW_NO_SCREEN_TIMEOUT
gordon13370d9133d2013-06-08 14:17:07 +020046#include "blanktimer.hpp"
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070047#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040048
49extern int gGuiRunning;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070050#ifndef TW_NO_SCREEN_TIMEOUT
gordon13370d9133d2013-06-08 14:17:07 +020051extern blanktimer blankTimer;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070052#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040053
54std::map<std::string, PageSet*> PageManager::mPageSets;
55PageSet* PageManager::mCurrentSet;
56PageSet* PageManager::mBaseSet = NULL;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +010057MouseCursor *PageManager::mMouseCursor = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040058
Dees_Troy51a0e822012-09-05 15:24:24 -040059// Helper routine to convert a string to a color declaration
60int ConvertStrToColor(std::string str, COLOR* color)
61{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020062 // Set the default, solid black
63 memset(color, 0, sizeof(COLOR));
64 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040065
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020066 // Translate variables
67 DataManager::GetValue(str, str);
68
69 // Look for some defaults
70 if (str == "black") return 0;
71 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
72 else if (str == "red") { color->red = 255; return 0; }
73 else if (str == "green") { color->green = 255; return 0; }
74 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040075
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020076 // At this point, we require an RGB(A) color
77 if (str[0] != '#')
78 return -1;
79
80 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040081
Dees_Troy30b962e2012-10-19 20:48:59 -040082 int result;
83 if (str.size() >= 8) {
84 // We have alpha channel
85 string alpha = str.substr(6, 2);
86 result = strtol(alpha.c_str(), NULL, 16);
87 color->alpha = result & 0x000000FF;
88 str.resize(6);
89 result = strtol(str.c_str(), NULL, 16);
90 color->red = (result >> 16) & 0x000000FF;
91 color->green = (result >> 8) & 0x000000FF;
92 color->blue = result & 0x000000FF;
93 } else {
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 }
99 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400100}
101
102// Helper APIs
103bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
104{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200105 if (!node)
106 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400107
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200108 std::string value;
109 if (node->first_attribute("x"))
110 {
111 value = node->first_attribute("x")->value();
112 DataManager::GetValue(value, value);
113 *x = atol(value.c_str());
114 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400115
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200116 if (node->first_attribute("y"))
117 {
118 value = node->first_attribute("y")->value();
119 DataManager::GetValue(value, value);
120 *y = atol(value.c_str());
121 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400122
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200123 if (w && node->first_attribute("w"))
124 {
125 value = node->first_attribute("w")->value();
126 DataManager::GetValue(value, value);
127 *w = atol(value.c_str());
128 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400129
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200130 if (h && node->first_attribute("h"))
131 {
132 value = node->first_attribute("h")->value();
133 DataManager::GetValue(value, value);
134 *h = atol(value.c_str());
135 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400136
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200137 if (placement && node->first_attribute("placement"))
138 {
139 value = node->first_attribute("placement")->value();
140 DataManager::GetValue(value, value);
141 *placement = (RenderObject::Placement) atol(value.c_str());
142 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400143
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200144 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400145}
146
147int ActionObject::SetActionPos(int x, int y, int w, int h)
148{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200149 if (x < 0 || y < 0)
150 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400151
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200152 mActionX = x;
153 mActionY = y;
154 if (w || h)
155 {
156 mActionW = w;
157 mActionH = h;
158 }
159 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400160}
161
162Page::Page(xml_node<>* page, xml_node<>* templates /* = NULL */)
163{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200164 mTouchStart = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400165
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200166 // We can memset the whole structure, because the alpha channel is ignored
167 memset(&mBackground, 0, sizeof(COLOR));
Dees_Troy51a0e822012-09-05 15:24:24 -0400168
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200169 // With NULL, we make a console-only display
170 if (!page)
171 {
172 mName = "console";
Dees_Troy51a0e822012-09-05 15:24:24 -0400173
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200174 GUIConsole* element = new GUIConsole(NULL);
175 mRenders.push_back(element);
176 mActions.push_back(element);
177 return;
178 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400179
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200180 if (page->first_attribute("name"))
181 mName = page->first_attribute("name")->value();
182 else
183 {
184 LOGERR("No page name attribute found!\n");
185 return;
186 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400187
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200188 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400189
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200190 // This is a recursive routine for template handling
191 ProcessNode(page, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400192
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200193 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400194}
195
196bool Page::ProcessNode(xml_node<>* page, xml_node<>* templates /* = NULL */, int depth /* = 0 */)
197{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200198 if (depth == 10)
199 {
200 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
201 return false;
202 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400203
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200204 // Let's retrieve the background value, if any
205 xml_node<>* bg = page->first_node("background");
206 if (bg)
207 {
208 xml_attribute<>* attr = bg->first_attribute("color");
209 if (attr)
210 {
211 std::string color = attr->value();
212 ConvertStrToColor(color, &mBackground);
213 }
214 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400215
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200216 xml_node<>* child;
217 child = page->first_node("object");
218 while (child)
219 {
220 if (!child->first_attribute("type"))
221 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400222
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200223 std::string type = child->first_attribute("type")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400224
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200225 if (type == "text")
226 {
227 GUIText* element = new GUIText(child);
228 mRenders.push_back(element);
229 mActions.push_back(element);
230 }
231 else if (type == "image")
232 {
233 GUIImage* element = new GUIImage(child);
234 mRenders.push_back(element);
235 }
236 else if (type == "fill")
237 {
238 GUIFill* element = new GUIFill(child);
239 mRenders.push_back(element);
240 }
241 else if (type == "action")
242 {
243 GUIAction* element = new GUIAction(child);
244 mActions.push_back(element);
245 }
246 else if (type == "console")
247 {
248 GUIConsole* element = new GUIConsole(child);
249 mRenders.push_back(element);
250 mActions.push_back(element);
251 }
252 else if (type == "button")
253 {
254 GUIButton* element = new GUIButton(child);
255 mRenders.push_back(element);
256 mActions.push_back(element);
257 }
258 else if (type == "checkbox")
259 {
260 GUICheckbox* element = new GUICheckbox(child);
261 mRenders.push_back(element);
262 mActions.push_back(element);
263 }
264 else if (type == "fileselector")
265 {
266 GUIFileSelector* element = new GUIFileSelector(child);
267 mRenders.push_back(element);
268 mActions.push_back(element);
269 }
270 else if (type == "animation")
271 {
272 GUIAnimation* element = new GUIAnimation(child);
273 mRenders.push_back(element);
274 }
275 else if (type == "progressbar")
276 {
277 GUIProgressBar* element = new GUIProgressBar(child);
278 mRenders.push_back(element);
279 mActions.push_back(element);
280 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400281 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200282 {
283 GUISlider* element = new GUISlider(child);
284 mRenders.push_back(element);
285 mActions.push_back(element);
286 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200287 else if (type == "slidervalue")
288 {
289 GUISliderValue *element = new GUISliderValue(child);
290 mRenders.push_back(element);
291 mActions.push_back(element);
292 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400293 else if (type == "listbox")
294 {
295 GUIListBox* element = new GUIListBox(child);
296 mRenders.push_back(element);
297 mActions.push_back(element);
298 }
299 else if (type == "keyboard")
300 {
301 GUIKeyboard* element = new GUIKeyboard(child);
302 mRenders.push_back(element);
303 mActions.push_back(element);
304 }
305 else if (type == "input")
306 {
307 GUIInput* element = new GUIInput(child);
308 mRenders.push_back(element);
309 mActions.push_back(element);
310 mInputs.push_back(element);
311 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500312 else if (type == "partitionlist")
313 {
314 GUIPartitionList* element = new GUIPartitionList(child);
315 mRenders.push_back(element);
316 mActions.push_back(element);
317 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200318 else if (type == "template")
319 {
320 if (!templates || !child->first_attribute("name"))
321 {
322 LOGERR("Invalid template request.\n");
323 }
324 else
325 {
326 std::string name = child->first_attribute("name")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400327
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200328 // We need to find the correct template
329 xml_node<>* node;
330 node = templates->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400331
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200332 while (node)
333 {
334 if (!node->first_attribute("name"))
335 continue;
Dees_Troy51a0e822012-09-05 15:24:24 -0400336
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200337 if (name == node->first_attribute("name")->value())
338 {
339 if (!ProcessNode(node, templates, depth + 1))
340 return false;
341 else
342 break;
343 }
344 node = node->next_sibling("template");
345 }
346 }
347 }
348 else
349 {
350 LOGERR("Unknown object type.\n");
351 }
352 child = child->next_sibling("object");
353 }
354 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400355}
356
357int Page::Render(void)
358{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200359 // Render background
360 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
361 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400362
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200363 // Render remaining objects
364 std::vector<RenderObject*>::iterator iter;
365 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
366 {
367 if ((*iter)->Render())
368 LOGERR("A render request has failed.\n");
369 }
370 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400371}
372
373int Page::Update(void)
374{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200375 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400376
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200377 std::vector<RenderObject*>::iterator iter;
378 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
379 {
380 int ret = (*iter)->Update();
381 if (ret < 0)
382 LOGERR("An update request has failed.\n");
383 else if (ret > retCode)
384 retCode = ret;
385 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400386
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200387 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400388}
389
390int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
391{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200392 // By default, return 1 to ignore further touches if nobody is listening
393 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400394
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200395 // Don't try to handle a lack of handlers
396 if (mActions.size() == 0)
397 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400398
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200399 // We record mTouchStart so we can pass all the touch stream to the same handler
400 if (state == TOUCH_START)
401 {
402 std::vector<ActionObject*>::reverse_iterator iter;
403 // We work backwards, from top-most element to bottom-most element
404 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
405 {
406 if ((*iter)->IsInRegion(x, y))
407 {
408 mTouchStart = (*iter);
409 ret = mTouchStart->NotifyTouch(state, x, y);
410 if (ret >= 0)
411 break;
412 mTouchStart = NULL;
413 }
414 }
415 }
416 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
417 {
418 ret = mTouchStart->NotifyTouch(state, x, y);
419 mTouchStart = NULL;
420 }
421 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
422 {
423 ret = mTouchStart->NotifyTouch(state, x, y);
424 }
425 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400426}
427
428int Page::NotifyKey(int key)
429{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200430 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400431
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200432 // Don't try to handle a lack of handlers
433 if (mActions.size() == 0)
434 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400435
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200436 // We work backwards, from top-most element to bottom-most element
437 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
438 {
439 int ret = (*iter)->NotifyKey(key);
440 if (ret == 0)
441 return 0;
442 else if (ret < 0)
443 LOGERR("An action handler has returned an error");
444 }
445 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400446}
447
448int Page::NotifyKeyboard(int key)
449{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200450 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400451
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200452 // Don't try to handle a lack of handlers
453 if (mInputs.size() == 0)
454 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400455
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200456 // We work backwards, from top-most element to bottom-most element
457 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
458 {
459 int ret = (*iter)->NotifyKeyboard(key);
460 if (ret == 0)
461 return 0;
462 else if (ret < 0)
463 LOGERR("A keyboard handler has returned an error");
464 }
465 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400466}
467
468int Page::SetKeyBoardFocus(int inFocus)
469{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200470 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400471
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200472 // Don't try to handle a lack of handlers
473 if (mInputs.size() == 0)
474 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400475
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200476 // We work backwards, from top-most element to bottom-most element
477 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
478 {
479 int ret = (*iter)->SetInputFocus(inFocus);
480 if (ret == 0)
481 return 0;
482 else if (ret < 0)
483 LOGERR("An input focus handler has returned an error");
484 }
485 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400486}
487
488void Page::SetPageFocus(int inFocus)
489{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200490 // Render remaining objects
491 std::vector<RenderObject*>::iterator iter;
492 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
493 (*iter)->SetPageFocus(inFocus);
494
495 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400496}
497
498int Page::NotifyVarChange(std::string varName, std::string value)
499{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200500 std::vector<ActionObject*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400501
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200502 // Don't try to handle a lack of handlers
503 if (mActions.size() == 0)
504 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400505
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200506 for (iter = mActions.begin(); iter != mActions.end(); ++iter)
507 {
508 if ((*iter)->NotifyVarChange(varName, value))
509 LOGERR("An action handler errored on NotifyVarChange.\n");
510 }
511 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400512}
513
514PageSet::PageSet(char* xmlFile)
515{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200516 mResources = NULL;
517 mCurrentPage = NULL;
518 mOverlayPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400519
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200520 mXmlFile = xmlFile;
521 if (xmlFile)
522 mDoc.parse<0>(mXmlFile);
523 else
524 mCurrentPage = new Page(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400525}
526
527PageSet::~PageSet()
528{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200529 delete mResources;
530 free(mXmlFile);
Dees_Troy51a0e822012-09-05 15:24:24 -0400531}
532
533int PageSet::Load(ZipArchive* package)
534{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200535 xml_node<>* parent;
536 xml_node<>* child;
537 xml_node<>* templates;
Dees_Troy51a0e822012-09-05 15:24:24 -0400538
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200539 parent = mDoc.first_node("recovery");
540 if (!parent)
541 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400542
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200543 // Now, let's parse the XML
544 LOGINFO("Loading resources...\n");
545 child = parent->first_node("resources");
546 if (child)
547 mResources = new ResourceManager(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400548
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200549 LOGINFO("Loading variables...\n");
550 child = parent->first_node("variables");
551 if (child)
552 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400553
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100554 LOGINFO("Loading mouse cursor...\n");
555 child = parent->first_node("mousecursor");
556 if(child)
557 PageManager::LoadCursorData(child);
558
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200559 LOGINFO("Loading pages...\n");
560 // This may be NULL if no templates are present
561 templates = parent->first_node("templates");
Dees_Troy51a0e822012-09-05 15:24:24 -0400562
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200563 child = parent->first_node("pages");
564 if (!child)
565 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400566
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200567 return LoadPages(child, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400568}
569
570int PageSet::SetPage(std::string page)
571{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200572 Page* tmp = FindPage(page);
573 if (tmp)
574 {
575 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
576 mCurrentPage = tmp;
577 mCurrentPage->SetPageFocus(1);
578 mCurrentPage->NotifyVarChange("", "");
579 return 0;
580 }
581 else
582 {
583 LOGERR("Unable to locate page (%s)\n", page.c_str());
584 }
585 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400586}
587
588int PageSet::SetOverlay(Page* page)
589{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200590 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
591 mOverlayPage = page;
592 if (mOverlayPage)
593 {
594 mOverlayPage->SetPageFocus(1);
595 mOverlayPage->NotifyVarChange("", "");
596 }
597 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400598}
599
600Resource* PageSet::FindResource(std::string name)
601{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200602 return mResources ? mResources->FindResource(name) : NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400603}
604
605Page* PageSet::FindPage(std::string name)
606{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200607 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400608
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200609 for (iter = mPages.begin(); iter != mPages.end(); iter++)
610 {
611 if (name == (*iter)->GetName())
612 return (*iter);
613 }
614 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400615}
616
617int PageSet::LoadVariables(xml_node<>* vars)
618{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200619 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100620 xml_attribute<> *name, *value, *persist;
621 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400622
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200623 child = vars->first_node("variable");
624 while (child)
625 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100626 name = child->first_attribute("name");
627 value = child->first_attribute("value");
628 persist = child->first_attribute("persist");
629 if(name && value)
630 {
631 p = persist ? atoi(persist->value()) : 0;
632 DataManager::SetValue(name->value(), value->value(), p);
633 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400634
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200635 child = child->next_sibling("variable");
636 }
637 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400638}
639
640int PageSet::LoadPages(xml_node<>* pages, xml_node<>* templates /* = NULL */)
641{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200642 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400643
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200644 if (!pages)
645 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400646
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200647 child = pages->first_node("page");
648 while (child != NULL)
649 {
650 Page* page = new Page(child, templates);
651 if (page->GetName().empty())
652 {
653 LOGERR("Unable to process load page\n");
654 delete page;
655 }
656 else
657 {
658 mPages.push_back(page);
659 }
660 child = child->next_sibling("page");
661 }
662 if (mPages.size() > 0)
663 return 0;
664 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400665}
666
667int PageSet::IsCurrentPage(Page* page)
668{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200669 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400670}
671
672int PageSet::Render(void)
673{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200674 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400675
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200676 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
677 if (ret < 0)
678 return ret;
679 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
680 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400681}
682
683int PageSet::Update(void)
684{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200685 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400686
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200687 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
688 if (ret < 0 || ret > 1)
689 return ret;
690 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
691 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400692}
693
694int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
695{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200696 if (mOverlayPage)
697 return (mOverlayPage->NotifyTouch(state, x, y));
698
699 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400700}
701
702int PageSet::NotifyKey(int key)
703{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200704 if (mOverlayPage)
705 return (mOverlayPage->NotifyKey(key));
706
707 return (mCurrentPage ? mCurrentPage->NotifyKey(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400708}
709
710int PageSet::NotifyKeyboard(int key)
711{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200712 if (mOverlayPage)
713 return (mOverlayPage->NotifyKeyboard(key));
714
715 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400716}
717
718int PageSet::SetKeyBoardFocus(int inFocus)
719{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200720 if (mOverlayPage)
721 return (mOverlayPage->SetKeyBoardFocus(inFocus));
722
723 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400724}
725
726int PageSet::NotifyVarChange(std::string varName, std::string value)
727{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200728 if (mOverlayPage)
729 mOverlayPage->NotifyVarChange(varName, value);
730
731 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400732}
733
734int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
735{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200736 int fd;
737 ZipArchive zip, *pZip = NULL;
738 long len;
739 char* xmlFile = NULL;
740 PageSet* pageSet = NULL;
741 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400742
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200743 // Open the XML file
744 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
745 if (mzOpenZipArchive(package.c_str(), &zip))
746 {
747 // We can try to load the XML directly...
748 struct stat st;
749 if(stat(package.c_str(),&st) != 0)
750 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400751
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200752 len = st.st_size;
753 xmlFile = (char*) malloc(len + 1);
754 if (!xmlFile)
755 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400756
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200757 fd = open(package.c_str(), O_RDONLY);
758 if (fd == -1)
759 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400760
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200761 read(fd, xmlFile, len);
762 close(fd);
763 }
764 else
765 {
766 pZip = &zip;
767 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
768 if (ui_xml == NULL)
769 {
770 LOGERR("Unable to locate ui.xml in zip file\n");
771 goto error;
772 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400773
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200774 // Allocate the buffer for the file
775 len = mzGetZipEntryUncompLen(ui_xml);
776 xmlFile = (char*) malloc(len + 1);
777 if (!xmlFile)
778 goto error;
779
780 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
781 {
782 LOGERR("Unable to extract ui.xml\n");
783 goto error;
784 }
785 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400786
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200787 // NULL-terminate the string
788 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -0400789
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200790 // Before loading, mCurrentSet must be the loading package so we can find resources
791 pageSet = mCurrentSet;
792 mCurrentSet = new PageSet(xmlFile);
793
794 ret = mCurrentSet->Load(pZip);
795 if (ret == 0)
796 {
797 mCurrentSet->SetPage(startpage);
798 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
799 }
800 else
801 {
802 LOGERR("Package %s failed to load.\n", name.c_str());
803 }
804
805 // The first successful package we loaded is the base
806 if (mBaseSet == NULL)
807 mBaseSet = mCurrentSet;
808
809 mCurrentSet = pageSet;
810
811 if (pZip)
812 mzCloseZipArchive(pZip);
813 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400814
815error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200816 LOGERR("An internal error has occurred.\n");
817 if (pZip)
818 mzCloseZipArchive(pZip);
819 if (xmlFile)
820 free(xmlFile);
821 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400822}
823
824PageSet* PageManager::FindPackage(std::string name)
825{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200826 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400827
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200828 iter = mPageSets.find(name);
829 if (iter != mPageSets.end())
830 return (*iter).second;
831
832 LOGERR("Unable to locate package %s\n", name.c_str());
833 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400834}
835
836PageSet* PageManager::SelectPackage(std::string name)
837{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200838 LOGINFO("Switching packages (%s)\n", name.c_str());
839 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -0400840
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200841 tmp = FindPackage(name);
842 if (tmp)
843 mCurrentSet = tmp;
844 else
845 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400846
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200847 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -0400848}
849
850int PageManager::ReloadPackage(std::string name, std::string package)
851{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200852 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400853
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200854 iter = mPageSets.find(name);
855 if (iter == mPageSets.end())
856 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400857
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100858 if(mMouseCursor)
859 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
860
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200861 PageSet* set = (*iter).second;
862 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -0400863
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200864 if (LoadPackage(name, package, "main") != 0)
865 {
866 LOGERR("Failed to load package.\n");
867 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
868 return -1;
869 }
870 if (mCurrentSet == set)
871 SelectPackage(name);
872 delete set;
873 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400874}
875
876void PageManager::ReleasePackage(std::string name)
877{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200878 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400879
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200880 iter = mPageSets.find(name);
881 if (iter == mPageSets.end())
882 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400883
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200884 PageSet* set = (*iter).second;
885 mPageSets.erase(iter);
886 delete set;
887 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400888}
889
890int PageManager::ChangePage(std::string name)
891{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200892 DataManager::SetValue("tw_operation_state", 0);
893 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
894 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400895}
896
897int PageManager::ChangeOverlay(std::string name)
898{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200899 if (name.empty())
900 return mCurrentSet->SetOverlay(NULL);
901 else
902 {
903 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
904 return mCurrentSet->SetOverlay(page);
905 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400906}
907
908Resource* PageManager::FindResource(std::string name)
909{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200910 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400911}
912
913Resource* PageManager::FindResource(std::string package, std::string name)
914{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200915 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -0400916
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200917 tmp = FindPackage(name);
918 return (tmp ? tmp->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400919}
920
921int PageManager::SwitchToConsole(void)
922{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200923 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400924
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200925 mCurrentSet = console;
926 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400927}
928
929int PageManager::IsCurrentPage(Page* page)
930{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200931 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400932}
933
934int PageManager::Render(void)
935{
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100936 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
937 if(mMouseCursor)
938 mMouseCursor->Render();
939 return res;
940}
941
942MouseCursor *PageManager::GetMouseCursor()
943{
944 if(!mMouseCursor)
945 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
946 return mMouseCursor;
947}
948
949void PageManager::LoadCursorData(xml_node<>* node)
950{
951 if(!mMouseCursor)
952 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
953
954 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -0400955}
956
957int PageManager::Update(void)
958{
Ricardo Gomezc9ecd442013-07-05 16:13:52 -0700959#ifndef TW_NO_SCREEN_TIMEOUT
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200960 if(blankTimer.IsScreenOff())
961 return 0;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -0700962#endif
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100963
964 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
965
966 if(mMouseCursor)
967 {
968 int c_res = mMouseCursor->Update();
969 if(c_res > res)
970 res = c_res;
971 }
972 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -0400973}
974
975int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
976{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200977 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400978}
979
980int PageManager::NotifyKey(int key)
981{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200982 return (mCurrentSet ? mCurrentSet->NotifyKey(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400983}
984
985int PageManager::NotifyKeyboard(int key)
986{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200987 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400988}
989
990int PageManager::SetKeyBoardFocus(int inFocus)
991{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200992 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400993}
994
995int PageManager::NotifyVarChange(std::string varName, std::string value)
996{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200997 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400998}
999
1000extern "C" void gui_notifyVarChange(const char *name, const char* value)
1001{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001002 if (!gGuiRunning)
1003 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001004
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001005 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001006}