Esempio n. 1
0
        private CustomPopupPlacement[] PlacementCallback(Size popup, Size target, Point offset)
        {
            double           x = 0, y = 0;
            double           gap         = Configurations.ToolTipTargetGapInPixels;
            PopupPrimaryAxis primaryAxis = PopupPrimaryAxis.None;

            switch (this.AttachmentSide)
            {
            case Side.Left:
                x           = -(popup.Width + gap);
                y           = (target.Height - popup.Height) * 0.5;
                primaryAxis = PopupPrimaryAxis.Horizontal;
                break;

            case Side.Right:
                x           = target.Width + gap;
                y           = (target.Height - popup.Height) * 0.5;
                primaryAxis = PopupPrimaryAxis.Horizontal;
                break;

            case Side.Top:
                x           = (target.Width - popup.Width) * 0.5;
                y           = -(popup.Height + gap);
                primaryAxis = PopupPrimaryAxis.Vertical;
                break;

            case Side.Bottom:
                x           = (target.Width - popup.Width) * 0.5;
                y           = target.Height + gap;
                primaryAxis = PopupPrimaryAxis.Vertical;
                break;
            }

            return(new CustomPopupPlacement[]
            {
                new CustomPopupPlacement()
                {
                    Point = new Point(x, y),
                    PrimaryAxis = primaryAxis
                }
            });
        }
Esempio n. 2
0
 /// <summary> 
 ///     Constructor
 /// </summary>
 /// <param name="point">Assigns to Point</param>
 /// <param name="primaryAxis">Assigns to PrimaryAxis</param> 
 public CustomPopupPlacement(Point point, PopupPrimaryAxis primaryAxis)
 { 
     _point = point; 
     _primaryAxis = primaryAxis;
 } 
Esempio n. 3
0
        // Returns the ith possible alignment for the given PlacementMode
        private PointCombination GetPointCombination(PlacementMode placement, int i, out PopupPrimaryAxis axis)
        {
            Debug.Assert(i >= 0 && i < GetNumberOfCombinations(placement));

            bool dropFromRight = SystemParameters.MenuDropAlignment;

            switch (placement)
            {
            case PlacementMode.Bottom:
            case PlacementMode.Mouse:
                axis = PopupPrimaryAxis.Horizontal;
                if (dropFromRight)
                {
                    if (i == 0)
                    {
                        return(new PointCombination(InterestPoint.BottomRight, InterestPoint.TopRight));
                    }
                    if (i == 1)
                    {
                        return(new PointCombination(InterestPoint.TopRight, InterestPoint.BottomRight));
                    }
                }
                else
                {
                    if (i == 0)
                    {
                        return(new PointCombination(InterestPoint.BottomLeft, InterestPoint.TopLeft));
                    }
                    if (i == 1)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomLeft));
                    }
                }
                break;


            case PlacementMode.Top:
                axis = PopupPrimaryAxis.Horizontal;
                if (dropFromRight)
                {
                    if (i == 0)
                    {
                        return(new PointCombination(InterestPoint.TopRight, InterestPoint.BottomRight));
                    }
                    if (i == 1)
                    {
                        return(new PointCombination(InterestPoint.BottomRight, InterestPoint.TopRight));
                    }
                }
                else
                {
                    if (i == 0)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomLeft));
                    }
                    if (i == 1)
                    {
                        return(new PointCombination(InterestPoint.BottomLeft, InterestPoint.TopLeft));
                    }
                }
                break;


            case PlacementMode.Right:
            case PlacementMode.Left:
                axis           = PopupPrimaryAxis.Vertical;
                dropFromRight |= DropOpposite;

                if (dropFromRight && placement == PlacementMode.Right ||
                    !dropFromRight && placement == PlacementMode.Left)
                {
                    if (i == 0)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight));
                    }
                    if (i == 1)
                    {
                        return(new PointCombination(InterestPoint.BottomLeft, InterestPoint.BottomRight));
                    }
                    if (i == 2)
                    {
                        return(new PointCombination(InterestPoint.TopRight, InterestPoint.TopLeft));
                    }
                    if (i == 3)
                    {
                        return(new PointCombination(InterestPoint.BottomRight, InterestPoint.BottomLeft));
                    }
                }
                else
                {
                    if (i == 0)
                    {
                        return(new PointCombination(InterestPoint.TopRight, InterestPoint.TopLeft));
                    }
                    if (i == 1)
                    {
                        return(new PointCombination(InterestPoint.BottomRight, InterestPoint.BottomLeft));
                    }
                    if (i == 2)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight));
                    }
                    if (i == 3)
                    {
                        return(new PointCombination(InterestPoint.BottomLeft, InterestPoint.BottomRight));
                    }
                }
                break;

            case PlacementMode.Relative:
            case PlacementMode.RelativePoint:
            case PlacementMode.MousePoint:
            case PlacementMode.AbsolutePoint:
                axis = PopupPrimaryAxis.Horizontal;
                if (dropFromRight)
                {
                    if (i == 0)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight));
                    }
                    if (i == 1)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.TopLeft));
                    }
                    if (i == 2)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomRight));
                    }
                    if (i == 3)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomLeft));
                    }
                }
                else
                {
                    if (i == 0)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.TopLeft));
                    }
                    if (i == 1)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight));
                    }
                    if (i == 2)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomLeft));
                    }
                    if (i == 3)
                    {
                        return(new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomRight));
                    }
                }
                break;

            case PlacementMode.Center:
                axis = PopupPrimaryAxis.None;
                return(new PointCombination(InterestPoint.Center, InterestPoint.Center));

            case PlacementMode.Absolute:
            case PlacementMode.Custom:
            default:
                axis = PopupPrimaryAxis.None;
                return(new PointCombination(InterestPoint.TopLeft, InterestPoint.TopLeft));
            }

            return(new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight));
        }
