diff --git a/xbmc/guilib/GUIControlFactory.cpp b/xbmc/guilib/GUIControlFactory.cpp index 5f00ad2669bfa..c1584da0982f4 100644 --- a/xbmc/guilib/GUIControlFactory.cpp +++ b/xbmc/guilib/GUIControlFactory.cpp @@ -174,18 +174,41 @@ bool CGUIControlFactory::GetFloatRange(const TiXmlNode* pRootNode, const char* s return true; } -bool CGUIControlFactory::GetDimension(const TiXmlNode *pRootNode, const char* strTag, float &value, float &min) +float CGUIControlFactory::ParsePosition(const char* pos, float parentSize) +{ + char* end; + float value = (float)strtod(pos, &end); + if (end) + { + if (*end == 'r') + value = parentSize - value; + else if (*end == '%') + value = value * parentSize / 100.0f; + } + return value; +} + +bool CGUIControlFactory::GetPosition(const TiXmlElement *pControlNode, const char* strTag, float& value, float parentSize) +{ + const TiXmlElement* pNode = pControlNode->FirstChildElement(strTag); + if (!pNode || !pNode->FirstChild()) return false; + + value = ParsePosition(pNode->FirstChild()->Value(), parentSize); + return true; +} + +bool CGUIControlFactory::GetDimension(const TiXmlNode *pRootNode, const char* strTag, float &value, float &min, float parentSize) { const TiXmlElement* pNode = pRootNode->FirstChildElement(strTag); if (!pNode || !pNode->FirstChild()) return false; if (0 == strnicmp("auto", pNode->FirstChild()->Value(), 4)) { // auto-width - at least min must be set - pNode->QueryFloatAttribute("max", &value); - pNode->QueryFloatAttribute("min", &min); + value = ParsePosition(pNode->Attribute("max"), parentSize); + min = ParsePosition(pNode->Attribute("min"), parentSize); if (!min) min = 1; return true; } - value = (float)atof(pNode->FirstChild()->Value()); + value = ParsePosition(pNode->FirstChild()->Value(), parentSize); return true; } @@ -691,19 +714,57 @@ CGUIControl* CGUIControlFactory::Create(int parentID, const CRect &rect, TiXmlEl // TODO: Perhaps we should check here whether id is valid for focusable controls // such as buttons etc. For labels/fadelabels/images it does not matter - XMLUtils::GetFloat(pControlNode, "posx", posX); - XMLUtils::GetFloat(pControlNode, "posy", posY); - // Convert these from relative coords - CStdString pos; - XMLUtils::GetString(pControlNode, "posx", pos); - if (pos.Right(1) == "r") - posX = rect.Width() - posX; - XMLUtils::GetString(pControlNode, "posy", pos); - if (pos.Right(1) == "r") - posY = rect.Height() - posY; - - GetDimension(pControlNode, "width", width, minWidth); - GetDimension(pControlNode, "height", height, minHeight); + { + // determine position and size of control + // horizontal + bool hasLeft = false; + bool hasWidth = false; + + if (GetPosition(pControlNode, "left", posX, rect.Width()) || + GetPosition(pControlNode, "posx", posX, rect.Width())) + hasLeft = true; + + if (GetDimension(pControlNode, "width", width, minWidth, rect.Width())) + hasWidth = true; + + if (hasLeft != hasWidth) // poor man xor, we have to have at least 1 to continue + { + // if we have just one of , we search for + float right; + if (GetPosition(pControlNode, "right", right, rect.Width())) + { + if (hasLeft) + width = (rect.Width() - right) - posX; + else // if (hasWidth) + posX = (rect.Width() - right) - width; + } + } + + // vertical + bool hasTop = false; + bool hasHeight = false; + + if (GetPosition(pControlNode, "top", posY, rect.Height()) || + GetPosition(pControlNode, "posy", posY, rect.Height())) + hasTop = true; + + if (GetDimension(pControlNode, "height", height, minHeight, rect.Height())) + hasHeight = true; + + if (hasTop != hasHeight) // poor man xor, we have to have at least 1 to continue + { + // if we have just one of , we search for + float bottom; + if (GetPosition(pControlNode, "bottom", bottom, rect.Height())) + { + if (hasTop) + height = (rect.Height() - bottom) - posY; + else // if (hasHeight) + posY = (rect.Height() - bottom) - height; + } + } + } + XMLUtils::GetFloat(pControlNode, "offsetx", offset.x); XMLUtils::GetFloat(pControlNode, "offsety", offset.y); diff --git a/xbmc/guilib/GUIControlFactory.h b/xbmc/guilib/GUIControlFactory.h index 4f2bd03e3f295..b3b482137f3ad 100644 --- a/xbmc/guilib/GUIControlFactory.h +++ b/xbmc/guilib/GUIControlFactory.h @@ -72,7 +72,7 @@ class CGUIControlFactory \param min minimum value - set != 0 if auto is used. \return true if we found and read the tag. */ - static bool GetDimension(const TiXmlNode* pRootNode, const char* strTag, float &value, float &min); + static bool GetDimension(const TiXmlNode* pRootNode, const char* strTag, float &value, float &min, float parentSize); static bool GetAspectRatio(const TiXmlNode* pRootNode, const char* strTag, CAspectRatio &aspectRatio); static bool GetInfoTexture(const TiXmlNode* pRootNode, const char* strTag, CTextureInfo &image, CGUIInfoLabel &info, int parentID); static bool GetTexture(const TiXmlNode* pRootNode, const char* strTag, CTextureInfo &image); @@ -102,6 +102,8 @@ class CGUIControlFactory static bool GetHitRect(const TiXmlNode* pRootNode, CRect &rect); static bool GetScroller(const TiXmlNode *pControlNode, const CStdString &scrollerTag, CScroller& scroller); private: + static float ParsePosition(const char* pos, float parentSize); + static bool GetPosition(const TiXmlElement *pControlNode, const char* strTag, float& value, float parentSize); static CStdString GetType(const TiXmlElement *pControlNode); static bool GetConditionalVisibility(const TiXmlNode* control, CStdString &condition, CStdString &allowHiddenFocus); bool GetString(const TiXmlNode* pRootNode, const char* strTag, CStdString& strString);