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); }