Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
#	imgui_internal.h
docking
omar 5 years ago
commit e6850891cc

@ -106,6 +106,13 @@ Breaking Changes:
- Renamed SetNextTreeNodeOpen() to SetNextItemOpen(). Kept inline redirection function (will obsolete).
Other Changes:
- Window: 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.
- Window: Fixed auto-resize with AlwaysVerticalScrollbar or AlwaysHorizontalScrollbar flags.
- Window: Fixed one case where auto-resize by double-clicking the resize grip would make either scrollbar
appear for a single frame after the resize.
- Columns: Fixed Separator from creating an extraneous draw command. (#125)
- Columns: Fixed Selectable with SpanAllColumns flag from creating an extraneous draw command. (#125)
- Separator: Revert 1.70 "Declare its thickness (1.0f) to the layout" change. It's not incorrect
@ -121,7 +128,8 @@ Other Changes:
- ColorEdit: Fixed the color picker popup only displaying inputs as HSV instead of showing multiple
options. (#2587, broken in 1.69 by #2384).
- CollapsingHeader: Better clipping when a close button is enabled and it overlaps the label. (#600)
- Scrollbar: Very minor bounding box adjustment to cope with various border size.
- Scrollbar: Minor bounding box adjustment to cope with various border size.
- Scrollbar, Style: Changed default style.ScrollbarSize from 16 to 14.
- Combo: Fixed rounding not applying with the ImGuiComboFlags_NoArrowButton flag. (#2607) [@DucaRii]
- Nav: Fixed gamepad/keyboard moving of window affecting contents size incorrectly, sometimes leading
to scrollbars appearing during the movement.
@ -129,6 +137,12 @@ Other Changes:
frame as clearing the focus. This was in most noticeable in back-ends such as Glfw and SDL which
emits key release events when focusing another viewport, leading to Alt+clicking on void on another
viewport triggering the issue. (#2609)
- TreeNode, CollapsingHeader: Fixed highlight frame not covering horizontal area fully when using
horizontal scrolling. (#2211, #2579)
- TabBar: Fixed BeginTabBar() within a window with horizontal scrolling from creating a feedback
loop with the horizontal contents size.
- Columns: Fixed Columns() within a window with horizontal scrolling from not covering the full
horizontal area (previously only worked with an explicit contents size). (#125)
- Style: Added style.WindowMenuButtonPosition (left/right, defaults to ImGuiDir_Left) to move the
collapsing/docking button to the other side of the title bar.
- Style: Made window close button cross slightly smaller.

@ -70,6 +70,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- widgets: selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
- widgets: checkbox: checkbox with custom glyph inside frame.
- widgets: coloredit: keep reporting as active when picker is on?
- widgets: group/scalarn functions: expose more per-component information. e.g. store NextItemData.ComponentIdx set by scalarn function, groups can expose them back somehow.
- input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile.
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
@ -258,6 +259,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
- style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
- style: global scale setting.
- style: FramePadding could be different for up vs down (#584)
- style: WindowPadding needs to be EVEN as the 0.5 multiplier used on this value probably have a subtle effect on clip rectangle
- style: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438, #707, #1223)
- style: gradients fill (#1223) ~ 2 bg colors for each fill? tricky with rounded shapes and using textures for corners.

@ -1090,7 +1090,7 @@ static int FindWindowFocusIndex(ImGuiWindow* window);
// Misc
static void UpdateMouseInputs();
static void UpdateMouseWheel();
static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
static bool UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
static void RenderWindowOuterBorders(ImGuiWindow* window);
static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, bool handle_borders_and_resize_grips, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
@ -1174,7 +1174,7 @@ ImGuiStyle::ImGuiStyle()
TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
ScrollbarSize = 14.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
@ -2599,7 +2599,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
ViewportPos = ImVec2(FLT_MAX, FLT_MAX);
Pos = ImVec2(0.0f, 0.0f);
Size = SizeFull = ImVec2(0.0f, 0.0f);
SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f);
ContentSize = ContentSizeExplicit = ImVec2(0.0f, 0.0f);
WindowPadding = ImVec2(0.0f, 0.0f);
WindowRounding = 0.0f;
WindowBorderSize = 0.0f;
@ -3060,7 +3060,7 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
ImGuiWindow* window = GImGui->CurrentWindow;
if (wrap_pos_x == 0.0f)
wrap_pos_x = GetContentRegionMaxAbs().x;
wrap_pos_x = window->WorkRect.Max.x;
else if (wrap_pos_x > 0.0f)
wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
@ -3393,7 +3393,7 @@ static void ScaleWindow(ImGuiWindow* window, float scale)
window->Pos = ImFloor((window->Pos - origin) * scale + origin);
window->Size = ImFloor(window->Size * scale);
window->SizeFull = ImFloor(window->SizeFull * scale);
window->SizeContents = ImFloor(window->SizeContents * scale);
window->ContentSize = ImFloor(window->ContentSize * scale);
}
static bool IsWindowActiveAndVisible(ImGuiWindow* window)
@ -4965,8 +4965,8 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
window->DockId = settings->DockId;
window->DockOrder = settings->DockOrder;
}
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 CalcContentSize() doesn't return crazy values
if ((flags & ImGuiWindowFlags_AlwaysAutoResize) != 0)
{
@ -5033,28 +5033,31 @@ static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
return new_size;
}
static ImVec2 CalcSizeContents(ImGuiWindow* window)
static ImVec2 CalcContentSize(ImGuiWindow* window)
{
if (window->Collapsed)
if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
return window->SizeContents;
return window->ContentSize;
if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0)
return window->SizeContents;
return window->ContentSize;
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->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
sz.y = (float)(int)((window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.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
{
@ -5071,14 +5074,16 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
const int monitor_idx = window->ViewportAllowPlatformMonitorExtend;
if (monitor_idx >= 0 && monitor_idx < g.PlatformIO.Monitors.Size)
avail_size = g.PlatformIO.Monitors[monitor_idx].WorkSize;
ImVec2 size_auto_fit = ImClamp(size_contents, size_min, ImMax(size_min, avail_size - g.Style.DisplaySafeAreaPadding * 2.0f));
ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, avail_size - g.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))
bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - size_decorations.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar);
bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - size_decorations.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar);
if (will_have_scrollbar_x)
size_auto_fit.y += style.ScrollbarSize;
if (size_auto_fit_after_constraint.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar))
if (will_have_scrollbar_y)
size_auto_fit.x += style.ScrollbarSize;
return size_auto_fit;
}
@ -5086,20 +5091,10 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window)
{
ImVec2 size_contents = CalcSizeContents(window);
ImVec2 size_contents = CalcContentSize(window);
return CalcSizeAfterConstraint(window, CalcSizeAutoFit(window, size_contents));
}
float ImGui::GetWindowScrollMaxX(ImGuiWindow* window)
{
return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x));
}
float ImGui::GetWindowScrollMaxY(ImGuiWindow* window)
{
return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y));
}
static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges)
{
ImGuiContext& g = *GImGui;
@ -5107,7 +5102,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)
{
@ -5116,15 +5111,15 @@ 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->ContentSize.y + window->WindowPadding.y + g.Style.ItemSpacing.y)
target_y = window->ContentSize.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)
{
scroll.x = ImMin(scroll.x, ImGui::GetWindowScrollMaxX(window));
scroll.y = ImMin(scroll.y, ImGui::GetWindowScrollMaxY(window));
scroll.x = ImMin(scroll.x, window->ScrollMax.x);
scroll.y = ImMin(scroll.y, window->ScrollMax.y);
}
return scroll;
}
@ -5180,15 +5175,18 @@ static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_
}
// Handle resize for: Resize Grips, Borders, Gamepad
static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
// Return true when using auto-fit (double click on resize grip)
static bool ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
{
ImGuiContext& g = *GImGui;
ImGuiWindowFlags flags = window->Flags;
if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
return;
return false;
if (window->WasActive == false) // Early out to avoid running this code for e.g. an hidden implicit/fallback Debug window.
return;
return false;
bool ret_auto_fit = false;
const int resize_border_count = g.IO.ConfigWindowsResizeFromEdges ? 4 : 0;
const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
const float grip_hover_inner_size = (float)(int)(grip_draw_size * 0.75f);
@ -5222,6 +5220,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au
{
// Manual auto-fit when double-clicking
size_target = CalcSizeAfterConstraint(window, size_auto_fit);
ret_auto_fit = true;
ClearActiveID();
}
else if (held)
@ -5296,6 +5295,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au
window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
window->Size = window->SizeFull;
return ret_auto_fit;
}
static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& rect, const ImVec2& padding)
@ -5685,16 +5685,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();
}
window->ContentSizeExplicit = g.NextWindowData.ContentSizeVal;
else if (first_begin_of_the_frame)
{
window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
}
window->ContentSizeExplicit = ImVec2(0.0f, 0.0f);
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasWindowClass)
window->WindowClass = g.NextWindowData.WindowClass;
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed)
@ -5733,7 +5726,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS
// Update contents size from last frame for auto-fitting (or use explicit size)
window->SizeContents = CalcSizeContents(window);
window->ContentSize = CalcContentSize(window);
if (window->HiddenFramesCanSkipItems > 0)
window->HiddenFramesCanSkipItems--;
if (window->HiddenFramesCannotSkipItems > 0)
@ -5744,7 +5737,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->HiddenFramesCannotSkipItems = 1;
// Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
// We reset Size/SizeContents for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size.
// We reset Size/ContentSize for reappearing popups/tooltips early in this function, so further code won't be tempted to use the old size.
if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0)
{
window->HiddenFramesCannotSkipItems = 1;
@ -5754,7 +5747,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->Size.x = window->SizeFull.x = 0.f;
if (!window_size_y_set_by_api)
window->Size.y = window->SizeFull.y = 0.f;
window->SizeContents = ImVec2(0.f, 0.f);
window->ContentSize = ImVec2(0.f, 0.f);
}
}
@ -5767,8 +5760,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
SetCurrentWindow(window);
flags = window->Flags;
// 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)
// We read Style data after the call to UpdateSelectWindowViewport() which might be swapping the style.
if (flags & ImGuiWindowFlags_ChildWindow)
window->WindowBorderSize = style.ChildBorderSize;
else
@ -5804,24 +5798,37 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// SIZE
// Calculate auto-fit size, handle automatic resize
const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents);
ImVec2 size_full_modified(FLT_MAX, FLT_MAX);
const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->ContentSize);
bool use_current_size_for_scrollbar_x = window_just_created;
bool use_current_size_for_scrollbar_y = window_just_created;
if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
{
// Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc.
if (!window_size_x_set_by_api)
window->SizeFull.x = size_full_modified.x = size_auto_fit.x;
{
window->SizeFull.x = size_auto_fit.x;
use_current_size_for_scrollbar_x = true;
}
if (!window_size_y_set_by_api)
window->SizeFull.y = size_full_modified.y = size_auto_fit.y;
{
window->SizeFull.y = size_auto_fit.y;
use_current_size_for_scrollbar_y = true;
}
}
else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
{
// Auto-fit may only grow window during the first few frames
// We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
{
window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
use_current_size_for_scrollbar_x = true;
}
if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
window->SizeFull.y = size_full_modified.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
{
window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
use_current_size_for_scrollbar_y = true;
}
if (!window->Collapsed)
MarkIniSettingsDirty(window);
}
@ -5830,20 +5837,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull);
window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
// SCROLLBAR STATUS
// 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));
if (window->ScrollbarX && !window->ScrollbarY)
window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
}
// Decoration size
const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight();
// POSITION
@ -5949,7 +5944,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->Viewport->Flags = viewport_flags;
}
// Clamp position so window stays visible within its viewport or monitor
// Clamp position/size so window stays visible within its viewport or monitor
// Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
ImRect viewport_rect = window->Viewport->GetRect();
if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
@ -5978,10 +5973,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if (window->ViewportOwned)
window->WindowRounding = 0.0f;
// Apply scrolling
window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
// Apply window focus (new and reactivated windows are moved to front)
bool want_focus = false;
if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing))
@ -6001,7 +5992,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4
const float resize_grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
if (handle_borders_and_resize_grips && !window->Collapsed)
UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]);
if (UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]))
use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true;
window->ResizeBorderHeld = (signed char)border_held;
// Synchronize window --> viewport again and one last time (clamping and manual resize may have affected either)
@ -6017,14 +6009,23 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Save last known viewport position within the window itself (so it can be saved in .ini file and restored)
window->ViewportPos = window->Viewport->Pos;
// Default item width. Make it proportional to window size if window manually resizes
if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
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 scrollbar visibility (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.
// When we use InnerRect here we are intentionally reading last frame size, same for ScrollbarSizes values before we set them again.
ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - decoration_up_height);
ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + window->ScrollbarSizes;
ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f;
float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
//bool scrollbar_y_from_last_frame = window->ScrollbarY; // FIXME: May want to use that in the ScrollbarX expression? How many pros vs cons?
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
if (window->ScrollbarX && !window->ScrollbarY)
window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar);
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
}
// UPDATE RECTANGLES (1- THOSE NOT AFFECTED BY SCROLLING)
// Update various regions. Variables they depends on should be set above in this function.
@ -6035,31 +6036,24 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// - FindHoveredWindow() (w/ extra padding when border resize is enabled)
// - Begin() initial clipping rect for drawing window background and borders.
// - Begin() clipping whole child
ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect;
window->OuterRectClipped = window->Rect();
const ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect;
const ImRect outer_rect = window->Rect();
const ImRect title_bar_rect = window->TitleBarRect();
window->OuterRectClipped = outer_rect;
if (window->DockIsActive)
window->OuterRectClipped.Min.y += window->TitleBarHeight();
window->OuterRectClipped.ClipWith(host_rect);
// Inner rectangle
// Used by:
// Not affected by window border size. Used by:
// - InnerClipRect
// - NavScrollToBringItemIntoView()
// - NavUpdatePageUpPageDown()
// - Scrollbar()
const ImRect title_bar_rect = window->TitleBarRect();
window->InnerRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
window->InnerRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
window->InnerRect.Max.x = window->Pos.x + window->Size.x - ImMax(window->ScrollbarSizes.x, window->WindowBorderSize);
window->InnerRect.Max.y = window->Pos.y + window->Size.y - ImMax(window->ScrollbarSizes.y, window->WindowBorderSize);
// Work rectangle.
// Affected by window padding and border size. Used by:
// - Columns() for right-most edge
// - BeginTabBar() for right-most edge
window->WorkRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
window->WorkRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y);
window->WorkRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
window->WorkRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y);
window->InnerRect.Min.x = window->Pos.x;
window->InnerRect.Min.y = window->Pos.y + decoration_up_height;
window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x;
window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y;
// Inner clipping rectangle.
// Will extend a little bit outside the normal work region.
@ -6068,9 +6062,31 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
// Affected by window/frame border size. Used by:
// - Begin() initial clip rect
window->InnerClipRect = window->WorkRect;
float top_border_size = (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(ImFloor(window->WindowPadding.x * 0.5f), window->WindowBorderSize));
window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + top_border_size);
window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(ImFloor(window->WindowPadding.y * 0.5f), window->WindowBorderSize));
window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - window->WindowBorderSize);
window->InnerClipRect.ClipWithFull(host_rect);
// Default item width. Make it proportional to window size if window manually resizes
if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
else
window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f);
// SCROLLING
// Lock down maximum scrolling
// The value of ScrollMax are ahead from ScrollbarX/ScrollbarY which is intentionally using InnerRect from previous rect in order to accommodate
// for right/bottom aligned items without creating a scrollbar.
window->ScrollMax.x = ImMax(0.0f, window->ContentSize.x + window->WindowPadding.x * 2.0f - window->InnerRect.GetWidth());
window->ScrollMax.y = ImMax(0.0f, window->ContentSize.y + window->WindowPadding.y * 2.0f - window->InnerRect.GetHeight());
// Apply scrolling
window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
// DRAWING
// Setup draw list and outer clipping rectangle
@ -6102,30 +6118,42 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// UPDATE RECTANGLES (2- THOSE AFFECTED BY SCROLLING)
// Work rectangle.
// Affected by window padding and border size. Used by:
// - Columns() for right-most edge
// - TreeNode(), CollapsingHeader() for right-most edge
// - BeginTabBar() for right-most edge
const bool allow_scrollbar_x = !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar);
const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar);
const float work_rect_size_x = (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : ImMax(allow_scrollbar_x ? window->ContentSize.x : 0.0f, window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x));
const float work_rect_size_y = (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : ImMax(allow_scrollbar_y ? window->ContentSize.y : 0.0f, window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y));
window->WorkRect.Min.x = ImFloor(window->InnerRect.Min.x - window->Scroll.x + ImMax(window->WindowPadding.x, window->WindowBorderSize));
window->WorkRect.Min.y = ImFloor(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize));
window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x;
window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y;
// [LEGACY] Contents Region
// FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
// NB: WindowBorderSize is included in WindowPadding _and_ ScrollbarSizes so we need to cancel one out when we have both.
// FIXME-OBSOLETE: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
// Used by:
// - Mouse wheel scrolling
// - ... (many things)
// - Mouse wheel scrolling + many other things
window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x;
window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight();
window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x + ImMin(window->ScrollbarSizes.x, window->WindowBorderSize)));
window->ContentsRegionRect.Max.y = window->Pos.y - window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y + ImMin(window->ScrollbarSizes.y, window->WindowBorderSize)));
window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + decoration_up_height;
window->ContentsRegionRect.Max.x = window->ContentsRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x));
window->ContentsRegionRect.Max.y = window->ContentsRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y));
// Setup drawing context
// (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.)
window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
window->DC.GroupOffset.x = 0.0f;
window->DC.ColumnsOffset.x = 0.0f;
window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y);
window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, decoration_up_height + window->WindowPadding.y - window->Scroll.y);
window->DC.CursorPos = window->DC.CursorStartPos;
window->DC.CursorPosPrevLine = window->DC.CursorPos;
window->DC.CursorMaxPos = window->DC.CursorStartPos;
window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.NavHideHighlightOneFrame = false;
window->DC.NavHasScroll = (GetWindowScrollMaxY(window) > 0.0f);
window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f);
window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
window->DC.NavLayerActiveMaskNext = 0x00;
window->DC.MenuBarAppending = false;
@ -6920,16 +6948,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)
@ -6945,8 +6969,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 ContentSize calculation doesn't get affected.
window->DC.CursorStartPos += offset;
}
void ImGui::SetWindowPos(const ImVec2& pos, ImGuiCond cond)
@ -7107,11 +7133,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)
@ -7332,22 +7360,26 @@ void ImGui::SetCursorScreenPos(const ImVec2& pos)
float ImGui::GetScrollX()
{
return GImGui->CurrentWindow->Scroll.x;
ImGuiWindow* window = GImGui->CurrentWindow;
return window->Scroll.x;
}
float ImGui::GetScrollY()
{
return GImGui->CurrentWindow->Scroll.y;
ImGuiWindow* window = GImGui->CurrentWindow;
return window->Scroll.y;
}
float ImGui::GetScrollMaxX()
{
return GetWindowScrollMaxX(GImGui->CurrentWindow);
ImGuiWindow* window = GImGui->CurrentWindow;
return window->ScrollMax.x;
}
float ImGui::GetScrollMaxY()
{
return GetWindowScrollMaxY(GImGui->CurrentWindow);
ImGuiWindow* window = GImGui->CurrentWindow;
return window->ScrollMax.y;
}
void ImGui::SetScrollX(float scroll_x)
@ -7360,7 +7392,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;
}
@ -8380,7 +8412,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->ContentSize.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);
}
@ -8392,7 +8424,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->ContentSize.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);
}
@ -9403,9 +9435,8 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
window->DC.CurrentColumns = columns;
// Set state for first column
const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->WorkRect.Max.x - window->Pos.x);
columns->OffMinX = window->DC.Indent.x - g.Style.ItemSpacing.x; // Lock our horizontal range
columns->OffMaxX = ImMax(content_region_width - window->Scroll.x, columns->OffMinX + 1.0f);
columns->OffMinX = window->DC.Indent.x - g.Style.ItemSpacing.x;
columns->OffMaxX = ImMax(window->WorkRect.Max.x - window->Pos.x, columns->OffMinX + 1.0f);
columns->HostCursorPosY = window->DC.CursorPos.y;
columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x;
columns->HostClipRect = window->ClipRect;
@ -14442,7 +14473,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
return;
}
enum { RT_OuterRect, RT_OuterRectClipped, RT_InnerRect, RT_InnerClipRect, RT_WorkRect, RT_Contents, RT_ContentsRegionRect };
enum { RT_OuterRect, RT_OuterRectClipped, RT_InnerRect, RT_InnerClipRect, RT_WorkRect, RT_Contents, RT_ContentsRegionRect, RT_Count };
static bool show_windows_begin_order = false;
static bool show_windows_rects = false;
static int show_windows_rect_type = RT_WorkRect;
@ -14465,7 +14496,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->ContentSize); }
else if (rect_type == RT_ContentsRegionRect) { return window->ContentsRegionRect; }
IM_ASSERT(0);
return ImRect();
@ -14570,12 +14601,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
return;
ImGuiWindowFlags flags = window->Flags;
NodeDrawList(window, window->Viewport, window->DrawList, "DrawList");
ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y);
ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y);
ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags,
(flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "",
(flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "",
(flags & ImGuiWindowFlags_NoMouseInputs)? "NoMouseInputs":"", (flags & ImGuiWindowFlags_NoNavInputs) ? "NoNavInputs" : "", (flags & ImGuiWindowFlags_AlwaysAutoResize) ? "AlwaysAutoResize" : "");
ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetWindowScrollMaxX(window), window->Scroll.y, GetWindowScrollMaxY(window));
ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y);
ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
ImGui::BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems);
ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask);
@ -14691,11 +14722,18 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGui::Checkbox("Show windows rectangles", &show_windows_rects);
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12);
show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, "OuterRect\0" "OuterRectClipped\0" "InnerRect\0" "InnerClipRect\0" "WorkRect\0" "Contents\0" "ContentsRegionRect\0");
const char* rects_names[RT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Contents", "ContentsRegionRect" };
show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, rects_names, RT_Count);
if (show_windows_rects && g.NavWindow)
{
ImRect r = Funcs::GetRect(g.NavWindow, show_windows_rect_type);
ImGui::BulletText("'%s': (%.1f,%.1f) (%.1f,%.1f) Size (%.1f,%.1f)", g.NavWindow->Name, r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight());
ImGui::BulletText("'%s':", g.NavWindow->Name);
ImGui::Indent();
for (int n = 0; n < RT_Count; n++)
{
ImRect r = Funcs::GetRect(g.NavWindow, n);
ImGui::Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), rects_names[n]);
}
ImGui::Unindent();
}
ImGui::Checkbox("Show clipping rectangle when hovering ImDrawCmd node", &show_drawcmd_clip_rects);
ImGui::TreePop();

