diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 15876be7..b91ec0ab 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3570,6 +3570,24 @@ static void ShowDemoWindowTables() } ImGui::EndTable(); } + + if (ImGui::BeginTable("##table2", 3, flags | ImGuiTableFlags_SizingPolicyFixedX)) + { + ImGui::TableSetupColumn("One"); + ImGui::TableSetupColumn("Two"); + ImGui::TableSetupColumn("Three"); + ImGui::TableAutoHeaders(); + for (int row = 0; row < 6; row++) + { + ImGui::TableNextRow(); + for (int column = 0; column < 3; column++) + { + ImGui::TableSetColumnIndex(column); + ImGui::Text("Fixed %d,%d", row, column); + } + } + ImGui::EndTable(); + } ImGui::TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index bd29e343..1d5b7020 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1981,9 +1981,9 @@ struct ImGuiTable float CellSpacingX; // Spacing between non-bordered cells float LastOuterHeight; // Outer height from last frame float LastFirstRowHeight; // Height of first row from last frame - float ColumnsTotalWidth; float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. - float IdealTotalWidth; // Sum of ideal column width for nothing to be clipped + float ColumnsTotalWidth; // Sum of current column width + float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window float ResizedColumnNextWidth; ImRect OuterRect; // Note: OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable(). ImRect WorkRect; diff --git a/imgui_tables.cpp b/imgui_tables.cpp index b6a526e8..29b1c9b1 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -558,13 +558,14 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // (can't make auto padding larger than what WorkRect knows about so right-alignment matches) const ImRect work_rect = table->WorkRect; const float padding_auto_x = table->CellPaddingX2; + const float spacing_auto_x = table->CellSpacingX * (1.0f + 2.0f); // CellSpacingX is >0.0f when there's no vertical border, in which case we add two extra CellSpacingX to make auto-fit look nice instead of cramped. We may want to expose this somehow. const float min_column_width = TableGetMinColumnWidth(); int count_fixed = 0; float width_fixed = 0.0f; float total_weights = 0.0f; table->LeftMostStretchedColumnDisplayOrder = -1; - table->IdealTotalWidth = 0.0f; + table->ColumnsAutoFitWidth = 0.0f; for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { if (!(table->ActiveMaskByDisplayOrder & ((ImU64)1 << order_n))) @@ -591,7 +592,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (!(table->Flags & ImGuiTableFlags_NoHeadersWidth) && !(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth)) column_width_ideal = ImMax(column_width_ideal, column_content_width_headers); column_width_ideal = ImMax(column_width_ideal + padding_auto_x, min_column_width); - table->IdealTotalWidth += column_width_ideal; + table->ColumnsAutoFitWidth += column_width_ideal; if (column->Flags & (ImGuiTableColumnFlags_WidthAlwaysAutoResize | ImGuiTableColumnFlags_WidthFixed)) { @@ -623,6 +624,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) } } + // CellSpacingX is >0.0f when there's no vertical border, in which case we add two extra CellSpacingX to make auto-fit look nice instead of cramped. + // We may want to expose this somehow. + table->ColumnsAutoFitWidth += spacing_auto_x * (table->ColumnsActiveCount - 1); + // Layout // Remove -1.0f to cancel out the +1.0f we are doing in EndTable() to make last column line visible const float width_spacings = table->CellSpacingX * (table->ColumnsActiveCount - 1); @@ -956,28 +961,6 @@ void ImGui::EndTable() table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y); table->LastOuterHeight = table->OuterRect.GetHeight(); - // Store content width reference for each column - float max_pos_x = inner_window->DC.CursorMaxPos.x; - for (int column_n = 0; column_n < table->ColumnsCount; column_n++) - { - ImGuiTableColumn* column = &table->Columns[column_n]; - - // Store content width (for both Headers and Rows) - //float ref_x = column->MinX; - float ref_x_rows = column->StartXRows - table->CellPaddingX1; - float ref_x_headers = column->StartXHeaders - table->CellPaddingX1; - column->ContentWidthRowsFrozen = (ImS16)ImMax(0.0f, column->ContentMaxPosRowsFrozen - ref_x_rows); - column->ContentWidthRowsUnfrozen = (ImS16)ImMax(0.0f, column->ContentMaxPosRowsUnfrozen - ref_x_rows); - column->ContentWidthHeadersUsed = (ImS16)ImMax(0.0f, column->ContentMaxPosHeadersUsed - ref_x_headers); - column->ContentWidthHeadersIdeal = (ImS16)ImMax(0.0f, column->ContentMaxPosHeadersIdeal - ref_x_headers); - - // Add an extra 1 pixel so we can see the last column vertical line if it lies on the right-most edge. - if (table->ActiveMaskByIndex & ((ImU64)1 << column_n)) - max_pos_x = ImMax(max_pos_x, column->MaxX + 1.0f); - } - - inner_window->DC.CursorMaxPos.x = max_pos_x; - if (!(flags & ImGuiTableFlags_NoClipX)) inner_window->DrawList->PopClipRect(); inner_window->ClipRect = inner_window->DrawList->_ClipRectStack.back(); @@ -1015,16 +998,16 @@ void ImGui::EndTable() } // Layout in outer window + const float backup_outer_cursor_pos_x = outer_window->DC.CursorPos.x; + const float backup_outer_max_pos_x = outer_window->DC.CursorMaxPos.x; + const float backup_inner_max_pos_x = inner_window->DC.CursorMaxPos.x; inner_window->WorkRect = table->HostWorkRect; inner_window->SkipItems = table->HostSkipItems; outer_window->DC.CursorPos = table->OuterRect.Min; outer_window->DC.ColumnsOffset.x = 0.0f; if (inner_window != outer_window) { - // Override EndChild's ItemSize with our own to enable auto-resize on the X axis when possible - float backup_outer_cursor_pos_x = outer_window->DC.CursorPos.x; EndChild(); - outer_window->DC.CursorMaxPos.x = backup_outer_cursor_pos_x + table->ColumnsTotalWidth + 1.0f + inner_window->ScrollbarSizes.x; } else { @@ -1034,6 +1017,38 @@ void ImGui::EndTable() ItemSize(item_size); } + // Store content width reference for each column + float max_pos_x = backup_inner_max_pos_x; + for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + { + ImGuiTableColumn* column = &table->Columns[column_n]; + + // Store content width (for both Headers and Rows) + //float ref_x = column->MinX; + float ref_x_rows = column->StartXRows - table->CellPaddingX1; + float ref_x_headers = column->StartXHeaders - table->CellPaddingX1; + column->ContentWidthRowsFrozen = (ImS16)ImMax(0.0f, column->ContentMaxPosRowsFrozen - ref_x_rows); + column->ContentWidthRowsUnfrozen = (ImS16)ImMax(0.0f, column->ContentMaxPosRowsUnfrozen - ref_x_rows); + column->ContentWidthHeadersUsed = (ImS16)ImMax(0.0f, column->ContentMaxPosHeadersUsed - ref_x_headers); + column->ContentWidthHeadersIdeal = (ImS16)ImMax(0.0f, column->ContentMaxPosHeadersIdeal - ref_x_headers); + + // Add an extra 1 pixel so we can see the last column vertical line if it lies on the right-most edge. + if (table->ActiveMaskByIndex & ((ImU64)1 << column_n)) + max_pos_x = ImMax(max_pos_x, column->MaxX + 1.0f); + } + + // Override EndChild/ItemSize max extent with our own to enable auto-resize on the X axis when possible + // FIXME-TABLE: This can be improved (e.g. for Fixed columns we don't want to auto AutoFitWidth? or propagate window auto-fit to table?) + if (table->Flags & ImGuiTableFlags_ScrollX) + { + inner_window->DC.CursorMaxPos.x = max_pos_x; // Set contents width for scrolling + outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, backup_outer_cursor_pos_x + table->ColumnsTotalWidth + 1.0f + inner_window->ScrollbarSizes.x); // For auto-fit + } + else + { + outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, table->WorkRect.Min.x + table->ColumnsAutoFitWidth); // For auto-fit + } + // Save settings if (table->IsSettingsDirty) TableSaveSettings(table); @@ -2571,7 +2586,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table) GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255)); if (!open) return; - BulletText("OuterWidth: %.1f, InnerWidth: %.1f%s, IdealWidth: %.1f", table->OuterRect.GetWidth(), table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "", table->IdealTotalWidth); + BulletText("OuterWidth: %.1f, InnerWidth: %.1f%s, ColumnsWidth: %.1f, AutoFitWidth: %.1f", table->OuterRect.GetWidth(), table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "", table->ColumnsTotalWidth, table->ColumnsAutoFitWidth); for (int n = 0; n < table->ColumnsCount; n++) { ImGuiTableColumn* column = &table->Columns[n];