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