UIElement.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Log.h"
  25. #include "ResourceCache.h"
  26. #include "UIElement.h"
  27. #include "UIEvents.h"
  28. #include "DebugNew.h"
  29. UIElement::UIElement(const std::string& name) :
  30. mName(name),
  31. mParent(0),
  32. mOrigin(0),
  33. mClipBorder(IntRect::sZero),
  34. mHoverColor(Color(0.0f, 0.0f, 0.0f, 0.0f)),
  35. mPriority(0),
  36. mOpacity(1.0f),
  37. mBringToFront(false),
  38. mBringToBack(true),
  39. mClipChildren(false),
  40. mEnabled(false),
  41. mFocusable(false),
  42. mFocus(false),
  43. mVisible(true),
  44. mHovering(false),
  45. mPosition(IntVector2::sZero),
  46. mSize(IntVector2::sZero),
  47. mChildOffset(IntVector2::sZero),
  48. mHorizontalAlignment(HA_LEFT),
  49. mVerticalAlignment(VA_TOP),
  50. mScreenPositionDirty(true),
  51. mDerivedOpacityDirty(true),
  52. mHasColorGradient(false)
  53. {
  54. }
  55. UIElement::~UIElement()
  56. {
  57. // If child elements have outside references, detach them
  58. while (mChildren.size())
  59. {
  60. const SharedPtr<UIElement>& element = mChildren.back();
  61. if (element.getRefCount() > 1)
  62. {
  63. element->mParent = 0;
  64. element->markDirty();
  65. }
  66. mChildren.pop_back();
  67. }
  68. }
  69. void UIElement::setStyle(const XMLElement& element, ResourceCache* cache)
  70. {
  71. if (!cache)
  72. return;
  73. if (element.hasAttribute("name"))
  74. mName = element.getString("name");
  75. if (element.hasChildElement("position"))
  76. setPosition(element.getChildElement("position").getIntVector2("value"));
  77. if (element.hasChildElement("size"))
  78. setSize(element.getChildElement("size").getIntVector2("value"));
  79. if (element.hasChildElement("alignment"))
  80. {
  81. XMLElement alignElem = element.getChildElement("alignment");
  82. std::string horiz;
  83. std::string vert;
  84. if (alignElem.hasAttribute("h"))
  85. horiz = alignElem.getStringLower("h");
  86. if (alignElem.hasAttribute("v"))
  87. vert = alignElem.getStringLower("v");
  88. if (alignElem.hasAttribute("horizontal"))
  89. horiz = alignElem.getStringLower("horizontal");
  90. if (alignElem.hasAttribute("vertical"))
  91. vert = alignElem.getStringLower("vertical");
  92. if (horiz == "left")
  93. setHorizontalAlignment(HA_LEFT);
  94. if (horiz == "center")
  95. setHorizontalAlignment(HA_CENTER);
  96. if (horiz == "right")
  97. setHorizontalAlignment(HA_RIGHT);
  98. if (vert == "top")
  99. setVerticalAlignment(VA_TOP);
  100. if (vert == "center")
  101. setVerticalAlignment(VA_CENTER);
  102. if (vert == "bottom")
  103. setVerticalAlignment(VA_BOTTOM);
  104. }
  105. if (element.hasChildElement("clipborder"))
  106. setClipBorder(element.getChildElement("clipborder").getIntRect("value"));
  107. if (element.hasChildElement("priority"))
  108. setPriority(element.getChildElement("priority").getInt("value"));
  109. if (element.hasChildElement("opacity"))
  110. setOpacity(element.getChildElement("opacity").getFloat("value"));
  111. if (element.hasChildElement("color"))
  112. {
  113. XMLElement colorElem = element.getChildElement("color");
  114. if (colorElem.hasAttribute("value"))
  115. setColor(colorElem.getColor("value"));
  116. if (colorElem.hasAttribute("topleft"))
  117. setColor(C_TOPLEFT, colorElem.getColor("topleft"));
  118. if (colorElem.hasAttribute("topright"))
  119. setColor(C_TOPRIGHT, colorElem.getColor("topright"));
  120. if (colorElem.hasAttribute("bottomleft"))
  121. setColor(C_BOTTOMLEFT, colorElem.getColor("bottomleft"));
  122. if (colorElem.hasAttribute("bottomright"))
  123. setColor(C_BOTTOMRIGHT, colorElem.getColor("bottomright"));
  124. }
  125. if (element.hasChildElement("hovercolor"))
  126. setHoverColor(element.getChildElement("hovercolor").getColor("value"));
  127. if (element.hasChildElement("bringtofront"))
  128. setBringToFront(element.getChildElement("bringtofront").getBool("enable"));
  129. if (element.hasChildElement("bringtoback"))
  130. setBringToBack(element.getChildElement("bringtoback").getBool("enable"));
  131. if (element.hasChildElement("clipchildren"))
  132. setClipChildren(element.getChildElement("clipchildren").getBool("enable"));
  133. if (element.hasChildElement("enabled"))
  134. setEnabled(element.getChildElement("enabled").getBool("enable"));
  135. if (element.hasChildElement("focusable"))
  136. setFocusable(element.getChildElement("focusable").getBool("enable"));
  137. if (element.hasChildElement("visible"))
  138. setVisible(element.getChildElement("visible").getBool("enable"));
  139. }
  140. void UIElement::update(float timeStep)
  141. {
  142. }
  143. void UIElement::getBatches(std::vector<UIBatch>& batches, std::vector<UIQuad>& quads, const IntRect& currentScissor)
  144. {
  145. // Reset hovering for next frame
  146. mHovering = false;
  147. }
  148. IntVector2 UIElement::getScreenPosition()
  149. {
  150. if (mScreenPositionDirty)
  151. {
  152. IntVector2 pos = mPosition;
  153. const UIElement* parent = mParent;
  154. const UIElement* current = this;
  155. while (parent)
  156. {
  157. switch (current->mHorizontalAlignment)
  158. {
  159. case HA_LEFT:
  160. pos.mX += parent->mPosition.mX;
  161. break;
  162. case HA_CENTER:
  163. pos.mX += parent->mPosition.mX + parent->mSize.mX / 2 - current->mSize.mX / 2;
  164. break;
  165. case HA_RIGHT:
  166. pos.mX += parent->mPosition.mX + parent->mSize.mX - current->mSize.mX;
  167. break;
  168. }
  169. switch (current->mVerticalAlignment)
  170. {
  171. case VA_TOP:
  172. pos.mY += parent->mPosition.mY;
  173. break;
  174. case VA_CENTER:
  175. pos.mY += parent->mPosition.mY + parent->mSize.mY / 2 - current->mSize.mY / 2;
  176. break;
  177. case VA_BOTTOM:
  178. pos.mY += parent->mPosition.mY + parent->mSize.mY - current->mSize.mY;
  179. break;
  180. }
  181. pos += parent->mChildOffset;
  182. current = parent;
  183. parent = parent->mParent;
  184. }
  185. mScreenPosition = pos;
  186. mScreenPositionDirty = false;
  187. }
  188. return mScreenPosition;
  189. }
  190. float UIElement::getDerivedOpacity()
  191. {
  192. if (mDerivedOpacityDirty)
  193. {
  194. float opacity = mOpacity;
  195. const UIElement* parent = mParent;
  196. while (parent)
  197. {
  198. opacity *= parent->mOpacity;
  199. parent = parent->mParent;
  200. }
  201. mDerivedOpacity = opacity;
  202. mDerivedOpacityDirty = false;
  203. }
  204. return mDerivedOpacity;
  205. }
  206. void UIElement::onChar(unsigned char c)
  207. {
  208. }
  209. void UIElement::onHover(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
  210. {
  211. mHovering = true;
  212. }
  213. void UIElement::onClick(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
  214. {
  215. }
  216. void UIElement::onDragStart(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
  217. {
  218. }
  219. void UIElement::onDragEnd(const IntVector2& position, const IntVector2& screenPosition)
  220. {
  221. }
  222. void UIElement::onDragMove(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
  223. {
  224. }
  225. void UIElement::setName(const std::string& name)
  226. {
  227. mName = name;
  228. }
  229. void UIElement::setPosition(const IntVector2& position)
  230. {
  231. if (position != mPosition)
  232. {
  233. mPosition = position;
  234. markDirty();
  235. }
  236. }
  237. void UIElement::setPosition(int x, int y)
  238. {
  239. setPosition(IntVector2(x, y));
  240. }
  241. void UIElement::setSize(const IntVector2& size)
  242. {
  243. if (size != mSize)
  244. {
  245. mSize.mX = max(size.mX, 0);
  246. mSize.mY = max(size.mY, 0);
  247. markDirty();
  248. }
  249. }
  250. void UIElement::setSize(int width, int height)
  251. {
  252. setSize(IntVector2(width, height));
  253. }
  254. void UIElement::setWidth(int width)
  255. {
  256. setSize(IntVector2(width, mSize.mY));
  257. }
  258. void UIElement::setHeight(int height)
  259. {
  260. setSize(IntVector2(mSize.mX, height));
  261. }
  262. void UIElement::setAlignment(HorizontalAlignment hAlign, VerticalAlignment vAlign)
  263. {
  264. mHorizontalAlignment = hAlign;
  265. mVerticalAlignment = vAlign;
  266. markDirty();
  267. }
  268. void UIElement::setHorizontalAlignment(HorizontalAlignment align)
  269. {
  270. mHorizontalAlignment = align;
  271. markDirty();
  272. }
  273. void UIElement::setVerticalAlignment(VerticalAlignment align)
  274. {
  275. mVerticalAlignment = align;
  276. markDirty();
  277. }
  278. void UIElement::setClipBorder(const IntRect& rect)
  279. {
  280. mClipBorder.mLeft = max(rect.mLeft, 0);
  281. mClipBorder.mTop = max(rect.mTop, 0);
  282. mClipBorder.mRight = max(rect.mRight, 0);
  283. mClipBorder.mBottom = max(rect.mBottom, 0);
  284. }
  285. void UIElement::setClipBorder(int left, int top, int right, int bottom)
  286. {
  287. setClipBorder(IntRect(left, top, right, bottom));
  288. }
  289. void UIElement::setColor(const Color& color)
  290. {
  291. for (unsigned i = 0; i < MAX_UIELEMENT_CORNERS; ++i)
  292. mColor[i] = color;
  293. mHasColorGradient = false;
  294. }
  295. void UIElement::setColor(UIElementCorner corner, const Color& color)
  296. {
  297. mColor[corner] = color;
  298. mHasColorGradient = false;
  299. for (unsigned i = 0; i < MAX_UIELEMENT_CORNERS; ++i)
  300. {
  301. if ((i != corner) && (mColor[i] != mColor[corner]))
  302. mHasColorGradient = true;
  303. }
  304. }
  305. void UIElement::setHoverColor(const Color& color)
  306. {
  307. mHoverColor = color;
  308. }
  309. void UIElement::setPriority(int priority)
  310. {
  311. mPriority = priority;
  312. }
  313. void UIElement::setOpacity(float opacity)
  314. {
  315. mOpacity = clamp(opacity, 0.0f, 1.0f);
  316. markDirty();
  317. }
  318. void UIElement::setBringToFront(bool enable)
  319. {
  320. mBringToFront = enable;
  321. }
  322. void UIElement::setBringToBack(bool enable)
  323. {
  324. mBringToBack = enable;
  325. }
  326. void UIElement::setClipChildren(bool enable)
  327. {
  328. mClipChildren = enable;
  329. }
  330. void UIElement::setEnabled(bool enable)
  331. {
  332. mEnabled = enable;
  333. }
  334. void UIElement::setFocusable(bool enable)
  335. {
  336. mFocusable = enable;
  337. }
  338. void UIElement::setFocus(bool enable)
  339. {
  340. if (!mFocusable)
  341. enable = false;
  342. if (enable != mFocus)
  343. {
  344. mFocus = enable;
  345. using namespace Focused;
  346. VariantMap eventData;
  347. eventData[P_ELEMENT] = (void*)this;
  348. sendEvent(mFocus ? EVENT_FOCUSED : EVENT_DEFOCUSED, eventData);
  349. }
  350. }
  351. void UIElement::setVisible(bool enable)
  352. {
  353. mVisible = enable;
  354. }
  355. void UIElement::setUserData(const Variant& userData)
  356. {
  357. mUserData = userData;
  358. }
  359. void UIElement::setStyleAuto(XMLFile* file, ResourceCache* cache)
  360. {
  361. XMLElement element = getStyleElement(file);
  362. setStyle(element, cache);
  363. }
  364. void UIElement::bringToFront()
  365. {
  366. // Follow the parent chain to the top level window. If it has BringToFront mode, bring it to front now
  367. UIElement* root = getRootElement();
  368. UIElement* ptr = this;
  369. while ((ptr) && (ptr->getParent() != root))
  370. ptr = ptr->getParent();
  371. if ((!ptr) || (!ptr->getBringToFront()))
  372. return;
  373. // Get the highest priority used by all other top level elements, decrease their priority by one,
  374. // and assign that to new front element. However, take into account only active (enabled) elements
  375. // and those which have the BringToBack flag set
  376. int maxPriority = M_MIN_INT;
  377. std::vector<UIElement*> topLevelElements = root->getChildren();
  378. for (std::vector<UIElement*>::iterator i = topLevelElements.begin(); i != topLevelElements.end(); ++i)
  379. {
  380. UIElement* other = *i;
  381. if ((other->isEnabled()) && (other->getBringToBack()) && (other != ptr))
  382. {
  383. int priority = other->getPriority();
  384. maxPriority = max(priority, maxPriority);
  385. other->setPriority(priority - 1);
  386. }
  387. }
  388. ptr->setPriority(maxPriority);
  389. }
  390. void UIElement::addChild(UIElement* element)
  391. {
  392. if ((!element) || (element->mParent == this) || (mParent == element))
  393. return;
  394. if (element->mParent)
  395. element->mParent->removeChild(element);
  396. mChildren.push_back(SharedPtr<UIElement>(element));
  397. element->mParent = this;
  398. element->markDirty();
  399. }
  400. void UIElement::removeChild(UIElement* element)
  401. {
  402. for (std::vector<SharedPtr<UIElement> >::iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  403. {
  404. if ((*i) == element)
  405. {
  406. element->mParent = 0;
  407. element->markDirty();
  408. mChildren.erase(i);
  409. return;
  410. }
  411. }
  412. }
  413. void UIElement::removeAllChildren()
  414. {
  415. while (mChildren.size())
  416. {
  417. const SharedPtr<UIElement>& element = mChildren.back();
  418. element->mParent = 0;
  419. element->markDirty();
  420. mChildren.pop_back();
  421. }
  422. }
  423. void UIElement::layoutHorizontal(int spacing, const IntRect& border, bool expand, bool contract)
  424. {
  425. IntVector2 currentPos(border.mLeft, border.mTop);
  426. IntVector2 neededSize(IntVector2::sZero);
  427. for (std::vector<SharedPtr<UIElement> >::iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  428. {
  429. (*i)->setHorizontalAlignment(HA_LEFT);
  430. if ((*i)->getVerticalAlignment() == VA_CENTER)
  431. (*i)->setPosition(currentPos.mX, 0);
  432. else
  433. (*i)->setPosition(currentPos);
  434. currentPos.mX += (*i)->getWidth() + spacing;
  435. if ((*i)->getHeight() + border.mTop + border.mBottom > neededSize.mY)
  436. neededSize.mY = (*i)->getHeight() + border.mTop + border.mBottom;
  437. }
  438. currentPos.mX -= spacing;
  439. if (currentPos.mX + border.mRight > neededSize.mX)
  440. neededSize.mX = currentPos.mX + border.mRight;
  441. adjustSize(neededSize, expand, contract);
  442. }
  443. void UIElement::layoutVertical(int spacing, const IntRect& border, bool expand, bool contract)
  444. {
  445. IntVector2 currentPos(border.mLeft, border.mTop);
  446. IntVector2 neededSize(IntVector2::sZero);
  447. for (std::vector<SharedPtr<UIElement> >::iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  448. {
  449. (*i)->setVerticalAlignment(VA_TOP);
  450. if ((*i)->getHorizontalAlignment() == HA_CENTER)
  451. (*i)->setPosition(0, currentPos.mY);
  452. else
  453. (*i)->setPosition(currentPos);
  454. currentPos.mY += (*i)->getHeight() + spacing;
  455. if ((*i)->getWidth() + border.mLeft + border.mRight > neededSize.mX)
  456. neededSize.mX = (*i)->getWidth() + border.mLeft + border.mRight;
  457. }
  458. currentPos.mY -= spacing;
  459. if (currentPos.mY + border.mBottom > neededSize.mY)
  460. neededSize.mY = currentPos.mY + border.mBottom;
  461. adjustSize(neededSize, expand, contract);
  462. }
  463. std::vector<UIElement*> UIElement::getChildren(bool recursive) const
  464. {
  465. if (!recursive)
  466. {
  467. std::vector<UIElement*> ret;
  468. for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  469. ret.push_back(*i);
  470. return ret;
  471. }
  472. else
  473. {
  474. std::vector<UIElement*> allChildren;
  475. getChildrenRecursive(allChildren);
  476. return allChildren;
  477. }
  478. }
  479. unsigned UIElement::getNumChildren(bool recursive) const
  480. {
  481. if (!recursive)
  482. return mChildren.size();
  483. else
  484. {
  485. unsigned allChildren = mChildren.size();
  486. for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  487. allChildren += (*i)->getNumChildren(true);
  488. return allChildren;
  489. }
  490. }
  491. UIElement* UIElement::getChild(unsigned index) const
  492. {
  493. if (index >= mChildren.size())
  494. return 0;
  495. return mChildren[index];
  496. }
  497. UIElement* UIElement::getChild(const std::string& name, bool recursive) const
  498. {
  499. for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  500. {
  501. if ((*i)->mName == name)
  502. return *i;
  503. if (recursive)
  504. {
  505. UIElement* element = (*i)->getChild(name, true);
  506. if (element)
  507. return element;
  508. }
  509. }
  510. return 0;
  511. }
  512. UIElement* UIElement::getRootElement() const
  513. {
  514. UIElement* root = mParent;
  515. if (!root)
  516. return 0;
  517. while (root->getParent())
  518. root = root->getParent();
  519. return root;
  520. }
  521. XMLElement UIElement::getStyleElement(XMLFile* file) const
  522. {
  523. if (file)
  524. {
  525. XMLElement rootElem = file->getRootElement();
  526. XMLElement childElem = rootElem.getChildElement("element");
  527. while (childElem)
  528. {
  529. if (childElem.getString("type") == getTypeName())
  530. return childElem;
  531. childElem = childElem.getNextElement("element");
  532. }
  533. }
  534. return XMLElement();
  535. }
  536. IntVector2 UIElement::screenToElement(const IntVector2& screenPosition)
  537. {
  538. return screenPosition - getScreenPosition();
  539. }
  540. IntVector2 UIElement::elementToScreen(const IntVector2& position)
  541. {
  542. return position + getScreenPosition();
  543. }
  544. bool UIElement::isInside(IntVector2 position, bool isScreen)
  545. {
  546. if (isScreen)
  547. position = screenToElement(position);
  548. return (position.mX >= 0) && (position.mY >= 0) && (position.mX < mSize.mX) && (position.mY < mSize.mY);
  549. }
  550. bool UIElement::isInsideCombined(IntVector2 position, bool isScreen)
  551. {
  552. // If child elements are clipped, no need to expand the rect
  553. if (mClipChildren)
  554. return isInside(position, isScreen);
  555. if (!isScreen)
  556. position = elementToScreen(position);
  557. IntRect combined = getCombinedScreenRect();
  558. return (position.mX >= combined.mLeft) && (position.mY >= combined.mTop) && (position.mX < combined.mRight) &&
  559. (position.mY < combined.mBottom);
  560. }
  561. IntRect UIElement::getCombinedScreenRect()
  562. {
  563. IntVector2 screenPosition(getScreenPosition());
  564. IntRect combined(screenPosition.mX, screenPosition.mY, screenPosition.mX + mSize.mX, screenPosition.mY + mSize.mY);
  565. for (std::vector<SharedPtr<UIElement> >::iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  566. {
  567. IntVector2 childPos = (*i)->getScreenPosition();
  568. const IntVector2& childSize = (*i)->getSize();
  569. if (childPos.mX < combined.mLeft)
  570. combined.mLeft = childPos.mX;
  571. if (childPos.mY < combined.mTop)
  572. combined.mTop = childPos.mY;
  573. if (childPos.mX + childSize.mX > combined.mRight)
  574. combined.mRight = childPos.mX + childSize.mX;
  575. if (childPos.mY + childSize.mY > combined.mBottom)
  576. combined.mBottom = childPos.mY + childSize.mY;
  577. }
  578. return combined;
  579. }
  580. void UIElement::setHovering(bool enable)
  581. {
  582. mHovering = enable;
  583. }
  584. void UIElement::setOrigin(UIElement* origin)
  585. {
  586. mOrigin = origin;
  587. }
  588. void UIElement::adjustScissor(IntRect& currentScissor)
  589. {
  590. if (mClipChildren)
  591. {
  592. IntVector2 screenPos = getScreenPosition();
  593. currentScissor.mLeft = max(currentScissor.mLeft, screenPos.mX + mClipBorder.mLeft);
  594. currentScissor.mTop = max(currentScissor.mTop, screenPos.mY + mClipBorder.mTop);
  595. currentScissor.mRight = min(currentScissor.mRight, screenPos.mX + mSize.mX - mClipBorder.mRight);
  596. currentScissor.mBottom = min(currentScissor.mBottom, screenPos.mY + mSize.mY - mClipBorder.mBottom);
  597. }
  598. }
  599. XMLElement UIElement::getStyleElement(XMLFile* file, const std::string& typeName)
  600. {
  601. if (file)
  602. {
  603. XMLElement rootElem = file->getRootElement();
  604. XMLElement childElem = rootElem.getChildElement("element");
  605. while (childElem)
  606. {
  607. if (childElem.getString("type") == typeName)
  608. return childElem;
  609. childElem = childElem.getNextElement("element");
  610. }
  611. }
  612. return XMLElement();
  613. }
  614. void UIElement::markDirty()
  615. {
  616. mScreenPositionDirty = true;
  617. mDerivedOpacityDirty = true;
  618. for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  619. (*i)->markDirty();
  620. }
  621. void UIElement::setChildOffset(const IntVector2& offset)
  622. {
  623. if (offset != mChildOffset)
  624. {
  625. mChildOffset = offset;
  626. for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  627. (*i)->markDirty();
  628. }
  629. }
  630. void UIElement::getChildrenRecursive(std::vector<UIElement*>& dest) const
  631. {
  632. for (std::vector<SharedPtr<UIElement> >::const_iterator i = mChildren.begin(); i != mChildren.end(); ++i)
  633. {
  634. dest.push_back(*i);
  635. (*i)->getChildrenRecursive(dest);
  636. }
  637. }
  638. void UIElement::adjustSize(const IntVector2& neededSize, bool expand, bool contract)
  639. {
  640. if (expand)
  641. {
  642. if (getWidth() < neededSize.mX)
  643. setWidth(neededSize.mX);
  644. if (getHeight() < neededSize.mY)
  645. setHeight(neededSize.mY);
  646. }
  647. if (contract)
  648. {
  649. if (getWidth() > neededSize.mX)
  650. setWidth(neededSize.mX);
  651. if (getHeight() > neededSize.mY)
  652. setHeight(neededSize.mY);
  653. }
  654. }