mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-04 07:01:04 +01:00 
			
		
		
		
	Tables: Added ImGuiTableFlags_NoHostExtendX (#3605) marked as WIP, will probably rename.
Moved some code from BeginTable() to TableUpdateLayout() to late latch some of the required data.
This commit is contained in:
		
							
								
								
									
										23
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								imgui.h
									
									
									
									
									
								
							@@ -1075,20 +1075,21 @@ enum ImGuiTableFlags_
 | 
			
		||||
    ImGuiTableFlags_ColumnsWidthFixed               = 1 << 14,  // Default if ScrollX is on. Columns will default to use _WidthFixed or _WidthAutoResize policy (if Resizable is off). Read description above for more details.
 | 
			
		||||
    ImGuiTableFlags_SameWidths                      = 1 << 15,  // Make all columns the same widths which is useful with Fixed columns policy (but granted by default with Stretch policy + no resize). Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible and disable ImGuiTableFlags_Resizable.
 | 
			
		||||
    ImGuiTableFlags_NoHeadersWidth                  = 1 << 16,  // Disable headers' contribution to automatic width calculation.
 | 
			
		||||
    ImGuiTableFlags_NoHostExtendY                   = 1 << 17,  // 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 << 18,  // Disable keeping column always minimally visible when ScrollX is off and table gets too small.
 | 
			
		||||
    ImGuiTableFlags_PreciseWidths                   = 1 << 19,  // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.
 | 
			
		||||
    ImGuiTableFlags_NoClip                          = 1 << 20,  // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze().
 | 
			
		||||
    ImGuiTableFlags_NoHostExtendX                   = 1 << 17,  // Disable extending table past the limit required by the right-most columns. Only meaningful with Fixed columns and when neither ScrollX nor ScrollY are set.
 | 
			
		||||
    ImGuiTableFlags_NoHostExtendY                   = 1 << 18,  // Disable extending table past the limit set by outer_size.y. Only meaningful when neither ScrollX nor ScrollY are set (data below the limit will be clipped and not visible)
 | 
			
		||||
    ImGuiTableFlags_NoKeepColumnsVisible            = 1 << 19,  // Disable keeping column always minimally visible when ScrollX is off and table gets too small.
 | 
			
		||||
    ImGuiTableFlags_PreciseWidths                   = 1 << 20,  // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.
 | 
			
		||||
    ImGuiTableFlags_NoClip                          = 1 << 21,  // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze().
 | 
			
		||||
    // Padding
 | 
			
		||||
    ImGuiTableFlags_PadOuterX                       = 1 << 21,  // Default if BordersOuterV is on. Enable outer-most padding.
 | 
			
		||||
    ImGuiTableFlags_NoPadOuterX                     = 1 << 22,  // Default if BordersOuterV is off. Disable outer-most padding.
 | 
			
		||||
    ImGuiTableFlags_NoPadInnerX                     = 1 << 23,  // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off).
 | 
			
		||||
    ImGuiTableFlags_PadOuterX                       = 1 << 22,  // Default if BordersOuterV is on. Enable outer-most padding.
 | 
			
		||||
    ImGuiTableFlags_NoPadOuterX                     = 1 << 23,  // Default if BordersOuterV is off. Disable outer-most padding.
 | 
			
		||||
    ImGuiTableFlags_NoPadInnerX                     = 1 << 24,  // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off).
 | 
			
		||||
    // Scrolling
 | 
			
		||||
    ImGuiTableFlags_ScrollX                         = 1 << 24,  // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this create a child window, ScrollY is currently generally recommended when using ScrollX.
 | 
			
		||||
    ImGuiTableFlags_ScrollY                         = 1 << 25,  // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
 | 
			
		||||
    ImGuiTableFlags_ScrollX                         = 1 << 25,  // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this create a child window, ScrollY is currently generally recommended when using ScrollX.
 | 
			
		||||
    ImGuiTableFlags_ScrollY                         = 1 << 26,  // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
 | 
			
		||||
    // Sorting
 | 
			
		||||
    ImGuiTableFlags_SortMulti                       = 1 << 26,  // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
 | 
			
		||||
    ImGuiTableFlags_SortTristate                    = 1 << 27   // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
 | 
			
		||||
    ImGuiTableFlags_SortMulti                       = 1 << 27,  // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
 | 
			
		||||
    ImGuiTableFlags_SortTristate                    = 1 << 28   // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Flags for ImGui::TableSetupColumn()
 | 
			
		||||
 
 | 
			
		||||
@@ -4221,6 +4221,7 @@ static void ShowDemoWindowTables()
 | 
			
		||||
        ImGui::SetNextItemOpen(open_action != 0);
 | 
			
		||||
    if (ImGui::TreeNode("Outer size"))
 | 
			
		||||
    {
 | 
			
		||||
        ImGui::Text("Using manual/explicit size:");
 | 
			
		||||
        if (ImGui::BeginTable("##table1", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
 | 
			
		||||
        {
 | 
			
		||||
            for (int row = 0; row < 5; row++)
 | 
			
		||||
@@ -4248,6 +4249,30 @@ static void ShowDemoWindowTables()
 | 
			
		||||
            }
 | 
			
		||||
            ImGui::EndTable();
 | 
			
		||||
        }
 | 
			
		||||
        ImGui::Spacing();
 | 
			
		||||
 | 
			
		||||
        // Showcasing use of ImGuiTableFlags_NoHostExtendX and ImGuiTableFlags_NoHostExtendY
 | 
			
		||||
        // FIXME-TABLE: WIP API: Don't use yet, will probably rework/rename those flags.
 | 
			
		||||
        ImGui::Text("Using NoHostExtend flags:");
 | 
			
		||||
        static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_ColumnsWidthFixed;
 | 
			
		||||
        ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
 | 
			
		||||
        ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
 | 
			
		||||
        if (ImGui::BeginTable("##table3", 3, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 5.5f)))
 | 
			
		||||
        {
 | 
			
		||||
            for (int row = 0; row < 10; row++)
 | 
			
		||||
            {
 | 
			
		||||
                ImGui::TableNextRow();
 | 
			
		||||
                for (int column = 0; column < 3; column++)
 | 
			
		||||
                {
 | 
			
		||||
                    ImGui::TableNextColumn();
 | 
			
		||||
                    ImGui::Text("Cell %d,%d", column, row);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            ImGui::EndTable();
 | 
			
		||||
        }
 | 
			
		||||
        ImGui::SameLine();
 | 
			
		||||
        ImGui::Text("Hello!");
 | 
			
		||||
 | 
			
		||||
        ImGui::TreePop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -4715,6 +4740,7 @@ static void ShowDemoWindowTables()
 | 
			
		||||
                    flags &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other
 | 
			
		||||
                ImGui::SameLine(); HelpMarker("[Default if ScrollX is on]\nEnlarge as needed: enable scrollbar if ScrollX is enabled, otherwise extend parent window's contents rectangle. Only Fixed columns allowed. Stretched columns will calculate their width assuming no scrolling.");
 | 
			
		||||
                ImGui::CheckboxFlags("ImGuiTableFlags_NoHeadersWidth", &flags, ImGuiTableFlags_NoHeadersWidth);
 | 
			
		||||
                ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
 | 
			
		||||
                ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
 | 
			
		||||
                ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible);
 | 
			
		||||
                ImGui::SameLine(); HelpMarker("Only available if ScrollX is disabled.");
 | 
			
		||||
 
 | 
			
		||||
@@ -2072,6 +2072,7 @@ struct ImGuiTable
 | 
			
		||||
    bool                        IsResetAllRequest;
 | 
			
		||||
    bool                        IsResetDisplayOrderRequest;
 | 
			
		||||
    bool                        IsUnfrozen;                 // Set when we got past the frozen row.
 | 
			
		||||
    bool                        IsOuterRectFitX;            // Set when outer_size value passed to BeginTable() is (>= -1.0f && <= 0.0f)
 | 
			
		||||
    bool                        MemoryCompacted;
 | 
			
		||||
    bool                        HostSkipItems;              // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ Index of this file:
 | 
			
		||||
// - TableSetupColumn()                         user submit columns details (optional)
 | 
			
		||||
// - TableSetupScrollFreeze()                   user submit scroll freeze information (optional)
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
// - TableUpdateLayout() [Internal]             setup everything, lock all widths, columns positions, clipping rectangles. Automatically called by the FIRST call to TableNextRow() or TableHeadersRow().
 | 
			
		||||
// - TableUpdateLayout() [Internal]             followup to BeginTable(): setup everything: widths, columns positions, clipping rectangles. Automatically called by the FIRST call to TableNextRow() or TableHeadersRow().
 | 
			
		||||
//    | TableSetupDrawChannels()                - setup ImDrawList channels
 | 
			
		||||
//    | TableUpdateBorders()                    - detect hovering columns for resize, ahead of contents submission
 | 
			
		||||
//    | TableDrawContextMenu()                  - draw right-click context menu
 | 
			
		||||
@@ -280,6 +280,7 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
 | 
			
		||||
    table->InnerWidth = inner_width;
 | 
			
		||||
    table->OuterRect = outer_rect;
 | 
			
		||||
    table->WorkRect = outer_rect;
 | 
			
		||||
    table->IsOuterRectFitX = (outer_size.x >= -1.0f && outer_size.x <= 0.0f); // Bit ambiguous
 | 
			
		||||
 | 
			
		||||
    // When not using a child window, WorkRect.Max will grow as we append contents.
 | 
			
		||||
    if (use_child_window)
 | 
			
		||||
@@ -325,7 +326,6 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
 | 
			
		||||
    table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
 | 
			
		||||
    table->HostBackupItemWidth = outer_window->DC.ItemWidth;
 | 
			
		||||
    table->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
 | 
			
		||||
    inner_window->ParentWorkRect = table->WorkRect;
 | 
			
		||||
    inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
 | 
			
		||||
 | 
			
		||||
    // Padding and Spacing
 | 
			
		||||
@@ -356,13 +356,6 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
 | 
			
		||||
    table->InnerClipRect.ClipWithFull(table->HostClipRect);
 | 
			
		||||
    table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : inner_window->ClipRect.Max.y;
 | 
			
		||||
 | 
			
		||||
    // Initial draw cmd starts with a BgClipRect that matches the one of its host, to facilitate merge draw commands by default.
 | 
			
		||||
    // This is because all our cell highlight are manually clipped with BgClipRect
 | 
			
		||||
    // Larger at first, if/after unfreezing will become same as tight
 | 
			
		||||
    table->BgClipRect = table->InnerClipRect;
 | 
			
		||||
    table->BgClipRectForDrawCmd = table->HostClipRect;
 | 
			
		||||
    IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y);
 | 
			
		||||
 | 
			
		||||
    table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow
 | 
			
		||||
    table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
 | 
			
		||||
    table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any
 | 
			
		||||
@@ -373,8 +366,6 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
 | 
			
		||||
    // Using opaque colors facilitate overlapping elements of the grid
 | 
			
		||||
    table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
 | 
			
		||||
    table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight);
 | 
			
		||||
    table->BorderX1 = table->InnerClipRect.Min.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : -1.0f);
 | 
			
		||||
    table->BorderX2 = table->InnerClipRect.Max.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : +1.0f);
 | 
			
		||||
 | 
			
		||||
    // Make table current
 | 
			
		||||
    const int table_idx = g.Tables.GetIndex(table);
 | 
			
		||||
