diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 667e197e..99cec37f 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -96,7 +96,7 @@ static const float TABLE_RESIZE_SEPARATOR_HALF_THICKNESS = 4.0f; // Extend ou static const float TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER = 0.06f; // Delay/timer before making the hover feedback (color+cursor) visible because tables/columns tends to be more cramped. // Helper -inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags) +inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_window) { // Adjust flags: set default sizing policy if ((flags & ImGuiTableFlags_SizingPolicyMaskX_) == 0) @@ -122,6 +122,15 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags) if (flags & ImGuiTableFlags_NoBordersInBodyUntilResize) flags &= ~ImGuiTableFlags_NoBordersInBody; + // Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set) +#ifdef IMGUI_HAS_DOCK + ImGuiWindow* window_for_settings = outer_window->RootWindowDockStop; +#else + ImGuiWindow* window_for_settings = outer_window->RootWindow; +#endif + if (window_for_settings->Flags & ImGuiWindowFlags_NoSavedSettings) + flags |= ImGuiTableFlags_NoSavedSettings; + return flags; } @@ -163,6 +172,34 @@ bool ImGui::BeginTable(const char* str_id, int columns_count, ImGuiTableFlags return BeginTableEx(str_id, id, columns_count, flags, outer_size, inner_width); } +// For reference, the total _allocation count_ for a table is: +// + 0 (for ImGuiTable instance, we sharing allocation in g.Tables pool) +// + 1 (for table->RawData allocated below) +// + 1 (for table->Splitter._Channels) +// + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels) +// Where active_channels_count is variable but often == columns_count or columns_count + 1, see TableUpdateDrawChannels() for details. +// Unused channels don't perform their +2 allocations. +static void TableBeginInitMemory(ImGuiTable* table, int columns_count) +{ + // Allocate single buffer for our arrays + ImSpanAllocator<3> span_allocator; + span_allocator.ReserveBytes(0, columns_count * sizeof(ImGuiTableColumn)); + span_allocator.ReserveBytes(1, columns_count * sizeof(ImS8)); + span_allocator.ReserveBytes(2, columns_count * sizeof(ImGuiTableCellData)); + table->RawData.resize(span_allocator.GetArenaSizeInBytes()); + span_allocator.SetArenaBasePtr(table->RawData.Data); + span_allocator.GetSpan(0, &table->Columns); + span_allocator.GetSpan(1, &table->DisplayOrderToIndex); + span_allocator.GetSpan(2, &table->RowCellData); + + for (int n = 0; n < columns_count; n++) + { + table->Columns[n] = ImGuiTableColumn(); + table->Columns[n].DisplayOrder = table->DisplayOrderToIndex[n] = (ImS8)n; + } + table->IsInitializing = table->IsSettingsRequestLoad = table->IsSortSpecsDirty = true; +} + bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width) { ImGuiContext& g = *GImGui; @@ -175,37 +212,28 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG if (flags & ImGuiTableFlags_ScrollX) IM_ASSERT(inner_width >= 0.0f); + // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping rules may evolve. const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0; const ImVec2 avail_size = GetContentRegionAvail(); ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f); ImRect outer_rect(outer_window->DC.CursorPos, outer_window->DC.CursorPos + actual_outer_size); - - // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping rules may evolve. if (use_child_window && IsClippedEx(outer_rect, 0, false)) { ItemSize(outer_rect); return false; } - flags = TableFixFlags(flags); - - // Inherit _NoSavedSettings from top-level window (child windows always have _NoSavedSettings set) -#ifdef IMGUI_HAS_DOCK - ImGuiWindow* window_for_settings = outer_window->RootWindowDockStop; -#else - ImGuiWindow* window_for_settings = outer_window->RootWindow; -#endif - if (window_for_settings->Flags & ImGuiWindowFlags_NoSavedSettings) - flags |= ImGuiTableFlags_NoSavedSettings; - // Acquire storage for the table ImGuiTable* table = g.Tables.GetOrAddByKey(id); - const ImGuiTableFlags table_last_flags = table->Flags; const int instance_no = (table->LastFrameActive != g.FrameCount) ? 0 : table->InstanceCurrent + 1; const ImGuiID instance_id = id + instance_no; + const ImGuiTableFlags table_last_flags = table->Flags; if (instance_no > 0) IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID"); + // Fix flags + flags = TableFixFlags(flags, outer_window); + // Initialize table->ID = id; table->Flags = flags; @@ -248,7 +276,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG IM_ASSERT(table->InnerWindow->WindowPadding.x == 0.0f && table->InnerWindow->WindowPadding.y == 0.0f && table->InnerWindow->WindowBorderSize == 0.0f); } - // Push a standardized ID for both child and not-child using tables, equivalent to BeginTable() doing PushID(label) matching + // Push a standardized ID for both child-using and not-child-using tables PushOverrideID(instance_id); // Backup a copy of host window members we will modify @@ -306,38 +334,12 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG if ((table_last_flags & ImGuiTableFlags_Reorderable) && !(flags & ImGuiTableFlags_Reorderable)) table->IsResetDisplayOrderRequest = true; - // Setup default columns state. Clear data if columns count changed + // Setup memory buffer (clear data if columns count changed) const int stored_size = table->Columns.size(); if (stored_size != 0 && stored_size != columns_count) table->RawData.resize(0); if (table->RawData.Size == 0) - { - // For reference, the total _allocation count_ for a table is: - // + 0 (for ImGuiTable instance, we sharing allocation in g.Tables pool) - // + 1 (for table->RawData allocated below) - // + 1 (for table->Splitter._Channels) - // + 2 * active_channels_count (for ImDrawCmd and ImDrawIdx buffers inside channels) - // Where active_channels_count is variable but often == columns_count or columns_count + 1, see TableUpdateDrawChannels() for details. - // Unused channels don't perform their +2 allocations. - - // Allocate single buffer for our arrays - ImSpanAllocator<3> span_allocator; - span_allocator.ReserveBytes(0, columns_count * sizeof(ImGuiTableColumn)); - span_allocator.ReserveBytes(1, columns_count * sizeof(ImS8)); - span_allocator.ReserveBytes(2, columns_count * sizeof(ImGuiTableCellData)); - table->RawData.resize(span_allocator.GetArenaSizeInBytes()); - span_allocator.SetArenaBasePtr(table->RawData.Data); - span_allocator.GetSpan(0, &table->Columns); - span_allocator.GetSpan(1, &table->DisplayOrderToIndex); - span_allocator.GetSpan(2, &table->RowCellData); - - for (int n = 0; n < columns_count; n++) - { - table->Columns[n] = ImGuiTableColumn(); - table->Columns[n].DisplayOrder = table->DisplayOrderToIndex[n] = (ImS8)n; - } - table->IsInitializing = table->IsSettingsRequestLoad = table->IsSortSpecsDirty = true; - } + TableBeginInitMemory(table, columns_count); // Load settings if (table->IsSettingsRequestLoad)