mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-04 07:01:04 +01:00 
			
		
		
		
	Tables: Calculating ideal total width, some renaming, comments. Clarify that inner_width is unused with ScrollX=0. Clip many comments to 120 columns.
This commit is contained in:
		@@ -10515,7 +10515,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
 | 
				
			|||||||
            else if (rect_type == TRT_ColumnsRect)                  { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table->LastOuterHeight); }
 | 
					            else if (rect_type == TRT_ColumnsRect)                  { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table->LastOuterHeight); }
 | 
				
			||||||
            else if (rect_type == TRT_ColumnsClipRect)              { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; }
 | 
					            else if (rect_type == TRT_ColumnsClipRect)              { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; }
 | 
				
			||||||
            else if (rect_type == TRT_ColumnsContentHeadersUsed)    { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }    // Note: y1/y2 not always accurate
 | 
					            else if (rect_type == TRT_ColumnsContentHeadersUsed)    { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }    // Note: y1/y2 not always accurate
 | 
				
			||||||
            else if (rect_type == TRT_ColumnsContentHeadersIdeal)   { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthHeadersDesired, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // "
 | 
					            else if (rect_type == TRT_ColumnsContentHeadersIdeal)   { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthHeadersIdeal, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // "
 | 
				
			||||||
            else if (rect_type == TRT_ColumnsContentRowsFrozen)     { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthRowsFrozen, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }     // "
 | 
					            else if (rect_type == TRT_ColumnsContentRowsFrozen)     { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthRowsFrozen, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }     // "
 | 
				
			||||||
            else if (rect_type == TRT_ColumnsContentRowsUnfrozen)   { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y + table->LastFirstRowHeight, c->MinX + c->ContentWidthRowsUnfrozen, table->InnerClipRect.Max.y); }   // "
 | 
					            else if (rect_type == TRT_ColumnsContentRowsUnfrozen)   { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y + table->LastFirstRowHeight, c->MinX + c->ContentWidthRowsUnfrozen, table->InnerClipRect.Max.y); }   // "
 | 
				
			||||||
            IM_ASSERT(0);
 | 
					            IM_ASSERT(0);
 | 
				
			||||||
@@ -10573,7 +10573,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
 | 
				
			|||||||
            for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++)
 | 
					            for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ImGuiTable* table = g.Tables.GetByIndex(table_n);
 | 
					                ImGuiTable* table = g.Tables.GetByIndex(table_n);
 | 
				
			||||||
                if (table->LastFrameActive < g.FrameCount - 1 || table->OuterWindow != g.NavWindow)
 | 
					                if (table->LastFrameActive < g.FrameCount - 1 || (table->OuterWindow != g.NavWindow && table->InnerWindow != g.NavWindow))
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
 | 
					                BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3680,8 +3680,8 @@ static void ShowDemoWindowTables()
 | 
				
			|||||||
                ImGui::CheckboxFlags("_NoSortDescending", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_NoSortDescending);
 | 
					                ImGui::CheckboxFlags("_NoSortDescending", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_NoSortDescending);
 | 
				
			||||||
                ImGui::CheckboxFlags("_PreferSortAscending", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_PreferSortAscending);
 | 
					                ImGui::CheckboxFlags("_PreferSortAscending", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_PreferSortAscending);
 | 
				
			||||||
                ImGui::CheckboxFlags("_PreferSortDescending", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_PreferSortDescending);
 | 
					                ImGui::CheckboxFlags("_PreferSortDescending", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_PreferSortDescending);
 | 
				
			||||||
                ImGui::CheckboxFlags("_IndentEnable", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_IndentEnable);
 | 
					                ImGui::CheckboxFlags("_IndentEnable", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_IndentEnable); ImGui::SameLine(); HelpMarker("Default for column 0");
 | 
				
			||||||
                ImGui::CheckboxFlags("_IndentDisable", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_IndentDisable);
 | 
					                ImGui::CheckboxFlags("_IndentDisable", (unsigned int*)&column_flags[column], ImGuiTableColumnFlags_IndentDisable); ImGui::SameLine(); HelpMarker("Default for column >0");
 | 
				
			||||||
                ImGui::PopID();
 | 
					                ImGui::PopID();
 | 
				
			||||||
                ImGui::PopStyleVar(2);
 | 
					                ImGui::PopStyleVar(2);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -4089,7 +4089,6 @@ static void ShowDemoWindowTables()
 | 
				
			|||||||
        static int items_count = IM_ARRAYSIZE(template_items_names);
 | 
					        static int items_count = IM_ARRAYSIZE(template_items_names);
 | 
				
			||||||
        static ImVec2 outer_size_value = ImVec2(0, 250);
 | 
					        static ImVec2 outer_size_value = ImVec2(0, 250);
 | 
				
			||||||
        static float row_min_height = 0.0f; // Auto
 | 
					        static float row_min_height = 0.0f; // Auto
 | 
				
			||||||
        static float inner_width_without_scroll = 0.0f; // Fill 
 | 
					 | 
				
			||||||
        static float inner_width_with_scroll = 0.0f; // Auto-extend
 | 
					        static float inner_width_with_scroll = 0.0f; // Auto-extend
 | 
				
			||||||
        static bool outer_size_enabled = true;
 | 
					        static bool outer_size_enabled = true;
 | 
				
			||||||
        static bool lock_first_column_visibility = false;
 | 
					        static bool lock_first_column_visibility = false;
 | 
				
			||||||
@@ -4171,10 +4170,7 @@ static void ShowDemoWindowTables()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling.
 | 
					            // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling.
 | 
				
			||||||
            // To facilitate experimentation we expose two values and will select the right one depending on active flags.
 | 
					            // To facilitate experimentation we expose two values and will select the right one depending on active flags.
 | 
				
			||||||
            if (flags & ImGuiTableFlags_ScrollX)
 | 
					            ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX);
 | 
				
			||||||
                ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX);
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                ImGui::DragFloat("inner_width (when ScrollX inactive)", &inner_width_without_scroll, 1.0f, 0.0f, FLT_MAX);
 | 
					 | 
				
			||||||
            ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX);
 | 
					            ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX);
 | 
				
			||||||
            ImGui::SameLine(); HelpMarker("Specify height of the Selectable item.");
 | 
					            ImGui::SameLine(); HelpMarker("Specify height of the Selectable item.");
 | 
				
			||||||
            ImGui::DragInt("items_count", &items_count, 0.1f, 0, 5000);
 | 
					            ImGui::DragInt("items_count", &items_count, 0.1f, 0, 5000);
 | 
				
			||||||
@@ -4213,7 +4209,7 @@ static void ShowDemoWindowTables()
 | 
				
			|||||||
        ImVec2 table_scroll_cur, table_scroll_max; // For debug display
 | 
					        ImVec2 table_scroll_cur, table_scroll_max; // For debug display
 | 
				
			||||||
        const ImDrawList* table_draw_list = NULL;  // "
 | 
					        const ImDrawList* table_draw_list = NULL;  // "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const float inner_width_to_use = (flags & ImGuiTableFlags_ScrollX) ? inner_width_with_scroll : inner_width_without_scroll;
 | 
					        const float inner_width_to_use = (flags & ImGuiTableFlags_ScrollX) ? inner_width_with_scroll : 0.0f;
 | 
				
			||||||
        if (ImGui::BeginTable("##table", 6, flags, outer_size_enabled ? outer_size_value : ImVec2(0, 0), inner_width_to_use))
 | 
					        if (ImGui::BeginTable("##table", 6, flags, outer_size_enabled ? outer_size_value : ImVec2(0, 0), inner_width_to_use))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Declare columns
 | 
					            // Declare columns
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1905,11 +1905,11 @@ struct ImGuiTableColumn
 | 
				
			|||||||
    float                   ContentMaxPosRowsFrozen;        // Submitted contents absolute maximum position, from which we can infer width.
 | 
					    float                   ContentMaxPosRowsFrozen;        // Submitted contents absolute maximum position, from which we can infer width.
 | 
				
			||||||
    float                   ContentMaxPosRowsUnfrozen;      // (kept as float because we need to manipulate those between each cell change)
 | 
					    float                   ContentMaxPosRowsUnfrozen;      // (kept as float because we need to manipulate those between each cell change)
 | 
				
			||||||
    float                   ContentMaxPosHeadersUsed;
 | 
					    float                   ContentMaxPosHeadersUsed;
 | 
				
			||||||
    float                   ContentMaxPosHeadersDesired;
 | 
					    float                   ContentMaxPosHeadersIdeal;
 | 
				
			||||||
    ImS16                   ContentWidthRowsFrozen;         // Contents width. Because row freezing is not correlated with headers/not-headers we need all 4 variants (ImDrawCmd merging uses different data than alignment code).
 | 
					    ImS16                   ContentWidthRowsFrozen;         // Contents width. Because row freezing is not correlated with headers/not-headers we need all 4 variants (ImDrawCmd merging uses different data than alignment code).
 | 
				
			||||||
    ImS16                   ContentWidthRowsUnfrozen;       // (encoded as ImS16 because we actually rarely use those width)
 | 
					    ImS16                   ContentWidthRowsUnfrozen;       // (encoded as ImS16 because we actually rarely use those width)
 | 
				
			||||||
    ImS16                   ContentWidthHeadersUsed;        // TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls
 | 
					    ImS16                   ContentWidthHeadersUsed;        // TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls
 | 
				
			||||||
    ImS16                   ContentWidthHeadersDesired;
 | 
					    ImS16                   ContentWidthHeadersIdeal;
 | 
				
			||||||
    ImS16                   NameOffset;                     // Offset into parent ColumnsNames[]
 | 
					    ImS16                   NameOffset;                     // Offset into parent ColumnsNames[]
 | 
				
			||||||
    bool                    IsActive;                       // Is the column not marked Hidden by the user (regardless of clipping). We're not calling this "Visible" here because visibility also depends on clipping.
 | 
					    bool                    IsActive;                       // Is the column not marked Hidden by the user (regardless of clipping). We're not calling this "Visible" here because visibility also depends on clipping.
 | 
				
			||||||
    bool                    IsActiveNextFrame;
 | 
					    bool                    IsActiveNextFrame;
 | 
				
			||||||
