Tables: support internal TableResetSettings(), clarify lifetime, fixed missing auto-fit on column unhidden after first run, fixed resize assert when changing column sizing policy to stretch mid-frame (before of -1.0f weight)
diff --git a/imgui.cpp b/imgui.cpp
index 98e9d57..57e2a72 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -11086,8 +11086,6 @@
 void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImGuiWindow*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}
 void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {}
 void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {}
-void ImGui::DebugNodeTable(ImGuiTable*) {}
-void ImGui::DebugNodeTableSettings(ImGuiTableSettings*) {}
 void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {}
 void ImGui::DebugNodeWindowSettings(ImGuiWindowSettings*) {}
 void ImGui::DebugNodeWindowsList(ImVector<ImGuiWindow*>*, const char*) {}
diff --git a/imgui_internal.h b/imgui_internal.h
index 439701f..ac84a27 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1936,6 +1936,7 @@
     bool                    IsVisibleY;
     bool                    IsRequestOutput;                // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not.
     bool                    IsSkipItems;                    // Do we want item submissions to this column to be completely ignored (no layout will happen).
+    bool                    IsPreserveWidthAuto;
     ImS8                    NavLayerCurrent;                // ImGuiNavLayer in 1 byte
     ImS8                    SortDirection;                  // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
     ImU8                    AutoFitQueue;                   // Queue of 8 values for the next 8 frames to request auto-fit
@@ -1946,7 +1947,6 @@
         memset(this, 0, sizeof(*this));
         StretchWeight = WidthRequest = -1.0f;
         NameOffset = -1;
-        IsEnabled = IsEnabledNextFrame = true;
         DisplayOrder = IndexWithinEnabledSet = -1;
         PrevEnabledColumn = NextEnabledColumn = -1;
         SortOrder = -1;
@@ -2062,6 +2062,7 @@
     bool                        IsSettingsRequestLoad;
     bool                        IsSettingsDirty;            // Set when table settings have changed and needs to be reported into ImGuiTableSetttings data.
     bool                        IsDefaultDisplayOrder;      // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
+    bool                        IsResetAllRequest;
     bool                        IsResetDisplayOrderRequest;
     bool                        IsUnfrozen;                 // Set when we got past the frozen row.
     bool                        MemoryCompacted;
@@ -2319,11 +2320,11 @@
     // Tables: Settings
     IMGUI_API void                  TableLoadSettings(ImGuiTable* table);
     IMGUI_API void                  TableSaveSettings(ImGuiTable* table);
+    IMGUI_API void                  TableResetSettings(ImGuiTable* table);
     IMGUI_API ImGuiTableSettings*   TableGetBoundSettings(ImGuiTable* table);
     IMGUI_API void                  TableSettingsInstallHandler(ImGuiContext* context);
     IMGUI_API ImGuiTableSettings*   TableSettingsCreate(ImGuiID id, int columns_count);
     IMGUI_API ImGuiTableSettings*   TableSettingsFindByID(ImGuiID id);
-    IMGUI_API void                  TableSettingsClearByID(ImGuiID id);
 
     // Tab Bars
     IMGUI_API bool          BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags);
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 50e391b..1274cb6 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -271,7 +271,6 @@
 
     // Acquire storage for the table
     ImGuiTable* table = g.Tables.GetOrAddByKey(id);
