|
@@ -457,7 +457,6 @@
|
|
|
The list below consist mostly of notes of things to do before they are requested/discussed by users (at that point it usually happens on the github)
|
|
The list below consist mostly of notes of things to do before they are requested/discussed by users (at that point it usually happens on the github)
|
|
|
|
|
|
|
|
- doc: add a proper documentation+regression testing system (#435)
|
|
- doc: add a proper documentation+regression testing system (#435)
|
|
|
- - window: maximum window size settings (per-axis). for large popups in particular user may not want the popup to fill all space.
|
|
|
|
|
- window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
|
|
- window: add a way for very transient windows (non-saved, temporary overlay over hundreds of objects) to "clean" up from the global window list. perhaps a lightweight explicit cleanup pass.
|
|
|
- window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis).
|
|
- window: calling SetNextWindowSize() every frame with <= 0 doesn't do anything, may be useful to allow (particularly when used for a single axis).
|
|
|
- window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify.
|
|
- window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify.
|
|
@@ -3420,7 +3419,7 @@ static inline void ClearSetNextWindowData()
|
|
|
{
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
|
g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0;
|
|
g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0;
|
|
|
- g.SetNextWindowFocus = false;
|
|
|
|
|
|
|
+ g.SetNextWindowSizeConstraint = g.SetNextWindowFocus = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
|
|
static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
|
|
@@ -3735,6 +3734,31 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
|
|
|
return window;
|
|
return window;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size)
|
|
|
|
|
+{
|
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
|
+ if (g.SetNextWindowSizeConstraint)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Using -1,-1 on either X/Y axis to preserve the current size.
|
|
|
|
|
+ ImRect cr = g.SetNextWindowSizeConstraintRect;
|
|
|
|
|
+ new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
|
|
|
|
|
+ new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
|
|
|
|
|
+ if (g.SetNextWindowSizeConstraintCallback)
|
|
|
|
|
+ {
|
|
|
|
|
+ ImGuiSizeConstraintCallbackData data;
|
|
|
|
|
+ data.UserData = g.SetNextWindowSizeConstraintCallbackUserData;
|
|
|
|
|
+ data.Pos = window->Pos;
|
|
|
|
|
+ data.CurrentSize = window->SizeFull;
|
|
|
|
|
+ data.DesiredSize = new_size;
|
|
|
|
|
+ g.SetNextWindowSizeConstraintCallback(&data);
|
|
|
|
|
+ new_size = data.DesiredSize;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize)))
|
|
|
|
|
+ new_size = ImMax(new_size, g.Style.WindowMinSize);
|
|
|
|
|
+ window->SizeFull = new_size;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// Push a new ImGui window to add widgets to.
|
|
// Push a new 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.
|
|
@@ -3800,7 +3824,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|
|
bool window_pos_set_by_api = false, window_size_set_by_api = false;
|
|
bool window_pos_set_by_api = false, window_size_set_by_api = false;
|
|
|
if (g.SetNextWindowPosCond)
|
|
if (g.SetNextWindowPosCond)
|
|
|
{
|
|
{
|
|
|
- const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this anymore :( need to look into that.
|
|
|
|
|
|
|
+ const ImVec2 backup_cursor_pos = window->DC.CursorPos; // FIXME: not sure of the exact reason of this saving/restore anymore :( need to look into that.
|
|
|
if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing;
|
|
if (!window_was_active || window_appearing_after_being_hidden) window->SetWindowPosAllowFlags |= ImGuiSetCond_Appearing;
|
|
|
window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0;
|
|
window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0;
|
|
|
if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f)
|
|
if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosVal - ImVec2(-FLT_MAX,-FLT_MAX)) < 0.001f)
|
|
@@ -3861,12 +3885,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|
|
window->Active = true;
|
|
window->Active = true;
|
|
|
window->IndexWithinParent = 0;
|
|
window->IndexWithinParent = 0;
|
|
|
window->BeginCount = 0;
|
|
window->BeginCount = 0;
|
|
|
- window->DrawList->Clear();
|
|
|
|
|
window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);
|
|
window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);
|
|
|
window->LastFrameActive = current_frame;
|
|
window->LastFrameActive = current_frame;
|
|
|
window->IDStack.resize(1);
|
|
window->IDStack.resize(1);
|
|
|
|
|
|
|
|
- // Setup texture, outer clipping rectangle
|
|
|
|
|
|
|
+ // Clear draw list, setup texture, outer clipping rectangle
|
|
|
|
|
+ window->DrawList->Clear();
|
|
|
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
|
|
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
|
|
|
ImRect fullscreen_rect(GetVisibleRect());
|
|
ImRect fullscreen_rect(GetVisibleRect());
|
|
|
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ComboBox|ImGuiWindowFlags_Popup)))
|
|
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ComboBox|ImGuiWindowFlags_Popup)))
|
|
@@ -3957,7 +3981,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|
|
window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
|
|
window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
|
|
|
if (window->AutoFitFramesY > 0)
|
|
if (window->AutoFitFramesY > 0)
|
|
|
window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
|
|
window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
|
|
|
- window->Size = window->TitleBarRect().GetSize();
|
|
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -3975,17 +3998,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|
|
if (!(flags & ImGuiWindowFlags_NoSavedSettings))
|
|
if (!(flags & ImGuiWindowFlags_NoSavedSettings))
|
|
|
MarkSettingsDirty();
|
|
MarkSettingsDirty();
|
|
|
}
|
|
}
|
|
|
- window->Size = window->SizeFull;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Minimum window size
|
|
|
|
|
- if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize)))
|
|
|
|
|
- {
|
|
|
|
|
- window->SizeFull = ImMax(window->SizeFull, style.WindowMinSize);
|
|
|
|
|
- if (!window->Collapsed)
|
|
|
|
|
- window->Size = window->SizeFull;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Apply minimum/maximum window size constraints and final size
|
|
|
|
|
+ ApplySizeFullWithConstraint(window, window->SizeFull);
|
|
|
|
|
+ window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull;
|
|
|
|
|
+
|
|
|
// POSITION
|
|
// POSITION
|
|
|
|
|
|
|
|
// Position child window
|
|
// Position child window
|
|
@@ -3997,7 +4015,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|
|
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup))
|
|
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup))
|
|
|
{
|
|
{
|
|
|
window->Pos = window->PosFloat = parent_window->DC.CursorPos;
|
|
window->Pos = window->PosFloat = parent_window->DC.CursorPos;
|
|
|
- window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user.
|
|
|
|
|
|
|
+ window->Size = window->SizeFull = size_on_first_use; // NB: argument name 'size_on_first_use' misleading here, it's really just 'size' as provided by user passed via BeginChild()->Begin().
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool window_pos_center = false;
|
|
bool window_pos_center = false;
|
|
@@ -4105,14 +4123,15 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|
|
if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0])
|
|
if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0])
|
|
|
{
|
|
{
|
|
|
// Manual auto-fit when double-clicking
|
|
// Manual auto-fit when double-clicking
|
|
|
- window->SizeFull = size_auto_fit;
|
|
|
|
|
|
|
+ ApplySizeFullWithConstraint(window, size_auto_fit);
|
|
|
if (!(flags & ImGuiWindowFlags_NoSavedSettings))
|
|
if (!(flags & ImGuiWindowFlags_NoSavedSettings))
|
|
|
MarkSettingsDirty();
|
|
MarkSettingsDirty();
|
|
|
SetActiveID(0);
|
|
SetActiveID(0);
|
|
|
}
|
|
}
|
|
|
else if (held)
|
|
else if (held)
|
|
|
{
|
|
{
|
|
|
- window->SizeFull = ImMax(window->SizeFull + g.IO.MouseDelta, style.WindowMinSize);
|
|
|
|
|
|
|
+ // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
|
|
|
|
|
+ ApplySizeFullWithConstraint(window, (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos);
|
|
|
if (!(flags & ImGuiWindowFlags_NoSavedSettings))
|
|
if (!(flags & ImGuiWindowFlags_NoSavedSettings))
|
|
|
MarkSettingsDirty();
|
|
MarkSettingsDirty();
|
|
|
}
|
|
}
|
|
@@ -4276,6 +4295,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us
|
|
|
if (first_begin_of_the_frame)
|
|
if (first_begin_of_the_frame)
|
|
|
window->Accessed = false;
|
|
window->Accessed = false;
|
|
|
window->BeginCount++;
|
|
window->BeginCount++;
|
|
|
|
|
+ g.SetNextWindowSizeConstraint = false;
|
|
|
|
|
|
|
|
// Child window can be out of sight and have "negative" clip windows.
|
|
// Child window can be out of sight and have "negative" clip windows.
|
|
|
// Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar).
|
|
// Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar).
|
|
@@ -4442,7 +4462,7 @@ void ImGui::FocusWindow(ImGuiWindow* window)
|
|
|
// Steal focus on active widgets
|
|
// Steal focus on active widgets
|
|
|
if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it..
|
|
if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it..
|
|
|
if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window)
|
|
if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window)
|
|
|
- ImGui::SetActiveID(0);
|
|
|
|
|
|
|
+ SetActiveID(0);
|
|
|
|
|
|
|
|
// Bring to front
|
|
// Bring to front
|
|
|
if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) || g.Windows.back() == window)
|
|
if ((window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) || g.Windows.back() == window)
|
|
@@ -4915,6 +4935,15 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiSetCond cond)
|
|
|
g.SetNextWindowSizeCond = cond ? cond : ImGuiSetCond_Always;
|
|
g.SetNextWindowSizeCond = cond ? cond : ImGuiSetCond_Always;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void ImGui::SetNextWindowSizeConstraint(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data)
|
|
|
|
|
+{
|
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
|
+ g.SetNextWindowSizeConstraint = true;
|
|
|
|
|
+ g.SetNextWindowSizeConstraintRect = ImRect(size_min, size_max);
|
|
|
|
|
+ g.SetNextWindowSizeConstraintCallback = custom_callback;
|
|
|
|
|
+ g.SetNextWindowSizeConstraintCallbackUserData = custom_callback_user_data;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void ImGui::SetNextWindowContentSize(const ImVec2& size)
|
|
void ImGui::SetNextWindowContentSize(const ImVec2& size)
|
|
|
{
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -5428,6 +5457,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
|
|
{
|
|
{
|
|
|
SetActiveID(id, window); // Hold on ID
|
|
SetActiveID(id, window); // Hold on ID
|
|
|
FocusWindow(window);
|
|
FocusWindow(window);
|
|
|
|
|
+ g.ActiveIdClickOffset = g.IO.MousePos - bb.Min;
|
|
|
}
|
|
}
|
|
|
if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0]))
|
|
if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0]))
|
|
|
{
|
|
{
|
|
@@ -9193,7 +9223,7 @@ static float GetDraggedColumnOffset(int column_index)
|
|
|
IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets.
|
|
IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets.
|
|
|
IM_ASSERT(g.ActiveId == window->DC.ColumnsSetID + ImGuiID(column_index));
|
|
IM_ASSERT(g.ActiveId == window->DC.ColumnsSetID + ImGuiID(column_index));
|
|
|
|
|
|
|
|
- float x = g.IO.MousePos.x + g.ActiveClickDeltaToCenter.x - window->Pos.x;
|
|
|
|
|
|
|
+ float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x;
|
|
|
x = ImClamp(x, ImGui::GetColumnOffset(column_index-1)+g.Style.ColumnsMinSpacing, ImGui::GetColumnOffset(column_index+1)-g.Style.ColumnsMinSpacing);
|
|
x = ImClamp(x, ImGui::GetColumnOffset(column_index-1)+g.Style.ColumnsMinSpacing, ImGui::GetColumnOffset(column_index+1)-g.Style.ColumnsMinSpacing);
|
|
|
|
|
|
|
|
return (float)(int)x;
|
|
return (float)(int)x;
|
|
@@ -9298,7 +9328,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border)
|
|
|
if (held)
|
|
if (held)
|
|
|
{
|
|
{
|
|
|
if (g.ActiveIdIsJustActivated)
|
|
if (g.ActiveIdIsJustActivated)
|
|
|
- g.ActiveClickDeltaToCenter.x = x - g.IO.MousePos.x;
|
|
|
|
|
|
|
+ g.ActiveIdClickOffset.x -= 4; // Store from center of column line
|
|
|
x = GetDraggedColumnOffset(i);
|
|
x = GetDraggedColumnOffset(i);
|
|
|
SetColumnOffset(i, x);
|
|
SetColumnOffset(i, x);
|
|
|
}
|
|
}
|