@@ -1001,26 +992,39 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
			
		||||
    // [Part 8] Detect/store when we are hovering the unused space after the right-most column (so e.g. context menus can react on it)
 | 
			
		||||
    // Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag, either
 | 
			
		||||
    // because of using _WidthAutoResize/_WidthStretch). This will hide the resizing option from the context menu.
 | 
			
		||||
    const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x);
 | 
			
		||||
    if (is_hovering_table && table->HoveredColumnBody == -1)
 | 
			
		||||
    {
 | 
			
		||||
        float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x);
 | 
			
		||||
        if (g.IO.MousePos.x >= unused_x1)
 | 
			
		||||
            table->HoveredColumnBody = (ImGuiTableColumnIdx)table->ColumnsCount;
 | 
			
		||||
    }
 | 
			
		||||
    if (count_resizable == 0 && (table->Flags & ImGuiTableFlags_Resizable))
 | 
			
		||||
        table->Flags &= ~ImGuiTableFlags_Resizable;
 | 
			
		||||
 | 
			
		||||
    // [Part 9] Allocate draw channels
 | 
			
		||||
    // [Part 9] Lock actual OuterRect/WorkRect right-most position.
 | 
			
		||||
    // This is done late to handle the case of fixed-columns tables not claiming more widths that they need.
 | 
			
		||||
    // Because of this we are careful with uses of WorkRect and InnerClipRect before this point.
 | 
			
		||||
    if ((table->Flags & ImGuiTableFlags_NoHostExtendX) && table->InnerWindow == table->OuterWindow && table->RightMostStretchedColumn == -1)
 | 
			
		||||
    {
 | 
			
		||||
        table->OuterRect.Max.x = table->WorkRect.Max.x = unused_x1;
 | 
			
		||||
        table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1);
 | 
			
		||||
        table->IsOuterRectFitX = false;
 | 
			
		||||
    }
 | 
			
		||||
    table->InnerWindow->ParentWorkRect = table->WorkRect;
 | 
			
		||||
    table->BorderX1 = table->InnerClipRect.Min.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : -1.0f);
 | 
			
		||||
    table->BorderX2 = table->InnerClipRect.Max.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : +1.0f);
 | 
			
		||||
 | 
			
		||||
    // [Part 10] Allocate draw channels and setup background cliprect
 | 
			
		||||
    TableSetupDrawChannels(table);
 | 
			
		||||
 | 
			
		||||
    // [Part 10] Hit testing on borders
 | 
			
		||||
    // [Part 11] Hit testing on borders
 | 
			
		||||
    if (table->Flags & ImGuiTableFlags_Resizable)
 | 
			
		||||
        TableUpdateBorders(table);
 | 
			
		||||
    table->LastFirstRowHeight = 0.0f;
 | 
			
		||||
    table->IsLayoutLocked = true;
 | 
			
		||||
    table->IsUsingHeaders = false;
 | 
			
		||||
 | 
			
		||||
    // [Part 11] Context menu
 | 
			
		||||
    // [Part 12] Context menu
 | 
			
		||||
    if (table->IsContextPopupOpen && table->InstanceCurrent == table->InstanceInteracted)
 | 
			
		||||
    {
 | 
			
		||||
        const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID);
 | 
			
		||||
