master
  1//
  2//  BlockTableAlertView.m
  3//  BlockAlertsDemo
  4//
  5//  Created by Barrett Jacobsen on 2/14/12.
  6//  Copyright (c) 2012 CodeCrop Software. All rights reserved.
  7//
  8
  9#define SUPPORTS_MULTIPLE_SELECTION [self.tableView respondsToSelector:@selector(setAllowsMultipleSelectionDuringEditing:)]
 10
 11#define kVerticalSpacing     5
 12#define kHorizontalMargin   12
 13
 14#define IS_IPAD UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
 15
 16#define IS_LANDSCAPE UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])
 17
 18#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
 19
 20#define kNumMaximumVisibleRowsInTableView (IS_IPAD ? 15 : (IS_LANDSCAPE ? 4 : (IS_IPHONE_5 ? 6 : 5)))
 21
 22#import "BlockTableAlertView.h"
 23#import <QuartzCore/QuartzCore.h>
 24#import <dispatch/dispatch.h>
 25
 26@implementation BlockTableAlertView
 27@synthesize tableView=_tableView;
 28@synthesize type=_type;
 29@synthesize	didSelectRow;
 30@synthesize willDismissWithButtonIndex;
 31@synthesize maxSelection;
 32@synthesize cellForRow;
 33@synthesize willPresent;
 34@synthesize numberOfRowsInTableAlert;
 35
 36@dynamic indexPathsForSelectedRows;
 37
 38+ (BlockTableAlertView *)tableAlertWithTitle:(NSString *)title message:(NSString *)message
 39{
 40    return [[[BlockTableAlertView alloc] initWithTitle:title message:message] autorelease];
 41}
 42
 43
 44- (id)initWithTitle:(NSString *)title message:(NSString *)message {
 45    self = [super initWithTitle:title message:message];
 46    
 47    if (self) {
 48        if (!SUPPORTS_MULTIPLE_SELECTION)
 49            selectedItems = [[NSMutableArray alloc] init];
 50    }
 51    
 52    return self;
 53}
 54
 55- (void)addComponents:(CGRect)frame {
 56    [super addComponents:frame];
 57   
 58    if (!_tableView) {
 59		_tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
 60		[_tableView setDelegate:self];
 61		[_tableView setDataSource:self];
 62		[_tableView setBackgroundColor:[UIColor colorWithWhite:0.90 alpha:1.0]];
 63		[_tableView setRowHeight:kDefaultRowHeight];
 64		[_tableView setSeparatorColor:[UIColor lightGrayColor]];
 65		_tableView.layer.cornerRadius = kTableCornerRadius;
 66    }
 67
 68    CGFloat tableHeight = kDefaultRowHeight * MIN(self.numberOfRowsInTableAlert(self), kNumMaximumVisibleRowsInTableView);
 69   
 70    _tableView.frame = CGRectMake(kHorizontalMargin, _height, frame.size.width - kHorizontalMargin * 2, tableHeight);
 71  
 72    [_view addSubview:_tableView];
 73    _height += tableHeight + kVerticalSpacing;
 74}
 75
 76
 77- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated {
 78    if (self.willDismissWithButtonIndex)
 79        self.willDismissWithButtonIndex(self, buttonIndex);
 80    
 81    [super dismissWithClickedButtonIndex:buttonIndex animated:animated];
 82}
 83
 84- (void)updateAlertHeight:(CGFloat)oldTableHeight {
 85    CGFloat newTableHeight = kDefaultRowHeight * MIN(self.numberOfRowsInTableAlert(self), kNumMaximumVisibleRowsInTableView);
 86    
 87    if (newTableHeight != oldTableHeight) {
 88        CGFloat diff = newTableHeight - oldTableHeight;
 89        [UIView animateWithDuration:0.3 animations:^{
 90            [self.view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
 91                UIView *v = obj;
 92                if (v.frame.origin.y >= _tableView.frame.origin.y + _tableView.frame.size.height)
 93                    v.frame = CGRectMake(v.frame.origin.x, v.frame.origin.y + diff, v.frame.size.width, v.frame.size.height);
 94            }];
 95            
 96            _tableView.frame = CGRectMake(_tableView.frame.origin.x, _tableView.frame.origin.y, _tableView.frame.size.width, newTableHeight);
 97            self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height + diff);
 98        }];
 99    }
100}
101
102- (void)reloadData {
103    CGFloat oldTableHeight = _tableView.frame.size.height;
104
105    [self.tableView reloadData];
106    
107    [self updateAlertHeight:oldTableHeight];
108}
109
110- (void)insertRowsAtIndexPaths:(NSArray*)rows {
111    CGFloat oldTableHeight = _tableView.frame.size.height;
112    
113    [self.tableView insertRowsAtIndexPaths:rows withRowAnimation:UITableViewRowAnimationAutomatic];
114    
115    [self updateAlertHeight:oldTableHeight];
116}
117
118- (void)deleteRowsAtIndexPaths:(NSArray*)rows {
119    CGFloat oldTableHeight = _tableView.frame.size.height;
120    
121    [self.tableView deleteRowsAtIndexPaths:rows withRowAnimation:UITableViewRowAnimationAutomatic];
122    
123    [self updateAlertHeight:oldTableHeight];
124}
125
126
127- (void)show {
128    if (!_shown)
129        [self setupDisplay];
130    
131    if (self.willPresent)
132        self.willPresent(self);
133    
134    if (self.type == BlockTableAlertTypeMultipleSelct && SUPPORTS_MULTIPLE_SELECTION) {
135        self.tableView.allowsMultipleSelectionDuringEditing = YES;
136        self.tableView.editing = YES;
137    }
138
139    [super show];
140}
141
142#pragma mark - iOS 4 Compatibility
143
144- (NSArray*)indexPathsForSelectedRows {
145    if (SUPPORTS_MULTIPLE_SELECTION) {
146        return self.tableView.indexPathsForSelectedRows;
147    }
148    else {
149        return selectedItems;
150    }
151}
152
153- (void)selectRowAtIndexPath:(NSIndexPath*)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scroll {
154    if (SUPPORTS_MULTIPLE_SELECTION) {
155        [self.tableView selectRowAtIndexPath:indexPath animated:animated scrollPosition:scroll];
156    }
157    else {
158        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
159        
160        if (cell.accessoryType == UITableViewCellAccessoryNone) {
161            [selectedItems addObject:indexPath];
162            cell.accessoryType = UITableViewCellAccessoryCheckmark;
163        }
164    }
165}
166
167
168#pragma mark - UITableViewDelegate
169
170- (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
171    if (self.type == BlockTableAlertTypeSingleSelect || self.maxSelection == 0)
172        return indexPath;
173    
174    NSIndexPath *toSelect = indexPath;
175    
176    if ([self.indexPathsForSelectedRows count] + 1 > self.maxSelection)
177        toSelect = nil;
178    
179    return toSelect;
180}
181
182- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
183	if (_type == BlockTableAlertTypeSingleSelect)
184		[self dismissWithClickedButtonIndex:-1 animated:YES];
185	
186    if (!SUPPORTS_MULTIPLE_SELECTION) {
187        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
188        
189        if (cell.accessoryType == UITableViewCellAccessoryNone) {
190            [selectedItems addObject:indexPath];
191            cell.accessoryType = UITableViewCellAccessoryCheckmark;
192            
193            if (self.didSelectRow)
194                self.didSelectRow(self, [indexPath row]);
195        }
196        else {
197            [selectedItems removeObject:indexPath];
198            cell.accessoryType = UITableViewCellAccessoryNone;
199        }
200        
201        [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
202        
203        return;
204    }
205    
206	if (self.didSelectRow)
207		self.didSelectRow(self, [indexPath row]);
208}
209
210#pragma mark - UITableViewDataSource
211
212- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {	
213	return self.cellForRow(self,[indexPath row]);
214}
215
216- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
217	return 1;
218}
219
220- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
221	return self.numberOfRowsInTableAlert(self);
222}
223
224
225@end