blob: aae85aec9ca49979423d75642622faa154776c40 [file] [log] [blame]
Dees_Troya13d74f2013-03-24 08:54:55 -05001/*
2 Copyright 2013 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
Dees Troy3be70a82013-10-22 14:25:12 +000018
Dees_Troya13d74f2013-03-24 08:54:55 -050019// pages.cpp - Source to manage GUI base objects
Dees_Troy51a0e822012-09-05 15:24:24 -040020
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <fcntl.h>
26#include <sys/reboot.h>
27#include <sys/stat.h>
28#include <sys/time.h>
29#include <sys/mman.h>
30#include <sys/types.h>
31#include <sys/ioctl.h>
32#include <time.h>
33#include <unistd.h>
34#include <stdlib.h>
Ethan Yonkera2dc2f22014-11-08 08:13:40 -060035#include "../twrp-functions.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040036
37#include <string>
38
39extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000040#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040041#include "../minuitwrp/minui.h"
Ethan Yonkera2dc2f22014-11-08 08:13:40 -060042#include "../minzip/SysUtil.h"
43#include "../minzip/Zip.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040044}
45
46#include "rapidxml.hpp"
47#include "objects.hpp"
gordon13370d9133d2013-06-08 14:17:07 +020048#include "blanktimer.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040049
50extern int gGuiRunning;
51
52std::map<std::string, PageSet*> PageManager::mPageSets;
53PageSet* PageManager::mCurrentSet;
54PageSet* PageManager::mBaseSet = NULL;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +010055MouseCursor *PageManager::mMouseCursor = NULL;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +010056HardwareKeyboard *PageManager::mHardwareKeyboard = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040057
Ethan Yonker751a85e2014-12-12 16:59:10 -060058int tw_x_offset = 0;
59int tw_y_offset = 0;
60
Dees_Troy51a0e822012-09-05 15:24:24 -040061// Helper routine to convert a string to a color declaration
62int ConvertStrToColor(std::string str, COLOR* color)
63{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020064 // Set the default, solid black
65 memset(color, 0, sizeof(COLOR));
66 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040067
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020068 // Translate variables
69 DataManager::GetValue(str, str);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -050070
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020071 // Look for some defaults
72 if (str == "black") return 0;
73 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
74 else if (str == "red") { color->red = 255; return 0; }
75 else if (str == "green") { color->green = 255; return 0; }
76 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040077
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020078 // At this point, we require an RGB(A) color
79 if (str[0] != '#')
80 return -1;
81
82 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040083
Dees_Troy30b962e2012-10-19 20:48:59 -040084 int result;
85 if (str.size() >= 8) {
86 // We have alpha channel
87 string alpha = str.substr(6, 2);
88 result = strtol(alpha.c_str(), NULL, 16);
89 color->alpha = result & 0x000000FF;
90 str.resize(6);
91 result = strtol(str.c_str(), NULL, 16);
92 color->red = (result >> 16) & 0x000000FF;
93 color->green = (result >> 8) & 0x000000FF;
94 color->blue = result & 0x000000FF;
95 } else {
96 result = strtol(str.c_str(), NULL, 16);
97 color->red = (result >> 16) & 0x000000FF;
98 color->green = (result >> 8) & 0x000000FF;
99 color->blue = result & 0x000000FF;
100 }
101 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400102}
103
104// Helper APIs
105bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
106{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200107 if (!node)
108 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400109
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200110 std::string value;
111 if (node->first_attribute("x"))
112 {
113 value = node->first_attribute("x")->value();
114 DataManager::GetValue(value, value);
115 *x = atol(value.c_str());
Ethan Yonker751a85e2014-12-12 16:59:10 -0600116 *x += tw_x_offset;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200117 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400118
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200119 if (node->first_attribute("y"))
120 {
121 value = node->first_attribute("y")->value();
122 DataManager::GetValue(value, value);
123 *y = atol(value.c_str());
Ethan Yonker751a85e2014-12-12 16:59:10 -0600124 *y += tw_y_offset;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200125 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400126
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200127 if (w && node->first_attribute("w"))
128 {
129 value = node->first_attribute("w")->value();
130 DataManager::GetValue(value, value);
131 *w = atol(value.c_str());
132 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400133
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200134 if (h && node->first_attribute("h"))
135 {
136 value = node->first_attribute("h")->value();
137 DataManager::GetValue(value, value);
138 *h = atol(value.c_str());
139 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400140
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200141 if (placement && node->first_attribute("placement"))
142 {
143 value = node->first_attribute("placement")->value();
144 DataManager::GetValue(value, value);
145 *placement = (RenderObject::Placement) atol(value.c_str());
146 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400147
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200148 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400149}
150
151int ActionObject::SetActionPos(int x, int y, int w, int h)
152{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200153 if (x < 0 || y < 0)
154 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400155
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500156 mActionX = x;
157 mActionY = y;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200158 if (w || h)
159 {
160 mActionW = w;
161 mActionH = h;
162 }
163 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400164}
165
Ethan Yonker780cd392014-07-21 15:24:39 -0500166Page::Page(xml_node<>* page, std::vector<xml_node<>*> *templates /* = NULL */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400167{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200168 mTouchStart = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400169
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200170 // We can memset the whole structure, because the alpha channel is ignored
171 memset(&mBackground, 0, sizeof(COLOR));
Dees_Troy51a0e822012-09-05 15:24:24 -0400172
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200173 // With NULL, we make a console-only display
174 if (!page)
175 {
176 mName = "console";
Dees_Troy51a0e822012-09-05 15:24:24 -0400177
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200178 GUIConsole* element = new GUIConsole(NULL);
179 mRenders.push_back(element);
180 mActions.push_back(element);
181 return;
182 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400183
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200184 if (page->first_attribute("name"))
185 mName = page->first_attribute("name")->value();
186 else
187 {
188 LOGERR("No page name attribute found!\n");
189 return;
190 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400191
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200192 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400193
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200194 // This is a recursive routine for template handling
195 ProcessNode(page, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400196
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200197 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400198}
199
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100200Page::~Page()
201{
202 for (std::vector<GUIObject*>::iterator itr = mObjects.begin(); itr != mObjects.end(); ++itr)
203 delete *itr;
204}
205
Ethan Yonker780cd392014-07-21 15:24:39 -0500206bool Page::ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates /* = NULL */, int depth /* = 0 */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400207{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200208 if (depth == 10)
209 {
210 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
211 return false;
212 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400213
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200214 // Let's retrieve the background value, if any
215 xml_node<>* bg = page->first_node("background");
216 if (bg)
217 {
218 xml_attribute<>* attr = bg->first_attribute("color");
219 if (attr)
220 {
221 std::string color = attr->value();
222 ConvertStrToColor(color, &mBackground);
223 }
224 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400225
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200226 xml_node<>* child;
227 child = page->first_node("object");
228 while (child)
229 {
230 if (!child->first_attribute("type"))
231 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400232
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200233 std::string type = child->first_attribute("type")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400234
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200235 if (type == "text")
236 {
237 GUIText* element = new GUIText(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100238 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200239 mRenders.push_back(element);
240 mActions.push_back(element);
241 }
242 else if (type == "image")
243 {
244 GUIImage* element = new GUIImage(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100245 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200246 mRenders.push_back(element);
247 }
248 else if (type == "fill")
249 {
250 GUIFill* element = new GUIFill(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100251 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200252 mRenders.push_back(element);
253 }
254 else if (type == "action")
255 {
256 GUIAction* element = new GUIAction(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100257 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200258 mActions.push_back(element);
259 }
260 else if (type == "console")
261 {
262 GUIConsole* element = new GUIConsole(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100263 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200264 mRenders.push_back(element);
265 mActions.push_back(element);
266 }
267 else if (type == "button")
268 {
269 GUIButton* element = new GUIButton(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100270 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200271 mRenders.push_back(element);
272 mActions.push_back(element);
273 }
274 else if (type == "checkbox")
275 {
276 GUICheckbox* element = new GUICheckbox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100277 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200278 mRenders.push_back(element);
279 mActions.push_back(element);
280 }
281 else if (type == "fileselector")
282 {
283 GUIFileSelector* element = new GUIFileSelector(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100284 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200285 mRenders.push_back(element);
286 mActions.push_back(element);
287 }
288 else if (type == "animation")
289 {
290 GUIAnimation* element = new GUIAnimation(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100291 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200292 mRenders.push_back(element);
293 }
294 else if (type == "progressbar")
295 {
296 GUIProgressBar* element = new GUIProgressBar(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100297 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200298 mRenders.push_back(element);
299 mActions.push_back(element);
300 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400301 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200302 {
303 GUISlider* element = new GUISlider(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100304 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200305 mRenders.push_back(element);
306 mActions.push_back(element);
307 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200308 else if (type == "slidervalue")
309 {
310 GUISliderValue *element = new GUISliderValue(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100311 mObjects.push_back(element);
Vojtech Bocek85932342013-04-01 22:11:33 +0200312 mRenders.push_back(element);
313 mActions.push_back(element);
314 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400315 else if (type == "listbox")
316 {
317 GUIListBox* element = new GUIListBox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100318 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400319 mRenders.push_back(element);
320 mActions.push_back(element);
321 }
322 else if (type == "keyboard")
323 {
324 GUIKeyboard* element = new GUIKeyboard(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100325 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400326 mRenders.push_back(element);
327 mActions.push_back(element);
328 }
329 else if (type == "input")
330 {
331 GUIInput* element = new GUIInput(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100332 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400333 mRenders.push_back(element);
334 mActions.push_back(element);
335 mInputs.push_back(element);
336 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500337 else if (type == "partitionlist")
338 {
339 GUIPartitionList* element = new GUIPartitionList(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100340 mObjects.push_back(element);
Dees_Troya13d74f2013-03-24 08:54:55 -0500341 mRenders.push_back(element);
342 mActions.push_back(element);
343 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200344 else if (type == "template")
345 {
346 if (!templates || !child->first_attribute("name"))
347 {
348 LOGERR("Invalid template request.\n");
349 }
350 else
351 {
352 std::string name = child->first_attribute("name")->value();
Ethan Yonker780cd392014-07-21 15:24:39 -0500353 xml_node<>* node;
354 bool node_found = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400355
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200356 // We need to find the correct template
Ethan Yonker780cd392014-07-21 15:24:39 -0500357 for (std::vector<xml_node<>*>::iterator itr = templates->begin(); itr != templates->end(); itr++) {
358 node = (*itr)->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400359
Ethan Yonker780cd392014-07-21 15:24:39 -0500360 while (node)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200361 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500362 if (!node->first_attribute("name"))
363 continue;
364
365 if (name == node->first_attribute("name")->value())
366 {
367 if (!ProcessNode(node, templates, depth + 1))
368 return false;
369 else {
370 node_found = true;
371 break;
372 }
373 }
374 if (node_found)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200375 break;
Ethan Yonker780cd392014-07-21 15:24:39 -0500376 node = node->next_sibling("template");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200377 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200378 }
379 }
380 }
381 else
382 {
383 LOGERR("Unknown object type.\n");
384 }
385 child = child->next_sibling("object");
386 }
387 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400388}
389
390int Page::Render(void)
391{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200392 // Render background
393 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
394 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400395
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200396 // Render remaining objects
397 std::vector<RenderObject*>::iterator iter;
398 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
399 {
400 if ((*iter)->Render())
401 LOGERR("A render request has failed.\n");
402 }
403 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400404}
405
406int Page::Update(void)
407{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200408 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400409
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200410 std::vector<RenderObject*>::iterator iter;
411 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
412 {
413 int ret = (*iter)->Update();
414 if (ret < 0)
415 LOGERR("An update request has failed.\n");
416 else if (ret > retCode)
417 retCode = ret;
418 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400419
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200420 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400421}
422
423int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
424{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200425 // By default, return 1 to ignore further touches if nobody is listening
426 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400427
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200428 // Don't try to handle a lack of handlers
429 if (mActions.size() == 0)
430 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400431
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200432 // We record mTouchStart so we can pass all the touch stream to the same handler
433 if (state == TOUCH_START)
434 {
435 std::vector<ActionObject*>::reverse_iterator iter;
436 // We work backwards, from top-most element to bottom-most element
437 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
438 {
439 if ((*iter)->IsInRegion(x, y))
440 {
441 mTouchStart = (*iter);
442 ret = mTouchStart->NotifyTouch(state, x, y);
443 if (ret >= 0)
444 break;
445 mTouchStart = NULL;
446 }
447 }
448 }
449 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
450 {
451 ret = mTouchStart->NotifyTouch(state, x, y);
452 mTouchStart = NULL;
453 }
454 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
455 {
456 ret = mTouchStart->NotifyTouch(state, x, y);
457 }
458 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400459}
460
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100461int Page::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400462{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200463 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400464
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200465 // Don't try to handle a lack of handlers
466 if (mActions.size() == 0)
467 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400468
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100469 int ret = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200470 // We work backwards, from top-most element to bottom-most element
471 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
472 {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100473 ret = (*iter)->NotifyKey(key, down);
474 if (ret < 0) {
475 LOGERR("An action handler has returned an error\n");
476 ret = 1;
477 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200478 }
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100479 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400480}
481
482int Page::NotifyKeyboard(int key)
483{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200484 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400485
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200486 // Don't try to handle a lack of handlers
487 if (mInputs.size() == 0)
488 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400489
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200490 // We work backwards, from top-most element to bottom-most element
491 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
492 {
493 int ret = (*iter)->NotifyKeyboard(key);
494 if (ret == 0)
495 return 0;
496 else if (ret < 0)
497 LOGERR("A keyboard handler has returned an error");
498 }
499 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400500}
501
502int Page::SetKeyBoardFocus(int inFocus)
503{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200504 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400505
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200506 // Don't try to handle a lack of handlers
507 if (mInputs.size() == 0)
508 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400509
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200510 // We work backwards, from top-most element to bottom-most element
511 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
512 {
513 int ret = (*iter)->SetInputFocus(inFocus);
514 if (ret == 0)
515 return 0;
516 else if (ret < 0)
517 LOGERR("An input focus handler has returned an error");
518 }
519 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400520}
521
522void Page::SetPageFocus(int inFocus)
523{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200524 // Render remaining objects
525 std::vector<RenderObject*>::iterator iter;
526 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
527 (*iter)->SetPageFocus(inFocus);
528
529 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400530}
531
532int Page::NotifyVarChange(std::string varName, std::string value)
533{
Vojtech Bocek07220562014-02-08 02:05:33 +0100534 std::vector<GUIObject*>::iterator iter;
535 for (iter = mObjects.begin(); iter != mObjects.end(); ++iter)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200536 {
537 if ((*iter)->NotifyVarChange(varName, value))
538 LOGERR("An action handler errored on NotifyVarChange.\n");
539 }
540 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400541}
542
543PageSet::PageSet(char* xmlFile)
544{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200545 mResources = NULL;
546 mCurrentPage = NULL;
547 mOverlayPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400548
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200549 mXmlFile = xmlFile;
550 if (xmlFile)
551 mDoc.parse<0>(mXmlFile);
552 else
553 mCurrentPage = new Page(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400554}
555
556PageSet::~PageSet()
557{
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100558 for (std::vector<Page*>::iterator itr = mPages.begin(); itr != mPages.end(); ++itr)
559 delete *itr;
Ethan Yonker780cd392014-07-21 15:24:39 -0500560 for (std::vector<xml_node<>*>::iterator itr2 = templates.begin(); itr2 != templates.end(); ++itr2)
561 delete *itr2;
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100562
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200563 delete mResources;
564 free(mXmlFile);
Dees_Troy51a0e822012-09-05 15:24:24 -0400565}
566
567int PageSet::Load(ZipArchive* package)
568{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200569 xml_node<>* parent;
570 xml_node<>* child;
Ethan Yonker780cd392014-07-21 15:24:39 -0500571 xml_node<>* xmltemplate;
572 xml_node<>* blank_templates;
573 int pages_loaded = -1, ret;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500574
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200575 parent = mDoc.first_node("recovery");
576 if (!parent)
577 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400578
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200579 // Now, let's parse the XML
580 LOGINFO("Loading resources...\n");
581 child = parent->first_node("resources");
582 if (child)
583 mResources = new ResourceManager(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400584
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200585 LOGINFO("Loading variables...\n");
586 child = parent->first_node("variables");
587 if (child)
588 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400589
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100590 LOGINFO("Loading mouse cursor...\n");
591 child = parent->first_node("mousecursor");
592 if(child)
593 PageManager::LoadCursorData(child);
594
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200595 LOGINFO("Loading pages...\n");
596 // This may be NULL if no templates are present
Ethan Yonker780cd392014-07-21 15:24:39 -0500597 xmltemplate = parent->first_node("templates");
598 if (xmltemplate)
599 templates.push_back(xmltemplate);
Dees_Troy51a0e822012-09-05 15:24:24 -0400600
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200601 child = parent->first_node("pages");
Ethan Yonker780cd392014-07-21 15:24:39 -0500602 if (child) {
603 if (LoadPages(child)) {
604 LOGERR("PageSet::Load returning -1\n");
605 return -1;
606 }
607 }
608
609 return CheckInclude(package, &mDoc);
610}
Dees_Troy51a0e822012-09-05 15:24:24 -0400611
Ethan Yonker780cd392014-07-21 15:24:39 -0500612int PageSet::CheckInclude(ZipArchive* package, xml_document<> *parentDoc)
613{
614 xml_node<>* par;
615 xml_node<>* par2;
616 xml_node<>* chld;
617 xml_node<>* parent;
618 xml_node<>* child;
619 xml_node<>* xmltemplate;
620 long len;
621 char* xmlFile = NULL;
622 string filename;
623 xml_document<> doc;
624
625 par = parentDoc->first_node("recovery");
626 if (!par) {
627 par = parentDoc->first_node("install");
628 }
629 if (!par) {
630 return 0;
631 }
632
633 par2 = par->first_node("include");
634 if (!par2)
635 return 0;
636 chld = par2->first_node("xmlfile");
637 while (chld != NULL) {
638 xml_attribute<>* attr = chld->first_attribute("name");
639 if (!attr)
640 break;
641
642 LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
643 if (!package) {
644 // We can try to load the XML directly...
645 filename = "/res/";
646 filename += attr->value();
647 struct stat st;
648 if(stat(filename.c_str(),&st) != 0) {
649 LOGERR("Unable to locate '%s'\n", filename.c_str());
650 return -1;
651 }
652
653 len = st.st_size;
654 xmlFile = (char*) malloc(len + 1);
655 if (!xmlFile)
656 return -1;
657
658 int fd = open(filename.c_str(), O_RDONLY);
659 if (fd == -1)
660 return -1;
661
662 read(fd, xmlFile, len);
663 close(fd);
664 } else {
665 filename += attr->value();
666 const ZipEntry* ui_xml = mzFindZipEntry(package, filename.c_str());
667 if (ui_xml == NULL)
668 {
669 LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
670 return -1;
671 }
672
673 // Allocate the buffer for the file
674 len = mzGetZipEntryUncompLen(ui_xml);
675 xmlFile = (char*) malloc(len + 1);
676 if (!xmlFile)
677 return -1;
678
679 if (!mzExtractZipEntryToBuffer(package, ui_xml, (unsigned char*) xmlFile))
680 {
681 LOGERR("Unable to extract '%s'\n", filename.c_str());
682 return -1;
683 }
684 }
685 doc.parse<0>(xmlFile);
686
687 parent = doc.first_node("recovery");
688 if (!parent)
689 parent = doc.first_node("install");
690
691 // Now, let's parse the XML
692 LOGINFO("Loading included resources...\n");
693 child = parent->first_node("resources");
694 if (child)
695 mResources->LoadResources(child, package);
696
697 LOGINFO("Loading included variables...\n");
698 child = parent->first_node("variables");
699 if (child)
700 LoadVariables(child);
701
702 LOGINFO("Loading mouse cursor...\n");
703 child = parent->first_node("mousecursor");
704 if(child)
705 PageManager::LoadCursorData(child);
706
707 LOGINFO("Loading included pages...\n");
708 // This may be NULL if no templates are present
709 xmltemplate = parent->first_node("templates");
710 if (xmltemplate)
711 templates.push_back(xmltemplate);
712
713 child = parent->first_node("pages");
714 if (child)
715 if (LoadPages(child))
716 return -1;
717
718 if (CheckInclude(package, &doc))
719 return -1;
720
721 chld = chld->next_sibling("xmlfile");
722 }
723
724 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400725}
726
727int PageSet::SetPage(std::string page)
728{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200729 Page* tmp = FindPage(page);
730 if (tmp)
731 {
732 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
733 mCurrentPage = tmp;
734 mCurrentPage->SetPageFocus(1);
735 mCurrentPage->NotifyVarChange("", "");
736 return 0;
737 }
738 else
739 {
740 LOGERR("Unable to locate page (%s)\n", page.c_str());
741 }
742 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400743}
744
745int PageSet::SetOverlay(Page* page)
746{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200747 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
748 mOverlayPage = page;
749 if (mOverlayPage)
750 {
751 mOverlayPage->SetPageFocus(1);
752 mOverlayPage->NotifyVarChange("", "");
753 }
754 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400755}
756
757Resource* PageSet::FindResource(std::string name)
758{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200759 return mResources ? mResources->FindResource(name) : NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400760}
761
762Page* PageSet::FindPage(std::string name)
763{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200764 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400765
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200766 for (iter = mPages.begin(); iter != mPages.end(); iter++)
767 {
768 if (name == (*iter)->GetName())
769 return (*iter);
770 }
771 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400772}
773
774int PageSet::LoadVariables(xml_node<>* vars)
775{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200776 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100777 xml_attribute<> *name, *value, *persist;
778 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400779
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200780 child = vars->first_node("variable");
781 while (child)
782 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100783 name = child->first_attribute("name");
784 value = child->first_attribute("value");
785 persist = child->first_attribute("persist");
786 if(name && value)
787 {
Ethan Yonker751a85e2014-12-12 16:59:10 -0600788 if (strcmp(name->value(), "tw_x_offset") == 0) {
789 tw_x_offset = atoi(value->value());
790 child = child->next_sibling("variable");
791 continue;
792 }
793 if (strcmp(name->value(), "tw_y_offset") == 0) {
794 tw_y_offset = atoi(value->value());
795 child = child->next_sibling("variable");
796 continue;
797 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100798 p = persist ? atoi(persist->value()) : 0;
Ethan Yonker96acb3d2014-08-05 09:20:30 -0500799 string temp = value->value();
800 string valstr = gui_parse_text(temp);
801
802 if (valstr.find("+") != string::npos) {
803 string val1str = valstr;
804 val1str = val1str.substr(0, val1str.find('+'));
805 string val2str = valstr;
806 val2str = val2str.substr(val2str.find('+') + 1, string::npos);
807 int val1 = atoi(val1str.c_str());
808 int val2 = atoi(val2str.c_str());
809 int val = val1 + val2;
810
811 DataManager::SetValue(name->value(), val, p);
812 } else if (valstr.find("-") != string::npos) {
813 string val1str = valstr;
814 val1str = val1str.substr(0, val1str.find('-'));
815 string val2str = valstr;
816 val2str = val2str.substr(val2str.find('-') + 1, string::npos);
817 int val1 = atoi(val1str.c_str());
818 int val2 = atoi(val2str.c_str());
819 int val = val1 - val2;
820
821 DataManager::SetValue(name->value(), val, p);
822 } else {
823 DataManager::SetValue(name->value(), valstr, p);
824 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100825 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400826
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200827 child = child->next_sibling("variable");
828 }
829 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400830}
831
Ethan Yonker780cd392014-07-21 15:24:39 -0500832int PageSet::LoadPages(xml_node<>* pages)
Dees_Troy51a0e822012-09-05 15:24:24 -0400833{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200834 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400835
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200836 if (!pages)
837 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400838
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200839 child = pages->first_node("page");
840 while (child != NULL)
841 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500842 Page* page = new Page(child, &templates);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200843 if (page->GetName().empty())
844 {
845 LOGERR("Unable to process load page\n");
846 delete page;
847 }
848 else
849 {
850 mPages.push_back(page);
851 }
852 child = child->next_sibling("page");
853 }
854 if (mPages.size() > 0)
855 return 0;
856 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400857}
858
859int PageSet::IsCurrentPage(Page* page)
860{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200861 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400862}
863
864int PageSet::Render(void)
865{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200866 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400867
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200868 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
869 if (ret < 0)
870 return ret;
871 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
872 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400873}
874
875int PageSet::Update(void)
876{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200877 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400878
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200879 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
880 if (ret < 0 || ret > 1)
881 return ret;
882 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
883 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400884}
885
886int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
887{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200888 if (mOverlayPage)
889 return (mOverlayPage->NotifyTouch(state, x, y));
890
891 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400892}
893
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100894int PageSet::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400895{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200896 if (mOverlayPage)
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100897 return (mOverlayPage->NotifyKey(key, down));
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200898
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100899 return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400900}
901
902int PageSet::NotifyKeyboard(int key)
903{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200904 if (mOverlayPage)
905 return (mOverlayPage->NotifyKeyboard(key));
906
907 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400908}
909
910int PageSet::SetKeyBoardFocus(int inFocus)
911{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200912 if (mOverlayPage)
913 return (mOverlayPage->SetKeyBoardFocus(inFocus));
914
915 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400916}
917
918int PageSet::NotifyVarChange(std::string varName, std::string value)
919{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200920 if (mOverlayPage)
921 mOverlayPage->NotifyVarChange(varName, value);
922
923 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400924}
925
926int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
927{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200928 int fd;
929 ZipArchive zip, *pZip = NULL;
930 long len;
931 char* xmlFile = NULL;
932 PageSet* pageSet = NULL;
933 int ret;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600934 MemMapping map;
Dees_Troy51a0e822012-09-05 15:24:24 -0400935
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200936 // Open the XML file
937 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600938 if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200939 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600940 LOGINFO("Load XML directly\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -0600941 tw_x_offset = TW_X_OFFSET;
942 tw_y_offset = TW_Y_OFFSET;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200943 // We can try to load the XML directly...
944 struct stat st;
945 if(stat(package.c_str(),&st) != 0)
946 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400947
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200948 len = st.st_size;
949 xmlFile = (char*) malloc(len + 1);
950 if (!xmlFile)
951 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400952
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200953 fd = open(package.c_str(), O_RDONLY);
954 if (fd == -1)
955 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400956
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200957 read(fd, xmlFile, len);
958 close(fd);
959 }
960 else
961 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600962 LOGINFO("Loading zip theme\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -0600963 tw_x_offset = 0;
964 tw_y_offset = 0;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600965 if (!TWFunc::Path_Exists(package))
966 return -1;
967 if (sysMapFile(package.c_str(), &map) != 0) {
968 LOGERR("Failed to map '%s'\n", package.c_str());
969 return -1;
970 }
971 if (mzOpenZipArchive(map.addr, map.length, &zip)) {
972 LOGERR("Unable to open zip archive '%s'\n", package.c_str());
973 sysReleaseMap(&map);
974 return -1;
975 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200976 pZip = &zip;
977 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
978 if (ui_xml == NULL)
979 {
980 LOGERR("Unable to locate ui.xml in zip file\n");
981 goto error;
982 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500983
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200984 // Allocate the buffer for the file
985 len = mzGetZipEntryUncompLen(ui_xml);
986 xmlFile = (char*) malloc(len + 1);
987 if (!xmlFile)
988 goto error;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500989
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200990 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
991 {
992 LOGERR("Unable to extract ui.xml\n");
993 goto error;
994 }
995 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400996
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200997 // NULL-terminate the string
998 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -0400999
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001000 // Before loading, mCurrentSet must be the loading package so we can find resources
1001 pageSet = mCurrentSet;
1002 mCurrentSet = new PageSet(xmlFile);
1003
1004 ret = mCurrentSet->Load(pZip);
1005 if (ret == 0)
1006 {
1007 mCurrentSet->SetPage(startpage);
1008 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
1009 }
1010 else
1011 {
1012 LOGERR("Package %s failed to load.\n", name.c_str());
1013 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001014
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001015 // The first successful package we loaded is the base
1016 if (mBaseSet == NULL)
1017 mBaseSet = mCurrentSet;
1018
1019 mCurrentSet = pageSet;
1020
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001021 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001022 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001023 sysReleaseMap(&map);
1024 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001025 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001026
1027error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001028 LOGERR("An internal error has occurred.\n");
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001029 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001030 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001031 sysReleaseMap(&map);
1032 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001033 if (xmlFile)
1034 free(xmlFile);
1035 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001036}
1037
1038PageSet* PageManager::FindPackage(std::string name)
1039{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001040 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001041
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001042 iter = mPageSets.find(name);
1043 if (iter != mPageSets.end())
1044 return (*iter).second;
1045
1046 LOGERR("Unable to locate package %s\n", name.c_str());
1047 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -04001048}
1049
1050PageSet* PageManager::SelectPackage(std::string name)
1051{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001052 LOGINFO("Switching packages (%s)\n", name.c_str());
1053 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001054
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001055 tmp = FindPackage(name);
1056 if (tmp)
Vojtech Bocek07220562014-02-08 02:05:33 +01001057 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001058 mCurrentSet = tmp;
Vojtech Bocek07220562014-02-08 02:05:33 +01001059 mCurrentSet->NotifyVarChange("", "");
1060 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001061 else
1062 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001063
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001064 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -04001065}
1066
1067int PageManager::ReloadPackage(std::string name, std::string package)
1068{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001069 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001070
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001071 iter = mPageSets.find(name);
1072 if (iter == mPageSets.end())
1073 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001074
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001075 if(mMouseCursor)
1076 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
1077
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001078 PageSet* set = (*iter).second;
1079 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -04001080
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001081 if (LoadPackage(name, package, "main") != 0)
1082 {
1083 LOGERR("Failed to load package.\n");
1084 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
1085 return -1;
1086 }
1087 if (mCurrentSet == set)
1088 SelectPackage(name);
Vojtech Bocekbfb63342014-02-08 00:32:31 +01001089 if (mBaseSet == set)
1090 mBaseSet = mCurrentSet;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001091 delete set;
1092 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001093}
1094
1095void PageManager::ReleasePackage(std::string name)
1096{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001097 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001098
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001099 iter = mPageSets.find(name);
1100 if (iter == mPageSets.end())
1101 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001102
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001103 PageSet* set = (*iter).second;
1104 mPageSets.erase(iter);
1105 delete set;
1106 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001107}
1108
1109int PageManager::ChangePage(std::string name)
1110{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001111 DataManager::SetValue("tw_operation_state", 0);
1112 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
1113 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001114}
1115
1116int PageManager::ChangeOverlay(std::string name)
1117{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001118 if (name.empty())
1119 return mCurrentSet->SetOverlay(NULL);
1120 else
1121 {
1122 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
1123 return mCurrentSet->SetOverlay(page);
1124 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001125}
1126
1127Resource* PageManager::FindResource(std::string name)
1128{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001129 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001130}
1131
1132Resource* PageManager::FindResource(std::string package, std::string name)
1133{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001134 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001135
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001136 tmp = FindPackage(name);
1137 return (tmp ? tmp->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001138}
1139
1140int PageManager::SwitchToConsole(void)
1141{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001142 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001143
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001144 mCurrentSet = console;
1145 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001146}
1147
Ethan Yonker03a42f62014-08-08 11:03:51 -05001148int PageManager::EndConsole(void)
1149{
1150 if (mCurrentSet && mBaseSet) {
1151 delete mCurrentSet;
1152 mCurrentSet = mBaseSet;
1153 return 0;
1154 }
1155 return -1;
1156}
1157
Dees_Troy51a0e822012-09-05 15:24:24 -04001158int PageManager::IsCurrentPage(Page* page)
1159{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001160 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001161}
1162
1163int PageManager::Render(void)
1164{
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001165 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
1166 if(mMouseCursor)
1167 mMouseCursor->Render();
1168 return res;
1169}
1170
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001171HardwareKeyboard *PageManager::GetHardwareKeyboard()
1172{
1173 if(!mHardwareKeyboard)
1174 mHardwareKeyboard = new HardwareKeyboard();
1175 return mHardwareKeyboard;
1176}
1177
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001178MouseCursor *PageManager::GetMouseCursor()
1179{
1180 if(!mMouseCursor)
1181 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1182 return mMouseCursor;
1183}
1184
1185void PageManager::LoadCursorData(xml_node<>* node)
1186{
1187 if(!mMouseCursor)
1188 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1189
1190 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -04001191}
1192
1193int PageManager::Update(void)
1194{
thatfb759d42015-01-11 12:16:53 +01001195 if(blankTimer.isScreenOff())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001196 return 0;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001197
1198 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
1199
1200 if(mMouseCursor)
1201 {
1202 int c_res = mMouseCursor->Update();
1203 if(c_res > res)
1204 res = c_res;
1205 }
1206 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -04001207}
1208
1209int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
1210{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001211 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001212}
1213
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001214int PageManager::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001215{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001216 return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001217}
1218
1219int PageManager::NotifyKeyboard(int key)
1220{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001221 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001222}
1223
1224int PageManager::SetKeyBoardFocus(int inFocus)
1225{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001226 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001227}
1228
1229int PageManager::NotifyVarChange(std::string varName, std::string value)
1230{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001231 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001232}
1233
1234extern "C" void gui_notifyVarChange(const char *name, const char* value)
1235{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001236 if (!gGuiRunning)
1237 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001238
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001239 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001240}