Jump to content

Recommended Posts

Posted

Yes, I want to have a simple tooltip that can be set with just a line of text, but I also plan to have the ability to retrieve the tooltip window so you can add text or images and make a custom "detail view" that pops up when you hover over items.

  • Like 2
  • Thanks 1

My job is to make tools you love, with the features you want, and performance you can't live without.

  • 3 weeks later...
Posted
class TooltipInfo : public Object
{
public:
    shared_ptr<Widget> target;
    shared_ptr<Widget> tooltipWidget;
};

enum class TooltipState
{
    Pending,
    Show,
    Showing,
    Hiding,
    Hide,
};

class TooltipService
{
    static vector<shared_ptr<TooltipInfo>> _tooltipInfos;
    static bool _initialized;
    static TooltipState _state;
    static shared_ptr<Window> _window;
    static shared_ptr<Interface> _ui;
    static bool Enter(const Event&, shared_ptr<Object>);
    static bool Leave(const Event&, shared_ptr<Object>);
    static bool Tick(const Event&, shared_ptr<Object>);
    static void Init();
    static shared_ptr<Timer> _timer;
    static shared_ptr<TooltipInfo> _activeWidget;
    static int _timerstart;
    static void ShowTooltip(shared_ptr<TooltipInfo> widget);
    static void HideTooltip();
public:
    static void RegisterTooltip(shared_ptr<Widget> target, shared_ptr<Widget> tooltipControl = nullptr);
};

vector<shared_ptr<TooltipInfo>> TooltipService::_tooltipInfos = vector<shared_ptr<TooltipInfo>>();
bool TooltipService::_initialized = false;
shared_ptr<TooltipInfo> TooltipService::_activeWidget = nullptr;
shared_ptr<Timer> TooltipService::_timer = nullptr;
int TooltipService::_timerstart = -1;
TooltipState TooltipService::_state = TooltipState::Pending;
shared_ptr<Window> TooltipService::_window = nullptr;
shared_ptr<Interface> TooltipService::_ui = nullptr;

bool TooltipService::Tick(const Event& ev, shared_ptr<Object> obj)
{
    if (_state == TooltipState::Show && (Millisecs() - _timerstart) > 500)
    {
        ShowTooltip(_activeWidget);
    }
    else if (_state == TooltipState::Hiding && (Millisecs() - _timerstart) > 200)
    {
        _state = TooltipState::Hide;
    }
    else if (_state == TooltipState::Hide)
    {
        HideTooltip();
    }

    return false;
}

void TooltipService::ShowTooltip(shared_ptr<TooltipInfo> widget)
{
    if (_state == TooltipState::Show)
    {
        HideTooltip();
    }

    if (widget->tooltipWidget == nullptr)
    {
        return;
    }

    auto mainwindow = widget->target->gui->GetWindow();
    auto bordersize = mainwindow->GetBorder();
    auto mp = mainwindow->GetMousePosition();
    auto wp = mainwindow->GetPosition();
    _window->SetShape(mp.x + wp.x +15, mp.y + wp.y + 50, widget->tooltipWidget->size.x, widget->tooltipWidget->size.y);
    widget->tooltipWidget->Show();
    _window->Show();
    _state = TooltipState::Showing;
}

void TooltipService::HideTooltip()
{
    _window->Hide();
    _state = TooltipState::Pending;
}

bool TooltipService::Enter(const Event& ev, shared_ptr<Object> obj)
{
    _activeWidget = obj->As<TooltipInfo>();
    _timerstart = Millisecs();
    _state = TooltipState::Show;
    return false;
}

bool TooltipService::Leave(const Event& ev, shared_ptr<Object> obj)
{
    _activeWidget = nullptr;
    _state = TooltipState::Hiding;
    _timerstart = Millisecs();
    return false;
}

void TooltipService::Init()
{
    auto displays = GetDisplays();
    _window = CreateWindow("", 0, 0, 0, 0, displays[0], WindowStyles::WINDOW_HIDDEN | WindowStyles::WINDOW_CHILD);
    SetWindowLongA(_window->GetHandle(), GWL_EXSTYLE, (GetWindowLong(_window->GetHandle(), GWL_EXSTYLE) | WS_EX_TOOLWINDOW) & ~WS_EX_APPWINDOW);
    _ui = CreateInterface(_window);
    _timer = CreateTimer(50);
    ListenEvent(EventID::EVENT_TIMERTICK, _timer, TooltipService::Tick);
    _initialized = true;
}

void TooltipService::RegisterTooltip(shared_ptr<Widget> target, shared_ptr<Widget> tooltipControl)
{
    if (!_initialized)
    {
        Init();
    }

    auto info = make_shared<TooltipInfo>();
    info->target = target;
    info->tooltipWidget = tooltipControl;

    if (tooltipControl != nullptr)
    {
        tooltipControl->Hide();
        tooltipControl->SetParent(_ui->root);
    }

    _tooltipInfos.push_back(info);

    ListenEvent(EventID::EVENT_MOUSEENTER, target, TooltipService::Enter, info);
    ListenEvent(EventID::EVENT_MOUSELEAVE, target, TooltipService::Leave, info);
}

 

Very simple tooltip system (just a small prototype) (win32 only, for other remove the SetWindowLongA part in the init method).

This is how to use it:

    auto tooltipControl = CreatePanel(0, 0, 250, 80, ui->root, PANEL_BORDER);
    tooltipControl->SetColor(Vec4(0.7,0.7,0.7, 1.0), WidgetColor::WIDGETCOLOR_BACKGROUND);

    auto tooltipLabel = CreateLabel("Some tooltip.", 0, 0, tooltipControl->size.x, tooltipControl->size.y, tooltipControl, LabelStyle::LABEL_CENTER | LabelStyle::LABEL_MIDDLE);
    tooltipLabel->SetLayout(1, 1, 1, 1);

    TooltipService::RegisterTooltip(toolbarbutton_open, tooltipControl);
    TooltipService::RegisterTooltip(toolbarbutton_save);
    TooltipService::RegisterTooltip(toolbarbutton_options);
    TooltipService::RegisterTooltip(toolbarbutton_help);

 

  • Haha 1
  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...