38 double _altIncrementValue;
54 @"knob-size": CGSizeMakeZero(),
60 - (id)initWithFrame:(CGRect)aFrame
73 [
self _recalculateIsVertical];
79 - (void)setMinValue:(
float)aMinimumValue
81 if (_minValue === aMinimumValue)
84 _minValue = aMinimumValue;
88 if (doubleValue < _minValue)
101 - (void)setMaxValue:(
float)aMaximumValue
103 if (_maxValue === aMaximumValue)
106 _maxValue = aMaximumValue;
110 if (doubleValue > _maxValue)
123 - (void)setObjectValue:(
id)aValue
131 - (void)setSliderType:(CPSliderType)aSliderType
139 - (CPSliderType)sliderType
144 - (CGRect)trackRectForBounds:(CGRect)bounds
148 var originalBounds = CGRectCreateCopy(
bounds);
153 if (
bounds.size.width < originalBounds.size.width)
154 bounds.origin.x += (originalBounds.size.width -
bounds.size.width) / 2.0;
156 bounds.origin.y += (originalBounds.size.height -
bounds.size.height) / 2.0;
160 var trackWidth = [
self currentValueForThemeAttribute:@"track-width"];
163 return CGRectMakeZero();
165 if ([
self isVertical])
167 bounds.origin.x = (CGRectGetWidth(
bounds) - trackWidth) / 2.0;
168 bounds.size.width = trackWidth;
172 bounds.origin.y = (CGRectGetHeight(
bounds) - trackWidth) / 2.0;
173 bounds.size.height = trackWidth;
180 - (CGRect)knobRectForBounds:(CGRect)bounds
182 var knobSize = [
self currentValueForThemeAttribute:@"knob-size"];
184 if (knobSize.width <= 0 || knobSize.height <= 0)
185 return CGRectMakeZero();
187 var knobRect = CGRectMake(0.0, 0.0, knobSize.width, knobSize.height),
191 if (!trackRect || CGRectIsEmpty(trackRect))
196 var angle = 3 * PI_2 - (1.0 - [
self doubleValue] - _minValue) / (_maxValue - _minValue) * PI2,
197 radius = CGRectGetWidth(trackRect) / 2.0 - 8.0;
199 knobRect.origin.x = radius * COS(angle) + CGRectGetMidX(trackRect) - 3.0;
200 knobRect.origin.y = radius * SIN(angle) + CGRectGetMidY(trackRect) - 2.0;
202 else if ([
self isVertical])
204 knobRect.origin.x = CGRectGetMidX(trackRect) - knobSize.width / 2.0;
205 knobRect.origin.y = ((_maxValue - [
self doubleValue]) / (_maxValue - _minValue)) * (CGRectGetHeight(trackRect) - knobSize.height);
209 knobRect.origin.x = (([
self doubleValue] - _minValue) / (_maxValue - _minValue)) * (CGRectGetWidth(trackRect) - knobSize.width);
210 knobRect.origin.y = CGRectGetMidY(trackRect) - knobSize.height / 2.0;
216 - (CGRect)rectForEphemeralSubviewNamed:(
CPString)aName
218 if (aName ===
"track-view")
221 else if (aName ===
"knob-view")
229 if (aName ===
"track-view" || aName ===
"knob-view")
231 var view = [[
CPView alloc] init];
233 [view setHitTests:NO];
241 - (void)setAltIncrementValue:(
float)anAltIncrementValue
243 _altIncrementValue = anAltIncrementValue;
246 - (float)altIncrementValue
248 return _altIncrementValue;
251 - (void)setFrameSize:(CGSize)aSize
254 [
self _recalculateIsVertical];
257 - (void)_recalculateIsVertical
260 var
bounds = [
self bounds],
262 height = CGRectGetHeight(
bounds);
264 _isVertical = width < height ? 1 : (width > height ? 0 : -1);
266 if (_isVertical === 1)
267 [
self setThemeState:CPThemeStateVertical];
268 else if (_isVertical === 0)
269 [
self unsetThemeState:CPThemeStateVertical];
277 - (void)layoutSubviews
284 [trackView setBackgroundColor:[
self currentValueForThemeAttribute:@"track-color"]];
291 [knobView setBackgroundColor:[
self currentValueForThemeAttribute:"knob-color"]];
294 - (BOOL)tracksMouseOutsideOfFrame
299 - (float)_valueAtPoint:(CGPoint)aPoint
301 var
bounds = [
self bounds],
302 knobRect = [
self knobRectForBounds:bounds],
303 trackRect = [
self trackRectForBounds:bounds];
307 var knobWidth = CGRectGetWidth(knobRect);
309 trackRect.origin.x += knobWidth / 2;
310 trackRect.size.width -= knobWidth;
312 var minValue = [
self minValue],
313 dx = aPoint.x - CGRectGetMidX(trackRect),
314 dy = aPoint.y - CGRectGetMidY(trackRect);
316 return MAX(0.0, MIN(1.0, 1.0 - (3 * PI_2 - ATAN2(dy, dx)) % PI2 / PI2)) * ([
self maxValue] - minValue) + minValue;
318 else if ([
self isVertical])
320 var knobHeight = CGRectGetHeight(knobRect);
322 trackRect.origin.y += knobHeight / 2;
323 trackRect.size.height -= knobHeight;
325 var minValue = [
self minValue];
327 return MAX(0.0, MIN(1.0, (CGRectGetMaxY(trackRect) - aPoint.y) / CGRectGetHeight(trackRect))) * ([
self maxValue] - minValue) + minValue;
331 var knobWidth = CGRectGetWidth(knobRect);
333 trackRect.origin.x += knobWidth / 2;
334 trackRect.size.width -= knobWidth;
336 var minValue = [
self minValue];
338 return MAX(0.0, MIN(1.0, (aPoint.x - CGRectGetMinX(trackRect)) / CGRectGetWidth(trackRect))) * ([
self maxValue] - minValue) + minValue;
342 - (BOOL)startTrackingAt:(CGPoint)aPoint
347 if (CGRectContainsPoint(knobRect, aPoint))
348 _dragOffset = CGSizeMake(CGRectGetMidX(knobRect) - aPoint.x, CGRectGetMidY(knobRect) - aPoint.y);
353 if (trackRect && CGRectContainsPoint(trackRect, aPoint))
355 _dragOffset = CGSizeMakeZero();
372 - (BOOL)continueTracking:(CGPoint)lastPoint at:(CGPoint)aPoint
374 [
self setObjectValue:[
self _valueAtPoint:CGPointMake(aPoint.x + _dragOffset.width, aPoint.y + _dragOffset.height)]];
379 - (void)stopTracking:(CGPoint)lastPoint at:(CGPoint)aPoint mouseIsUp:(BOOL)mouseIsUp
383 if ([_target respondsToSelector:
@selector(sliderDidFinish:)])
384 [_target sliderDidFinish:self];
399 - (void)setContinuous:(BOOL)flag
407 - (void)takeValueFromKeyPath:(
CPString)aKeyPath ofObjects:(CPArray)objects
409 var count = objects.
length,
410 value = [objects[0] valueForKeyPath:aKeyPath];
415 if (value !== ([objects[count] valueForKeyPath:aKeyPath]))
429 _minValue = [aCoder decodeDoubleForKey:CPSliderMinValueKey];
430 _maxValue = [aCoder decodeDoubleForKey:CPSliderMaxValueKey];
436 _altIncrementValue = [aCoder decodeDoubleForKey:CPSliderAltIncrValueKey];
438 [
self _recalculateIsVertical];
451 [aCoder encodeDouble:_minValue forKey:CPSliderMinValueKey];
452 [aCoder encodeDouble:_maxValue forKey:CPSliderMaxValueKey];
453 [aCoder encodeDouble:_altIncrementValue forKey:CPSliderAltIncrValueKey];
462 CPLog.warn(
"[CPSlider value] is deprecated, use doubleValue or objectValue instead.");
467 - (void)setValue:(
id)aValue
469 CPLog.warn(
"[CPSlider setValue:] is deprecated, use setDoubleValue: or setObjectValue: instead.");
BOOL setThemeState:(ThemeState aState)
An object representation of nil.
id initWithFrame:(CGRect aFrame)
CGRect knobRectForBounds:(CGRect bounds)
A mutable key-value pair collection.
void setObjectValue:(id aValue)
CPView createEphemeralSubviewNamed:(CPString aViewName)
An immutable string (collection of characters).
void setFloatValue:(float aValue)
id initWithCoder:(CPCoder aCoder)
void setNeedsDisplay:(BOOL aFlag)
void setObjectValue:(id anObject)
void setHighlighted:(BOOL isHighlighted)
CGRect trackRectForBounds:(CGRect bounds)
void setContinuous:(BOOL flag)
Defines methods for use when archiving & restoring (enc/decoding).
BOOL unsetThemeState:(ThemeState aState)
void setFrameSize:(CGSize aSize)
var CPSliderAltIncrValueKey
void setDoubleValue:(double anObject)
void encodeWithCoder:(CPCoder aCoder)
CPView layoutEphemeralSubviewNamed:positioned:relativeToEphemeralSubviewNamed:(CPString aViewName, [positioned] CPWindowOrderingMode anOrderingMode, [relativeToEphemeralSubviewNamed] CPString relativeToViewName)
CGRect rectForEphemeralSubviewNamed:(CPString aViewName)