blob: 86d4dff9f50e368e07804d1b3a8df0042affa58a [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
53
54// Helper routine to convert a string to a color declaration
55int ConvertStrToColor(std::string str, COLOR* color)
56{
57 // Set the default, solid black
58 memset(color, 0, sizeof(COLOR));
59 color->alpha = 255;
60
61 // Translate variables
62 DataManager::GetValue(str, str);
63
64 // Look for some defaults
65 if (str == "black") return 0;
66 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
67 else if (str == "red") { color->red = 255; return 0; }
68 else if (str == "green") { color->green = 255; return 0; }
69 else if (str == "blue") { color->blue = 255; return 0; }
70
71 // At this point, we require an RGB(A) color
72 if (str[0] != '#') return -1;
73 str.erase(0, 1);
74
Dees_Troy30b962e2012-10-19 20:48:59 -040075 int result;
76 if (str.size() >= 8) {
77 // We have alpha channel
78 string alpha = str.substr(6, 2);
79 result = strtol(alpha.c_str(), NULL, 16);
80 color->alpha = result & 0x000000FF;
81 str.resize(6);
82 result = strtol(str.c_str(), NULL, 16);
83 color->red = (result >> 16) & 0x000000FF;
84 color->green = (result >> 8) & 0x000000FF;
85 color->blue = result & 0x000000FF;
86 } else {
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 }
92 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -040093}
94
95// Helper APIs
96bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
97{
98 if (!node) return false;
99
100 std::string value;
101 if (node->first_attribute("x"))
102 {
103 value = node->first_attribute("x")->value();
104 DataManager::GetValue(value, value);
105 *x = atol(value.c_str());
106 }
107
108 if (node->first_attribute("y"))
109 {
110 value = node->first_attribute("y")->value();
111 DataManager::GetValue(value, value);
112 *y = atol(value.c_str());
113 }
114
115 if (w && node->first_attribute("w"))
116 {
117 value = node->first_attribute("w")->value();
118 DataManager::GetValue(value, value);
119 *w = atol(value.c_str());
120 }
121
122 if (h && node->first_attribute("h"))
123 {
124 value = node->first_attribute("h")->value();
125 DataManager::GetValue(value, value);
126 *h = atol(value.c_str());
127 }
128
129 if (placement && node->first_attribute("placement"))
130 {
131 value = node->first_attribute("placement")->value();
132 DataManager::GetValue(value, value);
133 *placement = (RenderObject::Placement) atol(value.c_str());
134 }
135
136 return true;
137}
138
139int ActionObject::SetActionPos(int x, int y, int w, int h)
140{
141 if (x < 0 || y < 0) return -1;
142
143 mActionX = x;
144 mActionY = y;
145 if (w || h)
146 {
147 mActionW = w;
148 mActionH = h;
149 }
150 return 0;
151}
152
153Page::Page(xml_node<>* page, xml_node<>* templates /* = NULL */)
154{
155 mTouchStart = NULL;
156
157 // We can memset the whole structure, because the alpha channel is ignored
158 memset(&mBackground, 0, sizeof(COLOR));
159
160 // With NULL, we make a console-only display
161 if (!page)
162 {
163 mName = "console";
164
165 GUIConsole* element = new GUIConsole(NULL);
166 mRenders.push_back(element);
167 mActions.push_back(element);
168 return;
169 }
170
171 if (page->first_attribute("name"))
172 mName = page->first_attribute("name")->value();
173 else
174 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000175 LOGERR("No page name attribute found!\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400176 return;
177 }
178
Dees_Troy2673cec2013-04-02 20:22:16 +0000179 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400180
181 // This is a recursive routine for template handling
182 ProcessNode(page, templates);
183
184 return;
185}
186
187bool Page::ProcessNode(xml_node<>* page, xml_node<>* templates /* = NULL */, int depth /* = 0 */)
188{
189 if (depth == 10)
190 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000191 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400192 return false;
193 }
194
195 // Let's retrieve the background value, if any
196 xml_node<>* bg = page->first_node("background");
197 if (bg)
198 {
199 xml_attribute<>* attr = bg->first_attribute("color");
200 if (attr)
201 {
202 std::string color = attr->value();
203 ConvertStrToColor(color, &mBackground);
204 }
205 }
206
207 xml_node<>* child;
208 child = page->first_node("object");
209 while (child)
210 {
211 if (!child->first_attribute("type"))
212 break;
213
214 std::string type = child->first_attribute("type")->value();
215
216 if (type == "text")
217 {
218 GUIText* element = new GUIText(child);
219 mRenders.push_back(element);
220 mActions.push_back(element);
221 }
222 else if (type == "image")
223 {
224 GUIImage* element = new GUIImage(child);
225 mRenders.push_back(element);
226 }
227 else if (type == "fill")
228 {
229 GUIFill* element = new GUIFill(child);
230 mRenders.push_back(element);
231 }
232 else if (type == "action")
233 {
234 GUIAction* element = new GUIAction(child);
235 mActions.push_back(element);
236 }
237 else if (type == "console")
238 {
239 GUIConsole* element = new GUIConsole(child);
240 mRenders.push_back(element);
241 mActions.push_back(element);
242 }
243 else if (type == "button")
244 {
245 GUIButton* element = new GUIButton(child);
246 mRenders.push_back(element);
247 mActions.push_back(element);
248 }
249 else if (type == "checkbox")
250 {
251 GUICheckbox* element = new GUICheckbox(child);
252 mRenders.push_back(element);
253 mActions.push_back(element);
254 }
255 else if (type == "fileselector")
256 {
257 GUIFileSelector* element = new GUIFileSelector(child);
258 mRenders.push_back(element);
259 mActions.push_back(element);
260 }
261 else if (type == "animation")
262 {
263 GUIAnimation* element = new GUIAnimation(child);
264 mRenders.push_back(element);
265 }
266 else if (type == "progressbar")
267 {
268 GUIProgressBar* element = new GUIProgressBar(child);
269 mRenders.push_back(element);
270 mActions.push_back(element);
271 }
272 else if (type == "slider")
273 {
274 GUISlider* element = new GUISlider(child);
275 mRenders.push_back(element);
276 mActions.push_back(element);
277 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200278 else if (type == "slidervalue")
279 {
280 GUISliderValue *element = new GUISliderValue(child);
281 mRenders.push_back(element);
282 mActions.push_back(element);
283 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400284 else if (type == "listbox")
285 {
286 GUIListBox* element = new GUIListBox(child);
287 mRenders.push_back(element);
288 mActions.push_back(element);
289 }
290 else if (type == "keyboard")
291 {
292 GUIKeyboard* element = new GUIKeyboard(child);
293 mRenders.push_back(element);
294 mActions.push_back(element);
295 }
296 else if (type == "input")
297 {
298 GUIInput* element = new GUIInput(child);
299 mRenders.push_back(element);
300 mActions.push_back(element);
301 mInputs.push_back(element);
302 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500303 else if (type == "partitionlist")
304 {
305 GUIPartitionList* element = new GUIPartitionList(child);
306 mRenders.push_back(element);
307 mActions.push_back(element);
308 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400309 else if (type == "template")
310 {
311 if (!templates || !child->first_attribute("name"))
312 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000313 LOGERR("Invalid template request.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400314 }
315 else
316 {
317 std::string name = child->first_attribute("name")->value();
318
319 // We need to find the correct template
320 xml_node<>* node;
321 node = templates->first_node("template");
322
323 while (node)
324 {
325 if (!node->first_attribute("name"))
326 continue;
327
328 if (name == node->first_attribute("name")->value())
329 {
330 if (!ProcessNode(node, templates, depth + 1))
331 return false;
332 else
333 break;
334 }
335 node = node->next_sibling("template");
336 }
337 }
338 }
339 else
340 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000341 LOGERR("Unknown object type.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400342 }
343 child = child->next_sibling("object");
344 }
345 return true;
346}
347
348int Page::Render(void)
349{
350 // Render background
351 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
352 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
353
354 // Render remaining objects
355 std::vector<RenderObject*>::iterator iter;
356 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
357 {
358 if ((*iter)->Render())
Dees_Troy2673cec2013-04-02 20:22:16 +0000359 LOGERR("A render request has failed.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400360 }
361 return 0;
362}
363
364int Page::Update(void)
365{
366 int retCode = 0;
367
368 std::vector<RenderObject*>::iterator iter;
369 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
370 {
371 int ret = (*iter)->Update();
372 if (ret < 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000373 LOGERR("An update request has failed.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400374 else if (ret > retCode)
375 retCode = ret;
376 }
377
378 return retCode;
379}
380
381int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
382{
383 // By default, return 1 to ignore further touches if nobody is listening
384 int ret = 1;
385
386 // Don't try to handle a lack of handlers
387 if (mActions.size() == 0) return ret;
388
389 // We record mTouchStart so we can pass all the touch stream to the same handler
390 if (state == TOUCH_START)
391 {
392 std::vector<ActionObject*>::reverse_iterator iter;
393 // We work backwards, from top-most element to bottom-most element
394 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
395 {
396 if ((*iter)->IsInRegion(x, y))
397 {
398 mTouchStart = (*iter);
399 ret = mTouchStart->NotifyTouch(state, x, y);
400 if (ret >= 0) break;
401 mTouchStart = NULL;
402 }
403 }
404 }
405 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
406 {
407 ret = mTouchStart->NotifyTouch(state, x, y);
408 mTouchStart = NULL;
409 }
410 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
411 {
412 ret = mTouchStart->NotifyTouch(state, x, y);
413 }
414 return ret;
415}
416
417int Page::NotifyKey(int key)
418{
419 std::vector<ActionObject*>::reverse_iterator iter;
420
421 // Don't try to handle a lack of handlers
422 if (mActions.size() == 0) return 1;
423
424 // We work backwards, from top-most element to bottom-most element
425 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
426 {
427 int ret = (*iter)->NotifyKey(key);
428 if (ret == 0)
429 return 0;
430 else if (ret < 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000431 LOGERR("An action handler has returned an error");
Dees_Troy51a0e822012-09-05 15:24:24 -0400432 }
433 return 1;
434}
435
436int Page::NotifyKeyboard(int key)
437{
438 std::vector<InputObject*>::reverse_iterator iter;
439
440 // Don't try to handle a lack of handlers
441 if (mInputs.size() == 0) return 1;
442
443 // We work backwards, from top-most element to bottom-most element
444 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
445 {
446 int ret = (*iter)->NotifyKeyboard(key);
447 if (ret == 0)
448 return 0;
449 else if (ret < 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000450 LOGERR("A keyboard handler has returned an error");
Dees_Troy51a0e822012-09-05 15:24:24 -0400451 }
452 return 1;
453}
454
455int Page::SetKeyBoardFocus(int inFocus)
456{
457 std::vector<InputObject*>::reverse_iterator iter;
458
459 // Don't try to handle a lack of handlers
460 if (mInputs.size() == 0) return 1;
461
462 // We work backwards, from top-most element to bottom-most element
463 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
464 {
465 int ret = (*iter)->SetInputFocus(inFocus);
466 if (ret == 0)
467 return 0;
468 else if (ret < 0)
Dees_Troy2673cec2013-04-02 20:22:16 +0000469 LOGERR("An input focus handler has returned an error");
Dees_Troy51a0e822012-09-05 15:24:24 -0400470 }
471 return 1;
472}
473
474void Page::SetPageFocus(int inFocus)
475{
476 // Render remaining objects
477 std::vector<RenderObject*>::iterator iter;
478 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
479 {
480 (*iter)->SetPageFocus(inFocus);
481 }
482 return;
483}
484
485int Page::NotifyVarChange(std::string varName, std::string value)
486{
487 std::vector<ActionObject*>::iterator iter;
488
489 // Don't try to handle a lack of handlers
490 if (mActions.size() == 0) return 1;
491
492 for (iter = mActions.begin(); iter != mActions.end(); ++iter)
493 {
494 if ((*iter)->NotifyVarChange(varName, value))
Dees_Troy2673cec2013-04-02 20:22:16 +0000495 LOGERR("An action handler errored on NotifyVarChange.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400496 }
497 return 0;
498}
499
500PageSet::PageSet(char* xmlFile)
501{
502 mResources = NULL;
503 mCurrentPage = NULL;
504 mOverlayPage = NULL;
505
506 mXmlFile = xmlFile;
507 if (xmlFile)
508 mDoc.parse<0>(mXmlFile);
509 else
510 mCurrentPage = new Page(NULL);
511}
512
513PageSet::~PageSet()
514{
515 delete mResources;
516 free(mXmlFile);
517}
518
519int PageSet::Load(ZipArchive* package)
520{
521 xml_node<>* parent;
522 xml_node<>* child;
523 xml_node<>* templates;
524
525 parent = mDoc.first_node("recovery");
526 if (!parent)
527 parent = mDoc.first_node("install");
528
529 // Now, let's parse the XML
Dees_Troy2673cec2013-04-02 20:22:16 +0000530 LOGINFO("Loading resources...\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400531 child = parent->first_node("resources");
532 if (child)
533 mResources = new ResourceManager(child, package);
534
Dees_Troy2673cec2013-04-02 20:22:16 +0000535 LOGINFO("Loading variables...\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400536 child = parent->first_node("variables");
537 if (child)
538 LoadVariables(child);
539
Dees_Troy2673cec2013-04-02 20:22:16 +0000540 LOGINFO("Loading pages...\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400541 // This may be NULL if no templates are present
542 templates = parent->first_node("templates");
543
544 child = parent->first_node("pages");
545 if (!child)
546 return -1;
547
548 return LoadPages(child, templates);
549}
550
551int PageSet::SetPage(std::string page)
552{
553 Page* tmp = FindPage(page);
554 if (tmp)
555 {
556 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
557 mCurrentPage = tmp;
558 mCurrentPage->SetPageFocus(1);
559 mCurrentPage->NotifyVarChange("", "");
560 return 0;
561 }
562 else
563 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000564 LOGERR("Unable to locate page (%s)\n", page.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400565 }
566 return -1;
567}
568
569int PageSet::SetOverlay(Page* page)
570{
571 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
572 mOverlayPage = page;
573 if (mOverlayPage)
574 {
575 mOverlayPage->SetPageFocus(1);
576 mOverlayPage->NotifyVarChange("", "");
577 }
578 return 0;
579}
580
581Resource* PageSet::FindResource(std::string name)
582{
583 return mResources ? mResources->FindResource(name) : NULL;
584}
585
586Page* PageSet::FindPage(std::string name)
587{
588 std::vector<Page*>::iterator iter;
589
590 for (iter = mPages.begin(); iter != mPages.end(); iter++)
591 {
592 if (name == (*iter)->GetName())
593 return (*iter);
594 }
595 return NULL;
596}
597
598int PageSet::LoadVariables(xml_node<>* vars)
599{
600 xml_node<>* child;
601
602 child = vars->first_node("variable");
603 while (child)
604 {
605 if (!child->first_attribute("name"))
606 break;
607 if (!child->first_attribute("value"))
608 break;
609
610 DataManager::SetValue(child->first_attribute("name")->value(), child->first_attribute("value")->value());
611 child = child->next_sibling("variable");
612 }
613 return 0;
614}
615
616int PageSet::LoadPages(xml_node<>* pages, xml_node<>* templates /* = NULL */)
617{
618 xml_node<>* child;
619
620 if (!pages) return -1;
621
622 child = pages->first_node("page");
623 while (child != NULL)
624 {
625 Page* page = new Page(child, templates);
626 if (page->GetName().empty())
627 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000628 LOGERR("Unable to process load page\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400629 delete page;
630 }
631 else
632 {
633 mPages.push_back(page);
634 }
635 child = child->next_sibling("page");
636 }
637 if (mPages.size() > 0)
638 return 0;
639 return -1;
640}
641
642int PageSet::IsCurrentPage(Page* page)
643{
644 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
645}
646
647int PageSet::Render(void)
648{
649 int ret;
650
651 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
652 if (ret < 0) return ret;
653 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
654 return ret;
655}
656
657int PageSet::Update(void)
658{
659 int ret;
660
661 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
662 if (ret < 0 || ret > 1) return ret;
663 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
664 return ret;
665}
666
667int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
668{
669 if (mOverlayPage) return (mOverlayPage->NotifyTouch(state, x, y));
670 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
671}
672
673int PageSet::NotifyKey(int key)
674{
675 if (mOverlayPage) return (mOverlayPage->NotifyKey(key));
676 return (mCurrentPage ? mCurrentPage->NotifyKey(key) : -1);
677}
678
679int PageSet::NotifyKeyboard(int key)
680{
681 if (mOverlayPage) return (mOverlayPage->NotifyKeyboard(key));
682 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
683}
684
685int PageSet::SetKeyBoardFocus(int inFocus)
686{
687 if (mOverlayPage) return (mOverlayPage->SetKeyBoardFocus(inFocus));
688 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
689}
690
691int PageSet::NotifyVarChange(std::string varName, std::string value)
692{
693 if (mOverlayPage) mOverlayPage->NotifyVarChange(varName, value);
694 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
695}
696
697int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
698{
699 int fd;
700 ZipArchive zip, *pZip = NULL;
701 long len;
702 char* xmlFile = NULL;
703 PageSet* pageSet = NULL;
704 int ret;
705
706 // Open the XML file
Dees_Troy2673cec2013-04-02 20:22:16 +0000707 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400708 if (mzOpenZipArchive(package.c_str(), &zip))
709 {
710 // We can try to load the XML directly...
711 struct stat st;
712 if(stat(package.c_str(),&st) != 0)
713 return -1;
714
715 len = st.st_size;
716 xmlFile = (char*) malloc(len + 1);
717 if (!xmlFile) return -1;
718
719 fd = open(package.c_str(), O_RDONLY);
720 if (fd == -1) goto error;
721
722 read(fd, xmlFile, len);
723 close(fd);
724 }
725 else
726 {
727 pZip = &zip;
728 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
729 if (ui_xml == NULL)
730 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000731 LOGERR("Unable to locate ui.xml in zip file\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400732 goto error;
733 }
734
735 // Allocate the buffer for the file
736 len = mzGetZipEntryUncompLen(ui_xml);
737 xmlFile = (char*) malloc(len + 1);
738 if (!xmlFile) goto error;
739
740 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
741 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000742 LOGERR("Unable to extract ui.xml\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400743 goto error;
744 }
745 }
746
747 // NULL-terminate the string
748 xmlFile[len] = 0x00;
749
750 // Before loading, mCurrentSet must be the loading package so we can find resources
751 pageSet = mCurrentSet;
752 mCurrentSet = new PageSet(xmlFile);
753
754 ret = mCurrentSet->Load(pZip);
755 if (ret == 0)
756 {
757 mCurrentSet->SetPage(startpage);
758 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
759 }
760 else
761 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000762 LOGERR("Package %s failed to load.\n", name.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400763 }
764
765 // The first successful package we loaded is the base
766 if (mBaseSet == NULL)
767 mBaseSet = mCurrentSet;
768
769 mCurrentSet = pageSet;
770
771 if (pZip) mzCloseZipArchive(pZip);
772 return ret;
773
774error:
Dees_Troy2673cec2013-04-02 20:22:16 +0000775 LOGERR("An internal error has occurred.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400776 if (pZip) mzCloseZipArchive(pZip);
777 if (xmlFile) free(xmlFile);
778 return -1;
779}
780
781PageSet* PageManager::FindPackage(std::string name)
782{
783 std::map<std::string, PageSet*>::iterator iter;
784
785 iter = mPageSets.find(name);
786 if (iter != mPageSets.end())
787 {
788 return (*iter).second;
789 }
Dees_Troy2673cec2013-04-02 20:22:16 +0000790 LOGERR("Unable to locate package %s\n", name.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400791 return NULL;
792}
793
794PageSet* PageManager::SelectPackage(std::string name)
795{
Dees_Troy2673cec2013-04-02 20:22:16 +0000796 LOGINFO("Switching packages (%s)\n", name.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400797 PageSet* tmp;
798
799 tmp = FindPackage(name);
800 if (tmp)
801 mCurrentSet = tmp;
802 else
Dees_Troy2673cec2013-04-02 20:22:16 +0000803 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400804
805 return mCurrentSet;
806}
807
808int PageManager::ReloadPackage(std::string name, std::string package)
809{
810 std::map<std::string, PageSet*>::iterator iter;
811
812 iter = mPageSets.find(name);
813 if (iter == mPageSets.end())
814 return -1;
815
816 PageSet* set = (*iter).second;
817 mPageSets.erase(iter);
818
819 if (LoadPackage(name, package, "main") != 0)
820 {
Dees_Troy2673cec2013-04-02 20:22:16 +0000821 LOGERR("Failed to load package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400822 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
823 return -1;
824 }
825 if (mCurrentSet == set) SelectPackage(name);
826 delete set;
827 return 0;
828}
829
830void PageManager::ReleasePackage(std::string name)
831{
832 std::map<std::string, PageSet*>::iterator iter;
833
834 iter = mPageSets.find(name);
835 if (iter == mPageSets.end())
836 return;
837
838 PageSet* set = (*iter).second;
839 mPageSets.erase(iter);
840 delete set;
841 return;
842}
843
844int PageManager::ChangePage(std::string name)
845{
846 DataManager::SetValue("tw_operation_state", 0);
847 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
848 return ret;
849}
850
851int PageManager::ChangeOverlay(std::string name)
852{
853 if (name.empty())
854 return mCurrentSet->SetOverlay(NULL);
855 else
856 {
857 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
858 return mCurrentSet->SetOverlay(page);
859 }
860}
861
862Resource* PageManager::FindResource(std::string name)
863{
864 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
865}
866
867Resource* PageManager::FindResource(std::string package, std::string name)
868{
869 PageSet* tmp;
870
871 tmp = FindPackage(name);
872 return (tmp ? tmp->FindResource(name) : NULL);
873}
874
875int PageManager::SwitchToConsole(void)
876{
877 PageSet* console = new PageSet(NULL);
878
879 mCurrentSet = console;
880 return 0;
881}
882
883int PageManager::IsCurrentPage(Page* page)
884{
885 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
886}
887
888int PageManager::Render(void)
889{
890 return (mCurrentSet ? mCurrentSet->Render() : -1);
891}
892
893int PageManager::Update(void)
894{
gordon13370d9133d2013-06-08 14:17:07 +0200895 if(blankTimer.IsScreenOff())
896 return 0;
897
Dees_Troy51a0e822012-09-05 15:24:24 -0400898 return (mCurrentSet ? mCurrentSet->Update() : -1);
899}
900
901int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
902{
903 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
904}
905
906int PageManager::NotifyKey(int key)
907{
908 return (mCurrentSet ? mCurrentSet->NotifyKey(key) : -1);
909}
910
911int PageManager::NotifyKeyboard(int key)
912{
913 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
914}
915
916int PageManager::SetKeyBoardFocus(int inFocus)
917{
918 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
919}
920
921int PageManager::NotifyVarChange(std::string varName, std::string value)
922{
923 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
924}
925
926extern "C" void gui_notifyVarChange(const char *name, const char* value)
927{
928 if (!gGuiRunning) return;
929
930 PageManager::NotifyVarChange(name, value);
931}
932