@@ -1982,7 +1982,8 @@ struct ImGuiTable
 | 
				
			|||||||
    float                       LastOuterHeight;            // Outer height from last frame
 | 
					    float                       LastOuterHeight;            // Outer height from last frame
 | 
				
			||||||
    float                       LastFirstRowHeight;         // Height of first row from last frame
 | 
					    float                       LastFirstRowHeight;         // Height of first row from last frame
 | 
				
			||||||
    float                       ColumnsTotalWidth;
 | 
					    float                       ColumnsTotalWidth;
 | 
				
			||||||
    float                       InnerWidth;
 | 
					    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                       ResizedColumnNextWidth;
 | 
					    float                       ResizedColumnNextWidth;
 | 
				
			||||||
    ImRect                      OuterRect;                  // Note: OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable().
 | 
					    ImRect                      OuterRect;                  // Note: OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable().
 | 
				
			||||||
    ImRect                      WorkRect;
 | 
					    ImRect                      WorkRect;
 | 
				
			||||||
@@ -2264,14 +2265,14 @@ namespace ImGui
 | 
				
			|||||||
    IMGUI_API void          TableBeginCell(ImGuiTable* table, int column_n);
 | 
					    IMGUI_API void          TableBeginCell(ImGuiTable* table, int column_n);
 | 
				
			||||||
    IMGUI_API void          TableEndCell(ImGuiTable* table);
 | 
					    IMGUI_API void          TableEndCell(ImGuiTable* table);
 | 
				
			||||||
    IMGUI_API ImRect        TableGetCellRect();
 | 
					    IMGUI_API ImRect        TableGetCellRect();
 | 
				
			||||||
    IMGUI_API const char*   TableGetColumnName(ImGuiTable* table, int column_n);
 | 
					    IMGUI_API const char*   TableGetColumnName(const ImGuiTable* table, int column_n);
 | 
				
			||||||
    IMGUI_API ImGuiID       TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0);
 | 
					    IMGUI_API ImGuiID       TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0);
 | 
				
			||||||
    IMGUI_API void          TableSetColumnAutofit(ImGuiTable* table, int column_n);
 | 
					    IMGUI_API void          TableSetColumnAutofit(ImGuiTable* table, int column_n);
 | 
				
			||||||
    IMGUI_API void          PushTableBackground();
 | 
					    IMGUI_API void          PushTableBackground();
 | 
				
			||||||
    IMGUI_API void          PopTableBackground();
 | 
					    IMGUI_API void          PopTableBackground();
 | 
				
			||||||
    IMGUI_API void          TableLoadSettings(ImGuiTable* table);
 | 
					    IMGUI_API void          TableLoadSettings(ImGuiTable* table);
 | 
				
			||||||
    IMGUI_API void          TableSaveSettings(ImGuiTable* table);
 | 
					    IMGUI_API void          TableSaveSettings(ImGuiTable* table);
 | 
				
			||||||
    IMGUI_API ImGuiTableSettings* TableFindSettings(ImGuiTable* table);
 | 
					    IMGUI_API ImGuiTableSettings* TableFindSettings(const ImGuiTable* table);
 | 
				
			||||||
    IMGUI_API void*         TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
 | 
					    IMGUI_API void*         TableSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name);
 | 
				
			||||||
    IMGUI_API void          TableSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
 | 
					    IMGUI_API void          TableSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line);
 | 
				
			||||||
    IMGUI_API void          TableSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
 | 
					    IMGUI_API void          TableSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										272
									
								
								imgui_tables.cpp
									
									
									
									
									
								
							
							
						
						
									
										272
									
								
								imgui_tables.cpp
									
									
									
									
									
								
							@@ -109,8 +109,8 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags)
 | 
				
			|||||||
    if (flags & ImGuiTableFlags_Resizable)
 | 
					    if (flags & ImGuiTableFlags_Resizable)
 | 
				
			||||||
        flags |= ImGuiTableFlags_BordersVInner;
 | 
					        flags |= ImGuiTableFlags_BordersVInner;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Adjust flags: disable top rows freezing if there's no scrolling
 | 
					    // Adjust flags: disable top rows freezing if there's no scrolling.
 | 
				
			||||||
    // In theory we could want to assert if ScrollFreeze was set without the corresponding scroll flag, but that would hinder demos.
 | 
					    // We could want to assert if ScrollFreeze was set without the corresponding scroll flag, but that would hinder demos.
 | 
				
			||||||
    if ((flags & ImGuiTableFlags_ScrollX) == 0)
 | 
					    if ((flags & ImGuiTableFlags_ScrollX) == 0)
 | 
				
			||||||
        flags &= ~ImGuiTableFlags_ScrollFreezeColumnsMask_;
 | 
					        flags &= ~ImGuiTableFlags_ScrollFreezeColumnsMask_;
 | 
				
			||||||
    if ((flags & ImGuiTableFlags_ScrollY) == 0)
 | 
					    if ((flags & ImGuiTableFlags_ScrollY) == 0)
 | 
				
			||||||
