6 #import "BlockAlertView.h"
7 #import "BlockBackground.h"
12 @synthesize view = _view;
13 @synthesize backgroundImage = _backgroundImage;
14 @synthesize vignetteBackground = _vignetteBackground;
16 static UIImage *background = nil;
17 static UIImage *backgroundlandscape = nil;
18 static UIFont *titleFont = nil;
19 static UIFont *messageFont = nil;
20 static UIFont *buttonFont = nil;
28 background = [UIImage imageNamed:kAlertViewBackground];
30 [[background stretchableImageWithLeftCapWidth:0
31 topCapHeight:kAlertViewBackgroundCapHeight] retain];
33 backgroundlandscape = [UIImage imageNamed:kAlertViewBackgroundLandscape];
34 backgroundlandscape = [[backgroundlandscape
35 stretchableImageWithLeftCapWidth:0
36 topCapHeight:kAlertViewBackgroundCapHeight] retain];
38 titleFont = [kAlertViewTitleFont retain];
39 messageFont = [kAlertViewMessageFont retain];
40 buttonFont = [kAlertViewButtonFont retain];
44 + (
BlockAlertView *)alertWithTitle:(NSString *)title message:(NSString *)message
46 return [[[
BlockAlertView alloc] initWithTitle:title message:message] autorelease];
49 + (void)showInfoAlertWithTitle:(NSString *)title message:(NSString *)message
52 [alert setCancelButtonWithTitle:NSLocalizedString(@"Dismiss", nil) block:nil];
57 + (void)showErrorAlert:(NSError *)error
60 initWithTitle:NSLocalizedString(@"Operation Failed", nil)
62 stringWithFormat:NSLocalizedString(
63 @"The operation did not complete successfully: %@",
66 [alert setCancelButtonWithTitle:@"Dismiss" block:nil];
72 #pragma mark - NSObject
74 - (void)addComponents:(CGRect)frame
78 CGSize size = [_title sizeWithFont:titleFont
79 constrainedToSize:CGSizeMake(frame.size.width - kAlertViewBorder * 2, 1000)
80 lineBreakMode:NSLineBreakByWordWrapping];
82 UILabel *labelView = [[UILabel alloc]
83 initWithFrame:CGRectMake(kAlertViewBorder, _height,
84 frame.size.width - kAlertViewBorder * 2, size.height)];
85 labelView.font = titleFont;
86 labelView.numberOfLines = 0;
87 labelView.lineBreakMode = NSLineBreakByWordWrapping;
88 labelView.textColor = kAlertViewTitleTextColor;
89 labelView.backgroundColor = [UIColor clearColor];
90 labelView.textAlignment = NSTextAlignmentCenter;
91 labelView.shadowColor = kAlertViewTitleShadowColor;
92 labelView.shadowOffset = kAlertViewTitleShadowOffset;
93 labelView.text = _title;
94 [_view addSubview:labelView];
97 _height += size.height + kAlertViewBorder;
103 [_message sizeWithFont:messageFont
104 constrainedToSize:CGSizeMake(frame.size.width - kAlertViewBorder * 2, 1000)
105 lineBreakMode:NSLineBreakByWordWrapping];
107 UILabel *labelView = [[UILabel alloc]
108 initWithFrame:CGRectMake(kAlertViewBorder, _height,
109 frame.size.width - kAlertViewBorder * 2, size.height)];
110 labelView.font = messageFont;
111 labelView.numberOfLines = 0;
112 labelView.lineBreakMode = NSLineBreakByWordWrapping;
113 labelView.textColor = kAlertViewMessageTextColor;
114 labelView.backgroundColor = [UIColor clearColor];
115 labelView.textAlignment = NSTextAlignmentCenter;
116 labelView.shadowColor = kAlertViewMessageShadowColor;
117 labelView.shadowOffset = kAlertViewMessageShadowOffset;
118 labelView.text = _message;
119 [_view addSubview:labelView];
122 _height += size.height + kAlertViewBorder;
128 [[_view subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
129 [obj removeFromSuperview];
133 CGRect frame = parentView.bounds;
134 frame.origin.x = floorf((frame.size.width - background.size.width) * 0.5);
135 frame.size.width = background.size.width;
137 UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
138 if (UIInterfaceOrientationIsLandscape(orientation))
140 frame.size.width += 150;
141 frame.origin.x -= 75;
146 _height = kAlertViewBorder + 15;
148 if (NeedsLandscapePhoneTweaks)
153 [
self addComponents:frame];
159 - (id)initWithTitle:(NSString *)title message:(NSString *)message
165 _title = [title copy];
166 _message = [message copy];
168 _view = [[UIView alloc] init];
170 _view.autoresizingMask =
171 UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin |
172 UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
174 _blocks = [[NSMutableArray alloc] init];
176 [[NSNotificationCenter defaultCenter]
178 selector:@selector(setupDisplay)
179 name:UIApplicationDidChangeStatusBarOrientationNotification
185 _vignetteBackground = NO;
195 [_backgroundImage release];
202 #pragma mark - Public
204 - (void)addButtonWithTitle:(NSString *)title color:(NSString *)color block:(
void (^)())block
206 [_blocks addObject:[NSArray arrayWithObjects:block ? [[block copy] autorelease] : [NSNull null],
210 - (void)addButtonWithTitle:(NSString *)title block:(
void (^)())block
212 [
self addButtonWithTitle:title color:@"gray" block:block];
215 - (void)setCancelButtonWithTitle:(NSString *)title block:(
void (^)())block
217 [
self addButtonWithTitle:title color:@"black" block:block];
220 - (void)setDestructiveButtonWithTitle:(NSString *)title block:(
void (^)())block
222 [
self addButtonWithTitle:title color:@"red" block:block];
229 BOOL isSecondButton = NO;
230 NSUInteger index = 0;
231 for (NSUInteger i = 0; i < _blocks.count; i++)
233 NSArray *block = [_blocks objectAtIndex:i];
234 NSString *title = [block objectAtIndex:1];
235 NSString *color = [block objectAtIndex:2];
238 [UIImage imageNamed:[NSString stringWithFormat:@"alert-%@-button.png", color]];
239 image = [image stretchableImageWithLeftCapWidth:(int)(image.size.width + 1) >> 1
242 CGFloat maxHalfWidth = floorf((_view.bounds.size.width - kAlertViewBorder * 3) * 0.5);
243 CGFloat width = _view.bounds.size.width - kAlertViewBorder * 2;
244 CGFloat xOffset = kAlertViewBorder;
247 width = maxHalfWidth;
248 xOffset = width + kAlertViewBorder * 2;
251 else if (i + 1 < _blocks.count)
255 CGSize size = [title sizeWithFont:buttonFont
258 forWidth:_view.bounds.size.width - kAlertViewBorder * 2
259 lineBreakMode:NSLineBreakByClipping];
261 if (size.width < maxHalfWidth - kAlertViewBorder)
264 NSArray *block2 = [_blocks objectAtIndex:i + 1];
265 NSString *title2 = [block2 objectAtIndex:1];
266 size = [title2 sizeWithFont:buttonFont
269 forWidth:_view.bounds.size.width - kAlertViewBorder * 2
270 lineBreakMode:NSLineBreakByClipping];
272 if (size.width < maxHalfWidth - kAlertViewBorder)
275 isSecondButton = YES;
276 width = maxHalfWidth;
280 else if (_blocks.count == 1)
283 CGSize size = [title sizeWithFont:buttonFont
286 forWidth:_view.bounds.size.width - kAlertViewBorder * 2
287 lineBreakMode:UILineBreakModeClip];
289 size.width = MAX(size.width, 80);
290 if (size.width + 2 * kAlertViewBorder < width)
292 width = size.width + 2 * kAlertViewBorder;
293 xOffset = floorf((_view.bounds.size.width - width) * 0.5);
297 UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
298 button.frame = CGRectMake(xOffset, _height, width, kAlertButtonHeight);
299 button.titleLabel.font = buttonFont;
302 #pragma clang diagnostic push
303 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
304 button.titleLabel.minimumFontSize = 10;
305 #pragma clang diagnostic pop
309 button.titleLabel.adjustsFontSizeToFitWidth = YES;
310 button.titleLabel.adjustsLetterSpacingToFitWidth = YES;
311 button.titleLabel.minimumScaleFactor = 0.1;
313 button.titleLabel.textAlignment = NSTextAlignmentCenter;
314 button.titleLabel.shadowOffset = kAlertViewButtonShadowOffset;
315 button.backgroundColor = [UIColor clearColor];
318 [button setBackgroundImage:image forState:UIControlStateNormal];
319 [button setTitleColor:kAlertViewButtonTextColor forState:UIControlStateNormal];
320 [button setTitleShadowColor:kAlertViewButtonShadowColor forState:UIControlStateNormal];
321 [button setTitle:title forState:UIControlStateNormal];
322 button.accessibilityLabel = title;
324 [button addTarget:self
325 action:@selector(buttonClicked:)
326 forControlEvents:UIControlEventTouchUpInside];
328 [_view addSubview:button];
331 _height += kAlertButtonHeight + kAlertViewBorder;
338 if (_height < background.size.height)
340 CGFloat offset = background.size.height - _height;
341 _height = background.size.height;
343 for (NSUInteger i = 0; i < _blocks.count; i++)
345 UIButton *btn = (UIButton *)[_view viewWithTag:i + 1];
347 frame.origin.y += offset;
352 CGRect frame = _view.frame;
353 frame.origin.y = -_height;
354 frame.size.height = _height;
357 UIImageView *modalBackground = [[UIImageView alloc] initWithFrame:_view.bounds];
359 if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
360 modalBackground.image = backgroundlandscape;
362 modalBackground.image = background;
364 modalBackground.contentMode = UIViewContentModeScaleToFill;
365 modalBackground.autoresizingMask =
366 UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
367 [_view insertSubview:modalBackground atIndex:0];
368 [modalBackground release];
370 if (_backgroundImage)
373 [_backgroundImage release];
374 _backgroundImage = nil;
377 [
BlockBackground sharedInstance].vignetteBackground = _vignetteBackground;
380 __block CGPoint center = _view.center;
381 center.y = floorf([
BlockBackground sharedInstance].bounds.size.height * 0.5) + kAlertViewBounce;
385 [UIView animateWithDuration:0.4
387 options:UIViewAnimationCurveEaseOut
390 _view.center = center;
392 completion:^(BOOL finished) {
396 [UIView animateWithDuration:0.1
400 center.y -= kAlertViewBounce;
401 _view.center = center;
403 completion:^(BOOL finished) {
404 [[NSNotificationCenter defaultCenter]
405 postNotificationName:@"AlertViewFinishedAnimations"
413 - (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
417 [[NSNotificationCenter defaultCenter] removeObserver:self];
419 if (buttonIndex >= 0 && buttonIndex < [_blocks count])
421 id obj = [[_blocks objectAtIndex:buttonIndex] objectAtIndex:0];
422 if (![obj isEqual:[NSNull
null]])
430 [UIView animateWithDuration:0.1
434 CGPoint center = _view.center;
436 _view.center = center;
438 completion:^(BOOL finished) {
439 [UIView animateWithDuration:0.4
441 options:UIViewAnimationCurveEaseIn
443 CGRect frame = _view.frame;
444 frame.origin.y = -frame.size.height;
448 completion:^(BOOL finished) {
466 #pragma mark - Action
468 - (void)buttonClicked:(
id)sender
471 int buttonIndex = [sender tag] - 1;
472 [
self dismissWithClickedButtonIndex:buttonIndex animated:YES];