mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-27 16:29:02 +08:00
BeginChild: Added ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY. (#1710)
This commit is contained in:
parent
34a0bc456e
commit
9235352400
@ -85,6 +85,9 @@ Breaking changes:
|
|||||||
Other changes:
|
Other changes:
|
||||||
|
|
||||||
- Windows:
|
- Windows:
|
||||||
|
- BeginChild(): Added ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY to allow resizing
|
||||||
|
child windows from the bottom/right border (toward layout direction). Resized child windows
|
||||||
|
settings are saved and persistent in .ini file. (#1666, #1496, #1395, #1710)
|
||||||
- BeginChild(): Added ImGuiChildFlags_Border as a replacement for 'bool border = true' parameter.
|
- BeginChild(): Added ImGuiChildFlags_Border as a replacement for 'bool border = true' parameter.
|
||||||
- BeginChild(): Internal name used by child windows now omits the hash/id if the child
|
- BeginChild(): Internal name used by child windows now omits the hash/id if the child
|
||||||
window is submitted in root of id stack of parent window. Makes debugging/metrics easier
|
window is submitted in root of id stack of parent window. Makes debugging/metrics easier
|
||||||
|
49
imgui.cpp
49
imgui.cpp
@ -5249,7 +5249,7 @@ static void FindHoveredWindow()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Using the clipped AABB, a child window will typically be clipped by its parent (not always)
|
// Using the clipped AABB, a child window will typically be clipped by its parent (not always)
|
||||||
ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) ? padding_regular : padding_for_resize;
|
ImVec2 hit_padding = (window->Flags & (ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize)) ? padding_regular : padding_for_resize;
|
||||||
if (!window->OuterRectClipped.ContainsWithPad(g.IO.MousePos, hit_padding))
|
if (!window->OuterRectClipped.ContainsWithPad(g.IO.MousePos, hit_padding))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -5442,22 +5442,29 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
|
|||||||
IM_ASSERT(id != 0);
|
IM_ASSERT(id != 0);
|
||||||
|
|
||||||
// Sanity check as it is likely that some user will accidentally pass ImGuiWindowFlags into the ImGuiChildFlags argument.
|
// Sanity check as it is likely that some user will accidentally pass ImGuiWindowFlags into the ImGuiChildFlags argument.
|
||||||
const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding;
|
const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Border | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY;
|
||||||
IM_UNUSED(ImGuiChildFlags_SupportedMask_);
|
IM_UNUSED(ImGuiChildFlags_SupportedMask_);
|
||||||
IM_ASSERT((child_flags & ~ImGuiChildFlags_SupportedMask_) == 0 && "Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?");
|
IM_ASSERT((child_flags & ~ImGuiChildFlags_SupportedMask_) == 0 && "Illegal ImGuiChildFlags value. Did you pass ImGuiWindowFlags values instead of ImGuiChildFlags?");
|
||||||
|
if (window_flags & ImGuiWindowFlags_AlwaysAutoResize)
|
||||||
|
IM_ASSERT((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0 && "Cannot combine ImGuiChildFlags_ResizeX/ImGuiChildFlags_ResizeY with ImGuiWindowFlags_AlwaysAutoResize.");
|
||||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||||
if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding)
|
if (window_flags & ImGuiWindowFlags_AlwaysUseWindowPadding)
|
||||||
child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding;
|
child_flags |= ImGuiChildFlags_AlwaysUseWindowPadding;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
|
window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar;
|
||||||
window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
|
window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
|
||||||
|
|
||||||
|
if ((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0)
|
||||||
|
window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
|
||||||
|
|
||||||
// Forward child flags
|
// Forward child flags
|
||||||
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
||||||
g.NextWindowData.ChildFlags = child_flags;
|
g.NextWindowData.ChildFlags = child_flags;
|
||||||
|
|
||||||
// Forward size
|
// Forward size
|
||||||
|
// Important: Begin() has special processing to switch condition to ImGuiCond_FirstUseEver for a given axis when ImGuiChildFlags_ResizeXXX is set.
|
||||||
|
// (the alternative would to store conditional flags per axis, which is possible but more code)
|
||||||
const ImVec2 content_avail = GetContentRegionAvail();
|
const ImVec2 content_avail = GetContentRegionAvail();
|
||||||
ImVec2 size = ImTrunc(size_arg);
|
ImVec2 size = ImTrunc(size_arg);
|
||||||
if (size.x <= 0.0f)
|
if (size.x <= 0.0f)
|
||||||
@ -5679,7 +5686,8 @@ static inline ImVec2 CalcWindowMinSize(ImGuiWindow* window)
|
|||||||
ImVec2 size_min;
|
ImVec2 size_min;
|
||||||
if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_ChildWindow))
|
if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_ChildWindow))
|
||||||
{
|
{
|
||||||
size_min = ImVec2(4.0f, 4.0f);
|
size_min.x = (window->ChildFlags & ImGuiChildFlags_ResizeX) ? g.Style.WindowMinSize.x : 4.0f;
|
||||||
|
size_min.y = (window->ChildFlags & ImGuiChildFlags_ResizeY) ? g.Style.WindowMinSize.y : 4.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -5939,7 +5947,11 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
|
|||||||
resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
|
resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int resize_border_mask = g.IO.ConfigWindowsResizeFromEdges ? 0x0F : 0x00;
|
int resize_border_mask = 0x00;
|
||||||
|
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||||
|
resize_border_mask |= ((window->ChildFlags & ImGuiChildFlags_ResizeX) ? 0x02 : 0) | ((window->ChildFlags & ImGuiChildFlags_ResizeY) ? 0x08 : 0);
|
||||||
|
else
|
||||||
|
resize_border_mask = g.IO.ConfigWindowsResizeFromEdges ? 0x0F : 0x00;
|
||||||
for (int border_n = 0; border_n < 4; border_n++)
|
for (int border_n = 0; border_n < 4; border_n++)
|
||||||
{
|
{
|
||||||
if ((resize_border_mask & (1 << border_n)) == 0)
|
if ((resize_border_mask & (1 << border_n)) == 0)
|
||||||
@ -5976,6 +5988,8 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si
|
|||||||
ImVec2 border_target = window->Pos;
|
ImVec2 border_target = window->Pos;
|
||||||
border_target[axis] = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING;
|
border_target[axis] = g.IO.MousePos[axis] - g.ActiveIdClickOffset[axis] + WINDOWS_HOVER_PADDING;
|
||||||
border_target = ImClamp(border_target, clamp_min, clamp_max);
|
border_target = ImClamp(border_target, clamp_min, clamp_max);
|
||||||
|
if (window->Flags & ImGuiWindowFlags_ChildWindow) // Clamp resizing of childs within parent
|
||||||
|
border_target = ImClamp(border_target, window->ParentWindow->InnerClipRect.Min, window->ParentWindow->InnerClipRect.Max);
|
||||||
CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target);
|
CalcResizePosSizeFromAnyCorner(window, border_target, ImMin(def.SegmentN1, def.SegmentN2), &pos_target, &size_target);
|
||||||
}
|
}
|
||||||
if (hovered)
|
if (hovered)
|
||||||
@ -6423,6 +6437,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
{
|
{
|
||||||
window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
|
window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
|
||||||
window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
|
window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
|
||||||
|
if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0) // Axis-specific conditions for BeginChild()
|
||||||
|
g.NextWindowData.SizeVal.x = window->SizeFull.x;
|
||||||
|
if ((window->ChildFlags & ImGuiChildFlags_ResizeY) && (window->SetWindowSizeAllowFlags & ImGuiCond_FirstUseEver) == 0)
|
||||||
|
g.NextWindowData.SizeVal.y = window->SizeFull.y;
|
||||||
SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
|
SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
|
||||||
}
|
}
|
||||||
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll)
|
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll)
|
||||||
@ -6680,7 +6698,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
// Handle manual resize: Resize Grips, Borders, Gamepad
|
// Handle manual resize: Resize Grips, Borders, Gamepad
|
||||||
int border_hovered = -1, border_held = -1;
|
int border_hovered = -1, border_held = -1;
|
||||||
ImU32 resize_grip_col[4] = {};
|
ImU32 resize_grip_col[4] = {};
|
||||||
const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it.
|
const int resize_grip_count = (window->Flags & ImGuiWindowFlags_ChildWindow) ? 0 : g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it.
|
||||||
const float resize_grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
|
const float resize_grip_draw_size = IM_TRUNC(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
|
||||||
if (!window->Collapsed)
|
if (!window->Collapsed)
|
||||||
if (int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect))
|
if (int auto_fit_mask = UpdateWindowManualResize(window, size_auto_fit, &border_hovered, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect))
|
||||||
@ -13327,6 +13345,7 @@ static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
|
|||||||
if (sscanf(line, "Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((short)x, (short)y); }
|
if (sscanf(line, "Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((short)x, (short)y); }
|
||||||
else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((short)x, (short)y); }
|
else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((short)x, (short)y); }
|
||||||
else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
|
else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
|
||||||
|
else if (sscanf(line, "IsChild=%d", &i) == 1) { settings->IsChild = (i != 0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply to existing windows (if any)
|
// Apply to existing windows (if any)
|
||||||
@ -13361,7 +13380,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
|||||||
IM_ASSERT(settings->ID == window->ID);
|
IM_ASSERT(settings->ID == window->ID);
|
||||||
settings->Pos = ImVec2ih(window->Pos);
|
settings->Pos = ImVec2ih(window->Pos);
|
||||||
settings->Size = ImVec2ih(window->SizeFull);
|
settings->Size = ImVec2ih(window->SizeFull);
|
||||||
|
settings->IsChild = (window->Flags & ImGuiWindowFlags_ChildWindow) != 0;
|
||||||
settings->Collapsed = window->Collapsed;
|
settings->Collapsed = window->Collapsed;
|
||||||
settings->WantDelete = false;
|
settings->WantDelete = false;
|
||||||
}
|
}
|
||||||
@ -13374,10 +13393,18 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
|||||||
continue;
|
continue;
|
||||||
const char* settings_name = settings->GetName();
|
const char* settings_name = settings->GetName();
|
||||||
buf->appendf("[%s][%s]\n", handler->TypeName, settings_name);
|
buf->appendf("[%s][%s]\n", handler->TypeName, settings_name);
|
||||||
buf->appendf("Pos=%d,%d\n", settings->Pos.x, settings->Pos.y);
|
if (settings->IsChild)
|
||||||
buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y);
|
{
|
||||||
if (settings->Collapsed)
|
buf->appendf("IsChild=1\n");
|
||||||
buf->appendf("Collapsed=1\n");
|
buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buf->appendf("Pos=%d,%d\n", settings->Pos.x, settings->Pos.y);
|
||||||
|
buf->appendf("Size=%d,%d\n", settings->Size.x, settings->Size.y);
|
||||||
|
if (settings->Collapsed)
|
||||||
|
buf->appendf("Collapsed=1\n");
|
||||||
|
}
|
||||||
buf->append("\n");
|
buf->append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
imgui.h
2
imgui.h
@ -1022,6 +1022,8 @@ enum ImGuiChildFlags_
|
|||||||
ImGuiChildFlags_None = 0,
|
ImGuiChildFlags_None = 0,
|
||||||
ImGuiChildFlags_Border = 1 << 0, // Show an outer border and enable WindowPadding. (Important: this is always == 1 for legacy reason)
|
ImGuiChildFlags_Border = 1 << 0, // Show an outer border and enable WindowPadding. (Important: this is always == 1 for legacy reason)
|
||||||
ImGuiChildFlags_AlwaysUseWindowPadding = 1 << 1, // Pad with style.WindowPadding even if no border are drawn (no padding by default for non-bordered child windows because it makes more sense)
|
ImGuiChildFlags_AlwaysUseWindowPadding = 1 << 1, // Pad with style.WindowPadding even if no border are drawn (no padding by default for non-bordered child windows because it makes more sense)
|
||||||
|
ImGuiChildFlags_ResizeX = 1 << 2, // Allow resize from right border (layout direction). Enable .ini saving (unless ImGuiWindowFlags_NoSavedSettings passed to window flags)
|
||||||
|
ImGuiChildFlags_ResizeY = 1 << 3, // Allow resize from bottom border (layout direction). "
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags for ImGui::InputText()
|
// Flags for ImGui::InputText()
|
||||||
|
@ -2764,6 +2764,18 @@ static void ShowDemoWindowLayout()
|
|||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Child 3: manual-resize
|
||||||
|
ImGui::SeparatorText("Manual-resize");
|
||||||
|
{
|
||||||
|
HelpMarker("Drag bottom border to resize. Double-click bottom border to auto-fit to vertical contents.");
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
|
||||||
|
ImGui::BeginChild("ResizableChild", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY);
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
for (int n = 0; n < 10; n++)
|
||||||
|
ImGui::Text("Line %04d", n);
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::SeparatorText("Misc/Advanced");
|
ImGui::SeparatorText("Misc/Advanced");
|
||||||
|
|
||||||
// Demonstrate a few extra things
|
// Demonstrate a few extra things
|
||||||
@ -2775,13 +2787,22 @@ static void ShowDemoWindowLayout()
|
|||||||
// the POV of the parent window). See 'Demo->Querying Status (Edited/Active/Hovered etc.)' for details.
|
// the POV of the parent window). See 'Demo->Querying Status (Edited/Active/Hovered etc.)' for details.
|
||||||
{
|
{
|
||||||
static int offset_x = 0;
|
static int offset_x = 0;
|
||||||
|
static bool override_bg_color = true;
|
||||||
|
static ImGuiChildFlags child_flags = ImGuiChildFlags_Border | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY;
|
||||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||||
ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
|
ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
|
||||||
|
ImGui::Checkbox("Override ChildBg color", &override_bg_color);
|
||||||
|
ImGui::CheckboxFlags("ImGuiChildFlags_Border", &child_flags, ImGuiChildFlags_Border);
|
||||||
|
ImGui::CheckboxFlags("ImGuiChildFlags_AlwaysUseWindowPadding", &child_flags, ImGuiChildFlags_AlwaysUseWindowPadding);
|
||||||
|
ImGui::CheckboxFlags("ImGuiChildFlags_ResizeX", &child_flags, ImGuiChildFlags_ResizeX);
|
||||||
|
ImGui::CheckboxFlags("ImGuiChildFlags_ResizeY", &child_flags, ImGuiChildFlags_ResizeY);
|
||||||
|
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
|
if (override_bg_color)
|
||||||
ImGui::BeginChild("Red", ImVec2(200, 100), ImGuiChildFlags_Border, ImGuiWindowFlags_None);
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
|
||||||
ImGui::PopStyleColor();
|
ImGui::BeginChild("Red", ImVec2(200, 100), child_flags, ImGuiWindowFlags_None);
|
||||||
|
if (override_bg_color)
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
for (int n = 0; n < 50; n++)
|
for (int n = 0; n < 50; n++)
|
||||||
ImGui::Text("Some test %d", n);
|
ImGui::Text("Some test %d", n);
|
||||||
|
@ -1712,6 +1712,7 @@ struct ImGuiWindowSettings
|
|||||||
ImVec2ih Pos;
|
ImVec2ih Pos;
|
||||||
ImVec2ih Size;
|
ImVec2ih Size;
|
||||||
bool Collapsed;
|
bool Collapsed;
|
||||||
|
bool IsChild;
|
||||||
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
||||||
bool WantDelete; // Set to invalidate/delete the settings entry
|
bool WantDelete; // Set to invalidate/delete the settings entry
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user