![]() |
API 0.9.5
|
00001 /* 00002 * CPScrollView.j 00003 * AppKit 00004 * 00005 * Created by Francisco Tolmasky. 00006 * Copyright 2008, 280 North, Inc. 00007 * 00008 * Modified to match Lion style by Antoine Mercadal 2011 00009 * <antoine.mercadal@archipelproject.org> 00010 * 00011 * This library is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Lesser General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 2.1 of the License, or (at your option) any later version. 00015 * 00016 * This library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with this library; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00024 */ 00025 00026 00027 00028 00030 var _isSystemUsingOverlayScrollers = function() 00031 { 00032 #if PLATFORM(DOM) 00033 var inner = document.createElement('p'), 00034 outer = document.createElement('div'); 00035 00036 inner.style.width = "100%"; 00037 inner.style.height = "200px"; 00038 00039 outer.style.position = "absolute"; 00040 outer.style.top = "0px"; 00041 outer.style.left = "0px"; 00042 outer.style.visibility = "hidden"; 00043 outer.style.width = "200px"; 00044 outer.style.height = "150px"; 00045 outer.style.overflow = "hidden"; 00046 outer.appendChild (inner); 00047 00048 document.body.appendChild (outer); 00049 var w1 = inner.offsetWidth; 00050 outer.style.overflow = 'scroll'; 00051 var w2 = inner.offsetWidth; 00052 if (w1 == w2) 00053 w2 = outer.clientWidth; 00054 00055 document.body.removeChild (outer); 00056 00057 return (w1 - w2 == 0); 00058 #else 00059 return NO; 00060 #endif 00061 } 00062 00072 var TIMER_INTERVAL = 0.2, 00073 CPScrollViewDelegate_scrollViewWillScroll_ = 1 << 0, 00074 CPScrollViewDelegate_scrollViewDidScroll_ = 1 << 1, 00075 00076 CPScrollViewFadeOutTime = 1.3; 00077 00078 var CPScrollerStyleGlobal = CPScrollerStyleOverlay, 00079 CPScrollerStyleGlobalChangeNotification = @"CPScrollerStyleGlobalChangeNotification"; 00080 00081 00082 @implementation CPScrollView : CPView 00083 { 00084 CPClipView _contentView; 00085 CPClipView _headerClipView; 00086 CPView _cornerView; 00087 CPView _bottomCornerView; 00088 00089 id _delegate; 00090 CPTimer _scrollTimer; 00091 00092 BOOL _hasVerticalScroller; 00093 BOOL _hasHorizontalScroller; 00094 BOOL _autohidesScrollers; 00095 00096 CPScroller _verticalScroller; 00097 CPScroller _horizontalScroller; 00098 00099 CPInteger _recursionCount; 00100 CPInteger _implementedDelegateMethods; 00101 00102 float _verticalLineScroll; 00103 float _verticalPageScroll; 00104 float _horizontalLineScroll; 00105 float _horizontalPageScroll; 00106 00107 CPBorderType _borderType; 00108 00109 CPTimer _timerScrollersHide; 00110 00111 int _scrollerStyle; 00112 int _scrollerKnobStyle; 00113 } 00114 00115 00116 #pragma mark - 00117 #pragma mark Class methods 00118 00119 + (void)initialize 00120 { 00121 var globalValue = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPScrollersGlobalStyle"]; 00122 00123 if (globalValue == nil || globalValue == -1) 00124 CPScrollerStyleGlobal = _isSystemUsingOverlayScrollers() ? CPScrollerStyleOverlay : CPScrollerStyleLegacy 00125 else 00126 CPScrollerStyleGlobal = globalValue; 00127 } 00128 00129 + (CPString)defaultThemeClass 00130 { 00131 return @"scrollview" 00132 } 00133 00134 + (CPDictionary)themeAttributes 00135 { 00136 return [CPDictionary dictionaryWithJSObject:{ 00137 @"bottom-corner-color": [CPColor whiteColor], 00138 @"border-color": [CPColor blackColor] 00139 }]; 00140 } 00141 00142 + (CGSize)contentSizeForFrameSize:(CGSize)frameSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType 00143 { 00144 var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType], 00145 scrollerWidth = [CPScroller scrollerWidth]; 00146 00147 if (hFlag) 00148 bounds.size.height -= scrollerWidth; 00149 00150 if (vFlag) 00151 bounds.size.width -= scrollerWidth; 00152 00153 return bounds.size; 00154 } 00155 00156 + (CGSize)frameSizeForContentSize:(CGSize)contentSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType 00157 { 00158 var bounds = [self _insetBounds:_CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType], 00159 widthInset = contentSize.width - bounds.size.width, 00160 heightInset = contentSize.height - bounds.size.height, 00161 frameSize = _CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset), 00162 scrollerWidth = [CPScroller scrollerWidth]; 00163 00164 if (hFlag) 00165 frameSize.height -= scrollerWidth; 00166 00167 if (vFlag) 00168 frameSize.width -= scrollerWidth; 00169 00170 return frameSize; 00171 } 00172 00173 + (CGRect)_insetBounds:(CGRect)bounds borderType:(CPBorderType)borderType 00174 { 00175 switch (borderType) 00176 { 00177 case CPLineBorder: 00178 case CPBezelBorder: 00179 return _CGRectInset(bounds, 1.0, 1.0); 00180 00181 case CPGrooveBorder: 00182 bounds = _CGRectInset(bounds, 2.0, 2.0); 00183 ++bounds.origin.y; 00184 --bounds.size.height; 00185 return bounds; 00186 00187 case CPNoBorder: 00188 default: 00189 return bounds; 00190 } 00191 } 00192 00196 + (int)globalScrollerStyle 00197 { 00198 return CPScrollerStyleGlobal; 00199 } 00200 00206 + (int)setGlobalScrollerStyle:(int)aStyle 00207 { 00208 CPScrollerStyleGlobal = aStyle; 00209 [[CPNotificationCenter defaultCenter] postNotificationName:CPScrollerStyleGlobalChangeNotification object:nil]; 00210 } 00211 00212 00213 #pragma mark - 00214 #pragma mark Initialization 00215 00216 - (id)initWithFrame:(CGRect)aFrame 00217 { 00218 self = [super initWithFrame:aFrame]; 00219 00220 if (self) 00221 { 00222 _verticalLineScroll = 10.0; 00223 _verticalPageScroll = 10.0; 00224 00225 _horizontalLineScroll = 10.0; 00226 _horizontalPageScroll = 10.0; 00227 00228 _borderType = CPNoBorder; 00229 00230 _contentView = [[CPClipView alloc] initWithFrame:[self _insetBounds]]; 00231 [self addSubview:_contentView]; 00232 00233 _headerClipView = [[CPClipView alloc] init]; 00234 [self addSubview:_headerClipView]; 00235 00236 _bottomCornerView = [[CPView alloc] init]; 00237 [self addSubview:_bottomCornerView]; 00238 00239 [self setHasVerticalScroller:YES]; 00240 [self setHasHorizontalScroller:YES]; 00241 _scrollerKnobStyle = CPScrollerKnobStyleDefault; 00242 [self setScrollerStyle:CPScrollerStyleGlobal]; 00243 00244 _delegate = nil; 00245 _scrollTimer = nil; 00246 _implementedDelegateMethods = 0; 00247 00248 [[CPNotificationCenter defaultCenter] addObserver:self 00249 selector:@selector(_didReceiveDefaultStyleChange:) 00250 name:CPScrollerStyleGlobalChangeNotification 00251 object:nil]; 00252 } 00253 00254 return self; 00255 } 00256 00257 00258 #pragma mark - 00259 #pragma mark Getters / Setters 00260 00264 - (id)delegate 00265 { 00266 return _delegate; 00267 } 00268 00272 - (void)setDelegate:(id)aDelegate 00273 { 00274 if (aDelegate === _delegate) 00275 return; 00276 00277 _delegate = aDelegate; 00278 _implementedDelegateMethods = 0; 00279 00280 if (_delegate === nil) 00281 return; 00282 00283 if ([_delegate respondsToSelector:@selector(scrollViewWillScroll:)]) 00284 _implementedDelegateMethods |= CPScrollViewDelegate_scrollViewWillScroll_; 00285 00286 if ([_delegate respondsToSelector:@selector(scrollViewDidScroll:)]) 00287 _implementedDelegateMethods |= CPScrollViewDelegate_scrollViewDidScroll_; 00288 } 00289 00290 - (int)scrollerStyle 00291 { 00292 return _scrollerStyle; 00293 } 00294 00301 - (void)setScrollerStyle:(int)aStyle 00302 { 00303 if (_scrollerStyle === aStyle) 00304 return; 00305 00306 _scrollerStyle = aStyle; 00307 00308 [self _updateScrollerStyle]; 00309 } 00310 00321 - (int)scrollerKnobStyle 00322 { 00323 return _scrollerKnobStyle; 00324 } 00325 00336 - (void)setScrollerKnobStyle:(int)newScrollerKnobStyle 00337 { 00338 if (_scrollerKnobStyle === newScrollerKnobStyle) 00339 return; 00340 00341 _scrollerKnobStyle = newScrollerKnobStyle; 00342 00343 [self _updateScrollerStyle]; 00344 } 00345 00349 - (CPClipView)contentView 00350 { 00351 return _contentView; 00352 } 00353 00359 - (void)setContentView:(CPClipView)aContentView 00360 { 00361 if (_contentView === aContentView || !aContentView) 00362 return; 00363 00364 var documentView = [aContentView documentView]; 00365 00366 if (documentView) 00367 [documentView removeFromSuperview]; 00368 00369 [_contentView removeFromSuperview]; 00370 00371 _contentView = aContentView; 00372 00373 [_contentView setDocumentView:documentView]; 00374 00375 [self addSubview:_contentView]; 00376 00377 // This will size the content view appropriately, so no need to size it in this method. 00378 [self reflectScrolledClipView:_contentView]; 00379 } 00380 00384 - (CGSize)contentSize 00385 { 00386 return [_contentView frame].size; 00387 } 00388 00392 - (id)documentView 00393 { 00394 return [_contentView documentView]; 00395 } 00396 00402 - (void)setDocumentView:(CPView)aView 00403 { 00404 [_contentView setDocumentView:aView]; 00405 00406 // FIXME: This should be observed. 00407 [self _updateCornerAndHeaderView]; 00408 [self reflectScrolledClipView:_contentView]; 00409 } 00410 00414 - (CPBorderType)borderType 00415 { 00416 return _borderType; 00417 } 00418 00429 - (void)setBorderType:(CPBorderType)borderType 00430 { 00431 if (_borderType == borderType) 00432 return; 00433 00434 _borderType = borderType; 00435 00436 [self reflectScrolledClipView:_contentView]; 00437 [self setNeedsDisplay:YES]; 00438 } 00439 00440 00444 - (CPScroller)horizontalScroller 00445 { 00446 return _horizontalScroller; 00447 } 00448 00454 - (void)setHorizontalScroller:(CPScroller)aScroller 00455 { 00456 if (_horizontalScroller === aScroller) 00457 return; 00458 00459 [_horizontalScroller removeFromSuperview]; 00460 [_horizontalScroller setTarget:nil]; 00461 [_horizontalScroller setAction:nil]; 00462 00463 _horizontalScroller = aScroller; 00464 00465 [_horizontalScroller setTarget:self]; 00466 [_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)]; 00467 00468 [self addSubview:_horizontalScroller]; 00469 00470 [self _updateScrollerStyle]; 00471 } 00472 00476 - (BOOL)hasHorizontalScroller 00477 { 00478 return _hasHorizontalScroller; 00479 } 00480 00487 - (void)setHasHorizontalScroller:(BOOL)shouldHaveHorizontalScroller 00488 { 00489 if (_hasHorizontalScroller === shouldHaveHorizontalScroller) 00490 return; 00491 00492 _hasHorizontalScroller = shouldHaveHorizontalScroller; 00493 00494 if (_hasHorizontalScroller && !_horizontalScroller) 00495 { 00496 var bounds = [self _insetBounds]; 00497 00498 [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]]; 00499 [[self horizontalScroller] setFrameSize:CGSizeMake(_CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])]; 00500 } 00501 00502 [self reflectScrolledClipView:_contentView]; 00503 } 00504 00508 - (CPScroller)verticalScroller 00509 { 00510 return _verticalScroller; 00511 } 00512 00518 - (void)setVerticalScroller:(CPScroller)aScroller 00519 { 00520 if (_verticalScroller === aScroller) 00521 return; 00522 00523 [_verticalScroller removeFromSuperview]; 00524 [_verticalScroller setTarget:nil]; 00525 [_verticalScroller setAction:nil]; 00526 00527 _verticalScroller = aScroller; 00528 00529 [_verticalScroller setTarget:self]; 00530 [_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)]; 00531 00532 [self addSubview:_verticalScroller]; 00533 00534 [self _updateScrollerStyle]; 00535 } 00536 00540 - (BOOL)hasVerticalScroller 00541 { 00542 return _hasVerticalScroller; 00543 } 00544 00552 - (void)setHasVerticalScroller:(BOOL)shouldHaveVerticalScroller 00553 { 00554 if (_hasVerticalScroller === shouldHaveVerticalScroller) 00555 return; 00556 00557 _hasVerticalScroller = shouldHaveVerticalScroller; 00558 00559 if (_hasVerticalScroller && !_verticalScroller) 00560 { 00561 var bounds = [self _insetBounds]; 00562 00563 [self setVerticalScroller:[[CPScroller alloc] initWithFrame:_CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(_CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]]; 00564 [[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], _CGRectGetHeight(bounds))]; 00565 } 00566 00567 [self reflectScrolledClipView:_contentView]; 00568 } 00569 00573 - (BOOL)autohidesScrollers 00574 { 00575 return _autohidesScrollers; 00576 } 00577 00584 - (void)setAutohidesScrollers:(BOOL)autohidesScrollers 00585 { 00586 if (_autohidesScrollers == autohidesScrollers) 00587 return; 00588 00589 _autohidesScrollers = autohidesScrollers; 00590 00591 [self reflectScrolledClipView:_contentView]; 00592 } 00593 00594 - (CPView)bottomCornerView 00595 { 00596 return _bottomCornerView; 00597 } 00598 00599 - (void)setBottomCornerView:(CPView)aBottomCornerView 00600 { 00601 if (_bottomCornerView === aBottomCornerView) 00602 return; 00603 00604 [_bottomCornerView removeFromSuperview]; 00605 00606 [aBottomCornerView setFrame:[self _bottomCornerViewFrame]]; 00607 [self addSubview:aBottomCornerView]; 00608 00609 _bottomCornerView = aBottomCornerView; 00610 00611 [self _updateCornerAndHeaderView]; 00612 } 00613 00617 - (float)lineScroll 00618 { 00619 return [self horizontalLineScroll]; 00620 } 00621 00627 - (void)setLineScroll:(float)aLineScroll 00628 { 00629 [self setHorizontalLineScroll:aLineScroll]; 00630 [self setVerticalLineScroll:aLineScroll]; 00631 } 00632 00636 - (float)horizontalLineScroll 00637 { 00638 return _horizontalLineScroll; 00639 } 00640 00646 - (void)setHorizontalLineScroll:(float)aLineScroll 00647 { 00648 _horizontalLineScroll = aLineScroll; 00649 } 00650 00654 - (float)verticalLineScroll 00655 { 00656 return _verticalLineScroll; 00657 } 00658 00664 - (void)setVerticalLineScroll:(float)aLineScroll 00665 { 00666 _verticalLineScroll = aLineScroll; 00667 } 00668 00672 - (float)pageScroll 00673 { 00674 return [self horizontalPageScroll]; 00675 } 00676 00682 - (void)setPageScroll:(float)aPageScroll 00683 { 00684 [self setHorizontalPageScroll:aPageScroll]; 00685 [self setVerticalPageScroll:aPageScroll]; 00686 } 00687 00691 - (float)horizontalPageScroll 00692 { 00693 return _horizontalPageScroll; 00694 } 00695 00701 - (void)setHorizontalPageScroll:(float)aPageScroll 00702 { 00703 _horizontalPageScroll = aPageScroll; 00704 } 00705 00709 - (float)verticalPageScroll 00710 { 00711 return _verticalPageScroll; 00712 } 00713 00719 - (void)setVerticalPageScroll:(float)aPageScroll 00720 { 00721 _verticalPageScroll = aPageScroll; 00722 } 00723 00724 00725 #pragma mark - 00726 #pragma mark Privates 00727 00728 /* @ignore */ 00729 - (void)_updateScrollerStyle 00730 { 00731 if (_hasHorizontalScroller) 00732 { 00733 [_horizontalScroller setStyle:_scrollerStyle]; 00734 [_horizontalScroller unsetThemeState:CPThemeStateSelected]; 00735 switch (_scrollerKnobStyle) 00736 { 00737 case CPScrollerKnobStyleLight: 00738 [_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobDark]; 00739 [_horizontalScroller setThemeState:CPThemeStateScrollerKnobLight]; 00740 break; 00741 case CPScrollerKnobStyleDark: 00742 [_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobLight]; 00743 [_horizontalScroller setThemeState:CPThemeStateScrollerKnobDark]; 00744 break; 00745 default: 00746 [_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobLight]; 00747 [_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobDark]; 00748 } 00749 } 00750 if (_hasVerticalScroller) 00751 { 00752 [_verticalScroller setStyle:_scrollerStyle]; 00753 [_verticalScroller unsetThemeState:CPThemeStateSelected]; 00754 switch (_scrollerKnobStyle) 00755 { 00756 case CPScrollerKnobStyleLight: 00757 [_verticalScroller unsetThemeState:CPThemeStateScrollerKnobDark]; 00758 [_verticalScroller setThemeState:CPThemeStateScrollerKnobLight]; 00759 break; 00760 case CPScrollerKnobStyleDark: 00761 [_verticalScroller unsetThemeState:CPThemeStateScrollerKnobLight]; 00762 [_verticalScroller setThemeState:CPThemeStateScrollerKnobDark]; 00763 break; 00764 default: 00765 [_verticalScroller unsetThemeState:CPThemeStateScrollerKnobLight]; 00766 [_verticalScroller unsetThemeState:CPThemeStateScrollerKnobDark]; 00767 } 00768 } 00769 00770 if (_scrollerStyle == CPScrollerStyleOverlay) 00771 { 00772 if (_timerScrollersHide) 00773 [_timerScrollersHide invalidate]; 00774 _timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO]; 00775 [[self bottomCornerView] setHidden:YES]; 00776 } 00777 else 00778 [[self bottomCornerView] setHidden:NO]; 00779 00780 [self reflectScrolledClipView:_contentView]; 00781 } 00782 00783 /* @ignore */ 00784 - (CGRect)_insetBounds 00785 { 00786 return [[self class] _insetBounds:[self bounds] borderType:_borderType]; 00787 } 00788 00789 /* @ignore */ 00790 - (void)_updateCornerAndHeaderView 00791 { 00792 var documentView = [self documentView], 00793 currentHeaderView = [self _headerView], 00794 documentHeaderView = [documentView respondsToSelector:@selector(headerView)] ? [documentView headerView] : nil; 00795 00796 if (currentHeaderView !== documentHeaderView) 00797 { 00798 [currentHeaderView removeFromSuperview]; 00799 [_headerClipView setDocumentView:documentHeaderView]; 00800 } 00801 00802 var documentCornerView = [documentView respondsToSelector:@selector(cornerView)] ? [documentView cornerView] : nil; 00803 00804 if (_cornerView !== documentCornerView) 00805 { 00806 [_cornerView removeFromSuperview]; 00807 00808 _cornerView = documentCornerView; 00809 00810 if (_cornerView) 00811 [self addSubview:_cornerView]; 00812 } 00813 00814 [self reflectScrolledClipView:_contentView]; 00815 } 00816 00817 /* @ignore */ 00818 - (CPView)_headerView 00819 { 00820 return [_headerClipView documentView]; 00821 } 00822 00823 /* @ignore */ 00824 - (CGRect)_cornerViewFrame 00825 { 00826 if (!_cornerView) 00827 return _CGRectMakeZero(); 00828 00829 var bounds = [self _insetBounds], 00830 frame = [_cornerView frame]; 00831 00832 frame.origin.x = _CGRectGetMaxX(bounds) - _CGRectGetWidth(frame); 00833 frame.origin.y = _CGRectGetMinY(bounds); 00834 00835 return frame; 00836 } 00837 00838 /* @ignore */ 00839 - (CGRect)_headerClipViewFrame 00840 { 00841 var headerView = [self _headerView]; 00842 00843 if (!headerView) 00844 return _CGRectMakeZero(); 00845 00846 var frame = [self _insetBounds]; 00847 00848 frame.size.height = _CGRectGetHeight([headerView frame]); 00849 frame.size.width -= _CGRectGetWidth([self _cornerViewFrame]); 00850 00851 return frame; 00852 } 00853 00854 /* @ignore */ 00855 - (CGRect)_bottomCornerViewFrame 00856 { 00857 if ([[self horizontalScroller] isHidden] || [[self verticalScroller] isHidden]) 00858 return CGRectMakeZero(); 00859 00860 var verticalFrame = [[self verticalScroller] frame], 00861 bottomCornerFrame = CGRectMakeZero(); 00862 00863 bottomCornerFrame.origin.x = CGRectGetMinX(verticalFrame); 00864 bottomCornerFrame.origin.y = CGRectGetMaxY(verticalFrame); 00865 bottomCornerFrame.size.width = [CPScroller scrollerWidthInStyle:_scrollerStyle]; 00866 bottomCornerFrame.size.height = [CPScroller scrollerWidthInStyle:_scrollerStyle]; 00867 00868 return bottomCornerFrame; 00869 } 00870 00871 /* @ignore */ 00872 - (void)_verticalScrollerDidScroll:(CPScroller)aScroller 00873 { 00874 var value = [aScroller floatValue], 00875 documentFrame = [[_contentView documentView] frame], 00876 contentBounds = [_contentView bounds]; 00877 00878 00879 switch ([_verticalScroller hitPart]) 00880 { 00881 case CPScrollerDecrementLine: 00882 contentBounds.origin.y -= _verticalLineScroll; 00883 break; 00884 00885 case CPScrollerIncrementLine: 00886 contentBounds.origin.y += _verticalLineScroll; 00887 break; 00888 00889 case CPScrollerDecrementPage: 00890 contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll; 00891 break; 00892 00893 case CPScrollerIncrementPage: 00894 contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll; 00895 break; 00896 00897 // We want integral bounds! 00898 case CPScrollerKnobSlot: 00899 case CPScrollerKnob: 00900 default: 00901 contentBounds.origin.y = ROUND(value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds))); 00902 } 00903 00904 [self _sendDelegateMessages]; 00905 00906 [_contentView scrollToPoint:contentBounds.origin]; 00907 } 00908 00909 /* @ignore */ 00910 - (void)_horizontalScrollerDidScroll:(CPScroller)aScroller 00911 { 00912 var value = [aScroller floatValue], 00913 documentFrame = [[self documentView] frame], 00914 contentBounds = [_contentView bounds]; 00915 00916 switch ([_horizontalScroller hitPart]) 00917 { 00918 case CPScrollerDecrementLine: 00919 contentBounds.origin.x -= _horizontalLineScroll; 00920 break; 00921 00922 case CPScrollerIncrementLine: 00923 contentBounds.origin.x += _horizontalLineScroll; 00924 break; 00925 00926 case CPScrollerDecrementPage: 00927 contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll; 00928 break; 00929 00930 case CPScrollerIncrementPage: 00931 contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll; 00932 break; 00933 00934 // We want integral bounds! 00935 case CPScrollerKnobSlot: 00936 case CPScrollerKnob: 00937 default: 00938 contentBounds.origin.x = ROUND(value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds))); 00939 } 00940 00941 [self _sendDelegateMessages]; 00942 00943 [_contentView scrollToPoint:contentBounds.origin]; 00944 [_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)]; 00945 } 00946 00947 /* @ignore */ 00948 - (void)_sendDelegateMessages 00949 { 00950 if (_implementedDelegateMethods == 0) 00951 return; 00952 00953 if (!_scrollTimer) 00954 { 00955 [self _scrollViewWillScroll]; 00956 _scrollTimer = [CPTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(_scrollViewDidScroll) userInfo:nil repeats:YES]; 00957 } 00958 else 00959 [_scrollTimer setFireDate:[CPDate dateWithTimeIntervalSinceNow:TIMER_INTERVAL]]; 00960 } 00961 00962 /* @ignore */ 00963 - (void)_hideScrollers:(CPTimer)theTimer 00964 { 00965 if ([_verticalScroller allowFadingOut]) 00966 [_verticalScroller fadeOut]; 00967 if ([_horizontalScroller allowFadingOut]) 00968 [_horizontalScroller fadeOut]; 00969 _timerScrollersHide = nil; 00970 } 00971 00972 /* @ignore */ 00973 - (void)_respondToScrollWheelEventWithDeltaX:(float)deltaX deltaY:(float)deltaY 00974 { 00975 var documentFrame = [[self documentView] frame], 00976 contentBounds = [_contentView bounds], 00977 contentFrame = [_contentView frame], 00978 enclosingScrollView = [self enclosingScrollView]; 00979 00980 // We want integral bounds! 00981 contentBounds.origin.x = ROUND(contentBounds.origin.x + deltaX); 00982 contentBounds.origin.y = ROUND(contentBounds.origin.y + deltaY); 00983 00984 var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)], 00985 extraX = contentBounds.origin.x - constrainedOrigin.x, 00986 extraY = contentBounds.origin.y - constrainedOrigin.y; 00987 00988 [self _sendDelegateMessages]; 00989 00990 [_contentView scrollToPoint:constrainedOrigin]; 00991 [_headerClipView scrollToPoint:CGPointMake(constrainedOrigin.x, 0.0)]; 00992 00993 if (extraX || extraY) 00994 [enclosingScrollView _respondToScrollWheelEventWithDeltaX:extraX deltaY:extraY]; 00995 } 00996 00997 /* @ignore */ 00998 - (void)_scrollViewWillScroll 00999 { 01000 if (_implementedDelegateMethods & CPScrollViewDelegate_scrollViewWillScroll_) 01001 [_delegate scrollViewWillScroll:self]; 01002 } 01003 01004 /* @ignore */ 01005 - (void)_scrollViewDidScroll 01006 { 01007 [_scrollTimer invalidate]; 01008 _scrollTimer = nil; 01009 01010 if (_implementedDelegateMethods & CPScrollViewDelegate_scrollViewDidScroll_) 01011 [_delegate scrollViewDidScroll:self]; 01012 } 01013 01015 - (void)_didReceiveDefaultStyleChange:(CPNotification)aNotification 01016 { 01017 [self setScrollerStyle:CPScrollerStyleGlobal]; 01018 } 01019 01020 01021 01022 #pragma mark - 01023 #pragma mark Utilities 01024 01028 - (void)tile 01029 { 01030 // yuck. 01031 // RESIZE: tile->setHidden AND refl 01032 // Outside Change: refl->tile->setHidden AND refl 01033 // scroll: refl. 01034 } 01035 01041 - (void)reflectScrolledClipView:(CPClipView)aClipView 01042 { 01043 if (_contentView !== aClipView) 01044 return; 01045 01046 if (_recursionCount > 5) 01047 return; 01048 01049 ++_recursionCount; 01050 01051 var documentView = [self documentView]; 01052 01053 if (!documentView) 01054 { 01055 if (_autohidesScrollers) 01056 { 01057 [_verticalScroller setHidden:YES]; 01058 [_horizontalScroller setHidden:YES]; 01059 } 01060 01061 [_contentView setFrame:[self _insetBounds]]; 01062 [_headerClipView setFrame:_CGRectMakeZero()]; 01063 01064 --_recursionCount; 01065 01066 return; 01067 } 01068 01069 var documentFrame = [documentView frame], // the size of the whole document 01070 contentFrame = [self _insetBounds], // assume it takes up the entire size of the scrollview (no scrollers) 01071 headerClipViewFrame = [self _headerClipViewFrame], 01072 headerClipViewHeight = _CGRectGetHeight(headerClipViewFrame); 01073 01074 contentFrame.origin.y += headerClipViewHeight; 01075 contentFrame.size.height -= headerClipViewHeight; 01076 01077 var difference = _CGSizeMake(_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentFrame), _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentFrame)), 01078 verticalScrollerWidth = _CGRectGetWidth([_verticalScroller frame]), 01079 horizontalScrollerHeight = _CGRectGetHeight([_horizontalScroller frame]), 01080 hasVerticalScroll = difference.height > 0.0, 01081 hasHorizontalScroll = difference.width > 0.0, 01082 shouldShowVerticalScroller = _hasVerticalScroller && (!_autohidesScrollers || hasVerticalScroll), 01083 shouldShowHorizontalScroller = _hasHorizontalScroller && (!_autohidesScrollers || hasHorizontalScroll); 01084 01085 // Now we have to account for the shown scrollers affecting the deltas. 01086 if (shouldShowVerticalScroller) 01087 { 01088 if (_scrollerStyle === CPScrollerStyleLegacy) 01089 difference.width += verticalScrollerWidth; 01090 hasHorizontalScroll = difference.width > 0.0; 01091 shouldShowHorizontalScroller = _hasHorizontalScroller && (!_autohidesScrollers || hasHorizontalScroll); 01092 } 01093 01094 if (shouldShowHorizontalScroller) 01095 { 01096 if (_scrollerStyle === CPScrollerStyleLegacy) 01097 difference.height += horizontalScrollerHeight; 01098 hasVerticalScroll = difference.height > 0.0; 01099 shouldShowVerticalScroller = _hasVerticalScroller && (!_autohidesScrollers || hasVerticalScroll); 01100 } 01101 01102 // We now definitively know which scrollers are shown or not, as well as whether they are showing scroll values. 01103 [_verticalScroller setHidden:!shouldShowVerticalScroller]; 01104 [_verticalScroller setEnabled:hasVerticalScroll]; 01105 01106 [_horizontalScroller setHidden:!shouldShowHorizontalScroller]; 01107 [_horizontalScroller setEnabled:hasHorizontalScroll]; 01108 01109 var overlay = [CPScroller scrollerOverlay]; 01110 if (_scrollerStyle === CPScrollerStyleLegacy) 01111 { 01112 // We can thus appropriately account for them changing the content size. 01113 if (shouldShowVerticalScroller) 01114 contentFrame.size.width -= verticalScrollerWidth; 01115 01116 if (shouldShowHorizontalScroller) 01117 contentFrame.size.height -= horizontalScrollerHeight; 01118 overlay = 0; 01119 } 01120 01121 var scrollPoint = [_contentView bounds].origin, 01122 wasShowingVerticalScroller = ![_verticalScroller isHidden], 01123 wasShowingHorizontalScroller = ![_horizontalScroller isHidden]; 01124 01125 if (shouldShowVerticalScroller) 01126 { 01127 var verticalScrollerY = 01128 MAX(_CGRectGetMinY(contentFrame), MAX(_CGRectGetMaxY([self _cornerViewFrame]), _CGRectGetMaxY(headerClipViewFrame))); 01129 01130 var verticalScrollerHeight = _CGRectGetMaxY(contentFrame) - verticalScrollerY; 01131 01132 // Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap. 01133 if (_scrollerStyle === CPScrollerStyleOverlay && hasHorizontalScroll) 01134 verticalScrollerHeight -= horizontalScrollerHeight; 01135 01136 [_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height]; 01137 [_verticalScroller setKnobProportion:_CGRectGetHeight(contentFrame) / _CGRectGetHeight(documentFrame)]; 01138 [_verticalScroller setFrame:_CGRectMake(_CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)]; 01139 } 01140 else if (wasShowingVerticalScroller) 01141 { 01142 [_verticalScroller setFloatValue:0.0]; 01143 [_verticalScroller setKnobProportion:1.0]; 01144 } 01145 01146 if (shouldShowHorizontalScroller) 01147 { 01148 var horizontalScrollerWidth = _CGRectGetWidth(contentFrame); 01149 // Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap. 01150 if (_scrollerStyle === CPScrollerStyleOverlay && hasVerticalScroll) 01151 horizontalScrollerWidth -= verticalScrollerWidth; 01152 01153 [_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width]; 01154 [_horizontalScroller setKnobProportion:_CGRectGetWidth(contentFrame) / _CGRectGetWidth(documentFrame)]; 01155 [_horizontalScroller setFrame:_CGRectMake(_CGRectGetMinX(contentFrame), _CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)]; 01156 } 01157 else if (wasShowingHorizontalScroller) 01158 { 01159 [_horizontalScroller setFloatValue:0.0]; 01160 [_horizontalScroller setKnobProportion:1.0]; 01161 } 01162 01163 [_contentView setFrame:contentFrame]; 01164 [_headerClipView setFrame:headerClipViewFrame]; 01165 [[_headerClipView documentView] setNeedsDisplay:YES]; 01166 [_cornerView setFrame:[self _cornerViewFrame]]; 01167 01168 if (_scrollerStyle === CPScrollerStyleLegacy) 01169 { 01170 [[self bottomCornerView] setFrame:[self _bottomCornerViewFrame]]; 01171 [[self bottomCornerView] setBackgroundColor:[self currentValueForThemeAttribute:@"bottom-corner-color"]]; 01172 } 01173 01174 --_recursionCount; 01175 } 01176 01180 - (void)flashScrollers 01181 { 01182 if (_scrollerStyle === CPScrollerStyleLegacy) 01183 return; 01184 01185 if (_hasHorizontalScroller) 01186 { 01187 [_horizontalScroller setHidden:NO]; 01188 [_horizontalScroller fadeIn]; 01189 } 01190 01191 if (_hasVerticalScroller) 01192 { 01193 [_verticalScroller setHidden:NO]; 01194 [_verticalScroller fadeIn]; 01195 } 01196 01197 if (_timerScrollersHide) 01198 [_timerScrollersHide invalidate] 01199 _timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO]; 01200 } 01201 01202 /* @ignore */ 01203 - (void)resizeSubviewsWithOldSize:(CGSize)aSize 01204 { 01205 [self reflectScrolledClipView:_contentView]; 01206 } 01207 01208 01209 #pragma mark - 01210 #pragma mark Overrides 01211 01212 - (void)drawRect:(CPRect)aRect 01213 { 01214 [super drawRect:aRect]; 01215 01216 if (_borderType == CPNoBorder) 01217 return; 01218 01219 var strokeRect = [self bounds], 01220 context = [[CPGraphicsContext currentContext] graphicsPort]; 01221 01222 CGContextSetLineWidth(context, 1); 01223 01224 switch (_borderType) 01225 { 01226 case CPLineBorder: 01227 CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"border-color"]); 01228 CGContextStrokeRect(context, _CGRectInset(strokeRect, 0.5, 0.5)); 01229 break; 01230 01231 case CPBezelBorder: 01232 [self _drawGrayBezelInContext:context bounds:strokeRect]; 01233 break; 01234 01235 case CPGrooveBorder: 01236 [self _drawGrooveInContext:context bounds:strokeRect]; 01237 break; 01238 01239 default: 01240 break; 01241 } 01242 } 01243 01244 - (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect 01245 { 01246 CGContextBeginPath(context); 01247 CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]); 01248 01249 var y = _CGRectGetMinY(aRect) + 0.5; 01250 01251 CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y); 01252 CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 1.0, y); 01253 CGContextStrokePath(context); 01254 01255 CGContextBeginPath(context); 01256 CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]); 01257 CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 1.0, y); 01258 CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y); 01259 CGContextStrokePath(context); 01260 01261 CGContextBeginPath(context); 01262 CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]); 01263 CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y); 01264 CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y); 01265 CGContextStrokePath(context); 01266 01267 CGContextBeginPath(context); 01268 CGContextSetStrokeColor(context, [CPColor colorWithWhite:190.0 / 255.0 alpha:1.0]); 01269 01270 var x = _CGRectGetMaxX(aRect) - 0.5; 01271 01272 CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 1.0); 01273 CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect)); 01274 01275 CGContextMoveToPoint(context, x - 0.5, _CGRectGetMaxY(aRect) - 0.5); 01276 CGContextAddLineToPoint(context, _CGRectGetMinX(aRect), _CGRectGetMaxY(aRect) - 0.5); 01277 01278 x = _CGRectGetMinX(aRect) + 0.5; 01279 01280 CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect)); 01281 CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect) + 1.0); 01282 01283 CGContextStrokePath(context); 01284 } 01285 01286 - (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect 01287 { 01288 CGContextBeginPath(context); 01289 CGContextSetStrokeColor(context, [CPColor colorWithWhite:159.0 / 255.0 alpha:1.0]); 01290 01291 var y = _CGRectGetMinY(aRect) + 0.5; 01292 01293 CGContextMoveToPoint(context, _CGRectGetMinX(aRect), y); 01294 CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect), y); 01295 01296 var x = _CGRectGetMaxX(aRect) - 1.5; 01297 01298 CGContextMoveToPoint(context, x, _CGRectGetMinY(aRect) + 2.0); 01299 CGContextAddLineToPoint(context, x, _CGRectGetMaxY(aRect) - 1.0); 01300 01301 y = _CGRectGetMaxY(aRect) - 1.5; 01302 01303 CGContextMoveToPoint(context, _CGRectGetMaxX(aRect) - 1.0, y); 01304 CGContextAddLineToPoint(context, _CGRectGetMinX(aRect) + 2.0, y); 01305 01306 x = _CGRectGetMinX(aRect) + 0.5; 01307 01308 CGContextMoveToPoint(context, x, _CGRectGetMaxY(aRect)); 01309 CGContextAddLineToPoint(context, x, _CGRectGetMinY(aRect)); 01310 01311 CGContextStrokePath(context); 01312 01313 CGContextBeginPath(context); 01314 CGContextSetStrokeColor(context, [CPColor whiteColor]); 01315 01316 var rect = _CGRectOffset(aRect, 1.0, 1.0); 01317 01318 rect.size.width -= 1.0; 01319 rect.size.height -= 1.0; 01320 CGContextStrokeRect(context, _CGRectInset(rect, 0.5, 0.5)); 01321 01322 CGContextBeginPath(context); 01323 CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]); 01324 01325 y = _CGRectGetMinY(aRect) + 2.5; 01326 01327 CGContextMoveToPoint(context, _CGRectGetMinX(aRect) + 2.0, y); 01328 CGContextAddLineToPoint(context, _CGRectGetMaxX(aRect) - 2.0, y); 01329 CGContextStrokePath(context); 01330 } 01331 01337 - (void)scrollWheel:(CPEvent)anEvent 01338 { 01339 if (_timerScrollersHide) 01340 [_timerScrollersHide invalidate]; 01341 if (![_verticalScroller isHidden]) 01342 [_verticalScroller fadeIn]; 01343 if (![_horizontalScroller isHidden]) 01344 [_horizontalScroller fadeIn]; 01345 if (![_horizontalScroller isHidden] || ![_verticalScroller isHidden]) 01346 _timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO]; 01347 01348 [self _respondToScrollWheelEventWithDeltaX:[anEvent deltaX] deltaY:[anEvent deltaY]]; 01349 } 01350 01351 - (void)scrollPageUp:(id)sender 01352 { 01353 var contentBounds = [_contentView bounds]; 01354 [self moveByOffset:CGSizeMake(0.0, -(_CGRectGetHeight(contentBounds) - _verticalPageScroll))]; 01355 } 01356 01357 - (void)scrollPageDown:(id)sender 01358 { 01359 var contentBounds = [_contentView bounds]; 01360 [self moveByOffset:CGSizeMake(0.0, _CGRectGetHeight(contentBounds) - _verticalPageScroll)]; 01361 } 01362 01363 - (void)scrollToBeginningOfDocument:(id)sender 01364 { 01365 [_contentView scrollToPoint:_CGPointMakeZero()]; 01366 [_headerClipView scrollToPoint:_CGPointMakeZero()]; 01367 } 01368 01369 - (void)scrollToEndOfDocument:(id)sender 01370 { 01371 var contentBounds = [_contentView bounds], 01372 documentFrame = [[self documentView] frame], 01373 scrollPoint = _CGPointMake(0.0, _CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds)); 01374 01375 [_contentView scrollToPoint:scrollPoint]; 01376 [_headerClipView scrollToPoint:_CGPointMakeZero()]; 01377 } 01378 01379 - (void)moveLeft:(id)sender 01380 { 01381 [self moveByOffset:CGSizeMake(-_horizontalLineScroll, 0.0)]; 01382 } 01383 01384 - (void)moveRight:(id)sender 01385 { 01386 [self moveByOffset:CGSizeMake(_horizontalLineScroll, 0.0)]; 01387 } 01388 01389 - (void)moveUp:(id)sender 01390 { 01391 [self moveByOffset:CGSizeMake(0.0, -_verticalLineScroll)]; 01392 } 01393 01394 - (void)moveDown:(id)sender 01395 { 01396 [self moveByOffset:CGSizeMake(0.0, _verticalLineScroll)]; 01397 } 01398 01399 - (void)moveByOffset:(CGSize)aSize 01400 { 01401 var documentFrame = [[self documentView] frame], 01402 contentBounds = [_contentView bounds]; 01403 01404 contentBounds.origin.x += aSize.width; 01405 contentBounds.origin.y += aSize.height; 01406 01407 [_contentView scrollToPoint:contentBounds.origin]; 01408 [_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0)]; 01409 } 01410 01411 @end 01412 01413 01414 var CPScrollViewContentViewKey = @"CPScrollViewContentView", 01415 CPScrollViewHeaderClipViewKey = @"CPScrollViewHeaderClipViewKey", 01416 CPScrollViewVLineScrollKey = @"CPScrollViewVLineScroll", 01417 CPScrollViewHLineScrollKey = @"CPScrollViewHLineScroll", 01418 CPScrollViewVPageScrollKey = @"CPScrollViewVPageScroll", 01419 CPScrollViewHPageScrollKey = @"CPScrollViewHPageScroll", 01420 CPScrollViewHasVScrollerKey = @"CPScrollViewHasVScroller", 01421 CPScrollViewHasHScrollerKey = @"CPScrollViewHasHScroller", 01422 CPScrollViewVScrollerKey = @"CPScrollViewVScroller", 01423 CPScrollViewHScrollerKey = @"CPScrollViewHScroller", 01424 CPScrollViewAutohidesScrollerKey = @"CPScrollViewAutohidesScroller", 01425 CPScrollViewCornerViewKey = @"CPScrollViewCornerViewKey", 01426 CPScrollViewBottomCornerViewKey = @"CPScrollViewBottomCornerViewKey", 01427 CPScrollViewBorderTypeKey = @"CPScrollViewBorderTypeKey", 01428 CPScrollViewScrollerStyleKey = @"CPScrollViewScrollerStyleKey", 01429 CPScrollViewScrollerKnobStyleKey = @"CPScrollViewScrollerKnobStyleKey"; 01430 01431 @implementation CPScrollView (CPCoding) 01432 01433 - (id)initWithCoder:(CPCoder)aCoder 01434 { 01435 if (self = [super initWithCoder:aCoder]) 01436 { 01437 _verticalLineScroll = [aCoder decodeFloatForKey:CPScrollViewVLineScrollKey]; 01438 _verticalPageScroll = [aCoder decodeFloatForKey:CPScrollViewVPageScrollKey]; 01439 01440 _horizontalLineScroll = [aCoder decodeFloatForKey:CPScrollViewHLineScrollKey]; 01441 _horizontalPageScroll = [aCoder decodeFloatForKey:CPScrollViewHPageScrollKey]; 01442 01443 _contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey]; 01444 _headerClipView = [aCoder decodeObjectForKey:CPScrollViewHeaderClipViewKey]; 01445 01446 if (!_headerClipView) 01447 { 01448 _headerClipView = [[CPClipView alloc] init]; 01449 [self addSubview:_headerClipView]; 01450 } 01451 01452 _verticalScroller = [aCoder decodeObjectForKey:CPScrollViewVScrollerKey]; 01453 _horizontalScroller = [aCoder decodeObjectForKey:CPScrollViewHScrollerKey]; 01454 01455 _hasVerticalScroller = [aCoder decodeBoolForKey:CPScrollViewHasVScrollerKey]; 01456 _hasHorizontalScroller = [aCoder decodeBoolForKey:CPScrollViewHasHScrollerKey]; 01457 _autohidesScrollers = [aCoder decodeBoolForKey:CPScrollViewAutohidesScrollerKey]; 01458 01459 _borderType = [aCoder decodeIntForKey:CPScrollViewBorderTypeKey]; 01460 01461 _cornerView = [aCoder decodeObjectForKey:CPScrollViewCornerViewKey]; 01462 _bottomCornerView = [aCoder decodeObjectForKey:CPScrollViewBottomCornerViewKey]; 01463 01464 _delegate = nil; 01465 _scrollTimer = nil; 01466 _implementedDelegateMethods = 0; 01467 01468 // Due to the anything goes nature of decoding, our subviews may not exist yet, so layout at the end of the run loop when we're sure everything is in a correct state. 01469 [[CPRunLoop currentRunLoop] performSelector:@selector(_updateCornerAndHeaderView) target:self argument:_contentView order:0 modes:[CPDefaultRunLoopMode]]; 01470 01471 [self setScrollerStyle:[aCoder decodeIntForKey:CPScrollViewScrollerStyleKey] || CPScrollerStyleGlobal]; 01472 [self setScrollerKnobStyle:[aCoder decodeIntForKey:CPScrollViewScrollerKnobStyleKey] || CPScrollerKnobStyleDefault]; 01473 01474 [[CPNotificationCenter defaultCenter] addObserver:self 01475 selector:@selector(_didReceiveDefaultStyleChange:) 01476 name:CPScrollerStyleGlobalChangeNotification 01477 object:nil]; 01478 } 01479 01480 return self; 01481 } 01482 01483 - (void)encodeWithCoder:(CPCoder)aCoder 01484 { 01485 [super encodeWithCoder:aCoder]; 01486 01487 [aCoder encodeObject:_contentView forKey:CPScrollViewContentViewKey]; 01488 [aCoder encodeObject:_headerClipView forKey:CPScrollViewHeaderClipViewKey]; 01489 01490 [aCoder encodeObject:_verticalScroller forKey:CPScrollViewVScrollerKey]; 01491 [aCoder encodeObject:_horizontalScroller forKey:CPScrollViewHScrollerKey]; 01492 01493 [aCoder encodeFloat:_verticalLineScroll forKey:CPScrollViewVLineScrollKey]; 01494 [aCoder encodeFloat:_verticalPageScroll forKey:CPScrollViewVPageScrollKey]; 01495 [aCoder encodeFloat:_horizontalLineScroll forKey:CPScrollViewHLineScrollKey]; 01496 [aCoder encodeFloat:_horizontalPageScroll forKey:CPScrollViewHPageScrollKey]; 01497 01498 [aCoder encodeBool:_hasVerticalScroller forKey:CPScrollViewHasVScrollerKey]; 01499 [aCoder encodeBool:_hasHorizontalScroller forKey:CPScrollViewHasHScrollerKey]; 01500 [aCoder encodeBool:_autohidesScrollers forKey:CPScrollViewAutohidesScrollerKey]; 01501 01502 [aCoder encodeObject:_cornerView forKey:CPScrollViewCornerViewKey]; 01503 [aCoder encodeObject:_bottomCornerView forKey:CPScrollViewBottomCornerViewKey]; 01504 01505 [aCoder encodeInt:_borderType forKey:CPScrollViewBorderTypeKey]; 01506 01507 [aCoder encodeInt:_scrollerStyle forKey:CPScrollViewScrollerStyleKey]; 01508 [aCoder encodeInt:_scrollerKnobStyle forKey:CPScrollViewScrollerKnobStyleKey]; 01509 } 01510 01511 @end