6#import "BlockAlertView.h" 
    7#import "BlockBackground.h" 
   12@synthesize view = _view;
 
   13@synthesize backgroundImage = _backgroundImage;
 
   14@synthesize vignetteBackground = _vignetteBackground;
 
   16static UIImage *background = nil;
 
   17static UIImage *backgroundlandscape = nil;
 
   18static UIFont *titleFont = nil;
 
   19static UIFont *messageFont = nil;
 
   20static 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];
 
  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) {
 
  468- (void)buttonClicked:(
id)sender
 
  471  int buttonIndex = [sender tag] - 1;
 
  472  [
self dismissWithClickedButtonIndex:buttonIndex animated:YES];