Tables: Moved TableSetupScrollFreeze(), TableUpdateDrawChannels() lower in more adequate spots.

+ rename IsFreezeRowsPassed to IsUnfrozen.
docking
ocornut 4 years ago
parent d9ca3939e1
commit d3222086f0

@ -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;

@ -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()

@ -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);

Loading…
Cancel
Save