API 0.9.5
AppKit/CPScrollView.j
Go to the documentation of this file.
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
 All Classes Files Functions Variables Defines