diff options
Diffstat (limited to 'gui/button.cpp')
-rw-r--r-- | gui/button.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/gui/button.cpp b/gui/button.cpp new file mode 100644 index 000000000..72e2fe905 --- /dev/null +++ b/gui/button.cpp @@ -0,0 +1,194 @@ +// button.cpp - GUIButton object + +#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" + +GUIButton::GUIButton(xml_node<>* node) + : Conditional(node) +{ + xml_attribute<>* attr; + xml_node<>* child; + + mButtonImg = NULL; + mButtonIcon = NULL; + mButtonLabel = NULL; + mAction = NULL; + mRendered = false; + + if (!node) return; + + // Three of the four can be loaded directly from the node + mButtonImg = new GUIImage(node); + mButtonLabel = new GUIText(node); + mAction = new GUIAction(node); + + if (mButtonImg->Render() < 0) + { + LOGE("Unable to locate button image\n"); + delete mButtonImg; + mButtonImg = NULL; + } + if (mButtonLabel->Render() < 0) + { + delete mButtonLabel; + mButtonLabel = NULL; + } + + // The icon is a special case + child = node->first_node("icon"); + if (child) + { + attr = child->first_attribute("resource"); + if (attr) + mButtonIcon = PageManager::FindResource(attr->value()); + } + + int x, y, w, h; + if (mButtonImg) mButtonImg->GetRenderPos(x, y, w, h); + SetRenderPos(x, y, w, h); + return; +} + +GUIButton::~GUIButton() +{ + if (mButtonImg) delete mButtonImg; + if (mButtonLabel) delete mButtonLabel; + if (mAction) delete mAction; + if (mButtonIcon) delete mButtonIcon; +} + +int GUIButton::Render(void) +{ + if (!isConditionTrue()) + { + mRendered = false; + return 0; + } + + int ret = 0; + + if (mButtonImg) ret = mButtonImg->Render(); + if (ret < 0) return ret; + if (mButtonIcon && mButtonIcon->GetResource()) + gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY); + if (mButtonLabel) ret = mButtonLabel->Render(); + if (ret < 0) return ret; + mRendered = true; + return ret; +} + +int GUIButton::Update(void) +{ + if (!isConditionTrue()) return (mRendered ? 2 : 0); + if (!mRendered) return 2; + + int ret = 0, ret2 = 0; + + if (mButtonImg) ret = mButtonImg->Update(); + if (ret < 0) return ret; + + if (ret == 0) + { + if (mButtonLabel) ret2 = mButtonLabel->Update(); + if (ret2 < 0) return ret2; + if (ret2 > ret) ret = ret2; + } + else if (ret == 1) + { + // The button re-rendered, so everyone else is a render + if (mButtonIcon && mButtonIcon->GetResource()) + gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY); + if (mButtonLabel) ret = mButtonLabel->Render(); + if (ret < 0) return ret; + ret = 1; + } + else + { + // Aparently, the button needs a background update + ret = 2; + } + return ret; +} + +int GUIButton::SetRenderPos(int x, int y, int w, int h) +{ + mRenderX = x; + mRenderY = y; + if (w || h) + { + mRenderW = w; + mRenderH = h; + } + + mIconW = 0; mIconH = 0; + if (mButtonIcon && mButtonIcon->GetResource()) + { + mIconW = gr_get_width(mButtonIcon->GetResource()); + mIconH = gr_get_height(mButtonIcon->GetResource()); + } + + mTextH = 0; + mTextW = 0; + mIconX = mRenderX + ((mRenderW - mIconW) / 2); + if (mButtonLabel) mButtonLabel->GetCurrentBounds(mTextW, mTextH); + if (mTextW) + { + // As a special case, we'll allow large text which automatically moves it to the right. + if (mTextW > mRenderW) + { + mTextX = mRenderW + mRenderX + 5; + mRenderW += mTextW + 5; + } + else + { + mTextX = mRenderX + ((mRenderW - mTextW) / 2); + } + } + + if (mIconH == 0 || mTextH == 0 || mIconH + mTextH > mRenderH) + { + mIconY = mRenderY + (mRenderH / 2) - (mIconH / 2); + mTextY = mRenderY + (mRenderH / 2) - (mTextH / 2); + } + else + { + int divisor = mRenderH - (mIconH + mTextH); + mIconY = mRenderY + (divisor / 3); + mTextY = mRenderY + (divisor * 2 / 3) + mIconH; + } + + if (mButtonLabel) mButtonLabel->SetRenderPos(mTextX, mTextY); + if (mAction) mAction->SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH); + SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH); + return 0; +} + +int GUIButton::NotifyTouch(TOUCH_STATE state, int x, int y) +{ + if (!isConditionTrue()) return -1; + return (mAction ? mAction->NotifyTouch(state, x, y) : 1); +} + |