-    const bool table_is_new = (table->ID == 0);
     const int instance_no = (table->LastFrameActive != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
     const ImGuiID instance_id = id + instance_no;
     const ImGuiTableFlags table_last_flags = table->Flags;
@@ -288,7 +287,6 @@
     table->LastFrameActive = g.FrameCount;
     table->OuterWindow = table->InnerWindow = outer_window;
     table->ColumnsCount = columns_count;
-    table->IsInitializing = false;
     table->IsLayoutLocked = false;
     table->InnerWidth = inner_width;
     table->OuterRect = outer_rect;
@@ -415,10 +413,25 @@
     if (table->RawData == NULL)
     {
         TableBeginInitMemory(table, columns_count);
-        if (table_is_new)
-            table->IsInitializing = true;
-        table->IsSortSpecsDirty = table->IsSettingsRequestLoad = true;
+        table->IsInitializing = table->IsSettingsRequestLoad = true;
+    }
+    if (table->IsResetAllRequest)
+        TableResetSettings(table);
+    if (table->IsInitializing)
+    {
+        // Initialize for new settings
         table->SettingsOffset = -1;
+        table->IsSortSpecsDirty = true;
+        for (int n = 0; n < columns_count; n++)
+        {
+            ImGuiTableColumn* column = &table->Columns[n];
+            float width_auto = column->WidthAuto;
+            *column = ImGuiTableColumn();
+            column->WidthAuto = width_auto;
+            column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker
+            column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n;
+            column->IsEnabled = column->IsEnabledNextFrame = true;
+        }
     }
 
     // Load settings
@@ -479,19 +492,11 @@
     span_allocator.ReserveBytes(1, columns_count * sizeof(ImGuiTableColumnIdx));
     span_allocator.ReserveBytes(2, columns_count * sizeof(ImGuiTableCellData));
     table->RawData = IM_ALLOC(span_allocator.GetArenaSizeInBytes());
+    memset(table->RawData, 0, span_allocator.GetArenaSizeInBytes());
     span_allocator.SetArenaBasePtr(table->RawData);
     span_allocator.GetSpan(0, &table->Columns);
     span_allocator.GetSpan(1, &table->DisplayOrderToIndex);
     span_allocator.GetSpan(2, &table->RowCellData);
-
-    memset(table->RowCellData.Data, 0, table->RowCellData.size_in_bytes());
-    for (int n = 0; n < columns_count; n++)
-    {
-        ImGuiTableColumn* column = &table->Columns[n];
-        *column = ImGuiTableColumn();
-        column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n;
-        column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames
-    }
 }
 
 // Apply queued resizing/reordering/hiding requests
@@ -513,7 +518,6 @@
         // FIXME-TABLE: Would be nice to redistribute available stretch space accordingly to other weights, instead of giving it all to siblings.
         if (table->AutoFitSingleStretchColumn != -1)
         {
-            table->Columns[table->AutoFitSingleStretchColumn].AutoFitQueue = 0x00;
             TableSetColumnWidth(table->AutoFitSingleStretchColumn, table->Columns[table->AutoFitSingleStretchColumn].WidthAuto);
             table->AutoFitSingleStretchColumn = -1;
         }
@@ -635,6 +639,15 @@
         }
         if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_MultiSortable))
             table->IsSortSpecsDirty = true;
+
+        bool start_auto_fit = false;
+        if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize))
+            start_auto_fit = column->WidthRequest < 0.0f;
+        else
+            start_auto_fit = column->StretchWeight < 0.0f;
+        if (start_auto_fit)
+            column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames
+
         if (column->AutoFitQueue != 0x00)
             want_column_auto_fit = true;
 
@@ -698,6 +711,7 @@
 
         // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping)
         // Combine width from regular rows + width from headers unless requested not to.
+        if (!column->IsPreserveWidthAuto)
         {
             const float content_width_body = (float)ImMax(column->ContentMaxXFrozen, column->ContentMaxXUnfrozen) - column->WorkMinX;
             const float content_width_headers = (float)column->ContentMaxXHeadersIdeal - column->WorkMinX;
@@ -708,11 +722,12 @@
 
             // Non-resizable columns also submit their requested width
             if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f)
-                if (!(table->Flags & ImGuiTableFlags_Resizable) || !(column->Flags & ImGuiTableColumnFlags_NoResize))
+                if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize))
                     width_auto = ImMax(width_auto, column->InitStretchWeightOrWidth);
 
             column->WidthAuto = width_auto;
         }
