1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-11-15 11:33:29 +01:00

Merge branch 'master' into docking

# Conflicts:
#	docs/CHANGELOG.txt
#	imgui.cpp
This commit is contained in:
omar 2019-05-10 22:56:43 +02:00
commit 835a8b2c9b
10 changed files with 462 additions and 380 deletions

View File

@ -28,6 +28,19 @@ HOW TO UPDATE?
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users. and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
- Please report any issue! - Please report any issue!
-----------------------------------------------------------------------
VERSION 1.71 (In Progress)
-----------------------------------------------------------------------
Breaking Changes:
Other Changes:
- 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
but it breaks existing some layout patterns. Will return back to it when we expose Separator flags.
- Scrollbar: Very minor bounding box adjustment to cope with various border size.
----------------------------------------------------------------------- -----------------------------------------------------------------------
DOCKING BRANCH (In Progress) DOCKING BRANCH (In Progress)
@ -94,7 +107,7 @@ Other changes:
----------------------------------------------------------------------- -----------------------------------------------------------------------
VERSION 1.70 WIP (In Progress) VERSION 1.70 (Released 2019-05-06)
----------------------------------------------------------------------- -----------------------------------------------------------------------
Breaking Changes: Breaking Changes:

View File

@ -28,6 +28,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- window: investigate better auto-positioning for new windows. - window: investigate better auto-positioning for new windows.
- window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. -> this may require enforcing that it is illegal to submit contents if Begin returns false. - window/opt: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. -> this may require enforcing that it is illegal to submit contents if Begin returns false.
- window/child: the first draw command of a child window could be moved into the current draw command of the parent window (unless child+tooltip?). - window/child: the first draw command of a child window could be moved into the current draw command of the parent window (unless child+tooltip?).
- window/child: border could be emitted in parent as well.
- window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero. - window/clipping: some form of clipping when DisplaySize (or corresponding viewport) is zero.
- window/tab: add a way to signify that a window or docked window requires attention (e.g. blinking title bar). - window/tab: add a way to signify that a window or docked window requires attention (e.g. blinking title bar).
- scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse) - scrolling: while holding down a scrollbar, try to keep the same contents visible (at least while not moving mouse)
@ -66,6 +67,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- widgets: a way to represent "mixed" values, so e.g. all values replaced with **, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed) - widgets: a way to represent "mixed" values, so e.g. all values replaced with **, including check-boxes, colors, etc. with support for multi-components widgets (e.g. SliderFloat3, make only "Y" mixed)
- widgets: selectable: generic BeginSelectable()/EndSelectable() mechanism. - widgets: selectable: generic BeginSelectable()/EndSelectable() mechanism.
- widgets: selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection) - widgets: selectable: a way to visualize partial/mixed selection (e.g. parent tree node has children with mixed selection)
- widgets: checkbox with custom glyph inside frame.
- input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now and super fragile. - 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) - input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
@ -132,7 +134,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- clipper: ability to disable the clipping through a simple flag/bool. - clipper: ability to disable the clipping through a simple flag/bool.
- clipper: ability to run without knowing full count in advance. - clipper: ability to run without knowing full count in advance.
- splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319) - separator: expose flags (#759)
- separator: width, thickness, centering (#1643)
- splitter: formalize the splitter idiom into an official api (we want to handle n-way split) (#319)
- dock: merge docking branch (#2109) - dock: merge docking branch (#2109)
- dock: B: ordering currently held in tab bar should be implicitly held by windows themselves (also see #2304) - dock: B: ordering currently held in tab bar should be implicitly held by windows themselves (also see #2304)
@ -197,6 +201,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- listbox: keyboard navigation. - listbox: keyboard navigation.
- listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681) - listbox: disable capturing mouse wheel if the listbox has no scrolling. (#1681)
- listbox: scrolling should track modified selection. - listbox: scrolling should track modified selection.
- listbox: future api should allow to enable horizontal scrolling (#2510)
!- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402) !- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402)
- popups/modal: make modal title bar blink when trying to click outside the modal - popups/modal: make modal title bar blink when trying to click outside the modal
@ -263,15 +268,19 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb) - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb)
- drag and drop: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers. - drag and drop: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers.
- drag and drop: fix/support/options for overlapping drag sources.
- drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725) - drag and drop: releasing a drop shows the "..." tooltip for one frame - since e13e598 (#1725)
- drag and drop: drag source on a group object (would need e.g. an invisible button covering group in EndGroup) https://twitter.com/paniq/status/1121446364909535233
- drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov. - drag and drop: have some way to know when a drag begin from BeginDragDropSource() pov.
- drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725) - drag and drop: allow preview tooltip to be submitted from a different place than the drag source. (#1725)
- drag and drop: allow using with other mouse buttons (where activeid won't be set). (#1637) - drag and drop: allow using with other mouse buttons (where activeid won't be set). (#1637)
- drag and drop: make it easier and provide a demo to have tooltip both are source and target site, with a more detailed one on target site (tooltip ordering problem) - drag and drop: make it easier and provide a demo to have tooltip both are source and target site, with a more detailed one on target site (tooltip ordering problem)
- drag and drop: test with reordering nodes (in a list, or a tree node). (#143) - drag and drop: demo with reordering nodes (in a list, or a tree node). (#143)
- drag and drop: test integrating with os drag and drop (make it easy to do a naive WM_DROPFILE integration) - drag and drop: test integrating with os drag and drop (make it easy to do a naive WM_DROPFILE integration)
- drag and drop: allow for multiple payload types. (#143)
- drag and drop: make payload optional? (#143) - drag and drop: make payload optional? (#143)
- drag and drop: feedback when hovering a modal (cursor?) - drag and drop: (#143) "both an in-process pointer and a promise to generate a serialized version, for whether the drag ends inside or outside the same process"
- drag and drop: feedback when hovering a region blocked by modal (mouse cursor "NO"?)
- node/graph editor (#306) - node/graph editor (#306)
- pie menus patterns (#434) - pie menus patterns (#434)
- markup: simple markup language for color change? (#902) - markup: simple markup language for color change? (#902)
@ -294,6 +303,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- font/draw: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise - font/draw: vertical and/or rotated text renderer (#705) - vertical is easier clipping wise
- font/draw: need to be able to specify wrap start position. - font/draw: need to be able to specify wrap start position.
- font/draw: better reserve policy for large horizontal block of text (shouldn't reserve for all clipped lines) - font/draw: better reserve policy for large horizontal block of text (shouldn't reserve for all clipped lines)
- font/draw: underline, squiggle line rendering helpers.
- font: optimization: for monospace font (like the default one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance (need to make sure TAB is still correct), would save on cache line. - font: optimization: for monospace font (like the default one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance (need to make sure TAB is still correct), would save on cache line.
- font: add support for kerning, probably optional. A) perhaps default to (32..128)^2 matrix ~ 9K entries = 36KB, then hash for non-ascii?. B) or sparse lookup into per-char list? - font: add support for kerning, probably optional. A) perhaps default to (32..128)^2 matrix ~ 9K entries = 36KB, then hash for non-ascii?. B) or sparse lookup into per-char list?
- font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize) - font: add a simpler CalcTextSizeA() api? current one ok but not welcome if user needs to call it directly (without going through ImGui::CalcTextSize)
@ -351,6 +361,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- inputs: support track pad style scrolling & slider edit. - inputs: support track pad style scrolling & slider edit.
- inputs/io: backspace and arrows in the context of a text input could use system repeat rate. - inputs/io: backspace and arrows in the context of a text input could use system repeat rate.
- inputs/io: clarify/standardize/expose repeat rate and repeat delays (#1808) - inputs/io: clarify/standardize/expose repeat rate and repeat delays (#1808)
- inputs: add mouse cursor for unavailable/no? IDC_NO/SDL_SYSTEM_CURSOR_NO.
- misc: idle: expose "woken up" boolean (set by inputs) and/or animation time (for cursor blink) for back-end to be able stop refreshing easily. - misc: idle: expose "woken up" boolean (set by inputs) and/or animation time (for cursor blink) for back-end to be able stop refreshing easily.
- misc: idle: if cursor blink if the _only_ visible animation, core imgui could rewrite vertex alpha to avoid CPU pass on ImGui:: calls. - misc: idle: if cursor blink if the _only_ visible animation, core imgui could rewrite vertex alpha to avoid CPU pass on ImGui:: calls.
@ -368,6 +379,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- remote: make a system like RemoteImGui first-class citizen/project (#75) - remote: make a system like RemoteImGui first-class citizen/project (#75)
- demo: find a way to demonstrate textures in the examples application, as it such a common issue for new users. - demo: find a way to demonstrate textures in the examples application, as it such a common issue for new users.
- demo: demonstrate using PushStyleVar() in more details.
- demo: add vertical separator demo - demo: add vertical separator demo
- demo: add virtual scrolling example? - demo: add virtual scrolling example?
- demo: demonstrate Plot offset - demo: demonstrate Plot offset

View File

@ -1,5 +1,5 @@
----------------------------------------------------------------------- -----------------------------------------------------------------------
dear imgui, v1.70 WIP dear imgui, v1.71 WIP
----------------------------------------------------------------------- -----------------------------------------------------------------------
examples/README.txt examples/README.txt
(This is the README file for the examples/ folder. See docs/ for more documentation) (This is the README file for the examples/ folder. See docs/ for more documentation)
@ -182,7 +182,7 @@ example_empscripten:
We provide this to make the Emscripten differences obvious, and have them not pollute all other examples. We provide this to make the Emscripten differences obvious, and have them not pollute all other examples.
example_glfw_metal/ example_glfw_metal/
GLFW (Mac) + Vulkan example. GLFW (Mac) + Metal example.
= main.mm + imgui_impl_glfw.cpp + imgui_impl_metal.mm. = main.mm + imgui_impl_glfw.cpp + imgui_impl_metal.mm.
example_glfw_opengl2/ example_glfw_opengl2/

469
imgui.cpp
View File

@ -1,4 +1,4 @@
// dear imgui, v1.70 WIP // dear imgui, v1.71 WIP
// (main code and documentation) // (main code and documentation)
// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code.
@ -1089,7 +1089,9 @@ static int FindWindowFocusIndex(ImGuiWindow* window);
static void UpdateMouseInputs(); static void UpdateMouseInputs();
static void UpdateMouseWheel(); 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 void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
static void RenderOuterBorders(ImGuiWindow* window); 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);
static void EndFrameDrawDimmedBackgrounds(); static void EndFrameDrawDimmedBackgrounds();
// Viewports // Viewports
@ -1168,7 +1170,7 @@ ImGuiStyle::ImGuiStyle()
ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
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! 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). 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 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 = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
@ -5269,7 +5271,7 @@ static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& rect, cons
window->Pos = ImMin(rect.Max - padding, ImMax(window->Pos + size_for_clamping, rect.Min + padding) - size_for_clamping); window->Pos = ImMin(rect.Max - padding, ImMax(window->Pos + size_for_clamping, rect.Min + padding) - size_for_clamping);
} }
static void ImGui::RenderOuterBorders(ImGuiWindow* window) static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
float rounding = window->WindowRounding; float rounding = window->WindowRounding;
@ -5306,6 +5308,170 @@ static void ImGui::RenderOuterBorders(ImGuiWindow* window)
} }
} }
void ImGui::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)
{
ImGuiContext& g = *GImGui;
ImGuiStyle& style = g.Style;
ImGuiWindowFlags flags = window->Flags;
// Draw window + handle manual resize
// As we highlight the title bar when want_focus is set, multiple reappearing windows will have have their title bar highlighted on their reappearing frame.
const float window_rounding = window->WindowRounding;
const float window_border_size = window->WindowBorderSize;
if (window->Collapsed)
{
// Title bar only
float backup_border_size = style.FrameBorderSize;
g.Style.FrameBorderSize = window->WindowBorderSize;
ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding);
g.Style.FrameBorderSize = backup_border_size;
}
else
{
// Window background
if (!(flags & ImGuiWindowFlags_NoBackground))
{
bool is_docking_transparent_payload = false;
if (g.DragDropActive && (g.FrameCount - g.DragDropAcceptFrameCount) <= 1 && g.IO.ConfigDockingTransparentPayload)
if (g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && *(ImGuiWindow**)g.DragDropPayload.Data == window)
is_docking_transparent_payload = true;
ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags));
if (window->ViewportOwned)
{
// No alpha
bg_col = (bg_col | IM_COL32_A_MASK);
if (is_docking_transparent_payload)
window->Viewport->Alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
}
else
{
// Adjust alpha. For docking
float alpha = 1.0f;
if (g.NextWindowData.BgAlphaCond != 0)
alpha = g.NextWindowData.BgAlphaVal;
if (is_docking_transparent_payload)
alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
if (alpha != 1.0f)
bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
}
window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
}
g.NextWindowData.BgAlphaCond = 0;
// Title bar
// (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,
// in order for their pos/size to be matching their undocking state.)
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top);
}
// Menu bar
if (flags & ImGuiWindowFlags_MenuBar)
{
ImRect menu_bar_rect = window->MenuBarRect();
menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
window->DrawList->AddRectFilled(menu_bar_rect.Min + ImVec2(window_border_size, 0), menu_bar_rect.Max - ImVec2(window_border_size, 0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top);
if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
}
// Docking: Unhide tab bar (small triangle in the corner)
if (window->DockNode && window->DockNode->IsHiddenTabBar() && !window->DockNode->IsNoTabBar())
{
float unhide_sz_draw = ImFloor(g.FontSize * 0.70f);
float unhide_sz_hit = ImFloor(g.FontSize * 0.55f);
ImVec2 p = window->DockNode->Pos;
ImRect r(p, p + ImVec2(unhide_sz_hit, unhide_sz_hit));
bool hovered, held;
if (ButtonBehavior(r, window->GetID("#UNHIDE"), &hovered, &held, ImGuiButtonFlags_FlattenChildren))
window->DockNode->WantHiddenTabBarToggle = true;
// FIXME-DOCK: Ideally we'd use ImGuiCol_TitleBgActive/ImGuiCol_TitleBg here, but neither is guaranteed to be visible enough at this sort of size..
ImU32 col = GetColorU32(((held && hovered) || (window->DockNode->IsFocused && !hovered)) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
window->DrawList->AddTriangleFilled(p, p + ImVec2(unhide_sz_draw, 0.0f), p + ImVec2(0.0f, unhide_sz_draw), col);
}
// Scrollbars
if (window->ScrollbarX)
Scrollbar(ImGuiAxis_X);
if (window->ScrollbarY)
Scrollbar(ImGuiAxis_Y);
// Render resize grips (after their input handling so we don't have a frame of latency)
if (handle_borders_and_resize_grips && !(flags & ImGuiWindowFlags_NoResize))
{
for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
{
const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_grip_draw_size) : ImVec2(resize_grip_draw_size, window_border_size)));
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_grip_draw_size, window_border_size) : ImVec2(window_border_size, resize_grip_draw_size)));
window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
}
}
// Borders (for dock node host they will be rendered over after the tab bar)
if (handle_borders_and_resize_grips && !window->DockNodeAsHost)
RenderWindowOuterBorders(window);
}
}
void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open)
{
ImGuiContext& g = *GImGui;
ImGuiStyle& style = g.Style;
ImGuiWindowFlags flags = window->Flags;
// Close & collapse button are on layer 1 (same as menus) and don't default focus
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
// Collapse button
if (!(flags & ImGuiWindowFlags_NoCollapse))
if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos, NULL))
window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function
// Close button
if (p_open != NULL)
{
const float rad = g.FontSize * 0.5f;
if (CloseButton(window->GetID("#CLOSE"), ImVec2(window->Pos.x + window->Size.x - style.FramePadding.x - rad, window->Pos.y + style.FramePadding.y + rad), rad + 1))
*p_open = false;
}
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
window->DC.ItemFlags = item_flags_backup;
// Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
// FIXME: Refactor text alignment facilities along with RenderText helpers, this is too much code..
const char* UNSAVED_DOCUMENT_MARKER = "*";
float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
ImRect text_r = title_bar_rect;
float pad_left = (flags & ImGuiWindowFlags_NoCollapse) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
float pad_right = (p_open == NULL) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
if (style.WindowTitleAlign.x > 0.0f)
pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x);
text_r.Min.x += pad_left;
text_r.Max.x -= pad_right;
ImRect clip_rect = text_r;
clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton()
RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect);
if (flags & ImGuiWindowFlags_UnsavedDocument)
{
ImVec2 marker_pos = ImVec2(ImMax(text_r.Min.x, text_r.Min.x + (text_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, text_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f));
RenderTextClipped(marker_pos + off, text_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_rect);
}
}
void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window) void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
{ {
window->ParentWindow = parent_window; window->ParentWindow = parent_window;
@ -5325,7 +5491,7 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags
} }
} }
// Push a new ImGui window to add widgets to. // Push a new Dear ImGui window to add widgets to.
// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
// - Begin/End can be called multiple times during the frame with the same window name to append content. // - Begin/End can be called multiple times during the frame with the same window name to append content.
// - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file). // - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file).
@ -5762,7 +5928,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
int border_held = -1; int border_held = -1;
ImU32 resize_grip_col[4] = { 0 }; ImU32 resize_grip_col[4] = { 0 };
const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4 const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // 4
const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); 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) if (handle_borders_and_resize_grips && !window->Collapsed)
UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]); UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]);
window->ResizeBorderHeld = (signed char)border_held; window->ResizeBorderHeld = (signed char)border_held;
@ -5786,6 +5952,41 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
else else
window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f); 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
// Update various regions. Variables they depends on are set above in this function.
// 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.
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)));
// Save clipped aabb so we can access it in constant-time in FindHoveredWindow()
window->OuterRectClipped = window->Rect();
if (window->DockIsActive)
window->OuterRectClipped.Min.y += window->TitleBarHeight();
window->OuterRectClipped.ClipWith(window->ClipRect);
// Inner rectangle
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
// Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
const ImRect title_bar_rect = window->TitleBarRect();
window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - ImMax(window->ScrollbarSizes.x, window->WindowBorderSize);
window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - ImMax(window->ScrollbarSizes.y, window->WindowBorderSize);
// Inner clipping rectangle
// Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y);
window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y);
// DRAWING // DRAWING
// Setup draw list and outer clipping rectangle // Setup draw list and outer clipping rectangle
@ -5815,145 +6016,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding); window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding);
} }
// Draw window + handle manual resize
// As we highlight the title bar when want_focus is set, multiple reappearing windows will have have their title bar highlighted on their reappearing frame.
const float window_rounding = window->WindowRounding;
const float window_border_size = window->WindowBorderSize;
const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow; const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow;
const bool title_bar_is_highlight = want_focus || (window_to_highlight && (window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight || (window->DockNode && window->DockNode == window_to_highlight->DockNode))); const bool title_bar_is_highlight = want_focus || (window_to_highlight && (window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight || (window->DockNode && window->DockNode == window_to_highlight->DockNode)));
const ImRect title_bar_rect = window->TitleBarRect(); RenderWindowDecorations(window, title_bar_rect, title_bar_is_highlight, handle_borders_and_resize_grips, resize_grip_count, resize_grip_col, resize_grip_draw_size);
if (window->Collapsed)
{
// Title bar only
float backup_border_size = style.FrameBorderSize;
g.Style.FrameBorderSize = window->WindowBorderSize;
ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed);
RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding);
g.Style.FrameBorderSize = backup_border_size;
}
else
{
// Window background
if (!(flags & ImGuiWindowFlags_NoBackground))
{
bool is_docking_transparent_payload = false;
if (g.DragDropActive && (g.FrameCount - g.DragDropAcceptFrameCount) <= 1 && g.IO.ConfigDockingTransparentPayload)
if (g.DragDropPayload.IsDataType(IMGUI_PAYLOAD_TYPE_WINDOW) && *(ImGuiWindow**)g.DragDropPayload.Data == window)
is_docking_transparent_payload = true;
ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags));
if (window->ViewportOwned)
{
// No alpha
bg_col = (bg_col | IM_COL32_A_MASK);
if (is_docking_transparent_payload)
window->Viewport->Alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
}
else
{
// Adjust alpha. For docking
float alpha = 1.0f;
if (g.NextWindowData.BgAlphaCond != 0)
alpha = g.NextWindowData.BgAlphaVal;
if (is_docking_transparent_payload)
alpha *= DOCKING_TRANSPARENT_PAYLOAD_ALPHA;
if (alpha != 1.0f)
bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(alpha) << IM_COL32_A_SHIFT);
}
window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
}
g.NextWindowData.BgAlphaCond = 0;
// Title bar
// (when docked, DockNode are drawing their own title bar. Individual windows however do NOT set the _NoTitleBar flag,
// in order for their pos/size to be matching their undocking state.)
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{
ImU32 title_bar_col = GetColorU32(title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg);
window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top);
}
// Menu bar
if (flags & ImGuiWindowFlags_MenuBar)
{
ImRect menu_bar_rect = window->MenuBarRect();
menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
window->DrawList->AddRectFilled(menu_bar_rect.Min+ImVec2(window_border_size,0), menu_bar_rect.Max-ImVec2(window_border_size,0), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top);
if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
}
// Docking: Unhide tab bar (small triangle in the corner)
if (window->DockNode && window->DockNode->IsHiddenTabBar() && !window->DockNode->IsNoTabBar())
{
float unhide_sz_draw = ImFloor(g.FontSize * 0.70f);
float unhide_sz_hit = ImFloor(g.FontSize * 0.55f);
ImVec2 p = window->DockNode->Pos;
ImRect r(p, p + ImVec2(unhide_sz_hit, unhide_sz_hit));
bool hovered, held;
if (ButtonBehavior(r, window->GetID("#UNHIDE"), &hovered, &held, ImGuiButtonFlags_FlattenChildren))
window->DockNode->WantHiddenTabBarToggle = true;
// FIXME-DOCK: Ideally we'd use ImGuiCol_TitleBgActive/ImGuiCol_TitleBg here, but neither is guaranteed to be visible enough at this sort of size..
ImU32 col = GetColorU32(((held && hovered) || (window->DockNode->IsFocused && !hovered)) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
window->DrawList->AddTriangleFilled(p, p + ImVec2(unhide_sz_draw, 0.0f), p + ImVec2(0.0f, unhide_sz_draw), col);
}
// Scrollbars
if (window->ScrollbarX)
Scrollbar(ImGuiAxis_X);
if (window->ScrollbarY)
Scrollbar(ImGuiAxis_Y);
// Render resize grips (after their input handling so we don't have a frame of latency)
if (handle_borders_and_resize_grips && !(flags & ImGuiWindowFlags_NoResize))
{
for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++)
{
const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n];
const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, grip_draw_size) : ImVec2(grip_draw_size, window_border_size)));
window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(grip_draw_size, window_border_size) : ImVec2(window_border_size, grip_draw_size)));
window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
}
}
// Borders (for dock node host they will be rendered over after the tab bar)
if (handle_borders_and_resize_grips && !window->DockNodeAsHost)
RenderOuterBorders(window);
}
// Store a backup of SizeFull which we will use next frame to decide if we need scrollbars.
window->SizeFullAtLastBegin = window->SizeFull;
// Update various regions. Variables they depends on are set above in this function.
// 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.
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)));
// Save clipped aabb so we can access it in constant-time in FindHoveredWindow()
window->OuterRectClipped = window->Rect();
if (window->DockIsActive)
window->OuterRectClipped.Min.y += window->TitleBarHeight();
window->OuterRectClipped.ClipWith(window->ClipRect);
// Inner rectangle
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
// Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - ImMax(window->ScrollbarSizes.x, window->WindowBorderSize);
window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - ImMax(window->ScrollbarSizes.y, window->WindowBorderSize);
// Inner clipping rectangle
// Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y);
window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y);
// Setup drawing context // 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.) // (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.)
@ -6020,52 +6085,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Title bar // Title bar
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive) if (!(flags & ImGuiWindowFlags_NoTitleBar) && !window->DockIsActive)
{ RenderWindowTitleBarContents(window, title_bar_rect, name, p_open);
// Close & collapse button are on layer 1 (same as menus) and don't default focus
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
// Collapse button
if (!(flags & ImGuiWindowFlags_NoCollapse))
if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos, NULL))
window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function
// Close button
if (p_open != NULL)
{
const float rad = g.FontSize * 0.5f;
if (CloseButton(window->GetID("#CLOSE"), ImVec2(window->Pos.x + window->Size.x - style.FramePadding.x - rad, window->Pos.y + style.FramePadding.y + rad), rad + 1))
*p_open = false;
}
window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
window->DC.ItemFlags = item_flags_backup;
// Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
// FIXME: Refactor text alignment facilities along with RenderText helpers, this is too much code..
const char* UNSAVED_DOCUMENT_MARKER = "*";
float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
ImRect text_r = title_bar_rect;
float pad_left = (flags & ImGuiWindowFlags_NoCollapse) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
float pad_right = (p_open == NULL) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
if (style.WindowTitleAlign.x > 0.0f)
pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x);
text_r.Min.x += pad_left;
text_r.Max.x -= pad_right;
ImRect clip_rect = text_r;
clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton()
RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect);
if (flags & ImGuiWindowFlags_UnsavedDocument)
{
ImVec2 marker_pos = ImVec2(ImMax(text_r.Min.x, text_r.Min.x + (text_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, text_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f));
RenderTextClipped(marker_pos + off, text_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_rect);
}
}
// Clear hit test shape every frame // Clear hit test shape every frame
window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0; window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
@ -9072,13 +9092,13 @@ void ImGui::NextColumn()
{ {
// New column (columns 1+ cancels out IndentX) // New column (columns 1+ cancels out IndentX)
window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x; window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x;
window->DrawList->ChannelsSetCurrent(columns->Current); window->DrawList->ChannelsSetCurrent(columns->Current + 1);
} }
else else
{ {
// New row/line // New row/line
window->DC.ColumnsOffset.x = 0.0f; window->DC.ColumnsOffset.x = 0.0f;
window->DrawList->ChannelsSetCurrent(0); window->DrawList->ChannelsSetCurrent(1);
columns->Current = 0; columns->Current = 0;
columns->LineMinY = columns->LineMaxY; columns->LineMinY = columns->LineMaxY;
} }
@ -9087,7 +9107,7 @@ void ImGui::NextColumn()
window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
window->DC.CurrentLineTextBaseOffset = 0.0f; window->DC.CurrentLineTextBaseOffset = 0.0f;
PushColumnClipRect(); PushColumnClipRect(columns->Current);
PushItemWidth(GetColumnWidth() * 0.65f); // FIXME-COLUMNS: Move on columns setup PushItemWidth(GetColumnWidth() * 0.65f); // FIXME-COLUMNS: Move on columns setup
} }
@ -9105,12 +9125,12 @@ int ImGui::GetColumnsCount()
static float OffsetNormToPixels(const ImGuiColumns* columns, float offset_norm) static float OffsetNormToPixels(const ImGuiColumns* columns, float offset_norm)
{ {
return offset_norm * (columns->MaxX - columns->MinX); return offset_norm * (columns->OffMaxX - columns->OffMinX);
} }
static float PixelsToOffsetNorm(const ImGuiColumns* columns, float offset) static float PixelsToOffsetNorm(const ImGuiColumns* columns, float offset)
{ {
return offset / (columns->MaxX - columns->MinX); return offset / (columns->OffMaxX - columns->OffMinX);
} }
static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f; static const float COLUMNS_HIT_RECT_HALF_WIDTH = 4.0f;
@ -9143,7 +9163,7 @@ float ImGui::GetColumnOffset(int column_index)
IM_ASSERT(column_index < columns->Columns.Size); IM_ASSERT(column_index < columns->Columns.Size);
const float t = columns->Columns[column_index].OffsetNorm; const float t = columns->Columns[column_index].OffsetNorm;
const float x_offset = ImLerp(columns->MinX, columns->MaxX, t); const float x_offset = ImLerp(columns->OffMinX, columns->OffMaxX, t);
return x_offset; return x_offset;
} }
@ -9186,8 +9206,8 @@ void ImGui::SetColumnOffset(int column_index, float offset)
const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f; const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f;
if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow))
offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); offset = ImMin(offset, columns->OffMaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index));
columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset - columns->MinX); columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset - columns->OffMinX);
if (preserve_width) if (preserve_width)
SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width));
@ -9215,6 +9235,25 @@ void ImGui::PushColumnClipRect(int column_index)
PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false); PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false);
} }
// Get into the columns background draw command (which is generally the same draw command as before we called BeginColumns)
void ImGui::PushColumnsBackground()
{
ImGuiWindow* window = GetCurrentWindowRead();
ImGuiColumns* columns = window->DC.CurrentColumns;
window->DrawList->ChannelsSetCurrent(0);
int cmd_size = window->DrawList->CmdBuffer.Size;
PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false);
IM_ASSERT(cmd_size == window->DrawList->CmdBuffer.Size); // Being in channel 0 this should not have created an ImDrawCmd
}
void ImGui::PopColumnsBackground()
{
ImGuiWindow* window = GetCurrentWindowRead();
ImGuiColumns* columns = window->DC.CurrentColumns;
window->DrawList->ChannelsSetCurrent(columns->Current + 1);
PopClipRect();
}
ImGuiColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id) ImGuiColumns* ImGui::FindOrCreateColumns(ImGuiWindow* window, ImGuiID id)
{ {
// We have few columns per window so for now we don't need bother much with turning this into a faster lookup. // We have few columns per window so for now we don't need bother much with turning this into a faster lookup.
@ -9249,9 +9288,8 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
IM_ASSERT(columns_count >= 1); IM_ASSERT(columns_count >= 1);
IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported IM_ASSERT(window->DC.CurrentColumns == NULL); // Nested columns are currently not supported
ImGuiID id = GetColumnsID(str_id, columns_count);
// Acquire storage for the columns set // Acquire storage for the columns set
ImGuiID id = GetColumnsID(str_id, columns_count);
ImGuiColumns* columns = FindOrCreateColumns(window, id); ImGuiColumns* columns = FindOrCreateColumns(window, id);
IM_ASSERT(columns->ID == id); IM_ASSERT(columns->ID == id);
columns->Current = 0; columns->Current = 0;
@ -9261,10 +9299,11 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
// Set state for first column // Set state for first column
const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x); const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x);
columns->MinX = window->DC.Indent.x - g.Style.ItemSpacing.x; // Lock our horizontal range columns->OffMinX = window->DC.Indent.x - g.Style.ItemSpacing.x; // Lock our horizontal range
columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f); columns->OffMaxX = ImMax(content_region_width - window->Scroll.x, columns->OffMinX + 1.0f);
columns->BackupCursorPosY = window->DC.CursorPos.y; columns->HostCursorPosY = window->DC.CursorPos.y;
columns->BackupCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x;
columns->HostClipRect = window->ClipRect;
columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y;
window->DC.ColumnsOffset.x = 0.0f; window->DC.ColumnsOffset.x = 0.0f;
window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
@ -9273,7 +9312,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1)
columns->Columns.resize(0); columns->Columns.resize(0);
// Initialize defaults // Initialize default widths
columns->IsFirstFrame = (columns->Columns.Size == 0); columns->IsFirstFrame = (columns->Columns.Size == 0);
if (columns->Columns.Size == 0) if (columns->Columns.Size == 0)
{ {
@ -9298,8 +9337,9 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag
if (columns->Count > 1) if (columns->Count > 1)
{ {
window->DrawList->ChannelsSplit(columns->Count); window->DrawList->ChannelsSplit(1 + columns->Count);
PushColumnClipRect(); window->DrawList->ChannelsSetCurrent(1);
PushColumnClipRect(0);
} }
PushItemWidth(GetColumnWidth() * 0.65f); PushItemWidth(GetColumnWidth() * 0.65f);
} }
@ -9318,17 +9358,19 @@ void ImGui::EndColumns()
window->DrawList->ChannelsMerge(); window->DrawList->ChannelsMerge();
} }
const ImGuiColumnsFlags flags = columns->Flags;
columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
window->DC.CursorPos.y = columns->LineMaxY; window->DC.CursorPos.y = columns->LineMaxY;
if (!(columns->Flags & ImGuiColumnsFlags_GrowParentContentsSize)) if (!(flags & ImGuiColumnsFlags_GrowParentContentsSize))
window->DC.CursorMaxPos.x = columns->BackupCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent window->DC.CursorMaxPos.x = columns->HostCursorMaxPosX; // Restore cursor max pos, as columns don't grow parent
// Draw columns borders and handle resize // Draw columns borders and handle resize
// The IsBeingResized flag ensure we preserve pre-resize columns width so back-and-forth are not lossy
bool is_being_resized = false; bool is_being_resized = false;
if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) if (!(flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
{ {
// We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers. // We clip Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.
const float y1 = ImMax(columns->BackupCursorPosY, window->ClipRect.Min.y); const float y1 = ImMax(columns->HostCursorPosY, window->ClipRect.Min.y);
const float y2 = ImMin(window->DC.CursorPos.y, window->ClipRect.Max.y); const float y2 = ImMin(window->DC.CursorPos.y, window->ClipRect.Max.y);
int dragging_column = -1; int dragging_column = -1;
for (int n = 1; n < columns->Count; n++) for (int n = 1; n < columns->Count; n++)
@ -9343,7 +9385,7 @@ void ImGui::EndColumns()
continue; continue;
bool hovered = false, held = false; bool hovered = false, held = false;
if (!(columns->Flags & ImGuiColumnsFlags_NoResize)) if (!(flags & ImGuiColumnsFlags_NoResize))
{ {
ButtonBehavior(column_hit_rect, column_id, &hovered, &held); ButtonBehavior(column_hit_rect, column_id, &hovered, &held);
if (hovered || held) if (hovered || held)
@ -9395,6 +9437,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border)
BeginColumns(id, columns_count, flags); BeginColumns(id, columns_count, flags);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] DRAG AND DROP // [SECTION] DRAG AND DROP
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -12187,7 +12230,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
// Render outer borders last (after the tab bar) // Render outer borders last (after the tab bar)
if (node->IsRootNode()) if (node->IsRootNode())
RenderOuterBorders(host_window); RenderWindowOuterBorders(host_window);
} }
// End host window // End host window
@ -14284,7 +14327,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
{ {
if (!ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) if (!ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags))
return; return;
ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->MaxX - columns->MinX, columns->MinX, columns->MaxX); ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->OffMaxX - columns->OffMinX, columns->OffMinX, columns->OffMaxX);
for (int column_n = 0; column_n < columns->Columns.Size; column_n++) for (int column_n = 0; column_n < columns->Columns.Size; column_n++)
ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, OffsetNormToPixels(columns, columns->Columns[column_n].OffsetNorm)); ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, OffsetNormToPixels(columns, columns->Columns[column_n].OffsetNorm));
ImGui::TreePop(); ImGui::TreePop();

