table widget

Started by starkhorn, 22 April 2016, 01:04:24

starkhorn

Hi Texus,

I was looking at the table.cpp for the new table widget. It looks awesome.

I want to put it into a child window which I can do easily enough but I was wondering if there is a way to get a scroll bar both vertical and horizontal on that?

texus

I don't think there is a clean solution for it, but it might not be too hard hack some working code together. You will have to edit the table class though (you might even better just copy the Table class in your own code).

1) Create the scrollbars inside the child window and place them next to the table (so not part of the table itself as this might cause problems with passing events to it)
2) Add a setVisibleSize function to Table in which you store the size that you want it to have on your screen
3) Add functions to the Table class (e.g. setHorizontalScrollbar) to pass a pointer to the scrollbar to it.
4) Change Tabel::draw to something like this (first two lines depend on the variables that you should create for step 2 and 3):
Code (cpp) Select
// Set the position (Note: everything above and to the left of getPosition() will be clipped by the other code in this function)
states.transform.translate(getPosition() - sf::Vector2f(m_horizontalScrollbar->getValue(), m_verticalScrollbar->getValue()));

// Set the wanted size
sf::Vector2f visibleSize = m_visibleSize;

// Clipping magic
const sf::View& view = target.getView();
float scaleViewX = target.getSize().x / view.getSize().x;
float scaleViewY = target.getSize().y / view.getSize().y;
sf::Vector2f topLeftPosition = {((getAbsolutePosition().x - view.getCenter().x + (view.getSize().x / 2.f)) * view.getViewport().width) + (view.getSize().x * view.getViewport().left),
                                ((getAbsolutePosition().y - view.getCenter().y + (view.getSize().y / 2.f)) * view.getViewport().height) + (view.getSize().y * view.getViewport().top)};
sf::Vector2f bottomRightPosition = {(getAbsolutePosition().x + visibleSize.x - view.getCenter().x + (view.getSize().x / 2.f)) * view.getViewport().width + (view.getSize().x * view.getViewport().left),
                                    (getAbsolutePosition().y + visibleSize.y - view.getCenter().y + (view.getSize().y / 2.f)) * view.getViewport().height + (view.getSize().y * view.getViewport().top)};
GLint scissor[4];
glGetIntegerv(GL_SCISSOR_BOX, scissor);
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 (scissorRight < scissorLeft)
    scissorRight = scissorLeft;
else if (scissorBottom < scissorTop)
    scissorTop = scissorBottom;
glScissor(scissorLeft, target.getSize().y - scissorBottom, scissorRight - scissorLeft, scissorBottom - scissorTop);

// Draw the background
if (m_backgroundColor != sf::Color::Transparent)
{
    sf::RectangleShape background(getSize());
    background.setFillColor(m_backgroundColor);
    target.draw(background, states);
}

// Draw the widgets
target.draw(*m_header, states);
drawWidgetContainer(&target, states);

for (std::size_t i = 0; i < m_columnsDelimitators.size(); ++i)
    target.draw(m_columnsDelimitators[i], states);

// Reset the old clipping area
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);

starkhorn

wow ok, it might take me a while to go through that all but I will give it a go.

One more thing about tables, can you click on a row and trigger an event?

texus

TableRow apparently inherit from Panel, so you can connect to the "clicked" event.
But you would have to call the connect function on every row.

Alternatively the following could be added to the Table class and then you can get a callback with the index of the clicked row as parameter:
- Add `addSignal<int>("RowClicked");` in Table constructor
- Add `row->connect("Clicked", &Table::rowClicked, this, row);` right before the return in Table::insert
- Add a Table::rowClicked function like this:
Code (cpp) Select
void Table::rowClicked(tgui::Widget::Ptr widgetOnWhichYouClicked)
{
    for (unsigned int i = 0; i < m_widgets.size(); ++i)
    {
        if (m_widgets[i] == widgetOnWhichYouClicked)
        {
            m_callback.index = i;
            sendSignal("RowClicked", i);
        }
    }
}

- You will now be able to connect a callback function to the table for when a row is clicked, e.g. `table->connect("RowClicked", [](int i){ /* row i was clicked */ });`

starkhorn

Hi Texus,

This might be a little beyond me. I'm getting lots of linking errors when trying to copying the table class to my code but I am slowly working through it. However bear with me, I will get back to trying this again.

texus

#5
If you copy the table into your own code you shouldn't keep it in a "tgui" namespace of course. Otherwise the linker finds tgui::Table twice.

It I would have enough time I would write it myself, but I'm very busy until the beginning of June.