Skip to content

Commit

Permalink
Tables: Further fix ocornut#3293, ocornut#3163 + fixed for row unfree…
Browse files Browse the repository at this point in the history
…zing border not always showing due to unset clip rect.
  • Loading branch information
ocornut authored and rokups committed Dec 1, 2020
1 parent d3f2638 commit eb8651f
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 31 deletions.
4 changes: 2 additions & 2 deletions imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -1036,8 +1036,8 @@ enum ImGuiTableFlags_
ImGuiTableFlags_BordersVFullHeight = 1 << 11, // Borders covers all rows even when Headers are being used. Allow resizing from any rows.
// Padding, Sizing
ImGuiTableFlags_NoClipX = 1 << 12, // Disable pushing clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow)
ImGuiTableFlags_SizingPolicyFixedX = 1 << 13, // Default if ScrollX is on. Columns will default to use WidthFixed or WidthAlwaysAutoResize policy. Read description above for more details.
ImGuiTableFlags_SizingPolicyStretchX = 1 << 14, // Default if ScrollX is off. Columns will default to use WidthStretch policy. Read description above for more details.
ImGuiTableFlags_SizingPolicyFixedX = 1 << 13, // Default if ScrollX is on. Columns will default to use _WidthFixed or _WidthAlwaysAutoResize policy. Read description above for more details.
ImGuiTableFlags_SizingPolicyStretchX = 1 << 14, // Default if ScrollX is off. Columns will default to use _WidthStretch policy. Read description above for more details.
ImGuiTableFlags_NoHeadersWidth = 1 << 15, // Disable header width contribution to automatic width calculation.
ImGuiTableFlags_NoHostExtendY = 1 << 16, // (FIXME-TABLE: Reword as SizingPolicy?) Disable extending past the limit set by outer_size.y, only meaningful when neither of ScrollX|ScrollY are set (data below the limit will be clipped and not visible)
ImGuiTableFlags_NoKeepColumnsVisible = 1 << 17, // (FIXME-TABLE) Disable code that keeps column always minimally visible when table width gets too small.
Expand Down
4 changes: 2 additions & 2 deletions imgui_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3790,10 +3790,10 @@ static void ShowDemoWindowTables()
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", (unsigned int*)&flags, ImGuiTableFlags_ScrollY);
if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyStretchX", (unsigned int*)&flags, ImGuiTableFlags_SizingPolicyStretchX))
flags &= ~(ImGuiTableFlags_SizingPolicyMaskX_ ^ ImGuiTableFlags_SizingPolicyStretchX); // Can't specify both sizing polices so we clear the other
ImGui::SameLine(); HelpMarker("Default if _ScrollX if disabled.");
ImGui::SameLine(); HelpMarker("Default if _ScrollX if disabled. Makes columns use _WidthStretch policy by default.");
if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyFixedX", (unsigned int*)&flags, ImGuiTableFlags_SizingPolicyFixedX))
flags &= ~(ImGuiTableFlags_SizingPolicyMaskX_ ^ ImGuiTableFlags_SizingPolicyFixedX); // Can't specify both sizing polices so we clear the other
ImGui::SameLine(); HelpMarker("Default if _ScrollX if enabled.");
ImGui::SameLine(); HelpMarker("Default if _ScrollX if enabled. Makes columns use _WidthFixed by default, or _WidthAlwaysAutoResize if _Resizable is not set.");
ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", (unsigned int*)&flags, ImGuiTableFlags_Resizable);
ImGui::CheckboxFlags("ImGuiTableFlags_NoClipX", (unsigned int*)&flags, ImGuiTableFlags_NoClipX);

Expand Down
1 change: 1 addition & 0 deletions imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1992,6 +1992,7 @@ struct ImGuiTable
ImRect BackgroundClipRect; // We use this to cpu-clip cell background color fill
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
ImRect HostWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
ImRect HostBackupClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
ImVec2 HostCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
ImGuiWindow* OuterWindow; // Parent window for the table
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
Expand Down
46 changes: 19 additions & 27 deletions imgui_tables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1620,6 +1620,8 @@ void ImGui::TableEndRow(ImGuiTable* table)
const float bg_y1 = table->RowPosY1;
const float bg_y2 = table->RowPosY2;

const bool unfreeze_rows = (table->CurrentRow + 1 == table->FreezeRowsCount && table->FreezeRowsCount > 0);

if (table->CurrentRow == 0)
table->LastFirstRowHeight = bg_y2 - bg_y1;

Expand Down Expand Up @@ -1651,8 +1653,11 @@ void ImGui::TableEndRow(ImGuiTable* table)
}
}

