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) from style.HoverFlagsForTooltipMouse or style.HoverFlagsForTooltipNav. (#1485)
- style.HoverFlagsForTooltipMouse defaults to ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort - style.HoverFlagsForTooltipMouse defaults to ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort
- style.HoverFlagsForTooltipNav defaults to ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal - style.HoverFlagsForTooltipNav defaults to ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal
- IsItemHovered: Tweaked default value of style.HoverDelayNormal from 0.30 to 0.40, - Tooltips: Added SetItemTooltip() and BeginItemTooltip() functions.
Tweaked default value of style.HoverDelayShort from 0.10 to 0.15. (#1485) 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 - 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) 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 - 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) ScrollX or ScrollY flags from being impossible to resize. (#6503)
- Clipper: Rework inner logic to allow functioning with a zero-clear constructor. - 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) moved below the lowest blocking modal (rather than the highest one). (#4317)
- Debug Tools: Added 'io.ConfigDebugIniSettings' option to save .ini data with extra - Debug Tools: Added 'io.ConfigDebugIniSettings' option to save .ini data with extra
comments. Currently mainly for inspecting Docking .ini data, but makes saving slower. 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: OpenGL3: Fixed support for glBindSampler() backup/restore on ES3. (#6375, #6508) [@jsm174]
- Backends: GLFW: Accept glfwGetTime() not returning a monotonically increasing value. - Backends: GLFW: Accept glfwGetTime() not returning a monotonically increasing value.
This seems to happens on some Windows setup when peripherals disconnect, and is likely 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); 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) bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -10149,6 +10156,23 @@ void ImGui::SetTooltipV(const char* fmt, va_list args)
EndTooltip(); 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 // [SECTION] POPUPS
@ -13533,7 +13557,7 @@ void ImGui::DebugTextEncoding(const char* str)
static void MetricsHelpMarker(const char* desc) static void MetricsHelpMarker(const char* desc)
{ {
ImGui::TextDisabled("(?)"); ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort) && ImGui::BeginTooltip()) if (ImGui::BeginItemTooltip())
{ {
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc); ImGui::TextUnformatted(desc);

View File

@ -667,10 +667,17 @@ namespace ImGui
// Tooltips // Tooltips
// - Tooltips are windows following the mouse. They do not take focus away. // - 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 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 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); 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 // Popups, Modals
// - They block normal mouse hovering detection (and therefore most mouse interactions) behind them. // - 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. // - 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) static void HelpMarker(const char* desc)
{ {
ImGui::TextDisabled("(?)"); ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort) && ImGui::BeginTooltip()) if (ImGui::BeginItemTooltip())
{ {
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc); ImGui::TextUnformatted(desc);
@ -626,48 +626,8 @@ static void ShowDemoWindowWidgets()
ImGui::SameLine(); ImGui::SameLine();
ImGui::Text("%d", counter); ImGui::Text("%d", counter);
{ ImGui::Button("Tooltip");
// Tooltips ImGui::SetItemTooltip("I am a tooltip");
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::LabelText("label", "Value"); ImGui::LabelText("label", "Value");
@ -802,6 +762,73 @@ static void ShowDemoWindowWidgets()
ImGui::TreePop(); 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. // Testing ImGuiOnceUponAFrame helper.
//static ImGuiOnceUponAFrame once; //static ImGuiOnceUponAFrame once;
//for (int i = 0; i < 5; i++) //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 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); 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); 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_sz = 32.0f;
float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
@ -2805,7 +2832,7 @@ static void ShowDemoWindowLayout()
ImGui::PushID(i); ImGui::PushID(i);
ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items)); ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
ImGui::PopID(); ImGui::PopID();
//if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i); //ImGui::SetItemTooltip("ListBox %d hovered", i);
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
@ -2858,8 +2885,7 @@ static void ShowDemoWindowLayout()
ImGui::SameLine(); ImGui::SameLine();
ImGui::Button("EEE"); ImGui::Button("EEE");
ImGui::EndGroup(); ImGui::EndGroup();
if (ImGui::IsItemHovered()) ImGui::SetItemTooltip("First group hovered");
ImGui::SetTooltip("First group hovered");
} }
// Capture the group size and create widgets using the same size // Capture the group size and create widgets using the same size
ImVec2 size = ImGui::GetItemRectSize(); ImVec2 size = ImGui::GetItemRectSize();
@ -3420,8 +3446,7 @@ static void ShowDemoWindowPopups()
ImGui::Separator(); ImGui::Separator();
ImGui::Text("Tooltip here"); ImGui::Text("Tooltip here");
if (ImGui::IsItemHovered()) ImGui::SetItemTooltip("I am a tooltip over a popup");
ImGui::SetTooltip("I am a tooltip over a popup");
if (ImGui::Button("Stacked Popup")) if (ImGui::Button("Stacked Popup"))
ImGui::OpenPopup("another popup"); ImGui::OpenPopup("another popup");
@ -3505,8 +3530,7 @@ static void ShowDemoWindowPopups()
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
ImGui::EndPopup(); ImGui::EndPopup();
} }
if (ImGui::IsItemHovered()) ImGui::SetItemTooltip("Right-click to open popup");
ImGui::SetTooltip("Right-click to open popup");
} }
} }
@ -3758,7 +3782,7 @@ static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextDisabled("(?)"); ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered() && ImGui::BeginTooltip()) if (ImGui::BeginItemTooltip())
{ {
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f); ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
for (int m = 0; m < IM_ARRAYSIZE(policies); m++) 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); 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); const bool text_clipped = label_size.x > (ellipsis_max - label_pos.x);
if (text_clipped && hovered && g.ActiveId == 0 && IsItemHovered(ImGuiHoveredFlags_DelayNormal)) if (text_clipped && hovered && g.ActiveId == 0)
SetTooltip("%.*s", (int)(label_end - label), label); 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 // We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
if (IsMouseReleased(1) && IsItemHovered()) if (IsMouseReleased(1) && IsItemHovered())

View File

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