diff --git a/imgui_internal.h b/imgui_internal.h index 1bf8a164..ea45d384 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1916,6 +1916,7 @@ struct ImGuiTableColumn bool IsVisibleNextFrame; bool IsClipped; // Set when not overlapping the host window clipping rectangle. bool SkipItems; + ImGuiNavLayer NavLayerCurrent; ImS8 DisplayOrder; // Index within Table's IndexToDisplayOrder[] (column may be reordered by users) ImS8 IndexWithinVisibleSet; // Index within visible set (<= IndexToDisplayOrder) ImS8 DrawChannelCurrent; // Index within DrawSplitter.Channels[] @@ -2039,7 +2040,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 (the first one). + bool IsFreezeRowsPassed; // 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 46ada6f3..7143b9f0 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -235,12 +235,13 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG if (override_content_size.x != FLT_MAX || override_content_size.y != FLT_MAX) SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f)); - // Create scrolling region (without border = zero window padding) + // Create scrolling region (without border and zero window padding) ImGuiWindowFlags child_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; BeginChildEx(name, instance_id, table->OuterRect.GetSize(), false, child_flags); table->InnerWindow = g.CurrentWindow; table->WorkRect = table->InnerWindow->WorkRect; table->OuterRect = table->InnerWindow->Rect(); + IM_ASSERT(table->InnerWindow->WindowPadding.x == 0.0f && table->InnerWindow->WindowPadding.y == 0.0f && table->InnerWindow->WindowBorderSize == 0.0f); } // Push a standardized ID for both child and not-child using tables, equivalent to BeginTable() doing PushID(label) matching @@ -479,7 +480,7 @@ 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 call TableSetupColumn() before first row!"); + 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 @@ -487,7 +488,7 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows) 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); + table->IsFreezeRowsPassed = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b } void ImGui::TableUpdateDrawChannels(ImGuiTable* table) @@ -778,6 +779,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) const int column_n = table->DisplayOrderToIndex[order_n]; ImGuiTableColumn* column = &table->Columns[column_n]; + column->NavLayerCurrent = (table->FreezeRowsCount > 0 || column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main; + if (table->FreezeColumnsCount > 0 && table->FreezeColumnsCount == visible_n) offset_x += work_rect.Min.x - table->OuterRect.Min.x; @@ -1671,12 +1674,12 @@ 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); - + const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount); + const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest); if (table->CurrentRow == 0) table->LastFirstRowHeight = bg_y2 - bg_y1; - const bool is_visible = table->CurrentRow >= 0 && bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y; + const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y); if (is_visible) { // Decide of background color for the row @@ -1710,7 +1713,7 @@ void ImGui::TableEndRow(ImGuiTable* table) } const bool draw_cell_bg_color = table->RowCellDataCurrent >= 0; - const bool draw_strong_bottom_border = unfreeze_rows;// || (table->RowFlags & ImGuiTableRowFlags_Headers); + const bool draw_strong_bottom_border = unfreeze_rows_actual;// || (table->RowFlags & ImGuiTableRowFlags_Headers); if ((bg_col0 | bg_col1 | border_col) != 0 || draw_strong_bottom_border || draw_cell_bg_color) { // In theory we could call SetWindowClipRectBeforeChannelChange() but since we know TableEndRow() is @@ -1757,18 +1760,22 @@ void ImGui::TableEndRow(ImGuiTable* table) // 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 // get the new cursor position. - if (unfreeze_rows) + if (unfreeze_rows_request) + for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + { + ImGuiTableColumn* column = &table->Columns[column_n]; + column->NavLayerCurrent = (column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main; + } + if (unfreeze_rows_actual) { IM_ASSERT(table->IsFreezeRowsPassed == false); table->IsFreezeRowsPassed = true; table->DrawSplitter.SetCurrentChannel(window->DrawList, 0); - ImRect r; - r.Min.x = table->InnerClipRect.Min.x; - r.Min.y = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); - r.Max.x = table->InnerClipRect.Max.x; - r.Max.y = window->InnerClipRect.Max.y; - table->BackgroundClipRect = r; + // BackgroundClipRect starts as table->InnerClipRect, reduce it now + float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); + table->BackgroundClipRect.Min.y = y0; + table->BackgroundClipRect.Max.y = window->InnerClipRect.Max.y; float row_height = table->RowPosY2 - table->RowPosY1; table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y; @@ -1777,7 +1784,7 @@ void ImGui::TableEndRow(ImGuiTable* table) { ImGuiTableColumn* column = &table->Columns[column_n]; column->DrawChannelCurrent = column->DrawChannelRowsAfterFreeze; - column->ClipRect.Min.y = r.Min.y; + column->ClipRect.Min.y = table->BackgroundClipRect.Min.y; } // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y @@ -1810,6 +1817,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n) window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT window->DC.CurrLineTextBaseOffset = table->RowTextBaseline; window->DC.LastItemId = 0; + window->DC.NavLayerCurrent = column->NavLayerCurrent; window->WorkRect.Min.y = window->DC.CursorPos.y; window->WorkRect.Min.x = column->MinX + table->CellPaddingX1; @@ -1964,7 +1972,7 @@ const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n) ImGuiID ImGui::TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no) { IM_ASSERT(column_n < table->ColumnsCount); - ImGuiID id = table->ID + (instance_no * table->ColumnsCount) + column_n; + ImGuiID id = table->ID + 1 + (instance_no * table->ColumnsCount) + column_n; return id; }