mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-11-04 09:44:29 +00:00 
			
		
		
		
	Tables: setup and maintain ItemWidth per column.
This commit is contained in:
		
							
								
								
									
										1
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								imgui.h
									
									
									
									
									
								
							@@ -1092,7 +1092,6 @@ enum ImGuiTableFlags_
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Flags for ImGui::TableSetupColumn()
 | 
			
		||||
// FIXME-TABLE: Rename to ImGuiColumns_*, stick old columns api flags in there under an obsolete api block
 | 
			
		||||
enum ImGuiTableColumnFlags_
 | 
			
		||||
{
 | 
			
		||||
    ImGuiTableColumnFlags_None                      = 0,
 | 
			
		||||
 
 | 
			
		||||
@@ -4021,12 +4021,13 @@ static void ShowDemoWindowTables()
 | 
			
		||||
        ImVec2 outer_size(0, TEXT_BASE_HEIGHT * 7);
 | 
			
		||||
        if (ImGui::BeginTable("##nways", column_count, flags, outer_size))
 | 
			
		||||
        {
 | 
			
		||||
            for (int row = 0; row < 10; row++)
 | 
			
		||||
            for (int cell = 0; cell < 10 * column_count; cell++)
 | 
			
		||||
            {
 | 
			
		||||
                ImGui::TableNextRow();
 | 
			
		||||
                for (int column = 0; column < column_count; column++)
 | 
			
		||||
                {
 | 
			
		||||
                    ImGui::TableSetColumnIndex(column);
 | 
			
		||||
                ImGui::TableNextColumn();
 | 
			
		||||
                int column = ImGui::TableGetColumnIndex();
 | 
			
		||||
                int row = ImGui::TableGetRowIndex();
 | 
			
		||||
 | 
			
		||||
                ImGui::PushID(cell);
 | 
			
		||||
                char label[32];
 | 
			
		||||
                static char text_buf[32] = "";
 | 
			
		||||
                sprintf(label, "Hello %d,%d", column, row);
 | 
			
		||||
@@ -4038,30 +4039,69 @@ static void ShowDemoWindowTables()
 | 
			
		||||
                case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
 | 
			
		||||
                case CT_InputText:  ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
 | 
			
		||||
                }
 | 
			
		||||
                }
 | 
			
		||||
                ImGui::PopID();
 | 
			
		||||
            }
 | 
			
		||||
            ImGui::EndTable();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ImGui::TextUnformatted("Item Widths");
 | 
			
		||||
        ImGui::SameLine();
 | 
			
		||||
        HelpMarker("Showcase using PushItemWidth() and how it is preserved on a per-column basis");
 | 
			
		||||
        if (ImGui::BeginTable("##table2", 3, ImGuiTableFlags_Borders))
 | 
			
		||||
        {
 | 
			
		||||
            ImGui::TableSetupColumn("small");
 | 
			
		||||
            ImGui::TableSetupColumn("half");
 | 
			
		||||
            ImGui::TableSetupColumn("right-align");
 | 
			
		||||
            ImGui::TableHeadersRow();
 | 
			
		||||
 | 
			
		||||
            for (int row = 0; row < 3; row++)
 | 
			
		||||
            {
 | 
			
		||||
                ImGui::TableNextRow();
 | 
			
		||||
                if (row == 0)
 | 
			
		||||
                {
 | 
			
		||||
                    // Setup ItemWidth once (instead of setting up every time, which is also possible but less efficient)
 | 
			
		||||
                    ImGui::TableSetColumnIndex(0);
 | 
			
		||||
                    ImGui::PushItemWidth(TEXT_BASE_WIDTH * 3.0f); // Small
 | 
			
		||||
                    ImGui::TableSetColumnIndex(1);
 | 
			
		||||
                    ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
 | 
			
		||||
                    ImGui::TableSetColumnIndex(2);
 | 
			
		||||
                    ImGui::PushItemWidth(-FLT_MIN); // Right-aligned
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Draw our contents
 | 
			
		||||
                static float dummy_f = 0.0f;
 | 
			
		||||
                ImGui::PushID(row);
 | 
			
		||||
                ImGui::TableSetColumnIndex(0);
 | 
			
		||||
                ImGui::SliderFloat("float0", &dummy_f, 0.0f, 1.0f);
 | 
			
		||||
                ImGui::TableSetColumnIndex(1);
 | 
			
		||||
                ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f);
 | 
			
		||||
                ImGui::TableSetColumnIndex(2);
 | 
			
		||||
                ImGui::SliderFloat("float2", &dummy_f, 0.0f, 1.0f);
 | 
			
		||||
                ImGui::PopID();
 | 
			
		||||
            }
 | 
			
		||||
            ImGui::EndTable();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ImGui::TextUnformatted("Stretch + ScrollX");
 | 
			
		||||
        ImGui::SameLine();
 | 
			
		||||
        HelpMarker(
 | 
			
		||||
            "Showcase using Stretch columns + ScrollX together: "
 | 
			
		||||
            "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
 | 
			
		||||
            "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense.");
 | 
			
		||||
        static ImGuiTableFlags flags2 = ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg;
 | 
			
		||||
        static ImGuiTableFlags flags3 = ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg;
 | 
			
		||||
        static float inner_width = 1000.0f;
 | 
			
		||||
        PushStyleCompact();
 | 
			
		||||
        ImGui::PushID("flags2");
 | 
			
		||||
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags2, ImGuiTableFlags_ScrollX);
 | 
			
		||||
        if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags2, ImGuiTableFlags_ColumnsWidthStretch))
 | 
			
		||||
            flags2 &= ~ImGuiTableFlags_ColumnsWidthFixed;      // Can't specify both sizing polices so we clear the other
 | 
			
		||||
        if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags2, ImGuiTableFlags_ColumnsWidthFixed))
 | 
			
		||||
            flags2 &= ~ImGuiTableFlags_ColumnsWidthStretch;    // Can't specify both sizing polices so we clear the other
 | 
			
		||||
        ImGui::PushID("flags3");
 | 
			
		||||
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags3, ImGuiTableFlags_ScrollX);
 | 
			
		||||
        if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags3, ImGuiTableFlags_ColumnsWidthStretch))
 | 
			
		||||
            flags3 &= ~ImGuiTableFlags_ColumnsWidthFixed;      // Can't specify both sizing polices so we clear the other
 | 
			
		||||
        if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags3, ImGuiTableFlags_ColumnsWidthFixed))
 | 
			
		||||
            flags3 &= ~ImGuiTableFlags_ColumnsWidthStretch;    // Can't specify both sizing polices so we clear the other
 | 
			
		||||
        ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 10.0f);
 | 
			
		||||
        ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
 | 
			
		||||
        ImGui::PopID();
 | 
			
		||||
        PopStyleCompact();
 | 
			
		||||
 | 
			
		||||
        if (ImGui::BeginTable("##table2", 7, flags2 | ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width))
 | 
			
		||||
        if (ImGui::BeginTable("##table3", 7, flags3 | ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width))
 | 
			
		||||
        {
 | 
			
		||||
            for (int cell = 0; cell < 20 * 7; cell++)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -1893,7 +1893,7 @@ struct ImGuiTabBar
 | 
			
		||||
#define IMGUI_TABLE_MAX_COLUMNS         64                  // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64.
 | 
			
		||||
#define IMGUI_TABLE_MAX_DRAW_CHANNELS   (4 + 64 * 2)        // See TableUpdateDrawChannels()
 | 
			
		||||
 | 
			
		||||
// [Internal] sizeof() ~ 100
 | 
			
		||||
// [Internal] sizeof() ~ 104
 | 
			
		||||
// We use the terminology "Visible" to refer to a column that is not Hidden by user or settings. However it may still be out of view and clipped (see IsClipped).
 | 
			
		||||
struct ImGuiTableColumn
 | 
			
		||||
{
 | 
			
		||||
@@ -1910,6 +1910,7 @@ struct ImGuiTableColumn
 | 
			
		||||
    float                   WidthGiven;                     // Final/actual width visible == (MaxX - MinX), locked in TableUpdateLayout(). May be > WidthRequest to honor minimum width, may be < WidthRequest to honor shrinking columns down in tight space.
 | 
			
		||||
    float                   WorkMinX;                       // Start position for the frame, currently ~(MinX + CellPaddingX)
 | 
			
		||||
    float                   WorkMaxX;
 | 
			
		||||
    float                   ItemWidth;
 | 
			
		||||
    float                   ContentMaxXFrozen;              // Contents maximum position for frozen rows (apart from headers), from which we can infer content width.
 | 
			
		||||
    float                   ContentMaxXUnfrozen;
 | 
			
		||||
    float                   ContentMaxXHeadersUsed;         // Contents maximum position for headers rows (regardless of freezing). TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls
 | 
			
		||||
@@ -2009,7 +2010,9 @@ struct ImGuiTable
 | 
			
		||||
    ImRect                      HostBackupParentWorkRect;   // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
 | 
			
		||||
    ImRect                      HostBackupClipRect;         // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
 | 
			
		||||
    ImVec2                      HostBackupCursorMaxPos;     // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
 | 
			
		||||
    ImVec1                      HostBackupColumnsOffset;    // Backup of OuterWindow->ColumnsOffset at the end of BeginTable()
 | 
			
		||||
    ImVec1                      HostBackupColumnsOffset;    // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
 | 
			
		||||
    float                       HostBackupItemWidth;        // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
 | 
			
		||||
    int                         HostBackupItemWidthStackSize;// Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
 | 
			
		||||
    ImGuiWindow*                OuterWindow;                // Parent window for the table
 | 
			
		||||
    ImGuiWindow*                InnerWindow;                // Window holding the table data (== OuterWindow or a child window)
 | 
			
		||||
    ImGuiTextBuffer             ColumnsNames;               // Contiguous buffer holding columns names
 | 
			
		||||
 
 | 
			
		||||
@@ -82,8 +82,8 @@
 | 
			
		||||
//    | TableEndRow()                           - finish existing row
 | 
			
		||||
//    | TableBeginRow()                         - add a new row
 | 
			
		||||
// - TableSetColumnIndex() / TableNextColumn()  user begin into a cell
 | 
			
		||||
//    | TableEndCell()                          - close existing cell
 | 
			
		||||
//    | TableBeginCell()                        - enter into current cell
 | 
			
		||||
//    | TableEndCell()                          - close existing column/cell
 | 
			
		||||
//    | TableBeginCell()                        - enter into current column/cell
 | 
			
		||||
// - [...]                                      user emit contents
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
// - EndTable()                                 user ends the table
 | 
			
		||||
@@ -320,6 +320,8 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
 | 
			
		||||
    table->HostBackupParentWorkRect = inner_window->ParentWorkRect;
 | 
			
		||||
    table->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
 | 
			
		||||
    table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
 | 
			
		||||
    table->HostBackupItemWidth = outer_window->DC.ItemWidth;
 | 
			
		||||
    table->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
 | 
			
		||||
    inner_window->ParentWorkRect = table->WorkRect;
 | 
			
		||||
 | 
			
		||||
    // Padding and Spacing
 | 
			
		||||
@@ -826,6 +828,7 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
			
		||||
            column->ClipRect.Max.y = FLT_MAX;
 | 
			
		||||
            column->ClipRect.ClipWithFull(host_clip_rect);
 | 
			
		||||
            column->IsClipped = column->IsSkipItems = true;
 | 
			
		||||
            column->ItemWidth = 1.0f;
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -866,6 +869,7 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
			
		||||
        column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
 | 
			
		||||
        column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1;
 | 
			
		||||
        column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max
 | 
			
		||||
        column->ItemWidth = ImFloor(column->WidthGiven * 0.65f);
 | 
			
		||||
        column->ClipRect.Min.x = column->MinX;
 | 
			
		||||
        column->ClipRect.Min.y = work_rect.Min.y;
 | 
			
		||||
        column->ClipRect.Max.x = column->MaxX; // column->WorkMaxX;
 | 
			
		||||
@@ -1128,11 +1132,14 @@ void    ImGui::EndTable()
 | 
			
		||||
 | 
			
		||||
    // Layout in outer window
 | 
			
		||||
    IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!");
 | 
			
		||||
    IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= table->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
 | 
			
		||||
    PopID();
 | 
			
		||||
    inner_window->WorkRect = table->HostBackupWorkRect;
 | 
			
		||||
    inner_window->ParentWorkRect = table->HostBackupParentWorkRect;
 | 
			
		||||
    inner_window->SkipItems = table->HostSkipItems;
 | 
			
		||||
    outer_window->DC.CursorPos = table->OuterRect.Min;
 | 
			
		||||
    outer_window->DC.ItemWidth = table->HostBackupItemWidth;
 | 
			
		||||
    outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize;
 | 
			
		||||
    outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset;
 | 
			
		||||
    if (inner_window != outer_window)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1927,6 +1934,7 @@ void    ImGui::TableBeginCell(ImGuiTable* table, int column_n)
 | 
			
		||||
    window->WorkRect.Min.y = window->DC.CursorPos.y;
 | 
			
		||||
    window->WorkRect.Min.x = column->WorkMinX;
 | 
			
		||||
    window->WorkRect.Max.x = column->WorkMaxX;
 | 
			
		||||
    window->DC.ItemWidth = column->ItemWidth;
 | 
			
		||||
 | 
			
		||||
    // To allow ImGuiListClipper to function we propagate our row height
 | 
			
		||||
    if (!column->IsVisible)
 | 
			
		||||
@@ -1961,6 +1969,7 @@ void    ImGui::TableEndCell(ImGuiTable* table)
 | 
			
		||||
        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);
 | 
			
		||||
    column->ItemWidth = window->DC.ItemWidth;
 | 
			
		||||
 | 
			
		||||
    // Propagate text baseline for the entire row
 | 
			
		||||
    // FIXME-TABLE: Here we propagate text baseline from the last line of the cell.. instead of the first one.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user