mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-10-26 12:27:30 +00:00 
			
		
		
		
	MultiSelect: ImGuiSelectionBasicStorage: simplify by removing compacting code (compacting may be opt-in?).
GetNextSelectedItem() wrapper gives us more flexibility to work on this kind of stuff now.
This commit is contained in:
		
							
								
								
									
										4
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								imgui.h
									
									
									
									
									
								
							| @@ -2835,7 +2835,7 @@ struct ImGuiSelectionBasicStorage | |||||||
| { | { | ||||||
|     // Members |     // Members | ||||||
|     ImGuiStorage    _Storage;       // [Internal] Selection set. Think of this as similar to e.g. std::set<ImGuiID>. Prefer not accessing directly: iterate with GetNextSelectedItem(). |     ImGuiStorage    _Storage;       // [Internal] Selection set. Think of this as similar to e.g. std::set<ImGuiID>. Prefer not accessing directly: iterate with GetNextSelectedItem(). | ||||||
|     int             Size;           // Number of selected items, maintained by this helper. |     int             Size;           // Number of selected items (== number of 1 in the Storage), maintained by this helper. | ||||||
|     void*           UserData;       // User data for use by adapter function                // e.g. selection.UserData = (void*)my_items; |     void*           UserData;       // User data for use by adapter function                // e.g. selection.UserData = (void*)my_items; | ||||||
|     ImGuiID         (*AdapterIndexToStorageId)(ImGuiSelectionBasicStorage* self, int idx);  // e.g. selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { return ((MyItems**)self->UserData)[idx]->ID; }; |     ImGuiID         (*AdapterIndexToStorageId)(ImGuiSelectionBasicStorage* self, int idx);  // e.g. selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { return ((MyItems**)self->UserData)[idx]->ID; }; | ||||||
|  |  | ||||||
| @@ -2849,7 +2849,7 @@ struct ImGuiSelectionBasicStorage | |||||||
|     ImGuiSelectionBasicStorage()                                { Size = 0; UserData = NULL; AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage*, int idx) { return (ImGuiID)idx; }; } |     ImGuiSelectionBasicStorage()                                { Size = 0; UserData = NULL; AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage*, int idx) { return (ImGuiID)idx; }; } | ||||||
|     void                Clear()                                 { _Storage.Data.resize(0); Size = 0; } |     void                Clear()                                 { _Storage.Data.resize(0); Size = 0; } | ||||||
|     void                Swap(ImGuiSelectionBasicStorage& r)     { _Storage.Data.swap(r._Storage.Data); int lhs_size = Size; Size = r.Size; r.Size = lhs_size; } |     void                Swap(ImGuiSelectionBasicStorage& r)     { _Storage.Data.swap(r._Storage.Data); int lhs_size = Size; Size = r.Size; r.Size = lhs_size; } | ||||||
|     IMGUI_API void      SetItemSelected(ImGuiID id, bool selected); |     void                SetItemSelected(ImGuiID id, bool v)     { int* p_int = _Storage.GetIntRef(id, 0); if (v && *p_int == 0) { *p_int = 1; Size++; } else if (!v && *p_int != 0) { *p_int = 0; Size--; } } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Optional helper to apply multi-selection requests to existing randomly accessible storage. | // Optional helper to apply multi-selection requests to existing randomly accessible storage. | ||||||
|   | |||||||
| @@ -7830,63 +7830,34 @@ ImGuiID ImGuiSelectionBasicStorage::GetNextSelectedItem(void** opaque_it) | |||||||
|     if (it == NULL) |     if (it == NULL) | ||||||
|         it = _Storage.Data.Data; |         it = _Storage.Data.Data; | ||||||
|     IM_ASSERT(it >= _Storage.Data.Data && it <= it_end); |     IM_ASSERT(it >= _Storage.Data.Data && it <= it_end); | ||||||
|  |     if (it != it_end) | ||||||
|  |         while (it->val_i == 0 && it < it_end) | ||||||
|  |             it++; | ||||||
|     const bool has_more = (it != it_end); |     const bool has_more = (it != it_end); | ||||||
|     *opaque_it = has_more ? (void**)(it + 1) : (void**)(it); |     *opaque_it = has_more ? (void**)(it + 1) : (void**)(it); | ||||||
|     return has_more ? it->key : 0; |     return has_more ? it->key : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Basic function to update selection (for very large amounts of changes, see what ApplyRequests is doing) |  | ||||||
| void ImGuiSelectionBasicStorage::SetItemSelected(ImGuiID id, bool selected) |  | ||||||
| { |  | ||||||
|     ImGuiStoragePair* it = ImLowerBound(_Storage.Data.Data, _Storage.Data.Data + _Storage.Data.Size, id); |  | ||||||
|     if (selected == (it != _Storage.Data.Data + _Storage.Data.Size) && (it->key == id)) |  | ||||||
|         return; |  | ||||||
|     if (selected) |  | ||||||
|         _Storage.Data.insert(it, ImGuiStoragePair(id, 1)); |  | ||||||
|     else |  | ||||||
|         _Storage.Data.erase(it); |  | ||||||
|     Size = _Storage.Data.Size; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Optimized for batch edits (with same value of 'selected') | // Optimized for batch edits (with same value of 'selected') | ||||||
| static void ImGuiSelectionBasicStorage_BatchSetItemSelected(ImGuiSelectionBasicStorage* selection, ImGuiID id, bool selected, int size_before_amends) | static void ImGuiSelectionBasicStorage_BatchSetItemSelected(ImGuiSelectionBasicStorage* selection, ImGuiID id, bool selected, int size_before_amends) | ||||||
| { | { | ||||||
|     ImGuiStorage* storage = &selection->_Storage; |     ImGuiStorage* storage = &selection->_Storage; | ||||||
|     ImGuiStoragePair* it = ImLowerBound(storage->Data.Data, storage->Data.Data + size_before_amends, id); |     ImGuiStoragePair* it = ImLowerBound(storage->Data.Data, storage->Data.Data + size_before_amends, id); | ||||||
|     if (selected == (it != storage->Data.Data + size_before_amends) && (it->key == id)) |     const bool is_contained = (it != storage->Data.Data + size_before_amends) && (it->key == id); | ||||||
|  |     if (selected == is_contained && it->val_i == 1) | ||||||
|         return; |         return; | ||||||
|     if (selected) |     if (selected && !is_contained) | ||||||
|         storage->Data.push_back(ImGuiStoragePair(id, 1)); // Push unsorted at end of vector, will be sorted in SelectionMultiAmendsFinish() |         storage->Data.push_back(ImGuiStoragePair(id, 1)); // Push unsorted at end of vector, will be sorted in SelectionMultiAmendsFinish() | ||||||
|     else |     else if (is_contained) | ||||||
|         it->val_i = 0; // Clear in-place, will be removed in SelectionMultiAmendsFinish() |         it->val_i = selected ? 1 : 0; // Modify in-place. | ||||||
|     selection->Size += selected ? +1 : -1; |     selection->Size += selected ? +1 : -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void ImGuiSelectionBasicStorage_Compact(ImGuiSelectionBasicStorage* selection) |  | ||||||
| { |  | ||||||
|     ImGuiStorage* storage = &selection->_Storage; |  | ||||||
|     ImGuiStoragePair* p_out = storage->Data.Data; |  | ||||||
|     ImGuiStoragePair* p_end = storage->Data.Data + storage->Data.Size; |  | ||||||
|     for (ImGuiStoragePair* p_in = p_out; p_in < p_end; p_in++) |  | ||||||
|         if (p_in->val_i != 0) |  | ||||||
|         { |  | ||||||
|             if (p_out != p_in) |  | ||||||
|                 *p_out = *p_in; |  | ||||||
|             p_out++; |  | ||||||
|         } |  | ||||||
|     storage->Data.Size = (int)(p_out - storage->Data.Data); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void ImGuiSelectionBasicStorage_BatchFinish(ImGuiSelectionBasicStorage* selection, bool selected, int size_before_amends) | static void ImGuiSelectionBasicStorage_BatchFinish(ImGuiSelectionBasicStorage* selection, bool selected, int size_before_amends) | ||||||
| { | { | ||||||
|     ImGuiStorage* storage = &selection->_Storage; |     ImGuiStorage* storage = &selection->_Storage; | ||||||
|     if (selection->Size == size_before_amends) |     if (selected && selection->Size != size_before_amends) | ||||||
|         return; |  | ||||||
|     if (selected) |  | ||||||
|         storage->BuildSortByKey(); // When done selecting: sort everything |         storage->BuildSortByKey(); // When done selecting: sort everything | ||||||
|     else |  | ||||||
|         ImGuiSelectionBasicStorage_Compact(selection); // When done unselecting: compact by removing all zero values (might be done lazily when iterating selection?) |  | ||||||
|     IM_ASSERT(selection->Size == storage->Data.Size); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| // Apply requests coming from BeginMultiSelect() and EndMultiSelect(). | // Apply requests coming from BeginMultiSelect() and EndMultiSelect(). | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ocornut
					ocornut