// move an item and return true if it really moved.
        // Also translate the indices to "leaf" coordinates
        internal bool Move(object item, IList list, ref int oldIndex, ref int newIndex)
        {
            int oldIndexLocal = -1, newIndexLocal = -1;
            int localIndex = 0;
            int n          = ProtectedItems.Count;

            // the input is in "full" coordinates.  Find the corresponding local coordinates
            for (int fullIndex = 0; ; ++fullIndex)
            {
                if (fullIndex == oldIndex)
                {
                    oldIndexLocal = localIndex;
                    if (newIndexLocal >= 0)
                    {
                        break;
                    }
                    ++localIndex;
                }

                if (fullIndex == newIndex)
                {
                    newIndexLocal = localIndex;
                    if (oldIndexLocal >= 0)
                    {
                        --newIndexLocal;
                        break;
                    }
                    ++fullIndex;
                    ++oldIndex;
                }

                if (localIndex < n && ItemsControl.EqualsEx(ProtectedItems[localIndex], list[fullIndex]))
                {
                    ++localIndex;
                }
            }

            // the move may be a no-op w.r.t. this group
            if (oldIndexLocal == newIndexLocal)
            {
                return(false);
            }

            // translate to "leaf" coordinates
            int low, high, lowLeafIndex, delta = 0;

            if (oldIndexLocal < newIndexLocal)
            {
                low          = oldIndexLocal + 1;
                high         = newIndexLocal + 1;
                lowLeafIndex = LeafIndexFromItem(null, oldIndexLocal);
            }
            else
            {
                low          = newIndexLocal;
                high         = oldIndexLocal;
                lowLeafIndex = LeafIndexFromItem(null, newIndexLocal);
            }

            for (int i = low; i < high; ++i)
            {
                CollectionViewGroupInternal subgroup = Items[i] as CollectionViewGroupInternal;
                delta += (subgroup == null) ? 1 : subgroup.ItemCount;
            }

            if (oldIndexLocal < newIndexLocal)
            {
                oldIndex = lowLeafIndex;
                newIndex = oldIndex + delta;
            }
            else
            {
                newIndex = lowLeafIndex;
                oldIndex = newIndex + delta;
            }

            // do the actual move
            ProtectedItems.Move(oldIndexLocal, newIndexLocal);
            return(true);
        }