| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- //
- // Urho3D Engine
- // Copyright (c) 2008-2011 Lasse Öörni
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- #include "Precompiled.h"
- #include "Log.h"
- #include "ResourceCache.h"
- #include "StringUtils.h"
- #include "UIElement.h"
- #include "UIEvents.h"
- #include "DebugNew.h"
- UIElement::UIElement(const std::string& name) :
- mName(name),
- mParent(0),
- mPosition(IntVector2::sZero),
- mSize(IntVector2::sZero),
- mHorizontalAlignment(HA_LEFT),
- mVerticalAlignment(VA_TOP),
- mPriority(0),
- mOpacity(1.0f),
- mBringToFront(false),
- mClipChildren(false),
- mEnabled(false),
- mFocusable(false),
- mFocus(false),
- mVisible(true),
- mScreenPositionDirty(true),
- mDerivedOpacityDirty(true),
- mHasColorGradient(false)
- {
- }
- UIElement::~UIElement()
- {
- // If child elements have outside references, detach them
- while (mChildren.size())
- {
- const SharedPtr<UIElement>& element = mChildren.back();
- if (element.getRefCount() > 1)
- {
- element->mParent = 0;
- element->markDirty();
- }
- mChildren.pop_back();
- }
- }
- XMLElement UIElement::loadParameters(XMLFile* file, const std::string& elementName, ResourceCache* cache)
- {
- if (!file)
- SAFE_EXCEPTION_RET("Null UI definition file", XMLElement());
- if (!cache)
- SAFE_EXCEPTION_RET("Null resource cache", XMLElement());
-
- XMLElement rootElem = file->getRootElement();
- XMLElement paramElem = rootElem.getChildElement("element", false);
-
- while (paramElem.notNull())
- {
- if (paramElem.getString("name") == elementName)
- break;
- paramElem = paramElem.getNextElement("element");
- }
-
- if (paramElem.isNull())
- SAFE_EXCEPTION_RET("No UI element definition " + elementName + " in " + file->getName(), XMLElement());
-
- if (paramElem.hasChildElement("position"))
- setPosition(paramElem.getChildElement("position").getIntVector2("value"));
- if (paramElem.hasChildElement("size"))
- setSize(paramElem.getChildElement("size").getIntVector2("value"));
- if (paramElem.hasChildElement("alignment"))
- {
- XMLElement alignElem = paramElem.getChildElement("alignment");
-
- std::string horiz;
- std::string vert;
- if (alignElem.hasAttribute("h"))
- horiz = alignElem.getStringLower("h");
- if (alignElem.hasAttribute("v"))
- vert = alignElem.getStringLower("v");
- if (alignElem.hasAttribute("horizontal"))
- horiz = alignElem.getStringLower("horizontal");
- if (alignElem.hasAttribute("vertical"))
- vert = alignElem.getStringLower("vertical");
- if (horiz == "left")
- setHorizontalAlignment(HA_LEFT);
- if (horiz == "center")
- setHorizontalAlignment(HA_CENTER);
- if (horiz == "right")
- setHorizontalAlignment(HA_RIGHT);
- if (vert == "top")
- setVerticalAlignment(VA_TOP);
- if (vert == "center")
- setVerticalAlignment(VA_CENTER);
- if (vert == "bottom")
- setVerticalAlignment(VA_BOTTOM);
- }
- if (paramElem.hasChildElement("priority"))
- setPriority(paramElem.getChildElement("priority").getInt("value"));
- if (paramElem.hasChildElement("opacity"))
- setOpacity(paramElem.getChildElement("opacity").getFloat("value"));
- if (paramElem.hasChildElement("color"))
- {
- XMLElement colorElem = paramElem.getChildElement("color");
- if (colorElem.hasAttribute("value"))
- setColor(colorElem.getColor("value"));
- if (colorElem.hasAttribute("topleft"))
- setColor(C_TOPLEFT, colorElem.getColor("topleft"));
- if (colorElem.hasAttribute("topright"))
- setColor(C_TOPRIGHT, colorElem.getColor("topright"));
- if (colorElem.hasAttribute("bottomleft"))
- setColor(C_BOTTOMLEFT, colorElem.getColor("bottomleft"));
- if (colorElem.hasAttribute("bottomright"))
- setColor(C_BOTTOMRIGHT, colorElem.getColor("bottomright"));
- }
- if (paramElem.hasChildElement("bringtofront"))
- setBringToFront(paramElem.getChildElement("bringtofront").getBool("enable"));
- if (paramElem.hasChildElement("clipchildren"))
- setClipChildren(paramElem.getChildElement("clipchildren").getBool("enable"));
- if (paramElem.hasChildElement("enabled"))
- setEnabled(paramElem.getChildElement("enabled").getBool("enable"));
- if (paramElem.hasChildElement("focusable"))
- setFocusable(paramElem.getChildElement("focusable").getBool("enable"));
- if (paramElem.hasChildElement("visible"))
- setVisible(paramElem.getChildElement("visible").getBool("enable"));
-
- return paramElem;
- }
- void UIElement::update(float timeStep)
- {
- }
- void UIElement::getBatches(std::vector<UIBatch>& batches, std::vector<UIQuad>& quads, const IntRect& currentScissor)
- {
- }
- IntVector2 UIElement::getScreenPosition()
- {
- if (mScreenPositionDirty)
- {
- IntVector2 pos = mPosition;
- const UIElement* parent = mParent;
- const UIElement* current = this;
-
- while (parent)
- {
- switch (current->mHorizontalAlignment)
- {
- case HA_LEFT:
- pos.mX += parent->mPosition.mX;
- break;
-
- case HA_CENTER:
- pos.mX += parent->mPosition.mX + parent->mSize.mX / 2 - current->mSize.mX / 2;
- break;
-
- case HA_RIGHT:
- pos.mX += parent->mPosition.mX + parent->mSize.mX - current->mSize.mX;
- break;
- }
- switch (current->mVerticalAlignment)
- {
- case VA_TOP:
- pos.mY += parent->mPosition.mY;
- break;
-
- case VA_CENTER:
- pos.mY += parent->mPosition.mY + parent->mSize.mY / 2 - current->mSize.mY / 2;
- break;
-
- case VA_BOTTOM:
- pos.mY += parent->mPosition.mY + parent->mSize.mY - current->mSize.mY;
- break;
- }
-
- current = parent;
- parent = parent->mParent;
- }
-
- mScreenPosition = pos;
- mScreenPositionDirty = false;
- }
-
- return mScreenPosition;
- }
- float UIElement::getDerivedOpacity()
- {
- if (mDerivedOpacityDirty)
- {
- float opacity = mOpacity;
- const UIElement* parent = mParent;
-
- while (parent)
- {
- opacity *= parent->mOpacity;
- parent = parent->mParent;
- }
-
- mDerivedOpacity = opacity;
- mDerivedOpacityDirty = false;
- }
-
- return mDerivedOpacity;
- }
- void UIElement::onChar(unsigned key)
- {
- }
- void UIElement::onHover(const IntVector2& position, const IntVector2& screenPosition)
- {
- }
- void UIElement::onClick(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
- {
- }
- void UIElement::onDragStart(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
- {
- }
- void UIElement::onDragEnd(const IntVector2& position, const IntVector2& screenPosition)
- {
- }
- void UIElement::onDragMove(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
- {
- }
- void UIElement::setName(const std::string& name)
- {
- mName = name;
- }
- void UIElement::setPosition(const IntVector2& position)
- {
- mPosition = position;
- markDirty();
- }
- void UIElement::setPosition(int x, int y)
- {
- setPosition(IntVector2(x, y));
- }
- void UIElement::setSize(const IntVector2& size)
- {
- mSize.mX = max(size.mX, 0);
- mSize.mY = max(size.mY, 0);
- markDirty();
- }
- void UIElement::setSize(int width, int height)
- {
- setSize(IntVector2(width, height));
- }
- void UIElement::setWidth(int width)
- {
- setSize(IntVector2(width, mSize.mY));
- }
- void UIElement::setHeight(int height)
- {
- setSize(IntVector2(mSize.mX, height));
- }
- void UIElement::setAlignment(HorizontalAlignment hAlign, VerticalAlignment vAlign)
- {
- mHorizontalAlignment = hAlign;
- mVerticalAlignment = vAlign;
- markDirty();
- }
- void UIElement::setHorizontalAlignment(HorizontalAlignment align)
- {
- mHorizontalAlignment = align;
- markDirty();
- }
- void UIElement::setVerticalAlignment(VerticalAlignment align)
- {
- mVerticalAlignment = align;
- markDirty();
- }
- void UIElement::setColor(const Color& color)
- {
- for (unsigned i = 0; i < NUM_UIELEMENT_CORNERS; ++i)
- mColor[i] = color;
- mHasColorGradient = false;
- }
- void UIElement::setColor(float r, float g, float b)
- {
- setColor(Color(r, g, b));
- }
- void UIElement::setColor(UIElementCorner corner, const Color& color)
- {
- mColor[corner] = color;
- mHasColorGradient = false;
-
- for (unsigned i = 0; i < NUM_UIELEMENT_CORNERS; ++i)
- {
- if ((i != corner) && (mColor[i] != mColor[corner]))
- mHasColorGradient = true;
- }
- }
- void UIElement::setColor(UIElementCorner corner, float r, float g, float b)
- {
- setColor(corner, Color(r, g, b));
- }
- void UIElement::setPriority(int priority)
- {
- mPriority = priority;
- }
- void UIElement::setOpacity(float opacity)
- {
- mOpacity = clamp(opacity, 0.0f, 1.0f);
- markDirty();
- }
- void UIElement::setBringToFront(bool enable)
- {
- mBringToFront = enable;
- }
- void UIElement::setClipChildren(bool enable)
- {
- mClipChildren = enable;
- }
- void UIElement::setEnabled(bool enable)
- {
- mEnabled = enable;
- }
- void UIElement::setFocusable(bool enable)
- {
- mFocusable = enable;
- }
- void UIElement::setFocus(bool enable)
- {
- if (!mFocusable)
- enable = false;
-
- if (enable != mFocus)
- {
- mFocus = enable;
-
- using namespace Focused;
-
- VariantMap eventData;
- eventData[P_ELEMENT] = (void*)this;
- sendEvent(mFocus ? EVENT_FOCUSED : EVENT_DEFOCUSED, eventData);
- }
- }
- void UIElement::setVisible(bool enable)
- {
- mVisible = enable;
- }
- void UIElement::addChild(UIElement* element)
- {
- if ((!element) || (element->mParent == this) || (mParent == element))
- return;
-
- if (element->mParent)
- element->mParent->removeChild(element);
-
- mChildren.push_back(SharedPtr<UIElement>(element));
-
- element->mParent = this;
- element->markDirty();
- }
- void UIElement::removeChild(UIElement* element)
- {
- for (std::vector<SharedPtr<UIElement> >::iterator i = mChildren.begin(); i != mChildren.end(); ++i)
- {
- if ((*i) == element)
- {
- element->mParent = 0;
- element->markDirty();
- mChildren.erase(i);
- return;
- }
- }
- }
- void UIElement::removeAllChildren()
- {
- while (mChildren.size())
- {
- const SharedPtr<UIElement>& element = mChildren.back();
- element->mParent = 0;
- element->markDirty();
- mChildren.pop_back();
- }
- }
- std::vector<UIElement*> UIElement::getChildren(bool recursive) const
- {
- if (!recursive)
- {
- std::vector<UIElement*> ret;
- for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
- ret.push_back(*i);
-
- return ret;
- }
- else
- {
- std::vector<UIElement*> allChildren;
- getChildrenRecursive(allChildren);
-
- return allChildren;
- }
- }
- unsigned UIElement::getNumChildren(bool recursive) const
- {
- if (!recursive)
- return mChildren.size();
- else
- {
- unsigned allChildren = mChildren.size();
- for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
- allChildren += (*i)->getNumChildren(true);
-
- return allChildren;
- }
- }
- UIElement* UIElement::getChild(unsigned index) const
- {
- if (index >= mChildren.size())
- return 0;
-
- return mChildren[index];
- }
- UIElement* UIElement::getChild(const std::string& name, bool recursive) const
- {
- for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
- {
- if ((*i)->mName == name)
- return *i;
-
- if (recursive)
- {
- UIElement* element = (*i)->getChild(name, true);
- if (element)
- return element;
- }
- }
-
- return 0;
- }
- IntVector2 UIElement::screenToElement(const IntVector2& screenPosition)
- {
- return screenPosition - getScreenPosition();
- }
- IntVector2 UIElement::elementToScreen(const IntVector2& position)
- {
- return position + getScreenPosition();
- }
- void UIElement::adjustScissor(IntRect& currentScissor)
- {
- if (mClipChildren)
- {
- IntVector2 screenPos = getScreenPosition();
- currentScissor.mLeft = max(currentScissor.mLeft, screenPos.mX);
- currentScissor.mTop = max(currentScissor.mTop, screenPos.mY);
- currentScissor.mRight = min(currentScissor.mRight, screenPos.mX + mSize.mX);
- currentScissor.mBottom = min(currentScissor.mBottom, screenPos.mY + mSize.mY);
- }
- }
- void UIElement::markDirty()
- {
- if ((mScreenPositionDirty) && (mDerivedOpacityDirty))
- return;
-
- mScreenPositionDirty = true;
- mDerivedOpacityDirty = true;
-
- for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
- (*i)->markDirty();
- }
- void UIElement::getChildrenRecursive(std::vector<UIElement*>& dest) const
- {
- for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
- {
- dest.push_back(*i);
- (*i)->getChildrenRecursive(dest);
- }
- }
|