public override void Draw (RectangleF rect)
		{
			rect = RectangleF.Inflate (rect, 4, 4);
			rect = new RectangleF ((rect.Size.Width - rect.Size.Height) / 2 + 4, 8, rect.Size.Height, rect.Size.Height);
			UIBezierPath path = UIBezierPath.FromOval (rect);
			UIColor.Black.SetStroke ();
			UIColor.White.SetFill ();
			path.LineWidth = 2;
			path.Fill ();
			path.Stroke ();

			UIBezierPath rightEye, leftEye, mouth = new UIBezierPath ();
			if (MovingRight) {
				rightEye = UIBezierPath.FromArc (new PointF (rect.GetMidX () - 5, rect.Y + 15), 4, 0, 180, true);
				leftEye = UIBezierPath.FromArc (new PointF (rect.GetMidX () + 10, rect.Y + 15), 4, 0, 180, true);
				mouth.MoveTo (new PointF (rect.GetMidX (), rect.Y + 30));
				mouth.AddLineTo (new PointF (rect.GetMidX () + 13, rect.Y + 30));
			} else {

				rightEye = UIBezierPath.FromArc (new PointF (rect.GetMidX () - 10, rect.Y + 15), 4, 0, 180, true);
				leftEye = UIBezierPath.FromArc (new PointF (rect.GetMidX () - 10, rect.Y + 15), 4, 0, 180, true);
				mouth.MoveTo (new PointF (rect.GetMidX (), rect.Y + 30));
				mouth.MoveTo (new PointF (rect.GetMidX (), rect.Y + 30));

			}
			rightEye.LineWidth = 2;
			rightEye.Stroke ();

			leftEye.LineWidth = 2;
			leftEye.Stroke ();

			mouth.LineWidth = 2;
			mouth.Stroke ();

		}
        public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(RectangleF rect)
        {
            var array = base.LayoutAttributesForElementsInRect (rect);
            var visibleRect = new RectangleF (CollectionView.ContentOffset, CollectionView.Bounds.Size);

            for (int i = 0; i < array.Length; i++)
            {
                var attributes = array[i];

                if (attributes.Frame.IntersectsWith(rect))
                {
                    float distance = visibleRect.GetMidX () - attributes.Center.X;
                    float normalizedDistance = distance / ACTIVE_DISTANCE;
                    if (Math.Abs (distance) < ACTIVE_DISTANCE)
                    {
                        //This disables the zooming (zoom is configured for horizontal scrolling)
                        //float zoom = 1 + ZOOM_FACTOR * (1 - Math.Abs (normalizedDistance));
                        //attributes.Transform3D = CATransform3D.MakeScale (zoom, zoom, 1.0f);
                        attributes.ZIndex = 1;
                    }
                }
            }

            return array;
        }
Example #3
0
        public override void Draw(System.Drawing.RectangleF rect)
        {
            base.Draw(rect);

            // Get current graphics context.
            using (CGContext g = UIGraphics.GetCurrentContext()) {
                // Overall transforms to shift (0, 0) to center and scale.
                g.TranslateCTM(rect.GetMidX(), rect.GetMidY());
                float scale = Math.Min(rect.Width, rect.Height) / 2 / 100;
                g.ScaleCTM(scale, scale);

                // Attributes for tick marks
                g.SetStrokeColor(new CGColor(0, 0, 0));
                g.SetLineCap(CGLineCap.Round);

                // Set line dash to draw tick marks for every minute.
                g.SetLineWidth(3);
                g.SetLineDash(0, new float[] { 0, 3 * (float)Math.PI });
                g.AddPath(tickMarks);
                g.DrawPath(CGPathDrawingMode.Stroke);

                // Set line dash to draw tick marks for every hour.
                g.SetLineWidth(6);
                g.SetLineDash(0, new float[] { 0, 15 * (float)Math.PI });
                g.AddPath(tickMarks);
                g.DrawPath(CGPathDrawingMode.Stroke);

                // Set common attributes for clock hands.
                g.SetStrokeColor(new CGColor(0, 0, 0));
                g.SetFillColor(new CGColor(0, 0, 1));
                g.SetLineWidth(2);
                g.SetLineDash(0, null);
                g.SetLineJoin(CGLineJoin.Round);

                // Draw hour hand.
                g.SaveState();
                g.RotateCTM(hourAngle);                  // 2 * (float)Math.PI * (dt.Hour + dt.Minute / 60.0f) / 12);
                g.AddPath(hourHand);
                g.DrawPath(CGPathDrawingMode.FillStroke);
                g.RestoreState();

                // Draw minute hand.
                g.SaveState();
                g.RotateCTM(minuteAngle);                  // 2 * (float)Math.PI * (dt.Minute + dt.Second / 60.0f) / 60);
                g.AddPath(minuteHand);
                g.DrawPath(CGPathDrawingMode.FillStroke);
                g.RestoreState();

                // Draw second hand.
                g.SaveState();
                g.RotateCTM(secondAngle);                  // 2 * (float)Math.PI * dt.Second / 60);
                g.AddPath(secondHand);
                g.DrawPath(CGPathDrawingMode.Stroke);
                g.RestoreState();
            }
        }
		public override void Draw (RectangleF rect)
		{
			rect = rect.Inset (4, 4);
			UIBezierPath path = UIBezierPath.FromArc (new PointF (rect.GetMidX (), rect.GetMidY ()), rect.Size.Width / 2, 0, 180, true);
			path.LineWidth = 8;

			UIColor.White.SetFill ();
			path.Fill ();

			UIColor.Black.SetStroke ();
			path.Stroke ();
		}
        public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(RectangleF rect)
        {
            var array = base.LayoutAttributesForElementsInRect (rect);
            var visibleRect = new RectangleF (CollectionView.ContentOffset, CollectionView.Bounds.Size);

            foreach (var attributes in array) {
                if (attributes.Frame.IntersectsWith (rect)) {
                    float distance = visibleRect.GetMidX () - attributes.Center.X;
                    float normalizedDistance = distance / ACTIVE_DISTANCE;
                    if (Math.Abs (distance) < ACTIVE_DISTANCE) {
                        float zoom = 1 + ZOOM_FACTOR * (1 - Math.Abs (normalizedDistance));
                        attributes.Transform3D = CATransform3D.MakeScale (zoom, zoom, 1.0f);
                        attributes.ZIndex = 1;
                    }
                }
            }
            return array;
        }
		public CGPath GetCellBorderPath(RectangleF rect)
		{
			var cornerRadius = 10;
			
			float minx = rect.GetMinX(), midx = rect.GetMidX(), maxx = rect.GetMaxX();
			float miny = rect.GetMinY(), midy = rect.GetMidY(), maxy = rect.GetMaxY();
			
			CGPath path = new CGPath();
			
			var cellPosition = CellPosition;

			if (cellPosition == CellPosition.Top)
			{
				minx = minx + 1;
				miny = miny + 1;
				
				maxx = maxx - 1;
				
				path.MoveToPoint(minx, maxy);
				path.AddArcToPoint(minx, miny, midx, miny, cornerRadius);
				path.AddArcToPoint(maxx, miny, maxx, maxy, cornerRadius);
				path.AddLineToPoint(maxx, maxy);
			}
			else if (cellPosition == CellPosition.Bottom)
			{
				minx = minx + 1;
				
				maxx = maxx - 1;
				maxy = maxy - 1;
				
				path.MoveToPoint(minx, miny);
				path.AddArcToPoint(minx, maxy, midx, maxy, cornerRadius);
				path.AddArcToPoint(maxx, maxy, maxx, miny, cornerRadius);
				path.AddLineToPoint(maxx, miny);
			}
			else if (cellPosition == CellPosition.Middle)
			{
				minx = minx + 1;
				maxx = maxx - 1;
				
				path.MoveToPoint(minx, miny);
				path.AddLineToPoint(maxx, miny);
				path.AddLineToPoint(maxx, maxy);
				path.AddLineToPoint(minx, maxy);
			}
			else if (cellPosition == CellPosition.Single)
			{
				minx = minx + 1;
				miny = miny + 1;
				
				maxx = maxx - 1;
				maxy = maxy - 1;
				
				path.MoveToPoint(minx, midy);
				path.AddArcToPoint(minx, miny, midx, miny, cornerRadius);
				path.AddArcToPoint(maxx, miny, maxx, midy, cornerRadius);
				path.AddArcToPoint(maxx, maxy, midx, maxy, cornerRadius);
				path.AddArcToPoint(minx, maxy, minx, midy, cornerRadius);
				
			}

			path.CloseSubpath();
			return path;
		}
