Blame client/iOS/Additions/Toast+UIView.m

Packit Service fa4841
/***************************************************************************
Packit Service fa4841
Packit Service fa4841
 Toast+UIView.h
Packit Service fa4841
 Toast
Packit Service fa4841
 Version 0.1
Packit Service fa4841
Packit Service fa4841
 Copyright (c) 2011 Charles Scalesse.
Packit Service fa4841
Packit Service fa4841
 Permission is hereby granted, free of charge, to any person obtaining a
Packit Service fa4841
 copy of this software and associated documentation files (the
Packit Service fa4841
 "Software"), to deal in the Software without restriction, including
Packit Service fa4841
 without limitation the rights to use, copy, modify, merge, publish,
Packit Service fa4841
 distribute, sublicense, and/or sell copies of the Software, and to
Packit Service fa4841
 permit persons to whom the Software is furnished to do so, subject to
Packit Service fa4841
 the following conditions:
Packit Service fa4841
Packit Service fa4841
 The above copyright notice and this permission notice shall be included
Packit Service fa4841
 in all copies or substantial portions of the Software.
Packit Service fa4841
Packit Service fa4841
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
Packit Service fa4841
 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit Service fa4841
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Packit Service fa4841
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
Packit Service fa4841
 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
Packit Service fa4841
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
Packit Service fa4841
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service fa4841
Packit Service fa4841
 ***************************************************************************/
