public void ShowToolTip(ITrackingSpan span, object toolTipContent, PopupStyles style) { if (span == null) { throw new ArgumentNullException("span"); } if (span.TextBuffer != _textView.TextBuffer) { throw new ArgumentException("Invalid span"); } if (toolTipContent == null) { throw new ArgumentNullException("toolTipContent"); } var element = toolTipContent as Control; if (element == null) { string toolTipContentAsString = toolTipContent as string; if (toolTipContentAsString != null) { element = BuildTooltipUIElement(toolTipContentAsString); } else { throw new ArgumentException("Invalid contnet", nameof(toolTipContent)); } } this.ClearToolTip(); _agent = _spaceReservationManager.CreatePopupAgent(span, style, element); _spaceReservationManager.AddAgent(_agent); }
public PopupSpaceReservationAgent(ISpaceReservationManager spaceReservationManager, IWpfTextView wpfTextView, ITrackingSpan visualSpan, PopupStyles style, UIElement content) { if (spaceReservationManager == null) { throw new ArgumentNullException(nameof(spaceReservationManager)); } if (visualSpan == null) { throw new ArgumentNullException(nameof(visualSpan)); } if (content == null) { throw new ArgumentNullException(nameof(content)); } if ((style & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) == (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) { throw new ArgumentOutOfRangeException(nameof(style)); } this.spaceReservationManager = spaceReservationManager; this.wpfTextView = wpfTextView; this.visualSpan = visualSpan; this.style = style; this.content = content; this.popup = new Popup { PlacementTarget = wpfTextView.VisualElement, Placement = PlacementMode.Relative, Visibility = Visibility.Collapsed, IsOpen = false, AllowsTransparency = true, UseLayoutRounding = true, SnapsToDevicePixels = true, }; }
internal static Rect GetLocation(PopupStyles style, Size desiredSize, Rect spanRectInScreenCoordinates, Rect reservedRect, Rect screenRect) { if ((style & PopupStyles.PositionLeftOrRight) != 0) { //Position left or right double xPosition = ((style & PopupStyles.PreferLeftOrTopPosition) != 0) ? (reservedRect.Left - desiredSize.Width) //To the left : reservedRect.Right; //To the right double yPosition = ((style & PopupStyles.RightOrBottomJustify) != 0) ? (spanRectInScreenCoordinates.Bottom - desiredSize.Height) //Bottom justified : spanRectInScreenCoordinates.Top; //Top justified return(ShiftVerticallyToFitScreen(xPosition, yPosition, desiredSize, screenRect)); } else { //Position above or below. double xPosition = ((style & PopupStyles.RightOrBottomJustify) != 0) ? (spanRectInScreenCoordinates.Right - desiredSize.Width) //Right justified : spanRectInScreenCoordinates.Left; //Left justified double yPosition = ((style & PopupStyles.PreferLeftOrTopPosition) != 0) ? (reservedRect.Top - desiredSize.Height) //Above : reservedRect.Bottom; //Below return(ShiftHorizontallyToFitScreen(xPosition, yPosition, desiredSize, screenRect)); } }
public void ShowToolTip(ITrackingSpan span, object toolTipContent, PopupStyles style) { if (span is null) { throw new ArgumentNullException(nameof(span)); } if (toolTipContent is null) { throw new ArgumentNullException(nameof(toolTipContent)); } if ((style & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) == (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) { throw new ArgumentOutOfRangeException(nameof(style)); } ClearToolTip(); var uiElement = GetUIElement(toolTipContent); if (uiElement is null) { throw new ArgumentException(); } spaceReservationManager.AgentChanged += SpaceReservationManager_AgentChanged; toolTipAgent = spaceReservationManager.CreatePopupAgent(span, style, uiElement); spaceReservationManager.AddAgent(toolTipAgent); }
internal void Update(ITrackingSpan visualSpan, PopupStyles style) { if ((style & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) == (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) { throw new ArgumentOutOfRangeException(nameof(style)); } this.visualSpan = visualSpan ?? throw new ArgumentNullException(nameof(visualSpan)); this.style = style; wpfTextView.QueueSpaceReservationStackRefresh(); }
public PopupAgent(Mono.TextEditor.MonoTextEditor textView, IMDSpaceReservationManager manager, ITrackingSpan visualSpan, PopupStyles style, Widget content) { if (textView == null) { throw new ArgumentNullException("textView"); } if (manager == null) { throw new ArgumentNullException("manager"); } if (visualSpan == null) { throw new ArgumentNullException("visualSpan"); } if (((int)style & ~(0xff)) != 0) //Union of all the legal style bits. { throw new ArgumentOutOfRangeException("style"); } if (content == null) { throw new ArgumentNullException("content"); } if ((style & PopupStyles.DismissOnMouseLeaveText) != 0 && (style & PopupStyles.DismissOnMouseLeaveTextOrContent) != 0) { throw new ArgumentException("Can't specify both PopupStyles.DismissOnMouseLeaveText and PopupStyles.DismissOnMouseLeaveTextOrContent", "style"); } _textView = textView; _manager = manager; _visualSpan = visualSpan; _style = style; var popupCache = textView.Properties.GetOrCreateSingletonProperty <Dictionary <WeakReferenceForDictionaryKey, PopupOrWindowContainer> >( () => new Dictionary <WeakReferenceForDictionaryKey, PopupOrWindowContainer>(MaxPopupCacheSize)); if (!popupCache.TryGetValue(new WeakReferenceForDictionaryKey(content), out _popup)) { _popup = PopupOrWindowContainer.Create(content, _textView.VisualElement); if (popupCache.Count == MaxPopupCacheSize) { popupCache.Clear(); } popupCache.Add(new WeakReferenceForDictionaryKey(content), _popup); } }
public void ShowToolTip(ITrackingSpan span, object toolTipContent, PopupStyles style) { if (span == null) throw new ArgumentNullException(nameof(span)); if (toolTipContent == null) throw new ArgumentNullException(nameof(toolTipContent)); if ((style & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) == (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) throw new ArgumentOutOfRangeException(nameof(style)); ClearToolTip(); var uiElement = GetUIElement(toolTipContent); if (uiElement == null) throw new ArgumentException(); spaceReservationManager.AgentChanged += SpaceReservationManager_AgentChanged; toolTipAgent = spaceReservationManager.CreatePopupAgent(span, style, uiElement); spaceReservationManager.AddAgent(toolTipAgent); }
Rect GetClosest(Rect spanBounds, Rect?rect, Rect candidate, PopupStyles style) { if (rect == null) { return(candidate); } if ((style & PopupStyles.PositionLeftOrRight) != 0) { var rectDist = GetHorizontalDistance(spanBounds, rect.Value); var candidateDist = GetHorizontalDistance(spanBounds, candidate); return(rectDist < candidateDist ? rect.Value : candidate); } else { var rectDist = GetVerticalDistance(spanBounds, rect.Value); var candidateDist = GetVerticalDistance(spanBounds, candidate); return(rectDist < candidateDist ? rect.Value : candidate); } }
Rect GetClosest(Rect spanBounds, Rect?rect, Rect candidate, PopupStyles style) { if (rect is null) { return(candidate); } double rectDist, candidateDist; if ((style & PopupStyles.PositionLeftOrRight) != 0) { rectDist = GetHorizontalDistance(spanBounds, rect.Value); candidateDist = GetHorizontalDistance(spanBounds, candidate); } else { rectDist = GetVerticalDistance(spanBounds, rect.Value); candidateDist = GetVerticalDistance(spanBounds, candidate); } return(rectDist <= candidateDist ? rect.Value : candidate); }
public ISpaceReservationAgent CreatePopupAgent(ITrackingSpan visualSpan, PopupStyles style, UIElement content) { if (wpfTextView.IsClosed) { throw new InvalidOperationException(); } if (visualSpan == null) { throw new ArgumentNullException(nameof(visualSpan)); } if (content == null) { throw new ArgumentNullException(nameof(content)); } if ((style & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) == (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) { throw new ArgumentOutOfRangeException(nameof(style)); } return(new PopupSpaceReservationAgent(this, wpfTextView, visualSpan, style, content)); }
public void DetachFromSession() { // Don't use the view model as the data context anymore. _surfaceElement.DataContext = null; // Unbind the view model. _sessionView.Session = null; // Stop listening to all of the session/surface element events. _session.Dismissed -= this.OnSessionDismissed; ((INotifyCollectionChanged)_session.Signatures).CollectionChanged -= this.OnSessionSignaturesChanged; _session.TextView.TextBuffer.Changed -= this.OnSessionViewBuffer_Changed; _session = null; // Reset out popup styles for the next session to which we get attached. _popupStyles = PopupStyles.None; _surfaceElement.Hide(); _presentationSpan = null; }
IEnumerable <Rect> GetPositions(Rect screenRect, Geometry reservedSpace, Size desiredSize, Rect spanBounds, PopupStyles style) { var rect1 = GetPosition(screenRect, desiredSize, spanBounds, spanBounds, style); if (!OverlapsReservedSpace(reservedSpace, rect1)) { yield return(rect1); } var unionBounds = Rect.Union(reservedSpace.Bounds, spanBounds); if ((style & PopupStyles.PositionLeftOrRight) != 0) { bool preferLeft = (style & PopupStyles.PreferLeftOrTopPosition) != 0; var rect2 = preferLeft ? new Rect(unionBounds.Left - desiredSize.Width, spanBounds.Y, desiredSize.Width, desiredSize.Height) : new Rect(unionBounds.Right, spanBounds.Y, desiredSize.Width, desiredSize.Height); if (!OverlapsReservedSpace(reservedSpace, rect2)) { yield return(rect2); } } else { bool preferTop = (style & PopupStyles.PreferLeftOrTopPosition) != 0; var rect2 = preferTop ? new Rect(spanBounds.X, unionBounds.Top - desiredSize.Height, desiredSize.Width, desiredSize.Height) : new Rect(spanBounds.X, unionBounds.Bottom, desiredSize.Width, desiredSize.Height); if (!OverlapsReservedSpace(reservedSpace, rect2)) { yield return(rect2); } } var rect3 = GetPosition(screenRect, desiredSize, spanBounds, unionBounds, style); if (!OverlapsReservedSpace(reservedSpace, rect3)) { yield return(rect3); } }
public void UpdatePopupAgent(ISpaceReservationAgent agent, ITrackingSpan visualSpan, PopupStyles styles) { if (wpfTextView.IsClosed) { throw new InvalidOperationException(); } if (agent == null) { throw new ArgumentNullException(nameof(agent)); } if (visualSpan == null) { throw new ArgumentNullException(nameof(visualSpan)); } if ((styles & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) == (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) { throw new ArgumentOutOfRangeException(nameof(styles)); } if (!spaceReservationAgents.Contains(agent)) { throw new ArgumentOutOfRangeException(nameof(agent)); } var popupAgent = agent as PopupSpaceReservationAgent; if (popupAgent == null) { throw new ArgumentException(); } popupAgent.Update(visualSpan, styles); UpdateAggregateFocus(); wpfTextView.QueueSpaceReservationStackRefresh(); }
public Geometry PositionAndDisplay(Geometry reservedSpace) { //This method should only be called from the popup manager (which should never call it when the containing //view is hidden or in the middle of a layout). //This method does not support virtual whitespace positioning. An attempt to support it by using caret position was introduced, but //regressed the behavior that popup should stay in place as the caret moves. If in the future we need to support virtual whitespace, //consider using virtual span instead. //Update the visual span to the current snapshot. SnapshotSpan visualSpan = _visualSpan.GetSpan(_textView.TextSnapshot); // If the style indicates that we should dismiss when the mouse leaves the span of the text, then we should make an // initial check to make sure the mouse starts-off in the span. If not, we should fail to position. if ((_style & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) != 0) { _textView.VisualElement.GetPointer(out int x, out int y); if (this.ShouldClearToolTipOnMouseMove(new Point(x, y))) { return(null); } } Rect?spanRectangle = null; if (visualSpan.Length > 0) { double left = double.MaxValue; double top = double.MaxValue; double right = double.MinValue; double bottom = double.MinValue; var bounds = _textView.TextViewLines.GetNormalizedTextBounds(visualSpan); foreach (var bound in bounds) { left = Math.Min(left, bound.Left); top = Math.Min(top, bound.TextTop); right = Math.Max(right, bound.Right); bottom = Math.Max(bottom, bound.TextBottom); } // If the start of the span lies within the view, use that instead of the left-bound of the span as a whole. // This will cause popups to be left-aligned with the start of their span, if at all possible. var startLine = _textView.TextViewLines.GetTextViewLineContainingBufferPosition(visualSpan.Start); if (startLine != null) { var startPointBounds = startLine.GetExtendedCharacterBounds(visualSpan.Start); if ((startPointBounds.Left < right) && (startPointBounds.Left >= _textView.ViewportLeft) && (startPointBounds.Left < _textView.ViewportRight)) { left = startPointBounds.Left; } } //Special case handling for when the end of the span is at the start of a line. ITextViewLine line = _textView.TextViewLines.GetTextViewLineContainingBufferPosition(visualSpan.End); if ((line != null) && (line.Start == visualSpan.End)) { bottom = Math.Max(bottom, line.TextBottom); } if (left < right) { spanRectangle = new Rect(left, top, right - left, bottom - top); } } else { //visualSpan is zero length so the default MarkerGeometry will be null. Create a custom marker geometry based on the location. ITextViewLine line = _textView.TextViewLines.GetTextViewLineContainingBufferPosition(visualSpan.Start); if (line != null) { TextBounds bounds = line.GetCharacterBounds(visualSpan.Start); spanRectangle = new Rect(bounds.Left, bounds.TextTop, 0.0, bounds.TextHeight); } } if (spanRectangle.HasValue) { //Get the portion of the span geometry that is inside the view. Rect viewRect = new Rect(_textView.ViewportLeft, _textView.ViewportTop, _textView.ViewportWidth, _textView.ViewportHeight); Rect spanRect = spanRectangle.Value; spanRect = spanRect.Intersect(viewRect); if (spanRect != default(Rect)) { // Determine two different rectangles for the span. One is the span in its raw form. The other is a "guess" at // what the already-reserved space around the span will be. We have a very-prevalent space reservation agent (the // current line agent) that reserves the current line plus a 3-pixel buffer below the line. We'll optimistically // guess that this agent might be in-play and attempt to avoid it. Rect spanRectWithBuffer = new Rect(spanRect.Left, spanRect.Top, spanRect.Right - spanRect.Left, spanRect.Bottom - spanRect.Top + BelowTheLineBufferHint); //Some of the text associated with the popup is visible, show the popup. Rect spanRectInScreenCoordinates = new Rect(this.GetScreenPointFromTextXY(spanRect.Left, spanRect.Top), this.GetScreenPointFromTextXY(spanRect.Right, spanRect.Bottom)); Rect spanRectWithBufferInScreenCoordinates = new Rect(this.GetScreenPointFromTextXY(spanRectWithBuffer.Left, spanRectWithBuffer.Top), this.GetScreenPointFromTextXY(spanRectWithBuffer.Right, spanRectWithBuffer.Bottom)); Rect screenRect = Xwt.Desktop.GetScreenAtLocation(spanRectInScreenCoordinates.TopLeft).Bounds;//TODO: Check if we should use VisualBounds Size desiredSize = _popup.Size; //The popup size specified in deivice pixels. Convert these to logical //pixels for purposes of calculating the actual size of the popup. //TODO desiredSize = new Size (desiredSize.Width / WpfHelper.DeviceScaleX, desiredSize.Height / WpfHelper.DeviceScaleY); desiredSize = new Size(desiredSize.Width, desiredSize.Height); PopupStyles alternateStyle = _style ^ PopupStyles.PreferLeftOrTopPosition; var tr = reservedSpace.Bounds; Point topLeft = new Point(Math.Min(spanRectInScreenCoordinates.Left, tr.Left), Math.Min(spanRectInScreenCoordinates.Top, tr.Top)); Point bottomRight = new Point(Math.Max(spanRectInScreenCoordinates.Right, tr.Right), Math.Max(spanRectInScreenCoordinates.Bottom, tr.Bottom)); var reservedRect = new Rect(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); //There are 6 possible locations for the popup. The order of preference is determined by the presence of the //'PositionClosest' PopupStyle. // // Without 'PositionClosest': // 1 .. On the desired side of the span. // 2 .. On the desired side of the span with a bit of buffer. // 3 .. on the desired side of the reserved rectangle. // 4 .. On the alternate side of the span. // 5 .. On the alternate side of the span with a bit of buffer. // 6 .. on the alternate side of the reserved rectangle. // // With 'PositionClosest': // 1 .. On the desired side of the span. // 2 .. On the desired side of the span with a bit of buffer. // 3 .. On the alternate side of the span. // 4 .. On the alternate side of the span with a bit of buffer. // 5 .. on the desired side of the reserved rectangle. // 6 .. on the alternate side of the reserved rectangle. // //Try each location till we get a winner. // A location is a winner if it is disjoint from the original reserved rect and // the edges of the screen. Tuple <PopupStyles, Rect>[] positionChoices; if (reservedRect != default(Rect)) { if ((_style & PopupStyles.PositionClosest) == 0) { positionChoices = new Tuple <PopupStyles, Rect>[] { new Tuple <PopupStyles, Rect>(_style, spanRectInScreenCoordinates), new Tuple <PopupStyles, Rect>(_style, spanRectWithBufferInScreenCoordinates), new Tuple <PopupStyles, Rect>(_style, reservedRect), new Tuple <PopupStyles, Rect>(alternateStyle, spanRectInScreenCoordinates), new Tuple <PopupStyles, Rect>(alternateStyle, spanRectWithBufferInScreenCoordinates), new Tuple <PopupStyles, Rect>(alternateStyle, reservedRect), }; } else { positionChoices = new Tuple <PopupStyles, Rect>[] { new Tuple <PopupStyles, Rect>(_style, spanRectInScreenCoordinates), new Tuple <PopupStyles, Rect>(_style, spanRectWithBufferInScreenCoordinates), new Tuple <PopupStyles, Rect>(alternateStyle, spanRectInScreenCoordinates), new Tuple <PopupStyles, Rect>(alternateStyle, spanRectWithBufferInScreenCoordinates), new Tuple <PopupStyles, Rect>(_style, reservedRect), new Tuple <PopupStyles, Rect>(alternateStyle, reservedRect), }; } } else { positionChoices = new Tuple <PopupStyles, Rect>[] { new Tuple <PopupStyles, Rect>(_style, spanRectInScreenCoordinates), new Tuple <PopupStyles, Rect>(_style, spanRectWithBufferInScreenCoordinates), new Tuple <PopupStyles, Rect>(alternateStyle, spanRectInScreenCoordinates), new Tuple <PopupStyles, Rect>(alternateStyle, spanRectWithBufferInScreenCoordinates), }; } Rect location = default; foreach (var choice in positionChoices) { Rect locationToTry = GetLocation(choice.Item1, desiredSize, spanRectInScreenCoordinates, choice.Item2, screenRect); if (DisjointWithPadding(reservedSpace, locationToTry) && ContainsWithPadding(screenRect, locationToTry)) { location = locationToTry; _style = choice.Item1; break; } } // If we couldn't locate a place to live, tell the manager we want to go away. if (location == default) { return(null); } if (!_popup.IsVisible) { this.RegisterForEvents(); } _popup.DisplayAt(location.TopLeft); GeometryGroup requestedSpace = new GeometryGroup(); requestedSpace.Children.Add(new RectangleGeometry(FromXwtRect(spanRectInScreenCoordinates))); requestedSpace.Children.Add(new RectangleGeometry(FromXwtRect(location))); return(requestedSpace); } } //The text associated with the popup visualSpan is not visible: tell the manager we want to go away. return(null); }
public ISpaceReservationAgent CreatePopupAgent(ITrackingSpan visualSpan, PopupStyles style, UIElement content) { if (wpfTextView.IsClosed) throw new InvalidOperationException(); if (visualSpan == null) throw new ArgumentNullException(nameof(visualSpan)); if (content == null) throw new ArgumentNullException(nameof(content)); if ((style & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) == (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) throw new ArgumentOutOfRangeException(nameof(style)); return new PopupSpaceReservationAgent(this, wpfTextView, visualSpan, style, content); }
public void UpdatePopupAgent(ISpaceReservationAgent agent, ITrackingSpan visualSpan, PopupStyles styles) { if (wpfTextView.IsClosed) throw new InvalidOperationException(); if (agent == null) throw new ArgumentNullException(nameof(agent)); if (visualSpan == null) throw new ArgumentNullException(nameof(visualSpan)); if ((styles & (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) == (PopupStyles.DismissOnMouseLeaveText | PopupStyles.DismissOnMouseLeaveTextOrContent)) throw new ArgumentOutOfRangeException(nameof(styles)); if (!spaceReservationAgents.Contains(agent)) throw new ArgumentOutOfRangeException(nameof(agent)); var popupAgent = agent as PopupSpaceReservationAgent; if (popupAgent == null) throw new ArgumentException(); popupAgent.Update(visualSpan, styles); UpdateAggregateFocus(); wpfTextView.QueueSpaceReservationStackRefresh(); }
public void UpdatePopupAgent(ISpaceReservationAgent agent, ITrackingSpan visualSpan, PopupStyles styles) { if (agent == null) { throw new ArgumentNullException("agent"); } if (visualSpan == null) { throw new ArgumentNullException("visualSpan"); } PopupAgent popupAgent = agent as PopupAgent; if (popupAgent == null) { throw new ArgumentException("The agent is not a PopupAgent", "agent"); } popupAgent.SetVisualSpan(visualSpan); popupAgent._style = styles; this.CheckFocusChange(); _view.QueueSpaceReservationStackRefresh(); }
public ISpaceReservationAgent CreatePopupAgent(ITrackingSpan visualSpan, PopupStyles styles, Xwt.Widget content) { return(new PopupAgent(_view, this, visualSpan, styles, content)); }
Rect GetPosition(Rect screenRect, Size desiredSize, Rect spanBounds, Rect reservedBounds, PopupStyles style) { Debug.Assert(Rect.Union(reservedBounds, spanBounds) == reservedBounds); double left, top; if ((style & PopupStyles.PositionLeftOrRight) != 0) { bool preferLeft = (style & PopupStyles.PreferLeftOrTopPosition) != 0; bool bottomJustify = (style & PopupStyles.RightOrBottomJustify) != 0; top = bottomJustify ? spanBounds.Bottom - desiredSize.Height : reservedBounds.Top; left = preferLeft ? reservedBounds.Left - desiredSize.Width : reservedBounds.Right; if (top < screenRect.Top) { top = screenRect.Top; } else if (top + desiredSize.Height > screenRect.Bottom) { top = screenRect.Bottom - desiredSize.Height; } } else { bool preferTop = (style & PopupStyles.PreferLeftOrTopPosition) != 0; bool rightJustify = (style & PopupStyles.RightOrBottomJustify) != 0; top = preferTop ? reservedBounds.Top - desiredSize.Height : reservedBounds.Bottom; left = rightJustify ? spanBounds.Right - desiredSize.Width : reservedBounds.Left; if (left < screenRect.Left) { left = screenRect.Left; } else if (left + desiredSize.Width > screenRect.Right) { left = screenRect.Right - desiredSize.Width; } } return(new Rect(left, top, desiredSize.Width, desiredSize.Height)); }
IEnumerable <Rect> GetPositions(Rect screenRect, Geometry reservedSpace, Size desiredSize, Rect spanBounds, PopupStyles style) { var rect1 = GetPosition(screenRect, desiredSize, spanBounds, spanBounds, style); if (!OverlapsReservedSpace(reservedSpace, rect1)) { yield return(rect1); } var unionBounds = Rect.Union(reservedSpace.Bounds, spanBounds); var rect2 = GetPosition(screenRect, desiredSize, spanBounds, unionBounds, style); if (!OverlapsReservedSpace(reservedSpace, rect2)) { yield return(rect2); } }
IEnumerable <Rect> GetValidPositions(Rect screenRect, Geometry reservedSpace, Size desiredSize, Rect spanBounds, PopupStyles style) { var possiblePositions = new List <Rect>(); possiblePositions.AddRange(GetPositions(screenRect, reservedSpace, desiredSize, spanBounds, style)); possiblePositions.AddRange(GetPositions(screenRect, reservedSpace, desiredSize, spanBounds, style ^ PopupStyles.PreferLeftOrTopPosition)); bool isLeftRight = (style & PopupStyles.PositionLeftOrRight) != 0; foreach (var pos in possiblePositions) { if (isLeftRight) { if (pos.Left >= screenRect.Left && pos.Right <= screenRect.Right) { yield return(pos); } } else { if (pos.Top >= screenRect.Top && pos.Bottom <= screenRect.Bottom) { yield return(pos); } } } }