Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
#	imgui_demo.cpp
This commit is contained in:
ocornut 2023-10-18 19:45:19 +02:00
commit 2a6d7b1eaa
6 changed files with 155 additions and 117 deletions

View File

@ -67,15 +67,17 @@ Breaking changes:
Other changes: Other changes:
- Tooltips: made using SetItemTooltip()/IsItemHovered(ImGuiHoveredFlags_ForTooltip) defaults to
activate tooltips on disabled items. This is done by adding ImGuiHoveredFlags_AllowWhenDisabled
to the default value of style.HoverFlagsForTooltipMouse/HoverFlagsForTooltipNav. (#1485)
- Nav: Tabbing always enable nav highlight when ImGuiConfigFlags_NavEnableKeyboard is set. - Nav: Tabbing always enable nav highlight when ImGuiConfigFlags_NavEnableKeyboard is set.
Previously was inconsistent and only enabled when stepping through a non-input item. Previously was inconsistent and only enabled when stepping through a non-input item.
(#6802, #3092, #5759, #787) (#6802, #3092, #5759, #787)
- Separator(): Altered end-points to use more standard boundaries. (#205, #4787, #1643) - Windows:
- Left position is always current cursor X position. - Popups: clarified meaning of 'p_open != NULL' in BeginPopupModal() + set back user value
- Right position is always work-rect rightmost edge. to false when popup is closed in ways other than clicking the close button. (#6900)
- Can also auto-resize by double-clicking lower-left resize grip (not only lower-right one).
- Separators:
- Altered end-points to use more standard boundaries. (#205, #4787, #1643)
Left position is always current cursor X position.
Right position is always work-rect rightmost edge.
- Effectively means that: - Effectively means that:
- A separator in the root of a window will end up a little more distant from edges - A separator in the root of a window will end up a little more distant from edges
than previously (essentially following WindowPadding instead of clipping edges). than previously (essentially following WindowPadding instead of clipping edges).
@ -87,13 +89,17 @@ Other changes:
- Mostly legacy behavior when used inside old Columns(), as we favored that idiom back then, - Mostly legacy behavior when used inside old Columns(), as we favored that idiom back then,
only different is left position follows indentation level, to match calling a Separator() only different is left position follows indentation level, to match calling a Separator()
inside or outside Columns(). inside or outside Columns().
- Popups: clarified meaning of 'p_open != NULL' in BeginPopupModal() + set back user value - Tooltips:
to false when popup is closed in ways other than clicking the close button. (#6900) - Made using SetItemTooltip()/IsItemHovered(ImGuiHoveredFlags_ForTooltip) defaults to
- Drag and Drop: Rework drop target highlight: reduce rectangle to its visible portion, and activate tooltips on disabled items. This is done by adding ImGuiHoveredFlags_AllowWhenDisabled
then expand slightly. A full rectangle is always visible and it may protrude slightly. (#4281, #3272) to the default value of style.HoverFlagsForTooltipMouse/HoverFlagsForTooltipNav. (#1485)
- Drag and Drop: Fixed submitting a tooltip from drop target location when using AcceptDragDropPayload() - Made is possible to combine ImGuiHoveredFlags_ForTooltip with a ImGuiHoveredFlags_DelayXXX
with ImGuiDragDropFlags_AcceptNoPreviewTooltip and submitting a tooltip manually. override. (#1485)
- TreeNode: Added ImGuiTreeNodeFlags_SpanAllColumns for use in tables. (#3151, #3565, #2451, #2438) - Drag and Drop:
- Reworked drop target highlight: reduce rectangle to its visible portion, and
then expand slightly. A full rectangle is always visible and it may protrude slightly. (#4281, #3272)
- Fixed submitting a tooltip from drop target location when using AcceptDragDropPayload()
with ImGuiDragDropFlags_AcceptNoPreviewTooltip and submitting a tooltip manually.
- Tables: - Tables:
- Added angled headers support. You need to set ImGuiTableColumnFlags_AngledHeader on selected - Added angled headers support. You need to set ImGuiTableColumnFlags_AngledHeader on selected
columns and call TableAngledHeadersRow(). Added style.TableAngledHeadersAngle style option. columns and call TableAngledHeadersRow(). Added style.TableAngledHeadersAngle style option.
@ -105,18 +111,20 @@ Other changes:
so a scrolling table can contribute to initial window size. (#6510) so a scrolling table can contribute to initial window size. (#6510)
- Fixed subtle drawing overlap between borders in some situations. - Fixed subtle drawing overlap between borders in some situations.
- Fixed bottom-most and right-most outer border offset by one. (#6765, #3752) [@v-ein] - Fixed bottom-most and right-most outer border offset by one. (#6765, #3752) [@v-ein]
- Fixed top-most and left-most outer border overlapping inner clip-rect when scrolling. (#6765)
- Fixed top-most outer border being drawn with both TableBorderLight and TableBorderStrong - Fixed top-most outer border being drawn with both TableBorderLight and TableBorderStrong
in some situations, causing the earlier to be visible underneath when alpha is not 1.0f. in some situations, causing the earlier to be visible underneath when alpha is not 1.0f.
- fixed right-clicking right-most section (past right-most column) from highlighting a column. - Fixed right-clicking right-most section (past right-most column) from highlighting a column.
- Fixed an issue with ScrollX enabled where an extraneous draw command would be created.
- Menus:
- Menus: Fixed a bug where activating an item in a child-menu and dragging mouse over the
parent-menu would erroneously close the child-menu. (Regression from 1.88). (#6869)
- MenuBar: Fixed an issue where layouting an item in the menu-bar would erroneously
register contents size in a way that would affect the scrolling layer.
Was most often noticable when using an horizontal scrollbar. (#6789)
- TreeNode: Added ImGuiTreeNodeFlags_SpanAllColumns for use in tables. (#3151, #3565, #2451, #2438)
- TabBar: Fixed position of unsaved document marker (ImGuiTabItemFlags_UnsavedDocument) which was - TabBar: Fixed position of unsaved document marker (ImGuiTabItemFlags_UnsavedDocument) which was
accidentally offset in 1.89.9. (#6862) [@alektron] accidentally offset in 1.89.9. (#6862) [@alektron]
- Fonts: 'float size_pixels' passed to AddFontXXX() functions is now rounded to lowest integer.
This is because our layout/font system currently doesn't fully support non-integer sizes. Until
it does, this has been a common pitfall leading to more or less subtle issues. (#3164, #3309, #6800)
- Fonts: Better assert during load when passing truncated font data or wrong data size. (#6822)
- Fonts: Ensure calling AddFontXXX function doesn't invalidates ImFont's ConfigData pointers
prior to building again. (#6825)
- Fonts, imgui_freetype: Fixed a warning and leak in IMGUI_ENABLE_FREETYPE_LUNASVG support. (#6842, #6591)
- InputTextMultiline: Fixed a crash pressing Down on last empty line of a multiline buffer. - InputTextMultiline: Fixed a crash pressing Down on last empty line of a multiline buffer.
(regression from 1.89.2, only happened in some states). (#6783, #6000) (regression from 1.89.2, only happened in some states). (#6783, #6000)
- InputTextMultiline: Fixed Tabbing cycle leading to a situation where Enter key wouldn't - InputTextMultiline: Fixed Tabbing cycle leading to a situation where Enter key wouldn't
@ -125,11 +133,14 @@ Other changes:
to SameLine() followed by manual cursor manipulation. to SameLine() followed by manual cursor manipulation.
- BeginCombo(): Added ImGuiComboFlags_WidthFitPreview flag. (#6881) [@mpv-enjoyer] - BeginCombo(): Added ImGuiComboFlags_WidthFitPreview flag. (#6881) [@mpv-enjoyer]
- BeginListBox(): Fixed not consuming SetNextWindowXXX data when returning false. - BeginListBox(): Fixed not consuming SetNextWindowXXX data when returning false.
- Menus: Fixed a bug where activating an item in a child-menu and dragging mouse over the - Fonts:
parent-menu would erroneously close the child-menu. (Regression from 1.88). (#6869) - Arument 'float size_pixels' passed to AddFontXXX() functions is now rounded to lowest integer.
- MenuBar: Fixed an issue where layouting an item in the menu-bar would erroneously This is because our layout/font system currently doesn't fully support non-integer sizes. Until
register contents size in a way that would affect the scrolling layer. it does, this has been a common pitfall leading to more or less subtle issues. (#3164, #3309, #6800)
Was most often noticable when using an horizontal scrollbar. (#6789) - Better assert during load when passing truncated font data or wrong data size. (#6822)
- Ensure calling AddFontXXX function doesn't invalidates ImFont's ConfigData pointers
prior to building again. (#6825)
- imgui_freetype: Fixed a warning and leak in IMGUI_ENABLE_FREETYPE_LUNASVG support. (#6842, #6591)
- Misc: Most text functions also treat "%.*s" (along with "%s") specially to avoid formatting. (#3466, #6846) - Misc: Most text functions also treat "%.*s" (along with "%s") specially to avoid formatting. (#3466, #6846)
- IO: Add extra keys to ImGuiKey enum: ImGuiKey_F13 to ImGuiKey_F24. (#6891, #4921) - IO: Add extra keys to ImGuiKey enum: ImGuiKey_F13 to ImGuiKey_F24. (#6891, #4921)
- IO: Add extra keys to ImGuiKey enum: ImGuiKey_AppBack, ImGuiKey_AppForward. (#4921) - IO: Add extra keys to ImGuiKey enum: ImGuiKey_AppBack, ImGuiKey_AppForward. (#4921)

143
imgui.cpp
View File

@ -2538,11 +2538,9 @@ void ImGuiStorage::SetInt(ImGuiID key, int val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = LowerBound(Data, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
{
Data.insert(it, ImGuiStoragePair(key, val)); Data.insert(it, ImGuiStoragePair(key, val));
return; else
} it->val_i = val;
it->val_i = val;
} }
void ImGuiStorage::SetBool(ImGuiID key, bool val) void ImGuiStorage::SetBool(ImGuiID key, bool val)
@ -2554,22 +2552,18 @@ void ImGuiStorage::SetFloat(ImGuiID key, float val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = LowerBound(Data, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
{
Data.insert(it, ImGuiStoragePair(key, val)); Data.insert(it, ImGuiStoragePair(key, val));
return; else
} it->val_f = val;
it->val_f = val;
} }
void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val) void ImGuiStorage::SetVoidPtr(ImGuiID key, void* val)
{ {
ImGuiStoragePair* it = LowerBound(Data, key); ImGuiStoragePair* it = LowerBound(Data, key);
if (it == Data.end() || it->key != key) if (it == Data.end() || it->key != key)
{
Data.insert(it, ImGuiStoragePair(key, val)); Data.insert(it, ImGuiStoragePair(key, val));
return; else
} it->val_p = val;
it->val_p = val;
} }
void ImGuiStorage::SetAllInt(int v) void ImGuiStorage::SetAllInt(int v)
@ -4098,13 +4092,21 @@ bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flag
static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags) static inline float CalcDelayFromHoveredFlags(ImGuiHoveredFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (flags & ImGuiHoveredFlags_DelayShort)
return g.Style.HoverDelayShort;
if (flags & ImGuiHoveredFlags_DelayNormal) if (flags & ImGuiHoveredFlags_DelayNormal)
return g.Style.HoverDelayNormal; return g.Style.HoverDelayNormal;
if (flags & ImGuiHoveredFlags_DelayShort)
return g.Style.HoverDelayShort;
return 0.0f; return 0.0f;
} }
static ImGuiHoveredFlags ApplyHoverFlagsForTooltip(ImGuiHoveredFlags user_flags, ImGuiHoveredFlags shared_flags)
{
// Allow instance flags to override shared flags
if (user_flags & (ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal))
shared_flags &= ~(ImGuiHoveredFlags_DelayNone | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_DelayNormal);
return user_flags | shared_flags;
}
// This is roughly matching the behavior of internal-facing ItemHoverable() // This is roughly matching the behavior of internal-facing ItemHoverable()
// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered() // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()
// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId // - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
@ -4122,7 +4124,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return false; return false;
if (flags & ImGuiHoveredFlags_ForTooltip) if (flags & ImGuiHoveredFlags_ForTooltip)
flags |= g.Style.HoverFlagsForTooltipNav; flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipNav);
} }
else else
{ {
@ -4132,7 +4134,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return false; return false;
if (flags & ImGuiHoveredFlags_ForTooltip) if (flags & ImGuiHoveredFlags_ForTooltip)
flags |= g.Style.HoverFlagsForTooltipMouse; flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse);
IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_DockHierarchy)) == 0); // Flags not supported by this function IM_ASSERT((flags & (ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy | ImGuiHoveredFlags_DockHierarchy)) == 0); // Flags not supported by this function
@ -5686,18 +5688,28 @@ ImVec2 ImGui::GetItemRectSize()
return g.LastItemData.Rect.GetSize(); return g.LastItemData.Rect.GetSize();
} }
bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags) bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags)
{
ImGuiID id = GetCurrentWindow()->GetID(str_id);
return BeginChildEx(str_id, id, size_arg, border, window_flags);
}
bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags)
{
IM_ASSERT(id != 0);
return BeginChildEx(NULL, id, size_arg, border, window_flags);
}
bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* parent_window = g.CurrentWindow; ImGuiWindow* parent_window = g.CurrentWindow;
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoDocking;
flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoDocking; window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
// Size // Size
const ImVec2 content_avail = GetContentRegionAvail(); const ImVec2 content_avail = GetContentRegionAvail();
ImVec2 size = ImTrunc(size_arg); ImVec2 size = ImTrunc(size_arg);
const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00);
if (size.x <= 0.0f) if (size.x <= 0.0f)
size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too many issues) size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too many issues)
if (size.y <= 0.0f) if (size.y <= 0.0f)
@ -5714,12 +5726,13 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
const float backup_border_size = g.Style.ChildBorderSize; const float backup_border_size = g.Style.ChildBorderSize;
if (!border) if (!border)
g.Style.ChildBorderSize = 0.0f; g.Style.ChildBorderSize = 0.0f;
bool ret = Begin(temp_window_name, NULL, flags);
// Begin into window
const bool ret = Begin(temp_window_name, NULL, window_flags);
g.Style.ChildBorderSize = backup_border_size; g.Style.ChildBorderSize = backup_border_size;
ImGuiWindow* child_window = g.CurrentWindow; ImGuiWindow* child_window = g.CurrentWindow;
child_window->ChildId = id; child_window->ChildId = id;
child_window->AutoFitChildAxises = (ImS8)auto_fit_axises;
// Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually. // Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually.
// While this is not really documented/defined, it seems that the expected thing to do. // While this is not really documented/defined, it seems that the expected thing to do.
@ -5727,11 +5740,11 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
parent_window->DC.CursorPos = child_window->Pos; parent_window->DC.CursorPos = child_window->Pos;
// Process navigation-in immediately so NavInit can run on first frame // Process navigation-in immediately so NavInit can run on first frame
// Can enter a child if (A) it has navigatable items or (B) it can be scrolled. // Can enter a child if (A) it has navigable items or (B) it can be scrolled.
const ImGuiID temp_id_for_activation = ImHashStr("##Child", 0, id); const ImGuiID temp_id_for_activation = ImHashStr("##Child", 0, id);
if (g.ActiveId == temp_id_for_activation) if (g.ActiveId == temp_id_for_activation)
ClearActiveID(); ClearActiveID();
if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY)) if (g.NavActivateId == id && !(window_flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY))
{ {
FocusWindow(child_window); FocusWindow(child_window);
NavInitWindow(child_window, false); NavInitWindow(child_window, false);
@ -5741,50 +5754,29 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
return ret; return ret;
} }
bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
{
ImGuiWindow* window = GetCurrentWindow();
return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags);
}
bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags)
{
IM_ASSERT(id != 0);
return BeginChildEx(NULL, id, size_arg, border, extra_flags);
}
void ImGui::EndChild() void ImGui::EndChild()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* child_window = g.CurrentWindow;
IM_ASSERT(g.WithinEndChild == false); IM_ASSERT(g.WithinEndChild == false);
IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls IM_ASSERT(child_window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() calls
g.WithinEndChild = true; g.WithinEndChild = true;
if (window->BeginCount > 1) ImVec2 child_size = child_window->Size;
End();
if (child_window->BeginCount == 1)
{ {
End();
}
else
{
ImVec2 sz = window->Size;
if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
sz.x = ImMax(4.0f, sz.x);
if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y))
sz.y = ImMax(4.0f, sz.y);
End();
ImGuiWindow* parent_window = g.CurrentWindow; ImGuiWindow* parent_window = g.CurrentWindow;
ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + child_size);
ItemSize(sz); ItemSize(child_size);
if ((window->DC.NavLayersActiveMask != 0 || window->DC.NavWindowHasScrollY) && !(window->Flags & ImGuiWindowFlags_NavFlattened)) if ((child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavWindowHasScrollY) && !(child_window->Flags & ImGuiWindowFlags_NavFlattened))
{ {
ItemAdd(bb, window->ChildId); ItemAdd(bb, child_window->ChildId);
RenderNavHighlight(bb, window->ChildId); RenderNavHighlight(bb, child_window->ChildId);
// When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying) // When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying)
if (window->DC.NavLayersActiveMask == 0 && window == g.NavWindow) if (child_window->DC.NavLayersActiveMask == 0 && child_window == g.NavWindow)
RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin); RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
} }
else else
@ -5793,10 +5785,10 @@ void ImGui::EndChild()
ItemAdd(bb, 0); ItemAdd(bb, 0);
// But when flattened we directly reach items, adjust active layer mask accordingly // But when flattened we directly reach items, adjust active layer mask accordingly
if (window->Flags & ImGuiWindowFlags_NavFlattened) if (child_window->Flags & ImGuiWindowFlags_NavFlattened)
parent_window->DC.NavLayersActiveMaskNext |= window->DC.NavLayersActiveMaskNext; parent_window->DC.NavLayersActiveMaskNext |= child_window->DC.NavLayersActiveMaskNext;
} }
if (g.HoveredWindow == window) if (g.HoveredWindow == child_window)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
} }
g.WithinEndChild = false; g.WithinEndChild = false;
@ -6202,7 +6194,7 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s
if (hovered || held) if (hovered || held)
g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE;
if (held && g.IO.MouseClickedCount[0] == 2 && resize_grip_n == 0) if (held && g.IO.MouseClickedCount[0] == 2)
{ {
// Manual auto-fit when double-clicking // Manual auto-fit when double-clicking
size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit); size_target = CalcWindowSizeAfterConstraint(window, size_auto_fit);
@ -6731,7 +6723,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->IDStack.push_back(window->ID); window->IDStack.push_back(window->ID);
// Add to stack // Add to stack
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g.CurrentWindow = window; g.CurrentWindow = window;
ImGuiWindowStackData window_stack_data; ImGuiWindowStackData window_stack_data;
window_stack_data.Window = window; window_stack_data.Window = window;
@ -6749,6 +6740,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
} }
// Add to focus scope stack // Add to focus scope stack
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
PushFocusScope(window->ID); PushFocusScope(window->ID);
window->NavRootFocusScopeId = g.CurrentFocusScopeId; window->NavRootFocusScopeId = g.CurrentFocusScopeId;
g.CurrentWindow = NULL; g.CurrentWindow = NULL;
@ -7934,7 +7926,7 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
// for different windows of the hierarchy. Possibly need a Hash(Current+Flags) ==> (Timer) cache. // for different windows of the hierarchy. Possibly need a Hash(Current+Flags) ==> (Timer) cache.
// We can implement this for _Stationary because the data is linked to HoveredWindow rather than CurrentWindow. // We can implement this for _Stationary because the data is linked to HoveredWindow rather than CurrentWindow.
if (flags & ImGuiHoveredFlags_ForTooltip) if (flags & ImGuiHoveredFlags_ForTooltip)
flags |= g.Style.HoverFlagsForTooltipMouse; flags = ApplyHoverFlagsForTooltip(flags, g.Style.HoverFlagsForTooltipMouse);
if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverWindowUnlockedStationaryId != ref_window->ID) if ((flags & ImGuiHoveredFlags_Stationary) != 0 && g.HoverWindowUnlockedStationaryId != ref_window->ID)
return false; return false;
@ -9758,16 +9750,10 @@ void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
} }
} }
bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) // This is equivalent to comparing KeyMods + doing a IsKeyPressed()
bool ImGui::IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
// When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any.
if ((flags & ImGuiInputFlags_RouteMask_) == 0)
flags |= ImGuiInputFlags_RouteFocused;
if (!SetShortcutRouting(key_chord, owner_id, flags))
return false;
if (key_chord & ImGuiMod_Shortcut) if (key_chord & ImGuiMod_Shortcut)
key_chord = ConvertShortcutMod(key_chord); key_chord = ConvertShortcutMod(key_chord);
ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_); ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
@ -9778,11 +9764,22 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
if (key == ImGuiKey_None) if (key == ImGuiKey_None)
key = ConvertSingleModFlagToKey(&g, mods); key = ConvertSingleModFlagToKey(&g, mods);
if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateMask_)))) if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateMask_))))
return false; return false;
IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function! return true;
}
bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
{
// When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any.
if ((flags & ImGuiInputFlags_RouteMask_) == 0)
flags |= ImGuiInputFlags_RouteFocused;
if (!SetShortcutRouting(key_chord, owner_id, flags))
return false;
if (!IsKeyChordPressed(key_chord, owner_id, flags))
return false;
IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function!
return true; return true;
} }

