Feature #368 ยป control_positioning.patch
xbmc/guilib/GUIControlFactory.cpp (working copy) | ||
---|---|---|
return g_SkinInfo.ResolveConstant(pNode->FirstChild()->Value(), value);
|
||
}
|
||
bool CGUIControlFactory::GetDimension(const TiXmlNode *pRootNode, const char* strTag, float &value, float &min)
|
||
float CGUIControlFactory::ParsePosition(const char* pos, const float parentSize)
|
||
{
|
||
char* end = NULL;
|
||
float value = pos ? (float)strtod(pos, &end) : 0;
|
||
if (end)
|
||
{
|
||
if (*end == 'r')
|
||
value = parentSize - value;
|
||
else if (*end == '%')
|
||
value = value * parentSize / 100.0f;
|
||
}
|
||
return value;
|
||
}
|
||
|
||
bool CGUIControlFactory::GetPosition(const TiXmlNode *node, const char* strTag, const float parentSize, float& value)
|
||
{
|
||
const TiXmlElement* pNode = node->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, const float parentSize, float &value, float &min)
|
||
{
|
||
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
|
||
g_SkinInfo.ResolveConstant(pNode->Attribute("max"), value);
|
||
g_SkinInfo.ResolveConstant(pNode->Attribute("min"), min);
|
||
value = ParsePosition(pNode->Attribute("max"), parentSize);
|
||
min = ParsePosition(pNode->Attribute("min"), parentSize);
|
||
if (!min) min = 1;
|
||
return true;
|
||
}
|
||
return g_SkinInfo.ResolveConstant(pNode->FirstChild()->Value(), value);
|
||
}
|
||
bool CGUIControlFactory::GetDimensions(const TiXmlNode *node, const char *leftTag, const char *rightTag, const char *centerLeftTag,
|
||
const char *centerRightTag, const char *widthTag, const float parentSize, float &left,
|
||
float &width, float &min_width)
|
||
{
|
||
float center = 0, right = 0;
|
||
|
||
// read from the XML
|
||
bool hasLeft = GetPosition(node, leftTag, parentSize, left);
|
||
bool hasCenter = GetPosition(node, centerLeftTag, parentSize, center);
|
||
if (!hasCenter && GetPosition(node, centerRightTag, parentSize, center))
|
||
{
|
||
center = parentSize - center;
|
||
hasCenter = true;
|
||
}
|
||
bool hasRight = false;
|
||
if (GetPosition(node, rightTag, parentSize, right))
|
||
{
|
||
right = parentSize - right;
|
||
hasRight = true;
|
||
}
|
||
bool hasWidth = GetDimension(node, widthTag, parentSize, width, min_width);
|
||
|
||
if (!hasLeft)
|
||
{ // figure out position
|
||
if (hasCenter) // no left specified
|
||
{
|
||
if (hasWidth)
|
||
{
|
||
left = center - width/2;
|
||
hasLeft = true;
|
||
}
|
||
else
|
||
{
|
||
if (hasRight)
|
||
{
|
||
width = (right - center) * 2;
|
||
left = right - width;
|
||
hasLeft = true;
|
||
}
|
||
}
|
||
}
|
||
else if (hasRight) // no left or centre
|
||
{
|
||
if (hasWidth)
|
||
{
|
||
left = right - width;
|
||
hasLeft = true;
|
||
}
|
||
}
|
||
}
|
||
if (!hasWidth)
|
||
{
|
||
if (hasRight)
|
||
{
|
||
width = max(0.0f, right - left); // if left=0, this fills to size of parent
|
||
hasLeft = true;
|
||
}
|
||
else if (hasCenter)
|
||
{
|
||
if (hasLeft)
|
||
{
|
||
width = max(0.0f, (center - left) * 2);
|
||
hasWidth = true;
|
||
}
|
||
else if (center > 0 && center < parentSize)
|
||
{ // centre given, so fill to edge of parent
|
||
width = max(0.0f, min(parentSize - center, center) * 2);
|
||
left = center - width/2;
|
||
hasLeft = hasWidth = true;
|
||
}
|
||
}
|
||
else if (hasLeft) // neither right nor center specified
|
||
{
|
||
width = max(0.0f, parentSize - left); // if left=0, this fills to parent
|
||
}
|
||
}
|
||
return hasLeft && hasWidth;
|
||
}
|
||
bool CGUIControlFactory::GetPath(const TiXmlNode* pRootNode, const char* strTag, CStdString& strStringPath)
|
||
{
|
||
const TiXmlNode* pNode = pRootNode->FirstChild(strTag );
|
||
... | ... | |
int id = 0;
|
||
float posX = 0, posY = 0;
|
||
float width = 0, height = 0;
|
||
float minWidth = 0;
|
||
float minHeight = 0, minWidth = 0;
|
||
CGUIAction leftActions, rightActions, upActions, downActions, backActions, nextActions, prevActions;
|
||
... | ... | |
// 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
|
||
GetFloat(pControlNode, "posx", posX);
|
||
GetFloat(pControlNode, "posy", posY);
|
||
// Convert these from relative coords
|
||
CStdString pos;
|
||
XMLUtils::GetString(pControlNode, "posx", pos);
|
||
if (pos.Right(1) == "r")
|
||
posX = (rect.right - rect.left) - posX;
|
||
XMLUtils::GetString(pControlNode, "posy", pos);
|
||
if (pos.Right(1) == "r")
|
||
posY = (rect.bottom - rect.top) - posY;
|
||
GetDimension(pControlNode, "width", width, minWidth);
|
||
GetFloat(pControlNode, "height", height);
|
||
GetFloat(pControlNode, "offsetx", offset.x);
|
||
GetAlignment(pControlNode, "align", labelInfo.align);
|
||
if (!GetDimensions(pControlNode, "left", "right", "centerleft", "centerright", "width", (rect.right - rect.left), posX, width, minWidth))
|
||
{ // didn't get 2 dimensions, so test for old <posx> as well
|
||
if (GetPosition(pControlNode, "posx", (rect.right - rect.left), posX))
|
||
{ // <posx> available, so use it along with any hacks we used to support
|
||
if (!insideContainer &&
|
||
type == CGUIControl::GUICONTROL_LABEL &&
|
||
(labelInfo.align & XBFONT_RIGHT))
|
||
posX -= width;
|
||
}
|
||
if (!width)
|
||
width = max((rect.right - rect.left) - posX, 0.0f);
|
||
}
|
||
if (!GetDimensions(pControlNode, "top", "bottom", "centertop", "centerbottom", "height", (rect.bottom - rect.top), posY, height, minHeight))
|
||
{
|
||
GetPosition(pControlNode, "posy", (rect.bottom - rect.top), posY);
|
||
if (!height)
|
||
height = max((rect.bottom - rect.top) - posY, 0.0f);
|
||
}
|
||
|
||
GetFloat(pControlNode, "offsetx", offset.x);
|
||
GetFloat(pControlNode, "offsety", offset.y);
|
||
// adjust width and height accordingly for groups. Groups should
|
||
// take the width/height of the parent (adjusted for positioning)
|
||
// if none is defined.
|
||
if (type == CGUIControl::GUICONTROL_GROUP || type == CGUIControl::GUICONTROL_GROUPLIST)
|
||
{
|
||
if (!width)
|
||
width = max(rect.right - posX, 0.0f);
|
||
if (!height)
|
||
height = max(rect.bottom - posY, 0.0f);
|
||
}
|
||
hitRect.SetRect(posX, posY, posX + width, posY + height);
|
||
GetHitRect(pControlNode, hitRect);
|
||
... | ... | |
CStdString strFont;
|
||
if (XMLUtils::GetString(pControlNode, "font", strFont))
|
||
labelInfo.font = g_fontManager.GetFont(strFont);
|
||
GetAlignment(pControlNode, "align", labelInfo.align);
|
||
uint32_t alignY = 0;
|
||
if (GetAlignmentY(pControlNode, "aligny", alignY))
|
||
labelInfo.align |= alignY;
|
xbmc/guilib/GUIControlFactory.h (working copy) | ||
---|---|---|
*/
|
||
static CStdString TranslateControlType(CGUIControl::GUICONTROLTYPES type);
|
||
/*! \brief grab a dimension out of the XML
|
||
|
||
Supports plain reading of a number (or constant) and, in addition allows "auto" as the value
|
||
for the dimension, whereby value is set to the max attribute (if it exists) and min is set the min
|
||
attribute (if it exists) or 1. Auto values are thus detected by min != 0.
|
||
\param pRootNode XML node to read
|
||
\param strTag tag within pRootNode to read
|
||
\param value value to set, or maximum value if using auto
|
||
\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 GetUnsigned(const TiXmlNode* pRootNode, const char* strTag, unsigned int& value);
|
||
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);
|
||
... | ... | |
bool GetString(const TiXmlNode* pRootNode, const char* strTag, CStdString& strString);
|
||
bool GetFloatRange(const TiXmlNode* pRootNode, const char* strTag, float& iMinValue, float& iMaxValue, float& iIntervalValue);
|
||
bool GetIntRange(const TiXmlNode* pRootNode, const char* strTag, int& iMinValue, int& iMaxValue, int& iIntervalValue);
|
||
/*! \brief Parse a position string
|
||
Handles strings of the form
|
||
### number of pixels
|
||
###r number of pixels measured from the right
|
||
###% percentage of parent size
|
||
\param pos the string to parse.
|
||
\param parentSize the size of the parent.
|
||
\sa GetPosition
|
||
*/
|
||
static float ParsePosition(const char* pos, const float parentSize);
|
||
|
||
/*! \brief Get the value of a position tag from XML
|
||
Handles both absolute and relative values.
|
||
\param node the <control> XML node.
|
||
\param tag the XML node to parse.
|
||
\param parentSize the size of the parent, for relative positioning.
|
||
\param value [out] the returned value.
|
||
\sa ParsePosition, GetDimension, GetDimensions.
|
||
*/
|
||
static bool GetPosition(const TiXmlNode *node, const char* tag, const float parentSize, float& value);
|
||
|
||
/*! \brief grab a dimension out of the XML
|
||
Supports plain reading of a number (or constant) and, in addition allows "auto" as the value
|
||
for the dimension, whereby value is set to the max attribute (if it exists) and min is set the min
|
||
attribute (if it exists) or 1. Auto values are thus detected by min != 0.
|
||
\param node the <control> XML node to read
|
||
\param strTag tag within node to read
|
||
\param parentSize the size of the parent for relative sizing.
|
||
\param value value to set, or maximum value if using auto
|
||
\param min minimum value - set != 0 if auto is used.
|
||
\return true if we found and read the tag.
|
||
\sa GetPosition, GetDimensions, ParsePosition.
|
||
*/
|
||
static bool GetDimension(const TiXmlNode *node, const char* strTag, const float parentSize, float &value, float &min);
|
||
|
||
/*! \brief Retrieve the dimensions for a control.
|
||
|
||
Handles positioning based on at least 2 of left/right/center/width.
|
||
|
||
\param node the <control> node describing the control.
|
||
\param leftTag the tag that holds the left field.
|
||
\param rightTag the tag that holds the right field.
|
||
\param centerLeftTag the tag that holds the center left field.
|
||
\param centerRightTag the tag that holds the center right field.
|
||
\param widthTag the tag holding the width.
|
||
\param parentSize the size of the parent, for relative sizing.
|
||
\param pos [out] the discovered position.
|
||
\param width [out] the discovered width.
|
||
\param min_width [out] the discovered minimum width.
|
||
\return true if we can successfully derive the position and size, false otherwise.
|
||
\sa GetDimension, GetPosition, ParsePosition.
|
||
*/
|
||
static bool GetDimensions(const TiXmlNode *node, const char *leftTag, const char *rightTag, const char *centerLeftTag,
|
||
const char *centerRightTag, const char *widthTag, const float parentSize, float &left,
|
||
float &width, float &min_width);
|
||
};
|
||
#endif
|
xbmc/guilib/GUILabelControl.cpp (working copy) | ||
---|---|---|
ControlType = GUICONTROL_LABEL;
|
||
m_startHighlight = m_endHighlight = 0;
|
||
m_minWidth = 0;
|
||
if ((labelInfo.align & XBFONT_RIGHT) && m_width)
|
||
m_posX -= m_width;
|
||
}
|
||
CGUILabelControl::~CGUILabelControl(void)
|