From d3222086f0568b1830733b45605960fb885ae6ad Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 27 Oct 2020 15:06:05 +0100 Subject: [PATCH] Tables: Moved TableSetupScrollFreeze(), TableUpdateDrawChannels() lower in more adequate spots. + rename IsFreezeRowsPassed to IsUnfrozen. --- imgui.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 126 +++++++++++++++++++++++------------------------ 3 files changed, 65 insertions(+), 65 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b754be6b..b355f679 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2276,7 +2276,7 @@ bool ImGuiListClipper::Step() { // While we are in frozen row state, keep displaying items one by one, unclipped // FIXME: Could be stored as a table-agnostic state. - if (table != NULL && !table->IsFreezeRowsPassed) + if (table != NULL && !table->IsUnfrozen) { DisplayStart = ItemsFrozen; DisplayEnd = ItemsFrozen + 1; diff --git a/imgui_internal.h b/imgui_internal.h index 9d0aaf2e..b7ba309d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2037,7 +2037,7 @@ struct ImGuiTable bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data. bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1) bool IsResetDisplayOrderRequest; - bool IsFreezeRowsPassed; // Set when we got past the frozen row. + bool IsUnfrozen; // Set when we got past the frozen row. bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis ImGuiTable() diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 96c6e272..01d56b57 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -323,7 +323,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any table->FreezeColumnsRequest = table->FreezeColumnsCount = 0; - table->IsFreezeRowsPassed = true; + table->IsUnfrozen = true; table->DeclColumnsCount = 0; table->RightMostVisibleColumn = -1; @@ -498,64 +498,6 @@ void ImGui::TableBeginUpdateColumns(ImGuiTable* table) table->InnerWindow->SkipItems = false; } -void ImGui::TableSetupScrollFreeze(int columns, int rows) -{ - ImGuiContext& g = *GImGui; - ImGuiTable* table = g.CurrentTable; - IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); - IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!"); - IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); - IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit - - table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImS8)columns : 0; - table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0; - table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImS8)rows : 0; - table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; - table->IsFreezeRowsPassed = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b -} - -void ImGui::TableUpdateDrawChannels(ImGuiTable* table) -{ - // Allocate draw channels. - // - We allocate them following storage order instead of display order so reordering columns won't needlessly - // increase overall dormant memory cost. - // - We isolate headers draw commands in their own channels instead of just altering clip rects. - // This is in order to facilitate merging of draw commands. - // - After crossing FreezeRowsCount, all columns see their current draw channel changed to a second set of channels. - // - We only use the dummy draw channel so we can push a null clipping rectangle into it without affecting other - // channels, while simplifying per-row/per-cell overhead. It will be empty and discarded when merged. - // Draw channel allocation (before merging): - // - NoClip --> 1+1 channels: background + foreground (same clip rect == 1 draw call) - // - Clip --> 1+N channels - // - FreezeRows || FreezeColumns --> 1+N*2 (unless scrolling value is zero) - // - FreezeRows && FreezeColunns --> 2+N*2 (unless scrolling value is zero) - const int freeze_row_multiplier = (table->FreezeRowsCount > 0) ? 2 : 1; - const int channels_for_row = (table->Flags & ImGuiTableFlags_NoClip) ? 1 : table->ColumnsVisibleCount; - const int channels_for_background = 1; - const int channels_for_dummy = (table->ColumnsVisibleCount < table->ColumnsCount || table->VisibleUnclippedMaskByIndex != table->VisibleMaskByIndex) ? +1 : 0; - const int channels_total = channels_for_background + (channels_for_row * freeze_row_multiplier) + channels_for_dummy; - table->DrawSplitter.Split(table->InnerWindow->DrawList, channels_total); - table->DummyDrawChannel = channels_for_dummy ? (ImS8)(channels_total - 1) : -1; - - int draw_channel_current = 1; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - if (!column->IsClipped) - { - column->DrawChannelFrozen = (ImS8)(draw_channel_current); - column->DrawChannelUnfrozen = (ImS8)(draw_channel_current + (table->FreezeRowsCount > 0 ? channels_for_row : 0)); - if (!(table->Flags & ImGuiTableFlags_NoClip)) - draw_channel_current++; - } - else - { - column->DrawChannelFrozen = column->DrawChannelUnfrozen = table->DummyDrawChannel; - } - column->DrawChannelCurrent = column->DrawChannelFrozen; - } -} - // Adjust flags: default width mode + stretch columns are not allowed when auto extending static ImGuiTableColumnFlags TableFixColumnFlags(ImGuiTable* table, ImGuiTableColumnFlags flags) { @@ -1363,7 +1305,49 @@ void ImGui::TableSetColumnWidth(ImGuiTable* table, ImGuiTableColumn* column_0, f } } -// This function reorder draw channels based on matching clip rectangle, to facilitate merging them. +// Allocate draw channels. Called by TableUpdateLayout() +// - We allocate them following storage order instead of display order so reordering columns won't needlessly +// increase overall dormant memory cost. +// - We isolate headers draw commands in their own channels instead of just altering clip rects. +// This is in order to facilitate merging of draw commands. +// - After crossing FreezeRowsCount, all columns see their current draw channel changed to a second set of channels. +// - We only use the dummy draw channel so we can push a null clipping rectangle into it without affecting other +// channels, while simplifying per-row/per-cell overhead. It will be empty and discarded when merged. +// Draw channel allocation (before merging): +// - NoClip --> 1+1 channels: background + foreground (same clip rect == 1 draw call) +// - Clip --> 1+N channels +// - FreezeRows || FreezeColumns --> 1+N*2 (unless scrolling value is zero) +// - FreezeRows && FreezeColunns --> 2+N*2 (unless scrolling value is zero) +void ImGui::TableUpdateDrawChannels(ImGuiTable* table) +{ + const int freeze_row_multiplier = (table->FreezeRowsCount > 0) ? 2 : 1; + const int channels_for_row = (table->Flags & ImGuiTableFlags_NoClip) ? 1 : table->ColumnsVisibleCount; + const int channels_for_background = 1; + const int channels_for_dummy = (table->ColumnsVisibleCount < table->ColumnsCount || table->VisibleUnclippedMaskByIndex != table->VisibleMaskByIndex) ? +1 : 0; + const int channels_total = channels_for_background + (channels_for_row * freeze_row_multiplier) + channels_for_dummy; + table->DrawSplitter.Split(table->InnerWindow->DrawList, channels_total); + table->DummyDrawChannel = channels_for_dummy ? (ImS8)(channels_total - 1) : -1; + + int draw_channel_current = 1; + for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + { + ImGuiTableColumn* column = &table->Columns[column_n]; + if (!column->IsClipped) + { + column->DrawChannelFrozen = (ImS8)(draw_channel_current); + column->DrawChannelUnfrozen = (ImS8)(draw_channel_current + (table->FreezeRowsCount > 0 ? channels_for_row : 0)); + if (!(table->Flags & ImGuiTableFlags_NoClip)) + draw_channel_current++; + } + else + { + column->DrawChannelFrozen = column->DrawChannelUnfrozen = table->DummyDrawChannel; + } + column->DrawChannelCurrent = column->DrawChannelFrozen; + } +} + +// This function reorder draw channels based on matching clip rectangle, to facilitate merging them. Called by EndTable(). // // Columns where the contents didn't stray off their local clip rectangle can be merged. To achieve // this we merge their clip rect and make them contiguous in the channel list, so they can be merged @@ -1619,6 +1603,22 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, } } +void ImGui::TableSetupScrollFreeze(int columns, int rows) +{ + ImGuiContext& g = *GImGui; + ImGuiTable* table = g.CurrentTable; + IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); + IM_ASSERT(table->IsLayoutLocked == false && "Need to call TableSetupColumn() before first row!"); + IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS); + IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit + + table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImS8)columns : 0; + table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0; + table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImS8)rows : 0; + table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; + table->IsUnfrozen = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b +} + // Starts into the first cell of a new row void ImGui::TableNextRow(ImGuiTableRowFlags row_flags, float row_min_height) { @@ -1777,8 +1777,8 @@ void ImGui::TableEndRow(ImGuiTable* table) } if (unfreeze_rows_actual) { - IM_ASSERT(table->IsFreezeRowsPassed == false); - table->IsFreezeRowsPassed = true; + IM_ASSERT(table->IsUnfrozen == false); + table->IsUnfrozen = true; table->DrawSplitter.SetCurrentChannel(window->DrawList, 0); // BackgroundClipRect starts as table->InnerClipRect, reduce it now @@ -1859,7 +1859,7 @@ void ImGui::TableEndCell(ImGuiTable* table) if (table->RowFlags & ImGuiTableRowFlags_Headers) p_max_pos_x = &column->ContentMaxXHeadersUsed; // Useful in case user submit contents in header row that is not a TableHeader() call else - p_max_pos_x = table->IsFreezeRowsPassed ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen; + p_max_pos_x = table->IsUnfrozen ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen; *p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x); table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY);