Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
805 | - | 1 | // |
2 | // Copyright 2009-2010 Facebook |
||
3 | // |
||
4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
||
5 | // you may not use this file except in compliance with the License. |
||
6 | // You may obtain a copy of the License at |
||
7 | // |
||
8 | // http://www.apache.org/licenses/LICENSE-2.0 |
||
9 | // |
||
10 | // Unless required by applicable law or agreed to in writing, software |
||
11 | // distributed under the License is distributed on an "AS IS" BASIS, |
||
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
13 | // See the License for the specific language governing permissions and |
||
14 | // limitations under the License. |
||
15 | // |
||
16 | |||
17 | #import "Three20UI/TTActivityLabel.h" |
||
18 | |||
19 | // UI |
||
20 | #import "Three20UI/TTView.h" |
||
21 | #import "Three20UI/TTButton.h" |
||
22 | #import "Three20UI/UIViewAdditions.h" |
||
23 | |||
24 | // UINavigator |
||
25 | #import "Three20UINavigator/TTGlobalNavigatorMetrics.h" |
||
26 | |||
27 | // Style |
||
28 | #import "Three20Style/TTGlobalStyle.h" |
||
29 | #import "Three20Style/TTDefaultStyleSheet.h" |
||
30 | #import "Three20Style/UIFontAdditions.h" |
||
31 | |||
32 | // Core |
||
33 | #import "Three20Core/TTCorePreprocessorMacros.h" |
||
34 | |||
35 | static CGFloat kMargin = 10; |
||
36 | static CGFloat kPadding = 15; |
||
37 | static CGFloat kBannerPadding = 8; |
||
38 | static CGFloat kSpacing = 6; |
||
39 | static CGFloat kProgressMargin = 6; |
||
40 | |||
41 | |||
42 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
43 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
44 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
45 | @implementation TTActivityLabel |
||
46 | |||
47 | @synthesize style = _style; |
||
48 | @synthesize progress = _progress; |
||
49 | @synthesize smoothesProgress = _smoothesProgress; |
||
50 | |||
51 | |||
52 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
53 | - (id)initWithFrame:(CGRect)frame style:(TTActivityLabelStyle)style text:(NSString*)text { |
||
54 | if (self = [super initWithFrame:frame]) { |
||
55 | _style = style; |
||
56 | _progress = 0; |
||
57 | _smoothesProgress = NO; |
||
58 | _smoothTimer =nil; |
||
59 | _progressView = nil; |
||
60 | |||
61 | _bezelView = [[TTView alloc] init]; |
||
62 | if (_style == TTActivityLabelStyleBlackBezel) { |
||
63 | _bezelView.backgroundColor = [UIColor clearColor]; |
||
64 | _bezelView.style = TTSTYLE(blackBezel); |
||
65 | self.backgroundColor = [UIColor clearColor]; |
||
66 | } else if (_style == TTActivityLabelStyleWhiteBezel) { |
||
67 | _bezelView.backgroundColor = [UIColor clearColor]; |
||
68 | _bezelView.style = TTSTYLE(whiteBezel); |
||
69 | self.backgroundColor = [UIColor clearColor]; |
||
70 | } else if (_style == TTActivityLabelStyleWhiteBox) { |
||
71 | _bezelView.backgroundColor = [UIColor clearColor]; |
||
72 | self.backgroundColor = [UIColor whiteColor]; |
||
73 | } else if (_style == TTActivityLabelStyleBlackBox) { |
||
74 | _bezelView.backgroundColor = [UIColor clearColor]; |
||
75 | self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.8]; |
||
76 | } else if (_style == TTActivityLabelStyleBlackBanner) { |
||
77 | _bezelView.backgroundColor = [UIColor clearColor]; |
||
78 | _bezelView.style = TTSTYLE(blackBanner); |
||
79 | self.backgroundColor = [UIColor clearColor]; |
||
80 | } else { |
||
81 | _bezelView.backgroundColor = [UIColor clearColor]; |
||
82 | self.backgroundColor = [UIColor clearColor]; |
||
83 | } |
||
84 | |||
85 | self.autoresizingMask = |
||
86 | UIViewAutoresizingFlexibleWidth | |
||
87 | UIViewAutoresizingFlexibleHeight; |
||
88 | |||
89 | _label = [[UILabel alloc] init]; |
||
90 | _label.text = text; |
||
91 | _label.backgroundColor = [UIColor clearColor]; |
||
92 | _label.lineBreakMode = UILineBreakModeTailTruncation; |
||
93 | |||
94 | if (_style == TTActivityLabelStyleWhite) { |
||
95 | _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: |
||
96 | UIActivityIndicatorViewStyleWhite]; |
||
97 | _label.font = TTSTYLEVAR(activityLabelFont); |
||
98 | _label.textColor = [UIColor whiteColor]; |
||
99 | } else if (_style == TTActivityLabelStyleGray |
||
100 | || _style == TTActivityLabelStyleWhiteBox |
||
101 | || _style == TTActivityLabelStyleWhiteBezel) { |
||
102 | _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: |
||
103 | UIActivityIndicatorViewStyleGray]; |
||
104 | _label.font = TTSTYLEVAR(activityLabelFont); |
||
105 | _label.textColor = TTSTYLEVAR(tableActivityTextColor); |
||
106 | } else if (_style == TTActivityLabelStyleBlackBezel || _style == TTActivityLabelStyleBlackBox) { |
||
107 | _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: |
||
108 | UIActivityIndicatorViewStyleWhiteLarge]; |
||
109 | _activityIndicator.frame = CGRectMake(0, 0, 24, 24); |
||
110 | _label.font = TTSTYLEVAR(activityLabelFont); |
||
111 | _label.textColor = [UIColor whiteColor]; |
||
112 | _label.shadowColor = [UIColor colorWithWhite:0 alpha:0.3]; |
||
113 | _label.shadowOffset = CGSizeMake(1, 1); |
||
114 | } else if (_style == TTActivityLabelStyleBlackBanner) { |
||
115 | _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: |
||
116 | UIActivityIndicatorViewStyleWhite]; |
||
117 | _label.font = TTSTYLEVAR(activityBannerFont); |
||
118 | _label.textColor = [UIColor whiteColor]; |
||
119 | _label.shadowColor = [UIColor colorWithWhite:0 alpha:0.3]; |
||
120 | _label.shadowOffset = CGSizeMake(1, 1); |
||
121 | } |
||
122 | |||
123 | [self addSubview:_bezelView]; |
||
124 | [_bezelView addSubview:_activityIndicator]; |
||
125 | [_bezelView addSubview:_label]; |
||
126 | [_activityIndicator startAnimating]; |
||
127 | } |
||
128 | return self; |
||
129 | } |
||
130 | |||
131 | |||
132 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
133 | - (id)initWithFrame:(CGRect)frame style:(TTActivityLabelStyle)style { |
||
134 | if (self = [self initWithFrame:frame style:style text:nil]) { |
||
135 | } |
||
136 | |||
137 | return self; |
||
138 | } |
||
139 | |||
140 | |||
141 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
142 | - (id)initWithStyle:(TTActivityLabelStyle)style { |
||
143 | if (self = [self initWithFrame:CGRectZero style:style text:nil]) { |
||
144 | } |
||
145 | |||
146 | return self; |
||
147 | } |
||
148 | |||
149 | |||
150 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
151 | - (id)initWithFrame:(CGRect)frame { |
||
152 | if (self = [self initWithFrame:frame style:TTActivityLabelStyleWhiteBox text:nil]) { |
||
153 | } |
||
154 | |||
155 | return self; |
||
156 | } |
||
157 | |||
158 | |||
159 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
160 | - (void)dealloc { |
||
161 | TT_INVALIDATE_TIMER(_smoothTimer); |
||
162 | TT_RELEASE_SAFELY(_bezelView); |
||
163 | TT_RELEASE_SAFELY(_progressView); |
||
164 | TT_RELEASE_SAFELY(_activityIndicator); |
||
165 | TT_RELEASE_SAFELY(_label); |
||
166 | [super dealloc]; |
||
167 | } |
||
168 | |||
169 | |||
170 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
171 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
172 | #pragma mark - |
||
173 | #pragma mark UIView |
||
174 | |||
175 | |||
176 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
177 | - (void)layoutSubviews { |
||
178 | [super layoutSubviews]; |
||
179 | |||
180 | CGSize textSize = [_label.text sizeWithFont:_label.font]; |
||
181 | |||
182 | CGFloat indicatorSize = 0; |
||
183 | [_activityIndicator sizeToFit]; |
||
184 | if (_activityIndicator.isAnimating) { |
||
185 | if (_activityIndicator.height > textSize.height) { |
||
186 | indicatorSize = textSize.height; |
||
187 | } else { |
||
188 | indicatorSize = _activityIndicator.height; |
||
189 | } |
||
190 | } |
||
191 | |||
192 | CGFloat contentWidth = indicatorSize + kSpacing + textSize.width; |
||
193 | CGFloat contentHeight = textSize.height > indicatorSize ? textSize.height : indicatorSize; |
||
194 | |||
195 | if (_progressView) { |
||
196 | [_progressView sizeToFit]; |
||
197 | contentHeight += _progressView.height + kSpacing; |
||
198 | } |
||
199 | |||
200 | CGFloat margin, padding, bezelWidth, bezelHeight; |
||
201 | if (_style == TTActivityLabelStyleBlackBezel || _style == TTActivityLabelStyleWhiteBezel) { |
||
202 | margin = kMargin; |
||
203 | padding = kPadding; |
||
204 | bezelWidth = contentWidth + padding*2; |
||
205 | bezelHeight = contentHeight + padding*2; |
||
206 | } else { |
||
207 | margin = 0; |
||
208 | padding = kBannerPadding; |
||
209 | bezelWidth = self.width; |
||
210 | bezelHeight = self.height; |
||
211 | } |
||
212 | |||
213 | CGFloat maxBevelWidth = TTScreenBounds().size.width - margin*2; |
||
214 | if (bezelWidth > maxBevelWidth) { |
||
215 | bezelWidth = maxBevelWidth; |
||
216 | contentWidth = bezelWidth - (kSpacing + indicatorSize); |
||
217 | } |
||
218 | |||
219 | CGFloat textMaxWidth = (bezelWidth - (indicatorSize + kSpacing)) - padding*2; |
||
220 | CGFloat textWidth = textSize.width; |
||
221 | if (textWidth > textMaxWidth) { |
||
222 | textWidth = textMaxWidth; |
||
223 | } |
||
224 | |||
225 | _bezelView.frame = CGRectMake(floor(self.width/2 - bezelWidth/2), |
||
226 | floor(self.height/2 - bezelHeight/2), |
||
227 | bezelWidth, bezelHeight); |
||
228 | |||
229 | CGFloat y = padding + floor((bezelHeight - padding*2)/2 - contentHeight/2); |
||
230 | |||
231 | if (_progressView) { |
||
232 | if (_style == TTActivityLabelStyleBlackBanner) { |
||
233 | y += kBannerPadding/2; |
||
234 | } |
||
235 | _progressView.frame = CGRectMake(kProgressMargin, y, |
||
236 | bezelWidth - kProgressMargin*2, _progressView.height); |
||
237 | y += _progressView.height + kSpacing-1; |
||
238 | } |
||
239 | |||
240 | _label.frame = CGRectMake(floor((bezelWidth/2 - contentWidth/2) + indicatorSize + kSpacing), y, |
||
241 | textWidth, textSize.height); |
||
242 | |||
243 | _activityIndicator.frame = CGRectMake(_label.left - (indicatorSize+kSpacing), y, |
||
244 | indicatorSize, indicatorSize); |
||
245 | } |
||
246 | |||
247 | |||
248 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
249 | - (CGSize)sizeThatFits:(CGSize)size { |
||
250 | CGFloat padding; |
||
251 | if (_style == TTActivityLabelStyleBlackBezel || _style == TTActivityLabelStyleWhiteBezel) { |
||
252 | padding = kPadding; |
||
253 | } else { |
||
254 | padding = kBannerPadding; |
||
255 | } |
||
256 | |||
257 | CGFloat height = _label.font.ttLineHeight + padding*2; |
||
258 | if (_progressView) { |
||
259 | height += _progressView.height + kSpacing; |
||
260 | } |
||
261 | |||
262 | return CGSizeMake(size.width, height); |
||
263 | } |
||
264 | |||
265 | |||
266 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
267 | - (void)smoothTimer { |
||
268 | if (_progressView.progress < _progress) { |
||
269 | _progressView.progress += 0.01; |
||
270 | } else { |
||
271 | TT_INVALIDATE_TIMER(_smoothTimer); |
||
272 | } |
||
273 | } |
||
274 | |||
275 | |||
276 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
277 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
278 | #pragma mark - |
||
279 | #pragma mark Public |
||
280 | |||
281 | |||
282 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
283 | - (NSString*)text { |
||
284 | return _label.text; |
||
285 | } |
||
286 | |||
287 | |||
288 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
289 | - (void)setText:(NSString*)text { |
||
290 | _label.text = text; |
||
291 | [self setNeedsLayout]; |
||
292 | } |
||
293 | |||
294 | |||
295 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
296 | - (UIFont*)font { |
||
297 | return _label.font; |
||
298 | } |
||
299 | |||
300 | |||
301 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
302 | - (void)setFont:(UIFont*)font { |
||
303 | _label.font = font; |
||
304 | [self setNeedsLayout]; |
||
305 | } |
||
306 | |||
307 | |||
308 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
309 | - (BOOL)isAnimating { |
||
310 | return _activityIndicator.isAnimating; |
||
311 | } |
||
312 | |||
313 | |||
314 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
315 | - (void)setIsAnimating:(BOOL)isAnimating { |
||
316 | if (isAnimating) { |
||
317 | [_activityIndicator startAnimating]; |
||
318 | |||
319 | } else { |
||
320 | [_activityIndicator stopAnimating]; |
||
321 | } |
||
322 | } |
||
323 | |||
324 | |||
325 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
||
326 | - (void)setProgress:(float)progress { |
||
327 | _progress = progress; |
||
328 | |||
329 | if (!_progressView) { |
||
330 | _progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; |
||
331 | _progressView.progress = 0; |
||
332 | [_bezelView addSubview:_progressView]; |
||
333 | [self setNeedsLayout]; |
||
334 | } |
||
335 | |||
336 | if (_smoothesProgress) { |
||
337 | if (!_smoothTimer) { |
||
338 | _smoothTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self |
||
339 | selector:@selector(smoothTimer) userInfo:nil repeats:YES]; |
||
340 | } |
||
341 | } else { |
||
342 | _progressView.progress = progress; |
||
343 | } |
||
344 | } |
||
345 | |||
346 | |||
347 | @end |