From 1ad5502f18fb1ad6159f461528b9e01567453b70 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 10 Dec 2020 18:53:57 +0100 Subject: [PATCH] Tables: Closer to zero-clear constructor. Lazily clearing name offsets to avoid an iteration in BeginTable(). Removed unused TableSetColumnIsEnabled(), signature went faulty anyway. --- imgui_internal.h | 6 ++-- imgui_tables.cpp | 93 +++++++++++++++++------------------------------- 2 files changed, 35 insertions(+), 64 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 4479d850..0e3d9e39 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2070,8 +2070,8 @@ struct ImGuiTable bool MemoryCompacted; bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis - IMGUI_API ImGuiTable(); - IMGUI_API ~ImGuiTable(); + IMGUI_API ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; } + IMGUI_API ~ImGuiTable() { IM_FREE(RawData); } }; // sizeof() ~ 12 @@ -2286,7 +2286,6 @@ namespace ImGui // Tables: Candidates for public API IMGUI_API void TableOpenContextMenu(int column_n = -1); IMGUI_API void TableSetColumnWidth(int column_n, float width); - IMGUI_API void TableSetColumnIsEnabled(int column_n, bool enabled); IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs); IMGUI_API int TableGetHoveredColumn(); // May use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) instead. Return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered. IMGUI_API float TableGetHeaderRowHeight(); @@ -2315,6 +2314,7 @@ namespace ImGui IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n); IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n); IMGUI_API ImGuiID TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0); + IMGUI_API float TableGetMinColumnWidth(); IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table); IMGUI_API void TableRemove(ImGuiTable* table); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index f3c3e36f..5540dee0 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -178,7 +178,7 @@ Index of this file: // Configuration static const int TABLE_DRAW_CHANNEL_BG0 = 0; static const int TABLE_DRAW_CHANNEL_BG1_FROZEN = 1; -static const int TABLE_DRAW_CHANNEL_UNCLIPPED = 2; // When using ImGuiTableFlags_NoClip +static const int TABLE_DRAW_CHANNEL_NOCLIP = 2; // When using ImGuiTableFlags_NoClip static const float TABLE_BORDER_SIZE = 1.0f; // FIXME-TABLE: Currently hard-coded because of clipping assumptions with outer borders rendering. static const float TABLE_RESIZE_SEPARATOR_HALF_THICKNESS = 4.0f; // Extend outside inner borders. 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. @@ -226,25 +226,6 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_w return flags; } -ImGuiTable::ImGuiTable() -{ - memset(this, 0, sizeof(*this)); - SettingsOffset = -1; - InstanceInteracted = -1; - LastFrameActive = -1; - LastResizedColumn = -1; - ContextPopupColumn = -1; - ReorderColumn = -1; - ResizedColumn = -1; - AutoFitSingleStretchColumn = -1; - HoveredColumnBody = HoveredColumnBorder = -1; -} - -ImGuiTable::~ImGuiTable() -{ - IM_FREE(RawData); -} - ImGuiTable* ImGui::TableFindByID(ImGuiID id) { ImGuiContext& g = *GImGui; @@ -433,9 +414,14 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG TableResetSettings(table); if (table->IsInitializing) { - // Initialize for new settings + // Initialize table->SettingsOffset = -1; table->IsSortSpecsDirty = true; + table->InstanceInteracted = -1; + table->ContextPopupColumn = -1; + table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1; + table->AutoFitSingleStretchColumn = -1; + table->HoveredColumnBody = table->HoveredColumnBorder = -1; for (int n = 0; n < columns_count; n++) { ImGuiTableColumn* column = &table->Columns[n]; @@ -473,16 +459,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG inner_window->SkipItems = true; // Clear names - // FIXME-TABLE: probably could be done differently... + // At this point the ->NameOffset field of each column will be invalid until TableUpdateLayout() or the first call to TableSetupColumn() if (table->ColumnsNames.Buf.Size > 0) - { table->ColumnsNames.Buf.resize(0); - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - column->NameOffset = -1; - } - } // Apply queued resizing/reordering/hiding requests TableBeginApplyRequests(table); @@ -619,14 +598,6 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I column->Flags = flags | (column->Flags & ImGuiTableColumnFlags_StatusMask_); } -// Minimum column content width (without padding) -static float TableGetMinColumnWidth() -{ - ImGuiContext& g = *GImGui; - //return g.Style.ColumnsMinSpacing; // FIXME-TABLE - return g.Style.FramePadding.x * 1.0f; -} - // Layout columns for the frame. This is in essence the followup to BeginTable(). // Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first. // FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for WidthAutoResize @@ -659,6 +630,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (column_n >= table->DeclColumnsCount) { TableSetupColumnFlags(table, column, ImGuiTableColumnFlags_None); + column->NameOffset = -1; column->UserID = 0; column->InitStretchWeightOrWidth = -1.0f; } @@ -835,7 +807,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (column->Flags & ImGuiTableColumnFlags_WidthStretch) { // StretchWeight gets converted into WidthRequest - if (!mixed_same_widths) + if (!mixed_same_widths) { float weight_ratio = column->StretchWeight / sum_weights_stretched; column->WidthRequest = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, min_column_width) + 0.01f); @@ -1074,7 +1046,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // Initial state ImGuiWindow* inner_window = table->InnerWindow; if (table->Flags & ImGuiTableFlags_NoClip) - table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_UNCLIPPED); + table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); else inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false); } @@ -1346,7 +1318,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo } // Store name (append with zero-terminator in contiguous buffer) - IM_ASSERT(column->NameOffset == -1); + column->NameOffset = -1; if (label != NULL && label[0] != 0) { column->NameOffset = (ImS16)table->ColumnsNames.size(); @@ -1389,6 +1361,15 @@ const char* ImGui::TableGetColumnName(int column_n) return TableGetColumnName(table, column_n); } +const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n) +{ + IM_ASSERT(table->IsLayoutLocked == true || column_n <= table->DeclColumnsCount); // NameOffset is invalid otherwise + const ImGuiTableColumn* column = &table->Columns[column_n]; + if (column->NameOffset == -1) + return ""; + return &table->ColumnsNames.Buf[column->NameOffset]; +} + // We allow querying for an extra column in order to poll the IsHovered state of the right-most section ImGuiTableColumnFlags ImGui::TableGetColumnFlags(int column_n) { @@ -1403,17 +1384,6 @@ ImGuiTableColumnFlags ImGui::TableGetColumnFlags(int column_n) return table->Columns[column_n].Flags; } -void ImGui::TableSetColumnIsEnabled(int column_n, bool hidden) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && table->IsLayoutLocked == false); - if (column_n < 0) - column_n = table->CurrentColumn; - IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); - table->Columns[column_n].IsEnabledNextFrame = !hidden; -} - // Return the cell rectangle based on currently known height. // - Important: we generally don't know our row height until the end of the row, so Max.y will be incorrect in many situations. // The only case where this is correct is if we provided a min_row_height to TableNextRow() and don't go below it. @@ -1431,14 +1401,6 @@ ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n) return ImRect(x1, table->RowPosY1, x2, table->RowPosY2); } -const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n) -{ - const ImGuiTableColumn* column = &table->Columns[column_n]; - if (column->NameOffset == -1) - return ""; - return &table->ColumnsNames.Buf[column->NameOffset]; -} - // Return the resizing ID for the right-side of the given column. ImGuiID ImGui::TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no) { @@ -1810,8 +1772,8 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n) if (table->Flags & ImGuiTableFlags_NoClip) { // FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed. - table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_UNCLIPPED); - //IM_ASSERT(table->DrawSplitter._Current == TABLE_DRAW_CHANNEL_UNCLIPPED); + table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP); + //IM_ASSERT(table->DrawSplitter._Current == TABLE_DRAW_CHANNEL_NOCLIP); } else { @@ -1845,12 +1807,21 @@ void ImGui::TableEndCell(ImGuiTable* table) //------------------------------------------------------------------------- // [SECTION] Tables: Columns width management //------------------------------------------------------------------------- +// - TableGetMinColumnWidth() [Internal] // - TableSetColumnWidth() // - TableSetColumnWidthAutoSingle() [Internal] // - TableSetColumnWidthAutoAll() [Internal] // - TableUpdateColumnsWeightFromWidth() [Internal] //------------------------------------------------------------------------- +// Minimum column content width (without padding) +float ImGui::TableGetMinColumnWidth() +{ + ImGuiContext& g = *GImGui; + //return g.Style.ColumnsMinSpacing; // FIXME-TABLE + return g.Style.FramePadding.x * 1.0f; +} + // 'width' = inner column width, without padding void ImGui::TableSetColumnWidth(int column_n, float width) {