|
1 /* |
|
2 * Hedgewars-iOS, a Hedgewars port for iOS devices |
|
3 * Copyright (c) 2009-2011 Vittorio Giovara <vittorio.giovara@gmail.com> |
|
4 * |
|
5 * This program is free software; you can redistribute it and/or modify |
|
6 * it under the terms of the GNU General Public License as published by |
|
7 * the Free Software Foundation; version 2 of the License |
|
8 * |
|
9 * This program is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 * GNU General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU General Public License |
|
15 * along with this program; if not, write to the Free Software |
|
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
17 * |
|
18 * File created on 06/02/2012. |
|
19 */ |
|
20 |
|
21 // class heavily based on: http://blog.neuwert-media.com/2011/04/customized-uislider-with-visual-value-tracking/ |
|
22 |
|
23 |
|
24 #import "ValueTrackingSliderView.h" |
|
25 |
|
26 #pragma mark - |
|
27 #pragma mark Private UIView subclass rendering the popup showing slider value |
|
28 @interface SliderValuePopupView : UIView |
|
29 @property (nonatomic) float value; |
|
30 @property (nonatomic, retain) UIFont *font; |
|
31 @property (nonatomic, retain) NSString *text; |
|
32 @end |
|
33 |
|
34 @implementation SliderValuePopupView |
|
35 |
|
36 @synthesize value = _value; |
|
37 @synthesize font = _font; |
|
38 @synthesize text = _text; |
|
39 |
|
40 -(id) initWithFrame:(CGRect) frame { |
|
41 self = [super initWithFrame:frame]; |
|
42 if (self) { |
|
43 self.font = [UIFont boldSystemFontOfSize:18]; |
|
44 } |
|
45 return self; |
|
46 } |
|
47 |
|
48 -(void) dealloc { |
|
49 self.text = nil; |
|
50 self.font = nil; |
|
51 [super dealloc]; |
|
52 } |
|
53 |
|
54 -(void) drawRect:(CGRect) rect { |
|
55 // Create the path for the rounded rectangle |
|
56 CGRect roundedRect = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, floorf(self.bounds.size.height * 0.8)); |
|
57 UIBezierPath *roundedRectPath = [UIBezierPath bezierPathWithRoundedRect:roundedRect cornerRadius:6.0]; |
|
58 roundedRectPath.lineWidth = 2.0f; |
|
59 |
|
60 // Create the arrow path |
|
61 UIBezierPath *arrowPath = [UIBezierPath bezierPath]; |
|
62 CGFloat midX = CGRectGetMidX(self.bounds); |
|
63 CGPoint p0 = CGPointMake(midX, CGRectGetMaxY(self.bounds)); |
|
64 [arrowPath moveToPoint:p0]; |
|
65 [arrowPath addLineToPoint:CGPointMake((midX - 10.0), CGRectGetMaxY(roundedRect))]; |
|
66 [arrowPath addLineToPoint:CGPointMake((midX + 10.0), CGRectGetMaxY(roundedRect))]; |
|
67 [arrowPath closePath]; |
|
68 |
|
69 // Attach the arrow path to the rounded rect |
|
70 [roundedRectPath appendPath:arrowPath]; |
|
71 |
|
72 // Color various sections |
|
73 [[UIColor blackColor] setFill]; |
|
74 [roundedRectPath fill]; |
|
75 [[UIColor whiteColor] setStroke]; |
|
76 [roundedRectPath stroke]; |
|
77 [[UIColor whiteColor] setFill]; |
|
78 [arrowPath fill]; |
|
79 |
|
80 // Draw the text |
|
81 if (self.text) { |
|
82 [[UIColor lightYellowColor] set]; |
|
83 CGSize s = [_text sizeWithFont:self.font]; |
|
84 CGFloat yOffset = (roundedRect.size.height - s.height) / 2; |
|
85 CGRect textRect = CGRectMake(roundedRect.origin.x, yOffset, roundedRect.size.width, s.height); |
|
86 |
|
87 [_text drawInRect:textRect |
|
88 withFont:self.font |
|
89 lineBreakMode:UILineBreakModeWordWrap |
|
90 alignment:UITextAlignmentCenter]; |
|
91 } |
|
92 } |
|
93 |
|
94 @end |
|
95 |
|
96 #pragma mark - |
|
97 #pragma mark MNEValueTrackingSlider implementations |
|
98 @implementation ValueTrackingSliderView |
|
99 |
|
100 @synthesize thumbRect, textValue; |
|
101 |
|
102 #pragma Private methods |
|
103 |
|
104 -(void) _constructSlider { |
|
105 valuePopupView = [[SliderValuePopupView alloc] initWithFrame:CGRectZero]; |
|
106 valuePopupView.backgroundColor = [UIColor clearColor]; |
|
107 valuePopupView.alpha = 0.0; |
|
108 [self addSubview:valuePopupView]; |
|
109 } |
|
110 |
|
111 -(void) _fadePopupViewInAndOut:(BOOL)aFadeIn { |
|
112 [UIView beginAnimations:nil context:NULL]; |
|
113 [UIView setAnimationDuration:0.25]; |
|
114 if (aFadeIn) { |
|
115 valuePopupView.alpha = 1.0; |
|
116 } else { |
|
117 valuePopupView.alpha = 0.0; |
|
118 } |
|
119 [UIView commitAnimations]; |
|
120 } |
|
121 |
|
122 -(void) _positionAndUpdatePopupView { |
|
123 CGRect _thumbRect = self.thumbRect; |
|
124 CGRect popupRect = CGRectOffset(_thumbRect, 0, -floorf(_thumbRect.size.height * 1.5)); |
|
125 valuePopupView.frame = CGRectInset(popupRect, -100, -15); |
|
126 valuePopupView.text = self.textValue; |
|
127 [valuePopupView setNeedsDisplay]; |
|
128 } |
|
129 |
|
130 #pragma mark Memory management |
|
131 |
|
132 -(id) initWithFrame:(CGRect) frame { |
|
133 self = [super initWithFrame:frame]; |
|
134 if (self) { |
|
135 [self _constructSlider]; |
|
136 } |
|
137 return self; |
|
138 } |
|
139 |
|
140 -(id) initWithCoder:(NSCoder *)aDecoder { |
|
141 self = [super initWithCoder:aDecoder]; |
|
142 if (self) { |
|
143 [self _constructSlider]; |
|
144 } |
|
145 return self; |
|
146 } |
|
147 |
|
148 -(void) dealloc { |
|
149 [valuePopupView release]; |
|
150 [textValue release]; |
|
151 [super dealloc]; |
|
152 } |
|
153 |
|
154 #pragma mark - |
|
155 #pragma mark UIControl touch event tracking |
|
156 -(BOOL) beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { |
|
157 // Fade in and update the popup view |
|
158 CGPoint touchPoint = [touch locationInView:self]; |
|
159 // Check if the knob is touched. Only in this case show the popup-view |
|
160 if(CGRectContainsPoint(CGRectInset(self.thumbRect, -12.0, -12.0), touchPoint)) { |
|
161 [self _positionAndUpdatePopupView]; |
|
162 [self _fadePopupViewInAndOut:YES]; |
|
163 } |
|
164 return [super beginTrackingWithTouch:touch withEvent:event]; |
|
165 } |
|
166 |
|
167 -(BOOL) continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { |
|
168 // Update the popup view as slider knob is being moved |
|
169 [self _positionAndUpdatePopupView]; |
|
170 return [super continueTrackingWithTouch:touch withEvent:event]; |
|
171 } |
|
172 |
|
173 -(void) cancelTrackingWithEvent:(UIEvent *)event { |
|
174 [super cancelTrackingWithEvent:event]; |
|
175 } |
|
176 |
|
177 -(void) endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event { |
|
178 // Fade out the popoup view |
|
179 [self _fadePopupViewInAndOut:NO]; |
|
180 [super endTrackingWithTouch:touch withEvent:event]; |
|
181 } |
|
182 |
|
183 #pragma mark - |
|
184 #pragma mark Custom property accessors |
|
185 -(CGRect) thumbRect { |
|
186 CGRect trackRect = [self trackRectForBounds:self.bounds]; |
|
187 CGRect thumbR = [self thumbRectForBounds:self.bounds |
|
188 trackRect:trackRect |
|
189 value:self.value]; |
|
190 return thumbR; |
|
191 } |
|
192 |
|
193 @end |