# Proposed smtk::attribute::GroupItem::shiftGroup() method

**URL:** https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263
**Category:** Design
**Created:** [June 4, 2019, 3:11pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263 "2019-06-04T15:11:14Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### Author: ![johnt](https://discourse.kitware.com/user_avatar/discourse.kitware.com/johnt/32/147_2.png) [@johnt](https://discourse.kitware.com/u/johnt)
#### Post date: [June 4, 2019, 3:11pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/1 "2019-06-04T15:11:14Z")

</div>

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

```auto
// 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.

---

<div class="post-metadata">

### Author: ![johnt](https://discourse.kitware.com/user_avatar/discourse.kitware.com/johnt/32/147_2.png) [@johnt](https://discourse.kitware.com/u/johnt)
#### Post date: [June 4, 2019, 6:32pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/2 "2019-06-04T18:32:26Z")

</div>

Considering some alternative names, in current order of preference

```auto
    bool moveGroup(std::size_t fromPosition, std::size_t toPosition)
    bool repositionGroup(...)
    bool shiftGroup(...)
    bool relocateGroup(...)

```

---

<div class="post-metadata">

### Author: ![johnt](https://discourse.kitware.com/user_avatar/discourse.kitware.com/johnt/32/147_2.png) [@johnt](https://discourse.kitware.com/u/johnt)
#### Post date: [June 5, 2019, 9:43pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/3 "2019-06-05T21:43:03Z")

</div>

Side note, I plan to add the equivalent functionality to ValueItem/ValueItemTemplate.

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)
#### Post date: [June 5, 2019, 9:57pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/4 "2019-06-05T21:57:35Z")

</div>

@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.

---

<div class="post-metadata">

### Author: ![johnt](https://discourse.kitware.com/user_avatar/discourse.kitware.com/johnt/32/147_2.png) [@johnt](https://discourse.kitware.com/u/johnt)
#### Post date: [June 5, 2019, 10:33pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/5 "2019-06-05T22:33:49Z")

</div>

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.

```auto
template <typename T>
bool smtk::common::VectorUtil::move(
  std::vector<T>& v, std::size_t fromPosition, std::size_t toPosition)

```

* * *

As for smtk::attribute, to add a little more detail, my current thinking is to add two functions:

```auto
bool smtk::attribute::GroupItem::moveGroup(std::size_t fromPosition, std::size_t toPosition)
bool smtk::attribute::ValueItemTemplate::moveValue(std::size_t fromPosition, std::size_t toPosition)

```

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.

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)
#### Post date: [June 5, 2019, 10:48pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/6 "2019-06-05T22:48:24Z")

</div>

> [@johnt](#):
>
> 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](http://www.cplusplus.com/reference/algorithm/move/)].

> [@johnt](#):
>
> As for smtk::attribute, to add a little more detail, my current thinking is to add two functions: …

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.

---

<div class="post-metadata">

### Author: ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)
#### Post date: [June 5, 2019, 11:20pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/7 "2019-06-05T23:20:57Z")

</div>

> > 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](http://www.cplusplus.com/reference/algorithm/move/)].

+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](http://www.drdobbs.com/cpp/c-type-traits/184404270), but since we control both sides of the API it is better to standardize the API now then to code around awkward API later.

---

<div class="post-metadata">

### Author: ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)
#### Post date: [June 5, 2019, 11:24pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/8 "2019-06-05T23:24:39Z")

</div>

> [@dcthomp](#):
>
> 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.

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.

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)
#### Post date: [June 5, 2019, 11:29pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/9 "2019-06-05T23:29:12Z")

</div>

> [@tj.corona](#):
>
> We have containers that can be iterated; perhaps the better play is to expose iterators for our containers.

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.

---

<div class="post-metadata">

### Author: ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)
#### Post date: [June 5, 2019, 11:31pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/10 "2019-06-05T23:31:47Z")

</div>

> [@dcthomp](#):
>
> 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.

> [@tj.corona](#):
>
> They can be (but need not be) simply iterators to the underlying container

Noted: change that to “cannot be simply iterators to the underlying container.”

---

<div class="post-metadata">

### Author: ![johnt](https://discourse.kitware.com/user_avatar/discourse.kitware.com/johnt/32/147_2.png) [@johnt](https://discourse.kitware.com/u/johnt)
#### Post date: [June 6, 2019, 1:43am UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/11 "2019-06-06T01:43:01Z")

</div>

Hmm, if I understand correctly, std::move() doesn’t shift the data, as would be needed for a drag & drop operation.

As an example, for a vector of integers

```
[0, 1, 2, 3, 4, 5]

```

I believe that a std::move call from positions [4,5) to 2 would change the vector to

```
[0, 1, 4, 3, undefined, 5]

```

whereas the desired result is

```
[0, 1, 4, 2, 3, 5]

```

Perhaps, as you suggest, I need a better name for this function?

- reorder() as you proposed
- moveAndShift()
- shuffleOne()

---

<div class="post-metadata">

### Author: ![johnt](https://discourse.kitware.com/user_avatar/discourse.kitware.com/johnt/32/147_2.png) [@johnt](https://discourse.kitware.com/u/johnt)
#### Post date: [June 6, 2019, 2:08am UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/12 "2019-06-06T02:08:56Z")

</div>

Oh, never mind, looks like std::rotate() is what we need…

---

<div class="post-metadata">

### Author: ![dcthomp](https://discourse.kitware.com/user_avatar/discourse.kitware.com/dcthomp/32/10_2.png) [@dcthomp](https://discourse.kitware.com/u/dcthomp)
#### Post date: [June 6, 2019, 2:38am UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/13 "2019-06-06T02:38:08Z")

</div>

> [@johnt](#):
>
> Oh, never mind, looks like std::rotate() is what we need…

Sounds like a good method name. It will be what people familiar w/ the STL would expect.

---

<div class="post-metadata">

### Author: ![tj.corona](https://discourse.kitware.com/user_avatar/discourse.kitware.com/tj.corona/32/35_2.png) [@tj.corona](https://discourse.kitware.com/u/tj.corona)
#### Post date: [June 6, 2019, 6:40am UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/14 "2019-06-06T06:40:55Z")

</div>

> [@johnt](#):
>
> Oh, never mind, looks like std::rotate() is what we need…

Or [insert](http://www.cplusplus.com/reference/vector/vector/insert/). Since vectors are guaranteed to be contiguous in memory, inserting and deleting the original range could be analogous to rotate.

EDIT: ah, never mind. I misunderstood the desired effect.

---

<div class="post-metadata">

### Author: ![johnt](https://discourse.kitware.com/user_avatar/discourse.kitware.com/johnt/32/147_2.png) [@johnt](https://discourse.kitware.com/u/johnt)
#### Post date: [June 6, 2019, 2:22pm UTC](https://discourse.kitware.com/t/proposed-smtk-shiftgroup-method/263/15 "2019-06-06T14:22:58Z")

</div>

Thanks for the thoughtful discussions. With the hope of making this my last post to this topic 🙂 , here is where I am at this morning:

1. Plan to add two methods:

```auto
bool smtk::attribute::GroupItem::rotate(std::size_t fromPosition, std::size_t toPosition)
bool smtk::attribute::ValueItemTemplate::rotate(std::size_t fromPosition, std::size_t toPosition)

```

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:

```auto
virtual bool smtk::attribute::Item::rotate(std::size_t fromPosition, std::size_t toPosition)
{
  (void)fromPosition;
  (void)toPosition;
  return false;
}

```
