/// <summary>
        /// Calculate appropriate rectangle from given current state and target size.
        /// </summary>
        /// <param name="size">Size enumeration.</param>
        /// <param name="rect">Rectangle to modify.</param>
        /// <param name="elementState">Animation state of element.</param>
        /// <returns>Calculated rectangle using provided size.</returns>
        protected Rect RectFromSize(AnimateSize size,
                                    Rect rect,
                                    MetaElementState elementState)
        {
            Size minSize = elementState.Element.DesiredSize;

            switch (size)
            {
                case AnimateSize.Original:
                    return rect;
                case AnimateSize.ZeroWidthLeft:
                    return new Rect(rect.X, rect.Y, minSize.Width, rect.Height);
                case AnimateSize.ZeroWidthCenter:
                    return new Rect(rect.X + ((rect.Width - minSize.Width) / 2), rect.Y, minSize.Width, rect.Height);
                case AnimateSize.ZeroWidthRight:
                    return new Rect(rect.Right - minSize.Width, rect.Y, minSize.Width, rect.Height);
                case AnimateSize.ZeroHeightTop:
                    return new Rect(rect.X, rect.Y, rect.Width, minSize.Height);
                case AnimateSize.ZeroHeightCenter:
                    return new Rect(rect.X, rect.Y + (rect.Height - minSize.Height) / 2, rect.Width, minSize.Height);
                case AnimateSize.ZeroHeightBottom:
                    return new Rect(rect.X, rect.Bottom - minSize.Height, rect.Width, minSize.Height);
                case AnimateSize.ZeroZeroCenter:
                    return new Rect(rect.X + (rect.Width - minSize.Width) / 2, rect.Y + (rect.Height - minSize.Height) / 2, minSize.Width, minSize.Height);
                case AnimateSize.ZeroZeroTopLeft:
                    return new Rect(rect.X, rect.Y, minSize.Width, minSize.Height);
                case AnimateSize.ZeroZeroTopRight:
                    return new Rect(rect.Right - minSize.Width, rect.Y, minSize.Width, minSize.Height);
                case AnimateSize.ZeroZeroBottomLeft:
                    return new Rect(rect.X, rect.Bottom - minSize.Height, minSize.Width, minSize.Height);
                case AnimateSize.ZeroZeroBottomRight:
                    return new Rect(rect.Right - minSize.Width, rect.Bottom - minSize.Height, minSize.Width, minSize.Height);
                default:
                    // Should never happen!
                    Debug.Assert(false);
                    return new Rect();
            }
        }
        /// <summary>
        /// Calculate appropriate rectangle from given current state and target location.
        /// </summary>
        /// <param name="location">Location enumeration.</param>
        /// <param name="metaPanel">Reference to owning panel instance.</param>
        /// <param name="elementState">Animation state of element.</param>
        /// <returns>Calculated rectangle using provided location.</returns>
        protected Rect RectFromLocation(AnimateLocation location,
                                        MetaPanelBase metaPanel,
                                        MetaElementState elementState)
        {
            // Nearest edge is converted into a particular edge
            switch (location)
            {
                case AnimateLocation.NearestEdge:
                case AnimateLocation.NearestEdgePaged:
                    bool paged = (location == AnimateLocation.NearestEdgePaged);

                    // Find distance from each edge
                    double left = Math.Abs(elementState.TargetRect.Left);
                    double top = Math.Abs(elementState.TargetRect.Top);
                    double right = Math.Abs(metaPanel.ActualWidth - elementState.TargetRect.Right);
                    double bottom = Math.Abs(metaPanel.ActualHeight - elementState.TargetRect.Bottom);

                    // Find nearest distance for vertical and horizontal
                    double horz = (left < right ? left : right);
                    double vert = (top < bottom ? top : bottom);

                    // Is horizontal nearest?
                    if (horz <= vert)
                    {
                        // Is the left the nearest?
                        if (horz == left)
                            location = (paged ? AnimateLocation.LeftPaged : AnimateLocation.Left);
                        else
                            location = (paged ? AnimateLocation.RightPaged : AnimateLocation.Right);
                    }
                    else
                    {
                        // Is the top the nearest?
                        if (vert == top)
                            location = (paged ? AnimateLocation.TopPaged : AnimateLocation.Top);
                        else
                            location = (paged ? AnimateLocation.BottomPaged : AnimateLocation.Bottom);
                    }
                    break;
            }

            switch (location)
            {
                case AnimateLocation.Target:
                    return elementState.TargetRect;
                case AnimateLocation.Center:
                    return new Rect((metaPanel.ActualWidth / 2) - (elementState.TargetRect.Width - 2),
                                    (metaPanel.ActualHeight / 2) - (elementState.TargetRect.Height - 2),
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.Top:
                    return new Rect(elementState.TargetRect.X,
                                    -elementState.TargetRect.Height,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.TopPaged:
                    return new Rect(elementState.TargetRect.X,
                                    -metaPanel.ActualHeight + elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.Bottom:
                    return new Rect(elementState.TargetRect.X,
                                    metaPanel.ActualHeight,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.BottomPaged:
                    return new Rect(elementState.TargetRect.X,
                                    metaPanel.ActualHeight + elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.Left:
                    return new Rect(-elementState.TargetRect.Width,
                                    elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.LeftPaged:
                    return new Rect(-metaPanel.ActualWidth + elementState.TargetRect.X,
                                    elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.Right:
                    return new Rect(metaPanel.ActualWidth,
                                    elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.RightPaged:
                    return new Rect(metaPanel.ActualWidth + elementState.TargetRect.X,
                                    elementState.TargetRect.Y,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.TopLeft:
                    return new Rect(-elementState.TargetRect.Width,
                                    -elementState.TargetRect.Height,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.TopRight:
                    return new Rect(metaPanel.ActualWidth,
                                    -elementState.TargetRect.Height,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.BottomLeft:
                    return new Rect(-elementState.TargetRect.Width,
                                    metaPanel.ActualHeight,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                case AnimateLocation.BottomRight:
                    return new Rect(metaPanel.ActualWidth,
                                    metaPanel.ActualHeight,
                                    elementState.TargetRect.Width,
                                    elementState.TargetRect.Height);
                default:
                    // Should never happen!
                    Debug.Assert(false);
                    return new Rect();
            }
        }