Example #7
0
			public override void Draw (RectangleF rect)
			{
				UIView head = ((WalkingDead)Superview).head;
				UIBezierPath path = new UIBezierPath ();
				path.LineCapStyle = CGLineCap.Round;
				RectangleF headFrame = head.Frame;
			
				if (!MovingRight) {
					rect.X -= 20;
					path.MoveTo (new PointF (rect.GetMidX () + 20, headFrame.GetMaxY () + 10));
					path.AddLineTo (new PointF (rect.GetMidX () + 20 + rect.Size.Width / 6, headFrame.GetMaxY () + 10));
					path.AddLineTo (new PointF (rect.GetMidX () + 20 + rect.Size.Width / 6 + 10, headFrame.GetMaxY () + 10 + 20));
				} else {
					path.MoveTo (new PointF (rect.GetMidX () - 20, headFrame.GetMaxY () + 10));
					path.AddLineTo (new PointF (rect.GetMidX () - 20 - rect.Size.Width / 6, headFrame.GetMaxY () + 10));
					path.AddLineTo (new PointF (rect.GetMidX () - 20 - rect.Size.Width / 6 - 10, headFrame.GetMaxY () + 10 + 20));
				
				}
				UIColor.Black.SetStroke ();
				path.LineWidth = 12;
				path.Stroke ();
			
				UIColor.White.SetStroke ();
				path.LineWidth = 8;
				path.Stroke ();
			}
        void Draw(RectangleF rect)
        {
            //// Color Declarations

            //// Frames
            var bgFrame = new RectangleF(0, 0, rect.Width, rect.Height);

            //// Subframes
            var circleGroup = new RectangleF(bgFrame.GetMinX() + (float)Math.Floor(bgFrame.Width * 0.13437f + 0.5f), bgFrame.GetMinY() + (float)Math.Floor(bgFrame.Height * 0.12500f + 0.5f), (float)Math.Floor(bgFrame.Width * 0.85938f + 0.5f) - (float)Math.Floor(bgFrame.Width * 0.13437f + 0.5f), (float)Math.Floor(bgFrame.Height * 0.84688f + 0.5f) - (float)Math.Floor(bgFrame.Height * 0.12500f + 0.5f));

            //// Abstracted Attributes
            var progressOvalEndAngle = Progress;

            //// circleGroup
            {
                //// outerOval Drawing
                var outerOvalPath = UIBezierPath.FromOval(new RectangleF(circleGroup.GetMinX() + (float)Math.Floor(circleGroup.Width * 0.00216f) + 0.5f, circleGroup.GetMinY() + (float)Math.Floor(circleGroup.Height * 0.00000f + 0.5f), (float)Math.Floor(circleGroup.Width * 0.99784f) - (float)Math.Floor(circleGroup.Width * 0.00216f), (float)Math.Floor(circleGroup.Height * 1.00000f + 0.5f) - (float)Math.Floor(circleGroup.Height * 0.00000f + 0.5f)));
                OuterColor.SetFill();
                outerOvalPath.Fill();

                //// progressOval Drawing
                var progressOvalRect = new RectangleF(circleGroup.GetMinX() + (float)Math.Floor(circleGroup.Width * 0.00216f) + 0.5f, circleGroup.GetMinY() + (float)Math.Floor(circleGroup.Height * 0.00000f + 0.5f), (float)Math.Floor(circleGroup.Width * 0.99784f) - (float)Math.Floor(circleGroup.Width * 0.00216f), (float)Math.Floor(circleGroup.Height * 1.00000f + 0.5f) - (float)Math.Floor(circleGroup.Height * 0.00000f + 0.5f));
                var progressOvalPath = new UIBezierPath();
                progressOvalPath.AddArc(new PointF(progressOvalRect.GetMidX(), progressOvalRect.GetMidY()), progressOvalRect.Width / 2, (float)(270 * Math.PI / 180), (float)(progressOvalEndAngle * Math.PI / 180), true);
                progressOvalPath.AddLineTo(new PointF(progressOvalRect.GetMidX(), progressOvalRect.GetMidY()));
                progressOvalPath.ClosePath();

                InnerColor.SetFill();
                progressOvalPath.Fill();

                //// innerOval Drawing
                var innerOvalPath = UIBezierPath.FromOval(new RectangleF(circleGroup.GetMinX() + (float)Math.Floor(circleGroup.Width * 0.09052f + 0.5f), circleGroup.GetMinY() + (float)Math.Floor(circleGroup.Height * 0.09091f + 0.5f), (float)Math.Floor(circleGroup.Width * 0.90948f + 0.5f) - (float)Math.Floor(circleGroup.Width * 0.09052f + 0.5f), (float)Math.Floor(circleGroup.Height * 0.91342f + 0.5f) - (float)Math.Floor(circleGroup.Height * 0.09091f + 0.5f)));
                InsideColor.SetFill();
                innerOvalPath.Fill();
            }
        }
