ListBox sounds
« on: 10 June 2016, 06:21:13 »
Hi Texus,

So I have a listbox setup fine but I wanted to play a sound when my mouse hovered over an item and also when an item was selected.
Now I think I can trap the item selected easily enough using the ItemSelected signal but what signal can be used when hovering over an item in a listbox? Is it the widgets MouseEntered ? Does that get triggered each time the mouse enters an item?


*

texus

  • *****
  • 1143
    • View Profile
    • Texus's Blog
Re: ListBox sounds
« Reply #1 on: 10 June 2016, 11:39:31 »
There is currently no way of getting a callback when you are just hovering over a widget. MouseEntered is only when the mouse enters the ListBox and not per item.
I could add it, but don't you think that the sounds will come too fast after each other to play? I never added a signal for it because I didn't see a use case for it, but this use case sounds weird because I can't imagine that it would work well. Can you give an example of where they do this?

*

texus

  • *****
  • 1143
    • View Profile
    • Texus's Blog
Re: ListBox sounds
« Reply #2 on: 10 June 2016, 23:45:59 »
Even after you convince me that such a callback is a good idea, I may not be able to add it soon, so here is a workaround: (just copy findHoverItem in your code and use it like in the main function below)

int findHoverItem(tgui::Gui& gui, tgui::ListBox::Ptr listBox, int x, int y)
{
    x = gui.getWindow()->mapPixelToCoords({x, y}, gui.getView()).x;
    y = gui.getWindow()->mapPixelToCoords({x, y}, gui.getView()).y;

    tgui::Padding padding = listBox->getRenderer()->getPadding();
    if ((x >= listBox->getAbsolutePosition().x + padding.left) && (x < listBox->getAbsolutePosition().x + listBox->getSize().x - padding.right)
     && (y >= listBox->getAbsolutePosition().y + padding.top) && (y < listBox->getAbsolutePosition().y + listBox->getSize().y - padding.bottom))
    {
        x = x - (listBox->getAbsolutePosition().x - listBox->getPosition().x);
        y = y - (listBox->getAbsolutePosition().y - listBox->getPosition().y) - padding.top;

        if (listBox->getScrollbar()->mouseOnWidget(x, y))
            return -1;
        else
        {
            if (listBox->getScrollbar()->getLowValue() < listBox->getScrollbar()->getMaximum())
            {
                // Check if the mouse is on the first (perhaps partially) visible item
                if (y - listBox->getPosition().y <= (listBox->getItemHeight() - (listBox->getScrollbar()->getValue() % listBox->getItemHeight())))
                {
                    return static_cast<int>(listBox->getScrollbar()->getValue() / listBox->getItemHeight());
                }
                else // The mouse is not on the first visible item
                {
                    // Calculate on what item the mouse is standing
                    if ((listBox->getScrollbar()->getValue() % listBox->getItemHeight()) == 0)
                        return static_cast<int>((y - listBox->getPosition().y) / listBox->getItemHeight() + (listBox->getScrollbar()->getValue() / listBox->getItemHeight()));
                    else
                        return static_cast<int>((((y - listBox->getPosition().y) - (listBox->getItemHeight() - (listBox->getScrollbar()->getValue() % listBox->getItemHeight())))
                                                 / listBox->getItemHeight()) + (listBox->getScrollbar()->getValue() / listBox->getItemHeight()) + 1);
                }
            }
            else // The scrollbar is not displayed
            {
                // Calculate on which item the mouse is standing
                int hoveringItem = static_cast<int>((y - listBox->getPosition().y) / listBox->getItemHeight());

                // Check if the mouse is behind the last item
                if (hoveringItem > static_cast<int>(listBox->getItems().size())-1)
                    return -1;
                else
                    return hoveringItem;
            }
        }
    }
    else // Mouse not on list box
        return -1;
}

int main()
{
    int hoveringItem = -1;

    sf::RenderWindow window{{800, 600}, "TGUI"};
    tgui::Gui gui{window};

    tgui::ListBox::Ptr listBox = std::make_shared<tgui::ListBox>();
    listBox->addItem("Test 1");
    listBox->addItem("Test 2");
    listBox->addItem("Test 3");
    listBox->addItem("Test 4");
    gui.add(listBox);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            else if (event.type == sf::Event::MouseMoved)
            {
                int newHoveringItem = findHoverItem(gui, listBox, event.mouseMove.x, event.mouseMove.y);

                if (hoveringItem != newHoveringItem)
                {
                    std::cout << "Play sound" << std::endl;
                }

                hoveringItem = newHoveringItem;
            }

            gui.handleEvent(event);
        }

        window.clear(sf::Color::White);
        gui.draw();
        window.display();
    }
}