View File

@ -1,4 +1,4 @@
// dear imgui, v1.70 WIP // dear imgui, v1.71 WIP
// (headers) // (headers)
// See imgui.cpp file for documentation. // See imgui.cpp file for documentation.
@ -47,8 +47,8 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.70 WIP" #define IMGUI_VERSION "1.71"
#define IMGUI_VERSION_NUM 16991 #define IMGUI_VERSION_NUM 17001
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_VIEWPORT 1 // Viewport WIP branch #define IMGUI_HAS_VIEWPORT 1 // Viewport WIP branch
#define IMGUI_HAS_DOCK 1 // Docking WIP branch #define IMGUI_HAS_DOCK 1 // Docking WIP branch
@ -1364,7 +1364,7 @@ struct ImGuiStyle
ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label). ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label).
ImVec2 TouchExtraPadding; // 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! ImVec2 TouchExtraPadding; // 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!
float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar. float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar.
float ScrollbarRounding; // Radius of grab corners for scrollbar. float ScrollbarRounding; // Radius of grab corners for scrollbar.
float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar.

View File

@ -1,4 +1,4 @@
// dear imgui, v1.70 WIP // dear imgui, v1.71 WIP
// (demo code) // (demo code)
// Message to the person tempted to delete this file when integrating Dear ImGui into their code base: // Message to the person tempted to delete this file when integrating Dear ImGui into their code base:
@ -2484,6 +2484,32 @@ static void ShowDemoWindowColumns()
ImGui::TreePop(); ImGui::TreePop();
} }
if (ImGui::TreeNode("Borders"))
{
// NB: Future columns API should allow automatic horizontal borders.
static bool h_borders = true;
static bool v_borders = true;
ImGui::Checkbox("horizontal", &h_borders);
ImGui::SameLine();
ImGui::Checkbox("vertical", &v_borders);
ImGui::Columns(4, NULL, v_borders);
for (int i = 0; i < 4 * 3; i++)
{
if (h_borders && ImGui::GetColumnIndex() == 0)
ImGui::Separator();
ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
ImGui::Text("Long text that is likely to clip");
ImGui::Button("Button", ImVec2(-1.0f, 0.0f));
ImGui::NextColumn();
}
ImGui::Columns(1);
if (h_borders)
ImGui::Separator();
ImGui::TreePop();
}
// Create multiple items in a same cell before switching to next column // Create multiple items in a same cell before switching to next column
if (ImGui::TreeNode("Mixed items")) if (ImGui::TreeNode("Mixed items"))
{ {
@ -2530,32 +2556,6 @@ static void ShowDemoWindowColumns()
ImGui::TreePop(); ImGui::TreePop();
} }
if (ImGui::TreeNode("Borders"))
{
// NB: Future columns API should allow automatic horizontal borders.
static bool h_borders = true;
static bool v_borders = true;
ImGui::Checkbox("horizontal", &h_borders);
ImGui::SameLine();
ImGui::Checkbox("vertical", &v_borders);
ImGui::Columns(4, NULL, v_borders);
for (int i = 0; i < 4*3; i++)
{
if (h_borders && ImGui::GetColumnIndex() == 0)
ImGui::Separator();
ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
ImGui::Text("Long text that is likely to clip");
ImGui::Button("Button", ImVec2(-1.0f, 0.0f));
ImGui::NextColumn();
}
ImGui::Columns(1);
if (h_borders)
ImGui::Separator();
ImGui::TreePop();
}
// Scrolling columns // Scrolling columns
/* /*
if (ImGui::TreeNode("Vertical Scrolling")) if (ImGui::TreeNode("Vertical Scrolling"))

View File

@ -1,4 +1,4 @@
// dear imgui, v1.70 WIP // dear imgui, v1.71 WIP
// (drawing and font code) // (drawing and font code)
/* /*

View File

@ -1,4 +1,4 @@
// dear imgui, v1.70 WIP // dear imgui, v1.71 WIP
// (internal structures/api) // (internal structures/api)
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
@ -362,7 +362,8 @@ enum ImGuiSeparatorFlags_
{ {
ImGuiSeparatorFlags_None = 0, ImGuiSeparatorFlags_None = 0,
ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar
ImGuiSeparatorFlags_Vertical = 1 << 1 ImGuiSeparatorFlags_Vertical = 1 << 1,
ImGuiSeparatorFlags_SpanAllColumns = 1 << 2
}; };
// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin(). // Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin().
@ -700,10 +701,11 @@ struct ImGuiColumns
bool IsBeingResized; bool IsBeingResized;
int Current; int Current;
int Count; int Count;
float MinX, MaxX; float OffMinX, OffMaxX; // Offsets from HostWorkRect.Min.x
float LineMinY, LineMaxY; float LineMinY, LineMaxY;
float BackupCursorPosY; // Backup of CursorPos at the time of BeginColumns() float HostCursorPosY; // Backup of CursorPos at the time of BeginColumns()
float BackupCursorMaxPosX; // Backup of CursorMaxPos at the time of BeginColumns() float HostCursorMaxPosX; // Backup of CursorMaxPos at the time of BeginColumns()
ImRect HostClipRect; // Backup of ClipRect at the time of BeginColumns()
ImVector<ImGuiColumnData> Columns; ImVector<ImGuiColumnData> Columns;
ImGuiColumns() { Clear(); } ImGuiColumns() { Clear(); }
@ -715,10 +717,10 @@ struct ImGuiColumns
IsBeingResized = false; IsBeingResized = false;
Current = 0; Current = 0;
Count = 1; Count = 1;
MinX = MaxX = 0.0f; OffMinX = OffMaxX = 0.0f;
LineMinY = LineMaxY = 0.0f; LineMinY = LineMaxY = 0.0f;
BackupCursorPosY = 0.0f; HostCursorPosY = 0.0f;
BackupCursorMaxPosX = 0.0f; HostCursorMaxPosX = 0.0f;
Columns.clear(); Columns.clear();
} }
}; };
@ -1093,7 +1095,7 @@ struct ImGuiContext
bool DragCurrentAccumDirty; bool DragCurrentAccumDirty;
float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings float DragCurrentAccum; // Accumulator for dragging modification. Always high-precision, not rounded by end-user precision settings
float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio float DragSpeedDefaultRatio; // If speed == 0.0f, uses (max-min) * DragSpeedDefaultRatio
ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
int TooltipOverrideCount; int TooltipOverrideCount;
ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined
@ -1237,7 +1239,7 @@ struct ImGuiContext
DragCurrentAccumDirty = false; DragCurrentAccumDirty = false;
DragCurrentAccum = 0.0f; DragCurrentAccum = 0.0f;
DragSpeedDefaultRatio = 1.0f / 100.0f; DragSpeedDefaultRatio = 1.0f / 100.0f;
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f); ScrollbarClickDeltaToGrabCenter = 0.0f;
TooltipOverrideCount = 0; TooltipOverrideCount = 0;
MultiSelectScopeId = 0; MultiSelectScopeId = 0;
@ -1720,7 +1722,9 @@ namespace ImGui
// New Columns API (FIXME-WIP) // New Columns API (FIXME-WIP)
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
IMGUI_API void EndColumns(); // close columns IMGUI_API void EndColumns(); // close columns
IMGUI_API void PushColumnClipRect(int column_index = -1); IMGUI_API void PushColumnClipRect(int column_index);
IMGUI_API void PushColumnsBackground();
IMGUI_API void PopColumnsBackground();
IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count); IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count);
IMGUI_API ImGuiColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id); IMGUI_API ImGuiColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id);
@ -1769,8 +1773,9 @@ namespace ImGui
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_node); IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_node);
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags); IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags);
IMGUI_API void Scrollbar(ImGuiAxis axis); IMGUI_API void Scrollbar(ImGuiAxis axis);
IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawCornerFlags rounding_corners);
IMGUI_API ImGuiID GetScrollbarID(ImGuiWindow* window, ImGuiAxis axis); IMGUI_API ImGuiID GetScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout. IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags);
// Widgets low-level behaviors // Widgets low-level behaviors
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);

View File

@ -1,4 +1,4 @@
// dear imgui, v1.70 WIP // dear imgui, v1.71 WIP
// (widgets code) // (widgets code)
/* /*
@ -380,6 +380,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
// - ArrowButton() // - ArrowButton()
// - CloseButton() [Internal] // - CloseButton() [Internal]
// - CollapseButton() [Internal] // - CollapseButton() [Internal]
// - ScrollbarEx() [Internal]
// - Scrollbar() [Internal] // - Scrollbar() [Internal]
// - Image() // - Image()
// - ImageButton() // - ImageButton()
@ -808,125 +809,124 @@ ImGuiID ImGui::GetScrollbarID(ImGuiWindow* window, ImGuiAxis axis)
// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) // - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)
// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar // - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
void ImGui::Scrollbar(ImGuiAxis axis) // Still, the code should probably be made simpler..
bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawCornerFlags rounding_corners)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
return false;
const bool horizontal = (axis == ImGuiAxis_X); const float bb_frame_width = bb_frame.GetWidth();
const ImGuiStyle& style = g.Style; const float bb_frame_height = bb_frame.GetHeight();
const ImGuiID id = GetScrollbarID(window, axis); if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f)
KeepAliveID(id); return false;
// Render background
bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX);
float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f;
const ImRect host_rect = window->Rect();
const float border_size = window->WindowBorderSize;
ImRect bb = horizontal
? ImRect(host_rect.Min.x + border_size, host_rect.Max.y - style.ScrollbarSize, host_rect.Max.x - other_scrollbar_size_w - border_size, host_rect.Max.y - border_size)
: ImRect(host_rect.Max.x - style.ScrollbarSize, host_rect.Min.y + border_size, host_rect.Max.x - border_size, host_rect.Max.y - other_scrollbar_size_w - border_size);
bb.Min.x = ImMax(host_rect.Min.x, bb.Min.x); // Handle case where the host rectangle is smaller than the scrollbar
bb.Min.y = ImMax(host_rect.Min.y, bb.Min.y);
if (!horizontal)
bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f); // FIXME: InnerRect?
const float bb_width = bb.GetWidth();
const float bb_height = bb.GetHeight();
if (bb_width <= 0.0f || bb_height <= 0.0f)
return;
// When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the resize grab) // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the resize grab)
float alpha = 1.0f; float alpha = 1.0f;
if ((axis == ImGuiAxis_Y) && bb_height < g.FontSize + g.Style.FramePadding.y * 2.0f) if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f)
{ alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f));
alpha = ImSaturate((bb_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f)); if (alpha <= 0.0f)
if (alpha <= 0.0f) return false;
return;
}
const bool allow_interaction = (alpha >= 1.0f);
int window_rounding_corners; const ImGuiStyle& style = g.Style;
if (horizontal) const bool allow_interaction = (alpha >= 1.0f);
window_rounding_corners = ImDrawCornerFlags_BotLeft | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight); const bool horizontal = (axis == ImGuiAxis_X);
else
window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0) | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight); ImRect bb = bb_frame;
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_ScrollbarBg), window->WindowRounding, window_rounding_corners); bb.Expand(ImVec2(-ImClamp((float)(int)((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f)));
bb.Expand(ImVec2(-ImClamp((float)(int)((bb_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb_height - 2.0f) * 0.5f), 0.0f, 3.0f)));
// V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)
float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); const float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight();
float scroll_v = horizontal ? window->Scroll.x : window->Scroll.y;
float win_size_avail_v = (horizontal ? window->SizeFull.x : window->SizeFull.y) - other_scrollbar_size_w;
float win_size_contents_v = horizontal ? window->SizeContents.x : window->SizeContents.y;
// Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)
// But we maintain a minimum size in pixel to allow for the user to still aim inside. // But we maintain a minimum size in pixel to allow for the user to still aim inside.
IM_ASSERT(ImMax(win_size_contents_v, win_size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
const float win_size_v = ImMax(ImMax(win_size_contents_v, win_size_avail_v), 1.0f); const float win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), 1.0f);
const float grab_h_pixels = ImClamp(scrollbar_size_v * (win_size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v); const float grab_h_pixels = ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v);
const float grab_h_norm = grab_h_pixels / scrollbar_size_v; const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
bool held = false; bool held = false;
bool hovered = false; bool hovered = false;
const bool previously_held = (g.ActiveId == id);
ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); float scroll_max = ImMax(1.0f, size_contents_v - size_avail_v);
float scroll_ratio = ImSaturate(scroll_v / scroll_max); float scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
if (held && allow_interaction && grab_h_norm < 1.0f) if (held && allow_interaction && grab_h_norm < 1.0f)
{ {
float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y; float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y;
float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y;
float* click_delta_to_grab_center_v = horizontal ? &g.ScrollbarClickDeltaToGrabCenter.x : &g.ScrollbarClickDeltaToGrabCenter.y;
// Click position in scrollbar normalized space (0.0f->1.0f) // Click position in scrollbar normalized space (0.0f->1.0f)
const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
SetHoveredID(id); SetHoveredID(id);
bool seek_absolute = false; bool seek_absolute = false;
if (!previously_held) if (g.ActiveIdIsJustActivated)
{ {
// On initial click calculate the distance between mouse and the center of the grab // On initial click calculate the distance between mouse and the center of the grab
if (clicked_v_norm >= grab_v_norm && clicked_v_norm <= grab_v_norm + grab_h_norm) seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm);
{ if (seek_absolute)
*click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f; g.ScrollbarClickDeltaToGrabCenter = 0.0f;
}
else else
{ g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
seek_absolute = true;
*click_delta_to_grab_center_v = 0.0f;
}
} }
// Apply scroll // 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 SizeContents and before setting up our starting position
const float scroll_v_norm = ImSaturate((clicked_v_norm - *click_delta_to_grab_center_v - grab_h_norm*0.5f) / (1.0f - grab_h_norm)); const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v)); *p_scroll_v = (float)(int)(0.5f + scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
if (horizontal)
window->Scroll.x = scroll_v;
else
window->Scroll.y = scroll_v;
// Update values for rendering // Update values for rendering
scroll_ratio = ImSaturate(scroll_v / scroll_max); scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
// Update distance to grab now that we have seeked and saturated // Update distance to grab now that we have seeked and saturated
if (seek_absolute) if (seek_absolute)
*click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f; g.ScrollbarClickDeltaToGrabCenter = clicked_v_norm - grab_v_norm - grab_h_norm * 0.5f;
} }
// Render grab // Render
window->DrawList->AddRectFilled(bb_frame.Min, bb_frame.Max, GetColorU32(ImGuiCol_ScrollbarBg), window->WindowRounding, rounding_corners);
const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha); const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha);
ImRect grab_rect; ImRect grab_rect;
if (horizontal) if (horizontal)
grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImMin(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, host_rect.Max.x), bb.Max.y); grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y);
else else
grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImMin(ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels, host_rect.Max.y)); grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels);
window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding); window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding);
return held;
}
void ImGui::Scrollbar(ImGuiAxis axis)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const ImGuiID id = GetScrollbarID(window, axis);
KeepAliveID(id);
// Calculate scrollbar bounding box
const ImRect outer_rect = window->Rect();
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->InnerMainRect.Min.x, window->InnerMainRect.Max.y);
bb.Max = ImVec2(window->InnerMainRect.Max.x, outer_rect.Max.y - window->WindowBorderSize);
rounding_corners |= ImDrawCornerFlags_BotLeft;
}
else
{
bb.Min = ImVec2(window->InnerMainRect.Max.x, window->InnerMainRect.Min.y);
bb.Max = ImVec2(outer_rect.Max.x - window->WindowBorderSize, window->InnerMainRect.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);
} }
void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col)
@ -1177,8 +1177,8 @@ void ImGui::Bullet()
// - Dummy() // - Dummy()
// - NewLine() // - NewLine()
// - AlignTextToFramePadding() // - AlignTextToFramePadding()
// - SeparatorEx() [Internal]
// - Separator() // - Separator()
// - VerticalSeparator() [Internal]
// - SplitterBehavior() [Internal] // - SplitterBehavior() [Internal]
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -1229,69 +1229,78 @@ void ImGui::AlignTextToFramePadding()
} }
// Horizontal/vertical separating line // Horizontal/vertical separating line
void ImGui::Separator() void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) if (window->SkipItems)
return; return;
ImGuiContext& g = *GImGui;
// Those flags should eventually be overrideable by the user ImGuiContext& g = *GImGui;
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected IM_ASSERT(ImIsPowerOfTwo(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical))); // Check that only 1 option is selected
float thickness_draw = 1.0f;
float thickness_layout = 0.0f;
if (flags & ImGuiSeparatorFlags_Vertical) if (flags & ImGuiSeparatorFlags_Vertical)
{ {
VerticalSeparator(); // Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout.
return; float y1 = window->DC.CursorPos.y;
float y2 = window->DC.CursorPos.y + window->DC.CurrentLineSize.y;
const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + thickness_draw, y2));
ItemSize(ImVec2(thickness_layout, 0.0f));
if (!ItemAdd(bb, 0))
return;
// Draw
window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
if (g.LogEnabled)
LogText(" |");
} }
else if (flags & ImGuiSeparatorFlags_Horizontal)
// Horizontal Separator
if (window->DC.CurrentColumns)
PopClipRect();
float x1 = window->Pos.x;
float x2 = window->Pos.x + window->Size.x;
if (!window->DC.GroupStack.empty())
x1 += window->DC.Indent.x;
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y+1.0f));
ItemSize(ImVec2(0.0f, 1.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit
if (!ItemAdd(bb, 0))
{ {
if (window->DC.CurrentColumns) // Horizontal Separator
PushColumnClipRect(); float x1 = window->Pos.x;
return; float x2 = window->Pos.x + window->Size.x;
} if (!window->DC.GroupStack.empty())
x1 += window->DC.Indent.x;
window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x,bb.Min.y), GetColorU32(ImGuiCol_Separator)); ImGuiColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
if (columns)
PushColumnsBackground();
if (g.LogEnabled) // We don't provide our width to the layout so that it doesn't get feed back into AutoFit
LogRenderedText(&bb.Min, "--------------------------------"); const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw));
ItemSize(ImVec2(0.0f, thickness_layout));
if (!ItemAdd(bb, 0))
{
if (columns)
PopColumnsBackground();
return;
}
if (window->DC.CurrentColumns) // Draw
{ window->DrawList->AddLine(bb.Min, ImVec2(bb.Max.x, bb.Min.y), GetColorU32(ImGuiCol_Separator));
PushColumnClipRect(); if (g.LogEnabled)
window->DC.CurrentColumns->LineMinY = window->DC.CursorPos.y; LogRenderedText(&bb.Min, "--------------------------------");
if (columns)
{
PopColumnsBackground();
columns->LineMinY = window->DC.CursorPos.y;
}
} }
} }
void ImGui::VerticalSeparator() void ImGui::Separator()
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems) if (window->SkipItems)
return; return;
ImGuiContext& g = *GImGui;
float y1 = window->DC.CursorPos.y; // Those flags should eventually be overridable by the user
float y2 = window->DC.CursorPos.y + window->DC.CurrentLineSize.y; ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
const ImRect bb(ImVec2(window->DC.CursorPos.x, y1), ImVec2(window->DC.CursorPos.x + 1.0f, y2)); flags |= ImGuiSeparatorFlags_SpanAllColumns;
ItemSize(ImVec2(1.0f, 0.0f)); SeparatorEx(flags);
if (!ItemAdd(bb, 0))
return;
window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x, bb.Max.y), GetColorU32(ImGuiCol_Separator));
if (g.LogEnabled)
LogText(" |");
} }
// Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise. // Using 'hover_visibility_delay' allows us to hide the highlight and mouse cursor for a short time, which can be convenient to reduce visual noise.
@ -5345,7 +5354,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped. if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped.
PopClipRect(); PushColumnsBackground();
ImGuiID id = window->GetID(label); ImGuiID id = window->GetID(label);
ImVec2 label_size = CalcTextSize(label, NULL, true); ImVec2 label_size = CalcTextSize(label, NULL, true);
@ -5389,7 +5398,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
if (!item_add) if (!item_add)
{ {
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns)
PushColumnClipRect(); PopColumnsBackground();
return false; return false;
} }
@ -5435,7 +5444,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns)
{ {
PushColumnClipRect(); PopColumnsBackground();
bb.Max.x -= (GetContentRegionMax().x - max_x); bb.Max.x -= (GetContentRegionMax().x - max_x);
} }

View File

@ -1,4 +1,4 @@
dear imgui, v1.70 WIP dear imgui, v1.71 WIP
(Font Readme) (Font Readme)
--------------------------------------- ---------------------------------------