Skip to content

Commit 082f1d1

Browse files
committed
Tables: renamed TableBeginUpdateColumns to TableBeginApplyRequests, moved code to TableUpdateLayout, in order to ensure that enable state is not inconsistent due to TableSetupColumn column hiding requests.
All the fields moved from TableBeginUpdateColumns to TableUpdateLayout are not used before.
1 parent 79c9eaa commit 082f1d1

File tree

2 files changed

+82
-68
lines changed

2 files changed

+82
-68
lines changed

imgui_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2282,7 +2282,7 @@ namespace ImGui
22822282
// Tables: Internals
22832283
IMGUI_API ImGuiTable* TableFindByID(ImGuiID id);
22842284
IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
2285-
IMGUI_API void TableBeginUpdateColumns(ImGuiTable* table);
2285+
IMGUI_API void TableBeginApplyRequests(ImGuiTable* table);
22862286
IMGUI_API void TableUpdateDrawChannels(ImGuiTable* table);
22872287
IMGUI_API void TableUpdateLayout(ImGuiTable* table);
22882288
IMGUI_API void TableUpdateBorders(ImGuiTable* table);

imgui_tables.cpp

Lines changed: 81 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
// Typical call flow: (root level is public API):
6565
// - BeginTable() user begin into a table
6666
// | BeginChild() - (if ScrollX/ScrollY is set)
67-
// | TableBeginUpdateColumns() - apply resize/order requests, lock columns active state, order
67+
// | TableBeginApplyRequests() - apply queued resizing/reordering/hiding requests
6868
// | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame)
6969
// | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of stretch columns) from their respective width
7070
// - TableSetupColumn() user submit columns details (optional)
@@ -273,7 +273,6 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
273273
table->LastFrameActive = g.FrameCount;
274274
table->OuterWindow = table->InnerWindow = outer_window;
275275
table->ColumnsCount = columns_count;
276-
table->ColumnsNames.Buf.resize(0);
277276
table->IsInitializing = false;
278277
table->IsLayoutLocked = false;
279278
table->InnerWidth = inner_width;
@@ -431,13 +430,26 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
431430
// Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option.
432431
inner_window->SkipItems = true;
433432

434-
// Update/lock which columns will be Visible for the frame
435-
TableBeginUpdateColumns(table);
433+
// Clear names
434+
// FIXME-TABLES: probably could be done differently...
435+
if (table->ColumnsNames.Buf.Size > 0)
436+
{
437+
table->ColumnsNames.Buf.resize(0);
438+
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
439+
{
440+
ImGuiTableColumn* column = &table->Columns[column_n];
441+
column->NameOffset = -1;
442+
}
443+
}
444+
445+
// Apply queued resizing/reordering/hiding requests
446+
TableBeginApplyRequests(table);
436447

437448
return true;
438449
}
439450

440-
void ImGui::TableBeginUpdateColumns(ImGuiTable* table)
451+
// Apply queued resizing/reordering/hiding requests
452+
void ImGui::TableBeginApplyRequests(ImGuiTable* table)
441453
{
442454
// Handle resizing request
443455
// (We process this at the first TableBegin of the frame)
@@ -504,67 +516,6 @@ void ImGui::TableBeginUpdateColumns(ImGuiTable* table)
504516
table->IsResetDisplayOrderRequest = false;
505517
table->IsSettingsDirty = true;
506518
}
507-
508-
// Lock Visible state and Order
509-
table->ColumnsEnabledCount = 0;
510-
table->IsDefaultDisplayOrder = true;
511-
ImGuiTableColumn* last_visible_column = NULL;
512-
bool want_column_auto_fit = false;
513-
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
514-
{
515-
const int column_n = table->DisplayOrderToIndex[order_n];
516-
if (column_n != order_n)
517-
table->IsDefaultDisplayOrder = false;
518-
ImGuiTableColumn* column = &table->Columns[column_n];
519-
column->NameOffset = -1;
520-
if (!(table->Flags & ImGuiTableFlags_Hideable) || (column->Flags & ImGuiTableColumnFlags_NoHide))
521-
column->IsEnabledNextFrame = true;
522-
if (column->IsEnabled != column->IsEnabledNextFrame)
523-
{
524-
column->IsEnabled = column->IsEnabledNextFrame;
525-
table->IsSettingsDirty = true;
526-
if (!column->IsEnabled && column->SortOrder != -1)
527-
table->IsSortSpecsDirty = true;
528-
}
529-
if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_MultiSortable))
530-
table->IsSortSpecsDirty = true;
531-
if (column->AutoFitQueue != 0x00)
532-
want_column_auto_fit = true;
533-
534-
ImU64 index_mask = (ImU64)1 << column_n;
535-
ImU64 display_order_mask = (ImU64)1 << column->DisplayOrder;
536-
if (column->IsEnabled)
537-
{
538-
column->PrevEnabledColumn = column->NextEnabledColumn = -1;
539-
if (last_visible_column)
540-
{
541-
last_visible_column->NextEnabledColumn = (ImS8)column_n;
542-
column->PrevEnabledColumn = (ImS8)table->Columns.index_from_ptr(last_visible_column);
543-
}
544-
column->IndexWithinEnabledSet = table->ColumnsEnabledCount;
545-
table->ColumnsEnabledCount++;
546-
table->EnabledMaskByIndex |= index_mask;
547-
table->EnabledMaskByDisplayOrder |= display_order_mask;
548-
last_visible_column = column;
549-
}
550-
else
551-
{
552-
column->IndexWithinEnabledSet = -1;
553-
table->EnabledMaskByIndex &= ~index_mask;
554-
table->EnabledMaskByDisplayOrder &= ~display_order_mask;
555-
}
556-
IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder);
557-
}
558-
table->EnabledUnclippedMaskByIndex = table->EnabledMaskByIndex; // Columns will be masked out by TableUpdateLayout() when Clipped
559-
table->RightMostEnabledColumn = (ImS8)(last_visible_column ? table->Columns.index_from_ptr(last_visible_column) : -1);
560-
561-
// Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible to avoid
562-
// the column fitting to wait until the first visible frame of the child container (may or not be a good thing).
563-
if (want_column_auto_fit && table->OuterWindow != table->InnerWindow)
564-
table->InnerWindow->SkipItems = false;
565-
566-
if (want_column_auto_fit)
567-
table->IsSettingsDirty = true;
568519
}
569520

