protected void ReplaceElement(IPanelGroupElement beforeElement, IPanelGroupElement afterElement)
        {
            if (beforeElement == afterElement)
            {
                return;
            }

            if (beforeElement.IsNull() || afterElement.IsNull())
            {
                Debug.LogError("Invalid argument!");
                return;
            }

            int index = elements.IndexOf(beforeElement);

            if (index < 0)
            {
                Debug.LogError("Invalid index!");
                return;
            }

            if (beforeElement.Group == this)
            {
                Canvas.UnanchoredPanelGroup.AddElement(beforeElement);
            }

            AddElementAt(index, afterElement);
        }
        protected void TryChangeSizeOf(IPanelGroupElement element, PanelDirection direction, float deltaSize)
        {
            if (element.IsNull() || deltaSize <= MIN_SIZE_TOLERANCE || element.GetSurroundingElement(direction).IsNull())
            {
                return;
            }

            resizePropsIndex = 0;

            IPanelGroupElement surroundingElement = element.GetSurroundingElement(direction);

            element = surroundingElement.GetSurroundingElement(direction.Opposite());
            AddResizeProperty(element);

            float deltaMovement = TryChangeSizeOfInternal(surroundingElement, direction, deltaSize);

            if (resizePropsIndex > 1)
            {
                ResizeElementHelper(0, direction, deltaMovement);

                for (int i = 0; i < resizePropsIndex; i++)
                {
                    ElementDirtyProperties properties = resizeProperties[i];

                    Vector2 position = properties.element.Position + new Vector2(properties.posX, properties.posY);
                    Vector2 size     = properties.element.Size + new Vector2(properties.sizeX, properties.sizeY);

                    UpdateBoundsOf(properties.element, position, size);
                }
            }
        }
        protected void AddElementAt(int index, IPanelGroupElement element)
        {
            if (element.IsNull())
            {
                Debug.LogError("Invalid argument!");
                return;
            }

            if (index < 0 || index > elements.Count)
            {
                Debug.LogError("Invalid index!");
                return;
            }

            int elementIndex = elements.IndexOf(element);

            if (elementIndex >= 0 && element.Group != this)
            {
                if (index > elementIndex)
                {
                    index--;
                }

                elements.RemoveAt(elementIndex);
                elementIndex = -1;
            }

            if (elementIndex == index)
            {
                return;
            }

            if (element.Group != null)
            {
                element.Group.SetDirty();
            }

            if (elementIndex < 0)
            {
                // Element not present in this group, add it
                elements.Insert(index, element);
                SetGroupFor(element, this);
            }
            else if (elementIndex != index)
            {
                // Element already present in this group, just change its index
                if (elementIndex > index)
                {
                    elementIndex++;
                }

                elements.Insert(index, element);
                elements.RemoveAt(elementIndex);
            }

            SetDirty();
        }
        protected float TryChangeSizeOfInternal(IPanelGroupElement element, PanelDirection direction, float deltaSize)
        {
            int currResizePropsIndex = resizePropsIndex;

            AddResizeProperty(element);

            float thisFlexibleSize;

            if (direction == PanelDirection.Left || direction == PanelDirection.Right)
            {
                thisFlexibleSize = element.Size.x - element.MinSize.x;
            }
            else
            {
                thisFlexibleSize = element.Size.y - element.MinSize.y;
            }

            if (thisFlexibleSize > MIN_SIZE_TOLERANCE)
            {
                if (thisFlexibleSize >= deltaSize)
                {
                    thisFlexibleSize = deltaSize;
                    deltaSize        = 0f;
                }
                else
                {
                    deltaSize -= thisFlexibleSize;
                }

                ResizeElementHelper(currResizePropsIndex, direction.Opposite(), -thisFlexibleSize);
            }
            else
            {
                thisFlexibleSize = 0f;
            }

            if (deltaSize > MIN_SIZE_TOLERANCE)
            {
                IPanelGroupElement surrounding = element.GetSurroundingElement(direction);
                if (!surrounding.IsNull())
                {
                    if (surrounding.Group != element.Group)
                    {
                        AddResizeProperty(surrounding.GetSurroundingElement(direction.Opposite()));
                    }

                    float deltaMovement = TryChangeSizeOfInternal(surrounding, direction, deltaSize);
                    if (deltaMovement > MIN_SIZE_TOLERANCE)
                    {
                        if (surrounding.Group == element.Group)
                        {
                            if (direction == PanelDirection.Left)
                            {
                                resizeProperties[currResizePropsIndex].posX -= deltaMovement;
                            }
                            else if (direction == PanelDirection.Top)
                            {
                                resizeProperties[currResizePropsIndex].posY += deltaMovement;
                            }
                            else if (direction == PanelDirection.Right)
                            {
                                resizeProperties[currResizePropsIndex].posX += deltaMovement;
                            }
                            else
                            {
                                resizeProperties[currResizePropsIndex].posY -= deltaMovement;
                            }

                            thisFlexibleSize += deltaMovement;
                        }
                        else
                        {
                            ResizeElementHelper(currResizePropsIndex + 1, direction, deltaMovement);
                        }
                    }
                    else
                    {
                        resizePropsIndex = currResizePropsIndex + (thisFlexibleSize == 0 ? 0 : 1);
                    }
                }
                else if (thisFlexibleSize == 0f)
                {
                    resizePropsIndex = currResizePropsIndex;
                }
            }

            return(thisFlexibleSize);
        }