From 66c428129051b278d252de9b1ec66443e49d48da Mon Sep 17 00:00:00 2001 From: Geoffrey Tucker Date: Sat, 29 Oct 2016 15:44:08 -0700 Subject: [PATCH 01/11] Began improvements to columns API by splitting the Columns() function into BeginColumns() and EndColumns() and adding additional flags. The columns data still needs to be placed into a stack. --- imgui.cpp | 202 ++++++++++++++++++++++++++++++----------------- imgui.h | 33 +++++--- imgui_demo.cpp | 43 ++++++++++ imgui_draw.cpp | 4 +- imgui_internal.h | 6 +- 5 files changed, 199 insertions(+), 89 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 07466840..8761f784 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3507,7 +3507,7 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags) bool ImGui::BeginPopup(const char* str_id) { - if (GImGui->OpenPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance + if (GImGui->OpenPopupStack.Size <= GImGui->CurrentPopupStack.Size) // Early out for performance { ClearSetNextWindowData(); // We behave like Begin() and need to consume those values return false; @@ -9175,7 +9175,7 @@ void ImGui::EndGroup() ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls + IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls ImGuiGroupData& group_data = window->DC.GroupStack.back(); @@ -9295,6 +9295,18 @@ int ImGui::GetColumnsCount() return window->DC.ColumnsCount; } +static float OffsetNormToPixels(float offsetNorm) +{ + ImGuiWindow* window = ImGui::GetCurrentWindowRead(); + return offsetNorm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); +} + +static float PixelsToOffsetNorm(float offset) +{ + ImGuiWindow* window = ImGui::GetCurrentWindowRead(); + return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); +} + static float GetDraggedColumnOffset(int column_index) { // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing @@ -9305,7 +9317,9 @@ static float GetDraggedColumnOffset(int column_index) IM_ASSERT(g.ActiveId == window->DC.ColumnsSetId + ImGuiID(column_index)); 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 = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); + if ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) + x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); return (float)(int)x; } @@ -9332,16 +9346,26 @@ float ImGui::GetColumnOffset(int column_index) void ImGui::SetColumnOffset(int column_index, float offset) { + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); if (column_index < 0) column_index = window->DC.ColumnsCurrent; IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const float t = (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); - window->DC.ColumnsData[column_index].OffsetNorm = t; + + const bool preserveWidth = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); + const float width = preserveWidth ? GetColumnWidth(column_index) : 0.0f; + + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin((float)(int)offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); + const float offsetNorm = PixelsToOffsetNorm(offset); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - window->DC.StateStorage->SetFloat(column_id, t); + window->DC.StateStorage->SetFloat(column_id, offsetNorm); + window->DC.ColumnsData[column_index].OffsetNorm = offsetNorm; + + if (preserveWidth) + SetColumnOffset(column_index+1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } float ImGui::GetColumnWidth(int column_index) @@ -9350,8 +9374,16 @@ float ImGui::GetColumnWidth(int column_index) if (column_index < 0) column_index = window->DC.ColumnsCurrent; - float w = GetColumnOffset(column_index+1) - GetColumnOffset(column_index); - return w; + return OffsetNormToPixels(window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); +} + +void ImGui::SetColumnWidth(int column_index, float width) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + if (column_index < 0) + column_index = window->DC.ColumnsCurrent; + + SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); } static void PushColumnClipRect(int column_index) @@ -9365,56 +9397,12 @@ static void PushColumnClipRect(int column_index) ImGui::PushClipRect(ImVec2(x1,-FLT_MAX), ImVec2(x2,+FLT_MAX), true); } -void ImGui::Columns(int columns_count, const char* id, bool border) +void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(columns_count >= 1); - - if (window->DC.ColumnsCount != 1) - { - if (window->DC.ColumnsCurrent != 0) - ItemSize(ImVec2(0,0)); // Advance to column 0 - PopItemWidth(); - PopClipRect(); - window->DrawList->ChannelsMerge(); - - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; - } - - // Draw columns borders and handle resize at the time of "closing" a columns set - if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1 && window->DC.ColumnsShowBorders && !window->SkipItems) - { - const float y1 = window->DC.ColumnsStartPosY; - const float y2 = window->DC.CursorPos.y; - for (int i = 1; i < window->DC.ColumnsCount; i++) - { - float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); - const ImRect column_rect(ImVec2(x-4,y1),ImVec2(x+4,y2)); - if (IsClippedEx(column_rect, &column_id, false)) - continue; - - bool hovered, held; - ButtonBehavior(column_rect, column_id, &hovered, &held); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; - - // Draw before resize so our items positioning are in sync with the line being drawn - const ImU32 col = GetColorU32(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column); - const float xi = (float)(int)x; - window->DrawList->AddLine(ImVec2(xi, y1+1.0f), ImVec2(xi, y2), col); - - if (held) - { - if (g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= 4; // Store from center of column line (we used a 8 wide rect for columns clicking) - x = GetDraggedColumnOffset(i); - SetColumnOffset(i, x); - } - } - } + IM_ASSERT(columns_count > 1); + IM_ASSERT(window->DC.ColumnsCount == 1); // Nested columns are currently not supported // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. @@ -9425,7 +9413,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) // Set state for first column window->DC.ColumnsCurrent = 0; window->DC.ColumnsCount = columns_count; - window->DC.ColumnsShowBorders = border; + window->DC.ColumnsFlags = flags; const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.x; window->DC.ColumnsMinX = window->DC.IndentX; // Lock our horizontal range @@ -9435,26 +9423,92 @@ void ImGui::Columns(int columns_count, const char* id, bool border) window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - if (window->DC.ColumnsCount != 1) + // Cache column offsets + window->DC.ColumnsData.resize(columns_count + 1); + for (int column_index = 0; column_index < columns_count + 1; column_index++) { - // Cache column offsets - window->DC.ColumnsData.resize(columns_count + 1); - for (int column_index = 0; column_index < columns_count + 1; column_index++) - { - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - KeepAliveID(column_id); - const float default_t = column_index / (float)window->DC.ColumnsCount; - const float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) - window->DC.ColumnsData[column_index].OffsetNorm = t; - } - window->DrawList->ChannelsSplit(window->DC.ColumnsCount); - PushColumnClipRect(); - PushItemWidth(GetColumnWidth() * 0.65f); - } - else - { - window->DC.ColumnsData.resize(0); + const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + KeepAliveID(column_id); + const float default_t = column_index / (float)window->DC.ColumnsCount; + float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); + window->DC.ColumnsData[column_index].OffsetNorm = t; } + window->DrawList->ChannelsSplit(window->DC.ColumnsCount); + PushColumnClipRect(); + PushItemWidth(GetColumnWidth() * 0.65f); +} + +void ImGui::EndColumns() +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(window->DC.ColumnsCount > 1); + + if (window->DC.ColumnsCurrent != 0) + ItemSize(ImVec2(0, 0)); // Advance to column 0 + PopItemWidth(); + PopClipRect(); + window->DrawList->ChannelsMerge(); + + window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; + + // Draw columns borders and handle resize + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + { + const float y1 = window->DC.ColumnsStartPosY; + const float y2 = window->DC.CursorPos.y; + for (int i = 1; i < window->DC.ColumnsCount; i++) + { + float x = window->Pos.x + GetColumnOffset(i); + const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); + const ImRect column_rect(ImVec2(x - 4, y1), ImVec2(x + 4, y2)); + if (IsClippedEx(column_rect, &column_id, false)) + continue; + + bool hovered, held; + ButtonBehavior(column_rect, column_id, &hovered, &held); + if (hovered || held) + g.MouseCursor = ImGuiMouseCursor_ResizeEW; + + // Draw before resize so our items positioning are in sync with the line being drawn + const ImU32 col = GetColorU32(held ? ImGuiCol_ColumnActive : hovered ? ImGuiCol_ColumnHovered : ImGuiCol_Column); + const float xi = (float)(int)x; + window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); + + if (held) + { + if (g.ActiveIdIsJustActivated) + g.ActiveIdClickOffset.x -= 4; // Store from center of column line (we used a 8 wide rect for columns clicking) + x = GetDraggedColumnOffset(i); + SetColumnOffset(i, x); + } + } + } + + window->DC.ColumnsSetId = 0; + window->DC.ColumnsCurrent = 0; + window->DC.ColumnsCount = 1; + window->DC.ColumnsFlags = 0; + window->DC.ColumnsData.resize(0); +} + +void ImGui::Columns(int columns_count, const char* id, bool border) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = GetCurrentWindow(); + IM_ASSERT(columns_count >= 1); + + ImGuiColumnsFlags flags = 0; + flags |= (border ? 0 : ImGuiColumnsFlags_NoBorder); + + if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1) + EndColumns(); + + if (columns_count != 1) + BeginColumns(id, columns_count, flags); } void ImGui::Indent(float indent_w) diff --git a/imgui.h b/imgui.h index edb1d68d..548d9cc6 100644 --- a/imgui.h +++ b/imgui.h @@ -73,6 +73,7 @@ typedef int ImGuiKey; // a key identifier (ImGui-side enum) // e typedef int ImGuiColorEditMode; // color edit mode for ColorEdit*() // enum ImGuiColorEditMode_ typedef int ImGuiMouseCursor; // a mouse cursor identifier // enum ImGuiMouseCursor_ typedef int ImGuiWindowFlags; // window flags for Begin*() // enum ImGuiWindowFlags_ +typedef int ImGuiColumnsFlags; // column flags for Columns() // enum ImGuiColumnsFlags_ typedef int ImGuiSetCond; // condition flags for Set*() // enum ImGuiSetCond_ typedef int ImGuiInputTextFlags; // flags for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags for Selectable() // enum ImGuiSelectableFlags_ @@ -221,13 +222,16 @@ namespace ImGui // Columns // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress and rather lacking. - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // setup number of columns. use an identifier to distinguish multiple column sets. close with Columns(1). - IMGUI_API void NextColumn(); // next column - IMGUI_API int GetColumnIndex(); // get current column index - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetcolumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this - IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column - IMGUI_API float GetColumnWidth(int column_index = -1); // column width (== GetColumnOffset(GetColumnIndex()+1) - GetColumnOffset(GetColumnOffset()) - IMGUI_API int GetColumnsCount(); // number of columns (what was passed to Columns()) + IMGUI_API void BeginColumns(const char* 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 NextColumn(); // next column, defaults to current row or next row if the current row is finished + IMGUI_API int GetColumnIndex(); // get current column index + IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column + IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column + IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this + IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column + IMGUI_API int GetColumnsCount(); + IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // ID scopes // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them. @@ -418,7 +422,7 @@ namespace ImGui IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. - IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame + IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame IMGUI_API void EndChildFrame(); IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); @@ -506,6 +510,15 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu() }; +// Flags for ImGui::Columns() +enum ImGuiColumnsFlags_ +{ + // Default: 0 + ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers + ImGuiColumnsFlags_NoPreserveWidths = 1 << 1, // Disable column width preservation when adjusting columns + ImGuiColumnsFlags_NoForceWithinWindow = 1 << 2 // Disable forcing columns to fit within window +}; + // Flags for ImGui::InputText() enum ImGuiInputTextFlags_ { @@ -1029,8 +1042,8 @@ struct ImGuiTextEditCallbackData struct ImGuiSizeConstraintCallbackData { void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() - ImVec2 Pos; // Read-only. Window position, for reference. - ImVec2 CurrentSize; // Read-only. Current window size. + ImVec2 Pos; // Read-only. Window position, for reference. + ImVec2 CurrentSize; // Read-only. Current window size. ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 544d6230..3ebdb8ab 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1400,6 +1400,49 @@ void ImGui::ShowTestWindow(bool* p_open) } */ + if (ImGui::TreeNode("Advanced settings")) + { + static bool border = true; + static bool preserveWidths = true; + static bool forceWithinWindow = true; + + ImGui::Checkbox("Border", &border); + ImGui::SameLine(); + ImGui::Checkbox("Preserve widths", &preserveWidths); + ImGui::SameLine(); + ImGui::Checkbox("Force within window", &forceWithinWindow); + + ImGuiColumnsFlags flags = 0; + flags |= (border ? 0 : ImGuiColumnsFlags_NoBorder); + flags |= (preserveWidths ? 0 : ImGuiColumnsFlags_NoPreserveWidths); + flags |= (forceWithinWindow ? 0 : ImGuiColumnsFlags_NoForceWithinWindow); + + ImGui::BeginColumns("AdvancedColumns", 4, flags); + ImGui::Separator(); + ImGui::Text("ID"); ImGui::NextColumn(); + ImGui::Text("Name"); ImGui::NextColumn(); + ImGui::Text("Path"); ImGui::NextColumn(); + ImGui::Text("Flags"); ImGui::NextColumn(); + ImGui::Separator(); + const char* names[3] = { "One", "Two", "Three" }; + const char* paths[3] = { "/path/one", "/path/two", "/path/three" }; + static int selected = -1; + for (int i = 0; i < 3; i++) + { + char label[32]; + sprintf(label, "%04d", i); + if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) + selected = i; + ImGui::NextColumn(); + ImGui::Text(names[i]); ImGui::NextColumn(); + ImGui::Text(paths[i]); ImGui::NextColumn(); + ImGui::Text("...."); ImGui::NextColumn(); + } + ImGui::EndColumns(); + ImGui::Separator(); + ImGui::TreePop(); + } + // Create multiple items in a same cell before switching to next column if (ImGui::TreeNode("Mixed items")) { diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ade41777..99004adc 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1145,8 +1145,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) ConfigData.push_back(*font_cfg); ImFontConfig& new_font_cfg = ConfigData.back(); - if (!new_font_cfg.DstFont) - new_font_cfg.DstFont = Fonts.back(); + if (!new_font_cfg.DstFont) + new_font_cfg.DstFont = Fonts.back(); if (!new_font_cfg.FontDataOwnedByAtlas) { new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize); diff --git a/imgui_internal.h b/imgui_internal.h index 08f206ad..9eed7b94 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -282,7 +282,7 @@ struct ImGuiGroupData // Per column data for Columns() struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) //float IndentX; }; @@ -571,7 +571,7 @@ struct IMGUI_API ImGuiDrawContext float ColumnsStartPosY; float ColumnsCellMinY; float ColumnsCellMaxY; - bool ColumnsShowBorders; + ImGuiColumnsFlags ColumnsFlags; ImGuiID ColumnsSetId; ImVector ColumnsData; @@ -603,7 +603,7 @@ struct IMGUI_API ImGuiDrawContext ColumnsMinX = ColumnsMaxX = 0.0f; ColumnsStartPosY = 0.0f; ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsShowBorders = true; + ColumnsFlags = 0; ColumnsSetId = 0; } }; From 19a42cb2fd864291419250e8c258a94761d620f2 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 18:44:48 +0800 Subject: [PATCH 02/11] Columns: Moved BeginColumns/EndColumns/flags from #913 to imgui_internals.h + minor shallow tweaks. Removed demo code temporarily. (#125) --- imgui.cpp | 26 ++++++++++++-------------- imgui.h | 15 ++------------- imgui_demo.cpp | 43 ------------------------------------------- imgui_internal.h | 14 +++++++++++++- 4 files changed, 27 insertions(+), 71 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8e774ab6..fbaf0801 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9928,15 +9928,13 @@ int ImGui::GetColumnsCount() return window->DC.ColumnsCount; } -static float OffsetNormToPixels(float offsetNorm) +static float OffsetNormToPixels(ImGuiWindow* window, float offset_norm) { - ImGuiWindow* window = ImGui::GetCurrentWindowRead(); - return offsetNorm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); + return offset_norm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); } -static float PixelsToOffsetNorm(float offset) +static float PixelsToOffsetNorm(ImGuiWindow* window, float offset) { - ImGuiWindow* window = ImGui::GetCurrentWindowRead(); return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); } @@ -9986,18 +9984,18 @@ void ImGui::SetColumnOffset(int column_index, float offset) IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const bool preserveWidth = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); - const float width = preserveWidth ? GetColumnWidth(column_index) : 0.0f; + const bool preserve_width = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); + const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) offset = ImMin((float)(int)offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); - const float offsetNorm = PixelsToOffsetNorm(offset); + const float offset_norm = PixelsToOffsetNorm(window, offset); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); - window->DC.StateStorage->SetFloat(column_id, offsetNorm); - window->DC.ColumnsData[column_index].OffsetNorm = offsetNorm; + window->DC.StateStorage->SetFloat(column_id, offset_norm); + window->DC.ColumnsData[column_index].OffsetNorm = offset_norm; - if (preserveWidth) + if (preserve_width) SetColumnOffset(column_index+1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } @@ -10007,7 +10005,7 @@ float ImGui::GetColumnWidth(int column_index) if (column_index < 0) column_index = window->DC.ColumnsCurrent; - return OffsetNormToPixels(window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); + return OffsetNormToPixels(window, window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); } void ImGui::SetColumnWidth(int column_index, float width) @@ -10066,7 +10064,7 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl const float default_t = column_index / (float)window->DC.ColumnsCount; float t = window->DC.StateStorage->GetFloat(column_id, default_t); // Cheaply store our floating point value inside the integer (could store a union into the map?) if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); + t = ImMin(t, PixelsToOffsetNorm(window, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); window->DC.ColumnsData[column_index].OffsetNorm = t; } window->DrawList->ChannelsSplit(window->DC.ColumnsCount); @@ -10098,7 +10096,7 @@ void ImGui::EndColumns() { float x = window->Pos.x + GetColumnOffset(i); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); - const float column_w = 4.0f; + const float column_w = 4.0f; // Width for interaction const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2)); if (IsClippedEx(column_rect, &column_id, false)) continue; diff --git a/imgui.h b/imgui.h index 8c6687a2..4fc0a9f9 100644 --- a/imgui.h +++ b/imgui.h @@ -231,9 +231,8 @@ namespace ImGui IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y // Columns - // You can also use SameLine(pos_x) for simplified columning. The columns API is still work-in-progress and rather lacking. - IMGUI_API void BeginColumns(const char* 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 + // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. + IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column @@ -241,7 +240,6 @@ namespace ImGui IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column IMGUI_API int GetColumnsCount(); - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); // ID scopes // If you are creating widgets in a loop you most likely want to push a unique identifier so ImGui can differentiate them. @@ -524,15 +522,6 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_ChildMenu = 1 << 27 // Don't use! For internal use by BeginMenu() }; -// Flags for ImGui::Columns() -enum ImGuiColumnsFlags_ -{ - // Default: 0 - ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers - ImGuiColumnsFlags_NoPreserveWidths = 1 << 1, // Disable column width preservation when adjusting columns - ImGuiColumnsFlags_NoForceWithinWindow = 1 << 2 // Disable forcing columns to fit within window -}; - // Flags for ImGui::InputText() enum ImGuiInputTextFlags_ { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 862e5533..4b901acf 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1553,49 +1553,6 @@ void ImGui::ShowTestWindow(bool* p_open) } */ - if (ImGui::TreeNode("Advanced settings")) - { - static bool border = true; - static bool preserveWidths = true; - static bool forceWithinWindow = true; - - ImGui::Checkbox("Border", &border); - ImGui::SameLine(); - ImGui::Checkbox("Preserve widths", &preserveWidths); - ImGui::SameLine(); - ImGui::Checkbox("Force within window", &forceWithinWindow); - - ImGuiColumnsFlags flags = 0; - flags |= (border ? 0 : ImGuiColumnsFlags_NoBorder); - flags |= (preserveWidths ? 0 : ImGuiColumnsFlags_NoPreserveWidths); - flags |= (forceWithinWindow ? 0 : ImGuiColumnsFlags_NoForceWithinWindow); - - ImGui::BeginColumns("AdvancedColumns", 4, flags); - ImGui::Separator(); - ImGui::Text("ID"); ImGui::NextColumn(); - ImGui::Text("Name"); ImGui::NextColumn(); - ImGui::Text("Path"); ImGui::NextColumn(); - ImGui::Text("Flags"); ImGui::NextColumn(); - ImGui::Separator(); - const char* names[3] = { "One", "Two", "Three" }; - const char* paths[3] = { "/path/one", "/path/two", "/path/three" }; - static int selected = -1; - for (int i = 0; i < 3; i++) - { - char label[32]; - sprintf(label, "%04d", i); - if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns)) - selected = i; - ImGui::NextColumn(); - ImGui::Text(names[i]); ImGui::NextColumn(); - ImGui::Text(paths[i]); ImGui::NextColumn(); - ImGui::Text("...."); ImGui::NextColumn(); - } - ImGui::EndColumns(); - ImGui::Separator(); - ImGui::TreePop(); - } - // Create multiple items in a same cell before switching to next column if (ImGui::TreeNode("Mixed items")) { diff --git a/imgui_internal.h b/imgui_internal.h index e83ebbe5..7d7f3fa8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -183,6 +183,14 @@ enum ImGuiSliderFlags_ ImGuiSliderFlags_Vertical = 1 << 0 }; +enum ImGuiColumnsFlags_ +{ + // Default: 0 + ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers + ImGuiColumnsFlags_NoPreserveWidths = 1 << 1, // Disable column width preservation when adjusting columns + ImGuiColumnsFlags_NoForceWithinWindow = 1 << 2 // Disable forcing columns to fit within window +}; + enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ @@ -598,7 +606,7 @@ struct IMGUI_API ImGuiDrawContext float ColumnsStartPosY; float ColumnsCellMinY; float ColumnsCellMaxY; - ImGuiColumnsFlags ColumnsFlags; + ImGuiColumnsFlags ColumnsFlags; ImGuiID ColumnsSetId; ImVector ColumnsData; @@ -748,6 +756,10 @@ namespace ImGui IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing); IMGUI_API bool IsPopupOpen(ImGuiID id); + // New Columns API + IMGUI_API void BeginColumns(const char* 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 + // NB: All position are in absolute pixels coordinates (never using window coordinates internally) // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); From 3bf2af23e641909890a568850e5dac8ebf8930f8 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 18:44:54 +0800 Subject: [PATCH 03/11] Columns: Fixed EndColumns() not repositioning the cursor. (#913) --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index fbaf0801..0837b93d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10126,6 +10126,8 @@ void ImGui::EndColumns() window->DC.ColumnsCount = 1; window->DC.ColumnsFlags = 0; window->DC.ColumnsData.resize(0); + window->DC.ColumnsOffsetX = 0.0f; + window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } // [2017/08: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] From a511b00226c31654b4cf99e027d6d51baf19d710 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 19:19:31 +0800 Subject: [PATCH 04/11] Columns: Fixed offset rounding leading to SetColumnOffset() being destructive when ImGuiColumnsFlags_NoPreserveWidths flag is not set. (#913, #125) --- imgui.cpp | 6 +++--- imgui.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0837b93d..08d63a8f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9952,7 +9952,7 @@ static float GetDraggedColumnOffset(int column_index) if ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); - return (float)(int)x; + return x; } float ImGui::GetColumnOffset(int column_index) @@ -9972,7 +9972,7 @@ float ImGui::GetColumnOffset(int column_index) IM_ASSERT(column_index < window->DC.ColumnsData.Size); const float t = window->DC.ColumnsData[column_index].OffsetNorm; const float x_offset = ImLerp(window->DC.ColumnsMinX, window->DC.ColumnsMaxX, t); - return (float)(int)x_offset; + return x_offset; } void ImGui::SetColumnOffset(int column_index, float offset) @@ -9988,7 +9988,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - offset = ImMin((float)(int)offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); + offset = ImMin(offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); const float offset_norm = PixelsToOffsetNorm(window, offset); const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); diff --git a/imgui.h b/imgui.h index 4fc0a9f9..7c102f7d 100644 --- a/imgui.h +++ b/imgui.h @@ -237,7 +237,7 @@ namespace ImGui IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is usually 0.0f and not resizable unless you call this + IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column IMGUI_API int GetColumnsCount(); From 9307631c901aae10601dd669a98c9793064004fe Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 19:25:29 +0800 Subject: [PATCH 05/11] Columns: Removed unnecessary/misleading dummy ItemSize(). Was fixed already before, and fixed again in this branch by 3bf2af23e641909890a568850e5dac8ebf8930f8. (#913, #125). End() calls EndColumns() directly. --- imgui.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 08d63a8f..fb43a4e6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4450,7 +4450,7 @@ void ImGui::End() ImGuiWindow* window = g.CurrentWindow; if (window->DC.ColumnsCount != 1) // close columns set if any is open - Columns(1, "#CLOSECOLUMNS"); + EndColumns(); PopClipRect(); // inner window clip rectangle // Stop logging @@ -10078,8 +10078,6 @@ void ImGui::EndColumns() ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(window->DC.ColumnsCount > 1); - if (window->DC.ColumnsCurrent != 0) - ItemSize(ImVec2(0, 0)); // Advance to column 0 PopItemWidth(); PopClipRect(); window->DrawList->ChannelsMerge(); From e70d49ba1f32b9a39550c32656468cb62f5bc964 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 19:30:57 +0800 Subject: [PATCH 06/11] Columns: Fixed one form of shearing during resizing columns with PreserveWidth enabled (there's another issue still). (#913, #125) --- imgui.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fb43a4e6..f32523cf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9996,7 +9996,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) window->DC.ColumnsData[column_index].OffsetNorm = offset_norm; if (preserve_width) - SetColumnOffset(column_index+1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); + SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } float ImGui::GetColumnWidth(int column_index) @@ -10090,6 +10090,7 @@ void ImGui::EndColumns() { const float y1 = window->DC.ColumnsStartPosY; const float y2 = window->DC.CursorPos.y; + int dragging_column = -1; for (int i = 1; i < window->DC.ColumnsCount; i++) { float x = window->Pos.x + GetColumnOffset(i); @@ -10098,25 +10099,28 @@ void ImGui::EndColumns() const ImRect column_rect(ImVec2(x - column_w, y1), ImVec2(x + column_w, y2)); if (IsClippedEx(column_rect, &column_id, false)) continue; - - bool hovered, held; + + bool hovered, held; ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeEW; + if (held && g.ActiveIdIsJustActivated) + g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). + if (held) + dragging_column = i; - // Draw before resize so our items positioning are in sync with the line being drawn - const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); - const float xi = (float)(int)x; - window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); + // Draw column + const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); + const float xi = (float)(int)x; + window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col); + } - if (held) - { - if (g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking) - x = GetDraggedColumnOffset(i); - SetColumnOffset(i, x); - } - } + // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. + if (dragging_column != -1) + { + float x = GetDraggedColumnOffset(dragging_column); + SetColumnOffset(dragging_column, x); + } } window->DC.ColumnsSetId = 0; From 7f0063f85849ae51eb3d291426cfc3e9da1b1507 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 19:32:18 +0800 Subject: [PATCH 07/11] Columns: Added ImGuiColumnsFlags_NoResize flag (internal). (#913, #125) --- imgui.cpp | 19 +++++++++++-------- imgui_internal.h | 5 +++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f32523cf..7c7a7636 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10100,14 +10100,17 @@ void ImGui::EndColumns() if (IsClippedEx(column_rect, &column_id, false)) continue; - bool hovered, held; - ButtonBehavior(column_rect, column_id, &hovered, &held); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeEW; - if (held && g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). - if (held) - dragging_column = i; + bool hovered = false, held = false; + if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize)) + { + ButtonBehavior(column_rect, column_id, &hovered, &held); + if (hovered || held) + g.MouseCursor = ImGuiMouseCursor_ResizeEW; + if (held && g.ActiveIdIsJustActivated) + g.ActiveIdClickOffset.x -= column_w; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). + if (held) + dragging_column = i; + } // Draw column const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); diff --git a/imgui_internal.h b/imgui_internal.h index 7d7f3fa8..f73cdcc8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -187,8 +187,9 @@ enum ImGuiColumnsFlags_ { // Default: 0 ImGuiColumnsFlags_NoBorder = 1 << 0, // Disable column dividers - ImGuiColumnsFlags_NoPreserveWidths = 1 << 1, // Disable column width preservation when adjusting columns - ImGuiColumnsFlags_NoForceWithinWindow = 1 << 2 // Disable forcing columns to fit within window + ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers + ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns + ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3 // Disable forcing columns to fit within window }; enum ImGuiSelectableFlagsPrivate_ From 1c83b073c66341ea7b22d7dd42916094c9a0fdeb Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 20:37:04 +0800 Subject: [PATCH 08/11] Columns: A set of column (and most importantly the right-most column) do not register its content to the parent, not affecting the window contents size. (#519, #125, #913) --- imgui.cpp | 3 +++ imgui_internal.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 7c7a7636..f20646e8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4345,6 +4345,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.ColumnsCurrent = 0; window->DC.ColumnsCount = 1; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; + window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPosY; window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; @@ -10051,6 +10052,7 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl window->DC.ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; + window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); @@ -10084,6 +10086,7 @@ void ImGui::EndColumns() window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; + window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX); // Columns don't grow parent // Draw columns borders and handle resize if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) diff --git a/imgui_internal.h b/imgui_internal.h index f73cdcc8..d47c7702 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -605,6 +605,7 @@ struct IMGUI_API ImGuiDrawContext float ColumnsMinX; float ColumnsMaxX; float ColumnsStartPosY; + float ColumnsStartMaxPosX; // Backup of CursorMaxPos float ColumnsCellMinY; float ColumnsCellMaxY; ImGuiColumnsFlags ColumnsFlags; @@ -638,6 +639,7 @@ struct IMGUI_API ImGuiDrawContext ColumnsCount = 1; ColumnsMinX = ColumnsMaxX = 0.0f; ColumnsStartPosY = 0.0f; + ColumnsStartMaxPosX = 0.0f; ColumnsCellMinY = ColumnsCellMaxY = 0.0f; ColumnsFlags = 0; ColumnsSetId = 0; From 7ff1c149b5657ee83c9146b6a467040ca0bbe921 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 20:40:25 +0800 Subject: [PATCH 09/11] Columns: Fixed another form of shearing made visible by the PreserveWidth option. The code was initially added in c46d5634d43c9f0296d845478c07b04f2c40d339 to fix because we've fixed in e42aaede42eb6d8a47cf104f3afd6057b13a61ee. (#913, #125) --- imgui.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index f20646e8..a7ff9122 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9958,17 +9958,19 @@ static float GetDraggedColumnOffset(int column_index) float ImGui::GetColumnOffset(int column_index) { - ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); if (column_index < 0) column_index = window->DC.ColumnsCurrent; + /* if (g.ActiveId) { + ImGuiContext& g = *GImGui; const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); if (g.ActiveId == column_id) return GetDraggedColumnOffset(column_index); } + */ IM_ASSERT(column_index < window->DC.ColumnsData.Size); const float t = window->DC.ColumnsData[column_index].OffsetNorm; @@ -10148,6 +10150,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); + //flags |= ImGuiColumnsFlags_NoPreserveWidths | ImGuiColumnsFlags_NoForceWithinWindow; // NB: Legacy behavior if (columns_count != 1) BeginColumns(id, columns_count, flags); } From 1ebd7ec0494a1b97ee5ce06ad0ffb4d0964d7bff Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 20:56:11 +0800 Subject: [PATCH 10/11] Demo: Columns: Added Horizontal Scrolling demo. Tweaked another Columns demo. (#519, #125, #913) --- imgui.cpp | 2 +- imgui_demo.cpp | 79 +++++++++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 31 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a7ff9122..33b9178f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10150,7 +10150,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); - //flags |= ImGuiColumnsFlags_NoPreserveWidths | ImGuiColumnsFlags_NoForceWithinWindow; // NB: Legacy behavior + //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior if (columns_count != 1) BeginColumns(id, columns_count, flags); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4b901acf..73a65808 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1527,32 +1527,6 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - // Scrolling columns - /* - if (ImGui::TreeNode("Scrolling")) - { - ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y)); - ImGui::Columns(3); - ImGui::Text("ID"); ImGui::NextColumn(); - ImGui::Text("Name"); ImGui::NextColumn(); - ImGui::Text("Path"); ImGui::NextColumn(); - ImGui::Columns(1); - ImGui::Separator(); - ImGui::EndChild(); - ImGui::BeginChild("##scrollingregion", ImVec2(0, 60)); - ImGui::Columns(3); - for (int i = 0; i < 10; i++) - { - ImGui::Text("%04d", i); ImGui::NextColumn(); - ImGui::Text("Foobar"); ImGui::NextColumn(); - ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn(); - } - ImGui::Columns(1); - ImGui::EndChild(); - ImGui::TreePop(); - } - */ - // Create multiple items in a same cell before switching to next column if (ImGui::TreeNode("Mixed items")) { @@ -1570,7 +1544,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("An extra line here."); ImGui::NextColumn(); - ImGui::Text("Sailor"); + ImGui::Text("Sailor"); ImGui::Button("Corniflower"); static float bar = 1.0f; ImGui::InputFloat("blue", &bar, 0.05f, 0, 3); @@ -1607,14 +1581,59 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::SameLine(); ImGui::Checkbox("vertical", &v_borders); ImGui::Columns(4, NULL, v_borders); - if (h_borders) ImGui::Separator(); - for (int i = 0; i < 8; i++) + 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\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset()); ImGui::NextColumn(); } ImGui::Columns(1); - if (h_borders) ImGui::Separator(); + if (h_borders) + ImGui::Separator(); + ImGui::TreePop(); + } + + // Scrolling columns + /* + if (ImGui::TreeNode("Vertical Scrolling")) + { + ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y)); + ImGui::Columns(3); + ImGui::Text("ID"); ImGui::NextColumn(); + ImGui::Text("Name"); ImGui::NextColumn(); + ImGui::Text("Path"); ImGui::NextColumn(); + ImGui::Columns(1); + ImGui::Separator(); + ImGui::EndChild(); + ImGui::BeginChild("##scrollingregion", ImVec2(0, 60)); + ImGui::Columns(3); + for (int i = 0; i < 10; i++) + { + ImGui::Text("%04d", i); ImGui::NextColumn(); + ImGui::Text("Foobar"); ImGui::NextColumn(); + ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn(); + } + ImGui::Columns(1); + ImGui::EndChild(); + ImGui::TreePop(); + } + */ + + if (ImGui::TreeNode("Horizontal Scrolling")) + { + ImGui::SetNextWindowContentWidth(2000); + ImGui::BeginChild("##scrollingregion", ImVec2(0, 120), false, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::Columns(10); + for (int i = 0; i < 20; i++) + for (int j = 0; j < 10; j++) + { + ImGui::Text("Line %d Column %d", i, j); + ImGui::NextColumn(); + } + ImGui::Columns(1); + ImGui::EndChild(); ImGui::TreePop(); } From 83e8d10fabc1b8a9cf069c64edeba53b65e6be63 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 20 Aug 2017 21:08:07 +0800 Subject: [PATCH 11/11] Columns: Columns set resize based on the presence of vertical scrollbar. Not 100% sure about that but it looks like we've fixed enough bugs that this may not cause troubles anymore. (#125, #913, #893, #1138) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 33b9178f..c677e79d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10052,7 +10052,8 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : window->Size.x; window->DC.ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range - window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + //window->DC.ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + window->DC.ColumnsMaxX = content_region_width - window->Scroll.x - window->ScrollbarSizes.x; window->DC.ColumnsStartPosY = window->DC.CursorPos.y; window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y;