00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import "CPView.j"
00024 @import "CPClipView.j"
00025 @import "CPScroller.j"
00026
00027 #include "CoreGraphics/CGGeometry.h"
00028
00029
00038 @implementation CPScrollView : CPView
00039 {
00040 CPClipView _contentView;
00041
00042 BOOL _hasVerticalScroller;
00043 BOOL _hasHorizontalScroller;
00044 BOOL _autohidesScrollers;
00045
00046 CPScroller _verticalScroller;
00047 CPScroller _horizontalScroller;
00048
00049 int _recursionCount;
00050
00051 float _verticalLineScroll;
00052 float _verticalPageScroll;
00053 float _horizontalLineScroll;
00054 float _horizontalPageScroll;
00055 }
00056
00057 - (id)initWithFrame:(CGRect)aFrame
00058 {
00059 self = [super initWithFrame:aFrame];
00060
00061 if (self)
00062 {
00063 _verticalLineScroll = 10.0;
00064 _verticalPageScroll = 10.0;
00065
00066 _horizontalLineScroll = 10.0;
00067 _horizontalPageScroll = 10.0;
00068
00069 _contentView = [[CPClipView alloc] initWithFrame:[self bounds]];
00070
00071 [self addSubview:_contentView];
00072
00073 [self setHasVerticalScroller:YES];
00074 [self setHasHorizontalScroller:YES];
00075 }
00076
00077 return self;
00078 }
00079
00080
00084 - (CGRect)contentSize
00085 {
00086 return [_contentView frame].size;
00087 }
00088
00092 - (id)documentView
00093 {
00094 return [_contentView documentView];
00095 }
00096
00101 - (void)setContentView:(CPClipView)aContentView
00102 {
00103 if (!aContentView)
00104 return;
00105
00106 var documentView = [aContentView documentView];
00107
00108 if (documentView)
00109 [documentView removeFromSuperview];
00110
00111 [_contentView removeFromSuperview];
00112
00113 var size = [self contentSize];
00114
00115 _contentView = aContentView;
00116
00117 [_contentView setFrame:CGRectMake(0.0, 0.0, size.width, size.height)];
00118 [_contentView setDocumentView:documentView];
00119
00120 [self addSubview:_contentView];
00121 }
00122
00126 - (CPClipView)contentView
00127 {
00128 return _contentView;
00129 }
00130
00135 - (void)setDocumentView:(CPView)aView
00136 {
00137 [_contentView setDocumentView:aView];
00138 [self reflectScrolledClipView:_contentView];
00139 }
00140
00145 - (void)reflectScrolledClipView:(CPClipView)aClipView
00146 {
00147 if(_contentView !== aClipView)
00148 return;
00149
00150 if (_recursionCount > 5)
00151 return;
00152
00153 ++_recursionCount;
00154
00155 var documentView = [self documentView];
00156
00157 if (!documentView)
00158 {
00159 if (_autohidesScrollers)
00160 {
00161 [_verticalScroller setHidden:YES];
00162 [_horizontalScroller setHidden:YES];
00163 }
00164 else
00165 {
00166
00167
00168 }
00169
00170 [_contentView setFrame:[self bounds]];
00171
00172 --_recursionCount;
00173
00174 return;
00175 }
00176
00177 var documentFrame = [documentView frame],
00178 contentViewFrame = [self bounds],
00179 scrollPoint = [_contentView bounds].origin,
00180 difference = _CGSizeMake(CPRectGetWidth(documentFrame) - CPRectGetWidth(contentViewFrame), CPRectGetHeight(documentFrame) - CPRectGetHeight(contentViewFrame)),
00181 shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > 0.0) && _hasVerticalScroller,
00182 shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > 0.0) && _hasHorizontalScroller,
00183 wasShowingVerticalScroller = ![_verticalScroller isHidden],
00184 wasShowingHorizontalScroller = ![_horizontalScroller isHidden],
00185 verticalScrollerWidth = _CGRectGetWidth([_verticalScroller frame]);
00186 horizontalScrollerHeight = _CGRectGetHeight([_horizontalScroller frame]);
00187
00188 if (_autohidesScrollers)
00189 {
00190
00191 if (shouldShowVerticalScroller)
00192 shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > -verticalScrollerWidth) && _hasHorizontalScroller;
00193
00194 if (shouldShowHorizontalScroller)
00195 shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > -horizontalScrollerHeight) && _hasVerticalScroller;
00196 }
00197
00198 [_verticalScroller setHidden:!shouldShowVerticalScroller];
00199 [_verticalScroller setEnabled:difference.height > 0.0];
00200
00201 [_horizontalScroller setHidden:!shouldShowHorizontalScroller];
00202 [_horizontalScroller setEnabled:difference.width > 0.0];
00203
00204 if (shouldShowVerticalScroller)
00205 {
00206 var verticalScrollerHeight = CPRectGetHeight(contentViewFrame);
00207
00208 if (shouldShowHorizontalScroller)
00209 verticalScrollerHeight -= horizontalScrollerHeight;
00210
00211 difference.width += verticalScrollerWidth;
00212 contentViewFrame.size.width -= verticalScrollerWidth;
00213
00214 [_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height
00215 knobProportion:CPRectGetHeight(contentViewFrame) / CPRectGetHeight(documentFrame)];
00216 [_verticalScroller setFrame:CPRectMake(CPRectGetMaxX(contentViewFrame), 0.0, verticalScrollerWidth, verticalScrollerHeight)];
00217 }
00218 else if (wasShowingVerticalScroller)
00219 [_verticalScroller setFloatValue:0.0 knobProportion:1.0];
00220
00221 if (shouldShowHorizontalScroller)
00222 {
00223 difference.height += horizontalScrollerHeight;
00224 contentViewFrame.size.height -= horizontalScrollerHeight;
00225
00226 [_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width
00227 knobProportion:CPRectGetWidth(contentViewFrame) / CPRectGetWidth(documentFrame)];
00228 [_horizontalScroller setFrame:CPRectMake(0.0, CPRectGetMaxY(contentViewFrame), CPRectGetWidth(contentViewFrame), horizontalScrollerHeight)];
00229 }
00230 else if (wasShowingHorizontalScroller)
00231 [_horizontalScroller setFloatValue:0.0 knobProportion:1.0];
00232
00233 [_contentView setFrame:contentViewFrame];
00234
00235 --_recursionCount;
00236 }
00237
00238
00243 - (void)setHorizontalScroller:(CPScroller)aScroller
00244 {
00245 if (_horizontalScroller === aScroller)
00246 return;
00247
00248 [_horizontalScroller removeFromSuperview];
00249 [_horizontalScroller setTarget:nil];
00250 [_horizontalScroller setAction:nil];
00251
00252 _horizontalScroller = aScroller;
00253
00254 [_horizontalScroller setTarget:self];
00255 [_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)];
00256
00257 [self addSubview:_horizontalScroller];
00258
00259 [self reflectScrolledClipView:_contentView];
00260 }
00261
00265 - (CPScroller)horizontalScroller
00266 {
00267 return _horizontalScroller;
00268 }
00269
00275 - (void)setHasHorizontalScroller:(BOOL)shouldHaveHorizontalScroller
00276 {
00277 if (_hasHorizontalScroller === shouldHaveHorizontalScroller)
00278 return;
00279
00280 _hasHorizontalScroller = shouldHaveHorizontalScroller;
00281
00282 if (_hasHorizontalScroller && !_horizontalScroller)
00283 [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, CPRectGetWidth([self bounds]), [CPScroller scrollerWidth])]];
00284
00285 else if (!_hasHorizontalScroller && _horizontalScroller)
00286 {
00287 [_horizontalScroller setHidden:YES];
00288
00289 [self reflectScrolledClipView:_contentView];
00290 }
00291 }
00292
00296 - (BOOL)hasHorizontalScroller
00297 {
00298 return _hasHorizontalScroller;
00299 }
00300
00305 - (void)setVerticalScroller:(CPScroller)aScroller
00306 {
00307 if (_verticalScroller === aScroller)
00308 return;
00309
00310 [_verticalScroller removeFromSuperview];
00311 [_verticalScroller setTarget:nil];
00312 [_verticalScroller setAction:nil];
00313
00314 _verticalScroller = aScroller;
00315
00316 [_verticalScroller setTarget:self];
00317 [_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)];
00318
00319 [self addSubview:_verticalScroller];
00320
00321 [self reflectScrolledClipView:_contentView];
00322 }
00323
00327 - (CPScroller)verticalScroller
00328 {
00329 return _verticalScroller;
00330 }
00331
00338 - (void)setHasVerticalScroller:(BOOL)shouldHaveVerticalScroller
00339 {
00340 if (_hasVerticalScroller === shouldHaveVerticalScroller)
00341 return;
00342
00343 _hasVerticalScroller = shouldHaveVerticalScroller;
00344
00345 if (_hasVerticalScroller && !_verticalScroller)
00346 [self setVerticalScroller:[[CPScroller alloc] initWithFrame:CPRectMake(0.0, 0.0, [CPScroller scrollerWidth], CPRectGetHeight([self bounds]))]];
00347
00348 else if (!_hasVerticalScroller && _verticalScroller)
00349 {
00350 [_verticalScroller setHidden:YES];
00351
00352 [self reflectScrolledClipView:_contentView];
00353 }
00354 }
00355
00359 - (BOOL)hasVerticalScroller
00360 {
00361 return _hasVerticalScroller;
00362 }
00363
00369 - (void)setAutohidesScrollers:(BOOL)autohidesScrollers
00370 {
00371 if (_autohidesScrollers == autohidesScrollers)
00372 return;
00373
00374 _autohidesScrollers = autohidesScrollers;
00375
00376 [self reflectScrolledClipView:_contentView];
00377 }
00378
00383 - (BOOL)autohidesScrollers
00384 {
00385 return _autohidesScrollers;
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 - (void)_verticalScrollerDidScroll:(CPScroller)aScroller
00397 {
00398 var value = [aScroller floatValue],
00399 documentFrame = [[_contentView documentView] frame];
00400 contentBounds = [_contentView bounds];
00401
00402 switch ([_verticalScroller hitPart])
00403 {
00404 case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll;
00405 break;
00406
00407 case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll;
00408 break;
00409
00410 case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
00411 break;
00412
00413 case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
00414 break;
00415
00416 case CPScrollerKnobSlot:
00417 case CPScrollerKnob:
00418 default: contentBounds.origin.y = value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds));
00419 }
00420
00421 [_contentView scrollToPoint:contentBounds.origin];
00422 }
00423
00424
00425 - (void)_horizontalScrollerDidScroll:(CPScroller)aScroller
00426 {
00427 var value = [aScroller floatValue],
00428 documentFrame = [[self documentView] frame],
00429 contentBounds = [_contentView bounds];
00430
00431 switch ([_horizontalScroller hitPart])
00432 {
00433 case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll;
00434 break;
00435
00436 case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll;
00437 break;
00438
00439 case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
00440 break;
00441
00442 case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
00443 break;
00444
00445 case CPScrollerKnobSlot:
00446 case CPScrollerKnob:
00447 default: contentBounds.origin.x = value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds));
00448 }
00449
00450 [_contentView scrollToPoint:contentBounds.origin];
00451 }
00452
00456 - (void)tile
00457 {
00458
00459
00460
00461
00462 }
00463
00464
00465
00466
00467 -(void)resizeSubviewsWithOldSize:(CGSize)aSize
00468 {
00469 [self reflectScrolledClipView:_contentView];
00470 }
00471
00472
00477 - (void)setLineScroll:(float)aLineScroll
00478 {
00479 [self setHorizonalLineScroll:aLineScroll];
00480 [self setVerticalLineScroll:aLineScroll];
00481 }
00482
00486 - (float)lineScroll
00487 {
00488 return [self horizontalLineScroll];
00489 }
00490
00495 - (void)setHorizontalLineScroll:(float)aLineScroll
00496 {
00497 _horizontalLineScroll = aLineScroll;
00498 }
00499
00503 - (float)horizontalLineScroll
00504 {
00505 return _horizontalLineScroll;
00506 }
00507
00512 - (void)setVerticalLineScroll:(float)aLineScroll
00513 {
00514 _verticalLineScroll = aLineScroll;
00515 }
00516
00520 - (float)verticalLineScroll
00521 {
00522 return _verticalLineScroll;
00523 }
00524
00529 - (void)setPageScroll:(float)aPageScroll
00530 {
00531 [self setHorizontalPageScroll:aPageScroll];
00532 [self setVerticalPageScroll:aPageScroll];
00533 }
00534
00538 - (float)pageScroll
00539 {
00540 return [self horizontalPageScroll];
00541 }
00542
00547 - (void)setHorizontalPageScroll:(float)aPageScroll
00548 {
00549 _horizontalPageScroll = aPageScroll;
00550 }
00551
00555 - (float)horizontalPageScroll
00556 {
00557 return _horizontalPageScroll;
00558 }
00559
00564 - (void)setVerticalPageScroll:(float)aPageScroll
00565 {
00566 _verticalPageScroll = aPageScroll;
00567 }
00568
00572 - (float)verticalPageScroll
00573 {
00574 return _verticalPageScroll;
00575 }
00576
00581 - (void)scrollWheel:(CPEvent)anEvent
00582 {
00583 var value = [_verticalScroller floatValue],
00584 documentFrame = [[self documentView] frame],
00585 contentBounds = [_contentView bounds];
00586
00587 contentBounds.origin.x += [anEvent deltaX] * _horizontalLineScroll;
00588 contentBounds.origin.y += [anEvent deltaY] * _verticalLineScroll;
00589
00590 [_contentView scrollToPoint:contentBounds.origin];
00591 }
00592
00593 - (void)keyDown:(CPEvent)anEvent
00594 {
00595 var keyCode = [anEvent keyCode],
00596 value = [_verticalScroller floatValue],
00597 documentFrame = [[self documentView] frame],
00598 contentBounds = [_contentView bounds];
00599
00600 switch (keyCode)
00601 {
00602 case 33:
00603 contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
00604 break;
00605
00606 case 34:
00607 contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
00608 break;
00609
00610 case 38:
00611 contentBounds.origin.y -= _verticalLineScroll;
00612 break;
00613
00614 case 40:
00615 contentBounds.origin.y += _verticalLineScroll;
00616 break;
00617
00618 case 37:
00619 contentBounds.origin.x -= _horizontalLineScroll;
00620 break;
00621
00622 case 49:
00623 contentBounds.origin.x += _horizontalLineScroll;
00624 break;
00625
00626 default: return [super keyDown:anEvent];
00627 }
00628
00629 [_contentView scrollToPoint:contentBounds.origin];
00630 }
00631
00632 @end
00633
00634 var CPScrollViewContentViewKey = "CPScrollViewContentView",
00635 CPScrollViewVLineScrollKey = "CPScrollViewVLineScroll",
00636 CPScrollViewHLineScrollKey = "CPScrollViewHLineScroll",
00637 CPScrollViewVPageScrollKey = "CPScrollViewVPageScroll",
00638 CPScrollViewHPageScrollKey = "CPScrollViewHPageScroll",
00639 CPScrollViewHasVScrollerKey = "CPScrollViewHasVScroller",
00640 CPScrollViewHasHScrollerKey = "CPScrollViewHasHScroller",
00641 CPScrollViewVScrollerKey = "CPScrollViewVScroller",
00642 CPScrollViewHScrollerKey = "CPScrollViewHScroller",
00643 CPScrollViewAutohidesScrollerKey = "CPScrollViewAutohidesScroller";
00644
00645 @implementation CPScrollView (CPCoding)
00646
00647 - (id)initWithCoder:(CPCoder)aCoder
00648 {
00649 if (self = [super initWithCoder:aCoder])
00650 {
00651 _verticalLineScroll = [aCoder decodeFloatForKey:CPScrollViewVLineScrollKey];
00652 _verticalPageScroll = [aCoder decodeFloatForKey:CPScrollViewVPageScrollKey];
00653
00654 _horizontalLineScroll = [aCoder decodeFloatForKey:CPScrollViewHLineScrollKey];
00655 _horizontalPageScroll = [aCoder decodeFloatForKey:CPScrollViewHPageScrollKey];
00656
00657 _contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey];
00658
00659 _verticalScroller = [aCoder decodeObjectForKey:CPScrollViewVScrollerKey];
00660 _horizontalScroller = [aCoder decodeObjectForKey:CPScrollViewHScrollerKey];
00661
00662 _hasVerticalScroller = [aCoder decodeBoolForKey:CPScrollViewHasVScrollerKey];
00663 _hasHorizontalScroller = [aCoder decodeBoolForKey:CPScrollViewHasHScrollerKey];
00664 _autohidesScrollers = [aCoder decodeBoolForKey:CPScrollViewAutohidesScrollerKey];
00665
00666
00667 [[CPRunLoop currentRunLoop] performSelector:@selector(reflectScrolledClipView:) target:self argument:_contentView order:0 modes:[CPDefaultRunLoopMode]];
00668 }
00669
00670 return self;
00671 }
00672
00673 - (void)encodeWithCoder:(CPCoder)aCoder
00674 {
00675 [super encodeWithCoder:aCoder];
00676
00677 [aCoder encodeObject:_contentView forKey:CPScrollViewContentViewKey];
00678
00679 [aCoder encodeObject:_verticalScroller forKey:CPScrollViewVScrollerKey];
00680 [aCoder encodeObject:_horizontalScroller forKey:CPScrollViewHScrollerKey];
00681
00682 [aCoder encodeFloat:_verticalLineScroll forKey:CPScrollViewVLineScrollKey];
00683 [aCoder encodeFloat:_verticalPageScroll forKey:CPScrollViewVPageScrollKey];
00684 [aCoder encodeFloat:_horizontalLineScroll forKey:CPScrollViewHLineScrollKey];
00685 [aCoder encodeFloat:_horizontalPageScroll forKey:CPScrollViewHPageScrollKey];
00686
00687 [aCoder encodeBool:_hasVerticalScroller forKey:CPScrollViewHasVScrollerKey];
00688 [aCoder encodeBool:_hasHorizontalScroller forKey:CPScrollViewHasHScrollerKey];
00689 [aCoder encodeBool:_autohidesScrollers forKey:CPScrollViewAutohidesScrollerKey];
00690 }
00691
00692 @end