17
imgui.h
View File

@ -349,8 +349,8 @@ namespace ImGui
// [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu, // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu,
// BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function
// returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.] // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.]
IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0); IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags window_flags = 0);
IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0); IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags window_flags = 0);
IMGUI_API void EndChild(); IMGUI_API void EndChild();
// Windows Utilities // Windows Utilities
@ -2465,9 +2465,9 @@ struct ImGuiStorage
{ {
ImGuiID key; ImGuiID key;
union { int val_i; float val_f; void* val_p; }; union { int val_i; float val_f; void* val_p; };
ImGuiStoragePair(ImGuiID _key, int _val_i) { key = _key; val_i = _val_i; } ImGuiStoragePair(ImGuiID _key, int _val) { key = _key; val_i = _val; }
ImGuiStoragePair(ImGuiID _key, float _val_f) { key = _key; val_f = _val_f; } ImGuiStoragePair(ImGuiID _key, float _val) { key = _key; val_f = _val; }
ImGuiStoragePair(ImGuiID _key, void* _val_p) { key = _key; val_p = _val_p; } ImGuiStoragePair(ImGuiID _key, void* _val) { key = _key; val_p = _val; }
}; };
ImVector<ImGuiStoragePair> Data; ImVector<ImGuiStoragePair> Data;
@ -2494,11 +2494,10 @@ struct ImGuiStorage
IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f); IMGUI_API float* GetFloatRef(ImGuiID key, float default_val = 0.0f);
IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL); IMGUI_API void** GetVoidPtrRef(ImGuiID key, void* default_val = NULL);
// Use on your own storage if you know only integer are being stored (open/close all tree nodes) // Advanced: for quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
IMGUI_API void SetAllInt(int val);
// For quicker full rebuild of a storage (instead of an incremental one), you may add all your contents and then sort once.
IMGUI_API void BuildSortByKey(); IMGUI_API void BuildSortByKey();
// Obsolete: use on your own storage if you know only integer are being stored (open/close all tree nodes)
IMGUI_API void SetAllInt(int val);
}; };
// Helper: Manually clip large list of items. // Helper: Manually clip large list of items.

