c4fd5e3740fd3ce28472a35a76dede73a743864c
[xscreensaver] / OSX / InvertedSlider.m
1 /* xscreensaver, Copyright (c) 2006-2012 Jamie Zawinski <jwz@jwz.org>
2 *
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation.  No representations are made about the suitability of this
8 * software for any purpose.  It is provided "as is" without express or 
9 * implied warranty.
10 *
11 * This is a subclass of NSSlider that is flipped horizontally:
12 * the high value is on the left and the low value is on the right.
13 */
14
15 #import "InvertedSlider.h"
16
17 @implementation InvertedSlider
18
19 - (id) initWithFrame:(NSRect)r
20 {
21   self = [super initWithFrame:r];
22   if (! self) return 0;
23   inverted = YES;
24   integers = NO;
25   return self;
26 }
27
28 - (id) initWithFrame:(NSRect)r inverted:(BOOL)_inv integers:(BOOL)_int
29 {
30   self = [self initWithFrame:r];
31   inverted = _inv;
32   integers = _int;
33   return self;
34 }
35
36
37 -(double) transformValue:(double) value
38 {
39   double v2 = (integers
40                ? (int) (value + (value < 0 ? -0.5 : 0.5))
41                : value);
42   double low   = [self minValue];
43   double high  = [self maxValue];
44   double range = high - low;
45   double off   = v2 - low;
46   if (inverted)
47     v2 = low + (range - off);
48   // NSLog (@" ... %.1f -> %.1f    [%.1f - %.1f]", value, v2, low, high);
49   return v2;
50 }
51
52 -(double) doubleValue;
53 {
54 # ifdef USE_IPHONE
55   return [self transformValue:[self value]];
56 # else
57   return [self transformValue:[super doubleValue]];
58 # endif
59 }
60
61 -(void) setDoubleValue:(double)v
62 {
63 # ifdef USE_IPHONE
64   return [super setValue:[self transformValue:v]];
65 # else
66   return [super setDoubleValue:[self transformValue:v]];
67 # endif
68 }
69
70
71 #ifdef USE_IPHONE
72
73 - (void)setValue:(float)v animated:(BOOL)a
74 {
75   return [super setValue:[self transformValue:v] animated:a];
76 }
77
78
79 /* Draw the thumb in the right place by also inverting its position
80    relative to the track.
81  */
82 - (CGRect)thumbRectForBounds:(CGRect)bounds
83                    trackRect:(CGRect)rect
84                        value:(float)value
85 {
86   CGRect thumb = [super thumbRectForBounds:bounds trackRect:rect value:value];
87   if (inverted)
88     thumb.origin.x = rect.size.width - thumb.origin.x - thumb.size.width;
89   return thumb;
90 }
91
92 #endif // !USE_IPHONE
93
94
95
96 /* Implement all accessor methods in terms of "doubleValue" above.
97    (Note that these normally exist only on MacOS, not on iOS.)
98  */
99
100 -(float) floatValue;
101 {
102   return (float) [self doubleValue];
103 }
104
105 -(int) intValue;
106 {
107   return (int) [self doubleValue];
108 }
109
110 -(id) objectValue;
111 {
112   return [NSNumber numberWithDouble:[self doubleValue]];
113 }
114
115 -(NSString *) stringValue;
116 {
117   return [NSString stringWithFormat:@"%f", [self floatValue]];
118 }
119
120 - (NSAttributedString *)attributedStringValue;
121 {
122   // #### "Build and Analyze" says this leaks. Unsure whether this is true.
123   return [[NSAttributedString alloc] initWithString:[self stringValue]];
124 }
125
126
127 /* Implment all setter methods in terms of "setDoubleValue", above.
128  */
129
130 -(void) setFloatValue:(float)v
131 {
132   [self setDoubleValue:(double)v];
133 }
134
135 -(void) setIntValue:(int)v
136 {
137   [self setDoubleValue:(double)v];
138 }
139
140 -(void) setObjectValue:(id <NSCopying>)v
141 {
142   NSAssert2((v == nil) ||
143             [(NSObject *) v respondsToSelector:@selector(doubleValue)], 
144             @"argument %@ to %s does not respond to doubleValue",
145             v, __PRETTY_FUNCTION__);
146   [self setDoubleValue:[((NSNumber *) v) doubleValue]];
147 }
148
149 -(void) setStringValue:(NSString *)v
150 {
151   [self setDoubleValue:[v doubleValue]];
152 }
153
154 -(void) setAttributedStringValue:(NSAttributedString *)v
155 {
156   [self setStringValue:[v string]];
157 }
158
159 @end