summaryrefslogtreecommitdiffstats
path: root/OSX/InvertedSlider.m
diff options
context:
space:
mode:
authorSimon Rettberg2018-10-16 10:08:48 +0200
committerSimon Rettberg2018-10-16 10:08:48 +0200
commitd3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch)
treecbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /OSX/InvertedSlider.m
downloadxscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz
xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip
Original 5.40
Diffstat (limited to 'OSX/InvertedSlider.m')
-rw-r--r--OSX/InvertedSlider.m151
1 files changed, 151 insertions, 0 deletions
diff --git a/OSX/InvertedSlider.m b/OSX/InvertedSlider.m
new file mode 100644
index 0000000..6ac0b41
--- /dev/null
+++ b/OSX/InvertedSlider.m
@@ -0,0 +1,151 @@
+/* xscreensaver, Copyright (c) 2006-2015 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * This is a subclass of NSSlider that is flipped horizontally:
+ * the high value is on the left and the low value is on the right.
+ */
+
+#import "InvertedSlider.h"
+
+@implementation InvertedSlider
+
+- (id) initWithFrame:(NSRect)r
+{
+ self = [super initWithFrame:r];
+ if (! self) return 0;
+ inverted = YES;
+ integers = NO;
+ return self;
+}
+
+- (id) initWithFrame:(NSRect)r inverted:(BOOL)_inv integers:(BOOL)_int
+{
+ self = [self initWithFrame:r];
+ inverted = _inv;
+ integers = _int;
+ return self;
+}
+
+
+-(double) transformValue:(double) value
+{
+ double v2 = (integers
+ ? (int) (value + (value < 0 ? -0.5 : 0.5))
+ : value);
+ double low = [self minValue];
+ double high = [self maxValue];
+ double range = high - low;
+ double off = v2 - low;
+ if (inverted)
+ v2 = low + (range - off);
+ // NSLog (@" ... %.1f -> %.1f [%.1f - %.1f]", value, v2, low, high);
+ return v2;
+}
+
+#ifndef USE_IPHONE
+
+/* On MacOS, we have to transform the value on every entry and exit point
+ to this class. So, we implement doubleValue and setDoubleValue to
+ transform the value; and we then have to re-implement every getter and
+ setter in terms of those. There's no way to simply change how the
+ slider is displayed without mucking with the value inside of it.
+ */
+
+-(double) doubleValue
+{
+ return [self transformValue:[super doubleValue]];
+}
+
+-(void) setDoubleValue:(double)v
+{
+ return [super setDoubleValue:[self transformValue:v]];
+}
+
+-(float)floatValue { return (float) [self doubleValue]; }
+-(int)intValue { return (int) [self doubleValue]; }
+-(NSInteger)integerValue { return (NSInteger) [self doubleValue]; }
+-(id)objectValue { return [NSNumber numberWithDouble:[self doubleValue]]; }
+
+-(NSString *)stringValue
+{
+ if (integers)
+ return [NSString stringWithFormat:@"%d", [self intValue]];
+ else
+ return [NSString stringWithFormat:@"%f", [self doubleValue]];
+}
+
+- (NSAttributedString *)attributedStringValue;
+{
+ return [[[NSAttributedString alloc] initWithString:[self stringValue]]
+ autorelease];
+}
+
+-(void)setFloatValue:(float)v { [self setDoubleValue: (double) v]; }
+-(void)setIntValue: (int)v { [self setDoubleValue: (double) v]; }
+-(void)setIntegerValue:(NSInteger)v { [self setDoubleValue: (double) v]; }
+-(void)setStringValue:(NSString *)v { [self setDoubleValue: [v doubleValue]]; }
+-(void)takeIntValueFrom:(id)f { [self setIntValue: [f intValue]]; }
+-(void)takeFloatValueFrom:(id)f { [self setFloatValue: [f floatValue]]; }
+-(void)takeDoubleValueFrom:(id)f { [self setDoubleValue: [f doubleValue]]; }
+-(void)takeStringValueFrom:(id)f { [self setStringValue: [f stringValue]]; }
+-(void)takeObjectValueFrom:(id)f { [self setObjectValue: [f objectValue]]; }
+-(void)takeIntegerValueFrom:(id)f { [self setIntegerValue:[f integerValue]];}
+-(void) setAttributedStringValue:(NSAttributedString *)v {
+ [self setStringValue:[v string]];
+}
+
+-(void) setObjectValue:(id <NSCopying>)v
+{
+ NSAssert2((v == nil) ||
+ [(NSObject *) v respondsToSelector:@selector(doubleValue)],
+ @"argument %@ to %s does not respond to doubleValue",
+ v, __PRETTY_FUNCTION__);
+ [self setDoubleValue:[((NSNumber *) v) doubleValue]];
+}
+
+#else // USE_IPHONE
+
+/* On iOS, we have control over how the value is displayed, but there's no
+ way to transform the value on input and output: if we wrap 'value' and
+ 'setValue' analagously to what we do on MacOS, things fail in weird
+ ways. Presumably some parts of the system are accessing the value
+ instance variable directly instead of going through the methods.
+
+ So the only way around this is to enforce that all of our calls into
+ this object use a new API: 'transformedValue' and 'setTransformedValue'.
+ The code in XScreenSaverConfigSheet uses that instead.
+ */
+
+- (CGRect)thumbRectForBounds:(CGRect)bounds
+ trackRect:(CGRect)rect
+ value:(float)value
+{
+ CGRect thumb = [super thumbRectForBounds: bounds
+ trackRect: rect
+ value: [self transformValue:value]];
+ if (inverted)
+ thumb.origin.x = rect.size.width - thumb.origin.x - thumb.size.width;
+ return thumb;
+}
+
+-(double) transformedValue
+{
+ return [self transformValue: [self value]];
+}
+
+-(void) setTransformedValue:(double)v
+{
+ [self setValue: [self transformValue: v]];
+}
+
+#endif // USE_IPHONE
+
+
+@end