Esempio n. 4
0
        // To position the popup, we find the InterestPoints of the placement rectangle/point
        // in the screen coordinate space.  We also find the InterestPoints of the child in
        // the popup's space.  Then we attempt all valid combinations of matching InterestPoints
        // (based on PlacementMode) to find the position that best fits on the screen.
        // NOTE: any reference to the screen implies the monitor for full trust and
        //       the browser area for partial trust
        private void UpdatePosition()
        {
            if (_popupRoot == null)
            {
                return;
            }

            PlacementMode placement = PlacementInternal;

            // Get a list of the corners of the target/child in screen space
            Point[] placementTargetInterestPoints = GetPlacementTargetInterestPoints(placement);
            Point[] childInterestPoints           = GetChildInterestPoints(placement);

            // Find bounds of screen and child in screen space
            Rect targetBounds = GetBounds(placementTargetInterestPoints);
            Rect screenBounds;
            Rect childBounds = GetBounds(childInterestPoints);

            double childArea = childBounds.Width * childBounds.Height;

            Rect windowRect = _secHelper.GetWindowRect();

            _positionInfo ??= new PositionInfo();
            _positionInfo.X         = (int)windowRect.X;
            _positionInfo.Y         = (int)windowRect.Y;
            _positionInfo.ChildSize = windowRect.Size;

            // Rank possible positions
            int              bestIndex       = -1;
            Vector           bestTranslation = new Vector(_positionInfo.X, _positionInfo.Y);
            double           bestScore       = -1;
            PopupPrimaryAxis bestAxis        = PopupPrimaryAxis.None;

            int positions;

            CustomPopupPlacement[] customPlacements = null;

            // Find the number of possible positions
            if (placement == PlacementMode.Custom)
            {
                CustomPopupPlacementCallback customCallback = CustomPopupPlacementCallback;
                if (customCallback != null)
                {
                    customPlacements = customCallback(childBounds.Size, targetBounds.Size, new Point(HorizontalOffset, VerticalOffset));
                }
                positions = customPlacements == null ? 0 : customPlacements.Length;

                // Return if callback closed the popup
                if (!IsOpen)
                {
                    return;
                }
            }
            else
            {
                positions = GetNumberOfCombinations(placement);
            }

            // Try each position until the best one is found
            for (int i = 0; i < positions; i++)
            {
                Vector popupTranslation;

                PopupPrimaryAxis axis;

                // Get the ith Position to rank
                if (placement == PlacementMode.Custom)
                {
                    // The custom callback only calculates relative to 0,0
                    // so the placementTarget's top/left need to be re-applied.
                    popupTranslation = (Vector)placementTargetInterestPoints[(int)InterestPoint.TopLeft]
                                       + (Vector)customPlacements[i].Point; // vector from origin

                    axis = customPlacements[i].PrimaryAxis;
                }
                else
                {
                    PointCombination pointCombination = GetPointCombination(placement, i, out axis);

                    InterestPoint targetInterestPoint = pointCombination.TargetInterestPoint;
                    InterestPoint childInterestPoint  = pointCombination.ChildInterestPoint;

                    // Compute the vector from the screen origin to the top left corner of the popup
                    // that will cause the the two interest points to overlap
                    popupTranslation = placementTargetInterestPoints[(int)targetInterestPoint]
                                       - childInterestPoints[(int)childInterestPoint];
                }

                // Find percent of popup on screen by translating the popup bounds
                // and calculating the percent of the bounds that is on screen
                // Note: this score is based on the percent of the popup that is on screen
                //       not the percent of the child that is on screen.  For certain
                //       scenarios, this may produce in counter-intuitive results.
                //       If this is a problem, more complex scoring is needed
                Rect tranlsatedChildBounds = Rect.Offset(childBounds, popupTranslation);
                screenBounds = GetScreenBounds(targetBounds, placementTargetInterestPoints[(int)InterestPoint.TopLeft]);
                Rect currentIntersection = Rect.Intersect(screenBounds, tranlsatedChildBounds);

                // Calculate area of intersection
                double score = currentIntersection != Rect.Empty ? currentIntersection.Width * currentIntersection.Height : 0;

                // If current score is better than the best score so far, save the position info
                if (score - bestScore > Tolerance)
                {
                    bestIndex       = i;
                    bestTranslation = popupTranslation;
                    bestScore       = score;
                    bestAxis        = axis;

                    // Stop when we find a popup that is completely on screen
                    if (Math.Abs(score - childArea) < Tolerance)
                    {
                        break;
                    }
                }
            }

            // Check to see if the pop needs to be nudged onto the screen.
            // Popups are not nudged if their axes do not align with the screen axes

            // Use the size of the popupRoot in case it is clipping the popup content
            Matrix transformToDevice = _secHelper.GetTransformToDevice();

            childBounds = new Rect((Size)transformToDevice.Transform((Point)GetChildSize()));

            childBounds.Offset(bestTranslation);

            Vector childTranslation = (Vector)transformToDevice.Transform(GetChildTranslation());

            childBounds.Offset(childTranslation);

            screenBounds = GetScreenBounds(targetBounds, placementTargetInterestPoints[(int)InterestPoint.TopLeft]);
            Rect intersection = Rect.Intersect(screenBounds, childBounds);

            // See if width/height of intersection are less than child's
            if (Math.Abs(intersection.Width - childBounds.Width) > Tolerance ||
                Math.Abs(intersection.Height - childBounds.Height) > Tolerance)
            {
                // Nudge Horizontally
                Point topLeft  = placementTargetInterestPoints[(int)InterestPoint.TopLeft];
                Point topRight = placementTargetInterestPoints[(int)InterestPoint.TopRight];

                // Create a vector pointing from the top of the placement target to the bottom
                // to determine which direction the popup should be nudged in.
                // If the vector is zero (NaN's after normalization), nudge horizontally
                Vector horizontalAxis = topRight - topLeft;
                horizontalAxis.Normalize();

                // See if target's horizontal axis is aligned with screen
                // (For opaque windows always translate horizontally)
                if (!IsTransparent || double.IsNaN(horizontalAxis.Y) || Math.Abs(horizontalAxis.Y) < Tolerance)
                {
                    // Nudge horizontally
                    if (childBounds.Right > screenBounds.Right)
                    {
                        bestTranslation.X  = screenBounds.Right - childBounds.Width;
                        bestTranslation.X -= childTranslation.X;
                    }
                    else if (childBounds.Left < screenBounds.Left)
                    {
                        bestTranslation.X  = screenBounds.Left;
                        bestTranslation.X -= childTranslation.X;
                    }
                }
                else if (IsTransparent && Math.Abs(horizontalAxis.X) < Tolerance)
                {
                    // Nudge vertically, limit horizontally
                    if (childBounds.Bottom > screenBounds.Bottom)
                    {
                        bestTranslation.Y  = screenBounds.Bottom - childBounds.Height;
                        bestTranslation.Y -= childTranslation.Y;
                    }
                    else if (childBounds.Top < screenBounds.Top)
                    {
                        bestTranslation.Y  = screenBounds.Top;
                        bestTranslation.Y -= childTranslation.Y;
                    }
                }

                // Nudge Vertically
                Point bottomLeft = placementTargetInterestPoints[(int)InterestPoint.BottomLeft];

                // Create a vector pointing from the top of the placement target to the bottom
                // to determine which direction the popup should be nudged in
                // If the vector is zero (NaN's after normalization), nudge vertically
                Vector verticalAxis = topLeft - bottomLeft;
                verticalAxis.Normalize();

                // Axis is aligned with screen, nudge
                if (!IsTransparent || double.IsNaN(verticalAxis.X) || Math.Abs(verticalAxis.X) < Tolerance)
                {
                    if (childBounds.Bottom > screenBounds.Bottom)
                    {
                        bestTranslation.Y  = screenBounds.Bottom - childBounds.Height;
                        bestTranslation.Y -= childTranslation.Y;
                    }
                    else if (childBounds.Top < screenBounds.Top)
                    {
                        bestTranslation.Y  = screenBounds.Top;
                        bestTranslation.Y -= childTranslation.Y;
                    }
                }
                else if (IsTransparent && Math.Abs(verticalAxis.Y) < Tolerance)
                {
                    if (childBounds.Right > screenBounds.Right)
                    {
                        bestTranslation.X  = screenBounds.Right - childBounds.Width;
                        bestTranslation.X -= childTranslation.X;
                    }
                    else if (childBounds.Left < screenBounds.Left)
                    {
                        bestTranslation.X  = screenBounds.Left;
                        bestTranslation.X -= childTranslation.X;
                    }
                }
            }

            // Finally, take the best position and apply it to the popup
            int bestX = DoubleUtil.DoubleToInt(bestTranslation.X);
            int bestY = DoubleUtil.DoubleToInt(bestTranslation.Y);

            if (bestX != _positionInfo.X || bestY != _positionInfo.Y)
            {
                _positionInfo.X = bestX;
                _positionInfo.Y = bestY;
                _secHelper.SetPopupPos(true, bestX, bestY, false, 0, 0);
            }

            Size GetChildSize()
            {
                if (_popup.Child is { } child)
                {
                    return(child.RenderSize);
                }
                return(_popupRoot.RenderSize);
            }

            Point GetChildTranslation()
            {
                if (_popup.Child is { } child)
                {
                    return(child.TranslatePoint(new Point(), _popupRoot));
                }
                return(new Point());
            }
        }
 public CustomPopupPlacement(System.Windows.Point point, PopupPrimaryAxis primaryAxis)
 {
 }