570521
// Adjust flags: default width mode + stretch columns are not allowed when auto extending
@@ -629,6 +580,65 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
629580
table->HoveredColumnBody = -1;
630581
table->HoveredColumnBorder = -1;
631582

583+
// Lock Enabled state and Order
584+
ImGuiTableColumn* last_visible_column = NULL;
585+
bool want_column_auto_fit = false;
586+
table->IsDefaultDisplayOrder = true;
587+
table->ColumnsEnabledCount = 0;
588+
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
589+
{
590+
const int column_n = table->DisplayOrderToIndex[order_n];
591+
if (column_n != order_n)
592+
table->IsDefaultDisplayOrder = false;
593+
ImGuiTableColumn* column = &table->Columns[column_n];
594+
if (!(table->Flags & ImGuiTableFlags_Hideable) || (column->Flags & ImGuiTableColumnFlags_NoHide))
595+
column->IsEnabledNextFrame = true;
596+
if (column->IsEnabled != column->IsEnabledNextFrame)
597+
{
598+
column->IsEnabled = column->IsEnabledNextFrame;
599+
table->IsSettingsDirty = true;
600+
if (!column->IsEnabled && column->SortOrder != -1)
601+
table->IsSortSpecsDirty = true;
602+
}
603+
if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_MultiSortable))
604+
table->IsSortSpecsDirty = true;
605+
if (column->AutoFitQueue != 0x00)
606+
want_column_auto_fit = true;
607+
608+
ImU64 index_mask = (ImU64)1 << column_n;
609+
ImU64 display_order_mask = (ImU64)1 << column->DisplayOrder;
610+
if (column->IsEnabled)
611+
{
612+
column->PrevEnabledColumn = column->NextEnabledColumn = -1;
613+
if (last_visible_column)
614+
{
615+
last_visible_column->NextEnabledColumn = (ImS8)column_n;
616+
column->PrevEnabledColumn = (ImS8)table->Columns.index_from_ptr(last_visible_column);
617+
}
618+
column->IndexWithinEnabledSet = table->ColumnsEnabledCount;
619+
table->ColumnsEnabledCount++;
620+
table->EnabledMaskByIndex |= index_mask;
621+
table->EnabledMaskByDisplayOrder |= display_order_mask;
622+
last_visible_column = column;
623+
}
624+
else
625+
{
626+
column->IndexWithinEnabledSet = -1;
627+
table->EnabledMaskByIndex &= ~index_mask;
628+
table->EnabledMaskByDisplayOrder &= ~display_order_mask;
629+
}
630+
IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder);
631+
}
632+
table->EnabledUnclippedMaskByIndex = table->EnabledMaskByIndex; // Columns will be masked out below when Clipped
633+
table->RightMostEnabledColumn = (ImS8)(last_visible_column ? table->Columns.index_from_ptr(last_visible_column) : -1);
634+
635+
// Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible to avoid
636+
// the column fitting to wait until the first visible frame of the child container (may or not be a good thing).
637+
if (want_column_auto_fit && table->OuterWindow != table->InnerWindow)
638+
table->InnerWindow->SkipItems = false;
639+
if (want_column_auto_fit)
640+
table->IsSettingsDirty = true;
641+
632642
// Compute offset, clip rect for the frame
633643
// (can't make auto padding larger than what WorkRect knows about so right-alignment matches)
634644
const ImRect work_rect = table->WorkRect;
@@ -1715,7 +1725,7 @@ void ImGui::TableNextRow(ImGuiTableRowFlags row_flags, float row_min_height)
17151725
ImGuiContext& g = *GImGui;
17161726
ImGuiTable* table = g.CurrentTable;
17171727

1718-
if (table->CurrentRow == -1)
1728+
if (!table->IsLayoutLocked)
17191729
TableUpdateLayout(table);
17201730
if (table->IsInsideRow)
17211731
TableEndRow(table);
@@ -2509,6 +2519,10 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
25092519
if (!(table->Flags & ImGuiTableFlags_Sortable))
25102520
return NULL;
25112521

2522+
// Require layout (in case TableHeadersRow() hasn't been called) as it may alter IsSortSpecsDirty in some paths.
2523+
if (!table->IsLayoutLocked)
2524+
TableUpdateLayout(table);
2525+
25122526
if (table->IsSortSpecsDirty)
25132527
TableSortSpecsBuild(table);
25142528

0 commit comments

Comments
 (0)