ui more error proning
This commit is contained in:
		
							parent
							
								
									992e0a8a6b
								
							
						
					
					
						commit
						dcbe4855bd
					
				|  | @ -1,120 +0,0 @@ | |||
| /* The MIT License
 | ||||
|  * | ||||
|  * Copyright (c) 2010 OTClient, https://github.com/edubart/otclient
 | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| #ifndef ANCHORLAYOUT_H | ||||
| #define ANCHORLAYOUT_H | ||||
| 
 | ||||
| #include "prerequisites.h" | ||||
| #include "uiconstants.h" | ||||
| 
 | ||||
| enum EAnchorType { | ||||
|     ANCHOR_LEFT = 0, | ||||
|     ANCHOR_RIGHT, | ||||
|     ANCHOR_TOP, | ||||
|     ANCHOR_BOTTOM, | ||||
|     ANCHOR_HORIZONTAL_CENTER, | ||||
|     ANCHOR_VERTICAL_CENTER, | ||||
|     ANCHOR_NONE | ||||
| }; | ||||
| 
 | ||||
| class AnchorLayout; | ||||
| typedef std::shared_ptr<AnchorLayout> AnchorLayoutPtr; | ||||
| typedef std::weak_ptr<AnchorLayout> AnchorLayoutWeakPtr; | ||||
| 
 | ||||
| class AnchorLine | ||||
| { | ||||
| public: | ||||
|     AnchorLine() : m_anchorType(ANCHOR_NONE) { } | ||||
|     AnchorLine(const AnchorLine& other) : | ||||
|         m_relativeElement(other.m_relativeElement), m_anchorType(other.m_anchorType) { } | ||||
|     AnchorLine(AnchorLayoutPtr relativeElement, EAnchorType anchorType) : | ||||
|         m_relativeElement(relativeElement), m_anchorType(anchorType) { } | ||||
|     bool isValid() const { return (m_anchorType != ANCHOR_NONE && !m_relativeElement.expired()); } | ||||
| 
 | ||||
|     int getPos() const; | ||||
|     EAnchorType getAnchorType() const { return m_anchorType; } | ||||
|     AnchorLayoutPtr getRelativeElement() const { return m_relativeElement.lock(); } | ||||
| 
 | ||||
| private: | ||||
|     AnchorLayoutWeakPtr m_relativeElement; | ||||
|     EAnchorType m_anchorType; | ||||
| }; | ||||
| 
 | ||||
| class AnchorLayout : public std::enable_shared_from_this<AnchorLayout> | ||||
| { | ||||
| public: | ||||
|     AnchorLayout() : | ||||
|         m_marginLeft(0), | ||||
|         m_marginRight(0), | ||||
|         m_marginTop(0), | ||||
|         m_marginBottom(0) { } | ||||
|     virtual ~AnchorLayout() { } | ||||
| 
 | ||||
|     void setSize(const Size& size); | ||||
|     Size getSize() { return m_rect.size(); } | ||||
| 
 | ||||
|     void setRect(const Rect& rect); | ||||
|     const Rect& getRect() const{ return m_rect; } | ||||
| 
 | ||||
|     void addAnchor(EAnchorType type, const AnchorLine& anchorLine); | ||||
|     void anchorLeft(const AnchorLine& anchorLine) { addAnchor(ANCHOR_LEFT, anchorLine); } | ||||
|     void anchorRight(const AnchorLine& anchorLine) { addAnchor(ANCHOR_RIGHT, anchorLine); } | ||||
|     void anchorTop(const AnchorLine& anchorLine) { addAnchor(ANCHOR_TOP, anchorLine); } | ||||
|     void anchorBottom(const AnchorLine& anchorLine) { addAnchor(ANCHOR_BOTTOM, anchorLine); } | ||||
|     void anchorHorizontalCenter(const AnchorLine& anchorLine) { addAnchor(ANCHOR_HORIZONTAL_CENTER, anchorLine); } | ||||
|     void anchorVerticalCenter(const AnchorLine& anchorLine) { addAnchor(ANCHOR_VERTICAL_CENTER, anchorLine); } | ||||
| 
 | ||||
|     AnchorLine left() { return AnchorLine(asAnchorLayout(), ANCHOR_LEFT); } | ||||
|     AnchorLine right() { return AnchorLine(asAnchorLayout(), ANCHOR_RIGHT); } | ||||
|     AnchorLine top() { return AnchorLine(asAnchorLayout(), ANCHOR_TOP); } | ||||
|     AnchorLine bottom() { return AnchorLine(asAnchorLayout(), ANCHOR_BOTTOM); } | ||||
|     AnchorLine horizontalCenter() { return AnchorLine(asAnchorLayout(), ANCHOR_HORIZONTAL_CENTER); } | ||||
|     AnchorLine verticalCenter() { return AnchorLine(asAnchorLayout(), ANCHOR_VERTICAL_CENTER); } | ||||
| 
 | ||||
|     void setMargin(int top, int left, int bottom, int right) { m_marginLeft = left; m_marginRight = right; m_marginTop = top; m_marginBottom = bottom; recalculateAnchors(); } | ||||
|     void setMargin(int horizontal, int vertical) { m_marginLeft = m_marginRight = horizontal; m_marginTop = m_marginBottom = vertical; recalculateAnchors(); } | ||||
|     void setMargin(int margin) { m_marginLeft = m_marginRight = m_marginTop = m_marginBottom = margin; recalculateAnchors(); } | ||||
| 
 | ||||
|     void setMarginLeft(int margin) { m_marginLeft = margin; recalculateAnchors(); } | ||||
|     void setMarginRight(int margin) { m_marginRight = margin; recalculateAnchors(); } | ||||
|     void setMarginTop(int margin) { m_marginTop = margin; recalculateAnchors(); } | ||||
|     void setMarginBottom(int margin) { m_marginBottom = margin; recalculateAnchors(); } | ||||
| 
 | ||||
|     AnchorLayoutPtr asAnchorLayout() { return shared_from_this(); } | ||||
| 
 | ||||
| private: | ||||
|     void recalculateAnchors(); | ||||
|     void addAnchoredElement(AnchorLayoutPtr anchoredElement); | ||||
| 
 | ||||
|     AnchorLine m_anchors[6]; | ||||
| 
 | ||||
|     Rect m_rect; | ||||
|     int m_marginLeft; | ||||
|     int m_marginRight; | ||||
|     int m_marginTop; | ||||
|     int m_marginBottom; | ||||
|     std::list<AnchorLayoutWeakPtr> m_anchoredElements; | ||||
| }; | ||||
| 
 | ||||
| #endif // ANCHORLAYOUT_H
 | ||||
|  | @ -38,7 +38,6 @@ public: | |||
|     void removeChild(UIElementPtr child); | ||||
|     UIElementPtr getChildById(const std::string& id); | ||||
| 
 | ||||
|     //TODO: make this backwards
 | ||||
|     UIElementPtr recursiveGetChildById(const std::string& id); | ||||
| 
 | ||||
|     virtual void render(); | ||||
|  |  | |||
|  | @ -57,3 +57,22 @@ void UIElement::render() | |||
|     if(m_skin) | ||||
|         m_skin->draw(this); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| UIElementPtr UIElement::backwardsGetElementById(const std::string& id) | ||||
| { | ||||
|     if(getId() == id) | ||||
|         return asUIElement(); | ||||
| 
 | ||||
|     UIElementPtr element; | ||||
| 
 | ||||
|     if(asUIContainer()) { | ||||
|         element = asUIContainer()->recursiveGetChildById(id); | ||||
|         if(element) | ||||
|             return element; | ||||
|     } | ||||
| 
 | ||||
|     if(getParent()) | ||||
|         element = getParent()->backwardsGetElementById(id); | ||||
|     return element; | ||||
| } | ||||
|  |  | |||
|  | @ -49,6 +49,8 @@ public: | |||
|     virtual void render(); | ||||
|     virtual bool onInputEvent(const InputEvent& event) { return false; } | ||||
| 
 | ||||
|     UIElementPtr backwardsGetElementById(const std::string& id); | ||||
| 
 | ||||
|     bool setSkin(const std::string& skinName); | ||||
|     void setSkin(UIElementSkin *skin); | ||||
|     UIElementSkin *getSkin() { return m_skin; } | ||||
|  |  | |||
|  | @ -46,35 +46,55 @@ int AnchorLine::getPos() const | |||
|                 return 0; | ||||
|         } | ||||
|     } | ||||
|     logError("anchor line of an element have expired"); | ||||
|     logError("anchor line of an element has expired, your UI is missconfigured"); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void UILayout::setSize(const Size& size) | ||||
| { | ||||
|     m_rect.setSize(size); | ||||
| 
 | ||||
|     // rect updated, recalculate itself and anchored elements positions
 | ||||
|     recalculateAnchors(); | ||||
| } | ||||
| 
 | ||||
| void UILayout::setRect(const Rect& rect) | ||||
| { | ||||
|     m_rect = rect; | ||||
| 
 | ||||
|     // rect updated, recalculate itself and anchored elements positions
 | ||||
|     recalculateAnchors(); | ||||
| } | ||||
| 
 | ||||
| void UILayout::addAnchor(EAnchorType type, const AnchorLine& anchorLine) | ||||
| bool UILayout::addAnchor(EAnchorType type, const AnchorLine& anchorLine) | ||||
| { | ||||
|     if(!anchorLine.isValid()) { | ||||
|         logError("anchoring for an element has failed, got an invalid anchor line"); | ||||
|         return; | ||||
|     // we can never anchor with itself
 | ||||
|     if(anchorLine.getRelativeElement() == asUILayout()) { | ||||
|         logError("anchoring with itself is not possible"); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     // check if this layout is already anchored with the relative element
 | ||||
|     // this only happens in missconfigurations
 | ||||
|     for(auto it = m_anchoredElements.begin(); it != m_anchoredElements.end(); ++it) { | ||||
|         if((*it).lock() == anchorLine.getRelativeElement()) { | ||||
|             logError("anchoring elements with each other is not possible"); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // setup the anchor
 | ||||
|     m_anchors[type] = anchorLine; | ||||
|     anchorLine.getRelativeElement()->addAnchoredElement(asUILayout()); | ||||
| 
 | ||||
|     // recalculate itself and anchored elements
 | ||||
|     recalculateAnchors(); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void UILayout::addAnchoredElement(UILayoutPtr anchoredElement) | ||||
| { | ||||
|     // check if is already anchored
 | ||||
|     bool found = false; | ||||
|     for(auto it = m_anchoredElements.begin(); it != m_anchoredElements.end(); ++it) { | ||||
|         if((*it).lock() == anchoredElement) { | ||||
|  | @ -82,13 +102,15 @@ void UILayout::addAnchoredElement(UILayoutPtr anchoredElement) | |||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // if not anchor it
 | ||||
|     if(!found) | ||||
|         m_anchoredElements.push_back(anchoredElement); | ||||
| } | ||||
| 
 | ||||
| void UILayout::recalculateAnchors() | ||||
| { | ||||
|     // horizontal
 | ||||
|     // recalculate horizontal position
 | ||||
|     if(m_anchors[ANCHOR_HORIZONTAL_CENTER].isValid()) { | ||||
|         m_rect.moveHorizontalCenter(m_anchors[ANCHOR_HORIZONTAL_CENTER].getPos() + m_marginLeft - m_marginRight); | ||||
|     } else { | ||||
|  | @ -102,7 +124,7 @@ void UILayout::recalculateAnchors() | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // vertical
 | ||||
|     // recalculate vertical position
 | ||||
|     if(m_anchors[ANCHOR_VERTICAL_CENTER].isValid()) { | ||||
|         m_rect.moveVerticalCenter(m_anchors[ANCHOR_VERTICAL_CENTER].getPos() + m_marginTop - m_marginBottom); | ||||
|     } else { | ||||
|  | @ -116,6 +138,7 @@ void UILayout::recalculateAnchors() | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // recalculate anchored elements positions
 | ||||
|     for(auto it = m_anchoredElements.begin(); it != m_anchoredElements.end(); ++it) { | ||||
|         UILayoutPtr element = (*it).lock(); | ||||
|         if(element) | ||||
|  |  | |||
|  | @ -52,6 +52,7 @@ public: | |||
|         m_relativeElement(relativeElement), m_anchorType(anchorType) { } | ||||
|     bool isValid() const { return (m_anchorType != ANCHOR_NONE && !m_relativeElement.expired()); } | ||||
| 
 | ||||
|     /// Get the position relative to this anchor line
 | ||||
|     int getPos() const; | ||||
|     EAnchorType getAnchorType() const { return m_anchorType; } | ||||
|     UILayoutPtr getRelativeElement() const { return m_relativeElement.lock(); } | ||||
|  | @ -74,10 +75,13 @@ public: | |||
|     void setSize(const Size& size); | ||||
|     Size getSize() { return m_rect.size(); } | ||||
| 
 | ||||
|     /// Set the layout rect, always absolute position
 | ||||
|     void setRect(const Rect& rect); | ||||
|     /// Get layout size, it always return the absolute position
 | ||||
|     const Rect& getRect() const{ return m_rect; } | ||||
| 
 | ||||
|     void addAnchor(EAnchorType type, const AnchorLine& anchorLine); | ||||
|     // anchors add methods
 | ||||
|     bool addAnchor(EAnchorType type, const AnchorLine& anchorLine); | ||||
|     void anchorLeft(const AnchorLine& anchorLine) { addAnchor(ANCHOR_LEFT, anchorLine); } | ||||
|     void anchorRight(const AnchorLine& anchorLine) { addAnchor(ANCHOR_RIGHT, anchorLine); } | ||||
|     void anchorTop(const AnchorLine& anchorLine) { addAnchor(ANCHOR_TOP, anchorLine); } | ||||
|  | @ -85,6 +89,7 @@ public: | |||
|     void anchorHorizontalCenter(const AnchorLine& anchorLine) { addAnchor(ANCHOR_HORIZONTAL_CENTER, anchorLine); } | ||||
|     void anchorVerticalCenter(const AnchorLine& anchorLine) { addAnchor(ANCHOR_VERTICAL_CENTER, anchorLine); } | ||||
| 
 | ||||
|     // anchor lines
 | ||||
|     AnchorLine left() { return AnchorLine(asUILayout(), ANCHOR_LEFT); } | ||||
|     AnchorLine right() { return AnchorLine(asUILayout(), ANCHOR_RIGHT); } | ||||
|     AnchorLine top() { return AnchorLine(asUILayout(), ANCHOR_TOP); } | ||||
|  | @ -92,10 +97,10 @@ public: | |||
|     AnchorLine horizontalCenter() { return AnchorLine(asUILayout(), ANCHOR_HORIZONTAL_CENTER); } | ||||
|     AnchorLine verticalCenter() { return AnchorLine(asUILayout(), ANCHOR_VERTICAL_CENTER); } | ||||
| 
 | ||||
|     // margins
 | ||||
|     void setMargin(int top, int left, int bottom, int right) { m_marginLeft = left; m_marginRight = right; m_marginTop = top; m_marginBottom = bottom; recalculateAnchors(); } | ||||
|     void setMargin(int horizontal, int vertical) { m_marginLeft = m_marginRight = horizontal; m_marginTop = m_marginBottom = vertical; recalculateAnchors(); } | ||||
|     void setMargin(int margin) { m_marginLeft = m_marginRight = m_marginTop = m_marginBottom = margin; recalculateAnchors(); } | ||||
| 
 | ||||
|     void setMarginLeft(int margin) { m_marginLeft = margin; recalculateAnchors(); } | ||||
|     void setMarginRight(int margin) { m_marginRight = margin; recalculateAnchors(); } | ||||
|     void setMarginTop(int margin) { m_marginTop = margin; recalculateAnchors(); } | ||||
|  | @ -104,6 +109,7 @@ public: | |||
|     UILayoutPtr asUILayout() { return shared_from_this(); } | ||||
| 
 | ||||
| private: | ||||
|     /// Recalculate itself and anchored elements positions
 | ||||
|     void recalculateAnchors(); | ||||
|     void addAnchoredElement(UILayoutPtr anchoredElement); | ||||
| 
 | ||||
|  |  | |||
|  | @ -241,13 +241,14 @@ void UILoader::loadElementAnchor(const UIElementPtr& element, EAnchorType type, | |||
|     if(relativeElementId == "parent" && element->getParent()) { | ||||
|         relativeElement = element->getParent()->asUILayout(); | ||||
|     } else { | ||||
|         UIElementPtr tmp = UIContainer::getRootContainer()->recursiveGetChildById(relativeElementId); | ||||
|         UIElementPtr tmp = element->backwardsGetElementById(relativeElementId); | ||||
|         if(tmp) | ||||
|             relativeElement = tmp->asUILayout(); | ||||
|     } | ||||
| 
 | ||||
|     if(relativeElement) { | ||||
|         element->addAnchor(type, AnchorLine(relativeElement, relativeAnchorType)); | ||||
|         if(!element->addAnchor(type, AnchorLine(relativeElement, relativeAnchorType))) | ||||
|             throw YAML::Exception(node.GetMark(), "error while processing anchors"); | ||||
|     } else { | ||||
|         throw YAML::Exception(node.GetMark(), "anchoring failed, does the relative element really exists?"); | ||||
|     } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Eduardo Bart
						Eduardo Bart