From 78320aa633a2bb107d3da7925d7f4ab1cdd65704 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 18:37:58 +0100 Subject: [PATCH] Columns: Refactor: Moved columns data into their own data structure. Minimum changes now to ease diffing. (#125, #1499) --- imgui.cpp | 214 ++++++++++++++++++++++++++--------------------- imgui_internal.h | 70 +++++++++------- 2 files changed, 158 insertions(+), 126 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c20916ef..bc60f574 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -627,8 +627,6 @@ // Forward Declarations //------------------------------------------------------------------------- -static float GetDraggedColumnOffset(int column_index); - static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static ImFont* GetDefaultFont(); @@ -1744,8 +1742,8 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) ImGuiWindow* window = ImGui::GetCurrentWindow(); window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. - if (window->DC.ColumnsCount > 1) - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + if (window->DC.ColumnsSet) + window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -4833,11 +4831,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.ItemFlagsStack.resize(0); window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); - 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.ColumnsSet = NULL; window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); @@ -4990,7 +4984,7 @@ void ImGui::End() ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (window->DC.ColumnsCount != 1) // close columns set if any is open + if (window->DC.ColumnsSet != NULL) EndColumns(); PopClipRect(); // inner window clip rectangle @@ -5736,8 +5730,8 @@ ImVec2 ImGui::GetContentRegionMax() { ImGuiWindow* window = GetCurrentWindowRead(); ImVec2 mx = window->ContentsRegionRect.Max; - if (window->DC.ColumnsCount != 1) - mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; + if (window->DC.ColumnsSet) + mx.x = GetColumnOffset(window->DC.ColumnsSet->ColumnsCurrent + 1) - window->WindowPadding.x; return mx; } @@ -9347,7 +9341,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) // FIXME-OPT: Avoid if vertically clipped. + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) // FIXME-OPT: Avoid if vertically clipped. PopClipRect(); ImGuiID id = window->GetID(label); @@ -9378,7 +9372,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl bb_with_spacing.Max.y += spacing_D; if (!ItemAdd(bb_with_spacing, id)) { - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) PushColumnClipRect(); return false; } @@ -9400,7 +9394,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f); } - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) { PushColumnClipRect(); bb_with_spacing.Max.x -= (GetContentRegionMax().x - max_x); @@ -10552,7 +10546,7 @@ void ImGui::Separator() } // Horizontal Separator - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) PopClipRect(); float x1 = window->Pos.x; @@ -10564,7 +10558,7 @@ void ImGui::Separator() ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout. if (!ItemAdd(bb, 0)) { - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) PushColumnClipRect(); return; } @@ -10574,10 +10568,10 @@ void ImGui::Separator() if (g.LogEnabled) LogRenderedText(NULL, IM_NEWLINE "--------------------------------"); - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) { PushColumnClipRect(); - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; + window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; } } @@ -10790,29 +10784,30 @@ void ImGui::NewLine() void ImGui::NextColumn() { ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems || window->DC.ColumnsCount <= 1) + if (window->SkipItems || window->DC.ColumnsSet == NULL) return; ImGuiContext& g = *GImGui; PopItemWidth(); PopClipRect(); - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - if (++window->DC.ColumnsCurrent < window->DC.ColumnsCount) + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); + if (++columns->ColumnsCurrent < columns->ColumnsCount) { // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; - window->DrawList->ChannelsSetCurrent(window->DC.ColumnsCurrent); + window->DC.ColumnsOffsetX = GetColumnOffset(columns->ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DrawList->ChannelsSetCurrent(columns->ColumnsCurrent); } else { - window->DC.ColumnsCurrent = 0; window->DC.ColumnsOffsetX = 0.0f; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY; + columns->ColumnsCurrent = 0; + columns->ColumnsCellMinY = columns->ColumnsCellMaxY; window->DrawList->ChannelsSetCurrent(0); } window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - window->DC.CursorPos.y = window->DC.ColumnsCellMinY; + window->DC.CursorPos.y = columns->ColumnsCellMinY; window->DC.CurrentLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = 0.0f; @@ -10823,37 +10818,37 @@ void ImGui::NextColumn() int ImGui::GetColumnIndex() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsCurrent; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCurrent : 0; } int ImGui::GetColumnsCount() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsCount; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCount : 1; } -static float OffsetNormToPixels(ImGuiWindow* window, float offset_norm) +static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm) { - return offset_norm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); + return offset_norm * (columns->ColumnsMaxX - columns->ColumnsMinX); } -static float PixelsToOffsetNorm(ImGuiWindow* window, float offset) +static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) { - return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); + return (offset - columns->ColumnsMinX) / (columns->ColumnsMaxX - columns->ColumnsMinX); } -static float GetDraggedColumnOffset(int column_index) +static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, 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 // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; 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 == columns->ColumnsSetId + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); - if ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) + if ((columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); return x; @@ -10862,44 +10857,50 @@ static float GetDraggedColumnOffset(int column_index) float ImGui::GetColumnOffset(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; /* if (g.ActiveId) { ImGuiContext& g = *GImGui; - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); if (g.ActiveId == column_id) - return GetDraggedColumnOffset(column_index); + return GetDraggedColumnOffset(columns, 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); + IM_ASSERT(column_index < columns->ColumnsData.Size); + const float t = columns->ColumnsData[column_index].OffsetNorm; + const float x_offset = ImLerp(columns->ColumnsMinX, columns->ColumnsMaxX, t); return x_offset; } void ImGui::SetColumnOffset(int column_index, float offset) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow* window = g.CurrentWindow; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; - IM_ASSERT(column_index < window->DC.ColumnsData.Size); + IM_ASSERT(column_index < columns->ColumnsData.Size); - const bool preserve_width = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); + const bool preserve_width = !(columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->ColumnsCount-1); const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - offset = ImMin(offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); - const float offset_norm = PixelsToOffsetNorm(window, offset); + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin(offset, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index)); + const float offset_norm = PixelsToOffsetNorm(columns, offset); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); window->DC.StateStorage->SetFloat(column_id, offset_norm); - window->DC.ColumnsData[column_index].OffsetNorm = offset_norm; + columns->ColumnsData[column_index].OffsetNorm = offset_norm; if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); @@ -10908,70 +10909,91 @@ void ImGui::SetColumnOffset(int column_index, float offset) float ImGui::GetColumnWidth(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); - return OffsetNormToPixels(window, window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); + if (column_index < 0) + column_index = columns->ColumnsCurrent; + return OffsetNormToPixels(columns, columns->ColumnsData[column_index+1].OffsetNorm - columns->ColumnsData[column_index].OffsetNorm); } void ImGui::SetColumnWidth(int column_index, float width) { ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) + column_index = columns->ColumnsCurrent; SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); } void ImGui::PushColumnClipRect(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; - PushClipRect(window->DC.ColumnsData[column_index].ClipRect.Min, window->DC.ColumnsData[column_index].ClipRect.Max, false); + PushClipRect(columns->ColumnsData[column_index].ClipRect.Min, columns->ColumnsData[column_index].ClipRect.Max, false); } -void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags flags) +static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) +{ + for (int n = 0; n < window->DC.ColumnsSets.Size; n++) + if (window->DC.ColumnsSets[n].ColumnsSetId == id) + return &window->DC.ColumnsSets[n]; + + window->DC.ColumnsSets.push_back(ImGuiColumnsSet()); + ImGuiColumnsSet* columns = &window->DC.ColumnsSets.back(); + columns->ColumnsSetId = id; + return columns; +} + +void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count > 1); - IM_ASSERT(window->DC.ColumnsCount == 1); // Nested columns are currently not supported + IM_ASSERT(window->DC.ColumnsSet == NULL); // 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. - PushID(0x11223347 + (id ? 0 : columns_count)); - window->DC.ColumnsSetId = window->GetID(id ? id : "columns"); + PushID(0x11223347 + (str_id ? 0 : columns_count)); + ImGuiID id = window->GetID(str_id ? str_id : "columns"); PopID(); + ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); + IM_ASSERT(columns->ColumnsSetId == id); + window->DC.ColumnsSet = columns; + // Set state for first column - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = columns_count; - window->DC.ColumnsFlags = flags; + columns->ColumnsCurrent = 0; + columns->ColumnsCount = columns_count; + columns->ColumnsFlags = flags; const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.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->DC.ColumnsStartPosY = window->DC.CursorPos.y; - window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; + columns->ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range + //column->ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + columns->ColumnsMaxX = content_region_width - window->Scroll.x; + columns->ColumnsStartPosY = window->DC.CursorPos.y; + columns->ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; + columns->ColumnsCellMinY = columns->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); // Cache column offsets - window->DC.ColumnsData.resize(columns_count + 1); + columns->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); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); KeepAliveID(column_id); - const float default_t = column_index / (float)window->DC.ColumnsCount; + const float default_t = column_index / (float)columns_count; float t = window->DC.StateStorage->GetFloat(column_id, default_t); - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(window, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); - window->DC.ColumnsData[column_index].OffsetNorm = t; + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(columns, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index))); + columns->ColumnsData[column_index].OffsetNorm = t; } // Cache clipping rectangles @@ -10979,11 +11001,11 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl { float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); - window->DC.ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - window->DC.ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); + columns->ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + columns->ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); } - window->DrawList->ChannelsSplit(window->DC.ColumnsCount); + window->DrawList->ChannelsSplit(columns->ColumnsCount); PushColumnClipRect(); PushItemWidth(GetColumnWidth() * 0.65f); } @@ -10992,34 +11014,35 @@ void ImGui::EndColumns() { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(window->DC.ColumnsCount > 1); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); PopItemWidth(); PopClipRect(); window->DrawList->ChannelsMerge(); - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) - window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX); // Restore cursor max pos, as columns don't grow parent + columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = columns->ColumnsCellMaxY; + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) + window->DC.CursorMaxPos.x = ImMax(columns->ColumnsStartMaxPosX, columns->ColumnsMaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { - const float y1 = window->DC.ColumnsStartPosY; + const float y1 = columns->ColumnsStartPosY; const float y2 = window->DC.CursorPos.y; int dragging_column = -1; - for (int i = 1; i < window->DC.ColumnsCount; i++) + for (int i = 1; i < columns->ColumnsCount; i++) { float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(i); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); if (IsClippedEx(column_rect, column_id, false)) continue; bool hovered = false, held = false; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize)) + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoResize)) { ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) @@ -11040,16 +11063,13 @@ void ImGui::EndColumns() // 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); + float x = GetDraggedColumnOffset(columns, dragging_column); SetColumnOffset(dragging_column, x); } } - window->DC.ColumnsSetId = 0; - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = 1; - window->DC.ColumnsFlags = 0; - window->DC.ColumnsData.resize(0); + columns->ColumnsData.resize(0); + window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } @@ -11060,7 +11080,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1) + if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->ColumnsCount != columns_count) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); diff --git a/imgui_internal.h b/imgui_internal.h index b8f7e992..30ac9707 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -331,14 +331,6 @@ struct ImGuiGroupData bool AdvanceCursor; }; -// Per column data for Columns() -struct ImGuiColumnData -{ - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) - ImRect ClipRect; - //float IndentX; -}; - // Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper. struct IMGUI_API ImGuiSimpleColumns { @@ -420,6 +412,42 @@ struct ImGuiPopupRef ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; +// Per column data for Columns() +struct ImGuiColumnData +{ + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + ImRect ClipRect; +}; + +struct ImGuiColumnsSet +{ + int ColumnsCurrent; + int ColumnsCount; + float ColumnsMinX; + float ColumnsMaxX; + float ColumnsStartPosY; + float ColumnsStartMaxPosX; // Backup of CursorMaxPos + float ColumnsCellMinY; + float ColumnsCellMaxY; + ImGuiColumnsFlags ColumnsFlags; + ImGuiID ColumnsSetId; + ImVector ColumnsData; + + ImGuiColumnsSet() { Clear(); } + void Clear() + { + ColumnsCurrent = 0; + ColumnsCount = 1; + ColumnsMinX = ColumnsMaxX = 0.0f; + ColumnsStartPosY = 0.0f; + ColumnsStartMaxPosX = 0.0f; + ColumnsCellMinY = ColumnsCellMaxY = 0.0f; + ColumnsFlags = 0; + ColumnsSetId = 0; + ColumnsData.clear(); + } +}; + // Main state for ImGui struct ImGuiContext { @@ -674,17 +702,8 @@ struct IMGUI_API ImGuiDrawContext float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) float GroupOffsetX; float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - int ColumnsCurrent; - int ColumnsCount; - float ColumnsMinX; - float ColumnsMaxX; - float ColumnsStartPosY; - float ColumnsStartMaxPosX; // Backup of CursorMaxPos - float ColumnsCellMinY; - float ColumnsCellMaxY; - ImGuiColumnsFlags ColumnsFlags; - ImGuiID ColumnsSetId; - ImVector ColumnsData; + ImGuiColumnsSet* ColumnsSet; + ImVector ColumnsSets; ImGuiDrawContext() { @@ -708,14 +727,7 @@ struct IMGUI_API ImGuiDrawContext IndentX = 0.0f; GroupOffsetX = 0.0f; ColumnsOffsetX = 0.0f; - ColumnsCurrent = 0; - ColumnsCount = 1; - ColumnsMinX = ColumnsMaxX = 0.0f; - ColumnsStartPosY = 0.0f; - ColumnsStartMaxPosX = 0.0f; - ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsFlags = 0; - ColumnsSetId = 0; + ColumnsSet = NULL; } }; @@ -877,8 +889,8 @@ namespace ImGui IMGUI_API bool IsDragDropPayloadBeingAccepted(); // FIXME-WIP: 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 + IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). + IMGUI_API void EndColumns(); // close columns IMGUI_API void PushColumnClipRect(int column_index = -1); // NB: All position are in absolute pixels coordinates (never using window coordinates internally)