API  0.9.10
CPScroller.j
Go to the documentation of this file.
1 /*
2  * CPScroller.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 #include "../Foundation/Foundation.h"
27 
28 
29 @global CPApp
30 
31 // CPScroller Constants
32 @typedef CPScrollerPart
40 
43 
44 @typedef CPUsableScrollerParts
48 
49 var PARTS_ARRANGEMENT = [CPScrollerKnobSlot, CPScrollerDecrementLine, CPScrollerIncrementLine, CPScrollerKnob],
52 
53 var _CACHED_THEME_SCROLLER = nil; // This is used by the class methods to pull the theme attributes.
54 
55 NAMES_FOR_PARTS[CPScrollerDecrementLine] = @"decrement-line";
56 NAMES_FOR_PARTS[CPScrollerIncrementLine] = @"increment-line";
57 NAMES_FOR_PARTS[CPScrollerKnobSlot] = @"knob-slot";
58 NAMES_FOR_PARTS[CPScrollerKnob] = @"knob";
59 
60 
63 
67 
68 CPThemeStateScrollViewLegacy = CPThemeState("scroller-style-legacy");
69 CPThemeStateScrollerKnobLight = CPThemeState("scroller-knob-light");
70 CPThemeStateScrollerKnobDark = CPThemeState("scroller-knob-dark");
71 
76 @implementation CPScroller : CPControl
77 {
78  CPUsableScrollerParts _usableParts;
79  CPArray _partRects;
80 
81  BOOL _isVertical;
82  float _knobProportion;
83 
84  CPScrollerPart _hitPart;
85 
86  CPScrollerPart _trackingPart;
87  float _trackingFloatValue;
88  CGPoint _trackingStartPoint;
89 
90  CPViewAnimation _animationScroller;
91 
92  BOOL _allowFadingOut;
93  int _style;
94  CPTimer _timerFadeOut;
95  BOOL _isMouseOver;
96 }
97 
98 
99 #pragma mark -
100 #pragma mark Class methods
101 
103 {
104  return "scroller";
105 }
106 
108 {
109  return @{
110  @"scroller-width": 7.0,
111  @"knob-slot-color": [CPNull null],
112  @"decrement-line-color": [CPNull null],
113  @"increment-line-color": [CPNull null],
114  @"knob-color": [CPNull null],
115  @"decrement-line-size": CGSizeMakeZero(),
116  @"increment-line-size": CGSizeMakeZero(),
117  @"track-inset": CGInsetMakeZero(),
118  @"knob-inset": CGInsetMakeZero(),
119  @"minimum-knob-length": 21.0,
120  @"track-border-overlay": 9.0
121  };
122 }
123 
125 {
126  return [self scrollerWidthInStyle:CPScrollerStyleLegacy];
127 }
128 
132 + (float)scrollerWidthInStyle:(int)aStyle
133 {
134  if (!_CACHED_THEME_SCROLLER)
135  _CACHED_THEME_SCROLLER = [[self alloc] init];
136 
137  if (aStyle == CPScrollerStyleLegacy)
138  return [_CACHED_THEME_SCROLLER valueForThemeAttribute:@"scroller-width" inState:CPThemeStateScrollViewLegacy];
139 
140  return [_CACHED_THEME_SCROLLER currentValueForThemeAttribute:@"scroller-width"];
141 }
142 
147 {
148  if (!_CACHED_THEME_SCROLLER)
149  _CACHED_THEME_SCROLLER = [[self alloc] init];
150 
151  return [_CACHED_THEME_SCROLLER currentValueForThemeAttribute:@"track-border-overlay"];
152 }
153 
158 + (float)scrollerWidthForControlSize:(CPControlSize)aControlSize
159 {
160  return [self scrollerWidth];
161 }
162 
163 
164 #pragma mark -
165 #pragma mark Initialization
166 
167 - (id)initWithFrame:(CGRect)aFrame
168 {
169  if (self = [super initWithFrame:aFrame])
170  {
171  _partRects = [];
172 
173  [self setFloatValue:0.0];
174  [self setKnobProportion:1.0];
175 
176  _hitPart = CPScrollerNoPart;
177  _allowFadingOut = YES;
178  _isMouseOver = NO;
179  _style = CPScrollerStyleOverlay;
180 
181  var paramAnimFadeOut = @{
184  };
185 
186  _animationScroller = [[CPViewAnimation alloc] initWithDuration:0.2 animationCurve:CPAnimationEaseInOut];
187  [_animationScroller setViewAnimations:[paramAnimFadeOut]];
188  [_animationScroller setDelegate:self];
189  [self setAlphaValue:0.0];
190 
191  // We have to choose an orientation. If for some bizarre reason width === height,
192  // punt and choose vertical.
193  [self _setIsVertical:CGRectGetHeight(aFrame) >= CGRectGetWidth(aFrame)];
194  }
195 
196  return self;
197 }
198 
199 
200 #pragma mark -
201 #pragma mark Getters / Setters
202 
206 - (void)style
207 {
208  return _style;
209 }
210 
215 - (void)setStyle:(id)aStyle
216 {
217  if (_style != nil && _style === aStyle)
218  return;
219 
220  _style = aStyle;
221 
222  if (_style === CPScrollerStyleLegacy)
223  {
224  [self fadeIn];
225  [self setThemeState:CPThemeStateScrollViewLegacy];
226  }
227  else
228  {
229  _allowFadingOut = YES;
230  [self unsetThemeState:CPThemeStateScrollViewLegacy];
231  }
232 
233  //[self _adjustScrollerSize];
234 }
235 
236 - (void)setObjectValue:(id)aValue
237 {
238  [super setObjectValue:MIN(1.0, MAX(0.0, +aValue))];
239 }
240 
245 {
246  return _knobProportion;
247 }
248 
253 - (void)setKnobProportion:(float)aProportion
254 {
255  if (!_IS_NUMERIC(aProportion))
256  [CPException raise:CPInvalidArgumentException reason:"aProportion must be numeric"];
257 
258  _knobProportion = MIN(1.0, MAX(0.0001, aProportion));
259 
260  [self setNeedsDisplay:YES];
261  [self setNeedsLayout];
262 }
263 
264 
265 #pragma mark -
266 #pragma mark Privates
267 
269 - (void)_adjustScrollerSize
270 {
271  var frame = [self frame],
272  scrollerWidth = [self currentValueForThemeAttribute:@"scroller-width"];
273 
274  if ([self isVertical] && CGRectGetWidth(frame) !== scrollerWidth)
275  frame.size.width = scrollerWidth;
276 
277  if (![self isVertical] && CGRectGetHeight(frame) !== scrollerWidth)
278  frame.size.height = scrollerWidth;
279 
280  [self setFrame:frame];
281 }
282 
284 - (void)_performFadeOut:(CPTimer)aTimer
285 {
286  [self fadeOut];
287  _timerFadeOut = nil;
288 }
289 
290 
291 #pragma mark -
292 #pragma mark Utilities
293 
294 - (CGRect)rectForPart:(CPScrollerPart)aPart
295 {
296  if (aPart == CPScrollerNoPart)
297  return CGRectMakeZero();
298 
299  return _partRects[aPart];
300 }
301 
307 - (CPScrollerPart)testPart:(CGPoint)aPoint
308 {
309  aPoint = [self convertPoint:aPoint fromView:nil];
310 
311  // The ordering of these tests is important. We check the knob and
312  // page rects first since they may overlap with the arrows.
313 
314  if (![self hasThemeState:CPThemeStateSelected] && ![self hasThemeState:CPThemeStateScrollViewLegacy])
315  return CPScrollerNoPart;
316 
317  if (CGRectContainsPoint([self rectForPart:CPScrollerKnob], aPoint))
318  return CPScrollerKnob;
319 
320  if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementPage], aPoint))
322 
323  if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementPage], aPoint))
325 
326  if (CGRectContainsPoint([self rectForPart:CPScrollerDecrementLine], aPoint))
328 
329  if (CGRectContainsPoint([self rectForPart:CPScrollerIncrementLine], aPoint))
331 
332  if (CGRectContainsPoint([self rectForPart:CPScrollerKnobSlot], aPoint))
333  return CPScrollerKnobSlot;
334 
335  return CPScrollerNoPart;
336 }
337 
342 {
343  var bounds = [self bounds];
344 
345  // Assume we won't be needing the arrows.
346  if (_knobProportion === 1.0)
347  {
348  _usableParts = CPNoScrollerParts;
349 
350  _partRects[CPScrollerDecrementPage] = CGRectMakeZero();
351  _partRects[CPScrollerKnob] = CGRectMakeZero();
352  _partRects[CPScrollerIncrementPage] = CGRectMakeZero();
353  _partRects[CPScrollerDecrementLine] = CGRectMakeZero();
354  _partRects[CPScrollerIncrementLine] = CGRectMakeZero();
355 
356  // In this case, the slot is the entirety of the scroller.
357  _partRects[CPScrollerKnobSlot] = CGRectMakeCopy(bounds);
358 
359  return;
360  }
361 
362  // At this point we know we're going to need arrows.
363  _usableParts = CPAllScrollerParts;
364 
365  var knobInset = [self currentValueForThemeAttribute:@"knob-inset"],
366  trackInset = [self currentValueForThemeAttribute:@"track-inset"],
367  width = CGRectGetWidth(bounds),
368  height = CGRectGetHeight(bounds);
369 
370  if ([self isVertical])
371  {
372  var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
373  incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"],
374  effectiveDecrementLineHeight = decrementLineSize.height + trackInset.top,
375  effectiveIncrementLineHeight = incrementLineSize.height + trackInset.bottom,
376  slotSize = height - effectiveDecrementLineHeight - effectiveIncrementLineHeight,
377  minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
378  knobWidth = width - knobInset.left - knobInset.right,
379  knobHeight = MAX(minimumKnobLength, (slotSize * _knobProportion)),
380  knobLocation = effectiveDecrementLineHeight + (slotSize - knobHeight) * [self floatValue];
381 
382  _partRects[CPScrollerDecrementPage] = CGRectMake(0.0, effectiveDecrementLineHeight, width, knobLocation - effectiveDecrementLineHeight);
383  _partRects[CPScrollerKnob] = CGRectMake(knobInset.left, knobLocation, knobWidth, knobHeight);
384  _partRects[CPScrollerIncrementPage] = CGRectMake(0.0, knobLocation + knobHeight, width, height - (knobLocation + knobHeight) - effectiveIncrementLineHeight);
385  _partRects[CPScrollerKnobSlot] = CGRectMake(trackInset.left, effectiveDecrementLineHeight, width - trackInset.left - trackInset.right, slotSize);
386  _partRects[CPScrollerDecrementLine] = CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
387  _partRects[CPScrollerIncrementLine] = CGRectMake(0.0, height - incrementLineSize.height, incrementLineSize.width, incrementLineSize.height);
388 
389  if (height < knobHeight + decrementLineSize.height + incrementLineSize.height + trackInset.top + trackInset.bottom)
390  _partRects[CPScrollerKnob] = CGRectMakeZero();
391 
392  if (height < decrementLineSize.height + incrementLineSize.height - 2)
393  {
394  _partRects[CPScrollerIncrementLine] = CGRectMakeZero();
395  _partRects[CPScrollerDecrementLine] = CGRectMakeZero();
396  _partRects[CPScrollerKnobSlot] = CGRectMake(trackInset.left, 0, width - trackInset.left - trackInset.right, height);
397  }
398  }
399  else
400  {
401  var decrementLineSize = [self currentValueForThemeAttribute:"decrement-line-size"],
402  incrementLineSize = [self currentValueForThemeAttribute:"increment-line-size"],
403  effectiveDecrementLineWidth = decrementLineSize.width + trackInset.left,
404  effectiveIncrementLineWidth = incrementLineSize.width + trackInset.right,
405  slotSize = width - effectiveDecrementLineWidth - effectiveIncrementLineWidth,
406  minimumKnobLength = [self currentValueForThemeAttribute:"minimum-knob-length"],
407  knobWidth = MAX(minimumKnobLength, (slotSize * _knobProportion)),
408  knobHeight = height - knobInset.top - knobInset.bottom,
409  knobLocation = effectiveDecrementLineWidth + (slotSize - knobWidth) * [self floatValue];
410 
411  _partRects[CPScrollerDecrementPage] = CGRectMake(effectiveDecrementLineWidth, 0.0, knobLocation - effectiveDecrementLineWidth, height);
412  _partRects[CPScrollerKnob] = CGRectMake(knobLocation, knobInset.top, knobWidth, knobHeight);
413  _partRects[CPScrollerIncrementPage] = CGRectMake(knobLocation + knobWidth, 0.0, width - (knobLocation + knobWidth) - effectiveIncrementLineWidth, height);
414  _partRects[CPScrollerKnobSlot] = CGRectMake(effectiveDecrementLineWidth, trackInset.top, slotSize, height - trackInset.top - trackInset.bottom);
415  _partRects[CPScrollerDecrementLine] = CGRectMake(0.0, 0.0, decrementLineSize.width, decrementLineSize.height);
416  _partRects[CPScrollerIncrementLine] = CGRectMake(width - incrementLineSize.width, 0.0, incrementLineSize.width, incrementLineSize.height);
417 
418  if (width < knobWidth + decrementLineSize.width + incrementLineSize.width + trackInset.left + trackInset.right)
419  _partRects[CPScrollerKnob] = CGRectMakeZero();
420 
421  if (width < decrementLineSize.width + incrementLineSize.width - 2)
422  {
423  _partRects[CPScrollerIncrementLine] = CGRectMakeZero();
424  _partRects[CPScrollerDecrementLine] = CGRectMakeZero();
425  _partRects[CPScrollerKnobSlot] = CGRectMake(0.0, 0.0, width, slotSize);
426  }
427  }
428 }
429 
434 - (CPUsableScrollerParts)usableParts
435 {
436  return _usableParts;
437 }
438 
442 - (void)fadeIn
443 {
444  if (_isMouseOver && _knobProportion != 1.0)
445  [self setThemeState:CPThemeStateSelected];
446 
447  if (_timerFadeOut)
448  [_timerFadeOut invalidate];
449 
450  [self setAlphaValue:1.0];
451 }
452 
456 - (void)fadeOut
457 {
458  if ([self hasThemeState:CPThemeStateScrollViewLegacy])
459  return;
460 
461  [_animationScroller startAnimation];
462 }
463 
464 
465 #pragma mark -
466 #pragma mark Drawing
467 
473 - (void)drawArrow:(CPScrollerArrow)anArrow highlight:(BOOL)shouldHighlight
474 {
475 }
476 
480 - (void)drawKnob
481 {
482 }
483 
488 {
489 }
490 
491 - (CPView)createViewForPart:(CPScrollerPart)aPart
492 {
493  var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
494 
495  [view setHitTests:NO];
496 
497  return view;
498 }
499 
500 - (CGRect)rectForEphemeralSubviewNamed:(CPString)aName
501 {
502  return _partRects[aName];
503 }
504 
505 - (CPView)createEphemeralSubviewNamed:(CPString)aName
506 {
507  var view = [[CPView alloc] initWithFrame:CGRectMakeZero()];
508 
509  [view setHitTests:NO];
510 
511  return view;
512 }
513 
515 {
516  [self _adjustScrollerSize];
517  [self checkSpaceForParts];
518 
519  var index = 0,
520  count = PARTS_ARRANGEMENT.length,
521  view;
522 
523  for (; index < count; ++index)
524  {
525  var part = PARTS_ARRANGEMENT[index];
526 
527  if (index === 0)
528  view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowBelow relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index + 1]];
529  else
530  view = [self layoutEphemeralSubviewNamed:part positioned:CPWindowAbove relativeToEphemeralSubviewNamed:PARTS_ARRANGEMENT[index - 1]];
531 
532  if (view)
533  [view setBackgroundColor:[self currentValueForThemeAttribute:NAMES_FOR_PARTS[part] + "-color"]];
534  }
535 }
536 
540 - (void)drawParts
541 {
542  [self drawKnobSlot];
543  [self drawKnob];
544  [self drawArrow:CPScrollerDecrementArrow highlight:NO];
545  [self drawArrow:CPScrollerIncrementArrow highlight:NO];
546 }
547 
548 // Event Handling
552 - (CPScrollerPart)hitPart
553 {
554  return _hitPart;
555 }
556 
561 - (void)trackKnob:(CPEvent)anEvent
562 {
563  var type = [anEvent type];
564 
565  if (type === CPLeftMouseUp)
566  {
567  _hitPart = CPScrollerNoPart;
568 
569  return;
570  }
571 
572  if (type === CPLeftMouseDown)
573  {
574  _trackingFloatValue = [self floatValue];
575  _trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
576  }
577 
578  else if (type === CPLeftMouseDragged)
579  {
580  var knobRect = [self rectForPart:CPScrollerKnob],
581  knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
582  remainder = ![self isVertical] ? (CGRectGetWidth(knobSlotRect) - CGRectGetWidth(knobRect)) : (CGRectGetHeight(knobSlotRect) - CGRectGetHeight(knobRect));
583 
584  if (remainder <= 0)
585  [self setFloatValue:0.0];
586  else
587  {
588  var location = [self convertPoint:[anEvent locationInWindow] fromView:nil],
589  delta = ![self isVertical] ? location.x - _trackingStartPoint.x : location.y - _trackingStartPoint.y;
590 
591  [self setFloatValue:_trackingFloatValue + delta / remainder];
592  }
593  }
594 
595  [CPApp setTarget:self selector:@selector(trackKnob:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
596 
597  if (type === CPLeftMouseDragged)
598  [self sendAction:[self action] to:[self target]];
599 }
600 
605 - (void)trackScrollButtons:(CPEvent)anEvent
606 {
607  var type = [anEvent type];
608 
609  if (type === CPLeftMouseUp)
610  {
611  [self highlight:NO];
613 
614  _hitPart = CPScrollerNoPart;
615 
616  return;
617  }
618 
619  if (type === CPLeftMouseDown)
620  {
621  _trackingPart = [self hitPart];
622 
623  _trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
624 
625  if ([anEvent modifierFlags] & CPAlternateKeyMask)
626  {
627  if (_trackingPart === CPScrollerDecrementLine)
628  _hitPart = CPScrollerDecrementPage;
629 
630  else if (_trackingPart === CPScrollerIncrementLine)
631  _hitPart = CPScrollerIncrementPage;
632 
633  else if (_trackingPart === CPScrollerDecrementPage || _trackingPart === CPScrollerIncrementPage)
634  {
635  var knobRect = [self rectForPart:CPScrollerKnob],
636  knobWidth = ![self isVertical] ? CGRectGetWidth(knobRect) : CGRectGetHeight(knobRect),
637  knobSlotRect = [self rectForPart:CPScrollerKnobSlot],
638  remainder = (![self isVertical] ? CGRectGetWidth(knobSlotRect) : CGRectGetHeight(knobSlotRect)) - knobWidth;
639 
640  [self setFloatValue:((![self isVertical] ? _trackingStartPoint.x - CGRectGetMinX(knobSlotRect) : _trackingStartPoint.y - CGRectGetMinY(knobSlotRect)) - knobWidth / 2.0) / remainder];
641 
642  _hitPart = CPScrollerKnob;
643 
644  [self sendAction:[self action] to:[self target]];
645 
646  // Now just track the knob.
647  return [self trackKnob:anEvent];
648  }
649  }
650 
651  [self highlight:YES];
652  [self sendAction:[self action] to:[self target]];
653 
655  }
656 
657  else if (type === CPLeftMouseDragged)
658  {
659  _trackingStartPoint = [self convertPoint:[anEvent locationInWindow] fromView:nil];
660 
661  if (_trackingPart === CPScrollerDecrementPage || _trackingPart === CPScrollerIncrementPage)
662  {
663  var hitPart = [self testPart:[anEvent locationInWindow]];
664 
665  if (hitPart === CPScrollerDecrementPage || hitPart === CPScrollerIncrementPage)
666  {
667  _trackingPart = hitPart;
668  _hitPart = hitPart;
669  }
670  }
671 
672  [self highlight:CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint)];
673  }
674  else if (type == CPPeriodic && CGRectContainsPoint([self rectForPart:_trackingPart], _trackingStartPoint))
675  [self sendAction:[self action] to:[self target]];
676 
677  [CPApp setTarget:self selector:@selector(trackScrollButtons:) forNextEventMatchingMask:CPPeriodicMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
678 
679 }
680 
681 - (void)_setIsVertical:(BOOL)isVertical
682 {
683  _isVertical = isVertical;
684 
685  if (_isVertical)
686  [self setThemeState:CPThemeStateVertical];
687  else
688  [self unsetThemeState:CPThemeStateVertical];
689 }
690 
691 - (void)setFrameSize:(CGSize)aSize
692 {
693  [super setFrameSize:aSize];
694 
695  [self checkSpaceForParts];
696  [self setNeedsLayout];
697 }
698 
699 
700 #pragma mark -
701 #pragma mark Overrides
702 
703 - (id)currentValueForThemeAttribute:(CPString)anAttributeName
704 {
705  var themeState = _themeState;
706 
707  if (NAMES_FOR_PARTS[_hitPart] + "-color" !== anAttributeName)
708  themeState = themeState.without(CPThemeStateHighlighted);
709 
710  return [self valueForThemeAttribute:anAttributeName inState:themeState];
711 }
712 
713 - (void)mouseDown:(CPEvent)anEvent
714 {
715  if (![self isEnabled])
716  return;
717 
718  _hitPart = [self testPart:[anEvent locationInWindow]];
719 
720  switch (_hitPart)
721  {
722  case CPScrollerKnob:
723  return [self trackKnob:anEvent];
724 
729  return [self trackScrollButtons:anEvent];
730  }
731 }
732 
733 - (void)mouseEntered:(CPEvent)anEvent
734 {
735  [super mouseEntered:anEvent];
736 
737  if (_timerFadeOut)
738  [_timerFadeOut invalidate];
739 
740  if (![self isEnabled])
741  return;
742 
743  _allowFadingOut = NO;
744  _isMouseOver = YES;
745 
746  if ([self alphaValue] > 0 && _knobProportion != 1.0)
747  [self setThemeState:CPThemeStateSelected];
748 }
749 
750 - (void)mouseExited:(CPEvent)anEvent
751 {
752  [super mouseExited:anEvent];
753 
754  if ([self isHidden] || ![self isEnabled] || !_isMouseOver)
755  return;
756 
757  _allowFadingOut = YES;
758  _isMouseOver = NO;
759 
760  if (_timerFadeOut)
761  [_timerFadeOut invalidate];
762 
763  _timerFadeOut = [CPTimer scheduledTimerWithTimeInterval:1.2 target:self selector:@selector(_performFadeOut:) userInfo:nil repeats:NO];
764 }
765 
766 
767 #pragma mark -
768 #pragma mark Delegates
769 
770 - (void)animationDidEnd:(CPAnimation)animation
771 {
772  [self unsetThemeState:CPThemeStateSelected];
773 }
774 
775 @end
776 
777 var CPScrollerIsVerticalKey = @"CPScrollerIsVerticalKey",
778  CPScrollerKnobProportionKey = @"CPScrollerKnobProportion",
779  CPScrollerStyleKey = @"CPScrollerStyleKey";
780 
781 @implementation CPScroller (CPCoding)
782 
783 - (id)initWithCoder:(CPCoder)aCoder
784 {
785  if (self = [super initWithCoder:aCoder])
786  {
787  _knobProportion = 1.0;
788 
789  if ([aCoder containsValueForKey:CPScrollerKnobProportionKey])
790  _knobProportion = [aCoder decodeFloatForKey:CPScrollerKnobProportionKey];
791 
792  _partRects = [];
793 
794  _hitPart = CPScrollerNoPart;
795 
796  _allowFadingOut = YES;
797  _isMouseOver = NO;
798 
799  var paramAnimFadeOut = @{
802  };
803 
804  _animationScroller = [[CPViewAnimation alloc] initWithDuration:0.2 animationCurve:CPAnimationEaseInOut];
805  [_animationScroller setViewAnimations:[paramAnimFadeOut]];
806  [_animationScroller setDelegate:self];
807  [self setAlphaValue:0.0];
808 
809  [self setStyle:[aCoder decodeIntForKey:CPScrollerStyleKey]];
810 
811  [self _setIsVertical:[aCoder decodeBoolForKey:CPScrollerIsVerticalKey]];
812  }
813 
814  return self;
815 }
816 
817 - (void)encodeWithCoder:(CPCoder)aCoder
818 {
819  [super encodeWithCoder:aCoder];
820 
821  [aCoder encodeInt:_isVertical forKey:CPScrollerIsVerticalKey];
822  [aCoder encodeFloat:_knobProportion forKey:CPScrollerKnobProportionKey];
823  [aCoder encodeInt:_style forKey:CPScrollerStyleKey];
824 }
825 
826 @end
827 
828 @implementation CPScroller (Deprecated)
829 
835 - (void)setFloatValue:(float)aValue knobProportion:(float)aProportion
836 {
837  [self setFloatValue:aValue];
838  [self setKnobProportion:aProportion];
839 }
840 
841 @end
842 
844 
848 - (BOOL)isVertical
849 {
850  return _isVertical;
851 }
852 
857 {
858  return _allowFadingOut;
859 }
860 
861 @end
var PARTS_FOR_NAMES
Definition: CPScroller.j:51
Used to implement exception handling (creating & raising).
Definition: CPException.h:2
CPThemeStateSelected
Definition: CPTheme.j:548
float scrollerWidthInStyle:(int aStyle)
Definition: CPScroller.j:132
void trackScrollButtons:(CPEvent anEvent)
Definition: CPScroller.j:605
BOOL isEnabled()
Definition: CPControl.j:970
void drawParts()
Definition: CPScroller.j:540
CPAllScrollerParts
Definition: CPScroller.j:47
BOOL setThemeState:(ThemeState aState)
Definition: CPView.j:3214
An object representation of nil.
Definition: CPNull.h:2
float scrollerWidth()
Definition: CPScroller.j:124
CPViewAnimationFadeOutEffect
void mouseExited:(CPEvent anEvent)
Definition: CPControl.j:512
float scrollerOverlay()
Definition: CPScroller.j:146
CPViewAnimationTargetKey
CPScrollerKnob
Definition: CPScroller.j:35
CGPoint locationInWindow()
Definition: CPEvent.j:290
float knobProportion()
Definition: CPScroller.j:244
CGRect rectForPart:(CPScrollerPart aPart)
Definition: CPScroller.j:294
int width
CPScrollerIncrementLine
Definition: CPScroller.j:38
CGRect bounds()
Definition: CPView.j:1302
CPScrollerDecrementPage
Definition: CPScroller.j:34
void raise:reason:(CPString aName, [reason] CPString aReason)
Definition: CPException.j:66
CPEventType type()
Definition: CPEvent.j:325
void fadeOut()
Definition: CPScroller.j:456
void layoutSubviews()
Definition: CPScroller.j:514
A mutable key-value pair collection.
Definition: CPDictionary.h:2
CPScrollerDecrementArrow
Definition: CPScroller.j:42
void style()
Definition: CPScroller.j:206
CPDictionary themeAttributes()
Definition: CPScroller.j:107
CPAlternateKeyMask
CPScrollerPart testPart:(CGPoint aPoint)
Definition: CPScroller.j:307
An immutable string (collection of characters).
Definition: CPString.h:2
CPNull null()
Definition: CPNull.j:51
CPOnlyScrollerArrows
Definition: CPScroller.j:46
CGPoint convertPoint:fromView:(CGPoint aPoint, [fromView] CPView aView)
Definition: CPView.j:2208
void stopPeriodicEvents()
Definition: CPEvent.j:598
void setStyle:(id aStyle)
Definition: CPScroller.j:215
CPScrollerKnobStyleDark
Definition: CPScroller.j:65
if(CPFeatureIsCompatible(CPHTMLCanvasFeature))
CPUsableScrollerParts CPNoScrollerParts
Definition: CPScroller.j:45
id initWithDuration:animationCurve:(float aDuration, [animationCurve] CPAnimationCurve anAnimationCurve)
Definition: CPAnimation.j:100
BOOL sendAction:to:(SEL anAction, [to] id anObject)
Definition: CPControl.j:319
CPScrollerIncrementArrow
Definition: CPScroller.j:41
SEL action()
Definition: CPControl.j:290
BOOL isVertical()
Definition: CPScroller.j:848
CPUsableScrollerParts usableParts()
Definition: CPScroller.j:434
void setFloatValue:(float aValue)
Definition: CPControl.j:554
var CPScrollerKnobProportionKey
Definition: CPScroller.j:778
void setNeedsDisplay:(BOOL aFlag)
Definition: CPView.j:2556
void setObjectValue:(id anObject)
Definition: CPControl.j:534
CPScrollerPart hitPart()
Definition: CPScroller.j:552
BOOL isHidden()
Definition: CPView.j:1697
CPString defaultThemeClass()
Definition: CPScroller.j:102
CPLeftMouseUp
CPScrollerDecrementLine
Definition: CPScroller.j:37
void setKnobProportion:(float aProportion)
Definition: CPScroller.j:253
CPTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:(CPTimeInterval seconds, [target] id aTarget, [selector] SEL aSelector, [userInfo] id userInfo, [repeats] BOOL shouldRepeat)
Definition: CPTimer.j:58
CPScrollerStyleLegacy
Definition: CPScroller.j:61
void setAlphaValue:(float anAlphaValue)
Definition: CPView.j:1724
void setNeedsLayout()
Definition: CPView.j:2707
void fadeIn()
Definition: CPScroller.j:442
CPThemeStateScrollerKnobLight
Definition: CPScroller.j:69
id target()
Definition: CPControl.j:308
void drawArrow:highlight:(CPScrollerArrow anArrow, [highlight] BOOL shouldHighlight)
Definition: CPScroller.j:473
global CPApp typedef CPScrollerPart CPScrollerNoPart
Definition: CPScroller.j:33
void highlight:(BOOL shouldHighlight)
Definition: CPControl.j:980
void trackKnob:(CPEvent anEvent)
Definition: CPScroller.j:561
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
CPLeftMouseDragged
Defines methods for use when archiving & restoring (enc/decoding).
Definition: CPCoder.h:2
CPThemeStateHighlighted
Definition: CPTheme.j:547
void mouseEntered:(CPEvent anEvent)
Definition: CPControl.j:504
BOOL unsetThemeState:(ThemeState aState)
Definition: CPView.j:3227
CPScrollerIncrementPage
Definition: CPScroller.j:36
var PARTS_ARRANGEMENT
Definition: CPScroller.j:49
CPLeftMouseDown
float alphaValue()
Definition: CPView.j:1750
void setFrameSize:(CGSize aSize)
Definition: CPView.j:1100
void drawKnobSlot()
Definition: CPScroller.j:487
CPThemeStateScrollViewLegacy
Definition: CPScroller.j:68
CPThemeStateScrollerKnobDark
Definition: CPScroller.j:70
Definition: CPEvent.h:2
void startPeriodicEventsAfterDelay:withPeriod:(CPTimeInterval aDelay, [withPeriod] CPTimeInterval aPeriod)
Definition: CPEvent.j:587
CPScrollerStyleOverlay
Definition: CPScroller.j:62
var CPScrollerStyleKey
Definition: CPScroller.j:779
CGRect frame()
Definition: CPView.j:1022
void checkSpaceForParts()
Definition: CPScroller.j:341
var NAMES_FOR_PARTS
Definition: CPScroller.j:50
void drawKnob()
Definition: CPScroller.j:480
void encodeWithCoder:(CPCoder aCoder)
Definition: CPControl.j:1114
CPScrollerKnobStyleDefault
Definition: CPScroller.j:64
var CPScrollerIsVerticalKey
Definition: CPScroller.j:777
CPViewAnimationEffectKey
CPView layoutEphemeralSubviewNamed:positioned:relativeToEphemeralSubviewNamed:(CPString aViewName, [positioned] CPWindowOrderingMode anOrderingMode, [relativeToEphemeralSubviewNamed] CPString relativeToViewName)
Definition: CPView.j:3366
id alloc()
Definition: CPObject.j:130
Definition: CPView.j:136
id currentValueForThemeAttribute:(CPString anAttributeName)
Definition: CPScroller.j:703
CPPeriodic