-
-
Notifications
You must be signed in to change notification settings - Fork 11.2k
Description
Version/Branch of Dear ImGui:
Version 1.90.7, Branch: master
Back-ends:
Any (Unity/C# integration most recent case)
Compiler, OS:
Any (Windows, Unity C# 2022.x in most recent case)
Full config/build information:
No response
Details:
Feature Request
A small control that I've written for past projects and which we implemented at Wargaming, Blizzard (SGE), and at my current employer is a "HyperLink" widget, so it seems to me to be a frequently recurring pattern.
A hyperlink is some Text but which is rendered in a different color (e.g. blue) and has an underline, changes color slightly when hovered, and responds to clicks like a button, etc.
For users, this would be something like:
if (ImGui::HyperLink("Some label##id"))
DoThing();
Writing the most basic version of this is almost trivial, of course, but it gets a bit trickier once things like keyboard focus and activation are considered, and really tricky to handle keyboard focus styling well. Every single implementation of such a control that I've seen (including mine!) got some or all of those wrong initially. I'm still not sure that I've seen one that handles word-wrap and focus highlight correctly, now that I think about it.
Having something like this in dear imgui itself instead of being reimplemented (often poorly) would be a small win.
Screenshots/Video:
Example of what a HyperLink control might look like:
And focused (styling could be better, just a quick demo here):
Minimal, Complete and Verifiable Example code:
// Crappy HyperLink implemented in a few minutes
//
// Does not handle: wordwrap
// Focus handling is not quite right (focus item stays after clicking with the mouse; ideally would be only outlined if keyboard was used to select/activate most recently)
// More input options for buttons, etc.
// Lacks custom style options. uses hard-coded colors
// Lacks a flag or style/color for "visited" links
// Lacks disabled link style/color
// Option to only show underline on hover could be a style? Or part of flags
bool ImGui::HyperLink(const char* label, bool underlineWhenHoveredOnly = false)
{
const ImU32 linkColor = ImGui::ColorConvertFloat4ToU32({0.2, 0.3, 0.8, 1});
const ImU32 linkHoverColor = ImGui::ColorConvertFloat4ToU32({0.4, 0.6, 0.8, 1});
const ImU32 linkFocusColor = ImGui::ColorConvertFloat4ToU32({0.6, 0.4, 0.8, 1});
const ImGuiID id = ImGui::GetID(label);
ImGuiWindow* const window = ImGui::GetCurrentWindow();
ImDrawList* const draw = ImGui::GetWindowDrawList();
const ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
const ImVec2 size = ImGui::CalcTextSize(label);
ImRect bb(pos, {pos.x + size.x, pos.y + size.y});
ImGui::ItemSize(bb, 0.0f);
if (!ImGui::ItemAdd(bb, id))
return false;
bool isHovered = false;
const bool isClicked = ImGui::ButtonBehavior(bb, id, &isHovered, nullptr);
const bool isFocused = ImGui::IsItemFocused();
const ImU32 color = isHovered ? linkHoverColor : isFocused ? linkFocusColor : linkColor;
draw->AddText(bb.Min, color, label);
if (isFocused)
draw->AddRect(bb.Min, bb.Max, color);
else if (!underlineWhenHoveredOnly || isHovered)
draw->AddLine({ bb.Min.x, bb.Max.y }, bb.Max, color);
return isClicked;
}
// Test code that generated the screenshot
if (ImGui::Begin("Test Hyperlink"))
{
static bool clicked = false;
ImGui::Text("%s", clicked ? "YES" : "NO");
ImGui::Text("This is a link."); ImGui::SameLine();
if (ImGuiHyperLink("Click me!"))
clicked = !clicked;
if (ImGui::BeginItemTooltip())
{
ImGui::Text("Click to toggle");
ImGui::EndTooltip();
}
ImGui::SameLine(); ImGui::Text("That was a link.");
}
ImGui::End();