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
00036 @implementation CPScrollView : CPView
00037 {
00038 CPClipView _contentView;
00039
00040 BOOL _hasVerticalScroller;
00041 BOOL _hasHorizontalScroller;
00042 BOOL _autohidesScrollers;
00043
00044 CPScroller _verticalScroller;
00045 CPScroller _horizontalScroller;
00046
00047 int _recursionCount;
00048
00049 float _verticalLineScroll;
00050 float _verticalPageScroll;
00051 float _horizontalLineScroll;
00052 float _horizontalPageScroll;
00053 }
00054
00055 - (id)initWithFrame:(CGRect)aFrame
00056 {
00057 self = [super initWithFrame:aFrame];
00058
00059 if (self)
00060 {
00061 _verticalLineScroll = 10.0;
00062 _verticalPageScroll = 10.0;
00063
00064 _horizontalLineScroll = 10.0;
00065 _horizontalPageScroll = 10.0;
00066
00067 _contentView = [[CPClipView alloc] initWithFrame:[self bounds]];
00068
00069 [self addSubview:_contentView];
00070
00071 [self setHasVerticalScroller:YES];
00072 [self setHasHorizontalScroller:YES];
00073 }
00074
00075 return self;
00076 }
00077
00078
00082 - (CGRect)contentSize
00083 {
00084 return [_contentView frame].size;
00085 }
00086
00090 - (id)documentView
00091 {
00092 return [_contentView documentView];
00093 }
00094
00099 - (void)setContentView:(CPClipView)aContentView
00100 {
00101 if (!aContentView)
00102 return;
00103
00104 var documentView = [aContentView documentView];
00105
00106 if (documentView)
00107 [documentView removeFromSuperview];
00108
00109 [_contentView removeFromSuperview];
00110
00111 var size = [self contentSize];
00112
00113 _contentView = aContentView;
00114
00115 [_contentView setFrame:CGRectMake(0.0, 0.0, size.width, size.height)];
00116 [_contentView setDocumentView:documentView];
00117
00118 [self addSubview:_contentView];
00119 }
00120
00124 - (CPClipView)contentView
00125 {
00126 return _contentView;
00127 }
00128
00133 - (void)setDocumentView:(CPView)aView
00134 {
00135 [_contentView setDocumentView:aView];
00136 [self reflectScrolledClipView:_contentView];
00137 }
00138
00143 - (void)reflectScrolledClipView:(CPClipView)aClipView
00144 {
00145 if(_contentView != aClipView)
00146 return;
00147
00148 if (_recursionCount > 5)
00149 return;
00150
00151 ++_recursionCount;
00152
00153 var documentView = [self documentView];
00154
00155 if (!documentView)
00156 {
00157 if (_autohidesScrollers)
00158 {
00159 [_verticalScroller setHidden:YES];
00160 [_horizontalScroller setHidden:YES];
00161 }
00162 else
00163 {
00164 [_verticalScroller setEnabled:NO];
00165 [_horizontalScroller setEnabled:NO];
00166 }
00167
00168 [_contentView setFrame:[self bounds]];
00169
00170 --_recursionCount;
00171
00172 return;
00173 }
00174
00175 var documentFrame = [documentView frame],
00176 contentViewFrame = [self bounds],
00177 scrollPoint = [_contentView bounds].origin,
00178 difference = _CGSizeMake(CPRectGetWidth(documentFrame) - CPRectGetWidth(contentViewFrame), CPRectGetHeight(documentFrame) - CPRectGetHeight(contentViewFrame)),
00179 shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > 0.0) && _hasVerticalScroller,
00180 shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > 0.0) && _hasHorizontalScroller,
00181 wasShowingVerticalScroller = ![_verticalScroller isHidden],
00182 wasShowingHorizontalScroller = ![_horizontalScroller isHidden],
00183 verticalScrollerWidth = [CPScroller scrollerWidthForControlSize:[_verticalScroller controlSize]],
00184 horizontalScrollerHeight = [CPScroller scrollerWidthForControlSize:[_horizontalScroller controlSize]];
00185
00186 if (_autohidesScrollers)
00187 {
00188 if (shouldShowVerticalScroller)
00189 shouldShowHorizontalScroller = (!_autohidesScrollers || difference.width > -verticalScrollerWidth) && _hasHorizontalScroller;
00190 if (shouldShowHorizontalScroller)
00191 shouldShowVerticalScroller = (!_autohidesScrollers || difference.height > -horizontalScrollerHeight) && _hasVerticalScroller;
00192 }
00193
00194 [_verticalScroller setHidden:!shouldShowVerticalScroller];
00195 [_verticalScroller setEnabled:!_autohidesScrollers && difference.height < 0];
00196
00197 [_horizontalScroller setHidden:!shouldShowHorizontalScroller];
00198 [_horizontalScroller setEnabled:!_autohidesScrollers && difference.width < 0];
00199
00200 if (shouldShowVerticalScroller)
00201 {
00202 var verticalScrollerHeight = CPRectGetHeight(contentViewFrame);
00203
00204 if (shouldShowHorizontalScroller)
00205 verticalScrollerHeight -= horizontalScrollerHeight;
00206
00207 difference.width += verticalScrollerWidth;
00208 contentViewFrame.size.width -= verticalScrollerWidth;
00209
00210 [_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height
00211 knobProportion:CPRectGetHeight(contentViewFrame) / CPRectGetHeight(documentFrame)];
00212 [_verticalScroller setFrame:CPRectMake(CPRectGetMaxX(contentViewFrame), 0.0, verticalScrollerWidth, verticalScrollerHeight)];
00213 }
00214 else if (wasShowingVerticalScroller)
00215 [_verticalScroller setFloatValue:0.0 knobProportion:1.0];
00216
00217 if (shouldShowHorizontalScroller)
00218 {
00219 difference.height += horizontalScrollerHeight;
00220 contentViewFrame.size.height -= horizontalScrollerHeight;
00221
00222 [_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width
00223 knobProportion:CPRectGetWidth(contentViewFrame) / CPRectGetWidth(documentFrame)];
00224 [_horizontalScroller setFrame:CPRectMake(0.0, CPRectGetMaxY(contentViewFrame), CPRectGetWidth(contentViewFrame), horizontalScrollerHeight)];
00225 }
00226 else if (wasShowingHorizontalScroller)
00227 [_horizontalScroller setFloatValue:0.0 knobProportion:1.0];
00228
00229 [_contentView setFrame:contentViewFrame];
00230
00231 --_recursionCount;
00232 }
00233
00234
00239 - (void)setHorizontalScroller:(CPScroller)aScroller
00240 {
00241 if (_horizontalScroller == aScroller)
00242 return;
00243
00244 [_horizontalScroller removeFromSuperview];
00245 [_horizontalScroller setTarget:nil];
00246 [_horizontalScroller setAction:nil];
00247
00248 _horizontalScroller = aScroller;
00249
00250 [_horizontalScroller setTarget:self];
00251 [_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)];
00252
00253 [self addSubview:_horizontalScroller];
00254
00255 [self reflectScrolledClipView:_contentView];
00256 }
00257
00261 - (CPScroller)horizontalScroller
00262 {
00263 return _horizontalScroller;
00264 }
00265
00271 - (void)setHasHorizontalScroller:(BOOL)shouldHaveHorizontalScroller
00272 {
00273 if (_hasHorizontalScroller == shouldHaveHorizontalScroller)
00274 return;
00275
00276 _hasHorizontalScroller = shouldHaveHorizontalScroller;
00277
00278 if (_hasHorizontalScroller && !_horizontalScroller)
00279 [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CPRectMake(0.0, 0.0, CPRectGetWidth([self bounds]), [CPScroller scrollerWidth])]];
00280
00281 else if (!_hasHorizontalScroller && _horizontalScroller)
00282 {
00283 [_horizontalScroller setHidden:YES];
00284
00285 [self reflectScrolledClipView:_contentView];
00286 }
00287 }
00288
00292 - (BOOL)hasHorizontalScroller
00293 {
00294 return _hasHorizontalScroller;
00295 }
00296
00301 - (void)setVerticalScroller:(CPScroller)aScroller
00302 {
00303 if (_verticalScroller == aScroller)
00304 return;
00305
00306 [_verticalScroller removeFromSuperview];
00307 [_verticalScroller setTarget:nil];
00308 [_verticalScroller setAction:nil];
00309
00310 _verticalScroller = aScroller;
00311
00312 [_verticalScroller setTarget:self];
00313 [_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)];
00314
00315 [self addSubview:_verticalScroller];
00316
00317 [self reflectScrolledClipView:_contentView];
00318 }
00319
00323 - (CPScroller)verticalScroller
00324 {
00325 return _verticalScroller;
00326 }
00327
00334 - (void)setHasVerticalScroller:(BOOL)shouldHaveVerticalScroller
00335 {
00336 if (_hasVerticalScroller == shouldHaveVerticalScroller)
00337 return;
00338
00339 _hasVerticalScroller = shouldHaveVerticalScroller;
00340
00341 if (_hasVerticalScroller && !_verticalScroller)
00342 [self setVerticalScroller:[[CPScroller alloc] initWithFrame:CPRectMake(0.0, 0.0, [CPScroller scrollerWidth], CPRectGetHeight([self bounds]))]];
00343
00344 else if (!_hasVerticalScroller && _verticalScroller)
00345 {
00346 [_verticalScroller setHidden:YES];
00347
00348 [self reflectScrolledClipView:_contentView];
00349 }
00350 }
00351
00355 - (BOOL)hasHorizontalScroller
00356 {
00357 return _hasHorizontalScroller;
00358 }
00359
00365 - (void)setAutohidesScrollers:(BOOL)autohidesScrollers
00366 {
00367 if (_autohidesScrollers == autohidesScrollers)
00368 return;
00369
00370 _autohidesScrollers = autohidesScrollers;
00371
00372 [self reflectScrolledClipView:_contentView];
00373 }
00374
00379 - (BOOL)autohidesScrollers
00380 {
00381 return _autohidesScrollers;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 - (void)_verticalScrollerDidScroll:(CPScroller)aScroller
00393 {
00394 var value = [aScroller floatValue],
00395 documentFrame = [[_contentView documentView] frame];
00396 contentBounds = [_contentView bounds];
00397
00398 switch ([_verticalScroller hitPart])
00399 {
00400 case CPScrollerDecrementLine: contentBounds.origin.y -= _verticalLineScroll;
00401 break;
00402
00403 case CPScrollerIncrementLine: contentBounds.origin.y += _verticalLineScroll;
00404 break;
00405
00406 case CPScrollerDecrementPage: contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
00407 break;
00408
00409 case CPScrollerIncrementPage: contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
00410 break;
00411
00412 case CPScrollerKnobSlot:
00413 case CPScrollerKnob:
00414 default: contentBounds.origin.y = value * (_CGRectGetHeight(documentFrame) - _CGRectGetHeight(contentBounds));
00415 }
00416
00417 [_contentView scrollToPoint:contentBounds.origin];
00418 }
00419
00420
00421 - (void)_horizontalScrollerDidScroll:(CPScroller)aScroller
00422 {
00423 var value = [aScroller floatValue],
00424 documentFrame = [[self documentView] frame],
00425 contentBounds = [_contentView bounds];
00426
00427 switch ([_horizontalScroller hitPart])
00428 {
00429 case CPScrollerDecrementLine: contentBounds.origin.x -= _horizontalLineScroll;
00430 break;
00431
00432 case CPScrollerIncrementLine: contentBounds.origin.x += _horizontalLineScroll;
00433 break;
00434
00435 case CPScrollerDecrementPage: contentBounds.origin.x -= _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
00436 break;
00437
00438 case CPScrollerIncrementPage: contentBounds.origin.x += _CGRectGetWidth(contentBounds) - _horizontalPageScroll;
00439 break;
00440
00441 case CPScrollerKnobSlot:
00442 case CPScrollerKnob:
00443 default: contentBounds.origin.x = value * (_CGRectGetWidth(documentFrame) - _CGRectGetWidth(contentBounds));
00444 }
00445
00446 [_contentView scrollToPoint:contentBounds.origin];
00447 }
00448
00452 - (void)tile
00453 {
00454
00455
00456
00457
00458 }
00459
00460
00461
00462
00463 -(void)resizeSubviewsWithOldSize:(CGSize)aSize
00464 {
00465 [self reflectScrolledClipView:_contentView];
00466 }
00467
00468
00473 - (void)setLineScroll:(float)aLineScroll
00474 {
00475 [self setHorizonalLineScroll:aLineScroll];
00476 [self setVerticalLineScroll:aLineScroll];
00477 }
00478
00482 - (float)lineScroll
00483 {
00484 return [self horizontalLineScroll];
00485 }
00486
00491 - (void)setHorizontalLineScroll:(float)aLineScroll
00492 {
00493 _horizontalLineScroll = aLineScroll;
00494 }
00495
00499 - (float)horizontalLineScroll
00500 {
00501 return _horizontalLineScroll;
00502 }
00503
00508 - (void)setVerticalLineScroll:(float)aLineScroll
00509 {
00510 _verticalLineScroll = aLineScroll;
00511 }
00512
00516 - (float)verticalLineScroll
00517 {
00518 return _verticalLineScroll;
00519 }
00520
00525 - (void)setPageScroll:(float)aPageScroll
00526 {
00527 [self setHorizontalPageScroll:aPageScroll];
00528 [self setVerticalPageScroll:aPageScroll];
00529 }
00530
00534 - (float)pageScroll
00535 {
00536 return [self horizontalPageScroll];
00537 }
00538
00543 - (void)setHorizontalPageScroll:(float)aPageScroll
00544 {
00545 _horizontalPageScroll = aPageScroll;
00546 }
00547
00551 - (float)horizontalPageScroll
00552 {
00553 return _horizontalPageScroll;
00554 }
00555
00560 - (void)setVerticalPageScroll:(float)aPageScroll
00561 {
00562 _verticalPageScroll = aPageScroll;
00563 }
00564
00568 - (float)verticalPageScroll
00569 {
00570 return _verticalPageScroll;
00571 }
00572
00577 - (void)scrollWheel:(CPEvent)anEvent
00578 {
00579 var value = [_verticalScroller floatValue],
00580 documentFrame = [[self documentView] frame],
00581 contentBounds = [_contentView bounds];
00582
00583 contentBounds.origin.x += [anEvent deltaX] * _horizontalLineScroll;
00584 contentBounds.origin.y += [anEvent deltaY] * _verticalLineScroll;
00585
00586 [_contentView scrollToPoint:contentBounds.origin];
00587 }
00588
00589 - (void)keyDown:(CPEvent)anEvent
00590 {
00591 var keyCode = [anEvent keyCode],
00592 value = [_verticalScroller floatValue],
00593 documentFrame = [[self documentView] frame],
00594 contentBounds = [_contentView bounds];
00595
00596 switch (keyCode)
00597 {
00598 case 33:
00599 contentBounds.origin.y -= _CGRectGetHeight(contentBounds) - _verticalPageScroll;
00600 break;
00601
00602 case 34:
00603 contentBounds.origin.y += _CGRectGetHeight(contentBounds) - _verticalPageScroll;
00604 break;
00605
00606 case 38:
00607 contentBounds.origin.y -= _verticalLineScroll;
00608 break;
00609
00610 case 40:
00611 contentBounds.origin.y += _verticalLineScroll;
00612 break;
00613
00614 case 37:
00615 contentBounds.origin.x -= _horizontalLineScroll;
00616 break;
00617
00618 case 49:
00619 contentBounds.origin.x += _horizontalLineScroll;
00620 break;
00621
00622 default: return [super keyDown:anEvent];
00623 }
00624
00625 [_contentView scrollToPoint:contentBounds.origin];
00626 }
00627
00628 @end