From df7fab7e032120c6360a2ee94116ea0f760f6b1a Mon Sep 17 00:00:00 2001 From: Ross Boucher Date: Thu, 16 Apr 2009 17:47:33 -0700 Subject: [PATCH] Add CPCircularSlider to CPSlider --- AppKit/CPSlider.j | 141 +++++++++++++----- AppKit/CPThemedAttribute.j | 2 + .../Aristo/Resources/CircularSliderBezel.png | Bin 0 -> 1374 bytes .../Aristo/Resources/CircularSliderKnob.png | Bin 0 -> 198 bytes AppKit/Themes/Aristo/ThemeDescriptors.j | 26 +++- 5 files changed, 132 insertions(+), 37 deletions(-) create mode 100644 AppKit/Themes/Aristo/Resources/CircularSliderBezel.png create mode 100644 AppKit/Themes/Aristo/Resources/CircularSliderKnob.png diff --git a/AppKit/CPSlider.j b/AppKit/CPSlider.j index efa3d9209..09a116037 100644 --- a/AppKit/CPSlider.j +++ b/AppKit/CPSlider.j @@ -24,28 +24,35 @@ #include "CoreGraphics/CGGeometry.h" +/*! SLIDER STATES */ + +CPLinearSlider = 0; +CPCircularSlider = 1; @implementation CPSlider : CPControl { double _minValue; double _maxValue; double _altIncrementValue; + int _sliderType; } + (id)themedAttributes { - return [CPDictionary dictionaryWithObjects:[nil, _CGSizeMakeZero(), 0.0, nil, nil] - forKeys:[@"knob-color", @"knob-size", @"track-width", @"vertical-track-color", @"horizontal-track-color"]]; + return [CPDictionary dictionaryWithObjects:[nil, _CGSizeMakeZero(), 0.0, nil] + forKeys:[@"knob-color", @"knob-size", @"track-width", @"track-color"]]; } - (id)initWithFrame:(CGRect)aFrame { self = [super initWithFrame:aFrame]; - + if (self) { _minValue = 0.0; _maxValue = 100.0; + + _sliderType = CPLinearSlider; [self setObjectValue:50.0]; @@ -99,6 +106,26 @@ [self setNeedsDisplay:YES]; } +- (void)setSliderType:(CPSliderType)sliderType +{ + if (sliderType === _sliderType) + return; + + _sliderType = sliderType; + + if (_sliderType === CPCircularSlider) + _controlState |= CPControlStateCircular; + else + _controlState &= ~CPControlStateCircular; + + [self setNeedsLayout]; +} + +- (CPSliderType)sliderType +{ + return _sliderType; +} + - (CGRect)trackRectForBounds:(CGRect)bounds { var trackWidth = [self currentValueForThemedAttributeName:@"track-width"]; @@ -106,15 +133,30 @@ if (trackWidth <= 0) return _CGRectMakeZero(); - if ([self isVertical]) + if ([self sliderType] === CPLinearSlider) { - bounds.origin.x = (_CGRectGetWidth(bounds) - trackWidth) / 2.0; - bounds.size.width = trackWidth; + if ([self isVertical]) + { + bounds.origin.x = (_CGRectGetWidth(bounds) - trackWidth) / 2.0; + bounds.size.width = trackWidth; + } + else + { + bounds.origin.y = (_CGRectGetHeight(bounds) - trackWidth) / 2.0; + bounds.size.height = trackWidth; + } } else { - bounds.origin.y = (_CGRectGetHeight(bounds) - trackWidth) / 2.0; - bounds.size.height = trackWidth; + var originalBounds = CGRectCreateCopy(bounds); + + bounds.size.width = MIN(bounds.size.width, bounds.size.height); + bounds.size.height = bounds.size.width; + + if (bounds.size.width < originalBounds.size.width) + bounds.origin.x += (originalBounds.size.width - bounds.size.width) / 2.0; + else + bounds.origin.y += (originalBounds.size.height - bounds.size.height) / 2.0; } return bounds; @@ -134,17 +176,28 @@ if (!trackRect || _CGRectIsEmpty(trackRect)) trackRect = bounds; - if ([self isVertical]) + if ([self sliderType] === CPLinearSlider) { - knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0; - knobRect.origin.y = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height); + if ([self isVertical]) + { + knobRect.origin.x = _CGRectGetMidX(trackRect) - knobSize.width / 2.0; + knobRect.origin.y = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetHeight(trackRect) - knobSize.height); + } + else + { + knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetWidth(trackRect) - knobSize.width); + knobRect.origin.y = _CGRectGetMidY(trackRect) - knobSize.height / 2.0; + } } else { - knobRect.origin.x = (([self doubleValue] - _minValue) / (_maxValue - _minValue)) * (_CGRectGetWidth(trackRect) - knobSize.width); - knobRect.origin.y = _CGRectGetMidY(trackRect) - knobSize.height / 2.0; + var angle = 3*PI_2 - ([self doubleValue] - _minValue) / (_maxValue - _minValue) * PI2, + radius = CGRectGetWidth(trackRect) / 2.0 - 6.0; + + knobRect.origin.x = radius * COS(angle) + CGRectGetMidX(trackRect) - 3.0; + knobRect.origin.y = radius * SIN(angle) + CGRectGetMidY(trackRect) - 2.0; } - + return knobRect; } @@ -200,9 +253,9 @@ if (trackView) if ([self isVertical]) - [trackView setBackgroundColor:[self currentValueForThemedAttributeName:@"vertical-track-color"]]; + [trackView setBackgroundColor:[self currentValueForThemedAttributeName:@"track-color"]]; else - [trackView setBackgroundColor:[self currentValueForThemedAttributeName:@"horizontal-track-color"]]; + [trackView setBackgroundColor:[self currentValueForThemedAttributeName:@"track-color"]]; var knobView = [self layoutEphemeralSubviewNamed:@"knob-view" positioned:CPWindowAbove @@ -223,27 +276,44 @@ knobRect = [self knobRectForBounds:bounds], trackRect = [self trackRectForBounds:bounds]; - if ([self isVertical]) + if ([self sliderType] === CPLinearSlider) { - var knobHeight = _CGRectGetHeight(knobRect); - - trackRect.origin.y += knobHeight / 2; - trackRect.size.height -= knobHeight; - - var minValue = [self minValue]; - - return MAX(0.0, MIN(1.0, (aPoint.y - _CGRectGetMinY(trackRect)) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue; + if ([self isVertical]) + { + var knobHeight = _CGRectGetHeight(knobRect); + + trackRect.origin.y += knobHeight / 2; + trackRect.size.height -= knobHeight; + + var minValue = [self minValue]; + + return MAX(0.0, MIN(1.0, (aPoint.y - _CGRectGetMinY(trackRect)) / _CGRectGetHeight(trackRect))) * ([self maxValue] - minValue) + minValue; + } + else + { + var knobWidth = _CGRectGetWidth(knobRect); + + trackRect.origin.x += knobWidth / 2; + trackRect.size.width -= knobWidth; + + var minValue = [self minValue]; + + return MAX(0.0, MIN(1.0, (aPoint.x - _CGRectGetMinX(trackRect)) / _CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue; + } } else + { + var knobWidth = _CGRectGetWidth(knobRect); - var knobWidth = _CGRectGetWidth(knobRect); - - trackRect.origin.x += knobWidth / 2; - trackRect.size.width -= knobWidth; - - var minValue = [self minValue]; - - return MAX(0.0, MIN(1.0, (aPoint.x - _CGRectGetMinX(trackRect)) / _CGRectGetWidth(trackRect))) * ([self maxValue] - minValue) + minValue; + trackRect.origin.x += knobWidth / 2; + trackRect.size.width -= knobWidth; + + var minValue = [self minValue], + dx = aPoint.x - _CGRectGetMidX(trackRect), + dy = aPoint.y - _CGRectGetMidY(trackRect); + + return MAX(0.0, MIN(1.0, (3*PI_2 - ATAN2(dy, dx))%PI2 / PI2)) * ([self maxValue] - minValue) + minValue; + } } - (BOOL)startTrackingAt:(CGPoint)aPoint @@ -311,7 +381,8 @@ var CPSliderMinValueKey = "CPSliderMinValueKey", CPSliderMaxValueKey = "CPSliderMaxValueKey", - CPSliderAltIncrValueKey = "CPSliderAltIncrValueKey"; + CPSliderAltIncrValueKey = "CPSliderAltIncrValueKey", + CPSliderTypeKey = "CPSliderTypeKey"; @implementation CPSlider (CPCoding) @@ -326,6 +397,7 @@ var CPSliderMinValueKey = "CPSliderMinValueKey", { _altIncrementValue = [aCoder decodeDoubleForKey:CPSliderAltIncrValueKey]; + [self setSliderType:[aCoder decodeIntForkey:CPSliderTypeKey]]; [self setContinuous:YES]; [self setNeedsLayout]; @@ -342,6 +414,7 @@ var CPSliderMinValueKey = "CPSliderMinValueKey", [aCoder encodeDouble:_minValue forKey:CPSliderMinValueKey]; [aCoder encodeDouble:_maxValue forKey:CPSliderMaxValueKey]; [aCoder encodeDouble:_altIncrementValue forKey:CPSliderAltIncrValueKey]; + [aCoder encodeInt:_sliderType forKey:CPSliderTypeKey]; } @end diff --git a/AppKit/CPThemedAttribute.j b/AppKit/CPThemedAttribute.j index a572aeb1a..e25590412 100644 --- a/AppKit/CPThemedAttribute.j +++ b/AppKit/CPThemedAttribute.j @@ -12,6 +12,8 @@ CPControlStateBezeled = 1 << 5, CPControlStateVertical = 1 << 6, CPControlStateEditable = 1 << 7, CPControlStateEditing = 1 << 8; +CPControlStateHorizontal = 1 << 9; +CPControlStateCircular = 1 << 10; var BIT_COUNT = [ 0 /*00000*/, 1 /*00001*/, 1 /*00010*/, 2 /*00011*/, 1 /*00100*/, 2 /*00101*/, 2 /*00110*/, 3 /*00111*/, 1 /*01000*/, 2 /*01001*/, 2 /*01010*/, 3 /*01011*/, 2 /*01100*/, 3 /*01101*/, 3 /*01110*/, 4 /*01111*/, diff --git a/AppKit/Themes/Aristo/Resources/CircularSliderBezel.png b/AppKit/Themes/Aristo/Resources/CircularSliderBezel.png new file mode 100644 index 0000000000000000000000000000000000000000..fca36e39e512bcbfea5255745ba4a708f860a2df GIT binary patch literal 1374 zcmV-k1)=(hP)H6F)RrZC?q2Bf&h}y21x{B9Ksqb7+@S2 zn1Lyqz(ize3*GDUo=}3a$Pik;&lxl9H0AqobqOda-0=WaP>R($mxV-rnA_ zprD|tz`($};o;#dARvI@Gm}UpBFG4{*~}~!3)|h@WhRqp8Q;HZZ*OlcFE6)VDPVYb z_`(|*85vx6cXwK3WMo53OiU`k6bc1%I-Lxbia5LA6;TY&^X&Nem~C%wvyF|7XNQM} zpWMHHUk4uNg#w0#hR$8g%*+&YI$c#rNXX~O$;n(qLvh1cvQkTU%Rf zZEdZkxVZRZaM{nrfa_l|@b0~P!VfxKjV2|fJQh~d%gD8_vdBvWKR-W~l$69|a`}fp z_Vp=YSlKU+9{ocE=Y~}tfSm8>=y;H%R+q=c#)=jrxK3UEs-WMJ`1m__m^v}>eFX6r zWZ+p&&hv0qRu-q#YBQBeWi7d!eoVo28?aifEGjCBB_<|TwzajDfs6O>o(jm#%~iz3 z#WktbYANmCO|8BPFpfn>N7oe<6-DIareL_ zS%s|#EG#U1Ps~^;YT0Rl?6g5xAU6Cm~g2@^CLO)v@Iu`gmeQu*}NB0hLRN&=YGW;;f+QE*~R zdVf(M+U$1M+}zv|32>Q=#;v2Hqi75nJ`q6u!E7?^P~Rc}j{W`p6$}umn09<3fQFZY zgM(G#CZF332E(to;PoQp0SsoFo11##CIJ>qK0jlEIi#-T?IJ{hjv>W9I5^lx+@c3C zLjC#d`SYK)Fh+UX`i;#^_QGHoT3A?kAqr?|ZKd2h`2OL;ZO=+3M=5 zwX3tU8JvHKF>q3R%($^MF){Hq4U;yT%_{=_z8Z+FdsSx1_qAFO-PlM->`3J z8va&`MTIElX*VlN(9B+H4szP{dlmQPYw zS9hTm6%`e9@C*c$K)k=de>{$BZ)0js#Y~rg@1fY5Krw1!(L9QPkAJ^~g z?a^MZp9Gu9o#Z!RpHhvY g9UPaQl>ZiB05}B4xj&7hQ~&?~07*qoM6N<$f??Z-d;kCd literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/Resources/CircularSliderKnob.png b/AppKit/Themes/Aristo/Resources/CircularSliderKnob.png new file mode 100644 index 0000000000000000000000000000000000000000..5c5164fe6f2b917c45b1996c9be8754d107fa889 GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G8J;eVAr-fhLV|-QKYQ|I&aq?1o_&0MeZB1c{q^UQ1Vu&X z>Z__gJ$3l-;SXP5hwoqRKmXHa4{z`2Q>RZGGlT+>p@ET6lo4a73_ItB4I3I%9cq^8 t$M0M6=f}t7M1Fx;0?XW`?MTMD$3!PC{xWt~$(695)oNUZ<> literal 0 HcmV?d00001 diff --git a/AppKit/Themes/Aristo/ThemeDescriptors.j b/AppKit/Themes/Aristo/ThemeDescriptors.j index 990e018da..648c13180 100644 --- a/AppKit/Themes/Aristo/ThemeDescriptors.j +++ b/AppKit/Themes/Aristo/ThemeDescriptors.j @@ -7,7 +7,7 @@ */ @import - +@import @implementation AristoThemeDescriptor : CPObject { @@ -315,7 +315,7 @@ isVertical:NO]]; [slider setValue:5.0 forThemedAttributeName:@"track-width"]; - [slider setValue:trackColor forThemedAttributeName:@"horizontal-track-color"]; + [slider setValue:trackColor forThemedAttributeName:@"track-color"]; var knobColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob.png" size:CGSizeMake(23.0, 24.0)]]; knobHighlightedColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob-highlighted.png" size:CGSizeMake(23.0, 24.0)]]; @@ -339,7 +339,7 @@ isVertical:YES]]; [slider setValue:5.0 forThemedAttributeName:@"track-width"]; - [slider setValue:trackColor forThemedAttributeName:@"vertical-track-color"]; + [slider setValue:trackColor forThemedAttributeName:@"track-color"]; var knobColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob.png" size:CGSizeMake(23.0, 24.0)]]; knobHighlightedColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"knob-highlighted.png" size:CGSizeMake(23.0, 24.0)]]; @@ -350,6 +350,26 @@ return slider; } + ++ (CPSlider)themedCircularSlider +{ + var slider = [[CPSlider alloc] initWithFrame:CGRectMake(0.0, 0.0, 32.0, 32.0)], + trackColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"circularSliderBezel.png" size:CGSizeMake(32.0, 32.0)]]; + + [slider setSliderType:CPCircularSlider]; + [slider setValue:trackColor forThemedAttributeName:@"track-color" inControlState:CPControlStateCircular]; + [slider setValue:trackColor forThemedAttributeName:@"track-color" inControlState:CPControlStateCircular|CPControlStateVertical]; + + var knobColor = [CPColor colorWithPatternImage:[_CPCibCustomResource imageResourceWithName:"circularSliderKnob.png" size:CGSizeMake(5.0, 5.0)]], + knobHighlightedColor = knobColor; + + [slider setValue:CGSizeMake(5.0, 5.0) forThemedAttributeName:@"knob-size" inControlState:CPControlStateCircular]; + [slider setValue:knobColor forThemedAttributeName:@"knob-color" inControlState:CPControlStateCircular]; + [slider setValue:knobHighlightedColor forThemedAttributeName:@"knob-color" inControlState:CPControlStateCircular|CPControlStateHighlighted]; + + return slider; +} + /* var buttonBar = [[CPButtonBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 100.0, 30.0)], color = [CPColor colorWithPatternImage:[[CPThreePartImage alloc] initWithImageSlices: