This repository was archived by the owner on Jun 8, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 111
Use next edge when preferred edge rect would be out of bounds #132
Merged
Merged
Changes from all commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
50a52ae
Separate arrow coordinate calculations from CGPath stuff
joshvera 905a29e
Remove arrow shrinking
joshvera 17f8464
Change demo to show popover relative to button bounds
joshvera c6ba986
Add popover anchor point and didOffsetFrame properties to RBLBackgrou…
joshvera d5cbe5b
Flip the edge if the proposed rect for the preferred edge is offscreen
joshvera 2795024
Merge remote-tracking branch 'origin/master' into popover-edge-fixes
joshvera 8846e44
Just set ivar
joshvera 26ec75b
style
joshvera 7c73e63
Replace M_PI / 2 with M_PI_2
joshvera 92b4ad2
Replace NSMax uses with maxX, maxY
joshvera 3f60097
Clean up popover path calculations
joshvera f28d565
Use next edge if screen rect doesn't contain the preferred edge
joshvera 1fbeeaf
Dont use midOriginY
joshvera 7a7b98e
Calculate based on window visible frame
joshvera 4366d3e
Dont forget to set else case
joshvera 4a2b244
Position positioningRect using -alignmentRectForFrame:
joshvera 5a4c6d1
Go back to using the median x and y to calculate mid origin x and y
joshvera 4d96766
Remove -didOffsetFrame
joshvera 06aba4e
Remove -popoverAnchorPoint
joshvera 725f53d
No need to set the popoverEdge again
joshvera deb6fcc
Clean up arrow variables
joshvera 1bdf150
No need to draw beginning point
joshvera b44ae6a
s/Midpoint/Centerpoint
joshvera File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -177,11 +177,11 @@ - (void)showRelativeToRect:(CGRect)positioningRect ofView:(NSView *)positioningV | |
positioningRect = [positioningView bounds]; | ||
} | ||
|
||
NSRect windowRelativeRect = [positioningView convertRect:positioningRect toView:nil]; | ||
NSRect windowRelativeRect = [positioningView convertRect:[positioningView alignmentRectForFrame:positioningRect] toView:nil]; | ||
CGRect screenRect = [positioningView.window convertRectToScreen:windowRelativeRect]; | ||
|
||
self.backgroundView.popoverOrigin = screenRect; | ||
|
||
self.originalViewSize = self.contentViewController.view.frame.size; | ||
CGSize contentViewSize = (CGSizeEqualToSize(self.contentSize, CGSizeZero) ? self.contentViewController.view.frame.size : self.contentSize); | ||
|
||
|
@@ -269,27 +269,43 @@ - (void)showRelativeToRect:(CGRect)positioningRect ofView:(NSView *)positioningV | |
|
||
return proposedRect; | ||
}; | ||
|
||
|
||
BOOL (^screenRectContainsRectEdge)(CGRectEdge) = ^ BOOL (CGRectEdge edge) { | ||
CGRect proposedRect = popoverRectForEdge(edge); | ||
NSRect screenRect = positioningView.window.screen.visibleFrame; | ||
|
||
BOOL minYInBounds = (edge == CGRectMinYEdge && NSMinY(proposedRect) >= NSMinY(screenRect)); | ||
BOOL maxYInBounds = (edge == CGRectMaxYEdge && NSMaxY(proposedRect) <= NSMaxY(screenRect)); | ||
BOOL minXInBounds = (edge == CGRectMinXEdge && NSMinX(proposedRect) >= NSMinX(screenRect)); | ||
BOOL maxXInBounds = (edge == CGRectMaxXEdge && NSMaxX(proposedRect) <= NSMaxX(screenRect)); | ||
|
||
return minYInBounds || maxYInBounds || minXInBounds || maxXInBounds; | ||
}; | ||
|
||
NSUInteger attemptCount = 0; | ||
while (!checkPopoverSizeForScreenWithPopoverEdge(popoverEdge)) { | ||
if (attemptCount >= 4) { | ||
popoverEdge = preferredEdge; | ||
popoverEdge = (screenRectContainsRectEdge(preferredEdge) ? preferredEdge : nextEdgeForEdge(preferredEdge)); | ||
|
||
return fitRectToScreen(popoverRectForEdge(popoverEdge)); | ||
break; | ||
} | ||
|
||
popoverEdge = nextEdgeForEdge(popoverEdge); | ||
attemptCount ++; | ||
} | ||
|
||
return popoverRectForEdge(popoverEdge); | ||
}; | ||
|
||
CGRect popoverScreenRect = popoverRect(); | ||
|
||
if (self.shown) { | ||
if (self.backgroundView.popoverEdge == popoverEdge) { | ||
CGSize size = [self.backgroundView sizeForBackgroundViewWithContentSize:contentViewSize popoverEdge:popoverEdge]; | ||
self.backgroundView.frame = (NSRect){ .size = size }; | ||
[self.popoverWindow setFrame:popoverScreenRect display:YES]; | ||
|
||
return; | ||
} | ||
|
||
|
@@ -495,9 +511,9 @@ - (CGPathRef)newPopoverPathForEdge:(CGRectEdge)popoverEdge inFrame:(CGRect)frame | |
|
||
CGRect windowRect = [self.window convertRectFromScreen:self.popoverOrigin]; | ||
CGRect originRect = [self convertRect:windowRect fromView:nil]; | ||
CGFloat midOriginY = floor(RBLRectsGetMedianY(originRect, contentRect)); | ||
CGFloat midOriginX = floor(RBLRectsGetMedianX(originRect, contentRect)); | ||
|
||
CGFloat midOriginY = floor(RBLRectsGetMedianY(originRect, contentRect)); | ||
|
||
CGFloat maxArrowX = 0.0; | ||
CGFloat minArrowX = 0.0; | ||
CGFloat minArrowY = 0.0; | ||
|
@@ -512,65 +528,79 @@ - (CGPathRef)newPopoverPathForEdge:(CGRectEdge)popoverEdge inFrame:(CGRect)frame | |
maxArrowX = floor(midOriginX + (self.arrowSize.width / 2.0)); | ||
CGFloat maxPossible = (NSMaxX(contentRect) - RBLPopoverBackgroundViewBorderRadius); | ||
if (maxArrowX > maxPossible) { | ||
CGFloat delta = maxArrowX - maxPossible; | ||
maxArrowX = maxPossible; | ||
minArrowX = maxArrowX - (self.arrowSize.width - delta); | ||
minArrowX = maxArrowX - self.arrowSize.width; | ||
} else { | ||
minArrowX = floor(midOriginX - (self.arrowSize.width / 2.0)); | ||
if (minArrowX < RBLPopoverBackgroundViewBorderRadius) { | ||
CGFloat delta = RBLPopoverBackgroundViewBorderRadius - minArrowX; | ||
minArrowX = RBLPopoverBackgroundViewBorderRadius; | ||
maxArrowX = minArrowX + (self.arrowSize.width - (delta * 2)); | ||
maxArrowX = minArrowX + self.arrowSize.width; | ||
} | ||
} | ||
} else { | ||
minArrowY = floor(midOriginY - (self.arrowSize.width / 2.0)); | ||
if (minArrowY < RBLPopoverBackgroundViewBorderRadius) { | ||
CGFloat delta = RBLPopoverBackgroundViewBorderRadius - minArrowY; | ||
minArrowY = RBLPopoverBackgroundViewBorderRadius; | ||
maxArrowY = minArrowY + (self.arrowSize.width - (delta * 2)); | ||
maxArrowY = minArrowY + self.arrowSize.width; | ||
} else { | ||
maxArrowY = floor(midOriginY + (self.arrowSize.width / 2.0)); | ||
CGFloat maxPossible = (NSMaxY(contentRect) - RBLPopoverBackgroundViewBorderRadius); | ||
if (maxArrowY > maxPossible) { | ||
CGFloat delta = maxArrowY - maxPossible; | ||
maxArrowY = maxPossible; | ||
minArrowY = maxArrowY - (self.arrowSize.width - delta); | ||
minArrowY = maxArrowY - self.arrowSize.width; | ||
} | ||
} | ||
} | ||
|
||
|
||
// These represent the centerpoints of the popover's corner arcs. | ||
CGFloat minCenterpointX = floor(minX + RBLPopoverBackgroundViewBorderRadius); | ||
CGFloat maxCenterpointX = floor(maxX - RBLPopoverBackgroundViewBorderRadius); | ||
CGFloat minCenterpointY = floor(minY + RBLPopoverBackgroundViewBorderRadius); | ||
CGFloat maxCenterpointY = floor(maxY - RBLPopoverBackgroundViewBorderRadius); | ||
|
||
CGMutablePathRef path = CGPathCreateMutable(); | ||
CGPathMoveToPoint(path, NULL, minX, floor(minY + RBLPopoverBackgroundViewBorderRadius)); | ||
if (arrowEdge == CGRectMinXEdge) { | ||
CGPathAddLineToPoint(path, NULL, minX, minArrowY); | ||
CGPathAddLineToPoint(path, NULL, floor(minX - self.arrowSize.height), midOriginY); | ||
CGPathAddLineToPoint(path, NULL, minX, maxArrowY); | ||
} | ||
|
||
CGPathAddArc(path, NULL, floor(minX + RBLPopoverBackgroundViewBorderRadius), floor(minY + contentRect.size.height - RBLPopoverBackgroundViewBorderRadius), RBLPopoverBackgroundViewBorderRadius, M_PI, M_PI / 2, 1); | ||
if (arrowEdge == CGRectMaxYEdge) { | ||
CGPathAddLineToPoint(path, NULL, minArrowX, maxY); | ||
CGPathAddLineToPoint(path, NULL, midOriginX, floor(maxY + self.arrowSize.height)); | ||
CGPathAddLineToPoint(path, NULL, maxArrowX, maxY); | ||
} | ||
|
||
CGPathAddArc(path, NULL, floor(minX + contentRect.size.width - RBLPopoverBackgroundViewBorderRadius), floor(minY + contentRect.size.height - RBLPopoverBackgroundViewBorderRadius), RBLPopoverBackgroundViewBorderRadius, M_PI / 2, 0.0, 1); | ||
if (arrowEdge == CGRectMaxXEdge) { | ||
CGPathAddLineToPoint(path, NULL, maxX, maxArrowY); | ||
CGPathAddLineToPoint(path, NULL, floor(maxX + self.arrowSize.height), midOriginY); | ||
CGPathAddLineToPoint(path, NULL, maxX, minArrowY); | ||
} | ||
|
||
CGPathAddArc(path, NULL, floor(contentRect.origin.x + contentRect.size.width - RBLPopoverBackgroundViewBorderRadius), floor(minY + RBLPopoverBackgroundViewBorderRadius), RBLPopoverBackgroundViewBorderRadius, 0.0, -M_PI / 2, 1); | ||
if (arrowEdge == CGRectMinYEdge) { | ||
CGPathAddLineToPoint(path, NULL, maxArrowX, minY); | ||
CGPathAddLineToPoint(path, NULL, midOriginX, floor(minY - self.arrowSize.height)); | ||
CGPathAddLineToPoint(path, NULL, minArrowX, minY); | ||
CGPathMoveToPoint(path, NULL, minX, minCenterpointY); | ||
|
||
CGFloat radius = RBLPopoverBackgroundViewBorderRadius; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you're putting the radius into a variable here, can you use it in the |
||
|
||
CGPathAddArc(path, NULL, minCenterpointX, maxCenterpointY, radius, M_PI, M_PI_2, true); | ||
|
||
CGPathAddArc(path, NULL, maxCenterpointX, maxCenterpointY, radius, M_PI_2, 0, true); | ||
|
||
CGPathAddArc(path, NULL, maxCenterpointX, minCenterpointY, radius, 0, -M_PI_2, true); | ||
|
||
CGPathAddArc(path, NULL, minCenterpointX, minCenterpointY, radius, -M_PI_2, M_PI, true); | ||
|
||
CGPoint minBasePoint, tipPoint, maxBasePoint; | ||
switch (arrowEdge) { | ||
case CGRectMinXEdge: | ||
minBasePoint = CGPointMake(minX, minArrowY); | ||
tipPoint = CGPointMake(floor(minX - self.arrowSize.height), floor((minArrowY + maxArrowY) / 2)); | ||
maxBasePoint = CGPointMake(minX, maxArrowY); | ||
break; | ||
case CGRectMaxYEdge: | ||
minBasePoint = CGPointMake(minArrowX, maxY); | ||
tipPoint = CGPointMake(floor((minArrowX + maxArrowX) / 2), floor(maxY + self.arrowSize.height)); | ||
maxBasePoint = CGPointMake(maxArrowX, maxY); | ||
break; | ||
case CGRectMaxXEdge: | ||
minBasePoint = CGPointMake(maxX, minArrowY); | ||
tipPoint = CGPointMake(floor(maxX + self.arrowSize.height), floor((minArrowY + maxArrowY) / 2)); | ||
maxBasePoint = CGPointMake(maxX, maxArrowY); | ||
break; | ||
case CGRectMinYEdge: | ||
minBasePoint = CGPointMake(minArrowX, minY); | ||
tipPoint = CGPointMake(floor((minArrowX + maxArrowX) / 2), floor(minY - self.arrowSize.height)); | ||
maxBasePoint = CGPointMake(maxArrowX, minY); | ||
break; | ||
default: | ||
break; | ||
} | ||
|
||
CGPathAddArc(path, NULL, floor(minX + RBLPopoverBackgroundViewBorderRadius), floor(minY + RBLPopoverBackgroundViewBorderRadius), RBLPopoverBackgroundViewBorderRadius, -M_PI / 2, M_PI, 1); | ||
|
||
|
||
CGPathMoveToPoint(path, NULL, minBasePoint.x, minBasePoint.y); | ||
CGPathAddLineToPoint(path, NULL, tipPoint.x, tipPoint.y); | ||
CGPathAddLineToPoint(path, NULL, maxBasePoint.x, maxBasePoint.y); | ||
|
||
return path; | ||
} | ||
|
||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are equivalent, FWIW.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