IsItemHovered: Added ImGuiHoveredFlags_DelayNormal, ImGuiHoveredFlags_DelayShort, ImGuiHoveredFlags_NoSharedDelay. (#1485)
IsItemHovered() can't have a non-zero default, but higher-level tooltip helpers may enable a different default later.
This commit is contained in:
parent
b3b3a07133
commit
e13913ed57
@ -67,6 +67,11 @@ Other Changes:
|
||||
Enter keep the input active and select all text.
|
||||
- InputText: numerical fields automatically accept full-width characters (U+FF01..U+FF5E)
|
||||
by converting them to half-width (U+0021..U+007E).
|
||||
- IsItemHovered: Added ImGuiHoveredFlags_DelayNormal and ImGuiHoveredFlags_DelayShort flags,
|
||||
allowing to introduce a shared delay for tooltip idioms. The delays are respectively
|
||||
io.HoverDelayNormal (default to 0.30f) and io.HoverDelayFast (default to 0.10f). (#1485)
|
||||
- IsItemHovered: Added ImGuiHoveredFlags_NoSharedDelay to disable sharing delays between itemm,
|
||||
so moving from one item to a nearby one will requires delay to elapse again. (#1485)
|
||||
- Tables,Columns: fixed a layout issue where SameLine() prior to a row change would set the
|
||||
next row in such state where subsequent SameLine() would move back to previous row.
|
||||
- Tabs: Fixed a crash when closing multiple windows (possible with docking only) with an
|
||||
|
40
imgui.cpp
40
imgui.cpp
@ -1147,6 +1147,8 @@ ImGuiIO::ImGuiIO()
|
||||
#endif
|
||||
KeyRepeatDelay = 0.275f;
|
||||
KeyRepeatRate = 0.050f;
|
||||
HoverDelayNormal = 0.30f;
|
||||
HoverDelayShort = 0.10f;
|
||||
UserData = NULL;
|
||||
|
||||
Fonts = NULL;
|
||||
@ -3571,6 +3573,24 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle hover delay
|
||||
// (some ideas: https://www.nngroup.com/articles/timing-exposing-content)
|
||||
float delay;
|
||||
if (flags & ImGuiHoveredFlags_DelayNormal)
|
||||
delay = g.IO.HoverDelayNormal;
|
||||
else if (flags & ImGuiHoveredFlags_DelayShort)
|
||||
delay = g.IO.HoverDelayShort;
|
||||
else
|
||||
delay = 0.0f;
|
||||
if (delay > 0.0f)
|
||||
{
|
||||
ImGuiID hover_delay_id = (g.LastItemData.ID != 0) ? g.LastItemData.ID : window->GetIDFromRectangle(g.LastItemData.Rect);
|
||||
if ((flags & ImGuiHoveredFlags_NoSharedDelay) && (g.HoverDelayIdPreviousFrame != hover_delay_id))
|
||||
g.HoverDelayTimer = 0.0f;
|
||||
g.HoverDelayId = hover_delay_id;
|
||||
return g.HoverDelayTimer >= delay;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -4466,6 +4486,23 @@ void ImGui::NewFrame()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Update hover delay for IsItemHovered() with delays and tooltips
|
||||
g.HoverDelayIdPreviousFrame = g.HoverDelayId;
|
||||
if (g.HoverDelayId != 0)
|
||||
{
|
||||
//if (g.IO.MouseDelta.x == 0.0f && g.IO.MouseDelta.y == 0.0f) // Need design/flags
|
||||
g.HoverDelayTimer += g.IO.DeltaTime;
|
||||
g.HoverDelayClearTimer = 0.0f;
|
||||
g.HoverDelayId = 0;
|
||||
}
|
||||
else if (g.HoverDelayTimer > 0.0f)
|
||||
{
|
||||
// This gives a little bit of leeway before clearing the hover timer, allowing mouse to cross gaps
|
||||
g.HoverDelayClearTimer += g.IO.DeltaTime;
|
||||
if (g.HoverDelayClearTimer >= ImMax(0.20f, g.IO.DeltaTime * 2.0f)) // ~6 frames at 30 Hz + allow for low framerate
|
||||
g.HoverDelayTimer = g.HoverDelayClearTimer = 0.0f; // May want a decaying timer, in which case need to clamp at max first, based on max of caller last requested timer.
|
||||
}
|
||||
|
||||
// Drag and drop
|
||||
g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr;
|
||||
g.DragDropAcceptIdCurr = 0;
|
||||
@ -12381,7 +12418,7 @@ void ImGui::DebugTextEncoding(const char* str)
|
||||
static void MetricsHelpMarker(const char* desc)
|
||||
{
|
||||
ImGui::TextDisabled("(?)");
|
||||
if (ImGui::IsItemHovered())
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort))
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
@ -12756,6 +12793,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
active_id_using_key_input_count += g.ActiveIdUsingKeyInputMask[n] ? 1 : 0;
|
||||
Text("ActiveIdUsing: NavDirMask: %X, KeyInputMask: %d key(s)", g.ActiveIdUsingNavDirMask, active_id_using_key_input_count);
|
||||
Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame
|
||||
Text("HoverDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverDelayId, g.HoverDelayTimer, g.HoverDelayClearTimer);
|
||||
Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
|
||||
Unindent();
|
||||
|
||||
|
9
imgui.h
9
imgui.h
@ -65,7 +65,7 @@ Index of this file:
|
||||
// Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
|
||||
#define IMGUI_VERSION "1.89 WIP"
|
||||
#define IMGUI_VERSION_NUM 18810
|
||||
#define IMGUI_VERSION_NUM 18811
|
||||
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
|
||||
#define IMGUI_HAS_TABLE
|
||||
|
||||
@ -1283,6 +1283,11 @@ enum ImGuiHoveredFlags_
|
||||
ImGuiHoveredFlags_NoNavOverride = 1 << 10, // Disable using gamepad/keyboard navigation state when active, always query mouse.
|
||||
ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped,
|
||||
ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows,
|
||||
|
||||
// Hovering delays (for tooltips)
|
||||
ImGuiHoveredFlags_DelayNormal = 1 << 11, // Return true after io.HoverDelayNormal elapsed (~0.30 sec)
|
||||
ImGuiHoveredFlags_DelayShort = 1 << 12, // Return true after io.HoverDelayShort elapsed (~0.10 sec)
|
||||
ImGuiHoveredFlags_NoSharedDelay = 1 << 13, // Disable shared delay system where moving from one item to the next keeps the previous timer for a short time (standard for tooltips with long delays)
|
||||
};
|
||||
|
||||
// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload()
|
||||
@ -1905,6 +1910,8 @@ struct ImGuiIO
|
||||
float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
|
||||
float KeyRepeatDelay; // = 0.275f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
|
||||
float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
|
||||
float HoverDelayNormal; // = 0.30 sec // Delay on hovering before IsItemHovered(ImGuiHoveredFlags_DelayNormal) returns true.
|
||||
float HoverDelayShort; // = 0.10 sec // Delay on hovering before IsItemHovered(ImGuiHoveredFlags_DelayShort) returns true.
|
||||
void* UserData; // = NULL // Store your own data for retrieval by callbacks.
|
||||
|
||||
ImFontAtlas*Fonts; // <auto> // Font atlas: load, rasterize and pack one or more fonts into a single texture.
|
||||
|
@ -191,7 +191,7 @@ static void ShowExampleMenuFile();
|
||||
static void HelpMarker(const char* desc)
|
||||
{
|
||||
ImGui::TextDisabled("(?)");
|
||||
if (ImGui::IsItemHovered())
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort))
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
|
||||
@ -633,22 +633,6 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%d", counter);
|
||||
|
||||
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
|
||||
ImGui::Text("Hover over me");
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("I am a tooltip");
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("- or me");
|
||||
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::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::LabelText("label", "Value");
|
||||
|
||||
@ -772,6 +756,40 @@ static void ShowDemoWindowWidgets()
|
||||
"Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
|
||||
}
|
||||
|
||||
{
|
||||
// Tooltips
|
||||
IMGUI_DEMO_MARKER("Widgets/Basic/Tooltips");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text("Tooltips:");
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Button("Button");
|
||||
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();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Button("Delayed");
|
||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal)) // Delay best used on items that highlight on hover, so this not a great example!
|
||||
ImGui::SetTooltip("I am a tooltip with a delay.");
|
||||
|
||||
ImGui::SameLine();
|
||||
HelpMarker(
|
||||
"Tooltip are created by using the IsItemHovered() function over any kind of item.");
|
||||
|
||||
}
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
@ -2346,6 +2364,10 @@ static void ShowDemoWindowWidgets()
|
||||
if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); }
|
||||
if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
|
||||
|
||||
bool hovered_delay_none = ImGui::IsItemHovered();
|
||||
bool hovered_delay_short = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort);
|
||||
bool hovered_delay_normal = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal);
|
||||
|
||||
// Display the values of IsItemHovered() and other common item state functions.
|
||||
// Note that the ImGuiHoveredFlags_XXX flags can be combined.
|
||||
// Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
|
||||
@ -2390,6 +2412,8 @@ static void ShowDemoWindowWidgets()
|
||||
ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
|
||||
ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
|
||||
);
|
||||
ImGui::BulletText(
|
||||
"w/ Hovering Delay: None = %d, Fast %d, Normal = %d", hovered_delay_none, hovered_delay_short, hovered_delay_normal);
|
||||
|
||||
if (item_disabled)
|
||||
ImGui::EndDisabled();
|
||||
|
@ -1781,6 +1781,12 @@ struct ImGuiContext
|
||||
ImVector<ImGuiPtrOrIndex> CurrentTabBarStack;
|
||||
ImVector<ImGuiShrinkWidthItem> ShrinkWidthBuffer;
|
||||
|
||||
// Hover Delay system
|
||||
ImGuiID HoverDelayId;
|
||||
ImGuiID HoverDelayIdPreviousFrame;
|
||||
float HoverDelayTimer; // Currently used IsItemHovered(), generally inferred from g.HoveredIdTimer but kept uncleared until clear timer elapse.
|
||||
float HoverDelayClearTimer; // Currently used IsItemHovered(): grace time before g.TooltipHoverTimer gets cleared.
|
||||
|
||||
// Widget state
|
||||
ImVec2 MouseLastValidPos;
|
||||
ImGuiInputTextState InputTextState;
|
||||
@ -1802,7 +1808,6 @@ struct ImGuiContext
|
||||
float DisabledAlphaBackup; // Backup for style.Alpha for BeginDisabled()
|
||||
short DisabledStackSize;
|
||||
short TooltipOverrideCount;
|
||||
float TooltipSlowDelay; // Time before slow tooltips appears (FIXME: This is temporary until we merge in tooltip timer+priority work)
|
||||
ImVector<char> ClipboardHandlerData; // If no custom clipboard handler is defined
|
||||
ImVector<ImGuiID> MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once
|
||||
|
||||
@ -1962,6 +1967,9 @@ struct ImGuiContext
|
||||
TablesTempDataStacked = 0;
|
||||
CurrentTabBar = NULL;
|
||||
|
||||
HoverDelayId = HoverDelayIdPreviousFrame = 0;
|
||||
HoverDelayTimer = HoverDelayClearTimer = 0.0f;
|
||||
|
||||
TempInputId = 0;
|
||||
ColorEditOptions = ImGuiColorEditFlags_DefaultOptions_;
|
||||
ColorEditLastHue = ColorEditLastSat = 0.0f;
|
||||
@ -1972,11 +1980,10 @@ struct ImGuiContext
|
||||
DragCurrentAccumDirty = false;
|
||||
DragCurrentAccum = 0.0f;
|
||||
DragSpeedDefaultRatio = 1.0f / 100.0f;
|
||||
ScrollbarClickDeltaToGrabCenter = 0.0f;
|
||||
DisabledAlphaBackup = 0.0f;
|
||||
DisabledStackSize = 0;
|
||||
ScrollbarClickDeltaToGrabCenter = 0.0f;
|
||||
TooltipOverrideCount = 0;
|
||||
TooltipSlowDelay = 0.50f;
|
||||
|
||||
PlatformImeData.InputPos = ImVec2(0.0f, 0.0f);
|
||||
PlatformImeDataPrev.InputPos = ImVec2(-1.0f, -1.0f); // Different to ensure initial submission
|
||||
|
@ -2994,7 +2994,7 @@ 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.HoveredIdNotActiveTimer > g.TooltipSlowDelay)
|
||||
if (text_clipped && hovered && g.ActiveId == 0 && IsItemHovered(ImGuiHoveredFlags_DelayNormal))
|
||||
SetTooltip("%.*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
|
||||
|
@ -8288,9 +8288,10 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
// (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores)
|
||||
// FIXME: This is a mess.
|
||||
// FIXME: We may want disabled tab to still display the tooltip?
|
||||
if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay && IsItemHovered())
|
||||
if (text_clipped && g.HoveredId == id && !held)
|
||||
if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
|
||||
SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
|
||||
if (IsItemHovered(ImGuiHoveredFlags_DelayNormal))
|
||||
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
|
||||
if (is_tab_button)
|
||||
|
Loading…
Reference in New Issue
Block a user