FYI all, I plan to add a public method to GroupItem to support reordering of subgroups. The target use case is for a new custom view for Truchas induction coils; specifically we want to allow dragging and dropping rows in a table that displays time steps vs frequency and electrical current data. The planned signature is
// smtk::attribute::GroupItem::
bool shiftGroup(std::size_t fromIndex, std::size_t toIndex);
// fromIndex: position of the selected subgroup to be moved
// toIndex: position of the subgroup after the move is complete
// return value indicates whether move was completed or not
It is a relatively minor change, but because I don’t touch smtkCore’s guts very often, I thought I should give everyone a chance to comment beforehand.
Related to the same use case, there is also a need to “sort” the table based on the time values. My current thinking is for the custom view code to figure out the sorted order, and call the shiftGroup() method, possibly multiple times, to update the GroupItem.
@johnt If you are going to provide the same functionality in other classes, how about removing Group from the name so it can be shared across classes? I like move() better than the others. Especially shift() which to me implies stack semantics like rot, swap, over in Forth (because my old HP calculator did things that way).
If the API were a little more generic, permute() or reorder() might make sense. But it sounds like those are out of scope.
Are you suggesting a templated function to move items within an std::vector? (I’m a bit surprised there isn’t one in std::algorithm.) Maybe I should add a VectorUtil.h file to smtk/common for this, analogous, in some ways, to the StringUtil class.
The names are consistent with the current API methods:
GroupItem’s appendGroup() and removeGroup()
ValueItemTemplate’s appendValue() and removeValue()
As an aside, I don’t foresee the internal logic being reused between the group and value methods, because the value item method needs to consider discrete-value and expression options. But both methods should be able to use a common VectorUtil::move() method.
No, there is already a move function in the <algorithm> header [1].
What I was suggesting is that these functions share the same name; there is no need to add part of the class name to the end of the method — the name and type of the variable usually make it quite apparent what you are doing. If you must name the methods moveXXX() instead of just move(), I would advocate for moveEntry() or something generic that can be shared across both classes. This makes it possible for the class to be a template parameter to a function that moves things without caring what the container contains. If SMTK insists on class-unique method names for identical functionality then we cannot use classes as templates, which is a bummer.
Are you suggesting a templated function to move items within an std::vector? (I’m a bit surprised there isn’t one in std::algorithm.)
No, there is already a move function in the <algorithm> header [1 ].
+1. We should be using the STL for this
there is no need to add part of the class name to the end of the method — the name and type of the variable usually make it quite apparent what you are doing.
+1 for a terse API.
If SMTK insists on class-unique method names for identical functionality then we cannot use classes as templates, which is a bummer.
Agreed, total bummer. There are ways around it, but since we control both sides of the API it is better to standardize the API now then to code around awkward API later.
Time notwithstanding, the STL operations for move, copy, find, accumulate, etc. all use a generic iterator-based interface. We have containers that can be iterated; perhaps the better play is to expose iterators for our containers. They can be (but need not be) simply iterators to the underlying container; that would be < 20 lines of code across the entire attribute system.
I have done this in the past (and there are begin() and end() methods in ValueItemTemplate thanks to YT), but it does mean that now the container class doesn’t know when its internal storage has been changed. This is especially problematic when things like isSet(int i) rely on a different container having the same length and ordering as the one you just borked by calling std::move(...) on the values.
So, I think read access via iterators is great, but write access needs to be considered very carefully and either avoided or guarded or at least really well-documented.
2. The return value is true if the underlying data is rotated (even if the end result looks the same, for example, if all value items have the same value). This implies that the return value is false if:
either position argument is outside the range of the item’s underlying data
the two position arguments are equal to each other
3. I have no plans to add a generic rotate_any_smtk_object() function; if such a function is potentially useful, then some other project will have to implement it.
4. But if we think rotating data might be applicable to other attribute item types, I am open to adding a virtual method in the base class, that is: