diff --git a/AppKit/CPScrollView.j b/AppKit/CPScrollView.j index 424b43f06..06d45eca3 100644 --- a/AppKit/CPScrollView.j +++ b/AppKit/CPScrollView.j @@ -5,6 +5,10 @@ * Created by Francisco Tolmasky. * Copyright 2008, 280 North, Inc. * + * Modified to match Lion style by Antoine Mercadal 2011 + * + * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -70,9 +74,13 @@ var TIMER_INTERVAL = 0.2, CPTimer _timerScrollersHide; - int _scrollerStyle @accessors(getter=scrollerStyle); + int _scrollerStyle; } + +#pragma mark - +#pragma mark Class methods + + (CPString)defaultThemeClass { return @"scrollview" @@ -86,97 +94,6 @@ var TIMER_INTERVAL = 0.2, }]; } -- (id)initWithFrame:(CGRect)aFrame -{ - self = [super initWithFrame:aFrame]; - - if (self) - { - _verticalLineScroll = 10.0; - _verticalPageScroll = 10.0; - - _horizontalLineScroll = 10.0; - _horizontalPageScroll = 10.0; - - _borderType = CPNoBorder; - - _contentView = [[CPClipView alloc] initWithFrame:[self _insetBounds]]; - [self addSubview:_contentView]; - - _headerClipView = [[CPClipView alloc] init]; - [self addSubview:_headerClipView]; - - _bottomCornerView = [[CPView alloc] init]; - [self addSubview:_bottomCornerView]; - - [self setHasVerticalScroller:YES]; - [self setHasHorizontalScroller:YES]; - [self setScrollerStyle:CPScrollerStyleOverlay]; - - _delegate = nil; - _scrollTimer = nil; - _implementedDelegateMethods = 0; - } - - return self; -} - -- (id)delegate -{ - return _delegate; -} - -- (void)setDelegate:(id)aDelegate -{ - if (aDelegate === _delegate) - return; - - _delegate = aDelegate; - _implementedDelegateMethods = 0; - - if (_delegate === nil) - return; - - if ([_delegate respondsToSelector:@selector(scrollViewWillScroll:)]) - _implementedDelegateMethods |= CPScrollViewDelegate_scrollViewWillScroll_; - - if ([_delegate respondsToSelector:@selector(scrollViewDidScroll:)]) - _implementedDelegateMethods |= CPScrollViewDelegate_scrollViewDidScroll_; -} - -/*! - Set the scroller styles - - CPScrollerStyleLegacy: Standard scroller like prior 10.7 - - CPScrollerStyleOverlay: scrollers like 10.7+ -*/ -- (void)setScrollerStyle:(int)aStyle -{ - if (_scrollerStyle == aStyle) - return; - - _scrollerStyle = aStyle; - - [self _updateScrollerStyle]; -} - -- (void)_updateScrollerStyle -{ - if (_hasHorizontalScroller) - { - [_horizontalScroller setStyle:_scrollerStyle]; - [_horizontalScroller unsetThemeState:CPThemeStateSelected]; - } - if (_hasVerticalScroller) - { - [_verticalScroller setStyle:_scrollerStyle]; - [_verticalScroller unsetThemeState:CPThemeStateSelected]; - } - - [self reflectScrolledClipView:_contentView]; -} - -// Calculating Layout - + (CGSize)contentSizeForFrameSize:(CGSize)frameSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType { var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType], @@ -228,26 +145,104 @@ var TIMER_INTERVAL = 0.2, } } -- (CGRect)_insetBounds + +#pragma mark - +#pragma mark Initialization + +- (id)initWithFrame:(CGRect)aFrame { - return [[self class] _insetBounds:[self bounds] borderType:_borderType]; + self = [super initWithFrame:aFrame]; + + if (self) + { + _verticalLineScroll = 10.0; + _verticalPageScroll = 10.0; + + _horizontalLineScroll = 10.0; + _horizontalPageScroll = 10.0; + + _borderType = CPNoBorder; + + _contentView = [[CPClipView alloc] initWithFrame:[self _insetBounds]]; + [self addSubview:_contentView]; + + _headerClipView = [[CPClipView alloc] init]; + [self addSubview:_headerClipView]; + + _bottomCornerView = [[CPView alloc] init]; + [self addSubview:_bottomCornerView]; + + [self setHasVerticalScroller:YES]; + [self setHasHorizontalScroller:YES]; + [self setScrollerStyle:CPScrollerStyleOverlay]; + + _delegate = nil; + _scrollTimer = nil; + _implementedDelegateMethods = 0; + } + + return self; } -// Determining component sizes + +#pragma mark - +#pragma mark Getters / Setters + /*! - Returns the size of the scroll view's content view. + The delegate of the scrol view */ -- (CGSize)contentSize +- (id)delegate { - return [_contentView frame].size; + return _delegate; } /*! - Returns the view that is scrolled for the user. + Set the delegate of the scroll view */ -- (id)documentView +- (void)setDelegate:(id)aDelegate { - return [_contentView documentView]; + if (aDelegate === _delegate) + return; + + _delegate = aDelegate; + _implementedDelegateMethods = 0; + + if (_delegate === nil) + return; + + if ([_delegate respondsToSelector:@selector(scrollViewWillScroll:)]) + _implementedDelegateMethods |= CPScrollViewDelegate_scrollViewWillScroll_; + + if ([_delegate respondsToSelector:@selector(scrollViewDidScroll:)]) + _implementedDelegateMethods |= CPScrollViewDelegate_scrollViewDidScroll_; +} + +- (int)scrollerStyle +{ + return _scrollerStyle; +} + +/*! + Set the scroller styles + - CPScrollerStyleLegacy: Standard scroller like prior 10.7 + - CPScrollerStyleOverlay: scrollers like 10.7+ +*/ +- (void)setScrollerStyle:(int)aStyle +{ + if (_scrollerStyle == aStyle) + return; + + _scrollerStyle = aStyle; + + [self _updateScrollerStyle]; +} + +/*! + Returns the content view that clips the document. +*/ +- (CPClipView)contentView +{ + return _contentView; } /*! @@ -276,12 +271,21 @@ var TIMER_INTERVAL = 0.2, [self reflectScrolledClipView:_contentView]; } + /*! - Returns the content view that clips the document. + Returns the size of the scroll view's content view. */ -- (CPClipView)contentView +- (CGSize)contentSize { - return _contentView; + return [_contentView frame].size; +} + +/*! + Returns the view that is scrolled for the user. +*/ +- (id)documentView +{ + return [_contentView documentView]; } /*! @@ -297,6 +301,560 @@ var TIMER_INTERVAL = 0.2, [self reflectScrolledClipView:_contentView]; } +/*! + Returns the border type drawn around the view. +*/ +- (CPBorderType)borderType +{ + return _borderType; +} + +/*! + Sets the type of border to be drawn around the view. + Valid types are: +
+    CPNoBorder
+    CPLineBorder
+    CPBezelBorder
+    CPGrooveBorder
+*/ +- (void)setBorderType:(CPBorderType)borderType +{ + if (_borderType == borderType) + return; + + _borderType = borderType; + + [self reflectScrolledClipView:_contentView]; + [self setNeedsDisplay:YES]; +} + + +/*! + Returns the scroll view's horizontal scroller +*/ +- (CPScroller)horizontalScroller +{ + return _horizontalScroller; +} + +/*! + Sets the scroll view's horizontal scroller. + @param aScroller the horizontal scroller for the scroll view +*/ +- (void)setHorizontalScroller:(CPScroller)aScroller +{ + if (_horizontalScroller === aScroller) + return; + + [_horizontalScroller removeFromSuperview]; + [_horizontalScroller setTarget:nil]; + [_horizontalScroller setAction:nil]; + + _horizontalScroller = aScroller; + + [_horizontalScroller setTarget:self]; + [_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)]; + + [self addSubview:_horizontalScroller]; + + [self _updateScrollerStyle]; +} + +/*! + Returns \c YES if the scroll view can have a horizontal scroller. +*/ +- (BOOL)hasHorizontalScroller +{ + return _hasHorizontalScroller; +} + +/*! + Specifies whether the scroll view can have a horizontal scroller. + @param hasHorizontalScroller \c YES lets the scroll view + allocate a horizontal scroller if necessary. +*/ +- (void)setHasHorizontalScroller:(BOOL)shouldHaveHorizontalScroller +{ + if (_hasHorizontalScroller === shouldHaveHorizontalScroller) + return; + + _hasHorizontalScroller = shouldHaveHorizontalScroller; + + if (_hasHorizontalScroller && !_horizontalScroller) + { + var bounds = [self _insetBounds]; + + [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]]; + [[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])]; + } + + [self reflectScrolledClipView:_contentView]; +} + +/*! + Return's the scroll view's vertical scroller +*/ +- (CPScroller)verticalScroller +{ + return _verticalScroller; +} + +/*! + Sets the scroll view's vertical scroller. + @param aScroller the vertical scroller +*/ +- (void)setVerticalScroller:(CPScroller)aScroller +{ + if (_verticalScroller === aScroller) + return; + + [_verticalScroller removeFromSuperview]; + [_verticalScroller setTarget:nil]; + [_verticalScroller setAction:nil]; + + _verticalScroller = aScroller; + + [_verticalScroller setTarget:self]; + [_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)]; + + [self addSubview:_verticalScroller]; + + [self _updateScrollerStyle]; +} + +/*! + Returns \c YES if the scroll view can have a vertical scroller. +*/ +- (BOOL)hasVerticalScroller +{ + return _hasVerticalScroller; +} + +/*! + Specifies whether the scroll view has can have + a vertical scroller. It allocates it if necessary. + @param hasVerticalScroller \c YES allows + the scroll view to display a vertical scroller +*/ +- (void)setHasVerticalScroller:(BOOL)shouldHaveVerticalScroller +{ + if (_hasVerticalScroller === shouldHaveVerticalScroller) + return; + + _hasVerticalScroller = shouldHaveVerticalScroller; + + if (_hasVerticalScroller && !_verticalScroller) + { + var bounds = [self _insetBounds]; + + [self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(_CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]]; + [[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], _CGRectGetHeight(bounds))]; + } + + [self reflectScrolledClipView:_contentView]; +} + +/*! + Returns \c YES if the scroll view hides its scroll + bars when not necessary. +*/ +- (BOOL)autohidesScrollers +{ + return _autohidesScrollers; +} + +/*! + Sets whether the scroll view hides its scroll bars when not needed. + @param autohidesScrollers \c YES causes the scroll bars + to be hidden when not needed. +*/ +- (void)setAutohidesScrollers:(BOOL)autohidesScrollers +{ + if (_autohidesScrollers == autohidesScrollers) + return; + + _autohidesScrollers = autohidesScrollers; + + [self reflectScrolledClipView:_contentView]; +} + +- (CPView)bottomCornerView +{ + return _bottomCornerView; +} + +- (void)setBottomCornerView:(CPView)aBottomCornerView +{ + if (_bottomCornerView === aBottomCornerView) + return; + + [_bottomCornerView removeFromSuperview]; + + [aBottomCornerView setFrame:[self _bottomCornerViewFrame]]; + [self addSubview:aBottomCornerView]; + + _bottomCornerView = aBottomCornerView; + + [self _updateCornerAndHeaderView]; +} + +/*! + Returns how much the document moves when scrolled +*/ +- (float)lineScroll +{ + return [self horizontalLineScroll]; +} + +/*! + Sets how much the document moves when scrolled. Sets the vertical and horizontal scroll. + @param aLineScroll the amount to move the document when scrolled +*/ +- (void)setLineScroll:(float)aLineScroll +{ + [self setHorizontalLineScroll:aLineScroll]; + [self setVerticalLineScroll:aLineScroll]; +} + +/*! + Returns how much the document moves horizontally when scrolled. +*/ +- (float)horizontalLineScroll +{ + return _horizontalLineScroll; +} + +/*! + Sets how much the document moves when scrolled horizontally. + @param aLineScroll the amount to move horizontally when scrolled. +*/ +- (void)setHorizontalLineScroll:(float)aLineScroll +{ + _horizontalLineScroll = aLineScroll; +} + +/*! + Returns how much the document moves vertically when scrolled. +*/ +- (float)verticalLineScroll +{ + return _verticalLineScroll; +} + +/*! + Sets how much the document moves when scrolled vertically. + @param aLineScroll the new amount to move vertically when scrolled. +*/ +- (void)setVerticalLineScroll:(float)aLineScroll +{ + _verticalLineScroll = aLineScroll; +} + +/*! + Returns the vertical and horizontal page scroll amount. +*/ +- (float)pageScroll +{ + return [self horizontalPageScroll]; +} + +/*! + Sets the horizontal and vertical page scroll amount. + @param aPageScroll the new horizontal and vertical page scroll amount +*/ +- (void)setPageScroll:(float)aPageScroll +{ + [self setHorizontalPageScroll:aPageScroll]; + [self setVerticalPageScroll:aPageScroll]; +} + +/*! + Returns the horizontal page scroll amount. +*/ +- (float)horizontalPageScroll +{ + return _horizontalPageScroll; +} + +/*! + Sets the horizontal page scroll amount. + @param aPageScroll the new horizontal page scroll amount +*/ +- (void)setHorizontalPageScroll:(float)aPageScroll +{ + _horizontalPageScroll = aPageScroll; +} + +/*! + Returns the vertical page scroll amount. +*/ +- (float)verticalPageScroll +{ + return _verticalPageScroll; +} + +/*! + Sets the vertical page scroll amount. + @param aPageScroll the new vertical page scroll amount +*/ +- (void)setVerticalPageScroll:(float)aPageScroll +{ + _verticalPageScroll = aPageScroll; +} + + +#pragma mark - +#pragma mark Utilities + +/* @ignore */ +- (void)_updateScrollerStyle +{ + if (_hasHorizontalScroller) + { + [_horizontalScroller setStyle:_scrollerStyle]; + [_horizontalScroller unsetThemeState:CPThemeStateSelected]; + } + if (_hasVerticalScroller) + { + [_verticalScroller setStyle:_scrollerStyle]; + [_verticalScroller unsetThemeState:CPThemeStateSelected]; + } + + [self reflectScrolledClipView:_contentView]; +} + +/* @ignore */ +- (CGRect)_insetBounds +{ + return [[self class] _insetBounds:[self bounds] borderType:_borderType]; +} + +/* @ignore */ +- (void)_updateCornerAndHeaderView +{ + var documentView = [self documentView], + currentHeaderView = [self _headerView], + documentHeaderView = [documentView respondsToSelector:@selector(headerView)] ? [documentView headerView] : nil; + + if (currentHeaderView !== documentHeaderView) + { + [currentHeaderView removeFromSuperview]; + [_headerClipView setDocumentView:documentHeaderView]; + } + + var documentCornerView = [documentView respondsToSelector:@selector(cornerView)] ? [documentView cornerView] : nil; + + if (_cornerView !== documentCornerView) + { + [_cornerView removeFromSuperview]; + + _cornerView = documentCornerView; + + if (_cornerView) + [self addSubview:_cornerView]; + } + + [self reflectScrolledClipView:_contentView]; +} + +/* @ignore */ +- (CPView)_headerView +{ + return [_headerClipView documentView]; +} + +/* @ignore */ +- (CGRect)_cornerViewFrame +{ + if (!_cornerView) + return _CGRectMakeZero(); + + var bounds = [self _insetBounds], + frame = [_cornerView frame]; + + frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame); + frame.origin.y = _CGRectGetMinY(bounds); + + return frame; +} + +/* @ignore */ +- (CGRect)_headerClipViewFrame +{ + var headerView = [self _headerView]; + + if (!headerView) + return _CGRectMakeZero(); + + var frame = [self _insetBounds]; + + frame.size.height = _CGRectGetHeight([headerView frame]); + frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]); + + return frame; +} + +/* @ignore */ +- (CGRect)_bottomCornerViewFrame +{ + if ([[self horizontalScroller] isHidden] || [[self verticalScroller] isHidden]) + return CGRectMakeZero(); + + var verticalFrame = [[self verticalScroller] frame], + bottomCornerFrame = CGRectMakeZero(); + + bottomCornerFrame.origin.x = CGRectGetMinX(verticalFrame); + bottomCornerFrame.origin.y = CGRectGetMaxY(verticalFrame); + bottomCornerFrame.size.width = [CPScroller scrollerWidthInStyle:_scrollerStyle]; + bottomCornerFrame.size.height = [CPScroller scrollerWidthInStyle:_scrollerStyle]; + + return bottomCornerFrame; +} + +/* @ignore */ +- (void)_verticalScrollerDidScroll:(CPScroller)aScroller +{ + var value = [aScroller floatValue], + documentFrame = [[_contentView documentView] frame], + contentBounds = [_contentView bounds]; + + switch ([_verticalScroller hitPart]) + { + case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll; + break; + + case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll; + break; + + case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll; + break; + + case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll; + break; + + case CPScrollerKnobSlot: + case CPScrollerKnob: + // We want integral bounds! + default: contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds))); + } + + [self _sendDelegateMessages]; + + [_contentView scrollToPoint:contentBounds.origin]; +} + +/* @ignore */ +- (void)_horizontalScrollerDidScroll:(CPScroller)aScroller +{ + var value = [aScroller floatValue], + documentFrame = [[self documentView] frame], + contentBounds = [_contentView bounds]; + + switch ([_horizontalScroller hitPart]) + { + case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll; + break; + + case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll; + break; + + case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll; + break; + + case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll; + break; + + case CPScrollerKnobSlot: + case CPScrollerKnob: + // We want integral bounds! + default: contentBounds.origin.x = ROUND(value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds))); + } + + [self _sendDelegateMessages]; + + [_contentView scrollToPoint:contentBounds.origin]; + [_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)]; +} + +/* @ignore */ +- (void)_sendDelegateMessages +{ + if (_implementedDelegateMethods == 0) + return; + + if (!_scrollTimer) + { + [self _scrollViewWillScroll]; + _scrollTimer = [CPTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(_scrollViewDidScroll) userInfo:nil repeats:YES]; + } + else + [_scrollTimer setFireDate:[CPDate dateWithTimeIntervalSinceNow:TIMER_INTERVAL]]; +} + +/* @ignore */ +- (void)_hideScrollers:(CPTimer)theTimer +{ + if ([_verticalScroller allowFadingOut]) + [_verticalScroller fadeOut]; + if ([_horizontalScroller allowFadingOut]) + [_horizontalScroller fadeOut]; + _timerScrollersHide = nil; +} + +/* @ignore */ +- (void)_respondToScrollWheelEventWithDeltaX:(float)deltaX deltaY:(float)deltaY +{ + var documentFrame = [[self documentView] frame], + contentBounds = [_contentView bounds], + contentFrame = [_contentView frame], + enclosingScrollView = [self enclosingScrollView]; + + // We want integral bounds! + contentBounds.origin.x = ROUND(contentBounds.origin.x + deltaX); + contentBounds.origin.y = ROUND(contentBounds.origin.y + deltaY); + + var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)], + extraX = contentBounds.origin.x - constrainedOrigin.x, + extraY = contentBounds.origin.y - constrainedOrigin.y; + + [self _sendDelegateMessages]; + + [_contentView scrollToPoint:constrainedOrigin]; + [_headerClipView scrollToPoint:CGPointMake(constrainedOrigin.x, 0.0)]; + + if (extraX || extraY) + [enclosingScrollView _respondToScrollWheelEventWithDeltaX:extraX deltaY:extraY]; +} + +/* @ignore */ +- (void)_scrollViewWillScroll +{ + if (_implementedDelegateMethods & CPScrollViewDelegate_scrollViewWillScroll_) + [_delegate scrollViewWillScroll:self]; +} + +/* @ignore */ +- (void)_scrollViewDidScroll +{ + [_scrollTimer invalidate]; + _scrollTimer = nil; + + if (_implementedDelegateMethods & CPScrollViewDelegate_scrollViewDidScroll_) + [_delegate scrollViewDidScroll:self]; +} + +/*! + Lays out the scroll view's components. +*/ +- (void)tile +{ + // yuck. + // RESIZE: tile->setHidden AND refl + // Outside Change: refl->tile->setHidden AND refl + // scroll: refl. +} + /*! Resizes the scroll view to contain the specified clip view. @param aClipView the clip view to resize to @@ -415,8 +973,6 @@ var TIMER_INTERVAL = 0.2, [_horizontalScroller setKnobProportion:1.0]; } - console.log(contentFrame) - debugger; [_contentView setFrame:contentFrame]; [_headerClipView setFrame:headerClipViewFrame]; [[_headerClipView documentView] setNeedsDisplay:YES]; @@ -446,359 +1002,6 @@ var TIMER_INTERVAL = 0.2, _timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO]; } -// Managing Graphics Attributes - -/*! - Sets the type of border to be drawn around the view. - Valid types are: -
-    CPNoBorder
-    CPLineBorder
-    CPBezelBorder
-    CPGrooveBorder
-*/ -- (void)setBorderType:(CPBorderType)borderType -{ - if (_borderType == borderType) - return; - - _borderType = borderType; - - [self reflectScrolledClipView:_contentView]; - [self setNeedsDisplay:YES]; -} - -/*! - Returns the border type drawn around the view. -*/ -- (CPBorderType)borderType -{ - return _borderType; -} - -// Managing Scrollers -/*! - Sets the scroll view's horizontal scroller. - @param aScroller the horizontal scroller for the scroll view -*/ -- (void)setHorizontalScroller:(CPScroller)aScroller -{ - if (_horizontalScroller === aScroller) - return; - - [_horizontalScroller removeFromSuperview]; - [_horizontalScroller setTarget:nil]; - [_horizontalScroller setAction:nil]; - - _horizontalScroller = aScroller; - - [_horizontalScroller setTarget:self]; - [_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)]; - - [self addSubview:_horizontalScroller]; - - [self _updateScrollerStyle]; -} - -/*! - Returns the scroll view's horizontal scroller -*/ -- (CPScroller)horizontalScroller -{ - return _horizontalScroller; -} - -/*! - Specifies whether the scroll view can have a horizontal scroller. - @param hasHorizontalScroller \c YES lets the scroll view - allocate a horizontal scroller if necessary. -*/ -- (void)setHasHorizontalScroller:(BOOL)shouldHaveHorizontalScroller -{ - if (_hasHorizontalScroller === shouldHaveHorizontalScroller) - return; - - _hasHorizontalScroller = shouldHaveHorizontalScroller; - - if (_hasHorizontalScroller && !_horizontalScroller) - { - var bounds = [self _insetBounds]; - - [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]]; - [[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])]; - } - - [self reflectScrolledClipView:_contentView]; -} - -/*! - Returns \c YES if the scroll view can have a horizontal scroller. -*/ -- (BOOL)hasHorizontalScroller -{ - return _hasHorizontalScroller; -} - -/*! - Sets the scroll view's vertical scroller. - @param aScroller the vertical scroller -*/ -- (void)setVerticalScroller:(CPScroller)aScroller -{ - if (_verticalScroller === aScroller) - return; - - [_verticalScroller removeFromSuperview]; - [_verticalScroller setTarget:nil]; - [_verticalScroller setAction:nil]; - - _verticalScroller = aScroller; - - [_verticalScroller setTarget:self]; - [_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)]; - - [self addSubview:_verticalScroller]; - - [self _updateScrollerStyle]; -} - -/*! - Return's the scroll view's vertical scroller -*/ -- (CPScroller)verticalScroller -{ - return _verticalScroller; -} - -/*! - Specifies whether the scroll view has can have - a vertical scroller. It allocates it if necessary. - @param hasVerticalScroller \c YES allows - the scroll view to display a vertical scroller -*/ -- (void)setHasVerticalScroller:(BOOL)shouldHaveVerticalScroller -{ - if (_hasVerticalScroller === shouldHaveVerticalScroller) - return; - - _hasVerticalScroller = shouldHaveVerticalScroller; - - if (_hasVerticalScroller && !_verticalScroller) - { - var bounds = [self _insetBounds]; - - [self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(_CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]]; - [[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], _CGRectGetHeight(bounds))]; - } - - [self reflectScrolledClipView:_contentView]; -} - -/*! - Returns \c YES if the scroll view can have a vertical scroller. -*/ -- (BOOL)hasVerticalScroller -{ - return _hasVerticalScroller; -} - -/*! - Sets whether the scroll view hides its scroll bars when not needed. - @param autohidesScrollers \c YES causes the scroll bars - to be hidden when not needed. -*/ -- (void)setAutohidesScrollers:(BOOL)autohidesScrollers -{ - if (_autohidesScrollers == autohidesScrollers) - return; - - _autohidesScrollers = autohidesScrollers; - - [self reflectScrolledClipView:_contentView]; -} - -/*! - Returns \c YES if the scroll view hides its scroll - bars when not necessary. -*/ -- (BOOL)autohidesScrollers -{ - return _autohidesScrollers; -} - -- (void)_updateCornerAndHeaderView -{ - var documentView = [self documentView], - currentHeaderView = [self _headerView], - documentHeaderView = [documentView respondsToSelector:@selector(headerView)] ? [documentView headerView] : nil; - - if (currentHeaderView !== documentHeaderView) - { - [currentHeaderView removeFromSuperview]; - [_headerClipView setDocumentView:documentHeaderView]; - } - - var documentCornerView = [documentView respondsToSelector:@selector(cornerView)] ? [documentView cornerView] : nil; - - if (_cornerView !== documentCornerView) - { - [_cornerView removeFromSuperview]; - - _cornerView = documentCornerView; - - if (_cornerView) - [self addSubview:_cornerView]; - } - - [self reflectScrolledClipView:_contentView]; -} - -- (CPView)_headerView -{ - return [_headerClipView documentView]; -} - -- (CGRect)_cornerViewFrame -{ - if (!_cornerView) - return _CGRectMakeZero(); - - var bounds = [self _insetBounds], - frame = [_cornerView frame]; - - frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame); - frame.origin.y = _CGRectGetMinY(bounds); - - return frame; -} - -- (CGRect)_headerClipViewFrame -{ - var headerView = [self _headerView]; - - if (!headerView) - return _CGRectMakeZero(); - - var frame = [self _insetBounds]; - - frame.size.height = _CGRectGetHeight([headerView frame]); - frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]); - - return frame; -} - -- (CGRect)_bottomCornerViewFrame -{ - if ([[self horizontalScroller] isHidden] || [[self verticalScroller] isHidden]) - return CGRectMakeZero(); - - var verticalFrame = [[self verticalScroller] frame], - bottomCornerFrame = CGRectMakeZero(); - - bottomCornerFrame.origin.x = CGRectGetMinX(verticalFrame); - bottomCornerFrame.origin.y = CGRectGetMaxY(verticalFrame); - bottomCornerFrame.size.width = [CPScroller scrollerWidthInStyle:_scrollerStyle]; - bottomCornerFrame.size.height = [CPScroller scrollerWidthInStyle:_scrollerStyle]; - - return bottomCornerFrame; -} - -- (void)setBottomCornerView:(CPView)aBottomCornerView -{ - if (_bottomCornerView === aBottomCornerView) - return; - - [_bottomCornerView removeFromSuperview]; - - [aBottomCornerView setFrame:[self _bottomCornerViewFrame]]; - [self addSubview:aBottomCornerView]; - - _bottomCornerView = aBottomCornerView; - - [self _updateCornerAndHeaderView]; -} - -- (CPView)bottomCornerView -{ - return _bottomCornerView; -} - -/* @ignore */ -- (void)_verticalScrollerDidScroll:(CPScroller)aScroller -{ - var value = [aScroller floatValue], - documentFrame = [[_contentView documentView] frame], - contentBounds = [_contentView bounds]; - - switch ([_verticalScroller hitPart]) - { - case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll; - break; - - case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll; - break; - - case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll; - break; - - case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll; - break; - - case CPScrollerKnobSlot: - case CPScrollerKnob: - // We want integral bounds! - default: contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds))); - } - - [self _sendDelegateMessages]; - - [_contentView scrollToPoint:contentBounds.origin]; -} - -/* @ignore */ -- (void)_horizontalScrollerDidScroll:(CPScroller)aScroller -{ - var value = [aScroller floatValue], - documentFrame = [[self documentView] frame], - contentBounds = [_contentView bounds]; - - switch ([_horizontalScroller hitPart]) - { - case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll; - break; - - case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll; - break; - - case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll; - break; - - case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll; - break; - - case CPScrollerKnobSlot: - case CPScrollerKnob: - // We want integral bounds! - default: contentBounds.origin.x = ROUND(value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds))); - } - - [self _sendDelegateMessages]; - - [_contentView scrollToPoint:contentBounds.origin]; - [_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)]; -} - -/*! - Lays out the scroll view's components. -*/ -- (void)tile -{ - // yuck. - // RESIZE: tile->setHidden AND refl - // Outside Change: refl->tile->setHidden AND refl - // scroll: refl. -} - /* @ignore */ @@ -807,112 +1010,9 @@ var TIMER_INTERVAL = 0.2, [self reflectScrolledClipView:_contentView]; } -// Setting Scrolling Behavior -/*! - Sets how much the document moves when scrolled. Sets the vertical and horizontal scroll. - @param aLineScroll the amount to move the document when scrolled -*/ -- (void)setLineScroll:(float)aLineScroll -{ - [self setHorizontalLineScroll:aLineScroll]; - [self setVerticalLineScroll:aLineScroll]; -} -/*! - Returns how much the document moves when scrolled -*/ -- (float)lineScroll -{ - return [self horizontalLineScroll]; -} - -/*! - Sets how much the document moves when scrolled horizontally. - @param aLineScroll the amount to move horizontally when scrolled. -*/ -- (void)setHorizontalLineScroll:(float)aLineScroll -{ - _horizontalLineScroll = aLineScroll; -} - -/*! - Returns how much the document moves horizontally when scrolled. -*/ -- (float)horizontalLineScroll -{ - return _horizontalLineScroll; -} - -/*! - Sets how much the document moves when scrolled vertically. - @param aLineScroll the new amount to move vertically when scrolled. -*/ -- (void)setVerticalLineScroll:(float)aLineScroll -{ - _verticalLineScroll = aLineScroll; -} - -/*! - Returns how much the document moves vertically when scrolled. -*/ -- (float)verticalLineScroll -{ - return _verticalLineScroll; -} - -/*! - Sets the horizontal and vertical page scroll amount. - @param aPageScroll the new horizontal and vertical page scroll amount -*/ -- (void)setPageScroll:(float)aPageScroll -{ - [self setHorizontalPageScroll:aPageScroll]; - [self setVerticalPageScroll:aPageScroll]; -} - -/*! - Returns the vertical and horizontal page scroll amount. -*/ -- (float)pageScroll -{ - return [self horizontalPageScroll]; -} - -/*! - Sets the horizontal page scroll amount. - @param aPageScroll the new horizontal page scroll amount -*/ -- (void)setHorizontalPageScroll:(float)aPageScroll -{ - _horizontalPageScroll = aPageScroll; -} - -/*! - Returns the horizontal page scroll amount. -*/ -- (float)horizontalPageScroll -{ - return _horizontalPageScroll; -} - -/*! - Sets the vertical page scroll amount. - @param aPageScroll the new vertical page scroll amount -*/ -- (void)setVerticalPageScroll:(float)aPageScroll -{ - _verticalPageScroll = aPageScroll; -} - -/*! - Returns the vertical page scroll amount. -*/ -- (float)verticalPageScroll -{ - return _verticalPageScroll; -} - -// CPView Overrides +#pragma mark - +#pragma mark Overrides - (void)drawRect:(CPRect)aRect { @@ -1034,9 +1134,6 @@ var TIMER_INTERVAL = 0.2, CGContextStrokePath(context); } - -// CPResponder Overrides - /*! Handles a scroll wheel event from the user. @param anEvent the scroll wheel event @@ -1055,39 +1152,6 @@ var TIMER_INTERVAL = 0.2, [self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] deltaY:[anEvent deltaY]]; } -- (void)_hideScrollers:(CPTimer)theTimer -{ - if ([_verticalScroller allowFadingOut]) - [_verticalScroller fadeOut]; - if ([_horizontalScroller allowFadingOut]) - [_horizontalScroller fadeOut]; - _timerScrollersHide = nil; -} - -- (void)_respondToScrollWheelEventWithDeltaX:(float)deltaX deltaY:(float)deltaY -{ - var documentFrame = [[self documentView] frame], - contentBounds = [_contentView bounds], - contentFrame = [_contentView frame], - enclosingScrollView = [self enclosingScrollView]; - - // We want integral bounds! - contentBounds.origin.x = ROUND(contentBounds.origin.x + deltaX); - contentBounds.origin.y = ROUND(contentBounds.origin.y + deltaY); - - var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)], - extraX = contentBounds.origin.x - constrainedOrigin.x, - extraY = contentBounds.origin.y - constrainedOrigin.y; - - [self _sendDelegateMessages]; - - [_contentView scrollToPoint:constrainedOrigin]; - [_headerClipView scrollToPoint:CGPointMake(constrainedOrigin.x, 0.0)]; - - if (extraX || extraY) - [enclosingScrollView _respondToScrollWheelEventWithDeltaX:extraX deltaY:extraY]; -} - - (void)scrollPageUp:(id)sender { var contentBounds = [_contentView bounds]; @@ -1148,37 +1212,9 @@ var TIMER_INTERVAL = 0.2, [_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0)]; } -- (void)_sendDelegateMessages -{ - if (_implementedDelegateMethods == 0) - return; - - if (!_scrollTimer) - { - [self _scrollViewWillScroll]; - _scrollTimer = [CPTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(_scrollViewDidScroll) userInfo:nil repeats:YES]; - } - else - [_scrollTimer setFireDate:[CPDate dateWithTimeIntervalSinceNow:TIMER_INTERVAL]]; -} - -- (void)_scrollViewWillScroll -{ - if (_implementedDelegateMethods & CPScrollViewDelegate_scrollViewWillScroll_) - [_delegate scrollViewWillScroll:self]; -} - -- (void)_scrollViewDidScroll -{ - [_scrollTimer invalidate]; - _scrollTimer = nil; - - if (_implementedDelegateMethods & CPScrollViewDelegate_scrollViewDidScroll_) - [_delegate scrollViewDidScroll:self]; -} - @end + var CPScrollViewContentViewKey = @"CPScrollViewContentView", CPScrollViewHeaderClipViewKey = @"CPScrollViewHeaderClipViewKey", CPScrollViewVLineScrollKey = @"CPScrollViewVLineScroll",