@@ -120,7 +120,8 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags)
 | 
				
			|||||||
    if ((flags & ImGuiTableFlags_NoHostExtendY) && (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0)
 | 
					    if ((flags & ImGuiTableFlags_NoHostExtendY) && (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0)
 | 
				
			||||||
        flags &= ~ImGuiTableFlags_NoHostExtendY;
 | 
					        flags &= ~ImGuiTableFlags_NoHostExtendY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Adjust flags: we don't support NoClipX with (FreezeColumns > 0), we could with some work but it doesn't appear to be worth the effort
 | 
					    // Adjust flags: we don't support NoClipX with (FreezeColumns > 0)
 | 
				
			||||||
 | 
					    // We could with some work but it doesn't appear to be worth the effort.
 | 
				
			||||||
    if (flags & ImGuiTableFlags_ScrollFreezeColumnsMask_)
 | 
					    if (flags & ImGuiTableFlags_ScrollFreezeColumnsMask_)
 | 
				
			||||||
        flags &= ~ImGuiTableFlags_NoClipX;
 | 
					        flags &= ~ImGuiTableFlags_NoClipX;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,28 +134,32 @@ ImGuiTable* ImGui::FindTableByID(ImGuiID id)
 | 
				
			|||||||
    return g.Tables.GetByKey(id);
 | 
					    return g.Tables.GetByKey(id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// About 'outer_size':
 | 
					// (Read carefully because this is subtle but it does make sense!)
 | 
				
			||||||
//   The meaning of outer_size needs to differ slightly depending of if we are using ScrollX/ScrollY flags.
 | 
					// About 'outer_size', its meaning needs to differ slightly depending of if we are using ScrollX/ScrollY flags:
 | 
				
			||||||
//   With ScrollX/ScrollY: using a child window for scrolling:
 | 
					//   X:
 | 
				
			||||||
 | 
					//   - outer_size.x < 0.0f  ->  right align from window/work-rect maximum x edge.
 | 
				
			||||||
 | 
					//   - outer_size.x = 0.0f  ->  auto enlarge, use all available space.
 | 
				
			||||||
 | 
					//   - outer_size.x > 0.0f  ->  fixed width
 | 
				
			||||||
 | 
					//   Y with ScrollX/ScrollY: using a child window for scrolling:
 | 
				
			||||||
//   - outer_size.y < 0.0f  ->  bottom align
 | 
					//   - outer_size.y < 0.0f  ->  bottom align
 | 
				
			||||||
//   - outer_size.y = 0.0f  ->  bottom align: consistent with BeginChild(), best to preserve (0,0) default arg
 | 
					//   - outer_size.y = 0.0f  ->  bottom align, consistent with BeginChild(). not recommended unless table is last item in parent window.
 | 
				
			||||||
//   - outer_size.y > 0.0f  ->  fixed child height
 | 
					//   - outer_size.y > 0.0f  ->  fixed child height. recommended when using Scrolling on any axis.
 | 
				
			||||||
//   Without scrolling, we output table directly in parent window:
 | 
					//   Y without scrolling, we output table directly in parent window:
 | 
				
			||||||
//   - outer_size.y < 0.0f  ->  bottom align (will auto extend, unless NoHostExtendV is set)
 | 
					//   - outer_size.y < 0.0f  ->  bottom align (will auto extend, unless NoHostExtendV is set)
 | 
				
			||||||
//   - outer_size.y = 0.0f  ->  zero minimum height (will auto extend, unless NoHostExtendV is set)
 | 
					//   - outer_size.y = 0.0f  ->  zero minimum height (will auto extend, unless NoHostExtendV is set)
 | 
				
			||||||
//   - outer_size.y > 0.0f  ->  minimum height (will auto extend, unless NoHostExtendV is set)
 | 
					//   - outer_size.y > 0.0f  ->  minimum height (will auto extend, unless NoHostExtendV is set)
 | 
				
			||||||
// About: 'inner_width':
 | 
					// About 'inner_width':
 | 
				
			||||||
//   With ScrollX:
 | 
					//   With ScrollX:
 | 
				
			||||||
//   - inner_width  < 0.0f  ->  *illegal* fit in known width (right align from outer_size.x) <-- weird
 | 
					//   - inner_width  < 0.0f  ->  *illegal* fit in known width (right align from outer_size.x) <-- weird
 | 
				
			||||||
//   - inner_width  = 0.0f  ->  auto enlarge: *only* fixed size columns, which will take space they need (proportional columns becomes fixed columns) <-- desired default :(
 | 
					//   - inner_width  = 0.0f  ->  fit in outer_width: Fixed size columns will take space they need (if avail, otherwise shrink down), Stretch columns becomes Fixed columns.
 | 
				
			||||||
//   - inner_width  > 0.0f  ->  fit in known width: fixed column take space they need if possible (otherwise shrink down), proportional columns share remaining space.
 | 
					//   - inner_width  > 0.0f  ->  override scrolling width, generally to be larger than outer_size.x. Fixed column take space they need (if avail, otherwise shrink down), Stretch columns share remaining space!
 | 
				
			||||||
//   Without ScrollX:
 | 
					//   Without ScrollX:
 | 
				
			||||||
//   - inner_width  < 0.0f  ->  fit in known width (right align from outer_size.x) <-- desired default
 | 
					//   - inner_width          ->  *ignored*
 | 
				
			||||||
//   - inner_width  = 0.0f  ->  auto enlarge: will emit contents size in parent window
 | 
					// Details:
 | 
				
			||||||
//   - inner_width  > 0.0f  ->  fit in known width (bypass outer_size.x, permitted but not useful, should instead alter outer_width)
 | 
					// - If you want to use Stretch columns with ScrollX, you generally need to specify 'inner_width' otherwise the concept
 | 
				
			||||||
// FIXME-TABLE: This is currently not very useful.
 | 
					//   of "available space" doesn't make sense.
 | 
				
			||||||
// FIXME-TABLE: Replace enlarge vs fixed width by a flag.
 | 
					// - Even if not really useful, we allow 'inner_width < outer_size.x' for consistency and to facilitate understanding
 | 
				
			||||||
// Even if not really useful, we allow 'inner_scroll_width < outer_size.x' for consistency and to facilitate understanding of what the value does.
 | 
					//   of what the value does.
 | 
				
			||||||
bool    ImGui::BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width)
 | 
					bool    ImGui::BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ImGuiID id = GetID(str_id);
 | 
					    ImGuiID id = GetID(str_id);
 | 
				
			||||||
@@ -213,15 +218,17 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (use_child_window)
 | 
					    if (use_child_window)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Ensure no vertical scrollbar appears if we only want horizontal one, to make flag consistent (we have no other way to disable vertical scrollbar of a window while keeping the horizontal one showing)
 | 
					        // Ensure no vertical scrollbar appears if we only want horizontal one, to make flag consistent
 | 
				
			||||||
 | 
					        // (we have no other way to disable vertical scrollbar of a window while keeping the horizontal one showing)
 | 
				
			||||||
        ImVec2 override_content_size(FLT_MAX, FLT_MAX);
 | 
					        ImVec2 override_content_size(FLT_MAX, FLT_MAX);
 | 
				
			||||||
        if ((flags & ImGuiTableFlags_ScrollX) && !(flags & ImGuiTableFlags_ScrollY))
 | 
					        if ((flags & ImGuiTableFlags_ScrollX) && !(flags & ImGuiTableFlags_ScrollY))
 | 
				
			||||||
            override_content_size.y = FLT_MIN;
 | 
					            override_content_size.y = FLT_MIN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Ensure specified width (when not specified, Stretched columns will act as if the width == OuterWidth and never lead to any scrolling)
 | 
					        // Ensure specified width (when not specified, Stretched columns will act as if the width == OuterWidth and
 | 
				
			||||||
        // We don't handle inner_width < 0.0f, we could potentially use it to right-align based on the right side of the child window work rect,
 | 
					        // never lead to any scrolling). We don't handle inner_width < 0.0f, we could potentially use it to right-align
 | 
				
			||||||
        // which would require knowing ahead if we are going to have decoration taking horizontal spaces (typically a vertical scrollbar).
 | 
					        // based on the right side of the child window work rect, which would require knowing ahead if we are going to
 | 
				
			||||||
        if (inner_width != 0.0f)
 | 
					        // have decoration taking horizontal spaces (typically a vertical scrollbar).
 | 
				
			||||||
 | 
					        if ((flags & ImGuiTableFlags_ScrollX) && inner_width > 0.0f)
 | 
				
			||||||
            override_content_size.x = inner_width;
 | 
					            override_content_size.x = inner_width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (override_content_size.x != FLT_MAX || override_content_size.y != FLT_MAX)
 | 
					        if (override_content_size.x != FLT_MAX || override_content_size.y != FLT_MAX)
 | 
				
			||||||
@@ -322,7 +329,7 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
 | 
				
			|||||||
        TableLoadSettings(table);
 | 
					        TableLoadSettings(table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Disable output until user calls TableNextRow() or TableNextCell() leading to the TableUpdateLayout() call..
 | 
					    // Disable output until user calls TableNextRow() or TableNextCell() leading to the TableUpdateLayout() call..
 | 
				
			||||||
    // This is not strictly necessary but will reduce cases were misleading "out of table" output will be confusing to the user.
 | 
					    // This is not strictly necessary but will reduce cases were "out of table" output will be misleading to the user.
 | 
				
			||||||
    // Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option.
 | 
					    // Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option.
 | 
				
			||||||
    inner_window->SkipItems = true;
 | 
					    inner_window->SkipItems = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -373,7 +380,8 @@ void ImGui::TableBeginUpdateColumns(ImGuiTable* table)
 | 
				
			|||||||
                table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImS8)reorder_dir;
 | 
					                table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder -= (ImS8)reorder_dir;
 | 
				
			||||||
            IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir);
 | 
					            IM_ASSERT(dst_column->DisplayOrder == dst_order - reorder_dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[], rebuild the later from the former.
 | 
					            // Display order is stored in both columns->IndexDisplayOrder and table->DisplayOrder[],
 | 
				
			||||||
 | 
					            // rebuild the later from the former.
 | 
				
			||||||
            for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
 | 
					            for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
 | 
				
			||||||
                table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImS8)column_n;
 | 
					                table->DisplayOrderToIndex[table->Columns[column_n].DisplayOrder] = (ImS8)column_n;
 | 
				
			||||||
            table->ReorderColumnDir = 0;
 | 
					            table->ReorderColumnDir = 0;
 | 
				
			||||||
@@ -452,10 +460,13 @@ void ImGui::TableBeginUpdateColumns(ImGuiTable* table)
 | 
				
			|||||||
void ImGui::TableUpdateDrawChannels(ImGuiTable* table)
 | 
					void ImGui::TableUpdateDrawChannels(ImGuiTable* table)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Allocate draw channels.
 | 
					    // Allocate draw channels.
 | 
				
			||||||
    // - We allocate them following the storage order instead of the display order so reordering columns won't needlessly increase overall dormant memory cost.
 | 
					    // - We allocate them following storage order instead of display order so reordering columns won't needlessly
 | 
				
			||||||
    // - We isolate headers draw commands in their own channels instead of just altering clip rects. This is in order to facilitate merging of draw commands.
 | 
					    //   increase overall dormant memory cost.
 | 
				
			||||||
    // - After crossing FreezeRowsCount, all columns see their current draw channel changed to a second set of draw channels.
 | 
					    // - We isolate headers draw commands in their own channels instead of just altering clip rects.
 | 
				
			||||||
    // - We only use the dummy draw channel so we can push a null clipping rectangle into it without affecting other channels, while simplifying per-row/per-cell overhead. It will be empty and discarded when merged.
 | 
					    //   This is in order to facilitate merging of draw commands.
 | 
				
			||||||
 | 
					    // - After crossing FreezeRowsCount, all columns see their current draw channel changed to a second set of channels.
 | 
				
			||||||
 | 
					    // - We only use the dummy draw channel so we can push a null clipping rectangle into it without affecting other
 | 
				
			||||||
 | 
					    //   channels, while simplifying per-row/per-cell overhead. It will be empty and discarded when merged.
 | 
				
			||||||
    // Draw channel allocation (before merging):
 | 
					    // Draw channel allocation (before merging):
 | 
				
			||||||
    // - NoClip                       --> 1+1 channels: background + foreground (same clip rect == 1 draw call)
 | 
					    // - NoClip                       --> 1+1 channels: background + foreground (same clip rect == 1 draw call)
 | 
				
			||||||
    // - Clip                         --> 1+N channels
 | 
					    // - Clip                         --> 1+N channels
 | 
				
			||||||
@@ -536,21 +547,24 @@ static float TableGetMinColumnWidth()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Layout columns for the frame
 | 
					// Layout columns for the frame
 | 
				
			||||||
// Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first.
 | 
					// Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first.
 | 
				
			||||||
// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for WidthAlwaysAutoResize columns,
 | 
					// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for WidthAlwaysAutoResize
 | 
				
			||||||
// increase feedback side-effect with widgets relying on WorkRect.Max.x. Maybe provide a default distribution for WidthAlwaysAutoResize columns?
 | 
					// columns, increase feedback side-effect with widgets relying on WorkRect.Max.x. Maybe provide a default distribution
 | 
				
			||||||
 | 
					// for WidthAlwaysAutoResize columns?
 | 
				
			||||||
void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
					void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    IM_ASSERT(table->IsLayoutLocked == false);
 | 
					    IM_ASSERT(table->IsLayoutLocked == false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Compute offset, clip rect for the frame
 | 
					    // Compute offset, clip rect for the frame
 | 
				
			||||||
 | 
					    // (can't make auto padding larger than what WorkRect knows about so right-alignment matches)
 | 
				
			||||||
    const ImRect work_rect = table->WorkRect;
 | 
					    const ImRect work_rect = table->WorkRect;
 | 
				
			||||||
    const float padding_auto_x = table->CellPaddingX2; // Can't make auto padding larger than what WorkRect knows about so right-alignment matches.
 | 
					    const float padding_auto_x = table->CellPaddingX2;
 | 
				
			||||||
    const float min_column_width = TableGetMinColumnWidth();
 | 
					    const float min_column_width = TableGetMinColumnWidth();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int count_fixed = 0;
 | 
					    int count_fixed = 0;
 | 
				
			||||||
    float width_fixed = 0.0f;
 | 
					    float width_fixed = 0.0f;
 | 
				
			||||||
    float total_weights = 0.0f;
 | 
					    float total_weights = 0.0f;
 | 
				
			||||||
    table->LeftMostStretchedColumnDisplayOrder = -1;
 | 
					    table->LeftMostStretchedColumnDisplayOrder = -1;
 | 
				
			||||||
 | 
					    table->IdealTotalWidth = 0.0f;
 | 
				
			||||||
    for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
 | 
					    for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        if (!(table->ActiveMaskByDisplayOrder & ((ImU64)1 << order_n)))
 | 
					        if (!(table->ActiveMaskByDisplayOrder & ((ImU64)1 << order_n)))
 | 
				
			||||||
@@ -569,6 +583,16 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
        if (table->Flags & ImGuiTableFlags_Sortable)
 | 
					        if (table->Flags & ImGuiTableFlags_Sortable)
 | 
				
			||||||
            TableFixColumnSortDirection(column);
 | 
					            TableFixColumnSortDirection(column);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Calculate "ideal" column width for nothing to be clipped.
 | 
				
			||||||
 | 
					        // Combine width from regular rows + width from headers unless requested not to.
 | 
				
			||||||
 | 
					        const float column_content_width_rows = (float)ImMax(column->ContentWidthRowsFrozen, column->ContentWidthRowsUnfrozen);
 | 
				
			||||||
 | 
					        const float column_content_width_headers = (float)column->ContentWidthHeadersIdeal;
 | 
				
			||||||
 | 
					        float column_width_ideal = column_content_width_rows;
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (column->Flags & (ImGuiTableColumnFlags_WidthAlwaysAutoResize | ImGuiTableColumnFlags_WidthFixed))
 | 
					        if (column->Flags & (ImGuiTableColumnFlags_WidthAlwaysAutoResize | ImGuiTableColumnFlags_WidthFixed))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Latch initial size for fixed columns
 | 
					            // Latch initial size for fixed columns
 | 
				
			||||||
@@ -576,14 +600,11 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
            const bool init_size = (column->AutoFitQueue != 0x00) || (column->Flags & ImGuiTableColumnFlags_WidthAlwaysAutoResize);
 | 
					            const bool init_size = (column->AutoFitQueue != 0x00) || (column->Flags & ImGuiTableColumnFlags_WidthAlwaysAutoResize);
 | 
				
			||||||
            if (init_size)
 | 
					            if (init_size)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Combine width from regular rows + width from headers unless requested not to
 | 
					                column->WidthRequested = column_width_ideal;
 | 
				
			||||||
                float width_request = (float)ImMax(column->ContentWidthRowsFrozen, column->ContentWidthRowsUnfrozen);
 | 
					 | 
				
			||||||
                if (!(table->Flags & ImGuiTableFlags_NoHeadersWidth) && !(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth))
 | 
					 | 
				
			||||||
                    width_request = ImMax(width_request, (float)column->ContentWidthHeadersDesired);
 | 
					 | 
				
			||||||
                column->WidthRequested = ImMax(width_request + padding_auto_x, min_column_width);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets (e.g. TextWrapped) too much.
 | 
					                // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets
 | 
				
			||||||
                // Otherwise what tends to happen is that TextWrapped would output a very large height (= first frame scrollbar display very off + clipper would skip lots of items)
 | 
					                // (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very
 | 
				
			||||||
 | 
					                // large height (= first frame scrollbar display very off + clipper would skip lots of items).
 | 
				
			||||||
                // This is merely making the side-effect less extreme, but doesn't properly fixes it.
 | 
					                // This is merely making the side-effect less extreme, but doesn't properly fixes it.
 | 
				
			||||||
                if (column->AutoFitQueue > 0x01 && table->IsInitializing)
 | 
					                if (column->AutoFitQueue > 0x01 && table->IsInitializing)
 | 
				
			||||||
                    column->WidthRequested = ImMax(column->WidthRequested, min_column_width * 4.0f);
 | 
					                    column->WidthRequested = ImMax(column->WidthRequested, min_column_width * 4.0f);
 | 
				
			||||||
@@ -606,7 +627,7 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
    // Remove -1.0f to cancel out the +1.0f we are doing in EndTable() to make last column line visible
 | 
					    // 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);
 | 
					    const float width_spacings = table->CellSpacingX * (table->ColumnsActiveCount - 1);
 | 
				
			||||||
    float width_avail;
 | 
					    float width_avail;
 | 
				
			||||||
    if ((table->Flags & ImGuiTableFlags_ScrollX) && (table->InnerWidth == 0.0f))
 | 
					    if ((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f)
 | 
				
			||||||
        width_avail = table->InnerClipRect.GetWidth() - width_spacings - 1.0f;
 | 
					        width_avail = table->InnerClipRect.GetWidth() - width_spacings - 1.0f;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        width_avail = work_rect.GetWidth() - width_spacings - 1.0f;
 | 
					        width_avail = work_rect.GetWidth() - width_spacings - 1.0f;
 | 
				
			||||||
@@ -630,15 +651,16 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
            column->WidthRequested = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, min_column_width) + 0.01f);
 | 
					            column->WidthRequested = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, min_column_width) + 0.01f);
 | 
				
			||||||
            width_remaining_for_stretched_columns -= column->WidthRequested;
 | 
					            width_remaining_for_stretched_columns -= column->WidthRequested;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // [Resize Rule 2] Resizing from right-side of a weighted column before a fixed column froward sizing to left-side of fixed column
 | 
					            // [Resize Rule 2] Resizing from right-side of a weighted column before a fixed column froward sizing
 | 
				
			||||||
            // We also need to copy the NoResize flag..
 | 
					            // to left-side of fixed column. We also need to copy the NoResize flag..
 | 
				
			||||||
            if (column->NextActiveColumn != -1)
 | 
					            if (column->NextActiveColumn != -1)
 | 
				
			||||||
                if (ImGuiTableColumn* next_column = &table->Columns[column->NextActiveColumn])
 | 
					                if (ImGuiTableColumn* next_column = &table->Columns[column->NextActiveColumn])
 | 
				
			||||||
                    if (next_column->Flags & ImGuiTableColumnFlags_WidthFixed)
 | 
					                    if (next_column->Flags & ImGuiTableColumnFlags_WidthFixed)
 | 
				
			||||||
                        column->Flags |= (next_column->Flags & ImGuiTableColumnFlags_NoDirectResize_);
 | 
					                        column->Flags |= (next_column->Flags & ImGuiTableColumnFlags_NoDirectResize_);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // [Resize Rule 1] The right-most active column is not resizable if there is at least one Stretch column (see comments in TableResizeColumn().)
 | 
					        // [Resize Rule 1] The right-most active column is not resizable if there is at least one Stretch column
 | 
				
			||||||
 | 
					        // (see comments in TableResizeColumn().)
 | 
				
			||||||
        if (column->NextActiveColumn == -1 && table->LeftMostStretchedColumnDisplayOrder != -1)
 | 
					        if (column->NextActiveColumn == -1 && table->LeftMostStretchedColumnDisplayOrder != -1)
 | 
				
			||||||
            column->Flags |= ImGuiTableColumnFlags_NoDirectResize_;
 | 
					            column->Flags |= ImGuiTableColumnFlags_NoDirectResize_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -675,8 +697,9 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
    else
 | 
					    else
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Redistribute remainder width due to rounding (remainder width is < 1.0f * number of Stretch column)
 | 
					    // Redistribute remainder width due to rounding (remainder width is < 1.0f * number of Stretch column).
 | 
				
			||||||
    // Using right-to-left distribution (more likely to match resizing cursor), could be adjusted depending where the mouse cursor is and/or relative weights.
 | 
					    // Using right-to-left distribution (more likely to match resizing cursor), could be adjusted depending where
 | 
				
			||||||
 | 
					    // the mouse cursor is and/or relative weights.
 | 
				
			||||||
    // FIXME-TABLE: May be simpler to store floating width and floor final positions only
 | 
					    // FIXME-TABLE: May be simpler to store floating width and floor final positions only
 | 
				
			||||||
    // FIXME-TABLE: Make it optional? User might prefer to preserve pixel perfect same size?
 | 
					    // FIXME-TABLE: Make it optional? User might prefer to preserve pixel perfect same size?
 | 
				
			||||||
    if (width_remaining_for_stretched_columns >= 1.0f)
 | 
					    if (width_remaining_for_stretched_columns >= 1.0f)
 | 
				
			||||||
