Project

General

Profile

Feature #368 ยป control_positioning.patch

antonic901, 13/02/2023 08:28 PM

View differences:

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)
    (1-1/1)