~ubuntuone-ios-client-team/ubuntuone-ios-contacts/trunk

« back to all changes in this revision

Viewing changes to musicstreaming/controls/MBProgressHUD.m

  • Committer: Jason Foreman
  • Date: 2011-06-16 18:33:42 UTC
  • mfrom: (191.1.60 master)
  • Revision ID: jason.foreman@canonical.com-20110616183342-vl7a4804xsf0s1b5
Merging branches for v 2.0.

lp:~threeve/ubuntuone-ios-client/master
lp:~urbanape/ubuntuone-ios-client/downloader

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
// MBProgressHUD.m
3
 
// Version 0.33
4
 
// Created by Matej Bukovinski on 2.4.09.
5
 
//
6
 
 
7
 
#import "MBProgressHUD.h"
8
 
 
9
 
@interface MBProgressHUD ()
10
 
 
11
 
- (void)hideUsingAnimation:(BOOL)animated;
12
 
- (void)showUsingAnimation:(BOOL)animated;
13
 
 
14
 
- (void)fillRoundedRect:(CGRect)rect inContext:(CGContextRef)context;
15
 
 
16
 
- (void)done;
17
 
 
18
 
- (void)updateLabelText:(NSString *)newText;
19
 
- (void)updateDetailsLabelText:(NSString *)newText;
20
 
- (void)updateProgress;
21
 
- (void)updateIndicators;
22
 
 
23
 
- (void)handleGraceTimer:(NSTimer *)theTimer;
24
 
- (void)handleMinShowTimer:(NSTimer *)theTimer;
25
 
 
26
 
@property (retain) UIView *indicator;
27
 
 
28
 
@property (assign) float width;
29
 
@property (assign) float height;
30
 
 
31
 
@property (retain) NSTimer *graceTimer;
32
 
@property (retain) NSTimer *minShowTimer;
33
 
 
34
 
@property (retain) NSDate *showStarted;
35
 
 
36
 
@end
37
 
 
38
 
 
39
 
@implementation MBProgressHUD
40
 
 
41
 
#pragma mark -
42
 
#pragma mark Accessors
43
 
 
44
 
@synthesize mode;
45
 
 
46
 
@synthesize delegate;
47
 
@synthesize labelText;
48
 
@synthesize detailsLabelText;
49
 
@synthesize opacity;
50
 
@synthesize labelFont;
51
 
@synthesize detailsLabelFont;
52
 
@synthesize progress;
53
 
 
54
 
@synthesize indicator;
55
 
 
56
 
@synthesize width;
57
 
@synthesize height;
58
 
@synthesize xOffset;
59
 
@synthesize yOffset;
60
 
 
61
 
@synthesize graceTime;
62
 
@synthesize minShowTime;
63
 
@synthesize graceTimer;
64
 
@synthesize minShowTimer;
65
 
@synthesize taskInProgress;
66
 
 
67
 
@synthesize customView;
68
 
 
69
 
@synthesize showStarted;
70
 
 
71
 
