public static bool ResizePopup(FrameworkElement itemsPresenter, Size minDropDownSize, bool canUserResizeHorizontally, bool canUserResizeVertically, bool isDropDownPositionedLeft, bool isDropDownPositionedAbove, Rect screenBounds, UIElement popupRoot, double horizontalDelta, double verticalDelta) { if (itemsPresenter != null) { verticalDelta = isDropDownPositionedAbove ? (-verticalDelta) : verticalDelta; horizontalDelta = isDropDownPositionedLeft ? (-horizontalDelta) : horizontalDelta; Rect rootScreenBounds = new Rect(popupRoot.PointToScreen(new Point()), popupRoot.PointToScreen(new Point(popupRoot.RenderSize.Width, popupRoot.RenderSize.Height))); // There is a bug in .net3.5 in PopupRoot. When a Popup reaches a screen edge its size is restricted in both dimensions, // regardless of which dimension is at the screen edge. // If Popup is at bottom screen edge and you try to increase width horizontally, // the contents increase in size but get clipped by the Popup. This has been fixed in 4.0. // To workaround this bug, we dont allow Popup to ever go beyond top/bottom screen edge via resizing // Note that Popup could still hit screen edge even before resizing, when Popup is opened for the first time. // This will cause clipping but we are not going to workaround this case. // Case 1: Popup is already at screen edge. // So we want to ignore the delta if trying to increase in direction of screen edge. bool isAtBottomScreenEdge = DoubleUtil.GreaterThanOrClose(rootScreenBounds.Bottom, screenBounds.Bottom); bool isAtTopScreenEdge = DoubleUtil.LessThanOrClose(rootScreenBounds.Top, screenBounds.Top + TopScreenEdgeBuffer); bool isAtRightScreenEdge = DoubleUtil.GreaterThanOrClose(rootScreenBounds.Right, screenBounds.Right); bool isAtLeftScreenEdge = DoubleUtil.LessThanOrClose(rootScreenBounds.Left, screenBounds.Left); // Case 2: If applying the deltas will make popup go over the screen edge. // Truncate delta to whatever is remaining until the screen edge. bool isAlmostAtBottomScreenEdge = DoubleUtil.GreaterThanOrClose(rootScreenBounds.Bottom + verticalDelta, screenBounds.Bottom); bool isAlmostAtTopScreenEdge = DoubleUtil.LessThanOrClose(rootScreenBounds.Top - verticalDelta, screenBounds.Top + TopScreenEdgeBuffer); bool isAlmostAtRightScreenEdge = DoubleUtil.GreaterThanOrClose(rootScreenBounds.Right + horizontalDelta, screenBounds.Right); bool isAlmostAtLeftScreenEdge = DoubleUtil.LessThanOrClose(rootScreenBounds.Left - horizontalDelta, screenBounds.Left); if (isDropDownPositionedAbove) { if (isAtTopScreenEdge && DoubleUtil.GreaterThanOrClose(verticalDelta, 0)) { verticalDelta = 0; } else if (isAlmostAtTopScreenEdge) { verticalDelta = rootScreenBounds.Top - TopScreenEdgeBuffer; } } else if (!isDropDownPositionedAbove) { if (isAtBottomScreenEdge && DoubleUtil.GreaterThanOrClose(verticalDelta, 0)) { verticalDelta = 0; } else if (isAlmostAtBottomScreenEdge) { verticalDelta = screenBounds.Bottom - rootScreenBounds.Bottom; } } // We need this check because WPF Popup's can render only on single monitor. // (i.e. wont extend to second monitor in multi-mon setup). if (isAtRightScreenEdge && DoubleUtil.GreaterThanOrClose(horizontalDelta, 0)) { horizontalDelta = 0; } else if (isAlmostAtRightScreenEdge) { horizontalDelta = screenBounds.Right - rootScreenBounds.Right; } if (isAtLeftScreenEdge && DoubleUtil.GreaterThanOrClose(horizontalDelta, 0)) { horizontalDelta = 0; } else if (isAlmostAtLeftScreenEdge) { horizontalDelta = rootScreenBounds.Left - screenBounds.Left; } double newWidth = itemsPresenter.Width + horizontalDelta; double newHeight = itemsPresenter.Height + verticalDelta; return(ResizePopupActual(itemsPresenter, minDropDownSize, canUserResizeHorizontally, canUserResizeVertically, newWidth, newHeight)); } return(false); }
/// <summary> /// Measures all of the RibbonGroups, and asks them to resize themselves appropriately /// to fit within the available room in the GroupsContainer. /// </summary> /// <param name="availableSize">The available size that this element can give to child elements.</param> /// <returns> /// The size that the groups container determines it needs during layout, based /// on its calculations of child element sizes. /// </returns> protected override Size MeasureOverride(Size availableSize) { RibbonTab ribbonTab = ParentRibbonTab; double remainingSpace = 0; Size desiredSize = BasicMeasure(availableSize, out remainingSpace); UIElementCollection children = InternalChildren; if (children.Count != _cachedChildCount) { ResetNextIncreaseGroupCache(); _cachedChildCount = children.Count; } if (DoubleUtil.GreaterThan(remainingSpace, 0)) { // nudging the positive remaining space by a pixel // protects against aggregation of double errors and // provides a better appreance. remainingSpace = Math.Max(0, remainingSpace - 1); } if ((DoubleUtil.GreaterThanOrClose(_cachedRemainingSpace, 0) && (DoubleUtil.LessThan(remainingSpace, 0) || DoubleUtil.GreaterThan(remainingSpace, _cachedRemainingSpace))) || (DoubleUtil.LessThan(_cachedRemainingSpace, 0) && DoubleUtil.GreaterThan(remainingSpace, 0))) { if (ribbonTab != null) { double?lastPreIncreaseRemainingSpace = null; while (DoubleUtil.GreaterThan(remainingSpace, 0)) { // When there is remaining space try to give it // to stars, which qualify to increase before // next group resize. desiredSize = StarMeasure(availableSize, desiredSize, ribbonTab, ref remainingSpace); // When there is more remaining space, increase // the size of the next group. if (DoubleUtil.GreaterThan(remainingSpace, 0)) { if (double.IsNaN(_nextGroupIncreaseWidth) || DoubleUtil.GreaterThanOrClose(remainingSpace, _nextGroupIncreaseWidth)) { if (ribbonTab.IncreaseNextGroupSize()) { ResetNextIncreaseGroupCache(); lastPreIncreaseRemainingSpace = remainingSpace; desiredSize = BasicMeasure(availableSize, out remainingSpace); } else { break; } } else { break; } } } double preDecreaseGroupRemainingSpace = remainingSpace; while (DoubleUtil.LessThan(remainingSpace, 0)) { // When the remaining space is negative decrease the // next groups size. if (ribbonTab.DecreaseNextGroupSize()) { desiredSize = BasicMeasure(availableSize, out remainingSpace); if (lastPreIncreaseRemainingSpace != null) { // Though in most of the cases we expect that the desired size of the // entire subtree is up to date synchronously, there are some cases where desired // size of subtree gets updated asynchronously(eg. where bindings // impacting desired size resolve at a later time). To gaurd against infinite // loops in such cases, if this decrease operation is to compensate any unnecessary // increase operation performed above, then use the remaining space // computed before such corresponding unnecessary increase operation, instead // of the value computed post decrease which may be inaccurate due to some // pending async updates. On the other hand if the group remains in // same stage and when such async update happens at a later point of time, // this measure would be executed again and hence fixing things. remainingSpace = lastPreIncreaseRemainingSpace.Value; // The remaining space needed to successfully perform the // preceeding group increase without needing to do a compensating // group decrease is cached to be used to optimize out the // unsuccessful group size increases on further increase // in remaining space. _nextGroupIncreaseWidth = lastPreIncreaseRemainingSpace.Value - preDecreaseGroupRemainingSpace; lastPreIncreaseRemainingSpace = null; } else { ResetNextIncreaseGroupCache(); } if (DoubleUtil.GreaterThan(remainingSpace, 0)) { // Now if there is remaining space, give it to the // qualified stars. desiredSize = StarMeasure(availableSize, desiredSize, ribbonTab, ref remainingSpace); } } else { break; } } } } else if (DoubleUtil.GreaterThan(remainingSpace, 0)) { desiredSize = StarMeasure(availableSize, desiredSize, ribbonTab, ref remainingSpace); } _cachedRemainingSpace = remainingSpace; //// Scroll if not enough space return(desiredSize); }
/// <summary> /// This method implement the core algorithm to check whether a point is within a polygon /// that are formed by the lasso points. /// </summary> /// <param name="point"></param> /// <returns>true if the point is contained within the lasso; false otherwise </returns> internal bool Contains(Point point) { System.Diagnostics.Debug.Assert(_points != null); if (false == _bounds.Contains(point)) { return(false); } bool isHigher = false; int last = _points.Count; while (--last >= 0) { if (!DoubleUtil.AreClose(_points[last].Y, point.Y)) { isHigher = (point.Y < _points[last].Y); break; } } bool isInside = false; Point prevLassoPoint = _points[_points.Count - 1]; for (int i = 0; i < _points.Count; i++) { Point lassoPoint = _points[i]; if (DoubleUtil.AreClose(lassoPoint.Y, point.Y)) { if (DoubleUtil.AreClose(lassoPoint.X, point.X)) { isInside = true; break; } if ((0 != i) && DoubleUtil.AreClose(prevLassoPoint.Y, point.Y) && DoubleUtil.GreaterThanOrClose(point.X, Math.Min(prevLassoPoint.X, lassoPoint.X)) && DoubleUtil.LessThanOrClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X))) { isInside = true; break; } } else if (isHigher != (point.Y < lassoPoint.Y)) { isHigher = !isHigher; if (DoubleUtil.GreaterThanOrClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X))) { // there certainly is an intersection on the left isInside = !isInside; } else if (DoubleUtil.GreaterThanOrClose(point.X, Math.Min(prevLassoPoint.X, lassoPoint.X))) { // The X of the point lies within the x ranges for the segment. // Calculate the x value of the point where the segment intersects with the line. Vector lassoSegment = lassoPoint - prevLassoPoint; System.Diagnostics.Debug.Assert(lassoSegment.Y != 0); double x = prevLassoPoint.X + (lassoSegment.X / lassoSegment.Y) * (point.Y - prevLassoPoint.Y); if (DoubleUtil.GreaterThanOrClose(point.X, x)) { isInside = !isInside; } } } prevLassoPoint = lassoPoint; } return(isInside); }
// ------------------------------------------------------------------ // Arrange content of formatted line. // // vc - Visual collection of the parent. // lineOffset - Offset of the line. // ------------------------------------------------------------------ internal override void Arrange(VisualCollection vc, Vector lineOffset) { // Arrange inline objects int runDcp = _dcp; IList <TextSpan <TextRun> > runs = _line.GetTextRunSpans(); Debug.Assert(runs != null, "Cannot retrieve runs collection."); // Calculate offset shift due to trailing spaces double adjustedXOffset = lineOffset.X + CalculateXOffsetShift(); foreach (TextSpan <TextRun> textSpan in runs) { TextRun run = textSpan.Value; if (run is InlineObject) { InlineObject inlineObject = run as InlineObject; // Disconnect visual from its old parent, if necessary. Visual currentParent = VisualTreeHelper.GetParent(inlineObject.Element) as Visual; if (currentParent != null) { ContainerVisual parent = currentParent as ContainerVisual; Invariant.Assert(parent != null, "parent should always derives from ContainerVisual"); parent.Children.Remove(inlineObject.Element); } // Get position of inline object withing the text line. FlowDirection flowDirection; Rect rect = GetBoundsFromPosition(runDcp, inlineObject.Length, out flowDirection); Debug.Assert(DoubleUtil.GreaterThanOrClose(rect.Width, 0), "Negative inline object's width."); ContainerVisual proxyVisual = new ContainerVisual(); if (inlineObject.Element is FrameworkElement) { FlowDirection parentFlowDirection = _owner.FlowDirection; // Check parent's FlowDirection to determine if mirroring is needed DependencyObject parent = ((FrameworkElement)inlineObject.Element).Parent; if (parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } PtsHelper.UpdateMirroringTransform(_owner.FlowDirection, parentFlowDirection, proxyVisual, rect.Width); } vc.Add(proxyVisual); if (_owner.UseLayoutRounding) { // If using layout rounding, check whether rounding needs to compensate for high DPI DpiScale dpi = _owner.GetDpi(); proxyVisual.Offset = new Vector(UIElement.RoundLayoutValue(lineOffset.X + rect.Left, dpi.DpiScaleX), UIElement.RoundLayoutValue(lineOffset.Y + rect.Top, dpi.DpiScaleY)); } else { proxyVisual.Offset = new Vector(lineOffset.X + rect.Left, lineOffset.Y + rect.Top); } proxyVisual.Children.Add(inlineObject.Element); // Combine text line offset (relative to the Text control) with inline object // offset (relative to the line) and set transorm on the visual. Trailing spaces // shift is not added here because it is returned by GetBoundsFromPosition inlineObject.Element.Arrange(new Rect(inlineObject.Element.DesiredSize)); } // Do not use TextRun.Length, because it gives total length of the run. // So, if the run is broken between lines, it gives incorrect value. // Use length of the TextSpan instead, which gives the correct length here. runDcp += textSpan.Length; } }
// Token: 0x06006DAF RID: 28079 RVA: 0x001F81B4 File Offset: 0x001F63B4 private bool Contains(Point point) { if (!this._boundingBox.Contains(point)) { return(false); } bool flag = false; int num = this._lasso.Count; while (--num >= 0) { if (!DoubleUtil.AreClose(this._lasso[num].Y, point.Y)) { flag = (point.Y < this._lasso[num].Y); break; } } bool flag2 = false; bool flag3 = false; Point point2 = this._lasso[this._lasso.Count - 1]; for (int i = 0; i < this._lasso.Count; i++) { Point point3 = this._lasso[i]; if (DoubleUtil.AreClose(point3.Y, point.Y)) { if (DoubleUtil.AreClose(point3.X, point.X)) { flag2 = true; break; } if (i != 0 && DoubleUtil.AreClose(point2.Y, point.Y) && DoubleUtil.GreaterThanOrClose(point.X, Math.Min(point2.X, point3.X)) && DoubleUtil.LessThanOrClose(point.X, Math.Max(point2.X, point3.X))) { flag2 = true; break; } } else if (flag != point.Y < point3.Y) { flag = !flag; if (DoubleUtil.GreaterThanOrClose(point.X, Math.Max(point2.X, point3.X))) { flag2 = !flag2; if (i == 0 && DoubleUtil.AreClose(point.X, Math.Max(point2.X, point3.X))) { flag3 = true; } } else if (DoubleUtil.GreaterThanOrClose(point.X, Math.Min(point2.X, point3.X))) { Vector vector = point3 - point2; double value = point2.X + vector.X / vector.Y * (point.Y - point2.Y); if (DoubleUtil.GreaterThanOrClose(point.X, value)) { flag2 = !flag2; if (i == 0 && DoubleUtil.AreClose(point.X, value)) { flag3 = true; } } } } point2 = point3; } return(flag2 && !flag3); }
protected override Size MeasureOverride(Size availableSize) { Size desiredSize = new Size(); // Don't measure the child if tabs are not ready yet or Ribbon is collapsed. if (Ribbon != null && !Ribbon.IsCollapsed) { double remainingSpace = availableSize.Width; bool invalidateTHPanel = false; RibbonTabHeadersPanel tabHeadersPanel = null; if (Ribbon.RibbonTabHeaderItemsControl != null) { tabHeadersPanel = Ribbon.RibbonTabHeaderItemsControl.InternalItemsHost as RibbonTabHeadersPanel; } double tabHeadersPanelSpaceAvailable = (tabHeadersPanel != null) ? tabHeadersPanel.SpaceAvailable : 0.0; foreach (RibbonContextualTabGroup tabGroupHeader in InternalChildren) { double width = 0; tabGroupHeader.ArrangeWidth = 0; tabGroupHeader.ArrangeX = 0; tabGroupHeader.IdealDesiredWidth = 0.0; if (tabGroupHeader.Visibility == Visibility.Visible && tabGroupHeader.FirstVisibleTab != null && DoubleUtil.GreaterThanOrClose(remainingSpace, 0.0)) { // Measure the maximum desired width // TabHeaders should be padded up more if needed. // Also we need to determine if we need to show the label tooltip tabGroupHeader.Measure(new Size(double.PositiveInfinity, availableSize.Height)); tabGroupHeader.IdealDesiredWidth = tabGroupHeader.DesiredSize.Width; // If TabHeadersPanel has space to expand, then invalidate it so that TabHeaders add extra Padding to themselves. double desiredExtraPadding = tabGroupHeader.IdealDesiredWidth - tabGroupHeader.TabsDesiredWidth; if (DoubleUtil.GreaterThan(desiredExtraPadding, 0.0) && DoubleUtil.GreaterThan(tabHeadersPanelSpaceAvailable, 0.0)) { invalidateTHPanel = true; } width = tabGroupHeader.TabsDesiredWidth; // If the difference between tabGroupHeader.TabsDesiredWidth and remainingSpace is less // than 1e-10 then assume that both are same. This is because TextBlock is very sensitive to // even a minute floating point difference and displays ellipsis even when sufficient // space is available. if (Math.Abs(tabGroupHeader.TabsDesiredWidth - remainingSpace) > _desiredWidthEpsilon) { // Clip on the left side width = Math.Min(tabGroupHeader.TabsDesiredWidth, remainingSpace); } tabGroupHeader.ArrangeWidth = width; tabGroupHeader.Measure(new Size(width, availableSize.Height)); // If label is truncated - show the tooltip tabGroupHeader.ShowLabelToolTip = DoubleUtil.GreaterThan(tabGroupHeader.IdealDesiredWidth, width); remainingSpace = remainingSpace - width; } desiredSize.Width += width; desiredSize.Height = Math.Max(desiredSize.Height, tabGroupHeader.DesiredSize.Height); } if (WaitingForMeasure || invalidateTHPanel) { if (tabHeadersPanel != null) { tabHeadersPanel.InvalidateMeasure(); } } } return(desiredSize); }