Esempio n. 6
0
 /// <summary>Initializes a new instance of the <see cref="T:System.Windows.Controls.Primitives.CustomPopupPlacement" /> structure.</summary>
 /// <param name="point">The <see cref="T:System.Windows.Point" /> that is relative to the <see cref="P:System.Windows.Controls.Primitives.Popup.PlacementTarget" /> where the upper-left corner of the <see cref="T:System.Windows.Controls.Primitives.Popup" /> is placed.</param>
 /// <param name="primaryAxis">The <see cref="T:System.Windows.Controls.Primitives.PopupPrimaryAxis" /> along which a <see cref="T:System.Windows.Controls.Primitives.Popup" /> control moves when it is obstructed by a screen edge.</param>
 // Token: 0x06005C81 RID: 23681 RVA: 0x001A08A4 File Offset: 0x0019EAA4
 public CustomPopupPlacement(Point point, PopupPrimaryAxis primaryAxis)
 {
     this._point       = point;
     this._primaryAxis = primaryAxis;
 }
Esempio n. 7
0
        // Returns the ith possible alignment for the given PlacementMode
        private PointCombination GetPointCombination(PlacementMode placement, int i, out PopupPrimaryAxis axis)
        {
            Debug.Assert(i >= 0 && i < GetNumberOfCombinations(placement));

            bool dropFromRight = SystemParameters.MenuDropAlignment;

            switch (placement)
            {
                case PlacementMode.Bottom:
                case PlacementMode.Mouse:
                    axis = PopupPrimaryAxis.Horizontal;
                    if (dropFromRight)
                    {
                        if (i == 0) return new PointCombination(InterestPoint.BottomRight, InterestPoint.TopRight);
                        if (i == 1) return new PointCombination(InterestPoint.TopRight, InterestPoint.BottomRight);
                    }
                    else
                    {
                        if (i == 0) return new PointCombination(InterestPoint.BottomLeft, InterestPoint.TopLeft);
                        if (i == 1) return new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomLeft);
                    }
                    break;


                case PlacementMode.Top:
                    axis = PopupPrimaryAxis.Horizontal;
                    if (dropFromRight)
                    {
                        if (i == 0) return new PointCombination(InterestPoint.TopRight, InterestPoint.BottomRight);
                        if (i == 1) return new PointCombination(InterestPoint.BottomRight, InterestPoint.TopRight);

                    }
                    else
                    {
                        if (i == 0) return new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomLeft);
                        if (i == 1) return new PointCombination(InterestPoint.BottomLeft, InterestPoint.TopLeft);

                    }
                    break;


                case PlacementMode.Right:
                case PlacementMode.Left:
                    axis = PopupPrimaryAxis.Vertical;
                    dropFromRight |= DropOpposite;

                    if ((dropFromRight && placement == PlacementMode.Right) ||
                        (!dropFromRight && placement == PlacementMode.Left))
                    {
                        if (i == 0) return new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight);
                        if (i == 1) return new PointCombination(InterestPoint.BottomLeft, InterestPoint.BottomRight);
                        if (i == 2) return new PointCombination(InterestPoint.TopRight, InterestPoint.TopLeft);
                        if (i == 3) return new PointCombination(InterestPoint.BottomRight, InterestPoint.BottomLeft);
                    }
                    else
                    {
                        if (i == 0) return new PointCombination(InterestPoint.TopRight, InterestPoint.TopLeft);
                        if (i == 1) return new PointCombination(InterestPoint.BottomRight, InterestPoint.BottomLeft);
                        if (i == 2) return new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight);
                        if (i == 3) return new PointCombination(InterestPoint.BottomLeft, InterestPoint.BottomRight);
                    }
                    break;

                case PlacementMode.Relative:
                case PlacementMode.RelativePoint:
                case PlacementMode.MousePoint:
                case PlacementMode.AbsolutePoint:
                    axis = PopupPrimaryAxis.Horizontal;
                    if (dropFromRight)
                    {
                        if (i == 0) return new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight);
                        if (i == 1) return new PointCombination(InterestPoint.TopLeft, InterestPoint.TopLeft);
                        if (i == 2) return new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomRight);
                        if (i == 3) return new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomLeft);
                    }
                    else
                    {
                        if (i == 0) return new PointCombination(InterestPoint.TopLeft, InterestPoint.TopLeft);
                        if (i == 1) return new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight);
                        if (i == 2) return new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomLeft);
                        if (i == 3) return new PointCombination(InterestPoint.TopLeft, InterestPoint.BottomRight);
                    }
                    break;

                case PlacementMode.Center:
                    axis = PopupPrimaryAxis.None;
                    return new PointCombination(InterestPoint.Center, InterestPoint.Center);

                case PlacementMode.Absolute:
                case PlacementMode.Custom:
                default:
                    axis = PopupPrimaryAxis.None;
                    return new PointCombination(InterestPoint.TopLeft, InterestPoint.TopLeft);
            }

            return new PointCombination(InterestPoint.TopLeft, InterestPoint.TopRight);
        }
Esempio n. 8
0
 public CustomPopupPlacement(System.Windows.Point point, PopupPrimaryAxis primaryAxis)
 {
 }