- (void)setMode:(MBProgressHUDMode)newMode {
72
 
    // Dont change mode if it wasn't actually changed to prevent flickering
73
 
    if (mode && (mode == newMode)) {
74
 
        return;
75
 
    }
76
 
        
77
 
    mode = newMode;
78
 
        
79
 
    [self performSelectorOnMainThread:@selector(updateIndicators) withObject:nil waitUntilDone:NO];
80
 
    [self performSelectorOnMainThread:@selector(setNeedsLayout) withObject:nil waitUntilDone:NO];
81
 
    [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
82
 
}
83
 
 
84
 
- (void)setLabelText:(NSString *)newText {
85
 
    [self performSelectorOnMainThread:@selector(updateLabelText:) withObject:newText waitUntilDone:NO];
86
 
    [self performSelectorOnMainThread:@selector(setNeedsLayout) withObject:nil waitUntilDone:NO];
87
 
    [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
88
 
}
89
 
 
90
 
- (void)setDetailsLabelText:(NSString *)newText {
91
 
    [self performSelectorOnMainThread:@selector(updateDetailsLabelText:) withObject:newText waitUntilDone:NO];
92
 
    [self performSelectorOnMainThread:@selector(setNeedsLayout) withObject:nil waitUntilDone:NO];
93
 
    [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
94
 
}
95
 
 
96
 
- (void)setProgress:(float)newProgress {
97
 
    progress = newProgress;
98
 
        
99
 
    // Update display ony if showing the determinate progress view
100
 
    if (mode == MBProgressHUDModeDeterminate) {
101
 
        [self performSelectorOnMainThread:@selector(updateProgress) withObject:nil waitUntilDone:NO];
102
 
        [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO];
103
 
    }
104
 
}
105
 
 
106
 
#pragma mark -
107
 
#pragma mark Accessor helpers
108
 
 
109
 
- (void)updateLabelText:(NSString *)newText {
110
 
    if (labelText != newText) {
111
 
        [labelText release];
112
 
        labelText = [newText copy];
113
 
    }
114
 
}
115
 
 
116
 
- (void)updateDetailsLabelText:(NSString *)newText {
117
 
    if (detailsLabelText != newText) {
118
 
        [detailsLabelText release];
119
 
        detailsLabelText = [newText copy];
120
 
    }
121
 
}
122
 
 
123
 
- (void)updateProgress {
124
 
    [(MBRoundProgressView *)indicator setProgress:progress];
125
 
}
126
 
 
127
 
- (void)updateIndicators {
128
 
    if (indicator) {
129
 
        [indicator removeFromSuperview];
130
 
    }
131
 
        
132
 
    if (mode == MBProgressHUDModeDeterminate) {
133
 
        self.indicator = [[[MBRoundProgressView alloc] initWithDefaultSize] autorelease];
134
 
    }
135
 
    else if (mode == MBProgressHUDModeCustomView && self.customView != nil){
136
 
        self.indicator = self.customView;
137
 
    } else {
138
 
                self.indicator = [[[UIActivityIndicatorView alloc]
139
 
                                                   initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
140
 
        [(UIActivityIndicatorView *)indicator startAnimating];
141
 
        }
142
 
        
143
 
        
144
 
    [self addSubview:indicator];
145
 
}
146
 
 
147
 
#pragma mark -
148
 
#pragma mark Constants
149
 
 
150
 
#define MARGIN 20.0
151
 
#define PADDING 4.0
152
 
 
153
 
#define LABELFONTSIZE 22.0
154
 
#define LABELDETAILSFONTSIZE 16.0
155
 
 
156
 
#define PI 3.14159265358979323846
157
 
 
158
 
#pragma mark -
159
 
#pragma mark Lifecycle methods
160
 
 
161
 
- (id)initWithWindow:(UIWindow *)window {
162
 
    return [self initWithView:window];
163
 
}
164
 
 
165
 
- (id)initWithView:(UIView *)view {
166
 
        // Let's check if the view is nil (this is a common error when using the windw initializer above)
167
 
        if (!view) {
168
 
                [NSException raise:@"MBProgressHUDViewIsNillException" 
169
 
                                        format:@"The view used in the MBProgressHUD initializer is nil."];
170
 
        }
171
 
        return [self initWithFrame:view.bounds];
172
 
}
173
 
 
174
 
- (id)initWithFrame:(CGRect)frame {
175
 
    if (self = [super initWithFrame:frame]) {
176
 
        // Set default values for properties
177
 
        self.mode = MBProgressHUDModeIndeterminate;
178
 
        self.labelText = nil;
179
 
        self.detailsLabelText = nil;
180
 
        self.opacity = 0.9;
181
 
        self.labelFont = [UIFont boldSystemFontOfSize:LABELFONTSIZE];
182
 
        self.detailsLabelFont = [UIFont boldSystemFontOfSize:LABELDETAILSFONTSIZE];
183
 
        self.xOffset = 0.0;
184
 
        self.yOffset = 0.0;
185
 
                self.graceTime = 0.0;
186
 
                self.minShowTime = 0.0;
187
 
                
188
 
                self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
189
 
                
190
 
        // Transparent background
191
 
        self.opaque = NO;
192
 
        self.backgroundColor = [UIColor clearColor];
193
 
                
194
 
        // Make invisible for now
195
 
        self.alpha = 0.0;
196
 
                
197
 
        // Add label
198
 
        label = [[UILabel alloc] initWithFrame:self.bounds];
199
 
                
200
 
        // Add details label
201
 
        detailsLabel = [[UILabel alloc] initWithFrame:self.bounds];
202
 
                
203
 
                taskInProgress = NO;
204
 
    }
205
 
    return self;
206
 
}
207
 
 
208
 
- (void)dealloc {
209
 
    [indicator release];
210
 
    [label release];
211
 
    [detailsLabel release];
212
 
    [labelText release];
213
 
    [detailsLabelText release];
214
 
        [graceTimer release];
215
 
        [minShowTimer release];
216
 
        [showStarted release];
217
 
        [customView release];
218
 
    [super dealloc];
219
 
}
220
 
 
221
 
#pragma mark -
222
 
#pragma mark Layout
223
 
 
224
 
- (void)layoutSubviews {
225
 
    CGRect frame = self.bounds;
226
 
        
227
 
    // Compute HUD dimensions based on indicator size (add margin to HUD border)
228
 
    CGRect indFrame = indicator.bounds;
229
 
    self.width = indFrame.size.width + 2 * MARGIN;
230
 
    self.height = indFrame.size.height + 2 * MARGIN;
231
 
        
232
 
    // Position the indicator
233
 
    indFrame.origin.x = floor((frame.size.width - indFrame.size.width) / 2) + self.xOffset;
234
 
    indFrame.origin.y = floor((frame.size.height - indFrame.size.height) / 2) + self.yOffset;
235
 
    indicator.frame = indFrame;
236
 
        
237
 
    // Add label if label text was set
238
 
    if (nil != self.labelText) {
239
 
        // Get size of label text
240
 
        CGSize dims = [self.labelText sizeWithFont:self.labelFont];
241
 
                
242
 
        // Compute label dimensions based on font metrics if size is larger than max then clip the label width
243
 
        float lHeight = dims.height;
244
 
        float lWidth;
245
 
        if (dims.width <= (frame.size.width - 2 * MARGIN)) {
246
 
            lWidth = dims.width;
247
 
        }
248
 
        else {
249
 
            lWidth = frame.size.width - 4 * MARGIN;
250
 
        }
251
 
                
252
 
        // Set label properties
253
 
        label.font = self.labelFont;
254
 
        label.adjustsFontSizeToFitWidth = NO;
255
 
        label.textAlignment = UITextAlignmentCenter;
256
 
        label.opaque = NO;
257
 
        label.backgroundColor = [UIColor clearColor];
258
 
        label.textColor = [UIColor whiteColor];
259
 
        label.text = self.labelText;
260
 
                
261
 
        // Update HUD size
262
 
        if (self.width < (lWidth + 2 * MARGIN)) {
263
 
            self.width = lWidth + 2 * MARGIN;
264
 
        }
265
 
        self.height = self.height + lHeight + PADDING;
266
 
                
267
 
        // Move indicator to make room for the label
268
 
        indFrame.origin.y -= (floor(lHeight / 2 + PADDING / 2));
269
 
        indicator.frame = indFrame;
270
 
                
271
 
        // Set the label position and dimensions
272
 
        CGRect lFrame = CGRectMake(floor((frame.size.width - lWidth) / 2) + xOffset,
273
 
                                   floor(indFrame.origin.y + indFrame.size.height + PADDING),
274
 
                                   lWidth, lHeight);
275
 
        label.frame = lFrame;
276
 
                
277
 
        [self addSubview:label];
278
 
                
279
 
        // Add details label delatils text was set
280
 
        if (nil != self.detailsLabelText) {
281
 
            // Get size of label text
282
 
            dims = [self.detailsLabelText sizeWithFont:self.detailsLabelFont];
283
 
                        
284
 
            // Compute label dimensions based on font metrics if size is larger than max then clip the label width
285
 
            lHeight = dims.height;
286
 
            if (dims.width <= (frame.size.width - 2 * MARGIN)) {
287
 
                lWidth = dims.width;
288
 
            }
289
 
            else {
290
 
                lWidth = frame.size.width - 4 * MARGIN;
291
 
            }
292
 
                        
293
 
            // Set label properties
294
 
            detailsLabel.font = self.detailsLabelFont;
295
 
            detailsLabel.adjustsFontSizeToFitWidth = NO;
296
 
            detailsLabel.textAlignment = UITextAlignmentCenter;
297
 
            detailsLabel.opaque = NO;
298
 
            detailsLabel.backgroundColor = [UIColor clearColor];
299
 
            detailsLabel.textColor = [UIColor whiteColor];
300
 
            detailsLabel.text = self.detailsLabelText;
301
 
                        
302
 
            // Update HUD size
303
 
            if (self.width < lWidth) {
304
 
                self.width = lWidth + 2 * MARGIN;
305
 
            }
306
 
            self.height = self.height + lHeight + PADDING;
307
 
                        
308
 
            // Move indicator to make room for the new label
309
 
            indFrame.origin.y -= (floor(lHeight / 2 + PADDING / 2));
310
 
            indicator.frame = indFrame;
311
 
                        
312
 
            // Move first label to make room for the new label
313
 
            lFrame.origin.y -= (floor(lHeight / 2 + PADDING / 2));
314
 
            label.frame = lFrame;
315
 
                        
316
 
            // Set label position and dimensions
317
 
            CGRect lFrameD = CGRectMake(floor((frame.size.width - lWidth) / 2) + xOffset,
318
 
                                        lFrame.origin.y + lFrame.size.height + PADDING, lWidth, lHeight);
319
 
            detailsLabel.frame = lFrameD;
320
 
                        
321
 
            [self addSubview:detailsLabel];
322
 
        }
323
 
    }
324
 
}
325
 
 
326
 
#pragma mark -
327
 
#pragma mark Showing and execution
328
 
 
329
 
- (void)show:(BOOL)animated {
330
 
        useAnimation = animated;
331
 
        
332
 
        // If the grace time is set postpone the HUD display
333
 
        if (self.graceTime > 0.0) {
334
 
                self.graceTimer = [NSTimer scheduledTimerWithTimeInterval:self.graceTime 
335
 
                                                                                                                   target:self 
336
 
                                                                                                                 selector:@selector(handleGraceTimer:) 
337
 
                                                                                                                 userInfo:nil 
338
 
                                                                                                                  repeats:NO];
339
 
        } 
340
 
        // ... otherwise show the HUD imediately 
341
 
        else {
342
 
                [self setNeedsDisplay];
343
 
                [self showUsingAnimation:useAnimation];
344
 
        }
345
 
}
346
 
 
347
 
- (void)hide:(BOOL)animated {
348
 
        useAnimation = animated;
349
 
        
350
 
        // If the minShow time is set, calculate how long the hud was shown,
351
 
        // and pospone the hiding operation if necessary
352
 
        if (self.minShowTime > 0.0 && showStarted) {
353
 
                NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:showStarted];
354
 
                if (interv < self.minShowTime) {
355
 
                        self.minShowTimer = [NSTimer scheduledTimerWithTimeInterval:(self.minShowTime - interv) 
356
 
                                                                                                                                 target:self 
357
 
                                                                                                                           selector:@selector(handleMinShowTimer:) 
358
 
                                                                                                                           userInfo:nil 
359
 
                                                                                                                                repeats:NO];
360
 
                        return;
361
 
                } 
362
 
        }
363
 
        
364
 
        // ... otherwise hide the HUD immediately
365
 
    [self hideUsingAnimation:useAnimation];
366
 
}
367
 
 
368
 
- (void)handleGraceTimer:(NSTimer *)theTimer {
369
 
        // Show the HUD only if the task is still running
370
 
        if (taskInProgress) {
371
 
                [self setNeedsDisplay];
372
 
                [self showUsingAnimation:useAnimation];
373
 
        }
374
 
}
375
 
 
376
 
- (void)handleMinShowTimer:(NSTimer *)theTimer {
377
 
        [self hideUsingAnimation:useAnimation];
378
 
}
379
 
 
380
 
- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated {
381
 
        
382
 
    methodForExecution = method;
383
 
    targetForExecution = [target retain];
384
 
    objectForExecution = [object retain];
385
 
        
386
 
    // Launch execution in new thread
387
 
        taskInProgress = YES;
388
 
    [NSThread detachNewThreadSelector:@selector(launchExecution) toTarget:self withObject:nil];
389
 
        
390
 
        // Show HUD view
391
 
        [self show:animated];
392
 
}
393
 
 
394
 
- (void)launchExecution {
395
 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
396
 
        
397
 
    // Start executing the requested task
398
 
    [targetForExecution performSelector:methodForExecution withObject:objectForExecution];
399
 
        
400
 
    // Task completed, update view in main thread (note: view operations should
401
 
    // be done only in the main thread)
402
 
    [self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO];
403
 
        
404
 
    [pool release];
405
 
}
406
 
 
407
 
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void*)context {
408
 
    [self done];
409
 
}
410
 
 
411
 
- (void)done {
412
 
    isFinished = YES;
413
 
        
414
 
    // If delegate was set make the callback
415
 
    self.alpha = 0.0;
416
 
    
417
 
    if(delegate != nil && [delegate conformsToProtocol:@protocol(MBProgressHUDDelegate)]) {
418
 
                if([delegate respondsToSelector:@selector(hudWasHidden)]) {
419
 
                        [delegate performSelector:@selector(hudWasHidden)];
420
 
                }
421
 
    }
422
 
}
423
 
 
424
 
- (void)cleanUp {
425
 
        taskInProgress = NO;
426
 
        
427
 
        self.indicator = nil;
428
 
        
429
 
    [targetForExecution release];
430
 
    [objectForExecution release];
431
 
        
432
 
    [self hide:useAnimation];
433
 
}
434
 
 
435
 
#pragma mark -
436
 
#pragma mark Fade in and Fade out
437
 
 
438
 
- (void)showUsingAnimation:(BOOL)animated {
439
 
        self.showStarted = [NSDate date];
440
 
    // Fade in
441
 
    if (animated) {
442
 
        [UIView beginAnimations:nil context:NULL];
443
 
        [UIView setAnimationDuration:0.40];
444
 
        self.alpha = 1.0;
445
 
        [UIView commitAnimations];
446
 
    }
447
 
    else {
448
 
        self.alpha = 1.0;
449
 
    }
450
 
}
451
 
 
452
 
- (void)hideUsingAnimation:(BOOL)animated {
453
 
    // Fade out
454
 
    if (animated) {
455
 
        [UIView beginAnimations:nil context:NULL];
456
 
        [UIView setAnimationDuration:0.40];
457
 
        [UIView setAnimationDelegate:self];
458
 
        [UIView setAnimationDidStopSelector:@selector(animationFinished: finished: context:)];
459
 
        // 0.02 prevents the hud from passing through touches during the animation the hud will get completely hidden
460
 
        // in the done method
461
 
        self.alpha = 0.02;
462
 
        [UIView commitAnimations];
463
 
    }
464
 
    else {
465
 
        self.alpha = 0.0;
466
 
        [self done];
467
 
    }
468
 
}
469
 
 
470
 
#pragma mark BG Drawing
471
 
 
472
 
- (void)drawRect:(CGRect)rect {
473
 
    // Center HUD
474
 
    CGRect allRect = self.bounds;
475
 
    // Draw rounded HUD bacgroud rect
476
 
    CGRect boxRect = CGRectMake(((allRect.size.width - self.width) / 2) + self.xOffset,
477
 
                                ((allRect.size.height - self.height) / 2) + self.yOffset, self.width, self.height);
478
 
    CGContextRef ctxt = UIGraphicsGetCurrentContext();
479
 
    [self fillRoundedRect:boxRect inContext:ctxt];
480
 
}
481
 
 
482
 
- (void)fillRoundedRect:(CGRect)rect inContext:(CGContextRef)context {
483
 
    float radius = 10.0f;
484
 
        
485
 
    CGContextBeginPath(context);
486
 
    CGContextSetGrayFillColor(context, 0.0, self.opacity);
487
 
    CGContextMoveToPoint(context, CGRectGetMinX(rect) + radius, CGRectGetMinY(rect));
488
 
    CGContextAddArc(context, CGRectGetMaxX(rect) - radius, CGRectGetMinY(rect) + radius, radius, 3 * M_PI / 2, 0, 0);
489
 
    CGContextAddArc(context, CGRectGetMaxX(rect) - radius, CGRectGetMaxY(rect) - radius, radius, 0, M_PI / 2, 0);
490
 
    CGContextAddArc(context, CGRectGetMinX(rect) + radius, CGRectGetMaxY(rect) - radius, radius, M_PI / 2, M_PI, 0);
491
 
    CGContextAddArc(context, CGRectGetMinX(rect) + radius, CGRectGetMinY(rect) + radius, radius, M_PI, 3 * M_PI / 2, 0);
492
 
    CGContextClosePath(context);
493
 
    CGContextFillPath(context);
494
 
}
495
 
 
496
 
@end
497
 
 
498
 
 
499
 
@implementation MBRoundProgressView
500
 
 
501
 
- (id)initWithDefaultSize {
502
 
    return [super initWithFrame:CGRectMake(0.0f, 0.0f, 37.0f, 37.0f)];
503
 
}
504
 
 
505
 
- (void)drawRect:(CGRect)rect {
506
 
    CGRect allRect = self.bounds;
507
 
    CGRect circleRect = CGRectMake(allRect.origin.x + 2, allRect.origin.y + 2, allRect.size.width - 4,
508
 
                                   allRect.size.height - 4);
509
 
        
510
 
    CGContextRef context = UIGraphicsGetCurrentContext();
511
 
        
512
 
    // Draw background
513
 
    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0); // white
514
 
    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.1); // translucent white
515
 
    CGContextSetLineWidth(context, 2.0);
516
 
    CGContextFillEllipseInRect(context, circleRect);
517
 
    CGContextStrokeEllipseInRect(context, circleRect);
518
 
        
519
 
    // Draw progress
520
 
    float x = (allRect.size.width / 2);
521
 
    float y = (allRect.size.height / 2);
522
 
    CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0); // white
523
 
    CGContextMoveToPoint(context, x, y);
524
 
    CGContextAddArc(context, x, y, (allRect.size.width - 4) / 2, -(PI / 2), (self.progress * 2 * PI) - PI / 2, 0);
525
 
    CGContextClosePath(context);
526
 
    CGContextFillPath(context);
527
 
}
528
 
 
529
 
@end