Example #9
0
		public void SSDrawRoundedRect(CGContext context, RectangleF rect, float cornerRadius)
		{
			var minx = rect.GetMinX();
			var midx = rect.GetMidX();
			var maxx = rect.GetMaxX();
			var miny = rect.GetMinY();
			var midy = rect.GetMidY();
			var maxy = rect.GetMaxY();
			context.MoveTo(minx, midy);
			context.AddArcToPoint(minx, miny, midx, miny, cornerRadius);
			context.AddArcToPoint(maxx, miny, maxx, midy, cornerRadius);
			context.AddArcToPoint(maxx, maxy, midx, maxy, cornerRadius);
			context.AddArcToPoint(minx, maxy, minx, midy, cornerRadius);
			context.ClosePath();
			context.FillPath();
		}
        private void DrawLinearGradient(CGContext context, RectangleF rect, CGColor startColor, CGColor  endColor)
        {
            CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB ();
            float [] locations = { 0.0f, 1.0f };

            CGColor [] colors = new CGColor[] { startColor, endColor };

            CGGradient gradient = new CGGradient (colorSpace, colors, locations);

            PointF startPoint = new PointF (rect.GetMidX (), rect.GetMinY ());
            PointF endPoint = new PointF (rect.GetMidX (), rect.GetMaxY ());

            context.SaveState ();
            context.AddPath (UIBezierPath.FromRoundedRect (rect, 10).CGPath);
            context.Clip ();
            context.DrawLinearGradient (gradient, startPoint, endPoint, 0);
            context.RestoreState ();
        }
