Borders are now inside Label

0.8
Bruno Van de Velde 2016-03-01 23:56:44 +01:00
parent 5c62f4fe1a
commit 73d6dc44d9
7 changed files with 351 additions and 295 deletions

View File

@ -128,6 +128,25 @@ namespace tgui
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Add two borders
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline Borders operator+(const Borders& left, const Borders& right)
{
return {left.left + right.left, left.top + right.top, left.right + right.right, left.bottom + right.bottom};
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Subtract two borders
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline Borders operator-(const Borders& left, const Borders& right)
{
return {left.left - right.left, left.top - right.top, left.right - right.right, left.bottom - right.bottom};
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using Padding = Borders;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -706,6 +706,15 @@ namespace tgui
std::shared_ptr<RendererData> getData() const;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Get a clone of the renderer data
///
/// You can pass this to a widget with the setRenderer function to have a separate non-shared copy of this renderer.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<RendererData> clone() const;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected:
std::shared_ptr<RendererData> m_data = std::make_shared<RendererData>();

View File

@ -100,23 +100,10 @@ namespace tgui
/// @return Temporary pointer to the renderer
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LabelRenderer* getRenderer() const;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// @brief Set the position of the widget
///
/// This function completely overwrites the previous position.
/// See the move function to apply an offset based on the previous position instead.
/// The default position of a transformable widget is (0, 0).
///
/// @param position New position
///
/// @see move, getPosition
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
virtual void setPosition(const Layout2d& position) override;
using Transformable::setPosition;
LabelRenderer* getRenderer() const
{
return aurora::downcast<LabelRenderer*>(m_renderer.get());
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -339,12 +326,6 @@ namespace tgui
virtual void update(sf::Time elapsedTime) override;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Rearrange the text, making use of the given size of maximum text width.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void rearrangeText();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Draws the widget on the render target.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -360,6 +341,15 @@ namespace tgui
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Rearrange the text, making use of the given size of maximum text width.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void rearrangeText();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
protected:

View File

@ -769,6 +769,13 @@ namespace tgui
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
std::shared_ptr<RendererData> WidgetRenderer::clone() const
{
return std::make_shared<RendererData>(*m_data);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -23,7 +23,6 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///TODO: FIX BORDERS in calculations
#include <TGUI/Container.hpp>
#include <TGUI/Widgets/Label.hpp>
#include <TGUI/Loading/Theme.hpp>
@ -60,70 +59,6 @@ namespace tgui
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LabelRenderer* Label::getRenderer() const
{
return aurora::downcast<LabelRenderer*>(m_renderer.get());
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Label::setPosition(const Layout2d& position)
{
Widget::setPosition(position);
m_background.setPosition(getPosition());
if (getFont())
{
sf::Vector2f pos{std::round(getPosition().x + getRenderer()->getPadding().left),
getPosition().y + getRenderer()->getPadding().top - getTextVerticalCorrection(getFont(), m_textSize, m_textStyle)};
if (m_verticalAlignment != VerticalAlignment::Top)
{
float totalHeight = getSize().y - getRenderer()->getPadding().top - getRenderer()->getPadding().bottom;
float totalTextHeight = m_lines.size() * getFont()->getLineSpacing(m_textSize);
if (m_verticalAlignment == VerticalAlignment::Center)
pos.y += (totalHeight - totalTextHeight) / 2.f;
else if (m_verticalAlignment == VerticalAlignment::Bottom)
pos.y += totalHeight - totalTextHeight;
}
if (m_horizontalAlignment == HorizontalAlignment::Left)
{
for (auto& line : m_lines)
{
line.setPosition(pos.x, std::floor(pos.y));
pos.y += getFont()->getLineSpacing(m_textSize);
}
}
else // Center or Right alignment
{
float totalWidth = getSize().x - getRenderer()->getPadding().left - getRenderer()->getPadding().right;
for (auto& line : m_lines)
{
line.setPosition(0, 0);
std::size_t lastChar = line.getString().getSize();
while (lastChar > 0 && isWhitespace(line.getString()[lastChar-1]))
lastChar--;
float textWidth = line.findCharacterPos(lastChar).x;
if (m_horizontalAlignment == HorizontalAlignment::Center)
line.setPosition(std::round(pos.x + (totalWidth - textWidth) / 2.f), std::floor(pos.y));
else if (m_horizontalAlignment == HorizontalAlignment::Right)
line.setPosition(std::round(pos.x + totalWidth - textWidth), std::floor(pos.y));
pos.y += getFont()->getLineSpacing(m_textSize);
}
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Label::setSize(const Layout2d& size)
{
Widget::setSize(size);
@ -175,7 +110,7 @@ namespace tgui
void Label::setHorizontalAlignment(HorizontalAlignment alignment)
{
m_horizontalAlignment = alignment;
updatePosition();
rearrangeText();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -190,7 +125,7 @@ namespace tgui
void Label::setVerticalAlignment(VerticalAlignment alignment)
{
m_verticalAlignment = alignment;
updatePosition();
rearrangeText();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -328,6 +263,75 @@ namespace tgui
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Label::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
states.transform.translate(std::round(getPosition().x), std::round(getPosition().y));
// Draw the background
if (m_background.getFillColor() != sf::Color::Transparent)
target.draw(m_background, states);
// Draw the borders
Borders borders = getRenderer()->getBorders();
if (borders != Borders{0, 0, 0, 0})
{
drawBorders(target, states, borders, getPosition(), getSize(), calcColorOpacity(getRenderer()->getBorderColor(), getRenderer()->getOpacity()));
// Don't try to draw the text when there is no space left for it
if ((getSize().x <= borders.left + borders.right) || (getSize().y <= borders.top + borders.bottom))
return;
}
if (m_autoSize)
{
// Draw the text
for (auto& line : m_lines)
target.draw(line, states);
}
else
{
const sf::View& view = target.getView();
// Calculate the scale factor of the view
float scaleViewX = target.getSize().x / view.getSize().x;
float scaleViewY = target.getSize().y / view.getSize().y;
// Get the global position
sf::Vector2f topLeftPosition = {((getAbsolutePosition().x + getRenderer()->getPadding().left - view.getCenter().x + (view.getSize().x / 2.f)) * view.getViewport().width) + (view.getSize().x * view.getViewport().left),
((getAbsolutePosition().y + getRenderer()->getPadding().top - view.getCenter().y + (view.getSize().y / 2.f)) * view.getViewport().height) + (view.getSize().y * view.getViewport().top)};
sf::Vector2f bottomRightPosition = {(getAbsolutePosition().x + getSize().x - getRenderer()->getPadding().right - view.getCenter().x + (view.getSize().x / 2.f)) * view.getViewport().width + (view.getSize().x * view.getViewport().left),
(getAbsolutePosition().y + getSize().y - getRenderer()->getPadding().bottom - view.getCenter().y + (view.getSize().y / 2.f)) * view.getViewport().height + (view.getSize().y * view.getViewport().top)};
// Get the old clipping area
GLint scissor[4];
glGetIntegerv(GL_SCISSOR_BOX, scissor);
// Calculate the clipping area
GLint scissorLeft = std::max(static_cast<GLint>(topLeftPosition.x * scaleViewX), scissor[0]);
GLint scissorTop = std::max(static_cast<GLint>(topLeftPosition.y * scaleViewY), static_cast<GLint>(target.getSize().y) - scissor[1] - scissor[3]);
GLint scissorRight = std::min(static_cast<GLint>(bottomRightPosition.x * scaleViewX), scissor[0] + scissor[2]);
GLint scissorBottom = std::min(static_cast<GLint>(bottomRightPosition.y * scaleViewY), static_cast<GLint>(target.getSize().y) - scissor[1]);
// If the object outside the window then don't draw anything
if (scissorRight < scissorLeft)
scissorRight = scissorLeft;
else if (scissorBottom < scissorTop)
scissorTop = scissorBottom;
// Set the clipping area
glScissor(scissorLeft, target.getSize().y - scissorBottom, scissorRight - scissorLeft, scissorBottom - scissorTop);
// Draw the text
for (auto& line : m_lines)
target.draw(line, states);
// Reset the old clipping area
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Label::rearrangeText()
{
if (!getFont())
@ -337,8 +341,14 @@ namespace tgui
float maxWidth = 0;
if (m_autoSize)
maxWidth = m_maximumTextWidth;
else if (getSize().x > getRenderer()->getPadding().left + getRenderer()->getPadding().right)
maxWidth = getSize().x - getRenderer()->getPadding().left - getRenderer()->getPadding().right;
else
{
Borders borders = getRenderer()->getPadding() + getRenderer()->getBorders();
if (getSize().x > borders.left + borders.right)
maxWidth = getSize().x - getRenderer()->getPadding().left - getRenderer()->getPadding().right;
else // There is no room for text
return;
}
m_lines.clear();
unsigned int index = 0;
@ -437,78 +447,63 @@ namespace tgui
if (m_autoSize)
{
m_size = {std::max(calculatedLabelWidth, maxWidth) + getRenderer()->getPadding().left + getRenderer()->getPadding().right,
(lineCount * getFont()->getLineSpacing(m_textSize)) + getRenderer()->getPadding().top + getRenderer()->getPadding().bottom};
Borders borders = getRenderer()->getPadding() + getRenderer()->getBorders();
m_size = {std::max(calculatedLabelWidth, maxWidth) + borders.left + borders.right,
(lineCount * getFont()->getLineSpacing(m_textSize)) + borders.top + borders.bottom};
m_background.setSize(getSize());
}
updatePosition();
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Label::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
if (m_autoSize)
// Update the line positions
{
// Draw the background
if (m_background.getFillColor() != sf::Color::Transparent)
target.draw(m_background, states);
Borders borders = getRenderer()->getPadding() + getRenderer()->getBorders();
if ((getSize().x <= borders.left + borders.right) || (getSize().y <= borders.top + borders.bottom))
return;
// Draw the text
for (auto& line : m_lines)
target.draw(line, states);
sf::Vector2f pos{borders.left, borders.top - getTextVerticalCorrection(getFont(), m_textSize, m_textStyle)};
if (m_verticalAlignment != VerticalAlignment::Top)
{
float totalHeight = getSize().y - borders.top - borders.bottom;
float totalTextHeight = m_lines.size() * getFont()->getLineSpacing(m_textSize);
if (m_verticalAlignment == VerticalAlignment::Center)
pos.y += (totalHeight - totalTextHeight) / 2.f;
else if (m_verticalAlignment == VerticalAlignment::Bottom)
pos.y += totalHeight - totalTextHeight;
}
if (m_horizontalAlignment == HorizontalAlignment::Left)
{
for (auto& line : m_lines)
{
line.setPosition(pos.x, std::floor(pos.y));
pos.y += getFont()->getLineSpacing(m_textSize);
}
}
else // Center or Right alignment
{
float totalWidth = getSize().x - borders.left - borders.right;
for (auto& line : m_lines)
{
line.setPosition(0, 0);
std::size_t lastChar = line.getString().getSize();
while (lastChar > 0 && isWhitespace(line.getString()[lastChar-1]))
lastChar--;
float textWidth = line.findCharacterPos(lastChar).x;
if (m_horizontalAlignment == HorizontalAlignment::Center)
line.setPosition(std::round(pos.x + (totalWidth - textWidth) / 2.f), std::floor(pos.y));
else if (m_horizontalAlignment == HorizontalAlignment::Right)
line.setPosition(std::round(pos.x + totalWidth - textWidth), std::floor(pos.y));
pos.y += getFont()->getLineSpacing(m_textSize);
}
}
}
else
{
const sf::View& view = target.getView();
// Calculate the scale factor of the view
float scaleViewX = target.getSize().x / view.getSize().x;
float scaleViewY = target.getSize().y / view.getSize().y;
// Get the global position
sf::Vector2f topLeftPosition = {((getAbsolutePosition().x + getRenderer()->getPadding().left - view.getCenter().x + (view.getSize().x / 2.f)) * view.getViewport().width) + (view.getSize().x * view.getViewport().left),
((getAbsolutePosition().y + getRenderer()->getPadding().top - view.getCenter().y + (view.getSize().y / 2.f)) * view.getViewport().height) + (view.getSize().y * view.getViewport().top)};
sf::Vector2f bottomRightPosition = {(getAbsolutePosition().x + getSize().x - getRenderer()->getPadding().right - view.getCenter().x + (view.getSize().x / 2.f)) * view.getViewport().width + (view.getSize().x * view.getViewport().left),
(getAbsolutePosition().y + getSize().y - getRenderer()->getPadding().bottom - view.getCenter().y + (view.getSize().y / 2.f)) * view.getViewport().height + (view.getSize().y * view.getViewport().top)};
// Get the old clipping area
GLint scissor[4];
glGetIntegerv(GL_SCISSOR_BOX, scissor);
// Calculate the clipping area
GLint scissorLeft = std::max(static_cast<GLint>(topLeftPosition.x * scaleViewX), scissor[0]);
GLint scissorTop = std::max(static_cast<GLint>(topLeftPosition.y * scaleViewY), static_cast<GLint>(target.getSize().y) - scissor[1] - scissor[3]);
GLint scissorRight = std::min(static_cast<GLint>(bottomRightPosition.x * scaleViewX), scissor[0] + scissor[2]);
GLint scissorBottom = std::min(static_cast<GLint>(bottomRightPosition.y * scaleViewY), static_cast<GLint>(target.getSize().y) - scissor[1]);
// If the object outside the window then don't draw anything
if (scissorRight < scissorLeft)
scissorRight = scissorLeft;
else if (scissorBottom < scissorTop)
scissorTop = scissorBottom;
// Draw the background
if (m_background.getFillColor() != sf::Color::Transparent)
target.draw(m_background, states);
// Set the clipping area
glScissor(scissorLeft, target.getSize().y - scissorBottom, scissorRight - scissorLeft, scissorBottom - scissorTop);
// Draw the text
for (auto& line : m_lines)
target.draw(line, states);
// Reset the old clipping area
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
// Draw the borders around the button
Borders borders = getRenderer()->getBorders();
if (borders != Borders{0, 0, 0, 0})
drawBorders(target, states, borders, getPosition(), getSize(), calcColorOpacity(getRenderer()->getBorderColor(), getRenderer()->getOpacity()));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -51,4 +51,40 @@ TEST_CASE("[Borders]") {
REQUIRE(borders.right == 3);
REQUIRE(borders.bottom == 4);
}
SECTION("Operators") {
auto borders0 = tgui::Borders();
auto borders1 = tgui::Borders(1, 2, 3, 4);
auto borders2 = tgui::Borders(1, 2, 3, 5);
auto borders3 = tgui::Borders(6, 7, 8, 9);
auto borders4 = tgui::Borders(1, 2, 3, 4);
SECTION("==") {
REQUIRE(!(borders1 == borders2));
REQUIRE(!(borders1 == borders3));
REQUIRE(!(borders2 == borders3));
REQUIRE(borders1 == borders1);
REQUIRE(borders1 == borders4);
REQUIRE(borders4 == borders4);
}
SECTION("!=") {
REQUIRE(borders1 != borders2);
REQUIRE(borders1 != borders3);
REQUIRE(borders2 != borders3);
REQUIRE(!(borders1 != borders1));
REQUIRE(!(borders1 != borders4));
REQUIRE(!(borders4 != borders4));
}
SECTION("+") {
REQUIRE((borders1 + borders3) == tgui::Borders(7, 9, 11, 13));
REQUIRE((borders2 + borders0) == borders2);
}
SECTION("-") {
REQUIRE((borders3 - borders1) == tgui::Borders(5, 5, 5, 5));
REQUIRE((borders2 - borders0) == borders2);
}
}
}

View File

@ -23,7 +23,7 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "Tests.hpp"
#include <TGUI/Widgets/Button.hpp>
#include <TGUI/Widgets/ClickableWidget.hpp>
#include <TGUI/Widgets/Panel.hpp>
#include <TGUI/Gui.hpp>
@ -177,23 +177,23 @@ TEST_CASE("[Layouts]") {
}
SECTION("bind functions") {
auto button1 = std::make_shared<tgui::Button>();
button1->setSize(300, 50);
button1->setPosition(40, 60);
auto widget1 = std::make_shared<tgui::ClickableWidget>();
widget1->setSize(300, 50);
widget1->setPosition(40, 60);
auto button2 = std::make_shared<tgui::Button>();
button2->setPosition(bindLeft(button1), bindTop(button1));
button2->setSize(bindWidth(button1), bindHeight(button1));
REQUIRE(button2->getSize() == sf::Vector2f(300, 50));
REQUIRE(button2->getPosition() == sf::Vector2f(40, 60));
auto widget2 = std::make_shared<tgui::ClickableWidget>();
widget2->setPosition(bindLeft(widget1), bindTop(widget1));
widget2->setSize(bindWidth(widget1), bindHeight(widget1));
REQUIRE(widget2->getSize() == sf::Vector2f(300, 50));
REQUIRE(widget2->getPosition() == sf::Vector2f(40, 60));
button2->setPosition(bindRight(button1), bindBottom(button1));
REQUIRE(button2->getPosition() == sf::Vector2f(340, 110));
widget2->setPosition(bindRight(widget1), bindBottom(widget1));
REQUIRE(widget2->getPosition() == sf::Vector2f(340, 110));
button2->setPosition(bindPosition(button1));
button2->setSize(bindSize(button1));
REQUIRE(button2->getSize() == sf::Vector2f(300, 50));
REQUIRE(button2->getPosition() == sf::Vector2f(40, 60));
widget2->setPosition(bindPosition(widget1));
widget2->setSize(bindSize(widget1));
REQUIRE(widget2->getSize() == sf::Vector2f(300, 50));
REQUIRE(widget2->getPosition() == sf::Vector2f(40, 60));
REQUIRE(bindMin(10, 20).getValue() == 10);
REQUIRE(bindMin(-50, 5).getValue() == -50);
@ -203,48 +203,48 @@ TEST_CASE("[Layouts]") {
REQUIRE(bindRange(10, 20, 25).getValue() == 20);
REQUIRE(bindRange(10, 20, 5).getValue() == 10);
button1->setSize(400, 40);
button1->setPosition(60, 75);
REQUIRE(button2->getSize() == sf::Vector2f(400, 40));
REQUIRE(button2->getPosition() == sf::Vector2f(60, 75));
widget1->setSize(400, 40);
widget1->setPosition(60, 75);
REQUIRE(widget2->getSize() == sf::Vector2f(400, 40));
REQUIRE(widget2->getPosition() == sf::Vector2f(60, 75));
button1->setSize(bindSize(button2)); // Binding each other only works when value is cached
REQUIRE(button1->getSize() == sf::Vector2f(400, 40));
REQUIRE(button2->getSize() == sf::Vector2f(400, 40));
widget1->setSize(bindSize(widget2)); // Binding each other only works when value is cached
REQUIRE(widget1->getSize() == sf::Vector2f(400, 40));
REQUIRE(widget2->getSize() == sf::Vector2f(400, 40));
auto button3 = std::make_shared<tgui::Button>();
auto widget3 = std::make_shared<tgui::ClickableWidget>();
auto panel = std::make_shared<tgui::Panel>();
panel->setSize(200, 180);
panel->setPosition(10, 25);
button1->setSize(300, 50);
button1->setPosition(40, 60);
button2->setSize(400, 40);
button2->setPosition(60, 75);
panel->add(button1);
panel->add(button2);
panel->add(button3);
widget1->setSize(300, 50);
widget1->setPosition(40, 60);
widget2->setSize(400, 40);
widget2->setPosition(60, 75);
panel->add(widget1);
panel->add(widget2);
panel->add(widget3);
button3->setSize(2.5 * bindPosition(button1) + bindSize(button2) / 4 + sf::Vector2f(100, 50));
REQUIRE(button3->getSize() == sf::Vector2f(300, 210));
widget3->setSize(2.5 * bindPosition(widget1) + bindSize(widget2) / 4 + sf::Vector2f(100, 50));
REQUIRE(widget3->getSize() == sf::Vector2f(300, 210));
button3->setPosition(2 * bindRight(button1) + bindLeft(button2) / 4 + bindWidth(button1), 50 + bindBottom(button2) % 75 * bindTop(button2));
REQUIRE(button3->getPosition() == sf::Vector2f(995, 3050));
REQUIRE(button3->getAbsolutePosition() == sf::Vector2f(1005, 3075));
widget3->setPosition(2 * bindRight(widget1) + bindLeft(widget2) / 4 + bindWidth(widget1), 50 + bindBottom(widget2) % 75 * bindTop(widget2));
REQUIRE(widget3->getPosition() == sf::Vector2f(995, 3050));
REQUIRE(widget3->getAbsolutePosition() == sf::Vector2f(1005, 3075));
button3->setSize(bindIf(bindWidth(button1) > bindHeight(button2), 2 * bindWidth(button1), bindWidth(button2) / 4) * 3, 0);
REQUIRE(button3->getSize().x == 1800);
button1->setSize(30, 10);
REQUIRE(button3->getSize().x == 300);
widget3->setSize(bindIf(bindWidth(widget1) > bindHeight(widget2), 2 * bindWidth(widget1), bindWidth(widget2) / 4) * 3, 0);
REQUIRE(widget3->getSize().x == 1800);
widget1->setSize(30, 10);
REQUIRE(widget3->getSize().x == 300);
button3->setPosition(bindIf(bindLeft(button1) != bindTop(button2), bindPosition(button1), 1.5 * bindPosition(button2)));
REQUIRE(button3->getPosition() == sf::Vector2f(40, 60));
button1->setPosition(75, 20);
REQUIRE(button3->getPosition() == sf::Vector2f(90, 112.5f));
widget3->setPosition(bindIf(bindLeft(widget1) != bindTop(widget2), bindPosition(widget1), 1.5 * bindPosition(widget2)));
REQUIRE(widget3->getPosition() == sf::Vector2f(40, 60));
widget1->setPosition(75, 20);
REQUIRE(widget3->getPosition() == sf::Vector2f(90, 112.5f));
button3->setPosition(bindIf(bindPosition(button1) == bindPosition(button2), bindPosition(button1) * 1.5, bindPosition(button2)));
REQUIRE(button3->getPosition() == sf::Vector2f(60, 75));
button1->setPosition(60, 75);
REQUIRE(button3->getPosition() == sf::Vector2f(90, 112.5f));
widget3->setPosition(bindIf(bindPosition(widget1) == bindPosition(widget2), bindPosition(widget1) * 1.5, bindPosition(widget2)));
REQUIRE(widget3->getPosition() == sf::Vector2f(60, 75));
widget1->setPosition(60, 75);
REQUIRE(widget3->getPosition() == sf::Vector2f(90, 112.5f));
}
}
@ -375,117 +375,117 @@ TEST_CASE("[Layouts]") {
panel->setSize(200, 180);
panel->setPosition(10, 25);
auto button1 = std::make_shared<tgui::Button>();
button1->setSize(300, 50);
button1->setPosition(40, 60);
panel->add(button1, "b1");
auto widget1 = std::make_shared<tgui::ClickableWidget>();
widget1->setSize(300, 50);
widget1->setPosition(40, 60);
panel->add(widget1, "b1");
auto button2 = std::make_shared<tgui::Button>();
button2->setPosition(bindStr2d("b1.position"));
button2->setSize(bindStr2d(std::string{"b1.size"}));
REQUIRE(button2->getSize() == sf::Vector2f(0, 0));
REQUIRE(button2->getPosition() == sf::Vector2f(0, 0));
auto widget2 = std::make_shared<tgui::ClickableWidget>();
widget2->setPosition(bindStr2d("b1.position"));
widget2->setSize(bindStr2d(std::string{"b1.size"}));
REQUIRE(widget2->getSize() == sf::Vector2f(0, 0));
REQUIRE(widget2->getPosition() == sf::Vector2f(0, 0));
panel->add(button2, "b2");
REQUIRE(button2->getSize() == sf::Vector2f(300, 50));
REQUIRE(button2->getPosition() == sf::Vector2f(40, 60));
panel->add(widget2, "b2");
REQUIRE(widget2->getSize() == sf::Vector2f(300, 50));
REQUIRE(widget2->getPosition() == sf::Vector2f(40, 60));
button2->setPosition({"b1.p"});
REQUIRE(button2->getPosition() == sf::Vector2f(0, 0));
widget2->setPosition({"b1.p"});
REQUIRE(widget2->getPosition() == sf::Vector2f(0, 0));
button2->setPosition({"b1.pos"});
REQUIRE(button2->getPosition() == sf::Vector2f(40, 60));
widget2->setPosition({"b1.pos"});
REQUIRE(widget2->getPosition() == sf::Vector2f(40, 60));
button2->setPosition(bindStr("b1.left"), bindStr(std::string{"b1.top"}));
REQUIRE(button2->getPosition() == sf::Vector2f(40, 60));
widget2->setPosition(bindStr("b1.left"), bindStr(std::string{"b1.top"}));
REQUIRE(widget2->getPosition() == sf::Vector2f(40, 60));
button2->setPosition({"b1.x"}, {"b1.y"});
REQUIRE(button2->getPosition() == sf::Vector2f(40, 60));
widget2->setPosition({"b1.x"}, {"b1.y"});
REQUIRE(widget2->getPosition() == sf::Vector2f(40, 60));
button2->setSize({"{b1.width, b1.height}"});
REQUIRE(button2->getSize() == sf::Vector2f(300, 50));
widget2->setSize({"{b1.width, b1.height}"});
REQUIRE(widget2->getSize() == sf::Vector2f(300, 50));
button2->setSize({"{b1.wi, b1.he}"});
REQUIRE(button2->getSize() == sf::Vector2f(0, 0));
widget2->setSize({"{b1.wi, b1.he}"});
REQUIRE(widget2->getSize() == sf::Vector2f(0, 0));
button2->setSize({"{b1.w, b1.h}"});
REQUIRE(button2->getSize() == sf::Vector2f(300, 50));
widget2->setSize({"{b1.w, b1.h}"});
REQUIRE(widget2->getSize() == sf::Vector2f(300, 50));
button2->setSize({"{b1.right, b1.bottom}"});
REQUIRE(button2->getSize() == sf::Vector2f(340, 110));
widget2->setSize({"{b1.right, b1.bottom}"});
REQUIRE(widget2->getSize() == sf::Vector2f(340, 110));
button2->setSize({"{b1.r, b1.b}"});
REQUIRE(button2->getSize() == sf::Vector2f(0, 0));
widget2->setSize({"{b1.r, b1.b}"});
REQUIRE(widget2->getSize() == sf::Vector2f(0, 0));
button2->setSize({{"b1.right"}, {"b1.bottom"}});
REQUIRE(button2->getSize() == sf::Vector2f(340, 110));
widget2->setSize({{"b1.right"}, {"b1.bottom"}});
REQUIRE(widget2->getSize() == sf::Vector2f(340, 110));
button2->setSize({"{@, #}"});
REQUIRE(button2->getSize() == sf::Vector2f(0, 0));
widget2->setSize({"{@, #}"});
REQUIRE(widget2->getSize() == sf::Vector2f(0, 0));
button2->setPosition({"parent.x"}, {"&.y"});
REQUIRE(button2->getPosition() == sf::Vector2f(10, 25));
widget2->setPosition({"parent.x"}, {"&.y"});
REQUIRE(widget2->getPosition() == sf::Vector2f(10, 25));
button2->setPosition({"parent.b1.parent.b1.x"}, {"&.b1.&.b1.y"});
REQUIRE(button2->getPosition() == sf::Vector2f(40, 60));
widget2->setPosition({"parent.b1.parent.b1.x"}, {"&.b1.&.b1.y"});
REQUIRE(widget2->getPosition() == sf::Vector2f(40, 60));
button2->setPosition({"b1.position"});
button2->setSize({"b1.size"});
button1->setSize(400, 40);
button1->setPosition(60, 75);
REQUIRE(button2->getSize() == sf::Vector2f(400, 40));
REQUIRE(button2->getPosition() == sf::Vector2f(60, 75));
widget2->setPosition({"b1.position"});
widget2->setSize({"b1.size"});
widget1->setSize(400, 40);
widget1->setPosition(60, 75);
REQUIRE(widget2->getSize() == sf::Vector2f(400, 40));
REQUIRE(widget2->getPosition() == sf::Vector2f(60, 75));
auto button3 = std::make_shared<tgui::Button>();
button1->setSize(300, 50);
button1->setPosition(40, 60);
button2->setSize(400, 40);
button2->setPosition(60, 75);
panel->add(button3);
auto widget3 = std::make_shared<tgui::ClickableWidget>();
widget1->setSize(300, 50);
widget1->setPosition(40, 60);
widget2->setSize(400, 40);
widget2->setPosition(60, 75);
panel->add(widget3);
button3->setSize({"2.5 * b1.pos + b2.size / 4 + {100, 50}"});
REQUIRE(button3->getSize() == sf::Vector2f(300, 210));
widget3->setSize({"2.5 * b1.pos + b2.size / 4 + {100, 50}"});
REQUIRE(widget3->getSize() == sf::Vector2f(300, 210));
button3->setPosition({"2 * b1.right + b2.x / 4 + b1.w"}, {"50 + b2.bottom % 75 * b2.y"});
REQUIRE(button3->getPosition() == sf::Vector2f(995, 3050));
REQUIRE(button3->getAbsolutePosition() == sf::Vector2f(1005, 3075));
widget3->setPosition({"2 * b1.right + b2.x / 4 + b1.w"}, {"50 + b2.bottom % 75 * b2.y"});
REQUIRE(widget3->getPosition() == sf::Vector2f(995, 3050));
REQUIRE(widget3->getAbsolutePosition() == sf::Vector2f(1005, 3075));
button3->setSize({"(if b1.w > b2.h then 2 * b1.w else b2.w / 4) * 3"});
REQUIRE(button3->getSize().x == 1800);
button1->setSize(30, 10);
REQUIRE(button3->getSize().x == 300);
widget3->setSize({"(if b1.w > b2.h then 2 * b1.w else b2.w / 4) * 3"});
REQUIRE(widget3->getSize().x == 1800);
widget1->setSize(30, 10);
REQUIRE(widget3->getSize().x == 300);
button3->setSize({"(if b1.w <= b2.h then 2 * b1.w else b2.w / 4) * 3"});
REQUIRE(button3->getSize().x == 180);
button2->setSize(200, 50);
button1->setSize(300, 50);
REQUIRE(button3->getSize().x == 150);
widget3->setSize({"(if b1.w <= b2.h then 2 * b1.w else b2.w / 4) * 3"});
REQUIRE(widget3->getSize().x == 180);
widget2->setSize(200, 50);
widget1->setSize(300, 50);
REQUIRE(widget3->getSize().x == 150);
button3->setPosition(bindIf(bindLeft(button1) != bindTop(button2), bindPosition(button1), 1.5 * bindPosition(button2)));
button3->setPosition({"b1.x != b2.y ? b1.pos : 1.5 * b2.position"});
REQUIRE(button3->getPosition() == sf::Vector2f(40, 60));
button1->setPosition(75, 20);
REQUIRE(button3->getPosition() == sf::Vector2f(90, 112.5f));
widget3->setPosition(bindIf(bindLeft(widget1) != bindTop(widget2), bindPosition(widget1), 1.5 * bindPosition(widget2)));
widget3->setPosition({"b1.x != b2.y ? b1.pos : 1.5 * b2.position"});
REQUIRE(widget3->getPosition() == sf::Vector2f(40, 60));
widget1->setPosition(75, 20);
REQUIRE(widget3->getPosition() == sf::Vector2f(90, 112.5f));
button3->setPosition({"if b1.pos == b2.pos then b1.pos * 1.5 else b2.pos"});
REQUIRE(button3->getPosition() == sf::Vector2f(60, 75));
button1->setPosition(60, 75);
REQUIRE(button3->getPosition() == sf::Vector2f(90, 112.5f));
widget3->setPosition({"if b1.pos == b2.pos then b1.pos * 1.5 else b2.pos"});
REQUIRE(widget3->getPosition() == sf::Vector2f(60, 75));
widget1->setPosition(60, 75);
REQUIRE(widget3->getPosition() == sf::Vector2f(90, 112.5f));
auto button4 = std::make_shared<tgui::Button>();
button4->setSize(200, 50);
auto widget4 = std::make_shared<tgui::ClickableWidget>();
widget4->setSize(200, 50);
panel->add(button4, "xyzifxyz");
button3->setSize({"xyzifxyz.size"});
REQUIRE(button3->getSize() == sf::Vector2f(200, 50));
panel->add(widget4, "xyzifxyz");
widget3->setSize({"xyzifxyz.size"});
REQUIRE(widget3->getSize() == sf::Vector2f(200, 50));
panel->add(button4, "ifthenelse");
button3->setSize({"ifthenelse.size"});
REQUIRE(button3->getSize() == sf::Vector2f(200, 50));
panel->add(widget4, "ifthenelse");
widget3->setSize({"ifthenelse.size"});
REQUIRE(widget3->getSize() == sf::Vector2f(200, 50));
panel->add(button4, "then");
button3->setSize({"then.size"});
REQUIRE(button3->getSize() == sf::Vector2f(200, 50));
panel->add(widget4, "then");
widget3->setSize({"then.size"});
REQUIRE(widget3->getSize() == sf::Vector2f(200, 50));
SECTION("Gui") {
sf::RenderTexture texture;
@ -527,17 +527,17 @@ TEST_CASE("[Layouts]") {
SECTION("Bug Fixes") {
SECTION("Setting negative size and reverting back to positive (https://github.com/texus/TGUI/issues/54)") {
tgui::Panel::Ptr panel = std::make_shared<tgui::Panel>();
tgui::Button::Ptr button = std::make_shared<tgui::Button>();
panel->add(button);
tgui::ClickableWidget::Ptr widget = std::make_shared<tgui::ClickableWidget>();
panel->add(widget);
// Button width becomes -10
// widget width becomes -10
panel->setSize(10, 10);
button->setSize({"{&.w - 20, &.h}"});
REQUIRE(button->getSize() == sf::Vector2f(-10, 10));
widget->setSize({"{&.w - 20, &.h}"});
REQUIRE(widget->getSize() == sf::Vector2f(-10, 10));
// Button width will become positive again
// widget width will become positive again
panel->setSize(200, 100);
REQUIRE(button->getSize() == sf::Vector2f(180, 100));
REQUIRE(widget->getSize() == sf::Vector2f(180, 100));
}
}
}