43 CPSegmentSwitchTracking _trackingMode;
45 unsigned _trackingSegment;
46 BOOL _trackingHighlighted;
51 return "segmented-control";
56 return [
CPDictionary dictionaryWithObjects:[CPCenterTextAlignment, CPCenterVerticalTextAlignment, CPImageLeft, CPImageScaleNone, _CGInsetMakeZero(), _CGInsetMakeZero(), [
CPNull null], [
CPNull null], [
CPNull null], [
CPNull null], 1.0, 24.0]
57 forKeys:[@"alignment", @"vertical-alignment", @"image-position", @"image-scaling", @"bezel-inset", @"content-inset", @"left-segment-bezel-color", @"right-segment-bezel-color", @"center-segment-bezel-color", @"divider-bezel-color", @"divider-thickness", @"default-height"]];
60 - (id)initWithFrame:(CGRect)aRect
69 _selectedSegment = -1;
82 return [_segments[_selectedSegment] tag];
90 - (void)setSegmentCount:(
unsigned)aCount
92 if (_segments.length == aCount)
95 var height = CGRectGetHeight([
self bounds]),
96 dividersBefore = MAX(0, _segments.length - 1),
97 dividersAfter = MAX(0, aCount - 1);
99 if (_segments.length < aCount)
101 for (var index = _segments.length; index < aCount; ++index)
103 _segments[index] = [[_CPSegmentItem alloc] init];
107 else if (aCount < _segments.length)
109 _segments.length = aCount;
110 _themeStates.length = aCount;
113 if (_selectedSegment >= _segments.length)
114 _selectedSegment = -1;
118 widthOfAllSegments = 0,
119 dividerExtraSpace = ([_segments count] - 1) * thickness;
121 for (var i = 0; i < [_segments count]; i++)
122 widthOfAllSegments += [_segments[i]
width];
124 [
self setFrameSize:CGSizeMake(widthOfAllSegments + dividerExtraSpace, frame.size.height)];
132 - (unsigned)segmentCount
134 return _segments.length;
143 - (void)setSelectedSegment:(
unsigned)aSegment
152 - (unsigned)selectedSegment
154 return _selectedSegment;
160 - (BOOL)selectSegmentWithTag:(
int)aTag
164 for (; index < _segments.length; ++index)
165 if (_segments[index].
tag == aTag)
182 - (void)setTrackingMode:(CPSegmentSwitchTracking)aTrackingMode
184 if (_trackingMode == aTrackingMode)
187 _trackingMode = aTrackingMode;
194 for (; index < _segments.length; ++index)
206 for (; index < _segments.length; ++index)
215 - (CPSegmentSwitchTracking)trackingMode
217 return _trackingMode;
227 - (void)setWidth:(
float)aWidth forSegment:(
unsigned)aSegment
229 [_segments[aSegment] setWidth:aWidth];
239 - (float)widthForSegment:(
unsigned)aSegment
241 return [_segments[aSegment] width];
250 - (void)setImage:(
CPImage)anImage forSegment:(
unsigned)aSegment
252 [_segments[aSegment] setImage:anImage];
264 return [_segments[aSegment] image];
273 - (void)setLabel:(
CPString)aLabel forSegment:(
unsigned)aSegment
275 [_segments[aSegment] setLabel:aLabel];
287 return [_segments[aSegment] label];
296 - (void)setMenu:(
CPMenu)aMenu forSegment:(
unsigned)aSegment
298 [_segments[aSegment] setMenu:aMenu];
306 - (
CPMenu)menuForSegment:(
unsigned)aSegment
308 return [_segments[aSegment] menu];
318 - (void)setSelected:(BOOL)isSelected forSegment:(
unsigned)aSegment
320 var segment = _segments[aSegment];
323 if ([segment
selected] == isSelected)
326 [segment setSelected:isSelected];
333 var oldSelectedSegment = _selectedSegment;
335 _selectedSegment = aSegment;
339 [_segments[oldSelectedSegment] setSelected:NO];
358 - (BOOL)isSelectedForSegment:(
unsigned)aSegment
360 return [_segments[aSegment] selected];
369 - (void)setEnabled:(BOOL)shouldBeEnabled forSegment:(
unsigned)aSegment
371 if ([_segments[aSegment]
enabled] === shouldBeEnabled)
374 [_segments[aSegment] setEnabled:shouldBeEnabled];
390 - (BOOL)isEnabledForSegment:(
unsigned)aSegment
392 return [_segments[aSegment] enabled];
400 - (void)setTag:(
int)aTag forSegment:(
unsigned)aSegment
402 [_segments[aSegment] setTag:aTag];
409 - (int)tagForSegment:(
unsigned)aSegment
411 return [_segments[aSegment] tag];
420 - (void)drawSegmentBezel:(
int)aSegment highlight:(BOOL)shouldHighlight
431 - (float)_leftOffsetForSegment:(
unsigned)segment
433 var bezelInset = [
self currentValueForThemeAttribute:@"bezel-inset"];
436 return bezelInset.left;
438 var thickness = [
self currentValueForThemeAttribute:@"divider-thickness"];
440 return [
self _leftOffsetForSegment:segment - 1] + [self widthForSegment:segment - 1] + thickness;
443 - (unsigned)_indexOfLastSegment
445 var lastSegmentIndex = [_segments count] - 1;
447 if (lastSegmentIndex < 0)
448 lastSegmentIndex = 0;
450 return lastSegmentIndex;
453 - (CGRect)rectForEphemeralSubviewNamed:(
CPString)aName
460 if (aName ===
"left-segment-bezel")
462 return CGRectMake(bezelInset.left, bezelInset.top, contentInset.left, height);
464 else if (aName ===
"right-segment-bezel")
466 return CPRectMake(CGRectGetWidth([
self bounds]) - contentInset.right,
471 else if (aName.indexOf(
"segment-bezel") === 0)
473 var segment = parseInt(aName.substring(
"segment-bezel-".length), 10),
474 frame = CGRectCreateCopy([_segments[segment]
frame]);
478 frame.origin.x += contentInset.left;
479 frame.size.width -= contentInset.left;
482 if (segment === _segments.length - 1)
483 frame.size.width = CGRectGetWidth([
self bounds]) - contentInset.right - frame.origin.x;
487 else if (aName.indexOf(
"divider-bezel") === 0)
489 var segment = parseInt(aName.substring(
"divider-bezel-".length), 10),
490 width = [
self widthForSegment:segment],
491 left = [
self _leftOffsetForSegment:segment],
492 thickness = [
self currentValueForThemeAttribute:
@"divider-thickness"];
494 return CGRectMake(left +
width, bezelInset.top, thickness, height);
496 else if (aName.indexOf(
"segment-content") === 0)
498 var segment = parseInt(aName.substring(
"segment-content-".length), 10);
508 if ([aName hasPrefix:
@"segment-content"])
509 return [[_CPImageAndTextView alloc] initWithFrame:_CGRectMakeZero()];
511 return [[
CPView alloc] initWithFrame:_CGRectMakeZero()];
514 - (void)layoutSubviews
516 if (_segments.length <= 0)
519 var themeState = _themeStates[0];
530 [leftBezelView setBackgroundColor:leftCapColor];
532 var themeState = _themeStates[_themeStates.length - 1];
543 [rightBezelView setBackgroundColor:rightCapColor];
545 for (var i = 0, count = _themeStates.length; i < count; i++)
547 var themeState = _themeStates[i];
558 [bezelView setBackgroundColor:bezelColor];
562 var segment = _segments[i],
567 [contentView setText:[segment label]];
568 [contentView setImage:[segment image]];
579 if ([segment image] && [segment
label])
581 else if ([segment image])
582 [contentView setImagePosition:CPImageOnly];
587 var borderState = _themeStates[i] | _themeStates[i + 1];
600 [borderView setBackgroundColor:borderColor];
610 - (void)drawSegment:(
int)aSegment highlight:(BOOL)shouldHighlight
614 - (void)tileWithChangedSegment:(
unsigned)aSegment
616 if (aSegment >= _segments.length)
619 var segment = _segments[aSegment],
620 segmentWidth = [segment width],
622 contentInset = [
self valueForThemeAttribute:
@"content-inset" inState:themeState],
627 if ([segment image] && [segment
label])
628 segmentWidth = [[segment label] sizeWithFont:font].width + [[segment image] size].width + contentInset.left + contentInset.right;
629 else if (segment.image)
630 segmentWidth = [[segment image] size].width + contentInset.left + contentInset.right;
631 else if (segment.label)
632 segmentWidth = [[segment label] sizeWithFont:font].width + contentInset.left + contentInset.right;
637 var delta = segmentWidth - CGRectGetWidth([segment
frame]);
650 [
self setFrameSize:CGSizeMake(CGRectGetWidth(frame) + delta, CGRectGetHeight(frame))];
653 [segment setWidth:segmentWidth];
657 var index = aSegment + 1;
659 for (; index < _segments.length; ++index)
661 [_segments[index] frame].origin.x += delta;
678 - (CGRect)frameForSegment:(
unsigned)aSegment
683 - (CGRect)bezelFrameForSegment:(
unsigned)aSegment
688 left = [
self _leftOffsetForSegment:aSegment];
690 return CGRectMake(left, bezelInset.top,
width, height);
693 - (CGRect)contentFrameForSegment:(
unsigned)aSegment
698 left = [
self _leftOffsetForSegment:aSegment];
700 return CGRectMake(left + contentInset.left, contentInset.top,
width - contentInset.left - contentInset.right, height - contentInset.top - contentInset.bottom);
708 - (unsigned)testSegment:(CGPoint)aPoint
711 count = _segments.length;
714 if (CGRectContainsPoint([_segments[count]
frame], aPoint))
717 if (_segments.length)
719 var adjustedLastFrame = CGRectCreateCopy([_segments[_segments.length - 1]
frame]);
720 adjustedLastFrame.size.width = CGRectGetWidth([
self bounds]) - adjustedLastFrame.origin.x;
722 if (CGRectContainsPoint(adjustedLastFrame, aPoint))
723 return _segments.length - 1;
731 if (![
self isEnabled])
748 var type = [anEvent
type],
753 if (_trackingSegment == -1)
756 if (_trackingSegment === [
self testSegment:location])
763 _selectedSegment = _trackingSegment;
774 _selectedSegment = -1;
780 _trackingSegment = -1;
788 if (trackingSegment > -1 && [
self isEnabledForSegment:trackingSegment])
790 _trackingHighlighted = YES;
791 _trackingSegment = trackingSegment;
798 if (_trackingSegment == -1)
801 var highlighted = [
self testSegment:location] === _trackingSegment;
802 if (highlighted != _trackingHighlighted)
804 _trackingHighlighted = highlighted;
810 [CPApp setTarget:self selector:@selector(trackSegment:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
836 originalWidth = frame.size.width;
838 frame.size.width = 0;
842 _segments = [aCoder decodeObjectForKey:CPSegmentedControlSegmentsKey];
843 _segmentStyle = [aCoder decodeIntForKey:CPSegmentedControlSegmentStyleKey];
847 _selectedSegment = [aCoder decodeIntForKey:CPSegmentedControlSelectedKey];
849 _selectedSegment = -1;
852 _trackingMode = [aCoder decodeIntForKey:CPSegmentedControlTrackingModeKey];
858 for (var i = 0; i < _segments.length; i++)
864 var difference = MAX(originalWidth - [
self frame].size.width, 0.0),
865 remainingWidth = FLOOR(difference / _segments.length);
867 for (var i = 0; i < _segments.length; i++)
868 [
self setWidth:[_segments[i]
width] + remainingWidth forSegment:i];
880 [aCoder encodeObject:_segments forKey:CPSegmentedControlSegmentsKey];
881 [aCoder encodeInt:_selectedSegment forKey:CPSegmentedControlSelectedKey];
882 [aCoder encodeInt:_segmentStyle forKey:CPSegmentedControlSegmentStyleKey];
883 [aCoder encodeInt:_trackingMode forKey:CPSegmentedControlTrackingModeKey];
889 @implementation _CPSegmentItem :
CPObject
904 if (
self = [super init])
914 frame = CGRectMakeZero();
929 @implementation _CPSegmentItem (CPCoding)
931 - (id)initWithCoder:(
CPCoder)aCoder
937 image = [aCoder decodeObjectForKey:CPSegmentItemImageKey];
938 label = [aCoder decodeObjectForKey:CPSegmentItemLabelKey];
939 menu = [aCoder decodeObjectForKey:CPSegmentItemMenuKey];
940 selected = [aCoder decodeBoolForKey:CPSegmentItemSelectedKey];
941 enabled = [aCoder decodeBoolForKey:CPSegmentItemEnabledKey];
942 tag = [aCoder decodeIntForKey:CPSegmentItemTagKey];
943 width = [aCoder decodeFloatForKey:CPSegmentItemWidthKey];
945 frame = CGRectMakeZero();
951 - (void)encodeWithCoder:(
CPCoder)aCoder
953 [aCoder encodeObject:image forKey:CPSegmentItemImageKey];
954 [aCoder encodeObject:label forKey:CPSegmentItemLabelKey];
955 [aCoder encodeObject:menu forKey:CPSegmentItemMenuKey];
956 [aCoder encodeBool:selected forKey:CPSegmentItemSelectedKey];
957 [aCoder encodeBool:enabled forKey:CPSegmentItemEnabledKey];
958 [aCoder encodeInt:tag forKey:CPSegmentItemTagKey];
959 [aCoder encodeFloat:width forKey:CPSegmentItemWidthKey];