/* Copyright (c) 2022 Alex Diener This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Alex Diener alex@ludobloom.com */ #ifndef __IndexSelection_H__ #define __IndexSelection_H__ typedef struct IndexSelection IndexSelection; #define IndexSelection_superclass StemObject #include "stemobject/StemObject.h" #include "utilities/ReverseIndexLookup.h" #define IndexSelection_ivars \ StemObject_ivars \ \ unsigned int indexCount; \ unsigned int private_ivar(indexAllocatedCount); \ unsigned int * indexes; \ ReverseIndexLookup * reverseLookup; \ unsigned int selectionDirtyValue; \ unsigned int reverseLookupDirtyValue; \ unsigned int lastReverseLookupDirtyValue; #define IndexSelection_vtable(self_type) \ StemObject_vtable(self_type) stemobject_declare(IndexSelection) IndexSelection * IndexSelection_create(void); bool IndexSelection_init(IndexSelection * self); void IndexSelection_dispose(IndexSelection * self); IndexSelection * IndexSelection_copy(IndexSelection * self); void IndexSelection_copySelectionFrom(IndexSelection * self, IndexSelection * selection); // Returns true if a change was made. No change is made if index is already selected. Setting assumeUnique to true // bypasses this check and assumes that the index being added is not already selected. bool IndexSelection_selectIndex(IndexSelection * self, unsigned int index, bool assumeUnique); // Returns true if a change was made. No change is made if index is not already selected. bool IndexSelection_deselectIndex(IndexSelection * self, unsigned int index); // Returns true if a change was made. No change is made if no indexes are already selected. bool IndexSelection_deselectAll(IndexSelection * self); // Returns the new selected state of the index. A change is always made. bool IndexSelection_toggleIndex(IndexSelection * self, unsigned int index); // selectionIndex is an index into the indexes array itself, rather than one of its values. Assumes selectionIndex is in range. void IndexSelection_deselectItemAtIndex(IndexSelection * self, unsigned int selectionIndex); // Selects all indexes from start to start + count. Returns true if a change was made. Setting assumeUnique to true // bypasses this check and assumes that nothing in the range being added is not already selected. bool IndexSelection_selectRange(IndexSelection * self, unsigned int start, unsigned int count, bool assumeUnique); // Toggles all indexes from start to start + count. void IndexSelection_toggleRange(IndexSelection * self, unsigned int start, unsigned int count); // Adds indexDelta to all values in the indexes array that are greater than or equal to the indexStart. If this would // cause an index to fall below indexStart, that index is instead deleted. void IndexSelection_adjustIndexes(IndexSelection * self, unsigned int indexStart, int indexDelta); // If outSelectionIndex is non-NULL and index is selected, the position of index in the indexes array is written to it. bool IndexSelection_isIndexSelected(IndexSelection * self, unsigned int index, unsigned int * outSelectionIndex); // Deselects all indexes whose value is greater than or equal to maxIndexCount. Returns true if a change was made. bool IndexSelection_truncateSelectionToMaxIndexCount(IndexSelection * self, unsigned int maxIndexCount); // Removes any duplicate entries in indexes, and returns the number of duplicates removed. This should only be // necessary if indexes was modified directly, or if selectIndex() was called with assumeUnique set to false without // checks to ensure uniqueness before inserting. unsigned int IndexSelection_removeDuplicates(IndexSelection * self); // Indexes are stored in the order they were selected, rather than in numerical order. These functions can be used to // find the numerically lowest or highest entry in indexes, which might not be the first and last elements. // If outSelectionIndex is non-NULL, the index of the returned value within indexes is written to it. // UINT_MAX is returned if nothing is selected. unsigned int IndexSelection_getMinSelectedIndex(IndexSelection * self, unsigned int * outSelectionIndex); unsigned int IndexSelection_getMaxSelectedIndex(IndexSelection * self, unsigned int * outSelectionIndex); #endif