if (bg_col != 0 || border_col != 0)
const bool draw_stong_bottom_border = unfreeze_rows;// || (table->RowFlags & ImGuiTableRowFlags_Headers);
if (bg_col != 0 || border_col != 0 || draw_stong_bottom_border)
{
// In theory we could call SetWindowClipRectBeforeChannelChange() but since we know TableEndRow() is
// always followed by a change of clipping rectangle we perform the smallest overwrite possible here.
window->DrawList->_CmdHeader.ClipRect = table->HostClipRect.ToVec4();
table->DrawSplitter.SetCurrentChannel(window->DrawList, 0);
}
Expand All @@ -1668,18 +1673,14 @@ void ImGui::TableEndRow(ImGuiTable* table)
}

// Draw top border
const float border_y = bg_y1;
if (border_col && border_y >= table->BackgroundClipRect.Min.y && border_y < table->BackgroundClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), border_col);
}

const bool unfreeze_rows = (table->CurrentRow + 1 == table->FreezeRowsCount && table->FreezeRowsCount > 0);
if (border_col && bg_y1 >= table->BackgroundClipRect.Min.y && bg_y1 < table->BackgroundClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), border_col);

// Draw bottom border (always strong)
const bool draw_separating_border = unfreeze_rows;// || (table->RowFlags & ImGuiTableRowFlags_Headers);
if (draw_separating_border)
if (bg_y2 >= table->BackgroundClipRect.Min.y && bg_y2 < table->BackgroundClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong);
// Draw bottom border at the row unfreezing mark (always strong)
if (draw_stong_bottom_border)
if (bg_y2 >= table->BackgroundClipRect.Min.y && bg_y2 < table->BackgroundClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong);
}

// End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle)
// We need to do that in TableEndRow() instead of TableBeginRow() so the list clipper can mark end of row and
Expand Down Expand Up @@ -1749,15 +1750,8 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
}
else
{
SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
table->DrawSplitter.SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
//window->ClipRect = column->ClipRect;
//IM_ASSERT(column->ClipRect.Max.x > column->ClipRect.Min.x && column->ClipRect.Max.y > column->ClipRect.Min.y);
//window->DrawList->_ClipRectStack.back() = ImVec4(column->ClipRect.Min.x, column->ClipRect.Min.y, column->ClipRect.Max.x, column->ClipRect.Max.y);
//window->DrawList->UpdateClipRect();
window->DrawList->PopClipRect();
window->DrawList->PushClipRect(column->ClipRect.Min, column->ClipRect.Max, false);
//IMGUI_DEBUG_LOG("%d (%.0f,%.0f)(%.0f,%.0f)\n", column_n, column->ClipRect.Min.x, column->ClipRect.Min.y, column->ClipRect.Max.x, column->ClipRect.Max.y);
window->ClipRect = window->DrawList->_ClipRectStack.back();
}
}

Expand Down Expand Up @@ -1894,10 +1888,10 @@ void ImGui::PushTableBackground()
ImGuiWindow* window = g.CurrentWindow;
ImGuiTable* table = g.CurrentTable;

// Set cmd header ahead to avoid SetCurrentChannel+PushClipRect doing an unnecessary AddDrawCmd/Pop
window->DrawList->_CmdHeader.ClipRect = table->HostClipRect.ToVec4();
// Optimization: avoid SetCurrentChannel() + PushClipRect()
table->HostBackupClipRect = window->ClipRect;
SetWindowClipRectBeforeSetChannel(window, table->HostClipRect);
table->DrawSplitter.SetCurrentChannel(window->DrawList, 0);
PushClipRect(table->HostClipRect.Min, table->HostClipRect.Max, false);
}

void ImGui::PopTableBackground()
Expand All @@ -1907,11 +1901,9 @@ void ImGui::PopTableBackground()
ImGuiTable* table = g.CurrentTable;
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];

// Set cmd header ahead to avoid SetCurrentChannel+PopClipRect doing an unnecessary AddDrawCmd/Pop
ImVec4 pop_clip_rect = window->DrawList->_ClipRectStack.Data[window->DrawList->_ClipRectStack.Size - 2];
window->DrawList->_CmdHeader.ClipRect = pop_clip_rect;
// Optimization: avoid PopClipRect() + SetCurrentChannel()
SetWindowClipRectBeforeSetChannel(window, table->HostBackupClipRect);
table->DrawSplitter.SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
PopClipRect();
}

// Output context menu into current window (generally a popup)
Expand Down

0 comments on commit eb8651f

Please sign in to comment.