@@ -707,7 +730,7 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
        if (!(table->ActiveMaskByDisplayOrder & ((ImU64)1 << order_n)))
 | 
					        if (!(table->ActiveMaskByDisplayOrder & ((ImU64)1 << order_n)))
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Hidden column: clear a few fields and we are done with it for the remainder of the function.
 | 
					            // Hidden column: clear a few fields and we are done with it for the remainder of the function.
 | 
				
			||||||
            // We set a zero-width clip rect however we pay attention to set Min.y/Max.y properly to not interfere with the clipper.
 | 
					            // We set a zero-width clip rect but set Min.y/Max.y properly to not interfere with the clipper.
 | 
				
			||||||
            column->MinX = column->MaxX = offset_x;
 | 
					            column->MinX = column->MaxX = offset_x;
 | 
				
			||||||
            column->StartXRows = column->StartXHeaders = offset_x;
 | 
					            column->StartXRows = column->StartXHeaders = offset_x;
 | 
				
			||||||
            column->WidthGiven = 0.0f;
 | 
					            column->WidthGiven = 0.0f;
 | 
				
			||||||
@@ -729,8 +752,9 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make sure they are all visible.
 | 
					            // If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make
 | 
				
			||||||
            // Because of this we also know that all of the columns will always fit in table->WorkRect and therefore in table->InnerRect (because ScrollX is off)
 | 
					            // sure they are all visible. Because of this we also know that all of the columns will always fit in
 | 
				
			||||||
 | 
					            // table->WorkRect and therefore in table->InnerRect (because ScrollX is off)
 | 
				
			||||||
            if (!(table->Flags & ImGuiTableFlags_NoKeepColumnsVisible))
 | 
					            if (!(table->Flags & ImGuiTableFlags_NoKeepColumnsVisible))
 | 
				
			||||||
                max_x = table->WorkRect.Max.x - (table->ColumnsActiveCount - (column->IndexWithinActiveSet + 1)) * min_column_width;
 | 
					                max_x = table->WorkRect.Max.x - (table->ColumnsActiveCount - (column->IndexWithinActiveSet + 1)) * min_column_width;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -760,8 +784,9 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
            column->StartXRows = column->StartXHeaders = column->MinX + table->CellPaddingX1;
 | 
					            column->StartXRows = column->StartXHeaders = column->MinX + table->CellPaddingX1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Alignment
 | 
					            // Alignment
 | 
				
			||||||
            // FIXME-TABLE: This align based on the whole column width, not per-cell, and therefore isn't useful in many cases.
 | 
					            // FIXME-TABLE: This align based on the whole column width, not per-cell, and therefore isn't useful in
 | 
				
			||||||
            // (To be able to honor this we might be able to store a log of cells width, per row, for visible rows, but nav/programmatic scroll would have visible artifacts.)
 | 
					            // many cases (to be able to honor this we might be able to store a log of cells width, per row, for
 | 
				
			||||||
 | 
					            // visible rows, but nav/programmatic scroll would have visible artifacts.)
 | 
				
			||||||
            //if (column->Flags & ImGuiTableColumnFlags_AlignRight)
 | 
					            //if (column->Flags & ImGuiTableColumnFlags_AlignRight)
 | 
				
			||||||
            //    column->StartXRows = ImMax(column->StartXRows, column->MaxX - column->ContentWidthRowsUnfrozen);
 | 
					            //    column->StartXRows = ImMax(column->StartXRows, column->MaxX - column->ContentWidthRowsUnfrozen);
 | 
				
			||||||
            //else if (column->Flags & ImGuiTableColumnFlags_AlignCenter)
 | 
					            //else if (column->Flags & ImGuiTableColumnFlags_AlignCenter)
 | 
				
			||||||
