mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-24 00:26:36 +00:00
Fix popup and tooltip positioning when not fitting in the screen. Amend fa42ccea8.
# Conflicts: # docs/CHANGELOG.txt
This commit is contained in:
parent
b7b08f52a4
commit
c47bcb25ed
@ -68,6 +68,8 @@ Other Changes:
|
||||
tabs reordered in the tab list popup. [@Xipiryon]
|
||||
- Columns: Fix inverted ClipRect being passed to renderer when using certain primitives inside of
|
||||
a fully clipped column. (#3475) [@szreder]
|
||||
- Popups, Tooltips: Fix edge cases issues with positionning popups and tooltips when they are larger than
|
||||
viewport on either or both axises. [@Rokups]
|
||||
- Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible.
|
||||
- Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console').
|
||||
- Backends: OpenGL3: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 contexts which have
|
||||
|
@ -219,7 +219,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- popups/modals: although it is sometimes convenient that popups/modals lifetime is owned by imgui, we could also a bool-owned-by-user api as long as Begin() return value testing is enforced.
|
||||
|
||||
- tooltip: drag and drop with tooltip near monitor edges lose/changes its last direction instead of locking one. The drag and drop tooltip should always follow without changing direction.
|
||||
- tooltip: tooltip that doesn't fit in entire screen seems to lose their "last preferred direction" and may teleport when moving mouse.
|
||||
- tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
|
||||
- tooltip: tooltips with delay timers? or general timer policy? (instantaneous vs timed): IsItemHovered() with timer + implicit aabb-id for items with no ID. (#1485)
|
||||
- tooltip: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers.
|
||||
|
65
imgui.cpp
65
imgui.cpp
@ -8007,37 +8007,47 @@ ImVec2 ImGui::FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& s
|
||||
}
|
||||
}
|
||||
|
||||
// Default popup policy
|
||||
const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
|
||||
for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
|
||||
// Tooltip and Default popup policy
|
||||
// (Always first try the direction we used on the last frame, if any)
|
||||
if (policy == ImGuiPopupPositionPolicy_Tooltip || policy == ImGuiPopupPositionPolicy_Default)
|
||||
{
|
||||
const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
|
||||
if (n != -1 && dir == *last_dir) // Already tried this direction?
|
||||
continue;
|
||||
float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x);
|
||||
float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y);
|
||||
const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left };
|
||||
for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++)
|
||||
{
|
||||
const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n];
|
||||
if (n != -1 && dir == *last_dir) // Already tried this direction?
|
||||
continue;
|
||||
|
||||
// There is no point in switching left/right sides when popup height exceeds available height or top/bottom
|
||||
// sides when popup width exceeds available width.
|
||||
if (avail_h < size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down))
|
||||
continue;
|
||||
else if (avail_w < size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right))
|
||||
continue;
|
||||
const float avail_w = (dir == ImGuiDir_Left ? r_avoid.Min.x : r_outer.Max.x) - (dir == ImGuiDir_Right ? r_avoid.Max.x : r_outer.Min.x);
|
||||
const float avail_h = (dir == ImGuiDir_Up ? r_avoid.Min.y : r_outer.Max.y) - (dir == ImGuiDir_Down ? r_avoid.Max.y : r_outer.Min.y);
|
||||
|
||||
ImVec2 pos;
|
||||
pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
|
||||
pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
|
||||
// If there not enough room on one axis, there's no point in positioning on a side on this axis (e.g. when not enough width, use a top/bottom position to maximize available width)
|
||||
if (avail_w < size.x && (dir == ImGuiDir_Left || dir == ImGuiDir_Right))
|
||||
continue;
|
||||
if (avail_h < size.y && (dir == ImGuiDir_Up || dir == ImGuiDir_Down))
|
||||
continue;
|
||||
|
||||
// Clamp top-left (or top-right for RTL languages in the future) corner of popup to remain visible.
|
||||
pos.x = ImMax(pos.x, r_outer.Min.x);
|
||||
pos.y = ImMax(pos.y, r_outer.Min.y);
|
||||
ImVec2 pos;
|
||||
pos.x = (dir == ImGuiDir_Left) ? r_avoid.Min.x - size.x : (dir == ImGuiDir_Right) ? r_avoid.Max.x : base_pos_clamped.x;
|
||||
pos.y = (dir == ImGuiDir_Up) ? r_avoid.Min.y - size.y : (dir == ImGuiDir_Down) ? r_avoid.Max.y : base_pos_clamped.y;
|
||||
|
||||
*last_dir = dir;
|
||||
return pos;
|
||||
// Clamp top-left corner of popup
|
||||
pos.x = ImMax(pos.x, r_outer.Min.x);
|
||||
pos.y = ImMax(pos.y, r_outer.Min.y);
|
||||
|
||||
*last_dir = dir;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback, try to keep within display
|
||||
// Fallback when not enough room:
|
||||
*last_dir = ImGuiDir_None;
|
||||
|
||||
// For tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible.
|
||||
if (policy == ImGuiPopupPositionPolicy_Tooltip)
|
||||
return ref_pos + ImVec2(2, 2);
|
||||
|
||||
// Otherwise try to keep within display
|
||||
ImVec2 pos = ref_pos;
|
||||
pos.x = ImMax(ImMin(pos.x + size.x, r_outer.Max.x) - size.x, r_outer.Min.x);
|
||||
pos.y = ImMax(ImMin(pos.y + size.y, r_outer.Max.y) - size.y, r_outer.Min.y);
|
||||
@ -8070,12 +8080,12 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
|
||||
r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, parent_window->ClipRect.Max.y); // Avoid parent menu-bar. If we wanted multi-line menu-bar, we may instead want to have the calling window setup e.g. a NextWindowData.PosConstraintAvoidRect field
|
||||
else
|
||||
r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX);
|
||||
return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
|
||||
return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default);
|
||||
}
|
||||
if (window->Flags & ImGuiWindowFlags_Popup)
|
||||
{
|
||||
ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Pos.x + 1, window->Pos.y + 1);
|
||||
return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
|
||||
return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default);
|
||||
}
|
||||
if (window->Flags & ImGuiWindowFlags_Tooltip)
|
||||
{
|
||||
@ -8087,10 +8097,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
|
||||
r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8);
|
||||
else
|
||||
r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important.
|
||||
ImVec2 pos = FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
|
||||
if (window->AutoPosLastDirection == ImGuiDir_None)
|
||||
pos = ref_pos + ImVec2(2, 2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible.
|
||||
return pos;
|
||||
return FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Tooltip);
|
||||
}
|
||||
IM_ASSERT(0);
|
||||
return window->Pos;
|
||||
|
@ -777,7 +777,8 @@ enum ImGuiNavLayer
|
||||
enum ImGuiPopupPositionPolicy
|
||||
{
|
||||
ImGuiPopupPositionPolicy_Default,
|
||||
ImGuiPopupPositionPolicy_ComboBox
|
||||
ImGuiPopupPositionPolicy_ComboBox,
|
||||
ImGuiPopupPositionPolicy_Tooltip
|
||||
};
|
||||
|
||||
struct ImGuiDataTypeTempStorage
|
||||
@ -1879,7 +1880,7 @@ namespace ImGui
|
||||
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags);
|
||||
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy = ImGuiPopupPositionPolicy_Default);
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
|
||||
|
||||
// Gamepad/Keyboard Navigation
|
||||
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
|
||||
|
Loading…
Reference in New Issue
Block a user