@ -282,7 +282,7 @@ namespace ImGui
IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc.
IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin()
IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Sizes will be rounded down. Use callback to apply non-trivial programmatic constraints.
IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). not including window decorations (title bar, menu bar, etc.). set an axis to 0.0f to leave it automatic. call before Begin()
IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ scrollable client area, which enforce the range of scrollbars). Not including window decorations (title bar, menu bar, etc.) nor WindowPadding. set an axis to 0.0f to leave it automatic. call before Begin()
IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin()
IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin()
IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. you may also use ImGuiWindowFlags_NoBackground.
@ -831,7 +831,7 @@ enum ImGuiTreeNodeFlags_
// Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiTreeNodeFlags_AllowOverlapMode = ImGuiTreeNodeFlags_AllowItemOverlap
, ImGuiTreeNodeFlags_AllowOverlapMode = ImGuiTreeNodeFlags_AllowItemOverlap // [renamed in 1.53]
#endif
};
@ -842,7 +842,7 @@ enum ImGuiSelectableFlags_
ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window
ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column)
ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too
ImGuiSelectableFlags_Disabled = 1 << 3 // Cannot be selected, display greyed out text
ImGuiSelectableFlags_Disabled = 1 << 3 // Cannot be selected, display grayed out text
};
// Flags for ImGui::BeginCombo()
@ -1178,7 +1178,8 @@ enum ImGuiStyleVar_
// Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiStyleVar_Count_ = ImGuiStyleVar_COUNT, ImGuiStyleVar_ChildWindowRounding = ImGuiStyleVar_ChildRounding
, ImGuiStyleVar_Count_ = ImGuiStyleVar_COUNT // [renamed in 1.60]
, ImGuiStyleVar_ChildWindowRounding = ImGuiStyleVar_ChildRounding // [renamed in 1.53]
#endif
};
@ -1223,7 +1224,7 @@ enum ImGuiColorEditFlags_
// Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex
, ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69]
#endif
};
@ -1244,7 +1245,7 @@ enum ImGuiMouseCursor_
// Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiMouseCursor_Count_ = ImGuiMouseCursor_COUNT
, ImGuiMouseCursor_Count_ = ImGuiMouseCursor_COUNT // [renamed in 1.60]
#endif
};
@ -1260,7 +1261,7 @@ enum ImGuiCond_
// Obsolete names (will be removed)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiSetCond_Always = ImGuiCond_Always, ImGuiSetCond_Once = ImGuiCond_Once, ImGuiSetCond_FirstUseEver = ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing = ImGuiCond_Appearing
, ImGuiSetCond_Always = ImGuiCond_Always, ImGuiSetCond_Once = ImGuiCond_Once, ImGuiSetCond_FirstUseEver = ImGuiCond_FirstUseEver, ImGuiSetCond_Appearing = ImGuiCond_Appearing // [renamed in 1.51]
#endif
};
@ -1628,7 +1629,6 @@ namespace ImGui
{
// OBSOLETED in 1.71 (from May 2019)
static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); }
// OBSOLETED in 1.70 (from May 2019)
static inline float GetContentRegionAvailWidth() { return GetContentRegionAvail().x; }
// OBSOLETED in 1.69 (from Mar 2019)
@ -1663,7 +1663,7 @@ namespace ImGui
static inline bool IsMouseHoveringAnyWindow() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); }
static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); }
}
typedef ImGuiInputTextCallback ImGuiTextEditCallback; // OBSOLETE in 1.63 (from Aug 2018): made the names consistent
typedef ImGuiInputTextCallback ImGuiTextEditCallback; // OBSOLETED in 1.63 (from Aug 2018): made the names consistent
typedef ImGuiInputTextCallbackData ImGuiTextEditCallbackData;
#endif
@ -2247,7 +2247,7 @@ struct ImFontAtlas
int CustomRectIds[1]; // Identifiers of custom texture rectangle used by ImFontAtlas/ImDrawList
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETE 1.67+
typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+
#endif
};
@ -2301,7 +2301,7 @@ struct ImFont
IMGUI_API void SetFallbackChar(ImWchar c);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
typedef ImFontGlyph Glyph; // OBSOLETE 1.52+
typedef ImFontGlyph Glyph; // OBSOLETED in 1.52+
#endif
};

