private void displaceElement(int targetIndex, Transform displaced)
        {
            _displacedFromIndex          = targetIndex;
            _displacedObjectOriginList   = _currentReorderableListRaycasted;
            _displacedObject             = displaced.GetComponent <RectTransform>();
            _displacedObjectLE           = _displacedObject.GetComponent <LayoutElement>();
            _displacedObjectOriginalSize = _displacedObject.rect.size;

            var args = new ReorderableList.ReorderableListEventStruct
            {
                DroppedObject = _displacedObject.gameObject,
                FromList      = _currentReorderableListRaycasted,
                FromIndex     = targetIndex,
            };


            int c = _fakeElement.parent == _reorderableList.Content
                ? _reorderableList.Content.childCount - 1
                : _reorderableList.Content.childCount;

            if (_reorderableList.IsDropable && c < _reorderableList.maxItems && _displacedObject.GetComponent <ReorderableListElement>().IsTransferable)
            {
                _displacedObjectLE.preferredWidth  = _draggingObjectOriginalSize.x;
                _displacedObjectLE.preferredHeight = _draggingObjectOriginalSize.y;
                _displacedObject.SetParent(_reorderableList.Content, false);
                _displacedObject.rotation = _reorderableList.transform.rotation;
                _displacedObject.SetSiblingIndex(_fromIndex);
                // Force refreshing both lists because otherwise we get inappropriate FromList in ReorderableListEventStruct
                _reorderableList.Refresh();
                _currentReorderableListRaycasted.Refresh();

                args.ToList  = _reorderableList;
                args.ToIndex = _fromIndex;
                _reorderableList.OnElementDisplacedTo.Invoke(args);
                _reorderableList.OnElementAdded.Invoke(args);
            }
            else if (_displacedObject.GetComponent <ReorderableListElement>().isDroppableInSpace)
            {
                _displacedObject.SetParent(_currentReorderableListRaycasted.DraggableArea, true);
                _currentReorderableListRaycasted.Refresh();
                _displacedObject.position += new Vector3(_draggingObjectOriginalSize.x / 2, _draggingObjectOriginalSize.y / 2, 0);
            }
            else
            {
                _displacedObject.SetParent(null, true);
                _displacedObjectOriginList.Refresh();
                _displacedObject.gameObject.SetActive(false);
            }
            _displacedObjectOriginList.OnElementDisplacedFrom.Invoke(args);
            _reorderableList.OnElementRemoved.Invoke(args);
        }
        private void revertDisplacedElement()
        {
            var args = new ReorderableList.ReorderableListEventStruct
            {
                DroppedObject = _displacedObject.gameObject,
                FromList      = _displacedObjectOriginList,
                FromIndex     = _displacedFromIndex,
            };

            if (_displacedObject.parent != null)
            {
                args.ToList  = _reorderableList;
                args.ToIndex = _fromIndex;
            }

            _displacedObjectLE.preferredWidth  = _displacedObjectOriginalSize.x;
            _displacedObjectLE.preferredHeight = _displacedObjectOriginalSize.y;
            _displacedObject.SetParent(_displacedObjectOriginList.Content, false);
            _displacedObject.rotation = _displacedObjectOriginList.transform.rotation;
            _displacedObject.SetSiblingIndex(_displacedFromIndex);
            _displacedObject.gameObject.SetActive(true);

            // Force refreshing both lists because otherwise we get inappropriate FromList in ReorderableListEventStruct
            _reorderableList.Refresh();
            _displacedObjectOriginList.Refresh();

            if (args.ToList != null)
            {
                _reorderableList.OnElementDisplacedToReturned.Invoke(args);
                _reorderableList.OnElementRemoved.Invoke(args);
            }
            _displacedObjectOriginList.OnElementDisplacedFromReturned.Invoke(args);
            _displacedObjectOriginList.OnElementAdded.Invoke(args);

            _displacedFromIndex        = -1;
            _displacedObjectOriginList = null;
            _displacedObject           = null;
            _displacedObjectLE         = null;
        }
        public void OnBeginDrag(PointerEventData eventData)
        {
            _canvasGroup.blocksRaycasts = false;
            isValid = true;
            if (_reorderableList == null)
            {
                return;
            }

            //Can't drag, return...
            if (!_reorderableList.IsDraggable || !this.IsGrabbable)
            {
                _draggingObject = null;
                return;
            }

            //If not CloneDraggedObject just set draggingObject to this gameobject
            if (_reorderableList.CloneDraggedObject == false)
            {
                _draggingObject     = _rect;
                _fromIndex          = _rect.GetSiblingIndex();
                _displacedFromIndex = -1;
                //Send OnElementRemoved Event
                if (_reorderableList.OnElementRemoved != null)
                {
                    _reorderableList.OnElementRemoved.Invoke(new ReorderableList.ReorderableListEventStruct
                    {
                        DroppedObject = _draggingObject.gameObject,
                        IsAClone      = _reorderableList.CloneDraggedObject,
                        SourceObject  = _reorderableList.CloneDraggedObject ? gameObject : _draggingObject.gameObject,
                        FromList      = _reorderableList,
                        FromIndex     = _fromIndex,
                    });
                }
                if (isValid == false)
                {
                    _draggingObject = null;
                    return;
                }
            }
            else
            {
                //Else Duplicate
                GameObject clone = (GameObject)Instantiate(gameObject);
                _draggingObject = clone.GetComponent <RectTransform>();
            }

            //Put _dragging object into the dragging area
            _draggingObjectOriginalSize = gameObject.GetComponent <RectTransform>().rect.size;
            _draggingObjectLE           = _draggingObject.GetComponent <LayoutElement>();
            _draggingObject.SetParent(_reorderableList.DraggableArea, true);
            _draggingObject.SetAsLastSibling();
            _reorderableList.Refresh();

            //Create a fake element for previewing placement
            _fakeElement   = new GameObject("Fake").AddComponent <RectTransform>();
            _fakeElementLE = _fakeElement.gameObject.AddComponent <LayoutElement>();

            RefreshSizes();

            //Send OnElementGrabbed Event
            if (_reorderableList.OnElementGrabbed != null)
            {
                _reorderableList.OnElementGrabbed.Invoke(new ReorderableList.ReorderableListEventStruct
                {
                    DroppedObject = _draggingObject.gameObject,
                    IsAClone      = _reorderableList.CloneDraggedObject,
                    SourceObject  = _reorderableList.CloneDraggedObject ? gameObject : _draggingObject.gameObject,
                    FromList      = _reorderableList,
                    FromIndex     = _fromIndex,
                });

                if (!isValid)
                {
                    CancelDrag();
                    return;
                }
            }

            _isDragging = true;
        }
        public void OnEndDrag(PointerEventData eventData)
        {
            _isDragging = false;

            if (_draggingObject != null)
            {
                //If we have a, ReorderableList that is dropable
                //Put the dragged object into the content and at the right index
                if (_currentReorderableListRaycasted != null && _currentReorderableListRaycasted.IsDropable &&
                    (IsTransferable || _currentReorderableListRaycasted == _reorderableList))
                {
                    var args = new ReorderableList.ReorderableListEventStruct
                    {
                        DroppedObject = _draggingObject.gameObject,
                        IsAClone      = _reorderableList.CloneDraggedObject,
                        SourceObject  = _reorderableList.CloneDraggedObject ? gameObject : _draggingObject.gameObject,
                        FromList      = _reorderableList,
                        FromIndex     = _fromIndex,
                        ToList        = _currentReorderableListRaycasted,
                        ToIndex       = _fakeElement.GetSiblingIndex()
                    };
                    //Send OnelementDropped Event
                    if (_reorderableList && _reorderableList.OnElementDropped != null)
                    {
                        _reorderableList.OnElementDropped.Invoke(args);
                    }
                    if (!isValid)
                    {
                        CancelDrag();
                        return;
                    }
                    RefreshSizes();
                    _draggingObject.SetParent(_currentReorderableListRaycasted.Content, false);
                    _draggingObject.rotation = _currentReorderableListRaycasted.transform.rotation;
                    _draggingObject.SetSiblingIndex(_fakeElement.GetSiblingIndex());

                    _reorderableList.OnElementAdded.Invoke(args);

                    // Force refreshing both lists because otherwise we get inappropriate FromList in ReorderableListEventStruct
                    _reorderableList.Refresh();
                    _currentReorderableListRaycasted.Refresh();

                    if (!isValid)
                    {
                        throw new Exception("It's too late to cancel the Transfer! Do so in OnElementDropped!");
                    }
                }
                //We don't have an ReorderableList
                else
                {
                    if (this.isDroppableInSpace)
                    {
                        _reorderableList.OnElementDropped.Invoke(new ReorderableList.ReorderableListEventStruct
                        {
                            DroppedObject = _draggingObject.gameObject,
                            IsAClone      = _reorderableList.CloneDraggedObject,
                            SourceObject  =
                                _reorderableList.CloneDraggedObject ? gameObject : _draggingObject.gameObject,
                            FromList  = _reorderableList,
                            FromIndex = _fromIndex
                        });
                    }
                    else
                    {
                        CancelDrag();
                    }
                }
            }

            //Delete fake element
            if (_fakeElement != null)
            {
                Destroy(_fakeElement.gameObject);
            }
        }