mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 05:01:05 +01: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