mirror of
https://github.com/CTCaer/CTCaer-TWRP.git
synced 2024-11-24 02:39:40 +00:00
900 lines
22 KiB
C++
900 lines
22 KiB
C++
// base_objects.cpp - Source to manage GUI base objects
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <sys/reboot.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <sys/ioctl.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <string>
|
|
|
|
extern "C" {
|
|
#include "../common.h"
|
|
#include "../minuitwrp/minui.h"
|
|
#include "../recovery_ui.h"
|
|
}
|
|
|
|
#include "rapidxml.hpp"
|
|
#include "objects.hpp"
|
|
|
|
extern int gGuiRunning;
|
|
|
|
std::map<std::string, PageSet*> PageManager::mPageSets;
|
|
PageSet* PageManager::mCurrentSet;
|
|
PageSet* PageManager::mBaseSet = NULL;
|
|
|
|
|
|
// Helper routine to convert a string to a color declaration
|
|
int ConvertStrToColor(std::string str, COLOR* color)
|
|
{
|
|
// Set the default, solid black
|
|
memset(color, 0, sizeof(COLOR));
|
|
color->alpha = 255;
|
|
|
|
// Translate variables
|
|
DataManager::GetValue(str, str);
|
|
|
|
// Look for some defaults
|
|
if (str == "black") return 0;
|
|
else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
|
|
else if (str == "red") { color->red = 255; return 0; }
|
|
else if (str == "green") { color->green = 255; return 0; }
|
|
else if (str == "blue") { color->blue = 255; return 0; }
|
|
|
|
// At this point, we require an RGB(A) color
|
|
if (str[0] != '#') return -1;
|
|
str.erase(0, 1);
|
|
|
|
int result;
|
|
if (str.size() >= 8) {
|
|
// We have alpha channel
|
|
string alpha = str.substr(6, 2);
|
|
result = strtol(alpha.c_str(), NULL, 16);
|
|
color->alpha = result & 0x000000FF;
|
|
str.resize(6);
|
|
result = strtol(str.c_str(), NULL, 16);
|
|
color->red = (result >> 16) & 0x000000FF;
|
|
color->green = (result >> 8) & 0x000000FF;
|
|
color->blue = result & 0x000000FF;
|
|
} else {
|
|
result = strtol(str.c_str(), NULL, 16);
|
|
color->red = (result >> 16) & 0x000000FF;
|
|
color->green = (result >> 8) & 0x000000FF;
|
|
color->blue = result & 0x000000FF;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Helper APIs
|
|
bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
|
|
{
|
|
if (!node) return false;
|
|
|
|
std::string value;
|
|
if (node->first_attribute("x"))
|
|
{
|
|
value = node->first_attribute("x")->value();
|
|
DataManager::GetValue(value, value);
|
|
*x = atol(value.c_str());
|
|
}
|
|
|
|
if (node->first_attribute("y"))
|
|
{
|
|
value = node->first_attribute("y")->value();
|
|
DataManager::GetValue(value, value);
|
|
*y = atol(value.c_str());
|
|
}
|
|
|
|
if (w && node->first_attribute("w"))
|
|
{
|
|
value = node->first_attribute("w")->value();
|
|
DataManager::GetValue(value, value);
|
|
*w = atol(value.c_str());
|
|
}
|
|
|
|
if (h && node->first_attribute("h"))
|
|
{
|
|
value = node->first_attribute("h")->value();
|
|
DataManager::GetValue(value, value);
|
|
*h = atol(value.c_str());
|
|
}
|
|
|
|
if (placement && node->first_attribute("placement"))
|
|
{
|
|
value = node->first_attribute("placement")->value();
|
|
DataManager::GetValue(value, value);
|
|
*placement = (RenderObject::Placement) atol(value.c_str());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int ActionObject::SetActionPos(int x, int y, int w, int h)
|
|
{
|
|
if (x < 0 || y < 0) return -1;
|
|
|
|
mActionX = x;
|
|
mActionY = y;
|
|
if (w || h)
|
|
{
|
|
mActionW = w;
|
|
mActionH = h;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Page::Page(xml_node<>* page, xml_node<>* templates /* = NULL */)
|
|
{
|
|
mTouchStart = NULL;
|
|
|
|
// We can memset the whole structure, because the alpha channel is ignored
|
|
memset(&mBackground, 0, sizeof(COLOR));
|
|
|
|
// With NULL, we make a console-only display
|
|
if (!page)
|
|
{
|
|
mName = "console";
|
|
|
|
GUIConsole* element = new GUIConsole(NULL);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
return;
|
|
}
|
|
|
|
if (page->first_attribute("name"))
|
|
mName = page->first_attribute("name")->value();
|
|
else
|
|
{
|
|
LOGE("No page name attribute found!\n");
|
|
return;
|
|
}
|
|
|
|
LOGI("Loading page %s\n", mName.c_str());
|
|
|
|
// This is a recursive routine for template handling
|
|
ProcessNode(page, templates);
|
|
|
|
return;
|
|
}
|
|
|
|
bool Page::ProcessNode(xml_node<>* page, xml_node<>* templates /* = NULL */, int depth /* = 0 */)
|
|
{
|
|
if (depth == 10)
|
|
{
|
|
LOGE("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
|
|
return false;
|
|
}
|
|
|
|
// Let's retrieve the background value, if any
|
|
xml_node<>* bg = page->first_node("background");
|
|
if (bg)
|
|
{
|
|
xml_attribute<>* attr = bg->first_attribute("color");
|
|
if (attr)
|
|
{
|
|
std::string color = attr->value();
|
|
ConvertStrToColor(color, &mBackground);
|
|
}
|
|
}
|
|
|
|
xml_node<>* child;
|
|
child = page->first_node("object");
|
|
while (child)
|
|
{
|
|
if (!child->first_attribute("type"))
|
|
break;
|
|
|
|
std::string type = child->first_attribute("type")->value();
|
|
|
|
if (type == "text")
|
|
{
|
|
GUIText* element = new GUIText(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "image")
|
|
{
|
|
GUIImage* element = new GUIImage(child);
|
|
mRenders.push_back(element);
|
|
}
|
|
else if (type == "fill")
|
|
{
|
|
GUIFill* element = new GUIFill(child);
|
|
mRenders.push_back(element);
|
|
}
|
|
else if (type == "action")
|
|
{
|
|
GUIAction* element = new GUIAction(child);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "console")
|
|
{
|
|
GUIConsole* element = new GUIConsole(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "button")
|
|
{
|
|
GUIButton* element = new GUIButton(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "checkbox")
|
|
{
|
|
GUICheckbox* element = new GUICheckbox(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "fileselector")
|
|
{
|
|
GUIFileSelector* element = new GUIFileSelector(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "animation")
|
|
{
|
|
GUIAnimation* element = new GUIAnimation(child);
|
|
mRenders.push_back(element);
|
|
}
|
|
else if (type == "progressbar")
|
|
{
|
|
GUIProgressBar* element = new GUIProgressBar(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "slider")
|
|
{
|
|
GUISlider* element = new GUISlider(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "listbox")
|
|
{
|
|
GUIListBox* element = new GUIListBox(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "keyboard")
|
|
{
|
|
GUIKeyboard* element = new GUIKeyboard(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
}
|
|
else if (type == "input")
|
|
{
|
|
GUIInput* element = new GUIInput(child);
|
|
mRenders.push_back(element);
|
|
mActions.push_back(element);
|
|
mInputs.push_back(element);
|
|
}
|
|
else if (type == "template")
|
|
{
|
|
if (!templates || !child->first_attribute("name"))
|
|
{
|
|
LOGE("Invalid template request.\n");
|
|
}
|
|
else
|
|
{
|
|
std::string name = child->first_attribute("name")->value();
|
|
|
|
// We need to find the correct template
|
|
xml_node<>* node;
|
|
node = templates->first_node("template");
|
|
|
|
while (node)
|
|
{
|
|
if (!node->first_attribute("name"))
|
|
continue;
|
|
|
|
if (name == node->first_attribute("name")->value())
|
|
{
|
|
if (!ProcessNode(node, templates, depth + 1))
|
|
return false;
|
|
else
|
|
break;
|
|
}
|
|
node = node->next_sibling("template");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LOGE("Unknown object type.\n");
|
|
}
|
|
child = child->next_sibling("object");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int Page::Render(void)
|
|
{
|
|
// Render background
|
|
gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
|
|
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
|
|
|
|
// Render remaining objects
|
|
std::vector<RenderObject*>::iterator iter;
|
|
for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
|
|
{
|
|
if ((*iter)->Render())
|
|
LOGE("A render request has failed.\n");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Page::Update(void)
|
|
{
|
|
int retCode = 0;
|
|
|
|
std::vector<RenderObject*>::iterator iter;
|
|
for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
|
|
{
|
|
int ret = (*iter)->Update();
|
|
if (ret < 0)
|
|
LOGE("An update request has failed.\n");
|
|
else if (ret > retCode)
|
|
retCode = ret;
|
|
}
|
|
|
|
return retCode;
|
|
}
|
|
|
|
int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
|
|
{
|
|
// By default, return 1 to ignore further touches if nobody is listening
|
|
int ret = 1;
|
|
|
|
// Don't try to handle a lack of handlers
|
|
if (mActions.size() == 0) return ret;
|
|
|
|
// We record mTouchStart so we can pass all the touch stream to the same handler
|
|
if (state == TOUCH_START)
|
|
{
|
|
std::vector<ActionObject*>::reverse_iterator iter;
|
|
// We work backwards, from top-most element to bottom-most element
|
|
for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
|
|
{
|
|
if ((*iter)->IsInRegion(x, y))
|
|
{
|
|
mTouchStart = (*iter);
|
|
ret = mTouchStart->NotifyTouch(state, x, y);
|
|
if (ret >= 0) break;
|
|
mTouchStart = NULL;
|
|
}
|
|
}
|
|
}
|
|
else if (state == TOUCH_RELEASE && mTouchStart != NULL)
|
|
{
|
|
ret = mTouchStart->NotifyTouch(state, x, y);
|
|
mTouchStart = NULL;
|
|
}
|
|
else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
|
|
{
|
|
ret = mTouchStart->NotifyTouch(state, x, y);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int Page::NotifyKey(int key)
|
|
{
|
|
std::vector<ActionObject*>::reverse_iterator iter;
|
|
|
|
// Don't try to handle a lack of handlers
|
|
if (mActions.size() == 0) return 1;
|
|
|
|
// We work backwards, from top-most element to bottom-most element
|
|
for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
|
|
{
|
|
int ret = (*iter)->NotifyKey(key);
|
|
if (ret == 0)
|
|
return 0;
|
|
else if (ret < 0)
|
|
LOGE("An action handler has returned an error");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int Page::NotifyKeyboard(int key)
|
|
{
|
|
std::vector<InputObject*>::reverse_iterator iter;
|
|
|
|
// Don't try to handle a lack of handlers
|
|
if (mInputs.size() == 0) return 1;
|
|
|
|
// We work backwards, from top-most element to bottom-most element
|
|
for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
|
|
{
|
|
int ret = (*iter)->NotifyKeyboard(key);
|
|
if (ret == 0)
|
|
return 0;
|
|
else if (ret < 0)
|
|
LOGE("A keyboard handler has returned an error");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int Page::SetKeyBoardFocus(int inFocus)
|
|
{
|
|
std::vector<InputObject*>::reverse_iterator iter;
|
|
|
|
// Don't try to handle a lack of handlers
|
|
if (mInputs.size() == 0) return 1;
|
|
|
|
// We work backwards, from top-most element to bottom-most element
|
|
for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
|
|
{
|
|
int ret = (*iter)->SetInputFocus(inFocus);
|
|
if (ret == 0)
|
|
return 0;
|
|
else if (ret < 0)
|
|
LOGE("An input focus handler has returned an error");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void Page::SetPageFocus(int inFocus)
|
|
{
|
|
// Render remaining objects
|
|
std::vector<RenderObject*>::iterator iter;
|
|
for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
|
|
{
|
|
(*iter)->SetPageFocus(inFocus);
|
|
}
|
|
return;
|
|
}
|
|
|
|
int Page::NotifyVarChange(std::string varName, std::string value)
|
|
{
|
|
std::vector<ActionObject*>::iterator iter;
|
|
|
|
// Don't try to handle a lack of handlers
|
|
if (mActions.size() == 0) return 1;
|
|
|
|
for (iter = mActions.begin(); iter != mActions.end(); ++iter)
|
|
{
|
|
if ((*iter)->NotifyVarChange(varName, value))
|
|
LOGE("An action handler errored on NotifyVarChange.\n");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
PageSet::PageSet(char* xmlFile)
|
|
{
|
|
mResources = NULL;
|
|
mCurrentPage = NULL;
|
|
mOverlayPage = NULL;
|
|
|
|
mXmlFile = xmlFile;
|
|
if (xmlFile)
|
|
mDoc.parse<0>(mXmlFile);
|
|
else
|
|
mCurrentPage = new Page(NULL);
|
|
}
|
|
|
|
PageSet::~PageSet()
|
|
{
|
|
delete mResources;
|
|
free(mXmlFile);
|
|
}
|
|
|
|
int PageSet::Load(ZipArchive* package)
|
|
{
|
|
xml_node<>* parent;
|
|
xml_node<>* child;
|
|
xml_node<>* templates;
|
|
|
|
parent = mDoc.first_node("recovery");
|
|
if (!parent)
|
|
parent = mDoc.first_node("install");
|
|
|
|
// Now, let's parse the XML
|
|
LOGI("Loading resources...\n");
|
|
child = parent->first_node("resources");
|
|
if (child)
|
|
mResources = new ResourceManager(child, package);
|
|
|
|
LOGI("Loading variables...\n");
|
|
child = parent->first_node("variables");
|
|
if (child)
|
|
LoadVariables(child);
|
|
|
|
LOGI("Loading pages...\n");
|
|
// This may be NULL if no templates are present
|
|
templates = parent->first_node("templates");
|
|
|
|
child = parent->first_node("pages");
|
|
if (!child)
|
|
return -1;
|
|
|
|
return LoadPages(child, templates);
|
|
}
|
|
|
|
int PageSet::SetPage(std::string page)
|
|
{
|
|
Page* tmp = FindPage(page);
|
|
if (tmp)
|
|
{
|
|
if (mCurrentPage) mCurrentPage->SetPageFocus(0);
|
|
mCurrentPage = tmp;
|
|
mCurrentPage->SetPageFocus(1);
|
|
mCurrentPage->NotifyVarChange("", "");
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
LOGE("Unable to locate page (%s)\n", page.c_str());
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int PageSet::SetOverlay(Page* page)
|
|
{
|
|
if (mOverlayPage) mOverlayPage->SetPageFocus(0);
|
|
mOverlayPage = page;
|
|
if (mOverlayPage)
|
|
{
|
|
mOverlayPage->SetPageFocus(1);
|
|
mOverlayPage->NotifyVarChange("", "");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Resource* PageSet::FindResource(std::string name)
|
|
{
|
|
return mResources ? mResources->FindResource(name) : NULL;
|
|
}
|
|
|
|
Page* PageSet::FindPage(std::string name)
|
|
{
|
|
std::vector<Page*>::iterator iter;
|
|
|
|
for (iter = mPages.begin(); iter != mPages.end(); iter++)
|
|
{
|
|
if (name == (*iter)->GetName())
|
|
return (*iter);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int PageSet::LoadVariables(xml_node<>* vars)
|
|
{
|
|
xml_node<>* child;
|
|
|
|
child = vars->first_node("variable");
|
|
while (child)
|
|
{
|
|
if (!child->first_attribute("name"))
|
|
break;
|
|
if (!child->first_attribute("value"))
|
|
break;
|
|
|
|
DataManager::SetValue(child->first_attribute("name")->value(), child->first_attribute("value")->value());
|
|
child = child->next_sibling("variable");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int PageSet::LoadPages(xml_node<>* pages, xml_node<>* templates /* = NULL */)
|
|
{
|
|
xml_node<>* child;
|
|
|
|
if (!pages) return -1;
|
|
|
|
child = pages->first_node("page");
|
|
while (child != NULL)
|
|
{
|
|
Page* page = new Page(child, templates);
|
|
if (page->GetName().empty())
|
|
{
|
|
LOGE("Unable to process load page\n");
|
|
delete page;
|
|
}
|
|
else
|
|
{
|
|
mPages.push_back(page);
|
|
}
|
|
child = child->next_sibling("page");
|
|
}
|
|
if (mPages.size() > 0)
|
|
return 0;
|
|
return -1;
|
|
}
|
|
|
|
int PageSet::IsCurrentPage(Page* page)
|
|
{
|
|
return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
|
|
}
|
|
|
|
int PageSet::Render(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = (mCurrentPage ? mCurrentPage->Render() : -1);
|
|
if (ret < 0) return ret;
|
|
ret = (mOverlayPage ? mOverlayPage->Render() : -1);
|
|
return ret;
|
|
}
|
|
|
|
int PageSet::Update(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = (mCurrentPage ? mCurrentPage->Update() : -1);
|
|
if (ret < 0 || ret > 1) return ret;
|
|
ret = (mOverlayPage ? mOverlayPage->Update() : -1);
|
|
return ret;
|
|
}
|
|
|
|
int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
|
|
{
|
|
if (mOverlayPage) return (mOverlayPage->NotifyTouch(state, x, y));
|
|
return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
|
|
}
|
|
|
|
int PageSet::NotifyKey(int key)
|
|
{
|
|
if (mOverlayPage) return (mOverlayPage->NotifyKey(key));
|
|
return (mCurrentPage ? mCurrentPage->NotifyKey(key) : -1);
|
|
}
|
|
|
|
int PageSet::NotifyKeyboard(int key)
|
|
{
|
|
if (mOverlayPage) return (mOverlayPage->NotifyKeyboard(key));
|
|
return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
|
|
}
|
|
|
|
int PageSet::SetKeyBoardFocus(int inFocus)
|
|
{
|
|
if (mOverlayPage) return (mOverlayPage->SetKeyBoardFocus(inFocus));
|
|
return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
|
|
}
|
|
|
|
int PageSet::NotifyVarChange(std::string varName, std::string value)
|
|
{
|
|
if (mOverlayPage) mOverlayPage->NotifyVarChange(varName, value);
|
|
return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
|
|
}
|
|
|
|
int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
|
|
{
|
|
int fd;
|
|
ZipArchive zip, *pZip = NULL;
|
|
long len;
|
|
char* xmlFile = NULL;
|
|
PageSet* pageSet = NULL;
|
|
int ret;
|
|
|
|
// Open the XML file
|
|
LOGI("Loading package: %s (%s)\n", name.c_str(), package.c_str());
|
|
if (mzOpenZipArchive(package.c_str(), &zip))
|
|
{
|
|
// We can try to load the XML directly...
|
|
struct stat st;
|
|
if(stat(package.c_str(),&st) != 0)
|
|
return -1;
|
|
|
|
len = st.st_size;
|
|
xmlFile = (char*) malloc(len + 1);
|
|
if (!xmlFile) return -1;
|
|
|
|
fd = open(package.c_str(), O_RDONLY);
|
|
if (fd == -1) goto error;
|
|
|
|
read(fd, xmlFile, len);
|
|
close(fd);
|
|
}
|
|
else
|
|
{
|
|
pZip = &zip;
|
|
const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
|
|
if (ui_xml == NULL)
|
|
{
|
|
LOGE("Unable to locate ui.xml in zip file\n");
|
|
goto error;
|
|
}
|
|
|
|
// Allocate the buffer for the file
|
|
len = mzGetZipEntryUncompLen(ui_xml);
|
|
xmlFile = (char*) malloc(len + 1);
|
|
if (!xmlFile) goto error;
|
|
|
|
if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
|
|
{
|
|
LOGE("Unable to extract ui.xml\n");
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
// NULL-terminate the string
|
|
xmlFile[len] = 0x00;
|
|
|
|
// Before loading, mCurrentSet must be the loading package so we can find resources
|
|
pageSet = mCurrentSet;
|
|
mCurrentSet = new PageSet(xmlFile);
|
|
|
|
ret = mCurrentSet->Load(pZip);
|
|
if (ret == 0)
|
|
{
|
|
mCurrentSet->SetPage(startpage);
|
|
mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
|
|
}
|
|
else
|
|
{
|
|
LOGE("Package %s failed to load.\n", name.c_str());
|
|
}
|
|
|
|
// The first successful package we loaded is the base
|
|
if (mBaseSet == NULL)
|
|
mBaseSet = mCurrentSet;
|
|
|
|
mCurrentSet = pageSet;
|
|
|
|
if (pZip) mzCloseZipArchive(pZip);
|
|
return ret;
|
|
|
|
error:
|
|
LOGE("An internal error has occurred.\n");
|
|
if (pZip) mzCloseZipArchive(pZip);
|
|
if (xmlFile) free(xmlFile);
|
|
return -1;
|
|
}
|
|
|
|
PageSet* PageManager::FindPackage(std::string name)
|
|
{
|
|
std::map<std::string, PageSet*>::iterator iter;
|
|
|
|
iter = mPageSets.find(name);
|
|
if (iter != mPageSets.end())
|
|
{
|
|
return (*iter).second;
|
|
}
|
|
LOGE("Unable to locate package %s\n", name.c_str());
|
|
return NULL;
|
|
}
|
|
|
|
PageSet* PageManager::SelectPackage(std::string name)
|
|
{
|
|
LOGI("Switching packages (%s)\n", name.c_str());
|
|
PageSet* tmp;
|
|
|
|
tmp = FindPackage(name);
|
|
if (tmp)
|
|
mCurrentSet = tmp;
|
|
else
|
|
LOGE("Unable to find package.\n");
|
|
|
|
return mCurrentSet;
|
|
}
|
|
|
|
int PageManager::ReloadPackage(std::string name, std::string package)
|
|
{
|
|
std::map<std::string, PageSet*>::iterator iter;
|
|
|
|
iter = mPageSets.find(name);
|
|
if (iter == mPageSets.end())
|
|
return -1;
|
|
|
|
PageSet* set = (*iter).second;
|
|
mPageSets.erase(iter);
|
|
|
|
if (LoadPackage(name, package, "main") != 0)
|
|
{
|
|
LOGE("Failed to load package.\n");
|
|
mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
|
|
return -1;
|
|
}
|
|
if (mCurrentSet == set) SelectPackage(name);
|
|
delete set;
|
|
return 0;
|
|
}
|
|
|
|
void PageManager::ReleasePackage(std::string name)
|
|
{
|
|
std::map<std::string, PageSet*>::iterator iter;
|
|
|
|
iter = mPageSets.find(name);
|
|
if (iter == mPageSets.end())
|
|
return;
|
|
|
|
PageSet* set = (*iter).second;
|
|
mPageSets.erase(iter);
|
|
delete set;
|
|
return;
|
|
}
|
|
|
|
int PageManager::ChangePage(std::string name)
|
|
{
|
|
DataManager::SetValue("tw_operation_state", 0);
|
|
int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
|
|
return ret;
|
|
}
|
|
|
|
int PageManager::ChangeOverlay(std::string name)
|
|
{
|
|
if (name.empty())
|
|
return mCurrentSet->SetOverlay(NULL);
|
|
else
|
|
{
|
|
Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
|
|
return mCurrentSet->SetOverlay(page);
|
|
}
|
|
}
|
|
|
|
Resource* PageManager::FindResource(std::string name)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
|
|
}
|
|
|
|
Resource* PageManager::FindResource(std::string package, std::string name)
|
|
{
|
|
PageSet* tmp;
|
|
|
|
tmp = FindPackage(name);
|
|
return (tmp ? tmp->FindResource(name) : NULL);
|
|
}
|
|
|
|
int PageManager::SwitchToConsole(void)
|
|
{
|
|
PageSet* console = new PageSet(NULL);
|
|
|
|
mCurrentSet = console;
|
|
return 0;
|
|
}
|
|
|
|
int PageManager::IsCurrentPage(Page* page)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
|
|
}
|
|
|
|
int PageManager::Render(void)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->Render() : -1);
|
|
}
|
|
|
|
int PageManager::Update(void)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->Update() : -1);
|
|
}
|
|
|
|
int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
|
|
}
|
|
|
|
int PageManager::NotifyKey(int key)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->NotifyKey(key) : -1);
|
|
}
|
|
|
|
int PageManager::NotifyKeyboard(int key)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
|
|
}
|
|
|
|
int PageManager::SetKeyBoardFocus(int inFocus)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
|
|
}
|
|
|
|
int PageManager::NotifyVarChange(std::string varName, std::string value)
|
|
{
|
|
return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
|
|
}
|
|
|
|
extern "C" void gui_notifyVarChange(const char *name, const char* value)
|
|
{
|
|
if (!gGuiRunning) return;
|
|
|
|
PageManager::NotifyVarChange(name, value);
|
|
}
|
|
|