Packit Service fa4841
Packit Service fa4841
#import "Toast+UIView.h"
Packit Service fa4841
#import <QuartzCore/QuartzCore.h>
Packit Service fa4841
#import <objc/runtime.h>
Packit Service fa4841
Packit Service fa4841
#define kMaxWidth 0.8
Packit Service fa4841
#define kMaxHeight 0.8
Packit Service fa4841
Packit Service fa4841
#define kHorizontalPadding 10.0
Packit Service fa4841
#define kVerticalPadding 10.0
Packit Service fa4841
#define kCornerRadius 10.0
Packit Service fa4841
#define kOpacity 0.8
Packit Service fa4841
#define kFontSize 16.0
Packit Service fa4841
#define kMaxTitleLines 999
Packit Service fa4841
#define kMaxMessageLines 999
Packit Service fa4841
Packit Service fa4841
#define kFadeDuration 0.2
Packit Service fa4841
Packit Service fa4841
#define kDefaultLength 3
Packit Service fa4841
#define kDefaultPosition @"bottom"
Packit Service fa4841
Packit Service fa4841
#define kImageWidth 80.0
Packit Service fa4841
#define kImageHeight 80.0
Packit Service fa4841
Packit Service fa4841
static NSString *kDurationKey = @"duration";
Packit Service fa4841
Packit Service fa4841
@interface UIView (ToastPrivate)
Packit Service fa4841
Packit Service fa4841
- (CGPoint)getPositionFor:(id)position toast:(UIView *)toast;
Packit Service fa4841
- (UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image;
Packit Service fa4841
Packit Service fa4841
@end
Packit Service fa4841
Packit Service fa4841
@implementation UIView (Toast)
Packit Service fa4841
Packit Service fa4841
#pragma mark -
Packit Service fa4841
#pragma mark Toast Methods
Packit Service fa4841
Packit Service fa4841
- (void)makeToast:(NSString *)message
Packit Service fa4841
{
Packit Service fa4841
	[self makeToast:message duration:kDefaultLength position:kDefaultPosition];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
- (void)makeToast:(NSString *)message duration:(float)interval position:(id)point
Packit Service fa4841
{
Packit Service fa4841
	UIView *toast = [self makeViewForMessage:message title:nil image:nil];
Packit Service fa4841
	[self showToast:toast duration:interval position:point];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
- (void)makeToast:(NSString *)message
Packit Service fa4841
         duration:(float)interval
Packit Service fa4841
         position:(id)point
Packit Service fa4841
            title:(NSString *)title
Packit Service fa4841
{
Packit Service fa4841
	UIView *toast = [self makeViewForMessage:message title:title image:nil];
Packit Service fa4841
	[self showToast:toast duration:interval position:point];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
- (void)makeToast:(NSString *)message
Packit Service fa4841
         duration:(float)interval
Packit Service fa4841
         position:(id)point
Packit Service fa4841
            image:(UIImage *)image
Packit Service fa4841
{
Packit Service fa4841
	UIView *toast = [self makeViewForMessage:message title:nil image:image];
Packit Service fa4841
	[self showToast:toast duration:interval position:point];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
- (void)makeToast:(NSString *)message
Packit Service fa4841
         duration:(float)interval
Packit Service fa4841
         position:(id)point
Packit Service fa4841
            title:(NSString *)title
Packit Service fa4841
            image:(UIImage *)image
Packit Service fa4841
{
Packit Service fa4841
	UIView *toast = [self makeViewForMessage:message title:title image:image];
Packit Service fa4841
	[self showToast:toast duration:interval position:point];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
- (void)showToast:(UIView *)toast
Packit Service fa4841
{
Packit Service fa4841
	[self showToast:toast duration:kDefaultLength position:kDefaultPosition];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
- (void)showToast:(UIView *)toast duration:(float)interval position:(id)point
Packit Service fa4841
{
Packit Service fa4841
Packit Service fa4841
	/****************************************************
Packit Service fa4841
	 *                                                  *
Packit Service fa4841
	 * Displays a view for a given duration & position. *
Packit Service fa4841
	 *                                                  *
Packit Service fa4841
	 ****************************************************/
Packit Service fa4841
Packit Service fa4841
	CGPoint toastPoint = [self getPositionFor:point toast:toast];
Packit Service fa4841
Packit Service fa4841
	// use an associative reference to associate the toast view with the display interval
Packit Service fa4841
	objc_setAssociatedObject(toast, &kDurationKey, [NSNumber numberWithFloat:interval],
Packit Service fa4841
	                         OBJC_ASSOCIATION_RETAIN);
Packit Service fa4841
Packit Service fa4841
	[toast setCenter:toastPoint];
Packit Service fa4841
	[toast setAlpha:0.0];
Packit Service fa4841
	[self addSubview:toast];
Packit Service fa4841
Packit Service fa4841
	[UIView beginAnimations:@"fade_in" context:toast];
Packit Service fa4841
	[UIView setAnimationDuration:kFadeDuration];
Packit Service fa4841
	[UIView setAnimationDelegate:self];
Packit Service fa4841
	[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
Packit Service fa4841
	[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
Packit Service fa4841
	[toast setAlpha:1.0];
Packit Service fa4841
	[UIView commitAnimations];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
#pragma mark -
Packit Service fa4841
#pragma mark Animation Delegate Method
Packit Service fa4841
Packit Service fa4841
- (void)animationDidStop:(NSString *)animationID finished:(BOOL)finished context:(void *)context
Packit Service fa4841
{
Packit Service fa4841
Packit Service fa4841
	UIView *toast = (UIView *)context;
Packit Service fa4841
Packit Service fa4841
	// retrieve the display interval associated with the view
Packit Service fa4841
	float interval = [(NSNumber *)objc_getAssociatedObject(toast, &kDurationKey) floatValue];
Packit Service fa4841
Packit Service fa4841
	if ([animationID isEqualToString:@"fade_in"])
Packit Service fa4841
	{
Packit Service fa4841
Packit Service fa4841
		[UIView beginAnimations:@"fade_out" context:toast];
Packit Service fa4841
		[UIView setAnimationDelay:interval];
Packit Service fa4841
		[UIView setAnimationDuration:kFadeDuration];
Packit Service fa4841
		[UIView setAnimationDelegate:self];
Packit Service fa4841
		[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
Packit Service fa4841
		[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
Packit Service fa4841
		[toast setAlpha:0.0];
Packit Service fa4841
		[UIView commitAnimations];
Packit Service fa4841
	}
Packit Service fa4841
	else if ([animationID isEqualToString:@"fade_out"])
Packit Service fa4841
	{
Packit Service fa4841
Packit Service fa4841
		[toast removeFromSuperview];
Packit Service fa4841
	}
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
#pragma mark -
Packit Service fa4841
#pragma mark Private Methods
Packit Service fa4841
Packit Service fa4841
- (CGPoint)getPositionFor:(id)point toast:(UIView *)toast
Packit Service fa4841
{
Packit Service fa4841
Packit Service fa4841
	/*************************************************************************************
Packit Service fa4841
	 *                                                                                   *
Packit Service fa4841
	 * Converts string literals @"top", @"bottom", @"center", or any point wrapped in an *
Packit Service fa4841
	 * NSValue object into a CGPoint                                                     *
Packit Service fa4841
	 *                                                                                   *
Packit Service fa4841
	 *************************************************************************************/
Packit Service fa4841
Packit Service fa4841
	if ([point isKindOfClass:[NSString class]])
Packit Service fa4841
	{
Packit Service fa4841
Packit Service fa4841
		if ([point caseInsensitiveCompare:@"top"] == NSOrderedSame)
Packit Service fa4841
		{
Packit Service fa4841
			return CGPointMake(self.bounds.size.width / 2,
Packit Service fa4841
			                   (toast.frame.size.height / 2) + kVerticalPadding);
Packit Service fa4841
		}
Packit Service fa4841
		else if ([point caseInsensitiveCompare:@"bottom"] == NSOrderedSame)
Packit Service fa4841
		{
Packit Service fa4841
			return CGPointMake(self.bounds.size.width / 2,
Packit Service fa4841
			                   (self.bounds.size.height - (toast.frame.size.height / 2)) -
Packit Service fa4841
			                       kVerticalPadding);
Packit Service fa4841
		}
Packit Service fa4841
		else if ([point caseInsensitiveCompare:@"center"] == NSOrderedSame)
Packit Service fa4841
		{
Packit Service fa4841
			return CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
	else if ([point isKindOfClass:[NSValue class]])
Packit Service fa4841
	{
Packit Service fa4841
		return [point CGPointValue];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	NSLog(@"Error: Invalid position for toast.");
Packit Service fa4841
	return [self getPositionFor:kDefaultPosition toast:toast];
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
- (UIView *)makeViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image
Packit Service fa4841
{
Packit Service fa4841
Packit Service fa4841
	/***********************************************************************************
Packit Service fa4841
	 *                                                                                 *
Packit Service fa4841
	 * Dynamically build a toast view with any combination of message, title, & image. *
Packit Service fa4841
	 *                                                                                 *
Packit Service fa4841
	 ***********************************************************************************/
Packit Service fa4841
Packit Service fa4841
	if ((message == nil) && (title == nil) && (image == nil))
Packit Service fa4841
		return nil;
Packit Service fa4841
Packit Service fa4841
	UILabel *messageLabel = nil;
Packit Service fa4841
	UILabel *titleLabel = nil;
Packit Service fa4841
	UIImageView *imageView = nil;
Packit Service fa4841
Packit Service fa4841
	// create the parent view
Packit Service fa4841
	UIView *wrapperView = [[[UIView alloc] init] autorelease];
Packit Service fa4841
	[wrapperView.layer setCornerRadius:kCornerRadius];
Packit Service fa4841
	[wrapperView setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:kOpacity]];
Packit Service fa4841
	wrapperView.autoresizingMask =
Packit Service fa4841
	    UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin |
Packit Service fa4841
	    UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
Packit Service fa4841
Packit Service fa4841
	if (image != nil)
Packit Service fa4841
	{
Packit Service fa4841
		imageView = [[[UIImageView alloc] initWithImage:image] autorelease];
Packit Service fa4841
		[imageView setContentMode:UIViewContentModeScaleAspectFit];
Packit Service fa4841
		[imageView
Packit Service fa4841
		    setFrame:CGRectMake(kHorizontalPadding, kVerticalPadding, kImageWidth, kImageHeight)];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	float imageWidth, imageHeight, imageLeft;
Packit Service fa4841
Packit Service fa4841
	// the imageView frame values will be used to size & position the other views
Packit Service fa4841
	if (imageView != nil)
Packit Service fa4841
	{
Packit Service fa4841
		imageWidth = imageView.bounds.size.width;
Packit Service fa4841
		imageHeight = imageView.bounds.size.height;
Packit Service fa4841
		imageLeft = kHorizontalPadding;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		imageWidth = imageHeight = imageLeft = 0;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (title != nil)
Packit Service fa4841
	{
Packit Service fa4841
		titleLabel = [[[UILabel alloc] init] autorelease];
Packit Service fa4841
		[titleLabel setNumberOfLines:kMaxTitleLines];
Packit Service fa4841
		[titleLabel setFont:[UIFont boldSystemFontOfSize:kFontSize]];
Packit Service fa4841
		[titleLabel setTextAlignment:UITextAlignmentLeft];
Packit Service fa4841
		[titleLabel setLineBreakMode:UILineBreakModeWordWrap];
Packit Service fa4841
		[titleLabel setTextColor:[UIColor whiteColor]];
Packit Service fa4841
		[titleLabel setBackgroundColor:[UIColor clearColor]];
Packit Service fa4841
		[titleLabel setAlpha:1.0];
Packit Service fa4841
		[titleLabel setText:title];
Packit Service fa4841
Packit Service fa4841
		// size the title label according to the length of the text
Packit Service fa4841
		CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * kMaxWidth) - imageWidth,
Packit Service fa4841
		                                 self.bounds.size.height * kMaxHeight);
Packit Service fa4841
		CGSize expectedSizeTitle = [title sizeWithFont:titleLabel.font
Packit Service fa4841
		                             constrainedToSize:maxSizeTitle
Packit Service fa4841
		                                 lineBreakMode:titleLabel.lineBreakMode];
Packit Service fa4841
		[titleLabel setFrame:CGRectMake(0, 0, expectedSizeTitle.width, expectedSizeTitle.height)];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (message != nil)
Packit Service fa4841
	{
Packit Service fa4841
		messageLabel = [[[UILabel alloc] init] autorelease];
Packit Service fa4841
		[messageLabel setNumberOfLines:kMaxMessageLines];
Packit Service fa4841
		[messageLabel setFont:[UIFont systemFontOfSize:kFontSize]];
Packit Service fa4841
		[messageLabel setLineBreakMode:UILineBreakModeWordWrap];
Packit Service fa4841
		[messageLabel setTextColor:[UIColor whiteColor]];
Packit Service fa4841
		[messageLabel setTextAlignment:UITextAlignmentCenter];
Packit Service fa4841
		[messageLabel setBackgroundColor:[UIColor clearColor]];
Packit Service fa4841
		[messageLabel setAlpha:1.0];
Packit Service fa4841
		[messageLabel setText:message];
Packit Service fa4841
Packit Service fa4841
		// size the message label according to the length of the text
Packit Service fa4841
		CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * kMaxWidth) - imageWidth,
Packit Service fa4841
		                                   self.bounds.size.height * kMaxHeight);
Packit Service fa4841
		CGSize expectedSizeMessage = [message sizeWithFont:messageLabel.font
Packit Service fa4841
		                                 constrainedToSize:maxSizeMessage
Packit Service fa4841
		                                     lineBreakMode:messageLabel.lineBreakMode];
Packit Service fa4841
		[messageLabel
Packit Service fa4841
		    setFrame:CGRectMake(0, 0, expectedSizeMessage.width, expectedSizeMessage.height)];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	// titleLabel frame values
Packit Service fa4841
	float titleWidth, titleHeight, titleTop, titleLeft;
Packit Service fa4841
Packit Service fa4841
	if (titleLabel != nil)
Packit Service fa4841
	{
Packit Service fa4841
		titleWidth = titleLabel.bounds.size.width;
Packit Service fa4841
		titleHeight = titleLabel.bounds.size.height;
Packit Service fa4841
		titleTop = kVerticalPadding;
Packit Service fa4841
		titleLeft = imageLeft + imageWidth + kHorizontalPadding;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		titleWidth = titleHeight = titleTop = titleLeft = 0;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	// messageLabel frame values
Packit Service fa4841
	float messageWidth, messageHeight, messageLeft, messageTop;
Packit Service fa4841
Packit Service fa4841
	if (messageLabel != nil)
Packit Service fa4841
	{
Packit Service fa4841
		messageWidth = messageLabel.bounds.size.width;
Packit Service fa4841
		messageHeight = messageLabel.bounds.size.height;
Packit Service fa4841
		messageLeft = imageLeft + imageWidth + kHorizontalPadding;
Packit Service fa4841
		messageTop = titleTop + titleHeight + kVerticalPadding;
Packit Service fa4841
	}
Packit Service fa4841
	else
Packit Service fa4841
	{
Packit Service fa4841
		messageWidth = messageHeight = messageLeft = messageTop = 0;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	// compare the title & message widths and use the longer value to calculate the size of the
Packit Service fa4841
	// wrapper width the same logic applies to the x value (left)
Packit Service fa4841
	float longerWidth = (messageWidth < titleWidth) ? titleWidth : messageWidth;
Packit Service fa4841
	float longerLeft = (messageLeft < titleLeft) ? titleLeft : messageLeft;
Packit Service fa4841
Packit Service fa4841
	// if the image width is larger than longerWidth, use the image width to calculate the wrapper
Packit Service fa4841
	// width. the same logic applies to the wrapper height
Packit Service fa4841
	float wrapperWidth =
Packit Service fa4841
	    ((longerLeft + longerWidth + kHorizontalPadding) < imageWidth + (kHorizontalPadding * 2))
Packit Service fa4841
	        ? imageWidth + (kHorizontalPadding * 2)
Packit Service fa4841
	        : (longerLeft + longerWidth + kHorizontalPadding);
Packit Service fa4841
	float wrapperHeight =
Packit Service fa4841
	    ((messageTop + messageHeight + kVerticalPadding) < imageHeight + (kVerticalPadding * 2))
Packit Service fa4841
	        ? imageHeight + (kVerticalPadding * 2)
Packit Service fa4841
	        : (messageTop + messageHeight + kVerticalPadding);
Packit Service fa4841
Packit Service fa4841
	[wrapperView setFrame:CGRectMake(0, 0, wrapperWidth, wrapperHeight)];
Packit Service fa4841
Packit Service fa4841
	if (titleLabel != nil)
Packit Service fa4841
	{
Packit Service fa4841
		[titleLabel setFrame:CGRectMake(titleLeft, titleTop, titleWidth, titleHeight)];
Packit Service fa4841
		[wrapperView addSubview:titleLabel];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (messageLabel != nil)
Packit Service fa4841
	{
Packit Service fa4841
		[messageLabel setFrame:CGRectMake(messageLeft, messageTop, messageWidth, messageHeight)];
Packit Service fa4841
		[wrapperView addSubview:messageLabel];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (imageView != nil)
Packit Service fa4841
	{
Packit Service fa4841
		[wrapperView addSubview:imageView];
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	return wrapperView;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
@end