ToolTip on click

Started by Nafffen, 14 February 2023, 15:21:54

Nafffen

Hello,
I want to make a custom widget able to show a tool tip only when the mouse click is pressed under it.

What I tried:
template <typename T>
concept DerivedFromWidget = std::derived_from<T, tgui::Widget>;

template<DerivedFromWidget T>
class BubblableWidget: public T{
public:
    BubblableWidget(): T(){}

    void setBubble(tgui::Widget::Ptr widget){
        m_bubble = widget;
    }

    void leftMousePressed(tgui::Vector2f pos) override{
        T::leftMousePressed(pos);
        T::setToolTip(m_bubble);
        std::cout << "BubblableWidget::leftMousePressed" << std::endl;
    }

    void leftMouseButtonNoLongerDown() override{
        T::leftMouseButtonNoLongerDown();
        T::setToolTip(nullptr);
        std::cout << "BubblableWidget::leftMouseButtonNoLongerDown " << std::endl;
        std::cout << m_bubble << std::endl;
    }

private:
    tgui::Widget::Ptr m_bubble;
};

In the above code, I removed Ptr,create,clone to make it easier to read

Then user side:
    auto test = BubblableWidget<tgui::Label>::create();
    test->setAutoSize(true);
    test->setText("Test");

    auto testBubble = tgui::Label::create("Test2");
    testBubble->setAutoSize(true);
    test->setBubble(testBubble);

When I click on the "Test" label, I can see "BubblableWidget::leftMousePressed" as expected, same for "BubblableWidget::leftMouseButtonNoLongerDown". However, the tool tip does not appear.

I was wondering if setToolTip can't be called in those override functions? Why the tool tip isnt drawn ?
How can I manage my wanted behavior ?

Thank you

texus

setToolTip is used to tell the Gui that the widget has a tool tip, so that it can be shown when the mouse stands still on the widget for a while. Calling setToolTip won't actually display anything.

You could call tgui::ToolTip::setInitialDelay(0) at the beginning of your code to make tool tips appear without a timeout, but I'm not certain if it will work because tool tip might be suppressed while the mouse button is down.

I suggest you show the bubble manually, instead of the existing tool tip system, because what you want is different from how tool tips typically work. Something like the following:
- When you press the mouse button, set the position of the bubble and call "getParent()->add(bubble)"
- When you receive a mouse release event, call "getParent()->remove(bubble)"
- In your constructor, set m_draggableWidget to true so that your widget keeps receiving mouse move events while the mouse is pressed, even when the bubble is below the mouse.
- Optionally move the bubble on mouse move events while m_mouseDown is true

Nafffen

Thank you for theses advices, this is what I did for people who wants:
#pragma once

template <typename T>
concept DerivedFromWidget = std::derived_from<T, tgui::Widget>;

template<DerivedFromWidget T>
class BubblableWidget: public T{
public:
    // Add a Ptr typedef so that "MyCustomWidget::Ptr" has the correct type
    typedef std::shared_ptr<BubblableWidget<T>> Ptr;
    typedef std::shared_ptr<const BubblableWidget<T>> ConstPtr;

    BubblableWidget(): T(){
        T::m_draggableWidget = true;
    }

    // Every widget needs a static create function which creates the widget and returns a smart pointer to it.
    // This function can have any parameters you want.
    static BubblableWidget::Ptr create()
    {
        return std::make_shared<BubblableWidget>();
    }

    // Every widget has a static method to copy it
    static BubblableWidget::Ptr copy(BubblableWidget::ConstPtr widget)
    {
        if (widget)
            return std::static_pointer_cast<BubblableWidget>(widget->clone());
        else
            return nullptr;
    }


    void setBubble(tgui::Container::Ptr parent, tgui::Widget::Ptr widget){
        m_parent = parent;
        m_bubble = widget;
    }

    void bindPosBubbleWith(tgui::Widget::Ptr widgetBindedPos){
        m_widgetBindedPos = widgetBindedPos;
    }

    void leftMousePressed(tgui::Vector2f pos) override{
        T::leftMousePressed(pos);
        // std::cout << "BubblableWidget::leftMousePressed" << std::endl;
        m_bubble->setPosition(m_widgetBindedPos->getAbsolutePosition());
        // std::cout << "pos: " << m_widgetBindedPos->getAbsolutePosition() << std::endl;
        m_parent->add(m_bubble);
    }

    void leftMouseButtonNoLongerDown() override{
        T::leftMouseButtonNoLongerDown();
        T::setToolTip(nullptr);
        // std::cout << "BubblableWidget::leftMouseButtonNoLongerDown " << std::endl;
        m_parent->remove(m_bubble);
    }

    // void mouseMoved(tgui::Vector2f pos) override{
    //     T::mouseMoved(pos);
    //     if(T::m_mouseDown){
    //         std::cout << "BubblableWidget::mouseMoved under" << std::endl;
    //     }
    // }

protected:

    // Every widget needs a method to copy it
    tgui::Widget::Ptr clone() const override
    {
        return std::make_shared<BubblableWidget>(*this);
    }

private:
    tgui::Container::Ptr m_parent;
    tgui::Widget::Ptr m_bubble;
    tgui::Widget::Ptr m_widgetBindedPos;
};

How to use:
auto picture = BubblableWidget<tgui::Picture>::create();
//another widget for the bubble (ItemContainerWidget is mine)
auto itemContainer = ItemContainerWidget::create(ItemContainerWidget::AlignmentSide::ADJUST,
                                                      3,
                                                      ItemContainerWidget::SelectionMode::NONE,
                                                      {ItemStack(ItemTypeEnum::COAL, 2),
                                                       ItemStack(ItemTypeEnum::IRON, 5)});
itemContainer->setOrigin(1.f,0.5f);
itemContainer->setSize("20%","20%");
picture->bindPosBubbleWith(picture);
picture->setBubble(bubbleGroup, itemContainer);

When clicking on the picture, the bubble will appear on the pos of the widget passed to bindPosBubbleWith(), with origin computation.
We need to pass the parent in which we want the bubble to be in setBubble to deal with different pos reference (in my case, I wanted to draw the bubbles in a screen sized group, not the one in which the picture is).
The bubble will not move like a tool tip with mouse pos but it is ok for me.