mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-04 03:58:47 +02:00
Clarified behavior of SetNextWindowContentSize(). Content size is defined as the size available after removal of WindowPadding on each sides. So SetNextWindowContentSize(ImVec2(100,100)) + auto-resize will always allow submitting a 100x100 item without creating a scrollbar, regarding of WindowPadding.The exact meaning of ContentSize for decorated windows was previously ill-defined.
This commit is contained in:
82
imgui.cpp
82
imgui.cpp
@ -4637,8 +4637,8 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
|
||||
if (ImLengthSqr(settings->Size) > 0.00001f)
|
||||
size = ImFloor(settings->Size);
|
||||
}
|
||||
window->Size = window->SizeFull = window->SizeFullAtLastBegin = ImFloor(size);
|
||||
window->DC.CursorMaxPos = window->Pos; // So first call to CalcSizeContents() doesn't return crazy values
|
||||
window->Size = window->SizeFull = ImFloor(size);
|
||||
window->DC.CursorStartPos = window->DC.CursorMaxPos = window->Pos; // So first call to CalcSizeContents() doesn't return crazy values
|
||||
|
||||
if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
|
||||
{
|
||||
@ -4703,19 +4703,22 @@ static ImVec2 CalcSizeContents(ImGuiWindow* window)
|
||||
return window->SizeContents;
|
||||
|
||||
ImVec2 sz;
|
||||
sz.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : (window->DC.CursorMaxPos.x - window->Pos.x + window->Scroll.x));
|
||||
sz.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : (window->DC.CursorMaxPos.y - window->Pos.y + window->Scroll.y));
|
||||
return sz + window->WindowPadding;
|
||||
sz.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
|
||||
sz.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y);
|
||||
return sz;
|
||||
}
|
||||
|
||||
static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiStyle& style = g.Style;
|
||||
ImVec2 size_decorations = ImVec2(0.0f, window->TitleBarHeight() + window->MenuBarHeight());
|
||||
ImVec2 size_pad = window->WindowPadding * 2.0f;
|
||||
ImVec2 size_desired = size_contents + size_pad + size_decorations;
|
||||
if (window->Flags & ImGuiWindowFlags_Tooltip)
|
||||
{
|
||||
// Tooltip always resize
|
||||
return size_contents;
|
||||
return size_desired;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -4725,14 +4728,14 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
|
||||
ImVec2 size_min = style.WindowMinSize;
|
||||
if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups)
|
||||
size_min = ImMin(size_min, ImVec2(4.0f, 4.0f));
|
||||
ImVec2 size_auto_fit = ImClamp(size_contents, size_min, ImMax(size_min, g.IO.DisplaySize - style.DisplaySafeAreaPadding * 2.0f));
|
||||
ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, g.IO.DisplaySize - style.DisplaySafeAreaPadding * 2.0f));
|
||||
|
||||
// When the window cannot fit all contents (either because of constraints, either because screen is too small),
|
||||
// we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding.
|
||||
ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit);
|
||||
if (size_auto_fit_after_constraint.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar))
|
||||
if (size_auto_fit_after_constraint.x - size_pad.x - size_decorations.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar))
|
||||
size_auto_fit.y += style.ScrollbarSize;
|
||||
if (size_auto_fit_after_constraint.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar))
|
||||
if (size_auto_fit_after_constraint.y - size_pad.y - size_decorations.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar))
|
||||
size_auto_fit.x += style.ScrollbarSize;
|
||||
return size_auto_fit;
|
||||
}
|
||||
@ -4746,12 +4749,12 @@ ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window)
|
||||
|
||||
float ImGui::GetWindowScrollMaxX(ImGuiWindow* window)
|
||||
{
|
||||
return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x));
|
||||
return ImMax(0.0f, window->SizeContents.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth());
|
||||
}
|
||||
|
||||
float ImGui::GetWindowScrollMaxY(ImGuiWindow* window)
|
||||
{
|
||||
return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y));
|
||||
return ImMax(0.0f, window->SizeContents.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight());
|
||||
}
|
||||
|
||||
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges)
|
||||
@ -4761,7 +4764,7 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s
|
||||
if (window->ScrollTarget.x < FLT_MAX)
|
||||
{
|
||||
float cr_x = window->ScrollTargetCenterRatio.x;
|
||||
scroll.x = window->ScrollTarget.x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x);
|
||||
scroll.x = window->ScrollTarget.x - cr_x * window->InnerRect.GetWidth();
|
||||
}
|
||||
if (window->ScrollTarget.y < FLT_MAX)
|
||||
{
|
||||
@ -4770,9 +4773,9 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool s
|
||||
float target_y = window->ScrollTarget.y;
|
||||
if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y)
|
||||
target_y = 0.0f;
|
||||
if (snap_on_edges && cr_y >= 1.0f && target_y >= window->SizeContents.y - window->WindowPadding.y + g.Style.ItemSpacing.y)
|
||||
target_y = window->SizeContents.y;
|
||||
scroll.y = target_y - (1.0f - cr_y) * (window->TitleBarHeight() + window->MenuBarHeight()) - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y);
|
||||
if (snap_on_edges && cr_y >= 1.0f && target_y >= window->SizeContents.y + window->WindowPadding.y + g.Style.ItemSpacing.y)
|
||||
target_y = window->SizeContents.y + window->WindowPadding.y * 2.0f;
|
||||
scroll.y = target_y - cr_y * window->InnerRect.GetHeight();
|
||||
}
|
||||
scroll = ImMax(scroll, ImVec2(0.0f, 0.0f));
|
||||
if (!window->Collapsed && !window->SkipItems)
|
||||
@ -5280,16 +5283,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
|
||||
}
|
||||
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize)
|
||||
{
|
||||
// Adjust passed "client size" to become a "window size"
|
||||
window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal;
|
||||
if (window->SizeContentsExplicit.y != 0.0f)
|
||||
window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight();
|
||||
}
|
||||
else if (first_begin_of_the_frame)
|
||||
{
|
||||
window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
|
||||
}
|
||||
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed)
|
||||
SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
|
||||
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus)
|
||||
@ -5349,9 +5345,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME-VIEWPORT: In the docking/viewport branch, this is the point where we select the current viewport (which may affect the style)
|
||||
SetCurrentWindow(window);
|
||||
|
||||
// Lock border size and padding for the frame (so that altering them doesn't cause inconsistencies)
|
||||
// LOCK BORDER SIZE AND PADDING FOR THE FRAME (so that altering them doesn't cause inconsistencies)
|
||||
|
||||
if (flags & ImGuiWindowFlags_ChildWindow)
|
||||
window->WindowBorderSize = style.ChildBorderSize;
|
||||
else
|
||||
@ -5417,13 +5415,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
// Update scrollbar status (based on the Size that was effective during last frame or the auto-resized Size).
|
||||
if (!window->Collapsed)
|
||||
{
|
||||
// When reading the current size we need to read it after size constraints have been applied
|
||||
float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->SizeFullAtLastBegin.x;
|
||||
float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y : window->SizeFullAtLastBegin.y;
|
||||
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
||||
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
||||
// When reading the current size we need to read it after size constraints have been applied.
|
||||
// When we use InnerRect here we are intentionally reading last frame size, same for ScrollbarSizes values before we set them again.
|
||||
float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->InnerRect.GetWidth() + window->ScrollbarSizes.x;
|
||||
float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y - window->TitleBarHeight() - window->MenuBarHeight() : window->InnerRect.GetHeight() + window->ScrollbarSizes.y;
|
||||
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y + window->WindowPadding.y * 2.0f > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
||||
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x + window->WindowPadding.x * 2.0f > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
||||
if (window->ScrollbarX && !window->ScrollbarY)
|
||||
window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
||||
window->ScrollbarY = (window->SizeContents.y + window->WindowPadding.y * 2.0f > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
||||
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
|
||||
}
|
||||
|
||||
@ -5502,9 +5501,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
else
|
||||
window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f);
|
||||
|
||||
// Store a backup of SizeFull which we will use next frame to decide if we need scrollbars.
|
||||
window->SizeFullAtLastBegin = window->SizeFull;
|
||||
|
||||
// UPDATE RECTANGLES (1- THOSE NOT AFFECTED BY SCROLLING)
|
||||
// Update various regions. Variables they depends on should be set above in this function.
|
||||
// We set this up after processing the resize grip so that our rectangles doesn't lag by a frame.
|
||||
@ -6325,16 +6321,12 @@ ImVec2 ImGui::GetWindowPos()
|
||||
|
||||
void ImGui::SetWindowScrollX(ImGuiWindow* window, float new_scroll_x)
|
||||
{
|
||||
window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
|
||||
window->Scroll.x = new_scroll_x;
|
||||
window->DC.CursorMaxPos.x -= window->Scroll.x;
|
||||
}
|
||||
|
||||
void ImGui::SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
|
||||
{
|
||||
window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
|
||||
window->Scroll.y = new_scroll_y;
|
||||
window->DC.CursorMaxPos.y -= window->Scroll.y;
|
||||
}
|
||||
|
||||
void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
|
||||
@ -6350,8 +6342,10 @@ void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
|
||||
// Set
|
||||
const ImVec2 old_pos = window->Pos;
|
||||
window->Pos = ImFloor(pos);
|
||||
window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor
|
||||
window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected.
|
||||
ImVec2 offset = window->Pos - old_pos;
|
||||
window->DC.CursorPos += offset; // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor
|
||||
window->DC.CursorMaxPos += offset; // And more importantly we need to offset CursorMaxPos/CursorStartPos this so SizeContents calculation doesn't get affected.
|
||||
window->DC.CursorStartPos += offset;
|
||||
}
|
||||
|
||||
void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond)
|
||||
@ -6495,11 +6489,13 @@ void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& s
|
||||
g.NextWindowData.SizeCallbackUserData = custom_callback_user_data;
|
||||
}
|
||||
|
||||
// Content size = inner scrollable rectangle, padded with WindowPadding.
|
||||
// SetNextWindowContentSize(ImVec2(100,100) + ImGuiWindowFlags_AlwaysAutoResize will always allow submitting a 100x100 item.
|
||||
void ImGui::SetNextWindowContentSize(const ImVec2& size)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize;
|
||||
g.NextWindowData.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value.
|
||||
g.NextWindowData.ContentSizeVal = size;
|
||||
}
|
||||
|
||||
void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
|
||||
@ -6712,7 +6708,7 @@ void ImGui::SetScrollX(float scroll_x)
|
||||
void ImGui::SetScrollY(float scroll_y)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY
|
||||
window->ScrollTarget.y = scroll_y;
|
||||
window->ScrollTargetCenterRatio.y = 0.0f;
|
||||
}
|
||||
|
||||
@ -7717,7 +7713,7 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov
|
||||
ImGuiDir clip_dir = g.NavMoveDir;
|
||||
if (g.NavMoveDir == ImGuiDir_Left && (move_flags & (ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX)))
|
||||
{
|
||||
bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x) - window->Scroll.x;
|
||||
bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x + window->WindowPadding.x * 2.0f) - window->Scroll.x;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapX) { bb_rel.TranslateY(-bb_rel.GetHeight()); clip_dir = ImGuiDir_Up; }
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||
}
|
||||
@ -7729,7 +7725,7 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov
|
||||
}
|
||||
if (g.NavMoveDir == ImGuiDir_Up && (move_flags & (ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY)))
|
||||
{
|
||||
bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y) - window->Scroll.y;
|
||||
bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y + window->WindowPadding.y * 2.0f) - window->Scroll.y;
|
||||
if (move_flags & ImGuiNavMoveFlags_WrapY) { bb_rel.TranslateX(-bb_rel.GetWidth()); clip_dir = ImGuiDir_Left; }
|
||||
NavMoveRequestForward(g.NavMoveDir, clip_dir, bb_rel, move_flags);
|
||||
}
|
||||
@ -9794,7 +9790,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
else if (rect_type == RT_InnerRect) { return window->InnerRect; }
|
||||
else if (rect_type == RT_InnerClipRect) { return window->InnerClipRect; }
|
||||
else if (rect_type == RT_WorkRect) { return window->WorkRect; }
|
||||
else if (rect_type == RT_Contents) { return ImRect(window->Pos, window->Pos + window->SizeContents); }
|
||||
else if (rect_type == RT_Contents) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->SizeContents); }
|
||||
else if (rect_type == RT_ContentsRegionRect) { return window->ContentsRegionRect; }
|
||||
IM_ASSERT(0);
|
||||
return ImRect();
|
||||
|
Reference in New Issue
Block a user