View File

@ -1256,6 +1256,14 @@ static void ShowDemoWindowWidgets()
if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview)) if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview))
flags &= ~ImGuiComboFlags_NoPreview; flags &= ~ImGuiComboFlags_NoPreview;
// Override default popup height
if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightSmall", &flags, ImGuiComboFlags_HeightSmall))
flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightSmall);
if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightRegular", &flags, ImGuiComboFlags_HeightRegular))
flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightRegular);
if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightLargest", &flags, ImGuiComboFlags_HeightLargest))
flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightLargest);
// Using the generic BeginCombo() API, you have full control over how to display the combo contents. // Using the generic BeginCombo() API, you have full control over how to display the combo contents.
// (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
// stored in the object itself, etc.) // stored in the object itself, etc.)
@ -1277,6 +1285,10 @@ static void ShowDemoWindowWidgets()
ImGui::EndCombo(); ImGui::EndCombo();
} }
ImGui::Spacing();
ImGui::SeparatorText("One-liner variants");
HelpMarker("Flags above don't apply to this section.");
// Simplified one-liner Combo() API, using values packed in a single constant string // Simplified one-liner Combo() API, using values packed in a single constant string
// This is a convenience for when the selection set is small and known at compile-time. // This is a convenience for when the selection set is small and known at compile-time.
static int item_current_2 = 0; static int item_current_2 = 0;
@ -5283,6 +5295,7 @@ static void ShowDemoWindowTables()
ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags, ImGuiTableFlags_HighlightHoveredColumn); ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags, ImGuiTableFlags_HighlightHoveredColumn);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
ImGui::SliderInt("Frozen columns", &frozen_cols, 0, 2); ImGui::SliderInt("Frozen columns", &frozen_cols, 0, 2);
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2); ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2);
if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12))) if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12)))
@ -6661,7 +6674,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
"Right-click to open edit options menu."); "Right-click to open edit options menu.");
ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened); ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
ImGui::PushItemWidth(-160); ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
for (int i = 0; i < ImGuiCol_COUNT; i++) for (int i = 0; i < ImGuiCol_COUNT; i++)
{ {
const char* name = ImGui::GetStyleColorName(i); const char* name = ImGui::GetStyleColorName(i);

View File

@ -1272,9 +1272,9 @@ struct IMGUI_API ImGuiStackSizes
// Data saved for each window pushed into the stack // Data saved for each window pushed into the stack
struct ImGuiWindowStackData struct ImGuiWindowStackData
{ {
ImGuiWindow* Window; ImGuiWindow* Window;
ImGuiLastItemData ParentLastItemDataBackup; ImGuiLastItemData ParentLastItemDataBackup;
ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting ImGuiStackSizes StackSizesOnBegin; // Store size of various stacks for asserting
}; };
struct ImGuiShrinkWidthItem struct ImGuiShrinkWidthItem
@ -2660,7 +2660,6 @@ struct IMGUI_API ImGuiWindow
short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused. short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused.
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
ImS8 AutoFitFramesX, AutoFitFramesY; ImS8 AutoFitFramesX, AutoFitFramesY;
ImS8 AutoFitChildAxises;
bool AutoFitOnlyGrows; bool AutoFitOnlyGrows;
ImGuiDir AutoPosLastDirection; ImGuiDir AutoPosLastDirection;
ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames
@ -3256,7 +3255,7 @@ namespace ImGui
IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix); IMGUI_API void LogSetNextTextDecoration(const char* prefix, const char* suffix);
// Popups, Modals, Tooltips // Popups, Modals, Tooltips
IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags flags); IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags window_flags);
IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None);
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup);
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup);
@ -3380,6 +3379,10 @@ namespace ImGui
// - Route is granted to a single owner. When multiple requests are made we have policies to select the winning route. // - Route is granted to a single owner. When multiple requests are made we have policies to select the winning route.
// - Multiple read sites may use the same owner id and will all get the granted route. // - Multiple read sites may use the same owner id and will all get the granted route.
// - For routing: when owner_id is 0 we use the current Focus Scope ID as a default owner in order to identify our location. // - For routing: when owner_id is 0 we use the current Focus Scope ID as a default owner in order to identify our location.
// - TL;DR;
// - IsKeyChordPressed() compares mods + call IsKeyPressed() -> function has no side-effect.
// - Shortcut() submits a route then if currently can be routed calls IsKeyChordPressed() -> function has (desirable) side-effects.
IMGUI_API bool IsKeyChordPressed(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags = 0);
IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0);
IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0);
IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id); IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id);

