Tooltips: Added SetItemTooltip(), BeginItemTooltip(). Improved Demo section.

This commit is contained in:
ocornut 2023-06-16 16:42:56 +02:00
parent 0f72652c2d
commit b60acfa87d
6 changed files with 124 additions and 61 deletions

View File

@ -51,10 +51,18 @@ Other changes:
from style.HoverFlagsForTooltipMouse or style.HoverFlagsForTooltipNav. (#1485)
- style.HoverFlagsForTooltipMouse defaults to ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort
- style.HoverFlagsForTooltipNav defaults to ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal
- IsItemHovered: Tweaked default value of style.HoverDelayNormal from 0.30 to 0.40,
Tweaked default value of style.HoverDelayShort from 0.10 to 0.15. (#1485)
- Tooltips: Added SetItemTooltip() and BeginItemTooltip() functions.
They are shortcuts for the common idiom of using IsItemHovered().
- SetItemTooltip("Hello") == if (IsItemHovered(ImGuiHoveredFlags_Tooltip)) { SetTooltip("Hello"); }
- BeginItemTooltip() == IsItemHovered(ImGuiHoveredFlags_Tooltip) && BeginTooltip()
The newly added ImGuiHoveredFlags_Tooltip is meant to standardize mouse hovering
delays and rules for a whole application.
The previously common idiom of using 'if (IsItemHovered()) { SetTooltip(...); }' won't
use delay or stationary test.
- Tooltips: Tweak default offset for non-drag and drop tooltips so underlying items
isn't covered as much. (Match offset for drag and drop tooltips)
- IsItemHovered: Tweaked default value of style.HoverDelayNormal from 0.30 to 0.40,
Tweaked default value of style.HoverDelayShort from 0.10 to 0.15. (#1485)
- Tables: Fixed a regression in 1.89.6 leading to the first column of tables with either
ScrollX or ScrollY flags from being impossible to resize. (#6503)
- Clipper: Rework inner logic to allow functioning with a zero-clear constructor.
@ -64,6 +72,7 @@ Other changes:
moved below the lowest blocking modal (rather than the highest one). (#4317)
- Debug Tools: Added 'io.ConfigDebugIniSettings' option to save .ini data with extra
comments. Currently mainly for inspecting Docking .ini data, but makes saving slower.
- Demo: Added more developed "Widgets->Tooltips" section. (#1485)
- Backends: OpenGL3: Fixed support for glBindSampler() backup/restore on ES3. (#6375, #6508) [@jsm174]
- Backends: GLFW: Accept glfwGetTime() not returning a monotonically increasing value.
This seems to happens on some Windows setup when peripherals disconnect, and is likely

View File

@ -10088,6 +10088,13 @@ bool ImGui::BeginTooltip()
return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
}
bool ImGui::BeginItemTooltip()
{
if (!IsItemHovered(ImGuiHoveredFlags_ForTooltip))
return false;
return BeginTooltipEx(ImGuiTooltipFlags_None, ImGuiWindowFlags_None);
}
bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
{
ImGuiContext& g = *GImGui;
@ -10149,6 +10156,23 @@ void ImGui::SetTooltipV(const char* fmt, va_list args)
EndTooltip();
}
// Shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav'.
// Defaults to == ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort when using the mouse.
void ImGui::SetItemTooltip(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
SetTooltipV(fmt, args);
va_end(args);
}
void ImGui::SetItemTooltipV(const char* fmt, va_list args)
{
if (IsItemHovered(ImGuiHoveredFlags_ForTooltip))
SetTooltipV(fmt, args);
}
//-----------------------------------------------------------------------------
// [SECTION] POPUPS
@ -13533,7 +13557,7 @@ void ImGui::DebugTextEncoding(const char* str)
static void MetricsHelpMarker(const char* desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort) && ImGui::BeginTooltip())
if (ImGui::BeginItemTooltip())
{
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);

View File

@ -667,10 +667,17 @@ namespace ImGui
// Tooltips
// - Tooltips are windows following the mouse. They do not take focus away.
IMGUI_API bool BeginTooltip(); // begin/append a tooltip window. to create full-featured tooltip (with any kind of items).
IMGUI_API void EndTooltip(); // only call EndTooltip() if BeginTooltip() returns true!
IMGUI_API void EndTooltip(); // only call EndTooltip() if BeginTooltip()/BeginItemTooltip() returns true!
IMGUI_API void SetTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip, typically use with ImGui::IsItemHovered(). override any previous call to SetTooltip().
IMGUI_API void SetTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
// Tooltips: helper for showing a tooltip when hovering an item
// - BeginItemTooltip(), SetItemTooltip() are shortcuts for the 'if (IsItemHovered(ImGuiHoveredFlags_Tooltip)) { BeginTooltip() or SetTooltip() }' idiom.
// - Where 'ImGuiHoveredFlags_Tooltip' itself is a shortcut to use 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav'. For mouse it defaults to 'ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort'.
IMGUI_API bool BeginItemTooltip(); // begin/append a tooltip window if preceding item was hovered.
IMGUI_API void SetItemTooltip(const char* fmt, ...) IM_FMTARGS(1); // set a text-only tooltip if preceeding item was hovered. override any previous call to SetTooltip().
IMGUI_API void SetItemTooltipV(const char* fmt, va_list args) IM_FMTLIST(1);
// Popups, Modals
// - They block normal mouse hovering detection (and therefore most mouse interactions) behind them.
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.

View File

@ -211,7 +211,7 @@ static void ShowDemoWindowInputs();
static void HelpMarker(const char* desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort) && ImGui::BeginTooltip())
if (ImGui::BeginItemTooltip())
{
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);
@ -626,48 +626,8 @@ static void ShowDemoWindowWidgets()
ImGui::SameLine();
ImGui::Text("%d", counter);
{
// Tooltips
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
ImGui::AlignTextToFramePadding();
ImGui::Text("Tooltips:");
ImGui::SameLine();
ImGui::Button("Basic");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip");
ImGui::SameLine();
ImGui::Button("Fancy");
if (ImGui::IsItemHovered() && ImGui::BeginTooltip())
{
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
ImGui::EndTooltip();
}
// Showcase use of ImGuiHoveredFlags_ForTooltip which is an alias for ImGuiHoveredFlags_DelayNormal + ImGuiHoveredFlags_Stationary.
// - ImGuiHoveredFlags_DelayNormal requires an hovering delay (default to 0.40 sec)
// - ImGuiHoveredFlags_Stationary requires mouse to be stationary (default to 0.15 sec) at least once on a new item.
// We show two items to showcase how the main delay is by default shared between items,
// so once in "tooltip mode" moving to another tooltip only requires the stationary delay.
ImGui::SameLine();
ImGui::Button("Delayed1");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
ImGui::SetTooltip("I am a tooltip with a delay.");
ImGui::SameLine();
ImGui::Button("Delayed2");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
ImGui::SetTooltip("I am another tooltip with a delay.");
ImGui::SameLine();
HelpMarker(
"Tooltip are created by using the IsItemHovered() function over any kind of item.");
}
ImGui::Button("Tooltip");
ImGui::SetItemTooltip("I am a tooltip");
ImGui::LabelText("label", "Value");
@ -802,6 +762,73 @@ static void ShowDemoWindowWidgets()
ImGui::TreePop();
}
IMGUI_DEMO_MARKER("Widgets/Tooltips");
if (ImGui::TreeNode("Tooltips"))
{
// Tooltips are windows following the mouse. They do not take focus away.
ImGui::SeparatorText("General");
// Typical use cases:
// - Short-form (text only): SetItemTooltip("Hello");
// - Short-form (any contents): if (BeginItemTooltip()) { Text("Hello"); EndTooltip(); }
// - Full-form (text only): if (IsItemHovered(...)) { SetTooltip("Hello"); }
// - Full-form (any contents): if (IsItemHovered(...) && BeginTooltip()) { Text("Hello"); EndTooltip(); }
HelpMarker(
"Tooltip are typically created by using the IsItemHovered() + SetTooltip() functions over any kind of item.\n\n"
"We provide a helper SetItemTooltip() function to perform the two with standards flags.");
ImVec2 sz = ImVec2(-FLT_MIN, 0.0f);
ImGui::Button("Basic", sz);
ImGui::SetItemTooltip("I am a tooltip");
ImGui::Button("Fancy", sz);
if (ImGui::BeginItemTooltip())
{
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
ImGui::EndTooltip();
}
ImGui::SeparatorText("Custom");
// Showcase NOT relying on a IsItemHovered() to emit a tooltip.
static bool always_on = false;
ImGui::Checkbox("Always On", &always_on);
if (always_on)
ImGui::SetTooltip("I am following you around.");
// The following examples are passed for documentation purpose but may not be useful to most users.
// Passing ImGuiHoveredFlags_Tooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from
// 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or gamepad/keyboard is being used.
// With default settings, ImGuiHoveredFlags_Tooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary.
ImGui::Button("Manual", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
ImGui::SetTooltip("I am a manually emitted tooltip");
ImGui::Button("DelayNone", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNone))
ImGui::SetTooltip("I am a tooltip with no delay.");
ImGui::Button("DelayShort", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_NoSharedDelay))
ImGui::SetTooltip("I am a tooltip with a short delay (%0.2f sec).", ImGui::GetStyle().HoverDelayShort);
ImGui::Button("DelayLong", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay))
ImGui::SetTooltip("I am a tooltip with a long delay (%0.2f sec)", ImGui::GetStyle().HoverDelayNormal);
ImGui::Button("Stationary", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary))
ImGui::SetTooltip("I am a tooltip requiring mouse to be stationary before activating.");
ImGui::TreePop();
}
// Testing ImGuiOnceUponAFrame helper.
//static ImGuiOnceUponAFrame once;
//for (int i = 0; i < 5; i++)
@ -1067,7 +1094,7 @@ static void ShowDemoWindowWidgets()
ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border);
ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
if (ImGui::IsItemHovered() && ImGui::BeginTooltip())
if (ImGui::BeginItemTooltip())
{
float region_sz = 32.0f;
float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
@ -2805,7 +2832,7 @@ static void ShowDemoWindowLayout()
ImGui::PushID(i);
ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
ImGui::PopID();
//if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
//ImGui::SetItemTooltip("ListBox %d hovered", i);
}
ImGui::PopItemWidth();
@ -2858,8 +2885,7 @@ static void ShowDemoWindowLayout()
ImGui::SameLine();
ImGui::Button("EEE");
ImGui::EndGroup();
if (ImGui::IsItemHovered())
ImGui::SetTooltip("First group hovered");
ImGui::SetItemTooltip("First group hovered");
}
// Capture the group size and create widgets using the same size
ImVec2 size = ImGui::GetItemRectSize();
@ -3420,8 +3446,7 @@ static void ShowDemoWindowPopups()
ImGui::Separator();
ImGui::Text("Tooltip here");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip over a popup");
ImGui::SetItemTooltip("I am a tooltip over a popup");
if (ImGui::Button("Stacked Popup"))
ImGui::OpenPopup("another popup");
@ -3505,8 +3530,7 @@ static void ShowDemoWindowPopups()
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Right-click to open popup");
ImGui::SetItemTooltip("Right-click to open popup");
}
}
@ -3758,7 +3782,7 @@ static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
}
ImGui::SameLine();
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered() && ImGui::BeginTooltip())
if (ImGui::BeginItemTooltip())
{
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
for (int m = 0; m < IM_ARRAYSIZE(policies); m++)

View File

@ -3036,8 +3036,8 @@ void ImGui::TableHeader(const char* label)
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size);
const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x);
if (text_clipped && hovered && g.ActiveId == 0 && IsItemHovered(ImGuiHoveredFlags_DelayNormal))
SetTooltip("%.*s", (int)(label_end - label), label);
if (text_clipped && hovered && g.ActiveId == 0)
SetItemTooltip("%.*s", (int)(label_end - label), label);
// We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
if (IsMouseReleased(1) && IsItemHovered())

View File

@ -5801,7 +5801,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
}
// Tooltip
if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)
if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered && IsItemHovered(ImGuiHoveredFlags_ForTooltip))
ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));
return pressed;
@ -8474,8 +8474,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// FIXME: We may want disabled tab to still display the tooltip?
if (text_clipped && g.HoveredId == id && !held)
if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
if (IsItemHovered(ImGuiHoveredFlags_DelayNormal))
SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
SetItemTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button)); // TabItemButton should not be selected
if (is_tab_button)