public void ArrangePopup(Popup ElementPopup, 
                                Canvas ElementPopupChildCanvas, 
                                Canvas ElementOutsidePopup, 
                                FrameworkElement ElementPopupChild, 
                                ContentControl LeaderPopupContent, 
                                StackPanel ElementPopupChildMaxRangeStackPanel,
                                Control AssociatedControl,
                                ExpandDirection ExpandDirection,
                                bool EnforceMinWidth = true,
                                bool isNestedPopup = true
                            )
        {
            if (ElementPopup != null && AssociatedControl != null)
            {
                bool isRTL = (AssociatedControl.FlowDirection == FlowDirection.RightToLeft);
                System.Windows.Interop.Content content = System.Windows.Application.Current.Host.Content;
                double applicationWidth = content.ActualWidth;
                double applicationHeight = content.ActualHeight;
                double popupWidth = ElementPopupChild.ActualWidth;
                double popupHeight = ElementPopupChild.ActualHeight;
                if ((applicationHeight != 0.0) && (applicationWidth != 0.0))
                {
                    GeneralTransform transform = AssociatedControl.TransformToVisual(null);
                    if (isRTL && transform is MatrixTransform)
                    {
                        var mt = (MatrixTransform) transform;
                        transform = new MatrixTransform
                                            {
                                                Matrix = new Matrix
                                                             {
                                                                 M11 = mt.Matrix.M11,
                                                                 M12 = mt.Matrix.M12,
                                                                 M21 = mt.Matrix.M21,
                                                                 M22 = mt.Matrix.M22,
                                                                 OffsetX = mt.Matrix.OffsetX - AssociatedControl.ActualWidth,
                                                                 OffsetY = mt.Matrix.OffsetY,
                                                             }
                                            };
                    }
                    if (transform != null)
                    {
                        Point topLeftTransPoint = new Point(0.0, 0.0);
                        Point topRightTransPoint = new Point(1.0, 0.0);
                        Point bottomLeftTransPoint = new Point(0.0, 1.0);
                        Point topLeftPosition = transform.Transform(topLeftTransPoint);
                        Point topRightPosition = transform.Transform(topRightTransPoint);
                        Point bottomLeftPosition = transform.Transform(bottomLeftTransPoint);
                        double xDropDown = topLeftPosition.X;
                        double yDropDown = topLeftPosition.Y;
                        double widthRatio = Math.Abs((double)(topRightPosition.X - topLeftPosition.X));
                        double heightRatio = Math.Abs((double)(bottomLeftPosition.Y - topLeftPosition.Y));
                        double heightDropDown = AssociatedControl.ActualHeight * heightRatio;
                        double widthDropDown = AssociatedControl.ActualWidth * widthRatio;
                        double yBottomDropDown = yDropDown + heightDropDown;
                        if ((heightDropDown != 0.0) && (widthDropDown != 0.0))
                        {
                            popupWidth *= widthRatio;
                            popupHeight *= heightRatio;
                            double maxDropDownHeight = double.PositiveInfinity;
                            if (ExpandDirection == ExpandDirection.BottomLeft)
                            {
                                if (double.IsInfinity(maxDropDownHeight) || double.IsNaN(maxDropDownHeight))
                                    maxDropDownHeight = ((applicationHeight - heightDropDown) * 3.0) / 5.0;
                                bool flag = true;
                                if (applicationHeight < (yBottomDropDown + popupHeight))
                                {
                                    flag = false;
                                    yBottomDropDown = yDropDown - popupHeight;
                                    if (yBottomDropDown < 0.0)
                                    {
                                        if (yDropDown < ((applicationHeight - heightDropDown) / 2.0))
                                        {
                                            flag = true;
                                            yBottomDropDown = yDropDown + heightDropDown;
                                        }
                                        else
                                        {
                                            flag = false;
                                            yBottomDropDown = yDropDown - popupHeight;
                                        }
                                    }
                                }
                                if (popupHeight != 0.0)
                                {
                                    if (flag)
                                        maxDropDownHeight = Math.Min(applicationHeight - yBottomDropDown, maxDropDownHeight);
                                    else
                                        maxDropDownHeight = Math.Min(yDropDown, maxDropDownHeight);
                                }
                            }
                            else
                            {
                                if (double.IsInfinity(maxDropDownHeight) || double.IsNaN(maxDropDownHeight))
                                    maxDropDownHeight = applicationHeight - 2 * RIGHT_CENTER_TOP_BOTTOM_MARGIN;
                            }
                            popupWidth = Math.Min(popupWidth, applicationWidth);
                            popupHeight = Math.Min(popupHeight, maxDropDownHeight);
                            popupWidth = Math.Max(widthDropDown, popupWidth);
                            double applicationRemainWidth = 0.0;
                            double leaderWidth = GetFrameworkElementWidth(LeaderPopupContent);
                            if (double.IsNaN(leaderWidth) || double.IsInfinity(leaderWidth))
                                leaderWidth = 0;

                            if (AssociatedControl.FlowDirection == FlowDirection.LeftToRight)
                            {
                                if (applicationWidth < (xDropDown + popupWidth))
                                    applicationRemainWidth = applicationWidth - (popupWidth + xDropDown);
                            }
                            else if (0.0 > (xDropDown - popupWidth))
                                applicationRemainWidth = xDropDown - popupWidth;

                            ElementPopup.HorizontalOffset = 0.0;
                            ElementPopup.VerticalOffset = 0.0;

                            Matrix identity = Matrix.Identity;
                            identity.OffsetX -= topLeftPosition.X / widthRatio;
                            identity.OffsetY -= topLeftPosition.Y / heightRatio;
                            MatrixTransform transform2 = new MatrixTransform();
                            transform2.Matrix = identity;

                            if (ElementOutsidePopup != null)
                            {
                                ElementOutsidePopup.Width = applicationWidth / widthRatio;
                                ElementOutsidePopup.Height = applicationHeight / heightRatio;
                                ElementOutsidePopup.RenderTransform = transform2;
                            }

                            double minWidthDropDown = 0.0;
                            if (EnforceMinWidth)
                            {
                                minWidthDropDown = widthDropDown / widthRatio;
                                ElementPopupChild.MinWidth = minWidthDropDown;
                            }

                            double maxPopupWidth = double.PositiveInfinity;
                            bool reversePopupExpandDirection = false;
                            if (ExpandDirection == ExpandDirection.BottomLeft)
                                maxPopupWidth = applicationWidth / widthRatio;
                            else
                            {
                                maxPopupWidth = applicationWidth - (xDropDown + widthDropDown) - leaderWidth;
                                maxPopupWidth = maxPopupWidth / widthRatio;

                                if (maxPopupWidth < popupWidth)
                                {
                                    double tempMaxPopupWidth;
                                    //try show on the other side
                                    tempMaxPopupWidth = xDropDown - leaderWidth;
                                    if (tempMaxPopupWidth >= 0 && tempMaxPopupWidth > maxPopupWidth)
                                    {
                                        maxPopupWidth = tempMaxPopupWidth;
                                        reversePopupExpandDirection = true;
                                    }
                                }
                            }

                            ElementPopupChild.MaxWidth = Math.Max(minWidthDropDown, maxPopupWidth);
                            ElementPopupChild.MinHeight = heightDropDown / heightRatio;
                            ElementPopupChild.MaxHeight = Math.Max((double)0.0, (double)(maxDropDownHeight / heightRatio));
                            ElementPopupChild.HorizontalAlignment = HorizontalAlignment.Left;
                            ElementPopupChild.VerticalAlignment = VerticalAlignment.Top;
                            ElementPopupChild.FlowDirection = AssociatedControl.FlowDirection;

                            if (ElementPopupChildMaxRangeStackPanel != null) //if horizontal central alignment, then simply reuse the maxrange canvas and align within
                            {
                                double top = isNestedPopup ? (heightDropDown - popupHeight) / 2 : Math.Max(0.0, yDropDown + (heightDropDown - popupHeight) / 2);
                                double overflow = Math.Abs(Math.Min(applicationHeight - (yDropDown + (yBottomDropDown - yDropDown) / 2 + popupHeight / 2 + RIGHT_CENTER_TOP_BOTTOM_MARGIN), 0.0));
                                if (overflow > 0)
                                {
                                    top -= overflow; //move up if overflowing underneath
                                }
                                top = Math.Max(top, -yDropDown + RIGHT_CENTER_TOP_BOTTOM_MARGIN); //did our best to calculate top, so set to top or application level x=0

                                Canvas.SetTop(ElementPopupChildMaxRangeStackPanel, top);
                                ElementPopupChildMaxRangeStackPanel.Width = maxPopupWidth;
                                ElementPopupChildMaxRangeStackPanel.Height = popupHeight;

                                if (isRTL && isNestedPopup)
                                    reversePopupExpandDirection = !reversePopupExpandDirection;

                                if (reversePopupExpandDirection)
                                    Canvas.SetLeft(ElementPopupChildMaxRangeStackPanel, isNestedPopup ? -xDropDown : 0);
                                else
                                {
                                    Canvas.SetLeft(ElementPopupChildMaxRangeStackPanel, (isNestedPopup ? 0: xDropDown) + AssociatedControl.ActualWidth + leaderWidth);
                                }

                                if (reversePopupExpandDirection)
                                    ElementPopupChild.HorizontalAlignment = HorizontalAlignment.Right;
                                
                                SetupLeader(LeaderPopupContent, ElementPopupChildMaxRangeStackPanel, reversePopupExpandDirection, xDropDown, yDropDown, heightDropDown, ExpandDirection, AssociatedControl, isNestedPopup);
                            }
                            else
                            {
                                SetPopupTop(ElementPopupChild, yBottomDropDown, heightRatio, yDropDown, popupHeight, applicationHeight, ExpandDirection);
                                SetPopupLeft(ElementPopupChild, applicationRemainWidth, widthRatio, popupWidth, maxPopupWidth, reversePopupExpandDirection, ExpandDirection, AssociatedControl, xDropDown);
                                SetupLeader(LeaderPopupContent, ElementPopupChild, reversePopupExpandDirection, xDropDown, yDropDown, heightDropDown, ExpandDirection, AssociatedControl, isNestedPopup);
                            }
                        }
                    }
                }
            }
        }
        public void GemButtonClick(Item gem, Control relativeTo, Action<Item> callback)
        {
            gemCallback = null;
            ComparisonGemList.SelectedItem = gem;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            GemPopup.VerticalOffset = offset.Y;
            GemPopup.HorizontalOffset = offset.X;

            ComparisonGemList.Measure(App.Current.RootVisual.RenderSize);

            // this doesn't work in WPF
            // The specified Visual and this Visual do not share a common ancestor, so there is no valid transformation between the two Visuals.
#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonGemList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                GemPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            GemPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonGemList.IsShown = true;
            GemPopup.IsOpen = true;
            ComparisonGemList.Focus();
            gemCallback = callback;
        }
        public void MetaButtonClick(Item meta, Control relativeTo, Action<Item> callback)
        {
            metaCallback = null;
            ComparisonMetaList.SelectedItem = meta;

            GeneralTransform gt = relativeTo.TransformToVisual(LayoutRoot);
            Point offset = gt.Transform(new Point(relativeTo.ActualWidth + 4, 0));
            MetaPopup.VerticalOffset = offset.Y;
            MetaPopup.HorizontalOffset = offset.X;

            ComparisonMetaList.Measure(App.Current.RootVisual.RenderSize);

#if SILVERLIGHT
            GeneralTransform transform = relativeTo.TransformToVisual(App.Current.RootVisual);
            double distBetweenBottomOfPopupAndBottomOfWindow =
                App.Current.RootVisual.DesiredSize.Height -
                transform.Transform(new Point(0, ComparisonMetaList.DesiredSize.Height)).Y;
            if (distBetweenBottomOfPopupAndBottomOfWindow < 0)
            {
                MetaPopup.VerticalOffset += distBetweenBottomOfPopupAndBottomOfWindow;
            }
#else
            // use PlacementTarget for WPF
            GemPopup.PlacementTarget = LayoutRoot;
#endif

            ComparisonMetaList.IsShown = true;
            MetaPopup.IsOpen = true;
            ComparisonMetaList.Focus();
            metaCallback = callback;
        }
        private static Point GetPopupLocation(Control parent)
        {
            var transform = parent.TransformToVisual(Application.Current.RootVisual);
            var location = transform.Transform(new Point(parent.ActualWidth, 0));

            return new Point(location.X + 8, location.Y - 28);
        }