@@ -1227,14 +1231,14 @@ void    ImGui::EndTable()
 | 
			
		||||
    outer_window->DC.ItemWidth = table->HostBackupItemWidth;
 | 
			
		||||
    outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize;
 | 
			
		||||
    outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset;
 | 
			
		||||
    const float outer_width = table->IsOuterRectFitX ? table->ColumnsAutoFitWidth : table->WorkRect.GetWidth();
 | 
			
		||||
    if (inner_window != outer_window)
 | 
			
		||||
    {
 | 
			
		||||
        EndChild();
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        ImVec2 item_size = table->OuterRect.GetSize();
 | 
			
		||||
        item_size.x = table->ColumnsTotalWidth;
 | 
			
		||||
        ImVec2 item_size(outer_width, table->OuterRect.GetHeight());
 | 
			
		||||
        ItemSize(item_size);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1247,7 +1251,8 @@ void    ImGui::EndTable()
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, table->WorkRect.Min.x + table->ColumnsAutoFitWidth); // For auto-fit
 | 
			
		||||
        outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, table->WorkRect.Min.x + outer_width); // For auto-fit
 | 
			
		||||
        outer_window->DC.CursorPosPrevLine.x = table->WorkRect.Max.x; // For consistent reaction to SameLine() // FIXME: Should be a feature of layout/ItemAdd
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Save settings
 | 
			
		||||
@@ -2068,6 +2073,13 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
 | 
			
		||||
        }
 | 
			
		||||
        column->DrawChannelCurrent = column->DrawChannelFrozen;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Initial draw cmd starts with a BgClipRect that matches the one of its host, to facilitate merge draw commands by default.
 | 
			
		||||
    // All our cell highlight are manually clipped with BgClipRect. When unfreezing it will be made smaller to fit scrolling rect.
 | 
			
		||||
    // (This technically isn't part of setting up draw channels, but is reasonably related to be done here)
 | 
			
		||||
    table->BgClipRect = table->InnerClipRect;
 | 
			
		||||
    table->BgClipRectForDrawCmd = table->HostClipRect;
 | 
			
		||||
    IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function reorder draw channels based on matching clip rectangle, to facilitate merging them. Called by EndTable().
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user