/// <summary> /// RibbonToolTip custom placement logic /// </summary> /// <param name="popupSize">The size of the popup.</param> /// <param name="targetSize">The size of the placement target.</param> /// <param name="offset">The Point computed from the HorizontalOffset and VerticalOffset property values.</param> /// <returns>An array of possible tooltip placements.</returns> private CustomPopupPlacement[] PlaceRibbonToolTip(Size popupSize, Size targetSize, Point offset) { UIElement placementTarget = this.PlacementTarget; double belowOffsetY = 0.0; double aboveOffsetY = 0.0; double offsetX = FlowDirection == FlowDirection.LeftToRight ? 0.0 : -popupSize.Width; if (IsPlacementTargetInRibbonGroup) { // If the PlacementTarget is within a RibbonGroup we proceed // with the custom placement policy. // Walk up the visual tree from PlacementTarget to find the Ribbon // if exists or the root element which is likely a PopupRoot. Ribbon ribbon = null; DependencyObject rootElement = null; DependencyObject element = placementTarget; while (element != null) { ribbon = element as Ribbon; if (ribbon != null) { break; } rootElement = element; element = VisualTreeHelper.GetParent(element); } double additionalOffset = 1.0; FrameworkElement referenceFE = null; if (ribbon != null) { additionalOffset = 0.0; referenceFE = ribbon; } else { if (rootElement != null) { referenceFE = rootElement as FrameworkElement; } } if (referenceFE != null) { // When RibbonControl (PlacementTarget) is within a collapsed group RibbonToolTip is // placed just below the Popup or just above the Popup (in case there is not enough // screen space left below the Popup). MatrixTransform transform = referenceFE.TransformToDescendant(placementTarget) as MatrixTransform; if (transform != null) { MatrixTransform deviceTransform = new MatrixTransform(RibbonHelper.GetTransformToDevice(referenceFE)); GeneralTransformGroup transformGroup = new GeneralTransformGroup(); transformGroup.Children.Add(transform); transformGroup.Children.Add(deviceTransform); Point leftTop, rightBottom; transformGroup.TryTransform(new Point(0, 0), out leftTop); transformGroup.TryTransform(new Point(referenceFE.ActualWidth, referenceFE.ActualHeight), out rightBottom); belowOffsetY = rightBottom.Y + additionalOffset; aboveOffsetY = leftTop.Y - popupSize.Height - additionalOffset; } } } else { // If PlacementTarget isn't within a RibbonGroup we shouldn't have // gotten here in the first place. But now that we are we will make // the best attempt at emulating PlacementMode.Bottom. FrameworkElement placementTargetAsFE = placementTarget as FrameworkElement; if (placementTargetAsFE != null) { belowOffsetY = targetSize.Height; aboveOffsetY = -popupSize.Height; } } // This is the prefered placement, below the ribbon for controls within Ribbon or below the Popup for controls within Popup. CustomPopupPlacement placementPreffered = new CustomPopupPlacement(new Point(offsetX, belowOffsetY), PopupPrimaryAxis.Horizontal); // This is a fallback placement, if the tooltip will not fit below the ribbon or Popup, place it above the ribbon or Popup. CustomPopupPlacement placementFallback = new CustomPopupPlacement(new Point(offsetX, aboveOffsetY), PopupPrimaryAxis.Horizontal); return(new CustomPopupPlacement[] { placementPreffered, placementFallback }); }