private float DrawAddArea(Rect position, SerializedProperty property, SerializedProperty collection)
        {
            DisplayState state = ListStates[CollectionDisplay.GetFullPath(collection)];

            if (!state.AddingElement || !collection.isExpanded)
            {
                return(0);
            }

            ReorderableList list          = state.List.List;
            Rect            startPosition = position;

            Rect labelPosition = position;

            labelPosition.height = EditorGUIUtility.singleLineHeight;
            UnityEngine.GUI.Label(labelPosition, new GUIContent("Add Element"), centeredLabelStyle);
            position.y    += labelPosition.height;
            position.xMin += 20;
            position.xMax -= 20;

            if (DrawAddElement != null)
            {
                position.y += DrawAddElement(position, property, collection);
            }

            Rect addButtonPosition = position;

            addButtonPosition.xMax  -= position.width * .55f;
            addButtonPosition.height = EditorGUIUtility.singleLineHeight;
            if (UnityEngine.GUI.Button(addButtonPosition, "Add"))
            {
                bool successful = true;
                try
                {
                    SerializationReflection.CallPrivateMethod(property, "AddTemp");
                }
                catch (Exception e)
                {
                    successful = false;
                    EditorUtility.DisplayDialog("Cannot Add to Collection", e.InnerException.Message, "Okay");
                }

                if (successful)
                {
                    EndAddMode(state);
                }
            }

            Rect cancelButtonPosition = position;

            cancelButtonPosition.xMin  += position.width * .55f;
            cancelButtonPosition.height = EditorGUIUtility.singleLineHeight;
            if (UnityEngine.GUI.Button(cancelButtonPosition, "Cancel"))
            {
                SerializationReflection.CallPrivateMethod(property, "ClearTemp");
                EndAddMode(state);
                state.LastAddingHeight = 0;
                return(0);
            }

            position.y += addButtonPosition.height;
            position.y += 5;

            state.LastAddingHeight = position.y - startPosition.y;
            return(state.LastAddingHeight);
        }
        public ReorderableCollection(SerializedProperty property, SerializedProperty collection)
        {
            bool   allowDrag     = true;
            object pathReference = SerializationReflection.GetPathReference(property);

            if (pathReference != null)
            {
                Type sortedType = SerializationReflection.GetPathReference(property).GetType();

                while (sortedType != null)
                {
                    if (sortedType.GetInterface("SortedCollection`1") != null)
                    {
                        allowDrag = false;
                        break;
                    }
                    sortedType = sortedType.BaseType;
                }
            }

            string collectionPath = CollectionDisplay.GetFullPath(collection);

            DisplayState listState;

            if (ListStates.ContainsKey(collectionPath))
            {
                ListStates.Remove(collectionPath);
            }

            listState = new DisplayState();
            ListStates.Add(collectionPath, listState);
            listState.Collection = collection;
            listState.List       = this;

            DrawerState drawerState = CollectionDisplay.GetDrawerState(property);
            var         newList     = new ReorderableList(collection.serializedObject, collection)
            {
                draggable = allowDrag,
            };

            newList.showDefaultBackground = false;

            newList.onReorderCallbackWithDetails = (ReorderableList list, int oldIndex, int newIndex) =>
            {
                Reorder?.Invoke(drawerState.Property, listState.Collection, oldIndex, newIndex);
            };

            newList.drawHeaderCallback = (Rect position) =>
            {
                SerializedProperty hasLostValue = drawerState.Property.FindPropertyRelative("hasLostValue");
                if (hasLostValue != null && hasLostValue.boolValue == true)
                {
                    EditorUtility.DisplayDialog("Collection Error", "You've attempted to change an element in a way that prevents it from being added to the collection. The element will be moved to the Add Element area of the list so you can change the element and add it back in.", "Okay");
                    ListStates[CollectionDisplay.GetFullPath(listState.Collection)].AddingElement = true;
                    hasLostValue.boolValue = false;
                }

                Rect startPosition = position;

                DrawHeaderBackground(position, drawerState.Property, listState.Collection);
                DrawSettingsButton(position, drawerState.Property, listState.Collection);
                position.y += DrawSettings(position, drawerState.Property, listState.Collection);

                for (var i = 0; i < DrawHeaderAreaHandlers.Count; i++)
                {
                    position.y += DrawHeaderAreaHandlers[i].Invoke(position, drawerState.Property, listState.Collection);
                }

                listState.LastHeaderHeight = position.y - startPosition.y;
                newList.headerHeight       = listState.LastHeaderHeight;
            };

            newList.drawElementCallback += (Rect position, int index, bool isActive, bool isFocused) =>
            {
                position.y += 2;

                var pageRange = GetPageDisplayRange(listState.Collection);
                if (index >= pageRange.x && index < pageRange.y)
                {
                    EditorGUI.BeginDisabledGroup(listState.AddingElement);
                    DrawElement?.Invoke(position, index, drawerState.Property, listState.Collection);
                    EditorGUI.EndDisabledGroup();
                }
            };

            newList.drawElementBackgroundCallback = (Rect position, int index, bool isActive, bool isFocused) =>
            {
                if (Mathf.Approximately(position.height, 0))
                {
                    return;
                }

                Rect backgroundPos = position;
                backgroundPos.yMin       -= 2;
                backgroundPos.yMax       += 2;
                boxBackground.fixedHeight = backgroundPos.height;
                boxBackground.fixedWidth  = backgroundPos.width;
                Color guiColor = UnityEngine.GUI.color;

                if (isActive)
                {
                    UnityEngine.GUI.color = UnityEngine.GUI.skin.settings.selectionColor;
                }

                if (index % 2 == 0)
                {
                    UnityEngine.GUI.color = Color.Lerp(UnityEngine.GUI.color, Color.black, .1f);
                }

                if (Event.current.type == EventType.Repaint)
                {
                    boxBackground.Draw(position, false, isActive, true, false);
                }

                UnityEngine.GUI.color = guiColor;

                position.xMin += 2;
                position.xMax -= 3;
            };

            newList.elementHeightCallback += (int index) =>
            {
                int pageSize       = GetItemsPerPage(listState.Collection);
                int pageStartIndex = (listState.CurrentPageSet * listState.PageSetSize * pageSize) + (listState.CurrentPage * pageSize);
                int pageEndIndex   = pageStartIndex + pageSize;

                if (index >= pageStartIndex && index < pageEndIndex && (GetElementHeight != null))
                {
                    return(GetElementHeight(index, drawerState.Property, listState.Collection) + 2);
                }

                return(0);
            };

            newList.drawFooterCallback = (Rect position) =>
            {
                DrawFooterBackground(position, drawerState.Property, listState.Collection);
                DrawAddRemoveButtons(position, drawerState.Property, listState.Collection);

                Rect startPosition = position;
                for (var i = 0; i < DrawFooterAreaHandlers.Count; i++)
                {
                    position.y += DrawFooterAreaHandlers[i].Invoke(position, drawerState.Property, listState.Collection);
                }

                position.y += DrawPageSelection(position, drawerState.Property, listState.Collection);
                if (listState.List.DrawCustomAdd)
                {
                    position.y += DrawAddArea(position, property, collection);
                }

                listState.LastFooterHeight  = position.y - startPosition.y;
                listState.LastFooterHeight += 4;
                List.footerHeight           = listState.LastFooterHeight;
            };

            newList.onRemoveCallback += (ReorderableList targetList) =>
            {
                if (targetList.index > -1)
                {
                    int pageSize       = GetItemsPerPage(listState.Collection);
                    int pageStartIndex = GetPageDisplayRange(listState.Collection).x;
                    listState.Collection.DeleteArrayElementAtIndex(pageStartIndex + targetList.index);
                }
            };

            newList.onAddCallback += (ReorderableList targetList) =>
            {
                if (DrawCustomAdd)
                {
                    ListStates[collectionPath].AddingElement = !ListStates[collectionPath].AddingElement;
                    if (ListStates[collectionPath].AddingElement)
                    {
                        SerializationReflection.CallPrivateMethod(property, "ClearTemp");
                    }
                }
                else
                {
                    listState.Collection.InsertArrayElementAtIndex(listState.Collection.arraySize);
                }
            };

            List = newList;
        }