View File

@ -445,6 +445,18 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size; temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f); inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
// Make left and top borders not overlap our contents by offsetting HostClipRect (#6765)
// (we normally shouldn't alter HostClipRect as we rely on TableMergeDrawChannels() expanding non-clipped column toward the
// limits of that rectangle, in order for ImDrawListSplitter::Merge() to merge the draw commands. However since the overlap
// problem only affect scrolling tables in this case we can get away with doing it without extra cost).
if (inner_window != outer_window)
{
if (flags & ImGuiTableFlags_BordersOuterV)
table->HostClipRect.Min.x = ImMin(table->HostClipRect.Min.x + TABLE_BORDER_SIZE, table->HostClipRect.Max.x);
if (flags & ImGuiTableFlags_BordersOuterH)
table->HostClipRect.Min.y = ImMin(table->HostClipRect.Min.y + TABLE_BORDER_SIZE, table->HostClipRect.Max.y);
}
// Padding and Spacing // Padding and Spacing
// - None ........Content..... Pad .....Content........ // - None ........Content..... Pad .....Content........
// - PadOuter | Pad ..Content..... Pad .....Content.. Pad | // - PadOuter | Pad ..Content..... Pad .....Content.. Pad |
@ -1149,7 +1161,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1); table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1);
} }
table->InnerWindow->ParentWorkRect = table->WorkRect; table->InnerWindow->ParentWorkRect = table->WorkRect;
table->BorderX1 = table->InnerClipRect.Min.x + ((table->Flags & ImGuiTableFlags_BordersOuterV) ? 1.0f : 0.0f); table->BorderX1 = table->InnerClipRect.Min.x;
table->BorderX2 = table->InnerClipRect.Max.x; table->BorderX2 = table->InnerClipRect.Max.x;
// Setup window's WorkRect.Max.y for GetContentRegionAvail(). Other values will be updated in each TableBeginCell() call. // Setup window's WorkRect.Max.y for GetContentRegionAvail(). Other values will be updated in each TableBeginCell() call.
@ -3015,11 +3027,14 @@ void ImGui::TableHeader(const char* label)
// Calculate ideal size for sort order arrow // Calculate ideal size for sort order arrow
float w_arrow = 0.0f; float w_arrow = 0.0f;
float w_sort_text = 0.0f; float w_sort_text = 0.0f;
bool sort_arrow = false;
char sort_order_suf[4] = ""; char sort_order_suf[4] = "";
const float ARROW_SCALE = 0.65f; const float ARROW_SCALE = 0.65f;
if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
{ {
w_arrow = ImTrunc(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x); w_arrow = ImTrunc(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x);
if (column->SortOrder != -1)
sort_arrow = true;
if (column->SortOrder > 0) if (column->SortOrder > 0)
{ {
ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1); ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);
@ -3027,9 +3042,9 @@ void ImGui::TableHeader(const char* label)
} }
} }
// We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considering for merging. // We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considered for merging.
float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow; float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow;
column->ContentMaxXHeadersUsed = ImMax(column->ContentMaxXHeadersUsed, column->WorkMaxX); column->ContentMaxXHeadersUsed = ImMax(column->ContentMaxXHeadersUsed, sort_arrow ? cell_r.Max.x : ImMin(max_pos_x, cell_r.Max.x));
column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x); column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x);
// Keep header highlighted when context menu is open. // Keep header highlighted when context menu is open.