mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	Tables: added ImGuiTableFlags_SortTristate. Renamed ImGuiTableFlags_MultiSortable to ImGuiTableFlags_SortMulti. Removed now unused FlagsIn storage.
This commit is contained in:
		
							
								
								
									
										115
									
								
								imgui_tables.cpp
									
									
									
									
									
								
							
							
						
						
									
										115
									
								
								imgui_tables.cpp
									
									
									
									
									
								
							| @@ -190,10 +190,6 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_w | ||||
|     if ((flags & (ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ColumnsWidthFixed)) == 0) | ||||
|         flags |= (flags & ImGuiTableFlags_ScrollX) ? ImGuiTableFlags_ColumnsWidthFixed : ImGuiTableFlags_ColumnsWidthStretch; | ||||
|  | ||||
|     // Adjust flags: MultiSortable automatically enable Sortable | ||||
|     if (flags & ImGuiTableFlags_MultiSortable) | ||||
|         flags |= ImGuiTableFlags_Sortable; | ||||
|  | ||||
|     // Adjust flags: disable Resizable when using SameWidths (done above enforcing BordersInnerV) | ||||
|     if (flags & ImGuiTableFlags_SameWidths) | ||||
|         flags = (flags & ~ImGuiTableFlags_Resizable) | ImGuiTableFlags_NoKeepColumnsVisible; | ||||
| @@ -562,7 +558,6 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table) | ||||
| } | ||||
|  | ||||
| // Adjust flags: default width mode + stretch columns are not allowed when auto extending | ||||
| // Set 'column->FlagsIn' and 'column->Flags'. | ||||
| static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags flags_in) | ||||
| { | ||||
|     ImGuiTableColumnFlags flags = flags_in; | ||||
| @@ -594,8 +589,23 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I | ||||
|     //IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_AlignMask_)); // Check that only 1 of each set is used. | ||||
|  | ||||
|     // Preserve status flags | ||||
|     column->FlagsIn = flags_in; | ||||
|     column->Flags = flags | (column->Flags & ImGuiTableColumnFlags_StatusMask_); | ||||
|  | ||||
|     // Build an ordered list of available sort directions | ||||
|     column->SortDirectionsAvailCount = column->SortDirectionsAvailMask = column->SortDirectionsAvailList = 0; | ||||
|     if (table->Flags & ImGuiTableFlags_Sortable) | ||||
|     { | ||||
|         int count = 0, mask = 0, list = 0; | ||||
|         if ((flags & ImGuiTableColumnFlags_PreferSortAscending)  != 0 && (flags & ImGuiTableColumnFlags_NoSortAscending)  == 0) { mask |= 1 << ImGuiSortDirection_Ascending;  list |= ImGuiSortDirection_Ascending  << (count << 1); count++; } | ||||
|         if ((flags & ImGuiTableColumnFlags_PreferSortDescending) != 0 && (flags & ImGuiTableColumnFlags_NoSortDescending) == 0) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << (count << 1); count++; } | ||||
|         if ((flags & ImGuiTableColumnFlags_PreferSortAscending)  == 0 && (flags & ImGuiTableColumnFlags_NoSortAscending)  == 0) { mask |= 1 << ImGuiSortDirection_Ascending;  list |= ImGuiSortDirection_Ascending  << (count << 1); count++; } | ||||
|         if ((flags & ImGuiTableColumnFlags_PreferSortDescending) == 0 && (flags & ImGuiTableColumnFlags_NoSortDescending) == 0) { mask |= 1 << ImGuiSortDirection_Descending; list |= ImGuiSortDirection_Descending << (count << 1); count++; } | ||||
|         if ((table->Flags & ImGuiTableFlags_SortTristate) || count == 0) { mask |= 1 << ImGuiSortDirection_None; count++; } | ||||
|         column->SortDirectionsAvailList = (ImU8)list; | ||||
|         column->SortDirectionsAvailMask = (ImU8)mask; | ||||
|         column->SortDirectionsAvailCount = (ImU8)count; | ||||
|         ImGui::TableFixColumnSortDirection(table, column); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Layout columns for the frame. This is in essence the followup to BeginTable(). | ||||
| @@ -644,7 +654,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) | ||||
|             if (!column->IsEnabled && column->SortOrder != -1) | ||||
|                 table->IsSortSpecsDirty = true; | ||||
|         } | ||||
|         if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_MultiSortable)) | ||||
|         if (column->SortOrder > 0 && !(table->Flags & ImGuiTableFlags_SortMulti)) | ||||
|             table->IsSortSpecsDirty = true; | ||||
|  | ||||
|         bool start_auto_fit = false; | ||||
| @@ -662,6 +672,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) | ||||
|         ImU64 display_order_mask = (ImU64)1 << column->DisplayOrder; | ||||
|         if (column->IsEnabled) | ||||
|         { | ||||
|             // Mark as enabled and link to previous/next enabled column | ||||
|             column->PrevEnabledColumn = (ImGuiTableColumnIdx)last_visible_column_idx; | ||||
|             column->NextEnabledColumn = -1; | ||||
|             if (last_visible_column_idx != -1) | ||||
| @@ -678,6 +689,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) | ||||
|         } | ||||
|         IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder); | ||||
|     } | ||||
|     if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) | ||||
|         table->IsSortSpecsDirty = true; | ||||
|     table->RightMostEnabledColumn = (ImGuiTableColumnIdx)last_visible_column_idx; | ||||
|  | ||||
|     // [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible | ||||
| @@ -707,11 +720,6 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) | ||||
|         if ((column->Flags & ImGuiTableColumnFlags_NoResize) == 0) | ||||
|             count_resizable++; | ||||
|  | ||||
|         // We have a unusual edge case where if the user doesn't call TableGetSortSpecs() but has sorting enabled | ||||
|         // or varying sorting flags, we still want the sorting arrows to honor those flags. | ||||
|         if (table->Flags & ImGuiTableFlags_Sortable) | ||||
|             TableFixColumnSortDirection(column); | ||||
|  | ||||
|         // 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) | ||||
| @@ -942,7 +950,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) | ||||
|         // Note that scrolling tables (where inner_window != outer_window) handle Y clipped earlier in BeginTable() so IsVisibleY really only applies to non-scrolling tables. | ||||
|         // FIXME-TABLE: Because InnerClipRect.Max.y is conservatively ==outer_window->ClipRect.Max.y, we never can mark columns _Above_ the scroll line as not IsVisibleY. | ||||
|         // Taking advantage of LastOuterHeight would yield good results there... | ||||
|         // FIXME-TABLE: IsVisible == false is disabled because it effectively means not submitting will reduces contents width which is fed to outer_window->DC.CursorMaxPos.x, | ||||
|         // FIXME-TABLE: Y clipping is disabled because it effectively means not submitting will reduce contents width which is fed to outer_window->DC.CursorMaxPos.x, | ||||
|         // and this may be used (e.g. typically by outer_window using AlwaysAutoResize or outer_window's horizontal scrollbar, but could be something else). | ||||
|         // Possible solution to preserve last known content width for clipped column. Test 'table_reported_size' fails when enabling Y clipping and window is resized small. | ||||
|         column->IsVisibleX = (column->ClipRect.Max.x > column->ClipRect.Min.x); | ||||
| @@ -958,9 +966,6 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) | ||||
|  | ||||
|         // Mark column as SkipItems (ignoring all items/layout) | ||||
|         column->IsSkipItems = !column->IsEnabled || table->HostSkipItems; | ||||
|         //if (!is_visible && (column->Flags & ImGuiTableColumnFlags_AutoCull)) | ||||
|         //    if ((column->AutoFitQueue & 1) == 0 && (column->CannotSkipItemsQueue & 1) == 0) | ||||
|         //        column->IsSkipItems = true; | ||||
|         if (column->IsSkipItems) | ||||
|             IM_ASSERT(!is_visible); | ||||
|  | ||||
| @@ -1177,7 +1182,8 @@ void    ImGui::EndTable() | ||||
| #if 0 | ||||
|     // Strip out dummy channel draw calls | ||||
|     // We have no way to prevent user submitting direct ImDrawList calls into a hidden column (but ImGui:: calls will be clipped out) | ||||
|     // (The problem with this approach is we are effectively making it harder for users watching metrics to spot wasted vertices) | ||||
|     // Pros: remove draw calls which will have no effect. since they'll have zero-size cliprect they may be early out anyway. | ||||
|     // Cons: making it harder for users watching metrics/debugger to spot the wasted vertices. | ||||
|     if (table->DummyDrawChannel != (ImGuiTableColumnIdx)-1) | ||||
|     { | ||||
|         ImDrawChannel* dummy_channel = &table->DrawSplitter._Channels[table->DummyDrawChannel]; | ||||
| @@ -1281,7 +1287,6 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo | ||||
|  | ||||
|     // When passing a width automatically enforce WidthFixed policy | ||||
|     // (vs TableFixColumnFlags would default to WidthAutoResize) | ||||
|     // (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 ((table->Flags & ImGuiTableFlags_ColumnsWidthFixed) && (init_width_or_weight > 0.0f)) | ||||
|             flags |= ImGuiTableColumnFlags_WidthFixed; | ||||
| @@ -1313,7 +1318,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo | ||||
|             column->IsEnabled = column->IsEnabledNextFrame = false; | ||||
|         if (flags & ImGuiTableColumnFlags_DefaultSort && (table->SettingsLoadedFlags & ImGuiTableFlags_Sortable) == 0) | ||||
|         { | ||||
|             column->SortOrder = 0; // Multiple columns using _DefaultSort will be reordered when building the sort specs. | ||||
|             column->SortOrder = 0; // Multiple columns using _DefaultSort will be reassigned unique SortOrder values when building the sort specs. | ||||
|             column->SortDirection = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending); | ||||
|         } | ||||
|     } | ||||
| @@ -2342,6 +2347,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table) | ||||
| //------------------------------------------------------------------------- | ||||
| // - TableGetSortSpecs() | ||||
| // - TableFixColumnSortDirection() [Internal] | ||||
| // - TableGetColumnNextSortDirection() [Internal] | ||||
| // - TableSetColumnSortDirection() [Internal] | ||||
| // - TableSortSpecsSanitize() [Internal] | ||||
| // - TableSortSpecsBuild() [Internal] | ||||
| @@ -2367,22 +2373,39 @@ ImGuiTableSortSpecs* ImGui::TableGetSortSpecs() | ||||
|     if (table->IsSortSpecsDirty) | ||||
|         TableSortSpecsBuild(table); | ||||
|  | ||||
|     return table->SortSpecs.SpecsCount ? &table->SortSpecs : NULL; | ||||
|     return &table->SortSpecs; | ||||
| } | ||||
|  | ||||
| void ImGui::TableFixColumnSortDirection(ImGuiTableColumn* column) | ||||
| static inline ImGuiSortDirection TableGetColumnAvailSortDirection(ImGuiTableColumn* column, int n) | ||||
| { | ||||
|     // Initial sort state | ||||
|     if (column->SortDirection == ImGuiSortDirection_None) | ||||
|         column->SortDirection = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImS8)(ImGuiSortDirection_Ascending); | ||||
|  | ||||
|     // Handle NoSortAscending/NoSortDescending | ||||
|     if (column->SortDirection == ImGuiSortDirection_Ascending && (column->Flags & ImGuiTableColumnFlags_NoSortAscending)) | ||||
|         column->SortDirection = ImGuiSortDirection_Descending; | ||||
|     else if (column->SortDirection == ImGuiSortDirection_Descending && (column->Flags & ImGuiTableColumnFlags_NoSortDescending)) | ||||
|         column->SortDirection = ImGuiSortDirection_Ascending; | ||||
|     IM_ASSERT(n < column->SortDirectionsAvailCount); | ||||
|     return (column->SortDirectionsAvailList >> (n << 1)) & 0x03; | ||||
| } | ||||
|  | ||||
| // Fix sort direction if currently set on a value which is unavailable (e.g. activating NoSortAscending/NoSortDescending) | ||||
| void ImGui::TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column) | ||||
| { | ||||
|     if (column->SortOrder == -1 || (column->SortDirectionsAvailMask & (1 << column->SortDirection)) != 0) | ||||
|         return; | ||||
|     column->SortDirection = (ImU8)TableGetColumnAvailSortDirection(column, 0); | ||||
|     table->IsSortSpecsDirty = true; | ||||
| } | ||||
|  | ||||
| // Calculate next sort direction that would be set after clicking the column | ||||
| // - If the PreferSortDescending flag is set, we will default to a Descending direction on the first click. | ||||
| // - Note that the PreferSortAscending flag is never checked, it is essentially the default and therefore a no-op. | ||||
| IM_STATIC_ASSERT(ImGuiSortDirection_None == 0 && ImGuiSortDirection_Ascending == 1 && ImGuiSortDirection_Descending == 2); | ||||
| ImGuiSortDirection ImGui::TableGetColumnNextSortDirection(ImGuiTableColumn* column) | ||||
| { | ||||
|     IM_ASSERT(column->SortDirectionsAvailCount > 0); | ||||
|     if (column->SortOrder == -1) | ||||
|         return TableGetColumnAvailSortDirection(column, 0); | ||||
|     for (int n = 0; n < 3; n++) | ||||
|         if (column->SortDirection == TableGetColumnAvailSortDirection(column, n)) | ||||
|             return TableGetColumnAvailSortDirection(column, (n + 1) % column->SortDirectionsAvailCount); | ||||
|     IM_ASSERT(0); | ||||
|     return ImGuiSortDirection_None; | ||||
| } | ||||
|  | ||||
| // Note that the NoSortAscending/NoSortDescending flags are processed in TableSortSpecsSanitize(), and they may change/revert | ||||
| // the value of SortDirection. We could technically also do it here but it would be unnecessary and duplicate code. | ||||
| @@ -2391,8 +2414,10 @@ void ImGui::TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_di | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     ImGuiTable* table = g.CurrentTable; | ||||
|  | ||||
|     if (!(table->Flags & ImGuiTableFlags_MultiSortable)) | ||||
|     if (!(table->Flags & ImGuiTableFlags_SortMulti)) | ||||
|         append_to_sort_specs = false; | ||||
|     if (!(table->Flags & ImGuiTableFlags_SortTristate)) | ||||
|         IM_ASSERT(sort_direction != ImGuiSortDirection_None); | ||||
|  | ||||
|     ImGuiTableColumnIdx sort_order_max = 0; | ||||
|     if (append_to_sort_specs) | ||||
| @@ -2400,8 +2425,10 @@ void ImGui::TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_di | ||||
|             sort_order_max = ImMax(sort_order_max, table->Columns[other_column_n].SortOrder); | ||||
|  | ||||
|     ImGuiTableColumn* column = &table->Columns[column_n]; | ||||
|     column->SortDirection = (ImS8)sort_direction; | ||||
|     if (column->SortOrder == -1 || !append_to_sort_specs) | ||||
|     column->SortDirection = (ImU8)sort_direction; | ||||
|     if (column->SortDirection == ImGuiSortDirection_None) | ||||
|         column->SortOrder = -1; | ||||
|     else if (column->SortOrder == -1 || !append_to_sort_specs) | ||||
|         column->SortOrder = append_to_sort_specs ? sort_order_max + 1 : 0; | ||||
|  | ||||
|     for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++) | ||||
| @@ -2409,7 +2436,7 @@ void ImGui::TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_di | ||||
|         ImGuiTableColumn* other_column = &table->Columns[other_column_n]; | ||||
|         if (other_column != column && !append_to_sort_specs) | ||||
|             other_column->SortOrder = -1; | ||||
|         TableFixColumnSortDirection(other_column); | ||||
|         TableFixColumnSortDirection(table, other_column); | ||||
|     } | ||||
|     table->IsSettingsDirty = true; | ||||
|     table->IsSortSpecsDirty = true; | ||||
| @@ -2435,7 +2462,7 @@ void ImGui::TableSortSpecsSanitize(ImGuiTable* table) | ||||
|     } | ||||
|  | ||||
|     const bool need_fix_linearize = ((ImU64)1 << sort_order_count) != (sort_order_mask + 1); | ||||
|     const bool need_fix_single_sort_order = (sort_order_count > 1) && !(table->Flags & ImGuiTableFlags_MultiSortable); | ||||
|     const bool need_fix_single_sort_order = (sort_order_count > 1) && !(table->Flags & ImGuiTableFlags_SortMulti); | ||||
|     if (need_fix_linearize || need_fix_single_sort_order) | ||||
|     { | ||||
|         ImU64 fixed_mask = 0x00; | ||||
| @@ -2465,7 +2492,7 @@ void ImGui::TableSortSpecsSanitize(ImGuiTable* table) | ||||
|     } | ||||
|  | ||||
|     // Fallback default sort order (if no column had the ImGuiTableColumnFlags_DefaultSort flag) | ||||
|     if (sort_order_count == 0) | ||||
|     if (sort_order_count == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) | ||||
|         for (int column_n = 0; column_n < table->ColumnsCount; column_n++) | ||||
|         { | ||||
|             ImGuiTableColumn* column = &table->Columns[column_n]; | ||||
| @@ -2473,7 +2500,7 @@ void ImGui::TableSortSpecsSanitize(ImGuiTable* table) | ||||
|             { | ||||
|                 sort_order_count = 1; | ||||
|                 column->SortOrder = 0; | ||||
|                 TableFixColumnSortDirection(column); | ||||
|                 column->SortDirection = TableGetColumnAvailSortDirection(column, 0); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| @@ -2487,9 +2514,8 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table) | ||||
|     TableSortSpecsSanitize(table); | ||||
|  | ||||
|     // Write output | ||||
|     const bool single_sort_specs = (table->SortSpecsCount <= 1); | ||||
|     table->SortSpecsMulti.resize(single_sort_specs ? 0 : table->SortSpecsCount); | ||||
|     ImGuiTableColumnSortSpecs* sort_specs = single_sort_specs ? &table->SortSpecsSingle : table->SortSpecsMulti.Data; | ||||
|     table->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount); | ||||
|     ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data; | ||||
|     for (int column_n = 0; column_n < table->ColumnsCount; column_n++) | ||||
|     { | ||||
|         ImGuiTableColumn* column = &table->Columns[column_n]; | ||||
| @@ -2688,14 +2714,7 @@ void ImGui::TableHeader(const char* label) | ||||
|         // Handle clicking on column header to adjust Sort Order | ||||
|         if (pressed && table->ReorderColumn != column_n) | ||||
|         { | ||||
|             // Set new sort direction | ||||
|             // - If the PreferSortDescending flag is set, we will default to a Descending direction on the first click. | ||||
|             // - Note that the PreferSortAscending flag is never checked, it is essentially the default and therefore a no-op. | ||||
|             ImGuiSortDirection sort_direction; | ||||
|             if (column->SortOrder == -1) | ||||
|                 sort_direction = (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? ImGuiSortDirection_Descending : ImGuiSortDirection_Ascending; | ||||
|             else | ||||
|                 sort_direction = (column->SortDirection == ImGuiSortDirection_Ascending) ? ImGuiSortDirection_Descending : ImGuiSortDirection_Ascending; | ||||
|             ImGuiSortDirection sort_direction = TableGetColumnNextSortDirection(column); | ||||
|             TableSetColumnSortDirection(column_n, sort_direction, g.IO.KeyShift); | ||||
|         } | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user