@@ -770,7 +795,7 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
            // Reset content width variables
 | 
					            // Reset content width variables
 | 
				
			||||||
            const float initial_max_pos_x = column->MinX + table->CellPaddingX1;
 | 
					            const float initial_max_pos_x = column->MinX + table->CellPaddingX1;
 | 
				
			||||||
            column->ContentMaxPosRowsFrozen = column->ContentMaxPosRowsUnfrozen = initial_max_pos_x;
 | 
					            column->ContentMaxPosRowsFrozen = column->ContentMaxPosRowsUnfrozen = initial_max_pos_x;
 | 
				
			||||||
            column->ContentMaxPosHeadersUsed = column->ContentMaxPosHeadersDesired = initial_max_pos_x;
 | 
					            column->ContentMaxPosHeadersUsed = column->ContentMaxPosHeadersIdeal = initial_max_pos_x;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Don't decrement auto-fit counters until container window got a chance to submit its items
 | 
					        // Don't decrement auto-fit counters until container window got a chance to submit its items
 | 
				
			||||||
@@ -787,7 +812,8 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
        active_n++;
 | 
					        active_n++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag, either because of using _WidthAlwaysAutoResize/_WidthStretch)
 | 
					    // Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag,
 | 
				
			||||||
 | 
					    // either because of using _WidthAlwaysAutoResize/_WidthStretch).
 | 
				
			||||||
    // This will hide the resizing option from the context menu.
 | 
					    // This will hide the resizing option from the context menu.
 | 
				
			||||||
    if (count_resizable == 0 && (table->Flags & ImGuiTableFlags_Resizable))
 | 
					    if (count_resizable == 0 && (table->Flags & ImGuiTableFlags_Resizable))
 | 
				
			||||||
        table->Flags &= ~ImGuiTableFlags_Resizable;
 | 
					        table->Flags &= ~ImGuiTableFlags_Resizable;
 | 
				
			||||||
@@ -828,15 +854,16 @@ void    ImGui::TableUpdateLayout(ImGuiTable* table)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Process interaction on resizing borders. Actual size change will be applied in EndTable()
 | 
					// Process interaction on resizing borders. Actual size change will be applied in EndTable()
 | 
				
			||||||
// - Set table->HoveredColumnBorder with a short delay/timer to reduce feedback noise
 | 
					// - Set table->HoveredColumnBorder with a short delay/timer to reduce feedback noise
 | 
				
			||||||
// - Submit ahead of table contents and header, use ImGuiButtonFlags_AllowItemOverlap to prioritize widgets overlapping the same area.
 | 
					// - Submit ahead of table contents and header, use ImGuiButtonFlags_AllowItemOverlap to prioritize widgets
 | 
				
			||||||
 | 
					//   overlapping the same area.
 | 
				
			||||||
void    ImGui::TableUpdateBorders(ImGuiTable* table)
 | 
					void    ImGui::TableUpdateBorders(ImGuiTable* table)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ImGuiContext& g = *GImGui;
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
    IM_ASSERT(table->Flags & ImGuiTableFlags_Resizable);
 | 
					    IM_ASSERT(table->Flags & ImGuiTableFlags_Resizable);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // At this point OuterRect height may be zero or under actual final height, so we rely on temporal coherency and use
 | 
					    // At this point OuterRect height may be zero or under actual final height, so we rely on temporal coherency and
 | 
				
			||||||
    // the final height from last frame. Because this is only affecting _interaction_ with columns, it is not really problematic.
 | 
					    // use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not
 | 
				
			||||||
    // (whereas the actual visual will be displayed in EndTable() and using the current frame height)
 | 
					    // really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height).
 | 
				
			||||||
    // Actual columns highlight/render will be performed in EndTable() and not be affected.
 | 
					    // Actual columns highlight/render will be performed in EndTable() and not be affected.
 | 
				
			||||||
    const bool borders_full_height = (table->IsUsingHeaders == false) || (table->Flags & ImGuiTableFlags_BordersVFullHeight);
 | 
					    const bool borders_full_height = (table->IsUsingHeaders == false) || (table->Flags & ImGuiTableFlags_BordersVFullHeight);
 | 
				
			||||||
    const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS;
 | 
					    const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS;
 | 
				
			||||||