Example #11
0
        private void DrawWindowBackgroundGradient(RectangleF drawingRect, CGPath clippingPath)
        {
            var window = (AppStoreWindow)Window;
            clippingPath.ApplyClippingPathInCurrentContext();
            if (window.IsTextured())
            {
                // If this is a textured window, we can draw the real background gradient and noise pattern
                var contentBorderThickness = window.TitleBarHeight;
                if (window.IsFullScreen())
                {
                    contentBorderThickness -= window.MinimumTitleBarHeight();
                }
                window.SetAutorecalculatesContentBorderThickness(false, NSRectEdge.MaxYEdge);
                window.SetContentBorderThickness(contentBorderThickness, NSRectEdge.MaxYEdge);
                NSGraphicsExtensions.DrawWindowBackground(drawingRect);
            }
            else
            {
                // Not textured, we have to fake the background gradient and noise pattern
                var drawsAsMainWindow = window.DrawsAsMainWindow();
                var startColor = drawsAsMainWindow ? window.TitleBarStartColor : window.InactiveTitleBarStartColor;
                var endColor = drawsAsMainWindow ? window.TitleBarEndColor : window.InactiveTitleBarEndColor;

                if (startColor == default(NSColor))
                    startColor = AppStoreWindow.DefaultTitleBarStartColor(drawsAsMainWindow);
                if (endColor == default(NSColor))
                    endColor = AppStoreWindow.DefaultTitleBarEndColor(drawsAsMainWindow);

                var context = NSGraphicsContext.CurrentContext.GraphicsPort;
                var gradient = DrawingHelper.CreateGraidentWithColors(startColor, endColor);
                context.DrawLinearGradient(gradient, new PointF(drawingRect.GetMidX(), drawingRect.GetMinY()), new PointF(drawingRect.GetMidX(), drawingRect.GetMaxY()), 0);

                if (drawsAsMainWindow)
                {
                    var noiseRect = new RectangleF(1.0f, 1.0f, drawingRect.Width, drawingRect.Height);

                    if (window.ShowBaselineSeparator)
                    {
                        var separatorHeight = BaselineSeparatorFrame.Height;
                        noiseRect.Y -= separatorHeight;
                        noiseRect.Height += separatorHeight;
                    }

                    NSGraphicsContext.CurrentContext.SaveGraphicsState();
                    var noiseClippingPath = DrawingHelper.CreateClippingPath(noiseRect, CORNER_CLIP_RADIUS);
                    context.AddPath(noiseClippingPath);
                    context.Clip();
                    DrawNoise(0.1f);
                    NSGraphicsContext.CurrentContext.RestoreGraphicsState();
                }
            }
            if (window.ShowBaselineSeparator)
            {
                DrawBaselineSeparator(BaselineSeparatorFrame);
            }
        }
 public override void DrawRect (RectangleF dirtyRect)
 {
         // Don't draw if we don't have a font or a title.
         if (Font == null || Title == string.Empty)
                 return;
         
         // Initialize the text matrix to a known value
         CGContext context = NSGraphicsContext.CurrentContext.GraphicsPort;
         context.TextMatrix = CGAffineTransform.MakeIdentity ();
         
         // Draw a white background
         NSColor.White.Set ();
         context.FillRect (dirtyRect);
         
         //CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)self.attributedString);
         CTLine line = new CTLine (AttributedString);
         
         int glyphCount = line.GlyphCount;
         if (glyphCount == 0)
                 return;
         
         GlyphArcInfo[] glyphArcInfo = new GlyphArcInfo[glyphCount];
         PrepareGlyphArcInfo (line, glyphCount, glyphArcInfo);
         
         // Move the origin from the lower left of the view nearer to its center.
         context.SaveState ();
         context.TranslateCTM (dirtyRect.GetMidX (), dirtyRect.GetMidY () - Radius / 2);
         
         // Stroke the arc in red for verification.
         context.BeginPath ();
         context.AddArc (0, 0, Radius, (float)Math.PI, 0, true);
         context.SetRGBStrokeColor (1, 0, 0, 1);
         context.StrokePath ();
         
         // Rotate the context 90 degrees counterclockwise.
         context.RotateCTM ((float)PI_2);
         
         // Now for the actual drawing. The angle offset for each glyph relative to the previous 
         //      glyph has already been calculated; with that information in hand, draw those glyphs 
         //      overstruck and centered over one another, making sure to rotate the context after each 
         //      glyph so the glyphs are spread along a semicircular path.
         PointF textPosition = new PointF (0, Radius);
         context.TextPosition = textPosition;
         
         var runArray = line.GetGlyphRuns ();
         var runCount = runArray.Count ();
         
         var glyphOffset = 0;
         var runIndex = 0;
         
         for (; runIndex < runCount; runIndex++) {
                 var run = runArray[runIndex];
                 var runGlyphCount = run.GlyphCount;
                 bool drawSubstitutedGlyphsManually = false;
                 CTFont runFont = run.GetAttributes ().Font;
                 
                 // Determine if we need to draw substituted glyphs manually. Do so if the runFont is not 
                 //      the same as the overall font.
                 NSFont rrunFont = new NSFont (runFont.Handle);
                 // used for comparison
                 if (DimsSubstitutedGlyphs && Font != rrunFont) {
                         drawSubstitutedGlyphsManually = true;
                 }
                 
                 var runGlyphIndex = 0;
                 for (; runGlyphIndex < runGlyphCount; runGlyphIndex++) {
                         var glyphRange = new NSRange (runGlyphIndex, 1);
                         context.RotateCTM (-(glyphArcInfo[runGlyphIndex + glyphOffset].angle));
                         
                         // Center this glyph by moving left by half its width.
                         var glyphWidth = glyphArcInfo[runGlyphIndex + glyphOffset].width;
                         var halfGlyphWidth = glyphWidth / 2.0;
                         var positionForThisGlyph = new PointF (textPosition.X - (float)halfGlyphWidth, textPosition.Y);
                         
                         // Glyphs are positioned relative to the text position for the line, so offset text position leftwards by this glyph's 
                         //      width in preparation for the next glyph.
                         textPosition.X -= glyphWidth;
                         
                         CGAffineTransform textMatrix = run.TextMatrix;
                         textMatrix.x0 = positionForThisGlyph.X;
                         textMatrix.y0 = positionForThisGlyph.Y;
                         context.TextMatrix = textMatrix;
                         
                         if (!drawSubstitutedGlyphsManually)
                                 run.Draw (context, glyphRange);
                         else {
                                 
                                 // We need to draw the glyphs manually in this case because we are effectively applying a graphics operation by 
                                 //      setting the context fill color. Normally we would use kCTForegroundColorAttributeName, but this does not apply 
                                 // as we don't know the ranges for the colors in advance, and we wanted demonstrate how to manually draw.
                                 var cgFont = runFont.ToCGFont ();
                                 
                                 var glyph = run.GetGlyphs (glyphRange);
                                 var position = run.GetPositions (glyphRange);
                                 
                                 context.SetFont (cgFont);
                                 context.SetFontSize (runFont.Size);
                                 context.SetRGBFillColor (0.25f, 0.25f, 0.25f, 1);
                                 context.ShowGlyphsAtPositions (glyph, position, 1);
                                 
                         }
                         
                         // Draw the glyph bounds 
                         if (ShowsGlyphBounds) {
                                 
                                 var glyphBounds = run.GetImageBounds (context, glyphRange);
                                 context.SetRGBStrokeColor (0, 0, 1, 1);
                                 context.StrokeRect (glyphBounds);
                         }
                         
                         // Draw the bounding boxes defined by the line metrics
                         if (ShowsLineMetrics) {
                                 
                                 var lineMetrics = new RectangleF ();
                                 float ascent = 0;
                                 float descent = 0;
                                 float leading = 0;
                                 
                                 run.GetTypographicBounds (glyphRange, out ascent, out descent, out leading);
                                 
                                 // The glyph is centered around the y-axis
                                 lineMetrics.Location = new PointF (-(float)halfGlyphWidth, positionForThisGlyph.Y - descent);
                                 lineMetrics.Size = new SizeF (glyphWidth, ascent + descent);
                                 context.SetRGBStrokeColor (0, 1, 0, 1);
                                 context.StrokeRect (lineMetrics);
                         }
                         
                         
                 }
                 
                 glyphOffset += runGlyphCount;
         }
         
         context.RestoreState ();
 }
		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;
			}
		}