+        column->IsPreserveWidthAuto = false;
 
         if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize))
         {
@@ -734,9 +749,8 @@
         else
         {
             IM_ASSERT(column->Flags & ImGuiTableColumnFlags_WidthStretch);
-            const float default_weight = (column->InitStretchWeightOrWidth > 0.0f) ? column->InitStretchWeightOrWidth : 1.0f;
-            if (column->AutoFitQueue != 0x00)
-                column->StretchWeight = default_weight;
+            if (column->StretchWeight < 0.0f)
+                column->StretchWeight = 1.0f;
             sum_weights_stretched += column->StretchWeight;
             if (table->LeftMostStretchedColumnDisplayOrder == -1 || table->LeftMostStretchedColumnDisplayOrder > column->DisplayOrder)
                 table->LeftMostStretchedColumnDisplayOrder = column->DisplayOrder;
@@ -1232,6 +1246,7 @@
     // Save settings
     if (table->IsSettingsDirty)
         TableSaveSettings(table);
+    table->IsInitializing = false;
 
     // Clear or restore current table, if any
     IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
@@ -2731,6 +2746,10 @@
         want_separator = true;
     }
 
+    // Reset all (should work but seems unnecessary/noisy to expose?)
+    //if (MenuItem("Reset all"))
+    //    table->IsResetAllRequest = true;
+
     // Sorting
     // (modify TableOpenContextMenu() to add _Sortable flag if enabling this)
 #if 0
@@ -2777,12 +2796,14 @@
 //-------------------------------------------------------------------------
 // [SECTION] Tables: Settings (.ini data)
 //-------------------------------------------------------------------------
+// FIXME: The binding/finding/creating flow are too confusing.
+//-------------------------------------------------------------------------
 // - TableSettingsInit() [Internal]
 // - TableSettingsCalcChunkSize() [Internal]
 // - TableSettingsCreate() [Internal]
 // - TableSettingsFindByID() [Internal]
-// - TableSettingsClearByID() [Internal]
 // - TableGetBoundSettings() [Internal]
+// - TableResetSettings()
 // - TableSaveSettings() [Internal]
 // - TableLoadSettings() [Internal]
 // - TableSettingsHandler_ClearAll() [Internal]
@@ -2835,12 +2856,6 @@
     return NULL;
 }
 
-void ImGui::TableSettingsClearByID(ImGuiID id)
-{
-    if (ImGuiTableSettings* settings = TableSettingsFindByID(id))
-        settings->ID = 0;
-}
-
 // Get settings for a given table, NULL if none
 ImGuiTableSettings* ImGui::TableGetBoundSettings(ImGuiTable* table)
 {
@@ -2856,6 +2871,15 @@
     return NULL;
 }
 
+// Restore initial state of table (with or without saved settings)
+void ImGui::TableResetSettings(ImGuiTable* table)
+{
+    table->IsInitializing = table->IsSettingsDirty = true;
+    table->IsResetAllRequest = false;
+    table->IsSettingsRequestLoad = false;                   // Don't reload from ini
+    table->SettingsLoadedFlags = ImGuiTableFlags_None;      // Mark as nothing loaded so our initialized data becomes authoritative
+}
+
 void ImGui::TableSaveSettings(ImGuiTable* table)
 {
     table->IsSettingsDirty = false;
@@ -3163,6 +3187,7 @@
         GetForegroundDrawList()->AddRect(table->OuterRect.Min, table->OuterRect.Max, IM_COL32(255, 255, 0, 255));
     if (!open)
         return;
+    bool clear_settings = SmallButton("Clear settings");
     BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f)", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight());
     BulletText("ColumnsWidth: %.1f, AutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsTotalWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
     BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX);
@@ -3200,6 +3225,8 @@
     }
     if (ImGuiTableSettings* settings = TableGetBoundSettings(table))
         DebugNodeTableSettings(settings);
+    if (clear_settings)
+        table->IsResetAllRequest = true;
     TreePop();
 }
 
@@ -3221,7 +3248,12 @@
     TreePop();
 }
 
-#endif // #ifndef IMGUI_DISABLE_METRICS_WINDOW
+#else // #ifndef IMGUI_DISABLE_METRICS_WINDOW
+
+void ImGui::DebugNodeTable(ImGuiTable*) {}
+void ImGui::DebugNodeTableSettings(ImGuiTableSettings*) {}
+
+#endif
 
 
 //-------------------------------------------------------------------------