public void SetFrameWithArrowDirection(CGRect frame, UIPopoverArrowDirection direction) { Frame = frame; Layer.ShadowPath = TrianglePath(frame, direction, true).CGPath; Layer.ShadowPath = TrianglePath(frame, direction, false).CGPath; bool leftOrRight = (direction == UIPopoverArrowDirection.Left || direction == UIPopoverArrowDirection.Right); CGRect pathRect = new CGRect(CGPoint.Empty, new CGSize(frame.Width + (leftOrRight ? ShadowRadius + 1.0f : 2.0f * (ShadowRadius + 1.0f)), frame.Height + (leftOrRight ? 2.0f * (ShadowRadius + 1.0f) : ShadowRadius + 1.0f))); if (direction == UIPopoverArrowDirection.Up) { pathRect.Y -= ShadowRadius + 1.0f; } else if (direction == UIPopoverArrowDirection.Left) { pathRect.X -= ShadowRadius + 1.0f; } UIBezierPath path = UIBezierPath.FromRect(pathRect); CAShapeLayer mask = new CAShapeLayer(); mask.Path = path.CGPath; mask.FillColor = UIColor.Black.CGColor; Layer.Mask = mask; Layer.ShadowColor = UIColor.Black.CGColor; Layer.ShadowOffset = CGSize.Empty; Layer.ShadowRadius = ShadowRadius; Layer.ShadowOpacity = ShadowOpacity; Layer.ContentsScale = UIScreen.MainScreen.Scale; Layer.BackgroundColor = UIColor.White.CGColor; }
private static Task <DropDownListSelection <T> > ShowInternal <T>( UIView containerView, object anchorUIElement, UITableViewCellStyle itemStyle, UITableViewStyle viewStyle, IEnumerable <T> items, Func <T, GenericCellDescriptor> itemDescriber, string dropDownTitle, UIPopoverArrowDirection arrowDirection, CGSize?fitSize ) { if (itemDescriber == null) { throw new ArgumentNullException("displayNameGetter"); } return(ShowInternal( containerView, anchorUIElement, itemStyle, viewStyle, new [] { items }, (s) => new GenericTableViewSection <T>(dropDownTitle, items), itemDescriber, arrowDirection, fitSize )); }
public PopoverRootElement( string caption, string value, Func<RootElement, UIViewController> createOnSelected, UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirection.Any ) : this(caption, value, createOnSelected, () => arrowDirection) { }
/// <summary> /// Shows the action sheet from a specific point. /// This method is only available on iPad devices. /// </summary> /// <param name="point">The point to show the action sheet from.An arrow will point towards this point.</param> /// <param name="view">The hosting view in which the action sheet should be shown.</param> /// <param name="arrowDirection">The direction in which the arrow should show and the side of the section at which the arrow should be placed.</param> /// <param name="animated">Whether the action sheet should show with an animation.</param> public void ShowFromPointInView(CGPoint point, UIView view, UIPopoverArrowDirection arrowDirection, bool animated) { if (_isVisible) { Console.WriteLine("********** Action Sheet is already visible."); return; } if (!_isiPad) { ShowInView(view, animated); } UIApplication.SharedApplication.BeginIgnoringInteractionEvents(); _targetView = view; MoveToPoint(point, arrowDirection, false); if (_delegate != null) { _delegate.ActionSheetWillPresent(this); } NSNotificationCenter.DefaultCenter.AddObserver(new NSString("UIDeviceOrientationDidChangeNotification"), OrientationChanged); LayoutForVisible(!animated); _targetView.AddSubview(this); if (!animated) { UIApplication.SharedApplication.EndIgnoringInteractionEvents(); if (_delegate != null) { _delegate.ActionSheetDidPresent(this); } } else { float duration = 0.3f; Animate(duration, () => { LayoutForVisible(true); }, () => { UIApplication.SharedApplication.EndIgnoringInteractionEvents(); if (_delegate != null) { _delegate.ActionSheetDidPresent(this); } }); } }
private void Changes(CGPoint point, UIPopoverArrowDirection arrowDirection) { Frame = _targetView.Bounds; CGRect finalFrame = CGRect.Empty; float arrowHeight = ArrowHeight; float spacing = Spacing; if (arrowDirection == UIPopoverArrowDirection.Right) { finalFrame.Width = point.X - arrowHeight; finalFrame.Height = _targetView.Bounds.Height; } else if (arrowDirection == UIPopoverArrowDirection.Left) { finalFrame.Width = _targetView.Bounds.Width - point.X - arrowHeight; finalFrame.Height = _targetView.Bounds.Height; finalFrame.X = point.X + arrowHeight; } else if (arrowDirection == UIPopoverArrowDirection.Up) { finalFrame.Width = _targetView.Bounds.Width; finalFrame.Height = _targetView.Bounds.Height - point.Y - arrowHeight; finalFrame.Y = point.Y + arrowHeight; } else if (arrowDirection == UIPopoverArrowDirection.Down) { finalFrame.Width = _targetView.Bounds.Width; finalFrame.Height = point.Y - arrowHeight; } else { throw new ArgumentException("********** Invalid arrow direction."); } finalFrame.X += spacing; finalFrame.Y += spacing; finalFrame.Height -= spacing * 2.0f; finalFrame.Width -= spacing * 2.0f; base.Draw(AlignmentRectInsets.InsetRect(finalFrame)); _scrollViewHost.BackgroundColor = UIColor.White; _scrollViewHost.Layer.CornerRadius = HostsCornerRadius; _scrollViewHost.Layer.ShadowColor = UIColor.Black.CGColor; _scrollViewHost.Layer.ShadowOffset = CGSize.Empty; _scrollViewHost.Layer.ShadowRadius = ShadowRadius; _scrollViewHost.Layer.ShadowOpacity = ShadowOpacity; LayoutSheetForFrame(finalFrame, false, true, true); AnchorSheetAtPoint(point, arrowDirection, finalFrame); }
public static Task <DropDownListSelection <TItem> > Show <TSection, TItem>( UIBarButtonItem barButton, UITableViewCellStyle itemStyle, IEnumerable <TSection> sections, Func <TSection, GenericTableViewSection <TItem> > sectionDescriber, Func <TItem, GenericCellDescriptor> itemDescriber, UITableViewStyle headerStyle = UITableViewStyle.Plain, UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirection.Up, CGSize?fitSize = null ) where TSection : IEnumerable <TItem> { return(ShowInternal(null, barButton, itemStyle, headerStyle, sections, sectionDescriber, itemDescriber, arrowDirection, fitSize)); }
public static Task <DropDownListSelection <T> > Show <T>( UIBarButtonItem barButton, UITableViewCellStyle itemStyle, IEnumerable <T> items, Func <T, GenericCellDescriptor> itemDescriber, string dropDownTitle = null, UITableViewStyle headerStyle = UITableViewStyle.Plain, UIPopoverArrowDirection arrowDirection = UIPopoverArrowDirection.Up, CGSize?fitSize = null ) { return(ShowInternal(null, barButton, itemStyle, headerStyle, items, itemDescriber, dropDownTitle, arrowDirection, fitSize)); }
public static void PresentFromRect(RectangleF rect, UIView inView, UIPopoverArrowDirection arrowDirection) { if(_Popover.ShouldDismiss == null) { _Popover.ShouldDismiss += (controller) => { return true; }; } if(_Popover.DidDismiss == null) { _Popover.DidDismiss += (controller) => { Console.WriteLine("Popover Did Dismiss"); }; } using(var pool = new NSAutoreleasePool()) { pool.BeginInvokeOnMainThread(()=> { _Popover.PresentPopover(rect, inView, arrowDirection, true); }); } }
public PopoverContainerView(SizeF size, RectangleF anchor, RectangleF displayArea, UIPopoverArrowDirection arrowDirection, PopoverContainerModel properties) : base() { Properties = properties; _CorrectedSize = new SizeF(size.Width + properties.LeftBgMargin + properties.RightBgMargin + properties.LeftContentMargin + properties.RightContentMargin, size.Height + properties.TopBgMargin + properties.BottomBgMargin + properties.TopContentMargin + properties.BottomContentMargin); DetermineGeometry(size, anchor, displayArea, arrowDirection); InitializeFrame(); this.BackgroundColor = UIColor.Clear; var image = UIImage.FromBundle(properties.BackgroundImage); this._BackgroundImage = image.StretchableImage(properties.LeftBgCapSize, properties.TopBgCapSize); this.ClipsToBounds = true; this.UserInteractionEnabled = true; }
/// <summary> /// Moves the action sheet to a new point. /// This method can only be called if the action sheet is already visible on screen. /// This method is only available on iPad devices. /// </summary> /// <param name="point">The point to show the action sheet from. An arrow will point towards this point.</param> /// <param name="arrowDirection">The direction in which the arrow should show and the side of the section at which the arrow should be placed.</param> /// <param name="animated">Whether the action sheet should change point with an animation. If you are invoking this method from the animated interface orientation change methods of UIViewController (@c willAnimateRotationToInterfaceOrientation:) pass @c NO because the UIViewController will itself do the animation.</param> public void MoveToPoint(CGPoint point, UIPopoverArrowDirection arrowDirection, bool animated) { if (!_isiPad) { return; } if (!_isVisible) { Console.WriteLine("********** Action Sheet must be visible in order to move the anchor point"); return; } UIApplication.SharedApplication.BeginIgnoringInteractionEvents(); DisableCustomEasing = true; if (animated) { Animate(0.3, () => { Changes(point, arrowDirection); }, () => { UIApplication.SharedApplication.EndIgnoringInteractionEvents(); }); } else { Changes(point, arrowDirection); UIApplication.SharedApplication.EndIgnoringInteractionEvents(); } DisableCustomEasing = false; }
//NOTE Why do we need this? //public static Type LayerType { get { return typeof(CustomActionSheetLayer); } } UIBezierPath TrianglePath(CGRect rect, UIPopoverArrowDirection arrowDirection, bool closePath) { UIBezierPath path = new UIBezierPath(); if (arrowDirection == UIPopoverArrowDirection.Down) { path.MoveTo(CGPoint.Empty); path.AddLineTo(new CGPoint(rect.Width / 2.0f, rect.Height)); path.AddLineTo(new CGPoint(rect.Width, 0.0f)); } else if (arrowDirection == UIPopoverArrowDirection.Left) { path.MoveTo(new CGPoint(rect.Width, 0.0f)); path.AddLineTo(new CGPoint(0.0f, rect.Height / 2.0f)); path.AddLineTo(new CGPoint(rect.Width, rect.Height)); } else if (arrowDirection == UIPopoverArrowDirection.Right) { path.MoveTo(CGPoint.Empty); path.AddLineTo(new CGPoint(rect.Width, rect.Height / 2.0f)); path.AddLineTo(new CGPoint(0.0f, rect.Height)); } else if (arrowDirection == UIPopoverArrowDirection.Up) { path.MoveTo(new CGPoint(0.0f, rect.Height)); path.AddLineTo(new CGPoint(rect.Width / 2.0f, 0.0f)); path.AddLineTo(new CGPoint(rect.Width, rect.Height)); } if (closePath) { path.ClosePath(); } return(path); }
public void PresentFromRect(CGRect rect, UIView view, UIPopoverArrowDirection arrowDirections, bool animated) { ObjC.MessageSend(Handle, "presentPopoverFromRect:inView:permittedArrowDirections:animated:", rect, view.Handle, (uint)arrowDirections, animated); }
public static void PresentFromRect(RectangleF rect, UIView view, UIPopoverArrowDirection arrowDirection, bool animated) { _PopoverController.PresentFromRect(rect, view, arrowDirection, animated); }
public static void PresentFromRect(CGRect rect, UIView view, UIPopoverArrowDirection arrowDirection, bool animated) { _PopoverController.PresentPopover(rect, view, arrowDirection, animated); }
private static async Task <DropDownListSelection <TItem> > ShowInternal <TSection, TItem>( UIView containerView, object anchorUIElement, UITableViewCellStyle itemStyle, UITableViewStyle headerStyle, IEnumerable <TSection> sections, Func <TSection, GenericTableViewSection <TItem> > sectionDescriber, Func <TItem, GenericCellDescriptor> itemDescriber, UIPopoverArrowDirection arrowDirection, CGSize?fitSize ) where TSection : IEnumerable <TItem> { if (anchorUIElement == null) { throw new ArgumentNullException("anchorView"); } if (!(anchorUIElement is UIView || anchorUIElement is UIBarButtonItem)) { throw new ArgumentOutOfRangeException("anchorView", "Must be a UIView or a UIBarButtonItem"); } var sectionsArray = sections.Select(sectionDescriber).ToArray(); if (sectionsArray.Count() == 1 && string.IsNullOrWhiteSpace(sectionsArray.First().Title)) { headerStyle = UITableViewStyle.Plain; } var selectSignal = new ManualResetEventSlim(); var table = new UITableViewController(headerStyle); table.AutomaticallyAdjustsScrollViewInsets = false; var result = new DropDownListSelection <TItem>(); var popOverController = new UIPopoverController(table); var dropDownSource = new GenericTableViewSource <TItem>( table.TableView, itemStyle, sectionsArray, itemDescriber, (x) => { result.SelectedItem = x; popOverController.Dismiss(false); selectSignal.Set(); } ); popOverController.DidDismiss += (object sender, EventArgs e) => { if (!selectSignal.IsSet) { selectSignal.Set(); } }; ((UITableView)table.View).Source = dropDownSource; // Calculate how wide the view should be by finding how if (fitSize == null) { // calculate the fit size var tableView = (UITableView)table.View; nfloat largestWidth = 0.0f; var sectionHeight = (headerStyle == UITableViewStyle.Plain ? (float)tableView.SectionHeaderHeight : Tools.iOSTool.DefaultGroupedTableViewHeaderHeight); nfloat totalHeight = sectionHeight * sectionsArray.Count(s => !string.IsNullOrWhiteSpace(s.Title)); foreach (var section in sectionsArray) { foreach (var itemDescriptor in ((IEnumerable <TItem>)section.Items).WithDescriptions()) { var index = itemDescriptor.Index; var item = itemDescriptor.Description; var cellSize = (CGSize)dropDownSource.GetCell(tableView, (NSIndexPath)(NSIndexPath.FromRowSection(index, 0))).SizeThatFits((CGSize)CGSize.Empty); if (cellSize.Width > largestWidth) { largestWidth = cellSize.Width; } totalHeight += cellSize.Height; } } fitSize = new CGSize(largestWidth + ItemPadding, totalHeight); } popOverController.SetPopoverContentSize(fitSize.Value, false); TypeSwitch.Do( anchorUIElement, TypeSwitch.Case <UIBarButtonItem>(bbi => popOverController.PresentFromBarButtonItem( (UIBarButtonItem)anchorUIElement, arrowDirection, true ) ), TypeSwitch.Case <UIView>(v => popOverController.PresentFromRect( ((UIView)anchorUIElement).Frame, containerView, arrowDirection, true ) ), TypeSwitch.Case <UITabBarItem>(tb => { var tabBar = containerView as UITabBar; if (tabBar == null) { throw new ArgumentException("Container view must be an UITabBar when the anchor view is an UITabBarItem"); } if (!tabBar.Items.Contains(tb)) { throw new ArgumentException("Container view UITabBar does not contain the anchor view UITabBarItem"); } var index = tabBar.Items.IndexOf(tb); var tabBarItemWidth = tabBar.Frame.Size.Width / tabBar.Items.Count(); var rect = new CGRect(tabBarItemWidth * index, 0f, tabBarItemWidth, tabBar.Frame.Height); popOverController.PresentFromRect( rect, tabBar, arrowDirection, true ); }), TypeSwitch.Default(() => { throw new NotSupportedException("anchorUIElement was {0}".FormatWith(anchorUIElement.GetType().Name)); }) ); await Task.Run(() => selectSignal.Wait()); table.View.DisposeEx(); table.TableView.DisposeEx(); table.Dispose(); popOverController.Dispose(); return(result); }
public void UpdatePositionWithAnchorRect(RectangleF anchorRect, RectangleF displayArea, UIPopoverArrowDirection arrowDirections) { DetermineGeometry(_CorrectedSize, anchorRect, displayArea, arrowDirections); InitializeFrame(); }
public void PresentPopover(RectangleF rect, UIView inView, UIPopoverArrowDirection arrowDirection, bool animated) { this.DismissPopover(false); if(this.ContentViewController.View != null) { //obj-C selector calls [vc getView] which calls loadView } if(this.ContentSize == SizeF.Empty) { this.ContentSize = this.ContentViewController.ContentSizeForViewInPopover; } var displayArea = CalculateDisplayArea(inView); var properties = this.Properties ?? DefaultContainerModel; var containerView = new PopoverContainerView(this.ContentSize, rect, displayArea, arrowDirection, properties); this.ArrowDirection = containerView.PopoverArrowDirection; var keyView = this.GetKeyView(); BackgroundView = new TouchableView() { Frame = keyView.Bounds }; BackgroundView.ContentMode = UIViewContentMode.ScaleToFill; BackgroundView.BackgroundColor = UIColor.Clear; BackgroundView.ViewWasTouched = this.ViewWasTouched; BackgroundView.AutoresizingMask = UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleRightMargin | UIViewAutoresizing.FlexibleTopMargin | UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleBottomMargin; keyView.AddSubview(BackgroundView); containerView.Frame = inView.ConvertRectFromView(containerView.Frame, BackgroundView); BackgroundView.AddSubview(containerView); containerView.SetContentView(ContentViewController.View); containerView.AutoresizingMask = UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin; this.View = containerView; this.UpdateBackgroundPassthroughViews(); this.ContentViewController.ViewWillAppear(animated); this.View.BecomeFirstResponder(); if(animated) { this.View.Alpha = 0.0f; UIView.BeginAnimations("FadeIn", IntPtr.Zero); UIView.SetAnimationDuration(FadeDuration); UIView.SetAnimationDelegate(this); UIView.SetAnimationDidStopSelector(new MonoTouch.ObjCRuntime.Selector("animationDidStop:finished:context:")); this.View.Alpha = 1.0f; UIView.CommitAnimations(); } else { IsPopoverVisible = true; this.ContentViewController.ViewDidAppear(animated); } }
public void RepositionPopover(RectangleF rect, UIView inView, UIPopoverArrowDirection arrowDirection) { var displayArea = CalculateDisplayArea(View); var containerView = (PopoverContainerView)this.View; containerView.UpdatePositionWithAnchorRect(rect, displayArea, arrowDirection); containerView.Frame = inView.ConvertRectToView(containerView.Frame, this.BackgroundView); ArrowDirection = arrowDirection; }
public void PresentFromRect(CGRect rect, UIView view, UIPopoverArrowDirection arrowDirections, bool animated) { ObjC.MessageSend(Handle, Selector.GetHandle("presentPopoverFromRect:inView:permittedArrowDirections:animated:"), rect, view.Handle, (uint)arrowDirections, animated); }
public virtual void PresentPopoverFromBarButtonItem(UIBarButtonItem item, UIPopoverArrowDirection permittedArrowDirections, bool animated) { }
public virtual void PresentPopoverFromRect(CGRect rect, UIView inView, UIPopoverArrowDirection permittedArrowDirections, bool animated) { }
private void AnchorSheetAtPoint(CGPoint point, UIPopoverArrowDirection arrowDirection, CGRect frame) { _anchoredAtPoint = true; _anchorPoint = point; _anchoredArrowDirection = arrowDirection; CGRect finalFrame = _scrollViewHost.Frame; float arrowHeight = ArrowHeight; float arrrowBaseWidth = ArrowBaseWidth; bool leftOrRight = (arrowDirection == UIPopoverArrowDirection.Left || arrowDirection == UIPopoverArrowDirection.Right); CGRect arrowFrame = new CGRect(CGPoint.Empty, new CGSize((leftOrRight ? arrowHeight : arrrowBaseWidth), (leftOrRight ? arrrowBaseWidth : arrowHeight))); if (arrowDirection == UIPopoverArrowDirection.Right) { arrowFrame.X = point.X - arrowHeight; arrowFrame.Y = point.Y - arrrowBaseWidth / 2.0f; finalFrame.X = point.X - finalFrame.Width - arrowHeight; } else if (arrowDirection == UIPopoverArrowDirection.Left) { arrowFrame.X = point.X; arrowFrame.Y = point.Y - arrrowBaseWidth / 2.0f; finalFrame.X = point.X + arrowHeight; } else if (arrowDirection == UIPopoverArrowDirection.Up) { arrowFrame.X = point.X - arrrowBaseWidth / 2.0f; arrowFrame.Y = point.Y; finalFrame.Y = point.Y + arrowHeight; } else if (arrowDirection == UIPopoverArrowDirection.Down) { arrowFrame.X = point.X - arrrowBaseWidth / 2.0f; arrowFrame.Y = point.Y - arrowHeight; finalFrame.Y = point.Y - finalFrame.Height - arrowHeight; } if (leftOrRight) { finalFrame.Y = NMath.Min(NMath.Max(frame.GetMaxY() - finalFrame.Height, arrowFrame.GetMaxY() - finalFrame.Height + HostsCornerRadius), NMath.Min(NMath.Max(frame.GetMinY(), point.Y - finalFrame.Height / 2.0f), arrowFrame.GetMinY() - HostsCornerRadius)); } else { finalFrame.X = NMath.Min(NMath.Max(NMath.Min(frame.GetMinX(), arrowFrame.GetMinX() - HostsCornerRadius), point.X - finalFrame.Width / 2.0f), NMath.Max(frame.GetMaxX() - finalFrame.Width, arrowFrame.GetMaxX() + HostsCornerRadius - finalFrame.Width)); } if (_arrowView == null) { _arrowView = new CustomActionSheetTriangle(); AddSubview(_arrowView); } _arrowView.SetFrameWithArrowDirection(arrowFrame, arrowDirection); if (!_targetView.Bounds.Contains(finalFrame) || !_targetView.Bounds.Contains(arrowFrame)) { Console.WriteLine("WARNING: Action sheet does not fit within view bounds! Select a different arrow direction or provide a different anchor point."); } _scrollViewHost.Frame = finalFrame; }
public void DetermineGeometry(SizeF size, RectangleF anchorRect, RectangleF displayArea, UIPopoverArrowDirection supportedDirections) { _Offset = PointF.Empty; _BackgroundRect = RectangleF.Empty; _ArrowRect = RectangleF.Empty; PopoverArrowDirection = UIPopoverArrowDirection.Unknown; var biggestSurface = 0.0f; var currentMinMargin = 0.0f; var upArrowImage = UIImage.FromBundle(this.Properties.UpArrowImage); var downArrowImage = UIImage.FromBundle(this.Properties.DownArrowImage); var leftArrowImage = UIImage.FromBundle(this.Properties.LeftArrowImage); var rightArrowImage = UIImage.FromBundle(this.Properties.RightArrowImage); foreach(var direction in (UIPopoverArrowDirection[])Enum.GetValues(typeof(UIPopoverArrowDirection))) { if(supportedDirections.HasFlag(direction)) { var bgRect = RectangleF.Empty; var arrowRect = RectangleF.Empty; var offset = PointF.Empty; var xArrowOffset = 0.0f; var yArrowOffset = 0.0f; var anchorPoint = PointF.Empty; switch(direction) { case UIPopoverArrowDirection.Up: { anchorPoint = new PointF(anchorRect.GetMidX(), anchorRect.GetMaxY()); xArrowOffset = size.Width / 2 - upArrowImage.Size.Width / 2; yArrowOffset = Properties.TopBgMargin - upArrowImage.Size.Height; offset = new PointF(anchorPoint.X - xArrowOffset - upArrowImage.Size.Width / 2, anchorPoint.Y - yArrowOffset); bgRect = new RectangleF(0, 0, size.Width, size.Height); if(offset.X < 0) { xArrowOffset += offset.X; offset.X = 0; } else if(offset.X + size.Width > displayArea.Size.Width) { xArrowOffset += (offset.X + size.Width - displayArea.Size.Width); offset.X = displayArea.Size.Width - size.Width; } xArrowOffset = Math.Max(xArrowOffset, Properties.LeftBgMargin + Properties.ArrowMargin); xArrowOffset = Math.Min(xArrowOffset, size.Width - Properties.RightBgMargin - Properties.ArrowMargin - upArrowImage.Size.Width); arrowRect = new RectangleF(xArrowOffset, yArrowOffset, upArrowImage.Size.Width, upArrowImage.Size.Height); break; } case UIPopoverArrowDirection.Down: { anchorPoint = new PointF(anchorRect.GetMidX(), anchorRect.GetMinY()); xArrowOffset = size.Width / 2 - downArrowImage.Size.Width / 2; yArrowOffset = size.Height - Properties.BottomBgMargin; offset = new PointF(anchorPoint.X - xArrowOffset - downArrowImage.Size.Width / 2, anchorPoint.Y - yArrowOffset - downArrowImage.Size.Height); bgRect = new RectangleF(0, 0, size.Width, size.Height); if(offset.X < 0) { xArrowOffset += offset.X; offset.X = 0; } else if(offset.X + size.Width > displayArea.Size.Width) { xArrowOffset += (offset.X + size.Width - displayArea.Size.Width); offset.X = displayArea.Size.Width - size.Width; } //cap arrow offset; xArrowOffset = Math.Max(xArrowOffset, Properties.LeftBgMargin + Properties.ArrowMargin); xArrowOffset = Math.Min(xArrowOffset, size.Width - Properties.RightBgMargin - Properties.ArrowMargin - downArrowImage.Size.Width); arrowRect = new RectangleF(xArrowOffset, yArrowOffset, downArrowImage.Size.Width, downArrowImage.Size.Height); break; } case UIPopoverArrowDirection.Left: { anchorPoint = new PointF(anchorRect.GetMaxX(), anchorRect.GetMidY()); xArrowOffset = Properties.LeftBgMargin - leftArrowImage.Size.Width; yArrowOffset = size.Height / 2 - leftArrowImage.Size.Height / 2; offset = new PointF(anchorPoint.X - xArrowOffset, anchorPoint.Y - yArrowOffset - leftArrowImage.Size.Height / 2); bgRect = new RectangleF(0, 0, size.Width, size.Height); if(offset.Y < 0) { yArrowOffset += offset.Y; offset.Y = 0; } else if(offset.Y + size.Height > displayArea.Size.Height) { yArrowOffset += (offset.Y + size.Height) - displayArea.Size.Height; offset.Y = displayArea.Size.Height - size.Height; } //cap arrow offset; yArrowOffset = Math.Max(yArrowOffset, Properties.TopBgMargin + Properties.ArrowMargin); yArrowOffset = Math.Min(yArrowOffset, size.Height - Properties.BottomBgMargin - Properties.ArrowMargin - leftArrowImage.Size.Height); arrowRect = new RectangleF(xArrowOffset, yArrowOffset, leftArrowImage.Size.Width, leftArrowImage.Size.Height); break; } case UIPopoverArrowDirection.Right: { anchorPoint = new PointF(anchorRect.GetMinX(), anchorRect.GetMidY()); xArrowOffset = size.Width - Properties.RightBgMargin; yArrowOffset = size.Height / 2 - rightArrowImage.Size.Width / 2; offset = new PointF(anchorPoint.X - xArrowOffset - rightArrowImage.Size.Width, anchorPoint.Y - yArrowOffset - rightArrowImage.Size.Height / 2); bgRect = new RectangleF(0, 0, size.Width, size.Height); if(offset.Y < 0) { yArrowOffset += offset.Y; offset.Y = 0; } else if(offset.Y + size.Height > displayArea.Size.Height) { yArrowOffset += (offset.Y + size.Height) - displayArea.Size.Height; offset.Y = displayArea.Size.Height - size.Height; } //cap arrow offset; yArrowOffset = Math.Max(yArrowOffset, Properties.TopBgMargin + Properties.ArrowMargin); yArrowOffset = Math.Min(yArrowOffset, size.Height - Properties.BottomBgMargin - Properties.ArrowMargin - rightArrowImage.Size.Height); arrowRect = new RectangleF(xArrowOffset, yArrowOffset, rightArrowImage.Size.Width, rightArrowImage.Size.Height); break; } } //end switch statement // var bgFrame = bgRect.RectOffset(offset.X, offset.Y); // var bgFrame = RectangleFExtensions.Offset(bgRect, offset.X, offset.Y); var bgFrame = bgRect; bgFrame.X += offset.X; bgFrame.Y += offset.Y; var minMarginLeft = bgFrame.GetMinX() - displayArea.GetMinX(); var minMarginRight = displayArea.GetMaxX() - bgFrame.GetMaxY(); var minMarginTop = bgFrame.GetMinY() - displayArea.GetMinY(); var minMarginBottom = displayArea.GetMaxY() - bgFrame.GetMaxY(); if(minMarginLeft < 0) { // Popover is too wide and clipped on the left; decrease width // and move it to the right offset.X -= minMarginLeft; bgRect.Size.Width += minMarginLeft; minMarginLeft = 0; if(direction == UIPopoverArrowDirection.Right) { arrowRect.X = bgRect.GetMaxX() - Properties.RightBgMargin; } } if(minMarginRight < 0) { // Popover is too wide and clipped on the right; decrease width. bgRect.Size.Width += minMarginRight; minMarginRight = 0; if(direction == UIPopoverArrowDirection.Left) { arrowRect.X = bgRect.GetMinX() - leftArrowImage.Size.Width + Properties.LeftBgMargin; } } if(minMarginTop < 0) { // Popover is too high and clipped at the top; decrease height and move it down offset.Y -= minMarginTop; bgRect.Size.Height += minMarginTop; minMarginTop = 0; if(direction == UIPopoverArrowDirection.Down) { arrowRect.Y = bgRect.GetMaxY() - Properties.BottomBgMargin; } } if(minMarginBottom < 0) { // Popover is too high and clipped at the bottom; decrease height. bgRect.Size.Height += minMarginBottom; minMarginBottom = 0; if(direction == UIPopoverArrowDirection.Up) { arrowRect.Y = bgRect.GetMinY() - upArrowImage.Size.Height + Properties.TopBgMargin; } } bgFrame = bgRect.RectOffset(offset.X, offset.Y); var minMargin = Math.Min(minMarginLeft, minMarginRight); minMargin = Math.Min(minMargin, minMarginTop); minMargin = Math.Min(minMargin, minMarginBottom); // Calculate intersection and surface var intersection = RectangleF.Intersect(displayArea, bgFrame); var surface = intersection.Size.Width * intersection.Size.Height; if(surface >= biggestSurface && minMargin >= currentMinMargin) { biggestSurface = surface; _Offset = offset; _ArrowRect = arrowRect; _BackgroundRect = bgRect; PopoverArrowDirection = direction; currentMinMargin = minMargin; } } // end if } //end foreach switch(PopoverArrowDirection) { case UIPopoverArrowDirection.Up: _ArrowImage = upArrowImage; break; case UIPopoverArrowDirection.Down: _ArrowImage = downArrowImage; break; case UIPopoverArrowDirection.Left: _ArrowImage = leftArrowImage; break; case UIPopoverArrowDirection.Right: _ArrowImage = rightArrowImage; break; } }