API  0.9.10
CPScrollView.j
Go to the documentation of this file.
1 /*
2  * CPScrollView.j
3  * AppKit
4  *
5  * Created by Francisco Tolmasky.
6  * Copyright 2008, 280 North, Inc.
7  *
8  * Modified to match Lion style by Antoine Mercadal 2011
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24  */
25 
26 
27 
28 #define SHOULD_SHOW_CORNER_VIEW() (_scrollerStyle === CPScrollerStyleLegacy && _verticalScroller && ![_verticalScroller isHidden])
29 
30 
31 @protocol CPScrollViewDelegate <CPObject>
32 
33 @optional
34 - (void)scrollViewWillScroll:(CPScrollView)aScrollView;
35 - (void)scrollViewDidScroll:(CPScrollView)aScrollView;
36 
37 @end
38 
39 
41 var _isBrowserUsingOverlayScrollers = function()
42 {
43 #if PLATFORM(DOM)
44  /*
45  Even if the system supports overlay (Lion) scrollers,
46  the browser (e.g. FireFox *cough*) may not.
47 
48  To determine if the browser is using overlay scrollbars,
49  we put a <p> element inside a shorter <div> and set its
50  overflow to scroll. If the browser is using visible scrollers,
51  the outer div's clientWidth will less than the offsetWidth, because
52  clientWidth does not include scrollbars, whereas offsetWidth does.
53  So if clientWidth === offsetWidth, the scrollers must be overlay.
54  Even IE gets this right.
55  */
56  var outer = document.createElement('div'),
57  inner = document.createElement('p');
58 
59  // position it absolute so it doesn't affect existing DOM elements
60  outer.style.position = "absolute";
61  outer.style.top = "0px";
62  outer.style.left = "0px";
63  outer.style.visibility = "hidden";
64  outer.style.width = "200px";
65  outer.style.height = "150px";
66  outer.style.overflow = "scroll";
67 
68  inner.style.width = "100%";
69  inner.style.height = "200px";
70  outer.appendChild(inner);
71 
72  document.body.appendChild(outer);
73 
74  var usingOverlayScrollers = outer.clientWidth === outer.offsetWidth;
75 
76  document.body.removeChild(outer);
77 
78  return usingOverlayScrollers;
79 #else
80  return NO;
81 #endif
82 };
83 
84 var TIMER_INTERVAL = 0.2,
87 
89 
91  CPScrollerStyleGlobalChangeNotification = @"CPScrollerStyleGlobalChangeNotification";
92 
100 @implementation CPScrollView : CPView
101 {
102  CPClipView _contentView;
103  CPClipView _headerClipView;
104  CPView _cornerView;
105  CPView _bottomCornerView;
106 
107  id <CPScrollViewDelegate> _delegate;
108  CPTimer _scrollTimer;
109 
110  BOOL _hasVerticalScroller;
111  BOOL _hasHorizontalScroller;
112  BOOL _autohidesScrollers;
113 
114  CPScroller _verticalScroller;
115  CPScroller _horizontalScroller;
116 
117  CPInteger _recursionCount;
118  CPInteger _implementedDelegateMethods;
119 
120  float _verticalLineScroll;
121  float _verticalPageScroll;
122  float _horizontalLineScroll;
123  float _horizontalPageScroll;
124 
125  CPBorderType _borderType;
126 
127  CPTimer _timerScrollersHide;
128 
129  int _scrollerStyle;
130  int _scrollerKnobStyle;
131 }
132 
133 
134 #pragma mark -
135 #pragma mark Class methods
136 
137 + (void)initialize
138 {
139  if (self !== [CPScrollView class])
140  return;
141 
142  var globalValue = [[CPBundle mainBundle] objectForInfoDictionaryKey:@"CPScrollersGlobalStyle"];
143 
144  if (globalValue === nil || globalValue === -1)
145  CPScrollerStyleGlobal = _isBrowserUsingOverlayScrollers() ? CPScrollerStyleOverlay : CPScrollerStyleLegacy
146  else
147  CPScrollerStyleGlobal = globalValue;
148 }
149 
151 {
152  return @"scrollview"
153 }
154 
156 {
157  return @{
158  @"bottom-corner-color": [CPColor whiteColor],
159  @"border-color": [CPColor blackColor]
160  };
161 }
162 
163 + (CGSize)contentSizeForFrameSize:(CGSize)frameSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
164 {
165  var bounds = [self _insetBounds:CGRectMake(0.0, 0.0, frameSize.width, frameSize.height) borderType:borderType],
166  scrollerWidth = [CPScroller scrollerWidth];
167 
168  if (hFlag)
169  bounds.size.height -= scrollerWidth;
170 
171  if (vFlag)
172  bounds.size.width -= scrollerWidth;
173 
174  return bounds.size;
175 }
176 
177 + (CGSize)frameSizeForContentSize:(CGSize)contentSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(CPBorderType)borderType
178 {
179  var bounds = [self _insetBounds:CGRectMake(0.0, 0.0, contentSize.width, contentSize.height) borderType:borderType],
180  widthInset = contentSize.width - bounds.size.width,
181  heightInset = contentSize.height - bounds.size.height,
182  frameSize = CGSizeMake(contentSize.width + widthInset, contentSize.height + heightInset),
183  scrollerWidth = [CPScroller scrollerWidth];
184 
185  if (hFlag)
186  frameSize.height += scrollerWidth;
187 
188  if (vFlag)
189  frameSize.width += scrollerWidth;
190 
191  return frameSize;
192 }
193 
194 + (CGRect)_insetBounds:(CGRect)bounds borderType:(CPBorderType)borderType
195 {
196  switch (borderType)
197  {
198  case CPLineBorder:
199  case CPBezelBorder:
200  return CGRectInset(bounds, 1.0, 1.0);
201 
202  case CPGrooveBorder:
203  bounds = CGRectInset(bounds, 2.0, 2.0);
204  ++bounds.origin.y;
205  --bounds.size.height;
206  return bounds;
207 
208  case CPNoBorder:
209  default:
210  return bounds;
211  }
212 }
213 
218 {
219  return CPScrollerStyleGlobal;
220 }
221 
227 + (void)setGlobalScrollerStyle:(int)aStyle
228 {
229  CPScrollerStyleGlobal = aStyle;
230  [[CPNotificationCenter defaultCenter] postNotificationName:CPScrollerStyleGlobalChangeNotification object:nil];
231 }
232 
233 
234 #pragma mark -
235 #pragma mark Initialization
236 
237 - (id)initWithFrame:(CGRect)aFrame
238 {
239  self = [super initWithFrame:aFrame];
240 
241  if (self)
242  {
243  _verticalLineScroll = 10.0;
244  _verticalPageScroll = 10.0;
245 
246  _horizontalLineScroll = 10.0;
247  _horizontalPageScroll = 10.0;
248 
249  _borderType = CPNoBorder;
250 
251  _contentView = [[CPClipView alloc] initWithFrame:[self _insetBounds]];
252  [self addSubview:_contentView];
253 
254  _headerClipView = [[CPClipView alloc] init];
255  [self addSubview:_headerClipView];
256 
257  _bottomCornerView = [[CPView alloc] init];
258  [self addSubview:_bottomCornerView];
259 
260  [self setHasVerticalScroller:YES];
261  [self setHasHorizontalScroller:YES];
262  _scrollerKnobStyle = CPScrollerKnobStyleDefault;
263  [self setScrollerStyle:CPScrollerStyleGlobal];
264 
265  _delegate = nil;
266  _scrollTimer = nil;
267  _implementedDelegateMethods = 0;
268  }
269 
270  return self;
271 }
272 
273 
274 #pragma mark -
275 #pragma mark Getters / Setters
276 
280 - (id)delegate
281 {
282  return _delegate;
283 }
284 
300 - (void)setDelegate:(id <CPScrollViewDelegate>)aDelegate
301 {
302  if (aDelegate === _delegate)
303  return;
304 
305  _delegate = aDelegate;
306  _implementedDelegateMethods = 0;
307 
308  if (_delegate === nil)
309  return;
310 
311  if ([_delegate respondsToSelector:@selector(scrollViewWillScroll:)])
312  _implementedDelegateMethods |= CPScrollViewDelegate_scrollViewWillScroll_;
313 
314  if ([_delegate respondsToSelector:@selector(scrollViewDidScroll:)])
315  _implementedDelegateMethods |= CPScrollViewDelegate_scrollViewDidScroll_;
316 }
317 
319 {
320  return _scrollerStyle;
321 }
322 
329 - (void)setScrollerStyle:(int)aStyle
330 {
331  if (_scrollerStyle === aStyle)
332  return;
333 
334  _scrollerStyle = aStyle;
335 
336  [self _updateScrollerStyle];
337 }
338 
350 {
351  return _scrollerKnobStyle;
352 }
353 
364 - (void)setScrollerKnobStyle:(int)newScrollerKnobStyle
365 {
366  if (_scrollerKnobStyle === newScrollerKnobStyle)
367  return;
368 
369  _scrollerKnobStyle = newScrollerKnobStyle;
370 
371  [self _updateScrollerStyle];
372 }
373 
378 {
379  return _contentView;
380 }
381 
387 - (void)setContentView:(CPClipView)aContentView
388 {
389  if (_contentView === aContentView || !aContentView)
390  return;
391 
392  var documentView = [aContentView documentView];
393 
394  if (documentView)
395  [documentView removeFromSuperview];
396 
397  [_contentView removeFromSuperview];
398 
399  _contentView = aContentView;
400 
401  [_contentView setDocumentView:documentView];
402 
403  [self addSubview:_contentView];
404 
405  // This will size the content view appropriately, so no need to size it in this method.
406  [self reflectScrolledClipView:_contentView];
407 }
408 
412 - (CGSize)contentSize
413 {
414  return [_contentView frame].size;
415 }
416 
421 {
422  return [_contentView documentView];
423 }
424 
430 - (void)setDocumentView:(CPView)aView
431 {
432  [_contentView setDocumentView:aView];
433 
434  // FIXME: This should be observed.
435  [self _updateCornerAndHeaderView];
436  [self reflectScrolledClipView:_contentView];
437 }
438 
442 - (CPBorderType)borderType
443 {
444  return _borderType;
445 }
446 
457 - (void)setBorderType:(CPBorderType)borderType
458 {
459  if (_borderType == borderType)
460  return;
461 
462  _borderType = borderType;
463 
464  [self reflectScrolledClipView:_contentView];
465  [self setNeedsDisplay:YES];
466 }
467 
468 
473 {
474  return _horizontalScroller;
475 }
476 
482 - (void)setHorizontalScroller:(CPScroller)aScroller
483 {
484  if (_horizontalScroller === aScroller)
485  return;
486 
487  [_horizontalScroller removeFromSuperview];
488  [_horizontalScroller setTarget:nil];
489  [_horizontalScroller setAction:nil];
490 
491  _horizontalScroller = aScroller;
492 
493  [_horizontalScroller setTarget:self];
494  [_horizontalScroller setAction:@selector(_horizontalScrollerDidScroll:)];
495 
496  [self addSubview:_horizontalScroller];
497 
498  [self _updateScrollerStyle];
499 }
500 
505 {
506  return _hasHorizontalScroller;
507 }
508 
515 - (void)setHasHorizontalScroller:(BOOL)shouldHaveHorizontalScroller
516 {
517  if (_hasHorizontalScroller === shouldHaveHorizontalScroller)
518  return;
519 
520  _hasHorizontalScroller = shouldHaveHorizontalScroller;
521 
522  if (_hasHorizontalScroller && !_horizontalScroller)
523  {
524  var bounds = [self _insetBounds];
525 
526  [self setHorizontalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, MAX(CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1), [CPScroller scrollerWidthInStyle:_scrollerStyle])]];
527  [[self horizontalScroller] setFrameSize:CGSizeMake(CGRectGetWidth(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle])];
528  }
529 
530  [self reflectScrolledClipView:_contentView];
531 }
532 
537 {
538  return _verticalScroller;
539 }
540 
546 - (void)setVerticalScroller:(CPScroller)aScroller
547 {
548  if (_verticalScroller === aScroller)
549  return;
550 
551  [_verticalScroller removeFromSuperview];
552  [_verticalScroller setTarget:nil];
553  [_verticalScroller setAction:nil];
554 
555  _verticalScroller = aScroller;
556 
557  [_verticalScroller setTarget:self];
558  [_verticalScroller setAction:@selector(_verticalScrollerDidScroll:)];
559 
560  [self addSubview:_verticalScroller];
561 
562  [self _updateScrollerStyle];
563 }
564 
569 {
570  return _hasVerticalScroller;
571 }
572 
580 - (void)setHasVerticalScroller:(BOOL)shouldHaveVerticalScroller
581 {
582  if (_hasVerticalScroller === shouldHaveVerticalScroller)
583  return;
584 
585  _hasVerticalScroller = shouldHaveVerticalScroller;
586 
587  if (_hasVerticalScroller && !_verticalScroller)
588  {
589  var bounds = [self _insetBounds];
590 
591  [self setVerticalScroller:[[CPScroller alloc] initWithFrame:CGRectMake(0.0, 0.0, [CPScroller scrollerWidthInStyle:_scrollerStyle], MAX(CGRectGetHeight(bounds), [CPScroller scrollerWidthInStyle:_scrollerStyle] + 1))]];
592  [[self verticalScroller] setFrameSize:CGSizeMake([CPScroller scrollerWidthInStyle:_scrollerStyle], CGRectGetHeight(bounds))];
593  }
594 
595  [self reflectScrolledClipView:_contentView];
596 }
597 
602 {
603  return _autohidesScrollers;
604 }
605 
612 - (void)setAutohidesScrollers:(BOOL)autohidesScrollers
613 {
614  if (_autohidesScrollers == autohidesScrollers)
615  return;
616 
617  _autohidesScrollers = autohidesScrollers;
618 
619  [self reflectScrolledClipView:_contentView];
620 }
621 
623 {
624  return _bottomCornerView;
625 }
626 
627 - (void)setBottomCornerView:(CPView)aBottomCornerView
628 {
629  if (_bottomCornerView === aBottomCornerView)
630  return;
631 
632  [_bottomCornerView removeFromSuperview];
633 
634  [aBottomCornerView setFrame:[self _bottomCornerViewFrame]];
635  [self addSubview:aBottomCornerView];
636 
637  _bottomCornerView = aBottomCornerView;
638 
639  [self _updateCornerAndHeaderView];
640 }
641 
645 - (float)lineScroll
646 {
647  return [self horizontalLineScroll];
648 }
649 
655 - (void)setLineScroll:(float)aLineScroll
656 {
657  [self setHorizontalLineScroll:aLineScroll];
658  [self setVerticalLineScroll:aLineScroll];
659 }
660 
665 {
666  return _horizontalLineScroll;
667 }
668 
674 - (void)setHorizontalLineScroll:(float)aLineScroll
675 {
676  _horizontalLineScroll = aLineScroll;
677 }
678 
683 {
684  return _verticalLineScroll;
685 }
686 
692 - (void)setVerticalLineScroll:(float)aLineScroll
693 {
694  _verticalLineScroll = aLineScroll;
695 }
696 
700 - (float)pageScroll
701 {
702  return [self horizontalPageScroll];
703 }
704 
710 - (void)setPageScroll:(float)aPageScroll
711 {
712  [self setHorizontalPageScroll:aPageScroll];
713  [self setVerticalPageScroll:aPageScroll];
714 }
715 
720 {
721  return _horizontalPageScroll;
722 }
723 
729 - (void)setHorizontalPageScroll:(float)aPageScroll
730 {
731  _horizontalPageScroll = aPageScroll;
732 }
733 
738 {
739  return _verticalPageScroll;
740 }
741 
747 - (void)setVerticalPageScroll:(float)aPageScroll
748 {
749  _verticalPageScroll = aPageScroll;
750 }
751 
752 
753 #pragma mark -
754 #pragma mark Privates
755 
756 /* @ignore */
757 - (void)_updateScrollerStyle
758 {
759  if (_hasHorizontalScroller)
760  {
761  [_horizontalScroller setStyle:_scrollerStyle];
762  [_horizontalScroller unsetThemeState:CPThemeStateSelected];
763 
764  switch (_scrollerKnobStyle)
765  {
767  [_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
768  [_horizontalScroller setThemeState:CPThemeStateScrollerKnobLight];
769  break;
770 
772  [_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
773  [_horizontalScroller setThemeState:CPThemeStateScrollerKnobDark];
774  break;
775 
776  default:
777  [_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
778  [_horizontalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
779  }
780  }
781 
782  if (_hasVerticalScroller)
783  {
784  [_verticalScroller setStyle:_scrollerStyle];
785  [_verticalScroller unsetThemeState:CPThemeStateSelected];
786 
787  switch (_scrollerKnobStyle)
788  {
790  [_verticalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
791  [_verticalScroller setThemeState:CPThemeStateScrollerKnobLight];
792  break;
793 
795  [_verticalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
796  [_verticalScroller setThemeState:CPThemeStateScrollerKnobDark];
797  break;
798 
799  default:
800  [_verticalScroller unsetThemeState:CPThemeStateScrollerKnobLight];
801  [_verticalScroller unsetThemeState:CPThemeStateScrollerKnobDark];
802  }
803  }
804 
805  if (_scrollerStyle == CPScrollerStyleOverlay)
806  {
807  if (_timerScrollersHide)
808  [_timerScrollersHide invalidate];
809 
810  _timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
811  [[self bottomCornerView] setHidden:YES];
812  }
813  else
814  [[self bottomCornerView] setHidden:NO];
815 
816  [self reflectScrolledClipView:_contentView];
817 }
818 
819 /* @ignore */
820 - (CGRect)_insetBounds
821 {
822  return [[self class] _insetBounds:[self bounds] borderType:_borderType];
823 }
824 
825 /* @ignore */
826 - (void)_updateCornerAndHeaderView
827 {
828  var documentView = [self documentView],
829  currentHeaderView = [self _headerView],
830  documentHeaderView = [documentView respondsToSelector:@selector(headerView)] ? [documentView headerView] : nil;
831 
832  if (currentHeaderView !== documentHeaderView)
833  {
834  [currentHeaderView removeFromSuperview];
835  [_headerClipView setDocumentView:documentHeaderView];
836  }
837 
838  var documentCornerView = [documentView respondsToSelector:@selector(cornerView)] ? [documentView cornerView] : nil;
839 
840  if (_cornerView !== documentCornerView)
841  {
842  [_cornerView removeFromSuperview];
843 
844  _cornerView = documentCornerView;
845 
846  if (_cornerView)
847  {
848  [_cornerView setHidden:!SHOULD_SHOW_CORNER_VIEW()];
849  [self addSubview:_cornerView];
850  }
851  }
852 
853  [self reflectScrolledClipView:_contentView];
854  [documentHeaderView setNeedsLayout];
855  [documentHeaderView setNeedsDisplay:YES];
856 }
857 
858 /* @ignore */
859 - (CPView)_headerView
860 {
861  return [_headerClipView documentView];
862 }
863 
864 /* @ignore */
865 - (CGRect)_cornerViewFrame
866 {
867  if (!_cornerView)
868  return CGRectMakeZero();
869 
870  var bounds = [self _insetBounds],
871  frame = [_cornerView frame];
872 
873  frame.origin.x = CGRectGetMaxX(bounds) - CGRectGetWidth(frame);
874  frame.origin.y = CGRectGetMinY(bounds);
875 
876  return frame;
877 }
878 
879 /* @ignore */
880 - (CGRect)_headerClipViewFrame
881 {
882  var headerView = [self _headerView];
883 
884  if (!headerView)
885  return CGRectMakeZero();
886 
887  var frame = [self _insetBounds];
888 
889  frame.size.height = CGRectGetHeight([headerView frame]);
890 
892  frame.size.width -= CGRectGetWidth([self _cornerViewFrame]);
893 
894  return frame;
895 }
896 
897 /* @ignore */
898 - (CGRect)_bottomCornerViewFrame
899 {
900  if ([[self horizontalScroller] isHidden] || [[self verticalScroller] isHidden])
901  return CGRectMakeZero();
902 
903  var verticalFrame = [[self verticalScroller] frame],
904  bottomCornerFrame = CGRectMakeZero();
905 
906  bottomCornerFrame.origin.x = CGRectGetMinX(verticalFrame);
907  bottomCornerFrame.origin.y = CGRectGetMaxY(verticalFrame);
908  bottomCornerFrame.size.width = [CPScroller scrollerWidthInStyle:_scrollerStyle];
909  bottomCornerFrame.size.height = [CPScroller scrollerWidthInStyle:_scrollerStyle];
910 
911  return bottomCornerFrame;
912 }
913 
914 /* @ignore */
915 - (void)_verticalScrollerDidScroll:(CPScroller)aScroller
916 {
917  var value = [aScroller floatValue],
918  documentFrame = [[_contentView documentView] frame],
919  contentBounds = [_contentView bounds];
920 
921 
922  switch ([_verticalScroller hitPart])
923  {
925  contentBounds.origin.y -= _verticalLineScroll;
926  break;
927 
929  contentBounds.origin.y += _verticalLineScroll;
930  break;
931 
933  contentBounds.origin.y -= CGRectGetHeight(contentBounds) - _verticalPageScroll;
934  break;
935 
937  contentBounds.origin.y += CGRectGetHeight(contentBounds) - _verticalPageScroll;
938  break;
939 
940  // We want integral bounds!
941  case CPScrollerKnobSlot:
942  case CPScrollerKnob:
943  default:
944  contentBounds.origin.y = ROUND(value * (CGRectGetHeight(documentFrame) - CGRectGetHeight(contentBounds)));
945  }
946 
947  [self _sendDelegateMessages];
948 
949  [_contentView scrollToPoint:contentBounds.origin];
950 }
951 
952 /* @ignore */
953 - (void)_horizontalScrollerDidScroll:(CPScroller)aScroller
954 {
955  var value = [aScroller floatValue],
956  documentFrame = [[self documentView] frame],
957  contentBounds = [_contentView bounds];
958 
959  switch ([_horizontalScroller hitPart])
960  {
962  contentBounds.origin.x -= _horizontalLineScroll;
963  break;
964 
966  contentBounds.origin.x += _horizontalLineScroll;
967  break;
968 
970  contentBounds.origin.x -= CGRectGetWidth(contentBounds) - _horizontalPageScroll;
971  break;
972 
974  contentBounds.origin.x += CGRectGetWidth(contentBounds) - _horizontalPageScroll;
975  break;
976 
977  // We want integral bounds!
978  case CPScrollerKnobSlot:
979  case CPScrollerKnob:
980  default:
981  contentBounds.origin.x = ROUND(value * (CGRectGetWidth(documentFrame) - CGRectGetWidth(contentBounds)));
982  }
983 
984  [self _sendDelegateMessages];
985 
986  [_contentView scrollToPoint:contentBounds.origin];
987  [_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0.0)];
988 }
989 
990 /* @ignore */
991 - (void)_sendDelegateMessages
992 {
993  if (_implementedDelegateMethods == 0)
994  return;
995 
996  if (!_scrollTimer)
997  {
998  [self _scrollViewWillScroll];
999  _scrollTimer = [CPTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(_scrollViewDidScroll) userInfo:nil repeats:YES];
1000  }
1001  else
1002  [_scrollTimer setFireDate:[CPDate dateWithTimeIntervalSinceNow:TIMER_INTERVAL]];
1003 }
1004 
1005 /* @ignore */
1006 - (void)_hideScrollers:(CPTimer)theTimer
1007 {
1008  if ([_verticalScroller allowFadingOut])
1009  [_verticalScroller fadeOut];
1010  if ([_horizontalScroller allowFadingOut])
1011  [_horizontalScroller fadeOut];
1012  _timerScrollersHide = nil;
1013 }
1014 
1015 /* @ignore */
1016 - (void)_respondToScrollWheelEventWithDeltaX:(float)deltaX deltaY:(float)deltaY
1017 {
1018  var documentFrame = [[self documentView] frame],
1019  contentBounds = [_contentView bounds],
1020  contentFrame = [_contentView frame],
1022 
1023  // We want integral bounds!
1024  contentBounds.origin.x = ROUND(contentBounds.origin.x + deltaX);
1025  contentBounds.origin.y = ROUND(contentBounds.origin.y + deltaY);
1026 
1027  var constrainedOrigin = [_contentView constrainScrollPoint:CGPointCreateCopy(contentBounds.origin)],
1028  extraX = contentBounds.origin.x - constrainedOrigin.x,
1029  extraY = contentBounds.origin.y - constrainedOrigin.y;
1030 
1031  [self _sendDelegateMessages];
1032 
1033  [_contentView scrollToPoint:constrainedOrigin];
1034  [_headerClipView scrollToPoint:CGPointMake(constrainedOrigin.x, 0.0)];
1035 
1036  if (extraX || extraY)
1037  [enclosingScrollView _respondToScrollWheelEventWithDeltaX:extraX deltaY:extraY];
1038 }
1039 
1040 /* @ignore */
1041 - (void)_scrollViewWillScroll
1042 {
1043  if (_implementedDelegateMethods & CPScrollViewDelegate_scrollViewWillScroll_)
1044  [_delegate scrollViewWillScroll:self];
1045 }
1046 
1047 /* @ignore */
1048 - (void)_scrollViewDidScroll
1049 {
1050  [_scrollTimer invalidate];
1051  _scrollTimer = nil;
1052 
1053  if (_implementedDelegateMethods & CPScrollViewDelegate_scrollViewDidScroll_)
1054  [_delegate scrollViewDidScroll:self];
1055 }
1056 
1058 - (void)_didReceiveDefaultStyleChange:(CPNotification)aNotification
1059 {
1060  [self setScrollerStyle:CPScrollerStyleGlobal];
1061 }
1062 
1063 
1064 
1065 #pragma mark -
1066 #pragma mark Utilities
1067 
1071 - (void)tile
1072 {
1073  // yuck.
1074  // RESIZE: tile->setHidden AND refl
1075  // Outside Change: refl->tile->setHidden AND refl
1076  // scroll: refl.
1077 }
1078 
1084 - (void)reflectScrolledClipView:(CPClipView)aClipView
1085 {
1086  if (_contentView !== aClipView)
1087  return;
1088 
1089  if (_recursionCount > 5)
1090  return;
1091 
1092  ++_recursionCount;
1093 
1094  var documentView = [self documentView];
1095 
1096  if (!documentView)
1097  {
1098  if (_autohidesScrollers)
1099  {
1100  [_verticalScroller setHidden:YES];
1101  [_horizontalScroller setHidden:YES];
1102  }
1103 
1104  [_contentView setFrame:[self _insetBounds]];
1105  [_headerClipView setFrame:CGRectMakeZero()];
1106 
1107  --_recursionCount;
1108 
1109  return;
1110  }
1111 
1112  var documentFrame = [documentView frame], // the size of the whole document
1113  contentFrame = [self _insetBounds], // assume it takes up the entire size of the scrollview (no scrollers)
1114  headerClipViewFrame = [self _headerClipViewFrame],
1115  headerClipViewHeight = CGRectGetHeight(headerClipViewFrame);
1116 
1117  contentFrame.origin.y += headerClipViewHeight;
1118  contentFrame.size.height -= headerClipViewHeight;
1119 
1120  var difference = CGSizeMake(CGRectGetWidth(documentFrame) - CGRectGetWidth(contentFrame), CGRectGetHeight(documentFrame) - CGRectGetHeight(contentFrame)),
1121  verticalScrollerWidth = [CPScroller scrollerWidthInStyle:[_verticalScroller style]],
1122  horizontalScrollerHeight = [CPScroller scrollerWidthInStyle:[_horizontalScroller style]],
1123  hasVerticalScroll = difference.height > 0.0,
1124  hasHorizontalScroll = difference.width > 0.0,
1125  shouldShowVerticalScroller = _hasVerticalScroller && (!_autohidesScrollers || hasVerticalScroll),
1126  shouldShowHorizontalScroller = _hasHorizontalScroller && (!_autohidesScrollers || hasHorizontalScroll);
1127 
1128  // Now we have to account for the shown scrollers affecting the deltas.
1129  if (shouldShowVerticalScroller)
1130  {
1131  if (_scrollerStyle === CPScrollerStyleLegacy)
1132  difference.width += verticalScrollerWidth;
1133  hasHorizontalScroll = difference.width > 0.0;
1134  shouldShowHorizontalScroller = _hasHorizontalScroller && (!_autohidesScrollers || hasHorizontalScroll);
1135  }
1136 
1137  if (shouldShowHorizontalScroller)
1138  {
1139  if (_scrollerStyle === CPScrollerStyleLegacy)
1140  difference.height += horizontalScrollerHeight;
1141  hasVerticalScroll = difference.height > 0.0;
1142  shouldShowVerticalScroller = _hasVerticalScroller && (!_autohidesScrollers || hasVerticalScroll);
1143  }
1144 
1145  // We now definitively know which scrollers are shown or not, as well as whether they are showing scroll values.
1146  [_verticalScroller setHidden:!shouldShowVerticalScroller];
1147  [_verticalScroller setEnabled:hasVerticalScroll];
1148 
1149  [_horizontalScroller setHidden:!shouldShowHorizontalScroller];
1150  [_horizontalScroller setEnabled:hasHorizontalScroll];
1151 
1152  var overlay = [CPScroller scrollerOverlay];
1153  if (_scrollerStyle === CPScrollerStyleLegacy)
1154  {
1155  // We can thus appropriately account for them changing the content size.
1156  if (shouldShowVerticalScroller)
1157  contentFrame.size.width -= verticalScrollerWidth;
1158 
1159  if (shouldShowHorizontalScroller)
1160  contentFrame.size.height -= horizontalScrollerHeight;
1161  overlay = 0;
1162  }
1163 
1164  var scrollPoint = [_contentView bounds].origin,
1165  wasShowingVerticalScroller = ![_verticalScroller isHidden],
1166  wasShowingHorizontalScroller = ![_horizontalScroller isHidden];
1167 
1168  if (shouldShowVerticalScroller)
1169  {
1170  var verticalScrollerY =
1171  MAX(CGRectGetMinY(contentFrame), MAX(CGRectGetMaxY([self _cornerViewFrame]), CGRectGetMaxY(headerClipViewFrame)));
1172 
1173  var verticalScrollerHeight = CGRectGetMaxY(contentFrame) - verticalScrollerY;
1174 
1175  // Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap.
1176  if (_scrollerStyle === CPScrollerStyleOverlay && hasHorizontalScroll)
1177  verticalScrollerHeight -= horizontalScrollerHeight;
1178 
1179  var documentHeight = CGRectGetHeight(documentFrame);
1180  [_verticalScroller setFloatValue:(difference.height <= 0.0) ? 0.0 : scrollPoint.y / difference.height];
1181  [_verticalScroller setKnobProportion:documentHeight > 0 ? CGRectGetHeight(contentFrame) / documentHeight : 1.0];
1182  [_verticalScroller setFrame:CGRectMake(CGRectGetMaxX(contentFrame) - overlay, verticalScrollerY, verticalScrollerWidth, verticalScrollerHeight)];
1183  }
1184  else if (wasShowingVerticalScroller)
1185  {
1186  [_verticalScroller setFloatValue:0.0];
1187  [_verticalScroller setKnobProportion:1.0];
1188  }
1189 
1190  if (shouldShowHorizontalScroller)
1191  {
1192  var horizontalScrollerWidth = CGRectGetWidth(contentFrame);
1193  // Make a gap at the bottom of the vertical scroller so that the horizontal and vertical can't overlap.
1194  if (_scrollerStyle === CPScrollerStyleOverlay && hasVerticalScroll)
1195  horizontalScrollerWidth -= verticalScrollerWidth;
1196 
1197  var documentWidth = CGRectGetWidth(documentFrame);
1198 
1199  [_horizontalScroller setFloatValue:(difference.width <= 0.0) ? 0.0 : scrollPoint.x / difference.width];
1200  [_horizontalScroller setKnobProportion:documentWidth > 0 ? CGRectGetWidth(contentFrame) / documentWidth : 1.0];
1201  [_horizontalScroller setFrame:CGRectMake(CGRectGetMinX(contentFrame), CGRectGetMaxY(contentFrame) - overlay, horizontalScrollerWidth, horizontalScrollerHeight)];
1202  }
1203  else if (wasShowingHorizontalScroller)
1204  {
1205  [_horizontalScroller setFloatValue:0.0];
1206  [_horizontalScroller setKnobProportion:1.0];
1207  }
1208 
1209  [_contentView setFrame:contentFrame];
1210  [_headerClipView setFrame:[self _headerClipViewFrame]];
1211  [[_headerClipView documentView] setNeedsDisplay:YES];
1213  {
1214  [_cornerView setFrame:[self _cornerViewFrame]];
1215  [_cornerView setHidden:NO];
1216  }
1217  else
1218  [_cornerView setHidden:YES];
1219 
1220  if (_scrollerStyle === CPScrollerStyleLegacy)
1221  {
1222  [[self bottomCornerView] setFrame:[self _bottomCornerViewFrame]];
1223  [[self bottomCornerView] setBackgroundColor:[self currentValueForThemeAttribute:@"bottom-corner-color"]];
1224  }
1225 
1226  --_recursionCount;
1227 }
1228 
1233 {
1234  if (_scrollerStyle === CPScrollerStyleLegacy)
1235  return;
1236 
1237  if (_hasHorizontalScroller)
1238  {
1239  [_horizontalScroller setHidden:NO];
1240  [_horizontalScroller fadeIn];
1241  }
1242 
1243  if (_hasVerticalScroller)
1244  {
1245  [_verticalScroller setHidden:NO];
1246  [_verticalScroller fadeIn];
1247  }
1248 
1249  if (_timerScrollersHide)
1250  [_timerScrollersHide invalidate]
1251 
1252  _timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
1253 }
1254 
1255 /* @ignore */
1256 - (void)resizeSubviewsWithOldSize:(CGSize)aSize
1257 {
1258  [self reflectScrolledClipView:_contentView];
1259 }
1260 
1262 {
1263  return [_contentView documentVisibleRect];
1264 }
1265 
1266 #pragma mark -
1267 #pragma mark Overrides
1268 
1269 
1270 - (void)_removeObservers
1271 {
1272  if (!_isObserving)
1273  return;
1274 
1276  name:CPScrollerStyleGlobalChangeNotification
1277  object:nil];
1278 
1279  [super _removeObservers];
1280 }
1281 
1282 - (void)_addObservers
1283 {
1284  if (_isObserving)
1285  return;
1286 
1287  //Make sure to have the last global style for the scroller
1288  [self _didReceiveDefaultStyleChange:nil];
1289 
1292  name:CPScrollerStyleGlobalChangeNotification
1293  object:nil];
1294 
1295  [super _addObservers];
1296 }
1297 
1298 
1299 
1300 - (void)drawRect:(CGRect)aRect
1301 {
1302  [super drawRect:aRect];
1303 
1304  if (_borderType == CPNoBorder)
1305  return;
1306 
1307  var strokeRect = [self bounds],
1309 
1310  CGContextSetLineWidth(context, 1);
1311 
1312  switch (_borderType)
1313  {
1314  case CPLineBorder:
1315  CGContextSetStrokeColor(context, [self currentValueForThemeAttribute:@"border-color"]);
1316  CGContextStrokeRect(context, CGRectInset(strokeRect, 0.5, 0.5));
1317  break;
1318 
1319  case CPBezelBorder:
1320  [self _drawGrayBezelInContext:context bounds:strokeRect];
1321  break;
1322 
1323  case CPGrooveBorder:
1324  [self _drawGrooveInContext:context bounds:strokeRect];
1325  break;
1326 
1327  default:
1328  break;
1329  }
1330 }
1331 
1332 - (void)_drawGrayBezelInContext:(CGContext)context bounds:(CGRect)aRect
1333 {
1334  var minX = CGRectGetMinX(aRect),
1335  maxX = CGRectGetMaxX(aRect),
1336  minY = CGRectGetMinY(aRect),
1337  maxY = CGRectGetMaxY(aRect),
1338  y = minY + 0.5;
1339 
1340  // Slightly darker line on top.
1341  CGContextSetStrokeColor(context, [CPColor colorWithWhite:142.0 / 255.0 alpha:1.0]);
1342  CGContextBeginPath(context);
1343  CGContextMoveToPoint(context, minX, y);
1344  CGContextAddLineToPoint(context, maxX, y);
1345  CGContextStrokePath(context);
1346 
1347  // The rest of the border.
1348  CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
1349 
1350  var x = maxX - 0.5;
1351 
1352  CGContextBeginPath(context);
1353  CGContextMoveToPoint(context, x, minY + 1.0);
1354  CGContextAddLineToPoint(context, x, maxY);
1355  CGContextMoveToPoint(context, x - 0.5, maxY - 0.5);
1356  CGContextAddLineToPoint(context, minX, maxY - 0.5);
1357 
1358  x = minX + 0.5;
1359 
1360  CGContextMoveToPoint(context, x, maxY);
1361  CGContextAddLineToPoint(context, x, minY + 1.0);
1362 
1363  CGContextStrokePath(context);
1364 }
1365 
1366 - (void)_drawGrooveInContext:(CGContext)context bounds:(CGRect)aRect
1367 {
1368  var minX = CGRectGetMinX(aRect),
1369  maxX = CGRectGetMaxX(aRect),
1370  minY = CGRectGetMinY(aRect),
1371  maxY = CGRectGetMaxY(aRect);
1372 
1373  CGContextBeginPath(context);
1374  CGContextSetStrokeColor(context, [CPColor colorWithWhite:159.0 / 255.0 alpha:1.0]);
1375 
1376  var y = minY + 0.5;
1377 
1378  CGContextMoveToPoint(context, minX, y);
1379  CGContextAddLineToPoint(context, maxX, y);
1380 
1381  var x = maxX - 1.5;
1382 
1383  CGContextMoveToPoint(context, x, minY + 2.0);
1384  CGContextAddLineToPoint(context, x, maxY - 1.0);
1385 
1386  y = maxY - 1.5;
1387 
1388  CGContextMoveToPoint(context, maxX - 1.0, y);
1389  CGContextAddLineToPoint(context, minX + 2.0, y);
1390 
1391  x = minX + 0.5;
1392 
1393  CGContextMoveToPoint(context, x, maxY);
1394  CGContextAddLineToPoint(context, x, minY);
1395 
1396  CGContextStrokePath(context);
1397 
1398  CGContextBeginPath(context);
1399  CGContextSetStrokeColor(context, [CPColor whiteColor]);
1400 
1401  var rect = CGRectOffset(aRect, 1.0, 1.0);
1402 
1403  rect.size.width -= 1.0;
1404  rect.size.height -= 1.0;
1405  CGContextStrokeRect(context, CGRectInset(rect, 0.5, 0.5));
1406 
1407  CGContextBeginPath(context);
1408  CGContextSetStrokeColor(context, [CPColor colorWithWhite:192.0 / 255.0 alpha:1.0]);
1409 
1410  y = minY + 2.5;
1411 
1412  CGContextMoveToPoint(context, minX + 2.0, y);
1413  CGContextAddLineToPoint(context, maxX - 2.0, y);
1414  CGContextStrokePath(context);
1415 }
1416 
1422 - (void)scrollWheel:(CPEvent)anEvent
1423 {
1424  if (_timerScrollersHide)
1425  [_timerScrollersHide invalidate];
1426  if (![_verticalScroller isHidden])
1427  [_verticalScroller fadeIn];
1428  if (![_horizontalScroller isHidden])
1429  [_horizontalScroller fadeIn];
1430  if (![_horizontalScroller isHidden] || ![_verticalScroller isHidden])
1431  _timerScrollersHide = [CPTimer scheduledTimerWithTimeInterval:CPScrollViewFadeOutTime target:self selector:@selector(_hideScrollers:) userInfo:nil repeats:NO];
1432 
1433  var deltaX = [anEvent scrollingDeltaX],
1434  deltaY = [anEvent scrollingDeltaY];
1435 
1436  if (![anEvent hasPreciseScrollingDeltas])
1437  {
1438  deltaX *= (_horizontalLineScroll || 1.0);
1439  deltaY *= (_verticalLineScroll || 1.0);
1440  }
1441 
1442  [self _respondToScrollWheelEventWithDeltaX:deltaX deltaY:deltaY];
1443 }
1444 
1445 - (void)scrollPageUp:(id)sender
1446 {
1447  var contentBounds = [_contentView bounds];
1448  [self moveByOffset:CGSizeMake(0.0, -(CGRectGetHeight(contentBounds) - _verticalPageScroll))];
1449 }
1450 
1451 - (void)scrollPageDown:(id)sender
1452 {
1453  var contentBounds = [_contentView bounds];
1454  [self moveByOffset:CGSizeMake(0.0, CGRectGetHeight(contentBounds) - _verticalPageScroll)];
1455 }
1456 
1457 - (void)scrollToBeginningOfDocument:(id)sender
1458 {
1459  [_contentView scrollToPoint:CGPointMakeZero()];
1460  [_headerClipView scrollToPoint:CGPointMakeZero()];
1461 }
1462 
1463 - (void)scrollToEndOfDocument:(id)sender
1464 {
1465  var contentBounds = [_contentView bounds],
1466  documentFrame = [[self documentView] frame],
1467  scrollPoint = CGPointMake(0.0, CGRectGetHeight(documentFrame) - CGRectGetHeight(contentBounds));
1468 
1469  [_contentView scrollToPoint:scrollPoint];
1470  [_headerClipView scrollToPoint:CGPointMakeZero()];
1471 }
1472 
1473 - (void)moveLeft:(id)sender
1474 {
1475  [self moveByOffset:CGSizeMake(-_horizontalLineScroll, 0.0)];
1476 }
1477 
1478 - (void)moveRight:(id)sender
1479 {
1480  [self moveByOffset:CGSizeMake(_horizontalLineScroll, 0.0)];
1481 }
1482 
1483 - (void)moveUp:(id)sender
1484 {
1485  [self moveByOffset:CGSizeMake(0.0, -_verticalLineScroll)];
1486 }
1487 
1488 - (void)moveDown:(id)sender
1489 {
1490  [self moveByOffset:CGSizeMake(0.0, _verticalLineScroll)];
1491 }
1492 
1493 - (void)moveByOffset:(CGSize)aSize
1494 {
1495  var documentFrame = [[self documentView] frame],
1496  contentBounds = [_contentView bounds];
1497 
1498  contentBounds.origin.x += aSize.width;
1499  contentBounds.origin.y += aSize.height;
1500 
1501  [_contentView scrollToPoint:contentBounds.origin];
1502  [_headerClipView scrollToPoint:CGPointMake(contentBounds.origin.x, 0)];
1503 }
1504 
1505 @end
1506 
1507 
1508 var CPScrollViewContentViewKey = @"CPScrollViewContentView",
1509  CPScrollViewHeaderClipViewKey = @"CPScrollViewHeaderClipViewKey",
1510  CPScrollViewVLineScrollKey = @"CPScrollViewVLineScroll",
1511  CPScrollViewHLineScrollKey = @"CPScrollViewHLineScroll",
1512  CPScrollViewVPageScrollKey = @"CPScrollViewVPageScroll",
1513  CPScrollViewHPageScrollKey = @"CPScrollViewHPageScroll",
1514  CPScrollViewHasVScrollerKey = @"CPScrollViewHasVScroller",
1515  CPScrollViewHasHScrollerKey = @"CPScrollViewHasHScroller",
1516  CPScrollViewVScrollerKey = @"CPScrollViewVScroller",
1517  CPScrollViewHScrollerKey = @"CPScrollViewHScroller",
1518  CPScrollViewAutohidesScrollerKey = @"CPScrollViewAutohidesScroller",
1519  CPScrollViewCornerViewKey = @"CPScrollViewCornerViewKey",
1520  CPScrollViewBottomCornerViewKey = @"CPScrollViewBottomCornerViewKey",
1521  CPScrollViewBorderTypeKey = @"CPScrollViewBorderTypeKey",
1522  CPScrollViewScrollerStyleKey = @"CPScrollViewScrollerStyleKey",
1523  CPScrollViewScrollerKnobStyleKey = @"CPScrollViewScrollerKnobStyleKey";
1524 
1526 
1527 - (id)initWithCoder:(CPCoder)aCoder
1528 {
1529  if (self = [super initWithCoder:aCoder])
1530  {
1531  _verticalLineScroll = [aCoder decodeFloatForKey:CPScrollViewVLineScrollKey];
1532  _verticalPageScroll = [aCoder decodeFloatForKey:CPScrollViewVPageScrollKey];
1533 
1534  _horizontalLineScroll = [aCoder decodeFloatForKey:CPScrollViewHLineScrollKey];
1535  _horizontalPageScroll = [aCoder decodeFloatForKey:CPScrollViewHPageScrollKey];
1536 
1537  _contentView = [aCoder decodeObjectForKey:CPScrollViewContentViewKey];
1538  _headerClipView = [aCoder decodeObjectForKey:CPScrollViewHeaderClipViewKey];
1539 
1540  if (!_headerClipView)
1541  {
1542  _headerClipView = [[CPClipView alloc] init];
1543  [self addSubview:_headerClipView];
1544  }
1545 
1546  _verticalScroller = [aCoder decodeObjectForKey:CPScrollViewVScrollerKey];
1547  _horizontalScroller = [aCoder decodeObjectForKey:CPScrollViewHScrollerKey];
1548 
1549  _hasVerticalScroller = [aCoder decodeBoolForKey:CPScrollViewHasVScrollerKey];
1550  _hasHorizontalScroller = [aCoder decodeBoolForKey:CPScrollViewHasHScrollerKey];
1551  _autohidesScrollers = [aCoder decodeBoolForKey:CPScrollViewAutohidesScrollerKey];
1552 
1553  _borderType = [aCoder decodeIntForKey:CPScrollViewBorderTypeKey];
1554 
1555  _cornerView = [aCoder decodeObjectForKey:CPScrollViewCornerViewKey];
1556  _bottomCornerView = [aCoder decodeObjectForKey:CPScrollViewBottomCornerViewKey];
1557 
1558  _delegate = nil;
1559  _scrollTimer = nil;
1560  _implementedDelegateMethods = 0;
1561 
1562  _scrollerStyle = [aCoder decodeObjectForKey:CPScrollViewScrollerStyleKey] || CPScrollerStyleGlobal;
1563  _scrollerKnobStyle = [aCoder decodeObjectForKey:CPScrollViewScrollerKnobStyleKey] || CPScrollerKnobStyleDefault;
1564 
1567  name:CPScrollerStyleGlobalChangeNotification
1568  object:nil];
1569  }
1570 
1571  return self;
1572 }
1573 
1578 {
1579  [super awakeFromCib];
1580 
1581  [self _updateScrollerStyle];
1582  [self _updateCornerAndHeaderView];
1583 }
1584 
1585 - (void)encodeWithCoder:(CPCoder)aCoder
1586 {
1587  [super encodeWithCoder:aCoder];
1588 
1589  [aCoder encodeObject:_contentView forKey:CPScrollViewContentViewKey];
1590  [aCoder encodeObject:_headerClipView forKey:CPScrollViewHeaderClipViewKey];
1591 
1592  [aCoder encodeObject:_verticalScroller forKey:CPScrollViewVScrollerKey];
1593  [aCoder encodeObject:_horizontalScroller forKey:CPScrollViewHScrollerKey];
1594 
1595  [aCoder encodeFloat:_verticalLineScroll forKey:CPScrollViewVLineScrollKey];
1596  [aCoder encodeFloat:_verticalPageScroll forKey:CPScrollViewVPageScrollKey];
1597  [aCoder encodeFloat:_horizontalLineScroll forKey:CPScrollViewHLineScrollKey];
1598  [aCoder encodeFloat:_horizontalPageScroll forKey:CPScrollViewHPageScrollKey];
1599 
1600  [aCoder encodeBool:_hasVerticalScroller forKey:CPScrollViewHasVScrollerKey];
1601  [aCoder encodeBool:_hasHorizontalScroller forKey:CPScrollViewHasHScrollerKey];
1602  [aCoder encodeBool:_autohidesScrollers forKey:CPScrollViewAutohidesScrollerKey];
1603 
1604  [aCoder encodeObject:_cornerView forKey:CPScrollViewCornerViewKey];
1605  [aCoder encodeObject:_bottomCornerView forKey:CPScrollViewBottomCornerViewKey];
1606 
1607  [aCoder encodeInt:_borderType forKey:CPScrollViewBorderTypeKey];
1608 
1609  [aCoder encodeInt:_scrollerStyle forKey:CPScrollViewScrollerStyleKey];
1610  [aCoder encodeInt:_scrollerKnobStyle forKey:CPScrollViewScrollerKnobStyleKey];
1611 }
1612 
1613 @end
id initWithFrame:(CGRect aFrame)
Definition: CPView.j:334
void setHasHorizontalScroller:(BOOL shouldHaveHorizontalScroller)
Definition: CPScrollView.j:515
var CPScrollViewDelegate_scrollViewWillScroll_
Definition: CPScrollView.j:85
void addSubview:(CPView aSubview)
Definition: CPView.j:512
A CALayer is similar to a CPView
Definition: CALayer.j:46
float scrollerWidthInStyle:(int aStyle)
Definition: CPScroller.j:132
void drawRect:(CGRect aRect)
Definition: CPView.j:2464
BOOL autohidesScrollers()
Definition: CPScrollView.j:601
var CPScrollViewBorderTypeKey
float scrollingDeltaX()
Definition: CPEvent.j:487
void setVerticalScroller:(CPScroller aScroller)
Definition: CPScrollView.j:546
var CPScrollViewHasVScrollerKey
A representation of a single point in time.
Definition: CPDate.h:2
CPGraphicsContext currentContext()
int globalScrollerStyle()
Definition: CPScrollView.j:217
CPScroller verticalScroller()
Definition: CPScrollView.j:536
float scrollerWidth()
Definition: CPScroller.j:124
int scrollerKnobStyle()
Definition: CPScrollView.j:349
float lineScroll()
Definition: CPScrollView.j:645
#define SHOULD_SHOW_CORNER_VIEW()
Definition: CPScrollView.j:28
void setVerticalLineScroll:(float aLineScroll)
Definition: CPScrollView.j:692
CPDictionary themeAttributes()
Definition: CPScrollView.j:155
function CGContextSetStrokeColor(aContext, aColor)
Definition: CGContext.j:675
float scrollerOverlay()
Definition: CPScroller.j:146
CGRect documentVisibleRect()
CPBorderType CPNoBorder
Definition: CPBox.j:34
var CPScrollViewDelegate_scrollViewDidScroll_
Definition: CPScrollView.j:86
float scrollingDeltaY()
Definition: CPEvent.j:497
void addObserver:selector:name:object:(id anObserver, [selector] SEL aSelector, [name] CPString aNotificationName, [object] id anObject)
CPScrollerKnob
Definition: CPScroller.j:35
var CPScrollViewBottomCornerViewKey
void setFrame:(CGRect aFrame)
Definition: CPView.j:996
var CPScrollViewAutohidesScrollerKey
CPColor whiteColor()
Definition: CPColor.j:360
CPScrollerIncrementLine
Definition: CPScroller.j:38
var CPScrollViewFadeOutTime
Definition: CPScrollView.j:88
void setHasVerticalScroller:(BOOL shouldHaveVerticalScroller)
Definition: CPScrollView.j:580
CGRect bounds()
Definition: CPView.j:1302
CPScrollerDecrementPage
Definition: CPScroller.j:34
void postNotificationName:object:(CPString aNotificationName, [object] id anObject)
void setHorizontalScroller:(CPScroller aScroller)
Definition: CPScrollView.j:482
function CGContextAddLineToPoint(aContext, x, y)
Definition: CGContext.j:247
function CGContextStrokePath(aContext)
Definition: CGContext.j:619
CPNotificationCenter defaultCenter()
A mutable key-value pair collection.
Definition: CPDictionary.h:2
CPScrollView enclosingScrollView()
Definition: CPView.j:2928
function CGContextSetLineWidth(aContext, aLineWidth)
Definition: CGContext.j:177
var CPScrollViewVPageScrollKey
var CPScrollViewScrollerKnobStyleKey
CGSize frameSize()
Definition: CPView.j:1032
CPColor blackColor()
Definition: CPColor.j:283
void setHorizontalPageScroll:(float aPageScroll)
Definition: CPScrollView.j:729
void reflectScrolledClipView:(CPClipView aClipView)
var CPScrollViewHasHScrollerKey
CPString defaultThemeClass()
Definition: CPScrollView.j:150
void setHorizontalLineScroll:(float aLineScroll)
Definition: CPScrollView.j:674
float verticalLineScroll()
Definition: CPScrollView.j:682
An immutable string (collection of characters).
Definition: CPString.h:2
CGSize contentSize()
Definition: CPScrollView.j:412
CPBundle mainBundle()
Definition: CPBundle.j:82
CPScrollerKnobStyleDark
Definition: CPScroller.j:65
id documentView()
Definition: CPClipView.j:57
CPClipView contentView()
Definition: CPScrollView.j:377
BOOL hasHorizontalScroller()
Definition: CPScrollView.j:504
CPBorderType borderType()
Definition: CPScrollView.j:442
var TIMER_INTERVAL
Definition: CPScrollView.j:84
var CPScrollViewScrollerStyleKey
void setHidden:(BOOL aFlag)
Definition: CPView.j:1579
void flashScrollers()
void setNeedsDisplay:(BOOL aFlag)
Definition: CPView.j:2556
BOOL isHidden()
Definition: CPView.j:1697
void encodeWithCoder:(CPCoder aCoder)
Definition: CPView.j:3770
function CGContextBeginPath(aContext)
Definition: CGContext.j:311
BOOL hasVerticalScroller()
Definition: CPScrollView.j:568
CPScrollerDecrementLine
Definition: CPScroller.j:37
A notification that can be posted to a CPNotificationCenter.
Definition: CPNotification.h:2
CPTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:(CPTimeInterval seconds, [target] id aTarget, [selector] SEL aSelector, [userInfo] id userInfo, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:58
var CPScrollViewHPageScrollKey
CPScrollerStyleLegacy
Definition: CPScroller.j:61
void moveByOffset:(CGSize aSize)
CPLineBorder
Definition: CPBox.j:35
var CPScrollViewVLineScrollKey
var CPScrollViewVScrollerKey
CPGrooveBorder
Definition: CPBox.j:37
var CPScrollViewHLineScrollKey
CPScrollerKnobStyleLight
Definition: CPScroller.j:66
float floatValue()
Definition: CPControl.j:545
CPScrollerKnobSlot
Definition: CPScroller.j:39
A timer object that can send a message after the given time interval.
Definition: CPTimer.h:2
id objectForInfoDictionaryKey:(CPString aKey)
Definition: CPBundle.j:183
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
function CGContextStrokeRect(aContext, aRect)
Definition: CGContext.j:388
Sends messages (CPNotification) between objects.
CPScrollerIncrementPage
Definition: CPScroller.j:36
float pageScroll()
Definition: CPScrollView.j:700
var CPScrollViewCornerViewKey
void setBackgroundColor:(CPColor aColor)
Definition: CPView.j:1923
float horizontalPageScroll()
Definition: CPScrollView.j:719
var CPScrollViewContentViewKey
void removeObserver:name:object:(id anObserver, [name] CPString aNotificationName, [object] id anObject)
Definition: CPEvent.h:2
float horizontalLineScroll()
Definition: CPScrollView.j:664
CPView bottomCornerView()
Definition: CPScrollView.j:622
id dateWithTimeIntervalSinceNow:(CPTimeInterval seconds)
Definition: CPDate.j:47
CPScroller horizontalScroller()
Definition: CPScrollView.j:472
CPScrollerStyleOverlay
Definition: CPScroller.j:62
void setScrollerStyle:(int aStyle)
Definition: CPScrollView.j:329
var CPScrollerStyleGlobalChangeNotification
Definition: CPScrollView.j:91
CGRect frame()
Definition: CPView.j:1022
CPBezelBorder
Definition: CPBox.j:36
var CPScrollViewHScrollerKey
void setFrameSize:(CGSize aSize)
Definition: CPScroller.j:691
function CGContextMoveToPoint(aContext, x, y)
Definition: CGContext.j:344
float verticalPageScroll()
Definition: CPScrollView.j:737
var CPScrollerStyleGlobal
Definition: CPScrollView.j:90
CPScrollerKnobStyleDefault
Definition: CPScroller.j:64
Definition: CPView.j:136
var CPScrollViewHeaderClipViewKey
void setVerticalPageScroll:(float aPageScroll)
Definition: CPScrollView.j:747