Fixed scrollRectToVisible in CPView:

Earlier it only worked when the receiver was the document view of the clip view.
Added test case.
This commit is contained in:
Martin Carlberg
2012-09-28 12:27:23 +02:00
parent a337bc28f9
commit 1d1f2d73ca
2 changed files with 74 additions and 14 deletions
+26 -14
View File
@@ -2359,13 +2359,11 @@ setBoundsOrigin:
*/
- (BOOL)scrollRectToVisible:(CGRect)aRect
{
var visibleRect = [self visibleRect];
// Make sure we have a rect that exists.
aRect = CGRectIntersection(aRect, _bounds);
// If aRect is empty or is already visible then no scrolling required.
if (_CGRectIsEmpty(aRect) || CGRectContainsRect(visibleRect, aRect))
// If aRect is empty no scrolling required.
if (CGRectIsEmpty(aRect))
return NO;
var enclosingClipView = [self _enclosingClipView];
@@ -2374,20 +2372,34 @@ setBoundsOrigin:
if (!enclosingClipView)
return NO;
var scrollPoint = _CGPointMakeCopy(visibleRect.origin);
var documentView = [enclosingClipView documentView];
// If the clip view doesn't have a document view, then there isn't much we can do.
if (!documentView)
return NO;
// Get the document view visible rect and convert aRect to the document view's coordinate system
var documentViewVisibleRect = [documentView visibleRect],
rectInDocumentView = [self convertRect:aRect toView:documentView];
// If already visible then no scrolling required.
if (CGRectContainsRect(documentViewVisibleRect, rectInDocumentView))
return NO;
var scrollPoint = CGPointMakeCopy(documentViewVisibleRect.origin);
// One of the following has to be true since our current visible rect didn't contain aRect.
if (_CGRectGetMinX(aRect) <= _CGRectGetMinX(visibleRect))
scrollPoint.x = _CGRectGetMinX(aRect);
else if (_CGRectGetMaxX(aRect) > _CGRectGetMaxX(visibleRect))
scrollPoint.x += _CGRectGetMaxX(aRect) - _CGRectGetMaxX(visibleRect);
if (_CGRectGetMinX(rectInDocumentView) < _CGRectGetMinX(documentViewVisibleRect))
scrollPoint.x = _CGRectGetMinX(rectInDocumentView);
else if (_CGRectGetMaxX(rectInDocumentView) > _CGRectGetMaxX(documentViewVisibleRect))
scrollPoint.x += _CGRectGetMaxX(rectInDocumentView) - _CGRectGetMaxX(documentViewVisibleRect);
if (_CGRectGetMinY(aRect) <= _CGRectGetMinY(visibleRect))
scrollPoint.y = CGRectGetMinY(aRect);
else if (_CGRectGetMaxY(aRect) > _CGRectGetMaxY(visibleRect))
scrollPoint.y += _CGRectGetMaxY(aRect) - _CGRectGetMaxY(visibleRect);
if (_CGRectGetMinY(rectInDocumentView) < _CGRectGetMinY(documentViewVisibleRect))
scrollPoint.y = _CGRectGetMinY(rectInDocumentView);
else if (_CGRectGetMaxY(rectInDocumentView) > _CGRectGetMaxY(documentViewVisibleRect))
scrollPoint.y += _CGRectGetMaxY(rectInDocumentView) - _CGRectGetMaxY(documentViewVisibleRect);
[enclosingClipView scrollToPoint:CGPointMake(scrollPoint.x, scrollPoint.y)];
[enclosingClipView scrollToPoint:scrollPoint];
return YES;
}
+48
View File
@@ -214,5 +214,53 @@
[self assert:replacementDocumentView equals:[scrollView documentView] message:@"documentView was not replaced properly"];
}
- (void)testScrollRectToVisible
{
var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)],
documentView = [[CPView alloc] initWithFrame:CGRectMake(0, 0, 1000, 1000)],
textField1 = [CPTextField textFieldWithStringValue:@"Martin" placeholder:@"" width:10],
textField2 = [CPTextField textFieldWithStringValue:@"Malte" placeholder:@"" width:10],
textField1Size = CGSizeMakeCopy([textField1 bounds].size),
textField2Size = CGSizeMakeCopy([textField2 bounds].size);
[scrollView setDocumentView:documentView];
[textField1 setFrameOrigin:CGPointMake(0, 0)];
[textField2 setFrameOrigin:CGPointMake(500, 500)];
[documentView addSubview:textField1];
[documentView addSubview:textField2];
var visibleRect = [documentView visibleRect],
originalVisibleSize = CGSizeMakeCopy(visibleRect.size);
// Make sure we are at the top left corner
[self assertPoint:CGPointMake(0, 0) equals:visibleRect.origin message:@"VisibleRect origin not at top left corner"];
// Make the second text field visible
[textField2 scrollRectToVisible:[textField2 bounds]];
var visibleRectOriginShouldBeAt = CGPointMake(500 - originalVisibleSize.width + textField2Size.width, 500 -originalVisibleSize.height + textField2Size.height);
visibleRect = [documentView visibleRect];
// We should now have the text field in the lower right corner
[self assertPoint:visibleRectOriginShouldBeAt equals:visibleRect.origin message:@"Second text field not at lower right corner in visible rect"];
// Make the first text field visible again
[textField1 scrollRectToVisible:[textField2 bounds]];
visibleRect = [documentView visibleRect];
// We should now be back at top left corner
[self assertPoint:CGPointMake(0, 0) equals:visibleRect.origin message:@"VisibleRect origin not at top left corner again"];
}
- (void)assertPoint:(CGPoint)expected equals:(CGPoint)actual message:(CPString)message
{
[self assert:expected.x equals:actual.x message:@"X: " + message];
[self assert:expected.y equals:actual.y message:@"Y: " + message];
}
@end