project_files/HedgewarsMobile/Classes/MNEValueTrackingSlider.m
changeset 6679 d8b98aa486a6
child 6700 e04da46ee43c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/HedgewarsMobile/Classes/MNEValueTrackingSlider.m	Sun Feb 12 18:50:22 2012 +0100
@@ -0,0 +1,200 @@
+//
+// MNEValueTrackingSlider
+//
+// Copyright 2011 Michael Neuwert
+// "You can use the code in your own project and modify it as you like."
+// http://blog.neuwert-media.com/2011/04/customized-uislider-with-visual-value-tracking/
+//
+
+
+#import "MNEValueTrackingSlider.h"
+
+#pragma mark -
+#pragma mark Private UIView subclass rendering the popup showing slider value
+@interface SliderValuePopupView : UIView
+@property (nonatomic, retain) UIFont *font;
+@property (nonatomic, copy) NSString *text;
+@property (nonatomic) float arrowOffset;
+@end
+
+@implementation SliderValuePopupView
+
+@synthesize font = _font;
+@synthesize text = _text;
+@synthesize arrowOffset = _arrowOffset;
+
+-(id) initWithFrame:(CGRect) frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        self.font = [UIFont boldSystemFontOfSize:18];
+    }
+    return self;
+}
+
+-(void) dealloc {
+    self.text = nil;
+    self.font = nil;
+    [super dealloc];
+}
+
+-(void) drawRect:(CGRect) rect {
+    // Create the path for the rounded rectangle
+    CGRect roundedRect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, floorf(self.bounds.size.height * 0.8));
+    UIBezierPath *roundedRectPath = [UIBezierPath bezierPathWithRoundedRect:roundedRect cornerRadius:6.0];
+    roundedRectPath.lineWidth = 2.0f;
+
+    // Create the arrow path
+    UIBezierPath *arrowPath = [UIBezierPath bezierPath];
+    /*
+    // Make sure the arrow offset is nice
+    if (-self.arrowOffset + 1 > CGRectGetMidX(self.bounds) / 2)
+        self.arrowOffset = -CGRectGetMidX(self.bounds) / 2 + 1;
+    if (self.arrowOffset > CGRectGetMidX(self.bounds) / 2)
+        self.arrowOffset = CGRectGetMidX(self.bounds) / 2 -1;
+     */
+
+    CGFloat midX = CGRectGetMidX(self.bounds) + self.arrowOffset;
+    CGPoint p0 = CGPointMake(midX, CGRectGetMaxY(self.bounds));
+    [arrowPath moveToPoint:p0];
+    [arrowPath addLineToPoint:CGPointMake((midX - 10.0), CGRectGetMaxY(roundedRect))];
+    [arrowPath addLineToPoint:CGPointMake((midX + 10.0), CGRectGetMaxY(roundedRect))];
+    [arrowPath closePath];
+
+    // Attach the arrow path to the rounded rect
+    [roundedRectPath appendPath:arrowPath];
+
+    // Color various sections
+    [[UIColor blackColor] setFill];
+    [roundedRectPath fill];
+    [[UIColor whiteColor] setStroke];
+    [roundedRectPath stroke];
+    [[UIColor whiteColor] setFill];
+    [arrowPath fill];
+
+    // Draw the text
+    if (self.text) {
+        [[UIColor lightYellowColor] set];
+        CGSize s = [_text sizeWithFont:self.font];
+        CGFloat yOffset = (roundedRect.size.height - s.height) / 2;
+        CGRect textRect = CGRectMake(roundedRect.origin.x, yOffset, roundedRect.size.width, s.height);
+
+        [_text drawInRect:textRect
+                 withFont:self.font
+            lineBreakMode:UILineBreakModeWordWrap
+                alignment:UITextAlignmentCenter];
+    }
+}
+
+@end
+
+#pragma mark -
+#pragma mark MNEValueTrackingSlider implementations
+@implementation MNEValueTrackingSlider
+
+@synthesize thumbRect, textValue;
+
+#pragma Private methods
+
+-(void) _constructSlider {
+    valuePopupView = [[SliderValuePopupView alloc] initWithFrame:CGRectZero];
+    valuePopupView.backgroundColor = [UIColor clearColor];
+    valuePopupView.alpha = 0.0;
+    [self addSubview:valuePopupView];
+}
+
+-(void) _fadePopupViewInAndOut:(BOOL)aFadeIn {
+    [UIView beginAnimations:nil context:NULL];
+    [UIView setAnimationDuration:0.25];
+    if (aFadeIn) {
+        valuePopupView.alpha = 1.0;
+    } else {
+        valuePopupView.alpha = 0.0;
+    }
+    [UIView commitAnimations];
+}
+
+-(void) _positionAndUpdatePopupView {
+    CGRect _thumbRect = self.thumbRect;
+    CGRect popupRect = CGRectOffset(_thumbRect, 0, -floorf(_thumbRect.size.height * 1.5));
+    // (-100, -15) determines the size of the the rect
+    popupRect = CGRectInset(popupRect, -100, -15);
+
+    // this prevents drawing the popup outside the slider view
+    if (popupRect.origin.x < -self.frame.origin.x+5)
+        popupRect.origin.x = -self.frame.origin.x+5;
+    else if (popupRect.origin.x > self.superview.frame.size.width - popupRect.size.width - self.frame.origin.x - 5)
+        popupRect.origin.x = self.superview.frame.size.width - popupRect.size.width - self.frame.origin.x - 5;
+    //else if (CGRectGetMaxX(popupRect) > CGRectGetMaxX(self.superview.bounds))
+    //    popupRect.origin.x = CGRectGetMaxX(self.superview.bounds) - CGRectGetWidth(popupRect) - 1.0;
+
+    valuePopupView.arrowOffset = CGRectGetMidX(_thumbRect) - CGRectGetMidX(popupRect);
+
+    valuePopupView.frame = popupRect;
+    valuePopupView.text = self.textValue;
+    [valuePopupView setNeedsDisplay];
+}
+
+#pragma mark Memory management
+
+-(id) initWithFrame:(CGRect) frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        [self _constructSlider];
+    }
+    return self;
+}
+
+-(id) initWithCoder:(NSCoder *)aDecoder {
+    self = [super initWithCoder:aDecoder];
+    if (self) {
+        [self _constructSlider];
+    }
+    return self;
+}
+
+-(void) dealloc {
+    [valuePopupView release];
+    [textValue release];
+    [super dealloc];
+}
+
+#pragma mark -
+#pragma mark UIControl touch event tracking
+-(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+    // Fade in and update the popup view
+    CGPoint touchPoint = [touch locationInView:self];
+    // Check if the knob is touched. Only in this case show the popup-view
+    if(CGRectContainsPoint(CGRectInset(self.thumbRect, -14.0, -12.0), touchPoint)) {
+        [self _positionAndUpdatePopupView];
+        [self _fadePopupViewInAndOut:YES];
+    }
+    return [super beginTrackingWithTouch:touch withEvent:event];
+}
+
+-(BOOL) continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+    // Update the popup view as slider knob is being moved
+    [self _positionAndUpdatePopupView];
+    return [super continueTrackingWithTouch:touch withEvent:event];
+}
+
+-(void) cancelTrackingWithEvent:(UIEvent *)event {
+    [super cancelTrackingWithEvent:event];
+}
+
+-(void) endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
+    // Fade out the popoup view
+    [self _fadePopupViewInAndOut:NO];
+    [super endTrackingWithTouch:touch withEvent:event];
+}
+
+#pragma mark -
+#pragma mark Custom property accessors
+-(CGRect) thumbRect {
+    CGRect trackRect = [self trackRectForBounds:self.bounds];
+    CGRect thumbR = [self thumbRectForBounds:self.bounds
+                                         trackRect:trackRect
+                                             value:self.value];
+    return thumbR;
+}
+
+@end