@@ -895,8 +922,8 @@ void    ImGui::EndTable()
 | 
				
			|||||||
    ImGuiTable* table = g.CurrentTable;
 | 
					    ImGuiTable* table = g.CurrentTable;
 | 
				
			||||||
    IM_ASSERT(table != NULL && "Only call EndTable() if BeginTable() returns true!");
 | 
					    IM_ASSERT(table != NULL && "Only call EndTable() if BeginTable() returns true!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // This assert would be very useful to catch a common error... unfortunately it would probably trigger in some cases,
 | 
					    // This assert would be very useful to catch a common error... unfortunately it would probably trigger in some
 | 
				
			||||||
    // and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border)
 | 
					    // cases, and for consistency user may sometimes output empty tables (and still benefit from e.g. outer border)
 | 
				
			||||||
    //IM_ASSERT(table->IsLayoutLocked && "Table unused: never called TableNextRow(), is that the intent?");
 | 
					    //IM_ASSERT(table->IsLayoutLocked && "Table unused: never called TableNextRow(), is that the intent?");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If the user never got to call TableNextRow() or TableNextCell(), we call layout ourselves to ensure all our
 | 
					    // If the user never got to call TableNextRow() or TableNextCell(), we call layout ourselves to ensure all our
 | 
				
			||||||
@@ -942,7 +969,7 @@ void    ImGui::EndTable()
 | 
				
			|||||||
        column->ContentWidthRowsFrozen = (ImS16)ImMax(0.0f, column->ContentMaxPosRowsFrozen - ref_x_rows);
 | 
					        column->ContentWidthRowsFrozen = (ImS16)ImMax(0.0f, column->ContentMaxPosRowsFrozen - ref_x_rows);
 | 
				
			||||||
        column->ContentWidthRowsUnfrozen = (ImS16)ImMax(0.0f, column->ContentMaxPosRowsUnfrozen - 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->ContentWidthHeadersUsed = (ImS16)ImMax(0.0f, column->ContentMaxPosHeadersUsed - ref_x_headers);
 | 
				
			||||||
        column->ContentWidthHeadersDesired = (ImS16)ImMax(0.0f, column->ContentMaxPosHeadersDesired - ref_x_headers);
 | 
					        column->ContentWidthHeadersIdeal = (ImS16)ImMax(0.0f, column->ContentMaxPosHeadersIdeal - ref_x_headers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (table->ActiveMaskByIndex & ((ImU64)1 << column_n))
 | 
					        if (table->ActiveMaskByIndex & ((ImU64)1 << column_n))
 | 
				
			||||||
            max_pos_x = ImMax(max_pos_x, column->MaxX);
 | 
					            max_pos_x = ImMax(max_pos_x, column->MaxX);
 | 
				
			||||||
@@ -1084,9 +1111,9 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
 | 
				
			|||||||
    if (table->Flags & ImGuiTableFlags_BordersOuter)
 | 
					    if (table->Flags & ImGuiTableFlags_BordersOuter)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Display outer border offset by 1 which is a simple way to display it without adding an extra draw call
 | 
					        // Display outer border offset by 1 which is a simple way to display it without adding an extra draw call
 | 
				
			||||||
        // (Without the offset, in outer_window it would be rendered behind cells, because child windows are above their parent.
 | 
					        // (Without the offset, in outer_window it would be rendered behind cells, because child windows are above their
 | 
				
			||||||
        // In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part of it in inner window,
 | 
					        // parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part
 | 
				
			||||||
        // and the part that's over scrollbars in the outer window..)
 | 
					        // of it in inner window, and the part that's over scrollbars in the outer window..)
 | 
				
			||||||
        // Either solution currently won't allow us to use a larger border size: the border would clipped.
 | 
					        // Either solution currently won't allow us to use a larger border size: the border would clipped.
 | 
				
			||||||
        ImRect outer_border = table->OuterRect;
 | 
					        ImRect outer_border = table->OuterRect;
 | 
				
			||||||
        const ImU32 outer_col = table->BorderColorStrong;
 | 
					        const ImU32 outer_col = table->BorderColorStrong;
 | 
				
			||||||
@@ -1193,8 +1220,8 @@ void ImGui::TableSetColumnWidth(ImGuiTable* table, ImGuiTableColumn* column_0, f
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (column_0->Flags & ImGuiTableColumnFlags_WidthFixed)
 | 
					    if (column_0->Flags & ImGuiTableColumnFlags_WidthFixed)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // [Resize Rule 3] If we are are followed by a fixed column and we have a Stretch column before, we need to
 | 
					        // [Resize Rule 3] If we are are followed by a fixed column and we have a Stretch column before, we need to ensure
 | 
				
			||||||
        // ensure that our left border won't move, which we can do by making sure column_a/column_b resizes cancels each others.
 | 
					        // that our left border won't move, which we can do by making sure column_a/column_b resizes cancels each others.
 | 
				
			||||||
        if (column_1 && (column_1->Flags & ImGuiTableColumnFlags_WidthFixed))
 | 
					        if (column_1 && (column_1->Flags & ImGuiTableColumnFlags_WidthFixed))
 | 
				
			||||||
            if (table->LeftMostStretchedColumnDisplayOrder != -1 && table->LeftMostStretchedColumnDisplayOrder < column_0->DisplayOrder)
 | 
					            if (table->LeftMostStretchedColumnDisplayOrder != -1 && table->LeftMostStretchedColumnDisplayOrder < column_0->DisplayOrder)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@@ -1240,12 +1267,15 @@ void ImGui::TableSetColumnWidth(ImGuiTable* table, ImGuiTableColumn* column_0, f
 | 
				
			|||||||
// Each column itself can use 1 channel (row freeze disabled) or 2 channels (row freeze enabled).
 | 
					// Each column itself can use 1 channel (row freeze disabled) or 2 channels (row freeze enabled).
 | 
				
			||||||
// When the contents of a column didn't stray off its limit, we move its channels into the corresponding group
 | 
					// When the contents of a column didn't stray off its limit, we move its channels into the corresponding group
 | 
				
			||||||
// based on its position (within frozen rows/columns groups or not).
 | 
					// based on its position (within frozen rows/columns groups or not).
 | 
				
			||||||
// At the end of the operation our 1-4 groups will each have a ImDrawCmd using the same ClipRect, and they will be merged by the DrawSplitter.Merge() call.
 | 
					// At the end of the operation our 1-4 groups will each have a ImDrawCmd using the same ClipRect, and they will be
 | 
				
			||||||
 | 
					// merged by the DrawSplitter.Merge() call.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// Column channels will not be merged into one of the 1-4 groups in the following cases:
 | 
					// Column channels will not be merged into one of the 1-4 groups in the following cases:
 | 
				
			||||||
// - The contents stray off its clipping rectangle (we only compare the MaxX value, not the MinX value).
 | 
					// - The contents stray off its clipping rectangle (we only compare the MaxX value, not the MinX value).
 | 
				
			||||||
//   Direct ImDrawList calls won't be taken into account by default, if you use them make sure the ImGui:: bounds matches, by e.g. calling SetCursorScreenPos().
 | 
					//   Direct ImDrawList calls won't be taken into account by default, if you use them make sure the ImGui:: bounds
 | 
				
			||||||
// - The channel uses more than one draw command itself. We drop all our merging stuff here.. we could do better but it's going to be rare.
 | 
					//   matches, by e.g. calling SetCursorScreenPos().
 | 
				
			||||||
 | 
					// - The channel uses more than one draw command itself. We drop all our merging stuff here.. we could do better
 | 
				
			||||||
 | 
					//   but it's going to be rare.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// This function is particularly tricky to understand.. take a breath.
 | 
					// This function is particularly tricky to understand.. take a breath.
 | 
				
			||||||
void    ImGui::TableDrawMergeChannels(ImGuiTable* table)
 | 
					void    ImGui::TableDrawMergeChannels(ImGuiTable* table)
 | 
				
			||||||
@@ -1308,13 +1338,13 @@ void    ImGui::TableDrawMergeChannels(ImGuiTable* table)
 | 
				
			|||||||
            merge_group->ClipRect.Add(src_channel->_CmdBuffer[0].ClipRect);
 | 
					            merge_group->ClipRect.Add(src_channel->_CmdBuffer[0].ClipRect);
 | 
				
			||||||
            merge_group_mask |= (1 << merge_group_dst_n);
 | 
					            merge_group_mask |= (1 << merge_group_dst_n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // If we end with a single group and hosted by the outer window, we'll attempt to merge our draw command with
 | 
					            // If we end with a single group and hosted by the outer window, we'll attempt to merge our draw command
 | 
				
			||||||
            // the existing outer window command. But we can only do so if our columns all fit within the expected clip rect,
 | 
					            // with the existing outer window command. But we can only do so if our columns all fit within the expected
 | 
				
			||||||
            // otherwise clipping will be incorrect when ScrollX is disabled.
 | 
					            // clip rect, otherwise clipping will be incorrect when ScrollX is disabled.
 | 
				
			||||||
            // FIXME-TABLE FIXME-WORKRECT: We are wasting a merge opportunity on tables without scrolling if column don't fit within host clip rect, solely because of the half-padding difference between window->WorkRect and window->InnerClipRect
 | 
					            // FIXME-TABLE FIXME-WORKRECT: We are wasting a merge opportunity on tables without scrolling if column don't fit within host clip rect, solely because of the half-padding difference between window->WorkRect and window->InnerClipRect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // 2019/10/22: (1) This is breaking table_2_draw_calls but I cannot seem to repro what it is attempting to fix...
 | 
					            // 2019/10/22: (1) This is breaking table_2_draw_calls but I cannot seem to repro what it is attempting to
 | 
				
			||||||
            // cf git fce2e8dc "Fixed issue with clipping when outerwindow==innerwindow / support ScrollH without ScrollV."
 | 
					            // fix... cf git fce2e8dc "Fixed issue with clipping when outerwindow==innerwindow / support ScrollH without ScrollV."
 | 
				
			||||||
            // 2019/10/22: (2) Clamping code in TableUpdateLayout() seemingly made this not necessary...
 | 
					            // 2019/10/22: (2) Clamping code in TableUpdateLayout() seemingly made this not necessary...
 | 
				
			||||||
#if 0
 | 
					#if 0
 | 
				
			||||||
            if (column->MinX < table->InnerClipRect.Min.x || column->MaxX > table->InnerClipRect.Max.x)
 | 
					            if (column->MinX < table->InnerClipRect.Min.x || column->MaxX > table->InnerClipRect.Max.x)
 | 
				
			||||||
@@ -1322,7 +1352,8 @@ void    ImGui::TableDrawMergeChannels(ImGuiTable* table)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Invalidate current draw channel (we don't clear DrawChannelBeforeRowFreeze/DrawChannelAfterRowFreeze solely to facilitate debugging)
 | 
					        // Invalidate current draw channel
 | 
				
			||||||
 | 
					        // (we don't clear DrawChannelBeforeRowFreeze/DrawChannelAfterRowFreeze solely to facilitate debugging)
 | 
				
			||||||
        column->DrawChannelCurrent = -1;
 | 
					        column->DrawChannelCurrent = -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1402,8 +1433,9 @@ void    ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags,
 | 
				
			|||||||
    ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount];
 | 
					    ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount];
 | 
				
			||||||
    table->DeclColumnsCount++;
 | 
					    table->DeclColumnsCount++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // When passing a width automatically enforce WidthFixed policy (vs TableFixColumnFlags would default to WidthAlwaysAutoResize)
 | 
					    // When passing a width automatically enforce WidthFixed policy
 | 
				
			||||||
    // (we write down to FlagsIn which is a little misleading, another solution would be to pass init_width_or_weight to TableFixColumnFlags)
 | 
					    // (vs TableFixColumnFlags would default to WidthAlwaysAutoResize)
 | 
				
			||||||
 | 
					    // (we write to FlagsIn which is a little misleading, another solution would be to pass init_width_or_weight to TableFixColumnFlags)
 | 
				
			||||||
    if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0)
 | 
					    if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0)
 | 
				
			||||||
        if ((table->Flags & ImGuiTableFlags_SizingPolicyFixedX) && (init_width_or_weight > 0.0f))
 | 
					        if ((table->Flags & ImGuiTableFlags_SizingPolicyFixedX) && (init_width_or_weight > 0.0f))
 | 
				
			||||||
            flags |= ImGuiTableColumnFlags_WidthFixed;
 | 
					            flags |= ImGuiTableColumnFlags_WidthFixed;
 | 
				
			||||||
@@ -1521,8 +1553,8 @@ void    ImGui::TableEndRow(ImGuiTable* table)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    TableEndCell(table);
 | 
					    TableEndCell(table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Position cursor at the bottom of our row so it can be used for e.g. clipping calculation.
 | 
					    // Position cursor at the bottom of our row so it can be used for e.g. clipping calculation. However it is
 | 
				
			||||||
    // However it is likely that the next call to TableBeginCell() will reposition the cursor to take account of vertical padding.
 | 
					    // likely that the next call to TableBeginCell() will reposition the cursor to take account of vertical padding.
 | 
				
			||||||
    window->DC.CursorPos.y = table->RowPosY2;
 | 
					    window->DC.CursorPos.y = table->RowPosY2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Row background fill
 | 
					    // Row background fill
 | 
				
			||||||
@@ -1588,7 +1620,8 @@ void    ImGui::TableEndRow(ImGuiTable* table)
 | 
				
			|||||||
            window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong);
 | 
					            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)
 | 
					    // 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.
 | 
					    // 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)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        IM_ASSERT(table->IsFreezeRowsPassed == false);
 | 
					        IM_ASSERT(table->IsFreezeRowsPassed == false);
 | 
				
			||||||
@@ -1767,16 +1800,16 @@ ImRect  ImGui::TableGetCellRect()
 | 
				
			|||||||
    return ImRect(column->MinX, table->RowPosY1, column->MaxX, table->RowPosY2);
 | 
					    return ImRect(column->MinX, table->RowPosY1, column->MaxX, table->RowPosY2);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char* ImGui::TableGetColumnName(ImGuiTable* table, int column_n)
 | 
					const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ImGuiTableColumn* column = &table->Columns[column_n];
 | 
					    const ImGuiTableColumn* column = &table->Columns[column_n];
 | 
				
			||||||
    if (column->NameOffset == -1)
 | 
					    if (column->NameOffset == -1)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    return &table->ColumnsNames.Buf[column->NameOffset];
 | 
					    return &table->ColumnsNames.Buf[column->NameOffset];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Return the resizing ID for the right-side of the given column.
 | 
					// Return the resizing ID for the right-side of the given column.
 | 
				
			||||||
ImGuiID ImGui::TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no)
 | 
					ImGuiID ImGui::TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    IM_ASSERT(column_n < table->ColumnsCount);
 | 
					    IM_ASSERT(column_n < table->ColumnsCount);
 | 
				
			||||||
    ImGuiID id = table->ID + (instance_no * table->ColumnsCount) + column_n;
 | 
					    ImGuiID id = table->ID + (instance_no * table->ColumnsCount) + column_n;
 | 
				
			||||||
@@ -1880,8 +1913,8 @@ void    ImGui::TableDrawContextMenu(ImGuiTable* table, int selected_column_n)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
 | 
					// This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
 | 
				
			||||||
// The intent is that advanced users willing to create customized headers would not need to use this helper and may create their own.
 | 
					// The intent is that advanced users willing to create customized headers would not need to use this helper and may
 | 
				
			||||||
// However presently this function uses too many internal structures/calls.
 | 
					// create their own. However presently this function uses too many internal structures/calls.
 | 
				
			||||||
void    ImGui::TableAutoHeaders()
 | 
					void    ImGui::TableAutoHeaders()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ImGuiContext& g = *GImGui;
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
@@ -1964,7 +1997,7 @@ void    ImGui::TableAutoHeaders()
 | 
				
			|||||||
            window->DC.CursorPos.y -= g.Style.ItemSpacing.y;
 | 
					            window->DC.CursorPos.y -= g.Style.ItemSpacing.y;
 | 
				
			||||||
            window->DC.CursorMaxPos = backup_cursor_max_pos;    // Don't feed back into the width of the Header row
 | 
					            window->DC.CursorMaxPos = backup_cursor_max_pos;    // Don't feed back into the width of the Header row
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
 | 
					            // We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden.
 | 
				
			||||||
            if (IsMouseReleased(1) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
 | 
					            if (IsMouseReleased(1) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
 | 
				
			||||||
                open_context_popup = -1;
 | 
					                open_context_popup = -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -2024,7 +2057,8 @@ void    ImGui::TableHeader(const char* label)
 | 
				
			|||||||
    // FIXME-TABLE: Fix when padding are disabled.
 | 
					    // FIXME-TABLE: Fix when padding are disabled.
 | 
				
			||||||
    //window->DC.CursorPos.x = column->MinX + table->CellPadding.x;
 | 
					    //window->DC.CursorPos.x = column->MinX + table->CellPadding.x;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Keep header highlighted when context menu is open. (FIXME-TABLE: however we cannot assume the ID of said popup if it has been created by the user...)
 | 
					    // Keep header highlighted when context menu is open.
 | 
				
			||||||
 | 
					    // (FIXME-TABLE: however we cannot assume the ID of said popup if it has been created by the user...)
 | 
				
			||||||
    const bool selected = (table->IsContextPopupOpen && table->ContextPopupColumn == column_n && table->InstanceInteracted == table->InstanceCurrent);
 | 
					    const bool selected = (table->IsContextPopupOpen && table->ContextPopupColumn == column_n && table->InstanceInteracted == table->InstanceCurrent);
 | 
				
			||||||
    const bool pressed = Selectable("", selected, ImGuiSelectableFlags_DrawHoveredWhenHeld | ImGuiSelectableFlags_DontClosePopups, ImVec2(0.0f, label_height));
 | 
					    const bool pressed = Selectable("", selected, ImGuiSelectableFlags_DrawHoveredWhenHeld | ImGuiSelectableFlags_DontClosePopups, ImVec2(0.0f, label_height));
 | 
				
			||||||
    const bool held = IsItemActive();
 | 
					    const bool held = IsItemActive();
 | 
				
			||||||
@@ -2091,16 +2125,17 @@ void    ImGui::TableHeader(const char* label)
 | 
				
			|||||||
            TableSortSpecsClickColumn(table, column, g.IO.KeyShift);
 | 
					            TableSortSpecsClickColumn(table, column, g.IO.KeyShift);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Render clipped label
 | 
					    // Render clipped label. Clipping here ensure that in the majority of situations, all our header cells will
 | 
				
			||||||
    // Clipping here ensure that in the majority of situations, all our header cells will be merged into a single draw call.
 | 
					    // be merged into a single draw call.
 | 
				
			||||||
    //window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE);
 | 
					    //window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE);
 | 
				
			||||||
    RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size);
 | 
					    RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considering for merging.
 | 
					    // We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considering
 | 
				
			||||||
 | 
					    // for merging.
 | 
				
			||||||
    // FIXME-TABLE: Clarify policies of how label width and potential decorations (arrows) fit into auto-resize of the column
 | 
					    // FIXME-TABLE: Clarify policies of how label width and potential decorations (arrows) fit into auto-resize of the column
 | 
				
			||||||
    float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow;
 | 
					    float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow;
 | 
				
			||||||
    column->ContentMaxPosHeadersUsed = ImMax(column->ContentMaxPosHeadersUsed, work_r.Max.x);// ImMin(max_pos_x, work_r.Max.x));
 | 
					    column->ContentMaxPosHeadersUsed = ImMax(column->ContentMaxPosHeadersUsed, work_r.Max.x);// ImMin(max_pos_x, work_r.Max.x));
 | 
				
			||||||
    column->ContentMaxPosHeadersDesired = ImMax(column->ContentMaxPosHeadersDesired, max_pos_x);
 | 
					    column->ContentMaxPosHeadersIdeal = ImMax(column->ContentMaxPosHeadersIdeal, max_pos_x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PopID();
 | 
					    PopID();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -2144,7 +2179,8 @@ void ImGui::TableSortSpecsClickColumn(ImGuiTable* table, ImGuiTableColumn* click
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Return NULL if no sort specs (most often when ImGuiTableFlags_Sortable is not set)
 | 
					// Return NULL if no sort specs (most often when ImGuiTableFlags_Sortable is not set)
 | 
				
			||||||
// You can sort your data again when 'SpecsChanged == true'. It will be true with sorting specs have changed since last call, or the first time.
 | 
					// You can sort your data again when 'SpecsChanged == true'. It will be true with sorting specs have changed since
 | 
				
			||||||
 | 
					// last call, or the first time.
 | 
				
			||||||
// Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()!
 | 
					// Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()!
 | 
				
			||||||
const ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
 | 
					const ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -2292,7 +2328,7 @@ static ImGuiTableSettings* FindTableSettingsByID(ImGuiID id)
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ImGuiTableSettings* ImGui::TableFindSettings(ImGuiTable* table)
 | 
					ImGuiTableSettings* ImGui::TableFindSettings(const ImGuiTable* table)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (table->SettingsOffset == -1)
 | 
					    if (table->SettingsOffset == -1)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
@@ -2438,7 +2474,8 @@ void    ImGui::TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHan
 | 
				
			|||||||
        if (settings->ID == 0) // Skip ditched settings
 | 
					        if (settings->ID == 0) // Skip ditched settings
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TableSaveSettings() may clear some of those flags when we establish that the data can be stripped (e.g. Order was unchanged)
 | 
					        // TableSaveSettings() may clear some of those flags when we establish that the data can be stripped
 | 
				
			||||||
 | 
					        // (e.g. Order was unchanged)
 | 
				
			||||||
        const bool save_size    = (settings->SaveFlags & ImGuiTableFlags_Resizable) != 0;
 | 
					        const bool save_size    = (settings->SaveFlags & ImGuiTableFlags_Resizable) != 0;
 | 
				
			||||||
        const bool save_visible = (settings->SaveFlags & ImGuiTableFlags_Hideable) != 0;
 | 
					        const bool save_visible = (settings->SaveFlags & ImGuiTableFlags_Hideable) != 0;
 | 
				
			||||||
        const bool save_order   = (settings->SaveFlags & ImGuiTableFlags_Reorderable) != 0;
 | 
					        const bool save_order   = (settings->SaveFlags & ImGuiTableFlags_Reorderable) != 0;
 | 
				
			||||||
@@ -2473,6 +2510,7 @@ void    ImGui::TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHan
 | 
				
			|||||||
//-------------------------------------------------------------------------
 | 
					//-------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef IMGUI_DISABLE_METRICS_WINDOW
 | 
					#ifndef IMGUI_DISABLE_METRICS_WINDOW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ImGui::DebugNodeTable(ImGuiTable* table)
 | 
					void ImGui::DebugNodeTable(ImGuiTable* table)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char buf[256];
 | 
					    char buf[256];
 | 
				
			||||||
@@ -2482,33 +2520,33 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
 | 
				
			|||||||
    bool open = TreeNode(table, "%s", buf);
 | 
					    bool open = TreeNode(table, "%s", buf);
 | 
				
			||||||
    if (IsItemHovered())
 | 
					    if (IsItemHovered())
 | 
				
			||||||
        GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
 | 
					        GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
 | 
				
			||||||
    if (open)
 | 
					    if (!open)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    BulletText("OuterWidth: %.1f, InnerWidth: %.1f%s, IdealWidth: %.1f", table->OuterRect.GetWidth(), table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "", table->IdealTotalWidth);
 | 
				
			||||||
 | 
					    for (int n = 0; n < table->ColumnsCount; n++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        for (int n = 0; n < table->ColumnsCount; n++)
 | 
					        ImGuiTableColumn* column = &table->Columns[n];
 | 
				
			||||||
        {
 | 
					        const char* name = TableGetColumnName(table, n);
 | 
				
			||||||
            ImGuiTableColumn* column = &table->Columns[n];
 | 
					        BulletText("Column %d order %d name '%s': +%.1f to +%.1f\n"
 | 
				
			||||||
            const char* name = TableGetColumnName(table, n);
 | 
					            "Active: %d, Clipped: %d, DrawChannels: %d,%d\n"
 | 
				
			||||||
            BulletText("Column %d order %d name '%s': +%.1f to +%.1f\n"
 | 
					            "WidthGiven/Requested: %.1f/%.1f, Weight: %.2f\n"
 | 
				
			||||||
                "Active: %d, Clipped: %d, DrawChannels: %d,%d\n"
 | 
					            "ContentWidth: RowsFrozen %d, RowsUnfrozen %d, HeadersUsed/Ideal %d/%d\n"
 | 
				
			||||||
                "WidthGiven/Requested: %.1f/%.1f, Weight: %.2f\n"
 | 
					            "SortOrder: %d, SortDir: %s\n"
 | 
				
			||||||
                "ContentWidth: RowsFrozen %d, RowsUnfrozen %d, HeadersUsed/Desired %d/%d\n"
 | 
					            "UserID: 0x%08X, Flags: 0x%04X: %s%s%s%s..",
 | 
				
			||||||
                "SortOrder: %d, SortDir: %s\n"
 | 
					            n, column->DisplayOrder, name ? name : "NULL", column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x,
 | 
				
			||||||
                "UserID: 0x%08X, Flags: 0x%04X: %s%s%s%s..",
 | 
					            column->IsActive, column->IsClipped, column->DrawChannelRowsBeforeFreeze, column->DrawChannelRowsAfterFreeze,
 | 
				
			||||||
                n, column->DisplayOrder, name ? name : "NULL", column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x,
 | 
					            column->WidthGiven, column->WidthRequested, column->ResizeWeight,
 | 
				
			||||||
                column->IsActive, column->IsClipped, column->DrawChannelRowsBeforeFreeze, column->DrawChannelRowsAfterFreeze,
 | 
					            column->ContentWidthRowsFrozen, column->ContentWidthRowsUnfrozen, column->ContentWidthHeadersUsed, column->ContentWidthHeadersIdeal,
 | 
				
			||||||
                column->WidthGiven, column->WidthRequested, column->ResizeWeight,
 | 
					            column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? "Ascending" : (column->SortDirection == ImGuiSortDirection_Descending) ? "Descending" : "None",
 | 
				
			||||||
                column->ContentWidthRowsFrozen, column->ContentWidthRowsUnfrozen, column->ContentWidthHeadersUsed, column->ContentWidthHeadersDesired,
 | 
					            column->UserID, column->Flags,
 | 
				
			||||||
                column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? "Ascending" : (column->SortDirection == ImGuiSortDirection_Descending) ? "Descending" : "None",
 | 
					            (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "",
 | 
				
			||||||
                column->UserID, column->Flags,
 | 
					            (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "",
 | 
				
			||||||
                (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "",
 | 
					            (column->Flags & ImGuiTableColumnFlags_WidthAlwaysAutoResize) ? "WidthAlwaysAutoResize " : "",
 | 
				
			||||||
                (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "",
 | 
					            (column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : "");
 | 
				
			||||||
                (column->Flags & ImGuiTableColumnFlags_WidthAlwaysAutoResize) ? "WidthAlwaysAutoResize " : "",
 | 
					 | 
				
			||||||
                (column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : "");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (ImGuiTableSettings* settings = TableFindSettings(table))
 | 
					 | 
				
			||||||
            DebugNodeTableSettings(settings);
 | 
					 | 
				
			||||||
        TreePop();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (ImGuiTableSettings* settings = TableFindSettings(table))
 | 
				
			||||||
 | 
					        DebugNodeTableSettings(settings);
 | 
				
			||||||
 | 
					    TreePop();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ImGui::DebugNodeTableSettings(ImGuiTableSettings* settings)
 | 
					void ImGui::DebugNodeTableSettings(ImGuiTableSettings* settings)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user