@ -17,9 +17,18 @@
// In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, so it is
// essentially like a global variable but declared inside the scope of the function. We do this as a way to gather code and data
// in the same place, to make the demo source code faster to read, faster to write, and smaller in size.
// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant
// or used in threads. This might be a pattern you will want to use in your code, but most of the real data you would be editing is
// likely going to be stored outside your functions.
// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be
// reentrant or used in multiple threads. This might be a pattern you will want to use in your code, but most of the real data
// you would be editing is likely going to be stored outside your functions.
// The Demo code is this file is designed to be easy to copy-and-paste in into your application!
// Because of this:
// - We never omit the ImGui:: namespace when calling functions, even though most of our code is already in the same namespace.
// - We try to declare static variables in the local scope, as close as possible to the code using them.
// - We never use any of the helpers/facilities used internally by dear imgui, unless it has been exposed in the public API (imgui.h).
// - We never use maths operators on ImVec2/ImVec4. For other imgui sources files, they are provided by imgui_internal.h w/ IMGUI_DEFINE_MATH_OPERATORS,
// for your own sources file they are optional and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
// Because we don't want to assume anything about your support of maths operators, we don't use them in imgui_demo.cpp.
/*
@ -2108,14 +2117,21 @@ static void ShowDemoWindowLayout()
HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given position.");
static bool track = true;
static int track_line = 50, scroll_to_px = 200;
static int track_line = 50;
static float scroll_to_off_px = 0.0f;
static float scroll_to_pos_px = 200.0f;
ImGui::Checkbox("Track", &track);
ImGui::PushItemWidth(100);
ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %d");
bool scroll_to = ImGui::Button("Scroll To Pos");
ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %d px");
ImGui::SameLine(140); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %d");
bool scroll_to_off = ImGui::Button("Scroll Offset");
ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off_y", &scroll_to_off_px, 1.00f, 0, 9999, "+%.0f px");
bool scroll_to_pos = ImGui::Button("Scroll To Pos");
ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos_y", &scroll_to_pos_px, 1.00f, 0, 9999, "Y = %.0f px");
ImGui::PopItemWidth();
if (scroll_to)
if (scroll_to_off || scroll_to_pos)
track = false;
ImGuiStyle& style = ImGui::GetStyle();
@ -2125,9 +2141,13 @@ static void ShowDemoWindowLayout()
if (i > 0) ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(child_w, 200.0f), true);
if (scroll_to)
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
ImGuiWindowFlags child_flags = ImGuiWindowFlags_MenuBar;
ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(child_w, 200.0f), true, child_flags);
if (scroll_to_off)
ImGui::SetScrollY(scroll_to_off_px);
if (scroll_to_pos)
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
for (int line = 0; line < 100; line++)
{
if (track && line == track_line)
@ -2143,7 +2163,7 @@ static void ShowDemoWindowLayout()
float scroll_y = ImGui::GetScrollY();
float scroll_max_y = ImGui::GetScrollMaxY();
ImGui::EndChild();
ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
ImGui::EndGroup();
}
ImGui::TreePop();
@ -2193,6 +2213,97 @@ static void ShowDemoWindowLayout()
ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
ImGui::EndChild();
}
ImGui::Spacing();
static bool show_horizontal_contents_size_demo_window = false;
ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window);
if (show_horizontal_contents_size_demo_window)
{
static bool show_h_scrollbar = true;
static bool show_button = true;
static bool show_tree_nodes = true;
static bool show_text_wrapped = false;
static bool show_columns = true;
static bool show_tab_bar = true;
static bool show_child = false;
static bool explicit_content_size = false;
static float contents_size_x = 300.0f;
if (explicit_content_size)
ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten)
ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width
ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
ImGui::Checkbox("Columns", &show_columns); // Will use contents size
ImGui::Checkbox("Tab bar", &show_tab_bar); // Will use contents size
ImGui::Checkbox("Child", &show_child); // Will grow and use contents size
ImGui::Checkbox("Explicit content size", &explicit_content_size);
ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
if (explicit_content_size)
{
ImGui::SameLine();
ImGui::SetNextItemWidth(100);
ImGui::DragFloat("##csx", &contents_size_x);
ImVec2 p = ImGui::GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
ImGui::Dummy(ImVec2(0, 10));
}
ImGui::PopStyleVar(2);
ImGui::Separator();
if (show_button)
{
ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
}
if (show_tree_nodes)
{
bool open = true;
if (ImGui::TreeNode("this is a tree node"))
{
if (ImGui::TreeNode("another one of those tree node..."))
{
ImGui::Text("Some tree contents");
ImGui::TreePop();
}
ImGui::TreePop();
}
ImGui::CollapsingHeader("CollapsingHeader", &open);
}
if (show_text_wrapped)
{
ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
}
if (show_columns)
{
ImGui::Columns(4);
for (int n = 0; n < 4; n++)
{
ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
ImGui::NextColumn();
}
ImGui::Columns(1);
}
if (show_tab_bar && ImGui::BeginTabBar("Hello"))
{
if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
ImGui::EndTabBar();
}
if (show_child)
{
ImGui::BeginChild("child", ImVec2(0,0), true);
ImGui::EndChild();
}
ImGui::End();
}
ImGui::TreePop();
}

@ -1327,7 +1327,7 @@ struct IMGUI_API ImGuiWindowTempData
ImVec2 CursorPos;
ImVec2 CursorPosPrevLine;
ImVec2 CursorStartPos; // Initial position in client area with padding
ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Turned into window->SizeContents at the beginning of next frame
ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Used to calculate window->ContentSize at the beginning of next frame
ImVec2 CurrLineSize;
ImVec2 PrevLineSize;
float CurrLineTextBaseOffset;
@ -1415,9 +1415,8 @@ struct IMGUI_API ImGuiWindow
ImVec2 Pos; // Position (always rounded-up to nearest pixel)
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
ImVec2 SizeFull; // Size when non collapsed
ImVec2 SizeFullAtLastBegin; // Copy of SizeFull at the end of Begin. This is the reference value we'll use on the next frame to decide if we need scrollbars.
ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame. FIXME: Include decoration, window title, border, menu, etc. Ideally should remove them from this value?
ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize(). EXCLUDE decorations. Making this not consistent with the above!
ImVec2 ContentSize; // Size of contents/scrollable client area (calculated from the extents reach of the cursor) from previous frame. Does not include window decoration or window padding.
ImVec2 ContentSizeExplicit; // Size of contents/scrollable client area explicitly request by the user via SetNextWindowContentSize().
ImVec2 WindowPadding; // Window padding at the time of begin.
float WindowRounding; // Window rounding at the time of begin.
float WindowBorderSize; // Window border size at the time of begin.
@ -1425,6 +1424,7 @@ struct IMGUI_API ImGuiWindow
ImGuiID MoveId; // == window->GetID("#MOVE")
ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window)
ImVec2 Scroll;
ImVec2 ScrollMax;
ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered
ImVec2 ScrollbarSizes; // Size taken by scrollbars on each axis
@ -1459,13 +1459,17 @@ struct IMGUI_API ImGuiWindow
ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name.
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
ImRect ClipRect; // Current clipping rectangle. = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
ImRect OuterRectClipped; // == WindowRect just after setup in Begin(). == window->Rect() for root window.
ImRect InnerRect; // Inner rectangle
ImRect InnerClipRect; // == InnerRect minus WindowPadding.x, clipped within viewport or parent clip rect.
ImRect WorkRect; // == InnerRect minus WindowPadding.x
ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. Maximum visible content position ~~ Pos + (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis
// The best way to understand what those rectangles are is to use the 'Metrics -> Tools -> Show windows rectangles' viewer.
// The main 'OuterRect', omitted as a field, is window->Rect().
ImRect OuterRectClipped; // == Window->Rect() just after setup in Begin(). == window->Rect() for root window.
ImRect InnerRect; // Inner rectangle (omit title bar, menu bar)
ImRect InnerClipRect; // == InnerRect shrunk by WindowPadding*0.5f on each side, clipped within viewport or parent clip rect.
ImRect WorkRect; // Cover the whole scrolling region, shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentsRegionRect over time (from 1.71+ onward).
ImRect ClipRect; // Current clipping/scissoring rectangle, evolve as we are using PushClipRect(), etc. == DrawList->clip_rect_stack.back().
ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on.
ImVec2ih HitTestHoleSize, HitTestHoleOffset;
int LastFrameActive; // Last frame number the window was Active.
int LastFrameJustFocused; // Last frame number the window was made Focused.
float ItemWidthDefault;
@ -1631,8 +1635,6 @@ namespace ImGui
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
IMGUI_API void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x);
IMGUI_API void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y);
IMGUI_API float GetWindowScrollMaxX(ImGuiWindow* window);
IMGUI_API float GetWindowScrollMaxY(ImGuiWindow* window);
IMGUI_API ImRect GetWindowAllowedExtentRect(ImGuiWindow* window);
IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0);
IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0);

@ -878,7 +878,7 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
}
// Apply scroll
// It is ok to modify Scroll here because we are being called in Begin() after the calculation of SizeContents and before setting up our starting position
// It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position
const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
*p_scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
@ -914,22 +914,26 @@ void ImGui::Scrollbar(ImGuiAxis axis)
// Calculate scrollbar bounding box
const ImRect outer_rect = window->Rect();
const ImRect inner_rect = window->InnerRect;
const float border_size = window->WindowBorderSize;
const float scrollbar_size = window->ScrollbarSizes[axis ^ 1];
IM_ASSERT(scrollbar_size > 0.0f);
const float other_scrollbar_size = window->ScrollbarSizes[axis];
ImDrawCornerFlags rounding_corners = (other_scrollbar_size <= 0.0f) ? ImDrawCornerFlags_BotRight : 0;
ImRect bb;
if (axis == ImGuiAxis_X)
{
bb.Min = ImVec2(window->InnerRect.Min.x, window->InnerRect.Max.y);
bb.Max = ImVec2(window->InnerRect.Max.x, outer_rect.Max.y - window->WindowBorderSize);
bb.Min = ImVec2(inner_rect.Min.x, outer_rect.Max.y - border_size - scrollbar_size);
bb.Max = ImVec2(inner_rect.Max.x, outer_rect.Max.y);
rounding_corners |= ImDrawCornerFlags_BotLeft;
}
else
{
bb.Min = ImVec2(window->InnerRect.Max.x, window->InnerRect.Min.y);
bb.Max = ImVec2(outer_rect.Max.x - window->WindowBorderSize, window->InnerRect.Max.y);
bb.Min = ImVec2(outer_rect.Max.x - border_size - scrollbar_size, inner_rect.Min.y);
bb.Max = ImVec2(outer_rect.Max.x, window->InnerRect.Max.y);
rounding_corners |= ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0;
}
ScrollbarEx(bb, id, axis, &window->Scroll[axis], window->SizeFull[axis] - other_scrollbar_size, window->SizeContents[axis], rounding_corners);
ScrollbarEx(bb, id, axis, &window->Scroll[axis], inner_rect.Max[axis] - inner_rect.Min[axis], window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f, rounding_corners);
}
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
@ -5161,12 +5165,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
// We vertically grow up to current line height up the typical widget height.
const float text_base_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(GetContentRegionMaxAbs().x, window->DC.CursorPos.y + frame_height));
ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->WorkRect.Max.x, window->DC.CursorPos.y + frame_height));
if (display_frame)
{
// Framed header expand a little outside the default padding
frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f) - 1;
frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f) - 1;
frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f - 1.0f);
frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f - 1.0f);
}
const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing
@ -6360,7 +6364,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
tab_bar->FramePadding = g.Style.FramePadding;
// Layout
ItemSize(ImVec2(tab_bar->OffsetMax, tab_bar->BarRect.GetHeight()));
ItemSize(ImVec2(0.0f /*tab_bar->OffsetMax*/, tab_bar->BarRect.GetHeight())); // Don't feed width back
window->DC.CursorPos.x = tab_bar->BarRect.Min.x;
// Draw separator
@ -6374,8 +6378,8 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
}
else
{
const float separator_min_x = tab_bar->BarRect.Min.x - window->WindowPadding.x;
const float separator_max_x = tab_bar->BarRect.Max.x + window->WindowPadding.x;
const float separator_min_x = tab_bar->BarRect.Min.x - ImFloor(window->WindowPadding.x * 0.5f);
const float separator_max_x = tab_bar->BarRect.Max.x + ImFloor(window->WindowPadding.x * 0.5f);
window->DrawList->AddLine(ImVec2(separator_min_x, y), ImVec2(separator_max_x, y), col, 1.0f);
}
return true;
@ -6504,7 +6508,8 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
}
// Compute width
const float width_avail = tab_bar->BarRect.GetWidth();
const float initial_offset_x = 0.0f; // g.Style.ItemInnerSpacing.x;
const float width_avail = ImMax(tab_bar->BarRect.GetWidth() - initial_offset_x, 0.0f);
float width_excess = (width_avail < width_total_contents) ? (width_total_contents - width_avail) : 0.0f;
if (width_excess > 0.0f && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown))
{
@ -6524,7 +6529,8 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
}
// Layout all active tabs
float offset_x = 0.0f;
float offset_x = initial_offset_x;
tab_bar->OffsetNextTab = offset_x; // This is used by non-reorderable tab bar where the submission order is always honored.
for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
{
ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
@ -6534,7 +6540,6 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
offset_x += tab->Width + g.Style.ItemInnerSpacing.x;
}
tab_bar->OffsetMax = ImMax(offset_x - g.Style.ItemInnerSpacing.x, 0.0f);
tab_bar->OffsetNextTab = 0.0f;
// Horizontal scrolling buttons
const bool scrolling_buttons = (tab_bar->OffsetMax > tab_bar->BarRect.GetWidth() && tab_bar->Tabs.Size > 1) && !(tab_bar->Flags & ImGuiTabBarFlags_NoTabListScrollingButtons) && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll);
@ -6962,7 +6967,10 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
if (want_clip_rect)
PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->BarRect.Min.x), bb.Min.y - 1), ImVec2(tab_bar->BarRect.Max.x, bb.Max.y), true);
ItemSize(bb, style.FramePadding.y);
ImVec2 backup_cursor_max_pos = window->DC.CursorMaxPos;
ItemSize(bb.GetSize(), style.FramePadding.y);
window->DC.CursorMaxPos = backup_cursor_max_pos;
if (!ItemAdd(bb, id))
{
if (want_clip_rect)

Loading…
Cancel
Save