diff --git a/MPNotificationView/MPNotificationView.h b/MPNotificationView/MPNotificationView.h new file mode 100644 index 0000000..4e560f7 --- /dev/null +++ b/MPNotificationView/MPNotificationView.h @@ -0,0 +1,26 @@ +// +// MPNotificationView.h +// Moped +// +// Created by Engin Kurutepe on 1/2/13. +// Copyright (c) 2013 Moped Inc. All rights reserved. +// + +#import + +@interface MPNotificationView : UIView + +@property (nonatomic, strong) UILabel * textLabel; +@property (nonatomic, strong) UILabel * detailTextLabel; +@property (nonatomic, strong) UIImageView * imageView; + +@property (nonatomic) NSTimeInterval duration; + ++ (void) notifyWithText:(NSString*)text + detail:(NSString*)detail + image:(UIImage*)image + andDuration:(NSTimeInterval)duration; ++ (void) notifyWithText:(NSString*)text andDetail:(NSString*)detail andDuration:(NSTimeInterval)duration; ++ (void) notifyWithText:(NSString*)text andDetail:(NSString*)detail; + +@end diff --git a/MPNotificationView/MPNotificationView.m b/MPNotificationView/MPNotificationView.m new file mode 100644 index 0000000..439d0e7 --- /dev/null +++ b/MPNotificationView/MPNotificationView.m @@ -0,0 +1,401 @@ +// +// MPNotificationView.m +// Moped +// +// Created by Engin Kurutepe on 1/2/13. +// Copyright (c) 2013 Moped Inc. All rights reserved. +// + +#import "MPNotificationView.h" +#import "OBGradientView.h" + +#define kMPNotificationHeight 40.0f + +#pragma mark MPNotificationWindow +@interface MPNotificationWindow : UIWindow + +@property (nonatomic, strong) NSMutableArray * notificationQueue; +@property (nonatomic, strong) UIView * currentNotification; + +@end + +@implementation MPNotificationWindow + +- (id) initWithFrame:(CGRect)frame { + + BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation); + CGRect actualFrame = frame; + if (isPortrait) { + actualFrame.size.height = kMPNotificationHeight; + } + else { + actualFrame.size.width = kMPNotificationHeight; + } + + + self = [super initWithFrame:actualFrame]; + if (self) { + self.windowLevel = UIWindowLevelStatusBar + 1; + self.notificationQueue = [[NSMutableArray alloc] initWithCapacity:4]; + self.currentNotification = nil; + self.backgroundColor = [UIColor clearColor]; + UIView * topHalfBlackView = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMinX(actualFrame), + CGRectGetMinY(actualFrame), + CGRectGetWidth(actualFrame), + 0.5*CGRectGetHeight(actualFrame))]; + + topHalfBlackView.backgroundColor = [UIColor blackColor]; + topHalfBlackView.layer.zPosition = -100; + topHalfBlackView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self addSubview:topHalfBlackView]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(willRotateScreen:) + name:UIApplicationWillChangeStatusBarFrameNotification object:nil]; + + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + + [self rotateStatusBarWithFrame:[NSValue valueWithCGRect:statusBarFrame]]; + + } + return self; +} + +- (void)willRotateScreen:(NSNotification *)notification { + NSValue *frameValue = [notification.userInfo valueForKey:UIApplicationStatusBarFrameUserInfoKey]; + + NSLog(@"will rotate to: %@", NSStringFromCGRect([frameValue CGRectValue]) ); + if (NO == self.hidden) { + [self rotateStatusBarAnimatedWithFrame:frameValue]; + } else { + [self rotateStatusBarWithFrame:frameValue]; + } +} + +- (void)rotateStatusBarAnimatedWithFrame:(NSValue *)frameValue { + + CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration; + [UIView animateWithDuration:duration animations:^{ + self.alpha = 0; + } completion:^(BOOL finished) { + [self rotateStatusBarWithFrame:frameValue]; + [UIView animateWithDuration:duration animations:^{ + self.alpha = 1; + }]; + }]; +} + + +- (void)rotateStatusBarWithFrame:(NSValue *)frameValue { + CGRect frame = [frameValue CGRectValue]; + + if (frame.size.height == 20) { + frame.size.height = kMPNotificationHeight; + NSLog(@"portrait frame: %@", NSStringFromCGRect(frame)); + if (frame.origin.y > 0) { + // upside down + self.transform = CGAffineTransformMakeRotation(M_PI); + } + else { + self.transform = CGAffineTransformIdentity; + } + } + else if (frame.size.width == 20) { + frame.size.width = kMPNotificationHeight; + if (frame.origin.x > 0) { + frame.origin.x = 280; + self.transform = CGAffineTransformMakeRotation(M_PI * 90.0f / 180.0f); + } + else { + self.transform = CGAffineTransformMakeRotation(M_PI * (-90.0f) / 180.0f); + } + NSLog(@"landscape frame: %@", NSStringFromCGRect(frame)); + } + + self.frame = frame; + +} + +@end + + + +static MPNotificationWindow * __notificationWindow = nil; + +#pragma mark - +#pragma mark MPNotificationView + +@interface MPNotificationView () + + +@property (nonatomic, strong) OBGradientView * contentView; + ++ (void) showNextNotification; ++ (UIImage*) screenImageWithRect:(CGRect)rect; + +@end + +@implementation MPNotificationView + +- (id)initWithFrame:(CGRect)frame +{ + BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation); + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + CGFloat statusBarWidth = (isPortrait) ? statusBarFrame.size.width : statusBarFrame.size.height; + + + + self = [super initWithFrame:frame]; + if (self) { + self.autoresizingMask = UIViewAutoresizingFlexibleWidth; + + self.contentView = [[OBGradientView alloc] initWithFrame:self.bounds]; + self.contentView.colors = @[(id)[[UIColor colorWithWhite:0.99 alpha:1.0] CGColor], + (id)[[UIColor colorWithWhite:0.9 alpha:1.0] CGColor]]; + + self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth; + self.contentView.layer.cornerRadius = 8.f; + [self addSubview:self.contentView]; + + self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(6, 6, 28, 28)]; + self.imageView.contentMode = UIViewContentModeScaleAspectFill; + self.imageView.layer.cornerRadius = 4.f; + self.imageView.clipsToBounds = YES; + + [self addSubview:self.imageView]; + + + UIFont *textFont = [UIFont boldSystemFontOfSize:14.f]; + CGRect textFrame = CGRectMake(8+CGRectGetMaxX(self.imageView.frame), + 2, + statusBarWidth - 16- CGRectGetMaxX(self.imageView.frame), + textFont.lineHeight); + self.textLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + self.textLabel.frame = textFrame; + self.textLabel.backgroundColor = [UIColor clearColor]; + self.textLabel.font = textFont; + self.textLabel.textAlignment = NSTextAlignmentLeft; + self.textLabel.numberOfLines = 1; + self.textLabel.lineBreakMode = NSLineBreakByTruncatingTail; + [self.contentView addSubview:self.textLabel]; + + + UIFont *detailFont = [UIFont systemFontOfSize:13.f]; + CGRect detailFrame = CGRectMake(CGRectGetMinX(textFrame), + CGRectGetMaxY(textFrame), + statusBarWidth - 16 - CGRectGetMaxX(self.imageView.frame), + detailFont.lineHeight); + + self.detailTextLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + self.detailTextLabel.frame = detailFrame; + self.detailTextLabel.backgroundColor = [UIColor clearColor]; + self.detailTextLabel.font = detailFont; + self.detailTextLabel.textAlignment = NSTextAlignmentLeft; + self.detailTextLabel.numberOfLines = 1; + self.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingTail; + [self.contentView addSubview:self.detailTextLabel]; + + UIView * bottomLine = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetMinX(frame), + CGRectGetHeight(frame)-1.0f, + CGRectGetWidth(frame), + 1.f)]; + + bottomLine.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; + + [self.contentView addSubview:bottomLine]; + self.contentView.clipsToBounds = YES; + + } + return self; +} + + + ++ (void) notifyWithText:(NSString*)text andDetail:(NSString*)detail +{ + [self notifyWithText:text andDetail:detail andDuration:2.0]; +} + ++ (void) notifyWithText:(NSString*)text andDetail:(NSString*)detail andDuration:(NSTimeInterval)duration +{ + [self notifyWithText:text detail:detail image:nil andDuration:duration]; +} + ++ (void) notifyWithText:(NSString*)text + detail:(NSString*)detail + image:(UIImage*)image + andDuration:(NSTimeInterval)duration +{ + + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + + if (__notificationWindow == nil) { + BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation); + if (isPortrait) { + statusBarFrame.size.height = kMPNotificationHeight; + } + else { + statusBarFrame.size.width = kMPNotificationHeight; + } + __notificationWindow = [[MPNotificationWindow alloc] initWithFrame:statusBarFrame]; + __notificationWindow.hidden = NO; + } + + MPNotificationView * notification = [[MPNotificationView alloc] initWithFrame:__notificationWindow.bounds]; + + notification.textLabel.text = text; + notification.detailTextLabel.text = detail; + notification.imageView.image = image; + notification.duration = duration; + + [__notificationWindow.notificationQueue addObject:notification]; + + if (__notificationWindow.currentNotification == nil) { + [self showNextNotification]; + } +} + ++ (void) showNextNotification { + + + UIView * viewToRotateOut = nil; + + if (__notificationWindow.currentNotification) { + viewToRotateOut = __notificationWindow.currentNotification; + + } + else { + viewToRotateOut = [[UIImageView alloc] initWithImage: + [self screenImageWithRect:__notificationWindow.frame]]; + viewToRotateOut.frame = __notificationWindow.bounds; + [__notificationWindow addSubview:viewToRotateOut]; + __notificationWindow.hidden = NO; + } + + + UIView * viewToRotateIn = nil; + + + + if ([__notificationWindow.notificationQueue count]) { + + + MPNotificationView * nextNotification = [__notificationWindow.notificationQueue objectAtIndex:0]; + + viewToRotateIn = nextNotification; + + + } + else { + viewToRotateIn = [[UIImageView alloc] initWithImage: + [self screenImageWithRect:__notificationWindow.frame]]; +// viewToRotateIn.transform = __notificationWindow.transform; + viewToRotateIn.frame = __notificationWindow.bounds; + } + + + + + + viewToRotateIn.layer.anchorPointZ = 11.547f; + viewToRotateIn.layer.doubleSided = NO; + viewToRotateIn.layer.zPosition = 2; + + + CATransform3D viewInStartTransform = CATransform3DMakeRotation(-2*M_PI/3, 1.0, 0.0, 0.0); + viewInStartTransform.m34 = -1.0/200.0; + + + viewToRotateOut.layer.anchorPointZ = 11.547f; + viewToRotateOut.layer.doubleSided = NO; + viewToRotateOut.layer.zPosition = 2; + + CATransform3D viewOutEndTransform = CATransform3DMakeRotation(2*M_PI/3, 1.0, 0.0, 0.0); + viewOutEndTransform.m34 = -1.0/200.0; + + [__notificationWindow addSubview:viewToRotateIn]; + __notificationWindow.backgroundColor = [UIColor blackColor]; + + viewToRotateIn.layer.transform = viewInStartTransform; + + if ([viewToRotateIn isKindOfClass:[MPNotificationView class]] ){ + MPNotificationView * notification = (MPNotificationView*)viewToRotateIn; + __notificationWindow.currentNotification = notification; + } + [UIView animateWithDuration:0.5 + animations:^{ + viewToRotateIn.layer.transform = CATransform3DIdentity; + viewToRotateOut.layer.transform = viewOutEndTransform; + } + completion:^(BOOL finished) { + __notificationWindow.backgroundColor = [UIColor clearColor]; + [viewToRotateOut removeFromSuperview]; + if ([__notificationWindow.notificationQueue containsObject:viewToRotateOut]) { + [__notificationWindow.notificationQueue removeObject:viewToRotateOut]; + } + if ([viewToRotateIn isKindOfClass:[MPNotificationView class]] ){ + MPNotificationView * notification = (MPNotificationView*)viewToRotateIn; + + int64_t delayInSeconds = notification.duration; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + [self showNextNotification]; + }); + + __notificationWindow.currentNotification = notification; + [__notificationWindow.notificationQueue removeObject:notification]; + + } + else { + [viewToRotateIn removeFromSuperview]; + __notificationWindow.hidden = YES; + __notificationWindow.currentNotification = nil; + } + + }]; + + +} + ++ (UIImage*) screenImageWithRect:(CGRect)rect +{ + NSLog(@"capture: %@", NSStringFromCGRect(rect)); + CALayer * layer = [[UIApplication sharedApplication] keyWindow].layer; + + UIGraphicsBeginImageContext(layer.frame.size); + + [layer renderInContext:UIGraphicsGetCurrentContext()]; + UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); + NSLog(@"screenshot size %@", NSStringFromCGSize(screenshot.size)); + UIGraphicsEndImageContext(); + + CGImageRef imageRef = CGImageCreateWithImageInRect([screenshot CGImage], rect); + UIImage *croppedScreenshot = [UIImage imageWithCGImage:imageRef]; + CGImageRelease(imageRef); + + NSLog(@"crop size %@", NSStringFromCGSize(croppedScreenshot.size)); + + + UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; + UIImageOrientation imageOrientation; + if (UIDeviceOrientationPortrait == orientation) { + imageOrientation = UIImageOrientationUp; + } else if (UIDeviceOrientationPortraitUpsideDown == orientation) { + imageOrientation = UIImageOrientationDown; + } else if (UIDeviceOrientationLandscapeRight == orientation) { + imageOrientation = UIImageOrientationRight; + } else { + imageOrientation = UIImageOrientationLeft; + } + + UIImage * rotatedImage = [[UIImage alloc] initWithCGImage:croppedScreenshot.CGImage + scale:croppedScreenshot.scale + orientation:imageOrientation]; + NSLog(@"orientation %d", rotatedImage.imageOrientation); + + return rotatedImage; +} + + + +@end diff --git a/MPNotificationViewTest.xcodeproj/project.pbxproj b/MPNotificationViewTest.xcodeproj/project.pbxproj new file mode 100644 index 0000000..77b2ffd --- /dev/null +++ b/MPNotificationViewTest.xcodeproj/project.pbxproj @@ -0,0 +1,335 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 870D5CFA1696DA5A00AB84FB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 870D5CF91696DA5A00AB84FB /* UIKit.framework */; }; + 870D5CFC1696DA5A00AB84FB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 870D5CFB1696DA5A00AB84FB /* Foundation.framework */; }; + 870D5CFE1696DA5A00AB84FB /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 870D5CFD1696DA5A00AB84FB /* CoreGraphics.framework */; }; + 870D5D041696DA5A00AB84FB /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 870D5D021696DA5A00AB84FB /* InfoPlist.strings */; }; + 870D5D061696DA5A00AB84FB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 870D5D051696DA5A00AB84FB /* main.m */; }; + 870D5D0A1696DA5A00AB84FB /* MPAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 870D5D091696DA5A00AB84FB /* MPAppDelegate.m */; }; + 870D5D0C1696DA5A00AB84FB /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 870D5D0B1696DA5A00AB84FB /* Default.png */; }; + 870D5D0E1696DA5A00AB84FB /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 870D5D0D1696DA5A00AB84FB /* Default@2x.png */; }; + 870D5D101696DA5A00AB84FB /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 870D5D0F1696DA5A00AB84FB /* Default-568h@2x.png */; }; + 870D5D131696DA5A00AB84FB /* MainStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 870D5D111696DA5A00AB84FB /* MainStoryboard.storyboard */; }; + 870D5D161696DA5A00AB84FB /* MPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 870D5D151696DA5A00AB84FB /* MPViewController.m */; }; + 870D5D231696DA9E00AB84FB /* MPNotificationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 870D5D221696DA9E00AB84FB /* MPNotificationView.m */; }; + 870D5D281696DC9400AB84FB /* OBGradientView.m in Sources */ = {isa = PBXBuildFile; fileRef = 870D5D271696DC9400AB84FB /* OBGradientView.m */; }; + 870D5D2A1696DD3400AB84FB /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 870D5D291696DD3400AB84FB /* QuartzCore.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 870D5CF51696DA5A00AB84FB /* MPNotificationViewTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MPNotificationViewTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 870D5CF91696DA5A00AB84FB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 870D5CFB1696DA5A00AB84FB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 870D5CFD1696DA5A00AB84FB /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 870D5D011696DA5A00AB84FB /* MPNotificationViewTest-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MPNotificationViewTest-Info.plist"; sourceTree = ""; }; + 870D5D031696DA5A00AB84FB /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 870D5D051696DA5A00AB84FB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 870D5D071696DA5A00AB84FB /* MPNotificationViewTest-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MPNotificationViewTest-Prefix.pch"; sourceTree = ""; }; + 870D5D081696DA5A00AB84FB /* MPAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate.h; sourceTree = ""; }; + 870D5D091696DA5A00AB84FB /* MPAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate.m; sourceTree = ""; }; + 870D5D0B1696DA5A00AB84FB /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; + 870D5D0D1696DA5A00AB84FB /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; + 870D5D0F1696DA5A00AB84FB /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 870D5D121696DA5A00AB84FB /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = ""; }; + 870D5D141696DA5A00AB84FB /* MPViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPViewController.h; sourceTree = ""; }; + 870D5D151696DA5A00AB84FB /* MPViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPViewController.m; sourceTree = ""; }; + 870D5D211696DA9E00AB84FB /* MPNotificationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNotificationView.h; sourceTree = ""; }; + 870D5D221696DA9E00AB84FB /* MPNotificationView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPNotificationView.m; sourceTree = ""; }; + 870D5D261696DC9400AB84FB /* OBGradientView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OBGradientView.h; sourceTree = ""; }; + 870D5D271696DC9400AB84FB /* OBGradientView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OBGradientView.m; sourceTree = ""; }; + 870D5D291696DD3400AB84FB /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 870D5CF21696DA5A00AB84FB /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 870D5D2A1696DD3400AB84FB /* QuartzCore.framework in Frameworks */, + 870D5CFA1696DA5A00AB84FB /* UIKit.framework in Frameworks */, + 870D5CFC1696DA5A00AB84FB /* Foundation.framework in Frameworks */, + 870D5CFE1696DA5A00AB84FB /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 870D5CEA1696DA5A00AB84FB = { + isa = PBXGroup; + children = ( + 870D5D291696DD3400AB84FB /* QuartzCore.framework */, + 870D5D251696DC9400AB84FB /* OBGradientView */, + 870D5D201696DA9E00AB84FB /* MPNotificationView */, + 870D5CFF1696DA5A00AB84FB /* MPNotificationViewTest */, + 870D5CF81696DA5A00AB84FB /* Frameworks */, + 870D5CF61696DA5A00AB84FB /* Products */, + ); + sourceTree = ""; + }; + 870D5CF61696DA5A00AB84FB /* Products */ = { + isa = PBXGroup; + children = ( + 870D5CF51696DA5A00AB84FB /* MPNotificationViewTest.app */, + ); + name = Products; + sourceTree = ""; + }; + 870D5CF81696DA5A00AB84FB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 870D5CF91696DA5A00AB84FB /* UIKit.framework */, + 870D5CFB1696DA5A00AB84FB /* Foundation.framework */, + 870D5CFD1696DA5A00AB84FB /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 870D5CFF1696DA5A00AB84FB /* MPNotificationViewTest */ = { + isa = PBXGroup; + children = ( + 870D5D081696DA5A00AB84FB /* MPAppDelegate.h */, + 870D5D091696DA5A00AB84FB /* MPAppDelegate.m */, + 870D5D111696DA5A00AB84FB /* MainStoryboard.storyboard */, + 870D5D141696DA5A00AB84FB /* MPViewController.h */, + 870D5D151696DA5A00AB84FB /* MPViewController.m */, + 870D5D001696DA5A00AB84FB /* Supporting Files */, + ); + path = MPNotificationViewTest; + sourceTree = ""; + }; + 870D5D001696DA5A00AB84FB /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 870D5D011696DA5A00AB84FB /* MPNotificationViewTest-Info.plist */, + 870D5D021696DA5A00AB84FB /* InfoPlist.strings */, + 870D5D051696DA5A00AB84FB /* main.m */, + 870D5D071696DA5A00AB84FB /* MPNotificationViewTest-Prefix.pch */, + 870D5D0B1696DA5A00AB84FB /* Default.png */, + 870D5D0D1696DA5A00AB84FB /* Default@2x.png */, + 870D5D0F1696DA5A00AB84FB /* Default-568h@2x.png */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 870D5D201696DA9E00AB84FB /* MPNotificationView */ = { + isa = PBXGroup; + children = ( + 870D5D211696DA9E00AB84FB /* MPNotificationView.h */, + 870D5D221696DA9E00AB84FB /* MPNotificationView.m */, + ); + path = MPNotificationView; + sourceTree = ""; + }; + 870D5D251696DC9400AB84FB /* OBGradientView */ = { + isa = PBXGroup; + children = ( + 870D5D261696DC9400AB84FB /* OBGradientView.h */, + 870D5D271696DC9400AB84FB /* OBGradientView.m */, + ); + path = OBGradientView; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 870D5CF41696DA5A00AB84FB /* MPNotificationViewTest */ = { + isa = PBXNativeTarget; + buildConfigurationList = 870D5D191696DA5A00AB84FB /* Build configuration list for PBXNativeTarget "MPNotificationViewTest" */; + buildPhases = ( + 870D5CF11696DA5A00AB84FB /* Sources */, + 870D5CF21696DA5A00AB84FB /* Frameworks */, + 870D5CF31696DA5A00AB84FB /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MPNotificationViewTest; + productName = MPNotificationViewTest; + productReference = 870D5CF51696DA5A00AB84FB /* MPNotificationViewTest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 870D5CEC1696DA5A00AB84FB /* Project object */ = { + isa = PBXProject; + attributes = { + CLASSPREFIX = MP; + LastUpgradeCheck = 0450; + ORGANIZATIONNAME = "Moped Inc."; + }; + buildConfigurationList = 870D5CEF1696DA5A00AB84FB /* Build configuration list for PBXProject "MPNotificationViewTest" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 870D5CEA1696DA5A00AB84FB; + productRefGroup = 870D5CF61696DA5A00AB84FB /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 870D5CF41696DA5A00AB84FB /* MPNotificationViewTest */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 870D5CF31696DA5A00AB84FB /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 870D5D041696DA5A00AB84FB /* InfoPlist.strings in Resources */, + 870D5D0C1696DA5A00AB84FB /* Default.png in Resources */, + 870D5D0E1696DA5A00AB84FB /* Default@2x.png in Resources */, + 870D5D101696DA5A00AB84FB /* Default-568h@2x.png in Resources */, + 870D5D131696DA5A00AB84FB /* MainStoryboard.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 870D5CF11696DA5A00AB84FB /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 870D5D061696DA5A00AB84FB /* main.m in Sources */, + 870D5D0A1696DA5A00AB84FB /* MPAppDelegate.m in Sources */, + 870D5D161696DA5A00AB84FB /* MPViewController.m in Sources */, + 870D5D231696DA9E00AB84FB /* MPNotificationView.m in Sources */, + 870D5D281696DC9400AB84FB /* OBGradientView.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 870D5D021696DA5A00AB84FB /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 870D5D031696DA5A00AB84FB /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 870D5D111696DA5A00AB84FB /* MainStoryboard.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 870D5D121696DA5A00AB84FB /* en */, + ); + name = MainStoryboard.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 870D5D171696DA5A00AB84FB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 870D5D181696DA5A00AB84FB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 870D5D1A1696DA5A00AB84FB /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "MPNotificationViewTest/MPNotificationViewTest-Prefix.pch"; + INFOPLIST_FILE = "MPNotificationViewTest/MPNotificationViewTest-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 870D5D1B1696DA5A00AB84FB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "MPNotificationViewTest/MPNotificationViewTest-Prefix.pch"; + INFOPLIST_FILE = "MPNotificationViewTest/MPNotificationViewTest-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 4.3; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 870D5CEF1696DA5A00AB84FB /* Build configuration list for PBXProject "MPNotificationViewTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 870D5D171696DA5A00AB84FB /* Debug */, + 870D5D181696DA5A00AB84FB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 870D5D191696DA5A00AB84FB /* Build configuration list for PBXNativeTarget "MPNotificationViewTest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 870D5D1A1696DA5A00AB84FB /* Debug */, + 870D5D1B1696DA5A00AB84FB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 870D5CEC1696DA5A00AB84FB /* Project object */; +} diff --git a/MPNotificationViewTest/Default-568h@2x.png b/MPNotificationViewTest/Default-568h@2x.png new file mode 100644 index 0000000..0891b7a Binary files /dev/null and b/MPNotificationViewTest/Default-568h@2x.png differ diff --git a/MPNotificationViewTest/Default.png b/MPNotificationViewTest/Default.png new file mode 100644 index 0000000..4c8ca6f Binary files /dev/null and b/MPNotificationViewTest/Default.png differ diff --git a/MPNotificationViewTest/Default@2x.png b/MPNotificationViewTest/Default@2x.png new file mode 100644 index 0000000..35b84cf Binary files /dev/null and b/MPNotificationViewTest/Default@2x.png differ diff --git a/MPNotificationViewTest/MPAppDelegate.h b/MPNotificationViewTest/MPAppDelegate.h new file mode 100644 index 0000000..4439c70 --- /dev/null +++ b/MPNotificationViewTest/MPAppDelegate.h @@ -0,0 +1,15 @@ +// +// MPAppDelegate.h +// MPNotificationViewTest +// +// Created by Engin Kurutepe on 1/4/13. +// Copyright (c) 2013 Moped Inc. All rights reserved. +// + +#import + +@interface MPAppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/MPNotificationViewTest/MPAppDelegate.m b/MPNotificationViewTest/MPAppDelegate.m new file mode 100644 index 0000000..6c23c2e --- /dev/null +++ b/MPNotificationViewTest/MPAppDelegate.m @@ -0,0 +1,46 @@ +// +// MPAppDelegate.m +// MPNotificationViewTest +// +// Created by Engin Kurutepe on 1/4/13. +// Copyright (c) 2013 Moped Inc. All rights reserved. +// + +#import "MPAppDelegate.h" + +@implementation MPAppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/MPNotificationViewTest/MPNotificationViewTest-Info.plist b/MPNotificationViewTest/MPNotificationViewTest-Info.plist new file mode 100644 index 0000000..f87eb9e --- /dev/null +++ b/MPNotificationViewTest/MPNotificationViewTest-Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.moped.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIMainStoryboardFile + MainStoryboard + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/MPNotificationViewTest/MPNotificationViewTest-Prefix.pch b/MPNotificationViewTest/MPNotificationViewTest-Prefix.pch new file mode 100644 index 0000000..1ee4856 --- /dev/null +++ b/MPNotificationViewTest/MPNotificationViewTest-Prefix.pch @@ -0,0 +1,14 @@ +// +// Prefix header for all source files of the 'MPNotificationViewTest' target in the 'MPNotificationViewTest' project +// + +#import + +#ifndef __IPHONE_5_0 +#warning "This project uses features only available in iOS SDK 5.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/MPNotificationViewTest/MPViewController.h b/MPNotificationViewTest/MPViewController.h new file mode 100644 index 0000000..8ece50e --- /dev/null +++ b/MPNotificationViewTest/MPViewController.h @@ -0,0 +1,17 @@ +// +// MPViewController.h +// MPNotificationViewTest +// +// Created by Engin Kurutepe on 1/4/13. +// Copyright (c) 2013 Moped Inc. All rights reserved. +// + +#import + +@interface MPViewController : UIViewController + +-(IBAction) enqueueNotification1:(id)sender; +-(IBAction) enqueueNotification2:(id)sender; +-(IBAction) enqueueNotification3:(id)sender; + +@end diff --git a/MPNotificationViewTest/MPViewController.m b/MPNotificationViewTest/MPViewController.m new file mode 100644 index 0000000..0b2c66a --- /dev/null +++ b/MPNotificationViewTest/MPViewController.m @@ -0,0 +1,46 @@ +// +// MPViewController.m +// MPNotificationViewTest +// +// Created by Engin Kurutepe on 1/4/13. +// Copyright (c) 2013 Moped Inc. All rights reserved. +// + +#import "MPViewController.h" +#import "MPNotificationView.h" + +@interface MPViewController () + +@end + +@implementation MPViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + +-(IBAction) enqueueNotification1:(id)sender +{ + [MPNotificationView notifyWithText:@"Hello World!" andDetail:@"This is a test"]; +} + +-(IBAction) enqueueNotification2:(id)sender +{ + [MPNotificationView notifyWithText:@"Lorem Ipsum" andDetail:@"dolor sit amet"]; +} + +-(IBAction) enqueueNotification3:(id)sender +{ + [MPNotificationView notifyWithText:@"Grumpy wizards" andDetail:@"make a toxic brew for the jovial queen"]; +} + +@end diff --git a/MPNotificationViewTest/en.lproj/InfoPlist.strings b/MPNotificationViewTest/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/MPNotificationViewTest/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/MPNotificationViewTest/en.lproj/MainStoryboard.storyboard b/MPNotificationViewTest/en.lproj/MainStoryboard.storyboard new file mode 100644 index 0000000..ca2761d --- /dev/null +++ b/MPNotificationViewTest/en.lproj/MainStoryboard.storyboard @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MPNotificationViewTest/main.m b/MPNotificationViewTest/main.m new file mode 100644 index 0000000..532cc74 --- /dev/null +++ b/MPNotificationViewTest/main.m @@ -0,0 +1,18 @@ +// +// main.m +// MPNotificationViewTest +// +// Created by Engin Kurutepe on 1/4/13. +// Copyright (c) 2013 Moped Inc. All rights reserved. +// + +#import + +#import "MPAppDelegate.h" + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([MPAppDelegate class])); + } +} diff --git a/OBGradientView/OBGradientView.h b/OBGradientView/OBGradientView.h new file mode 100755 index 0000000..758b796 --- /dev/null +++ b/OBGradientView/OBGradientView.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2010 Ole Begemann + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/* + OBGradientView.h + + Created by Ole Begemann + April, 2010 + */ + + +#import +#import + + +/* + OBGradientView is a simple UIView wrapper for CAGradientLayer. It is a plain UIView whose layer + is a CAGradientLayer. It is useful if using a view is more convenient than using a layer, e.g. + because you want to use autoresizing masks. + + OBGradientView exposes all of the layer's gradient-related properties. + The getters and setters just forward the calls to the layer so the syntax is just the same as + for CAGradientLayer's properties itself. See the documentation for CAGradientLayer for details: + http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Reference/CAGradientLayer_class/Reference/Reference.html + + The one exception to this is the colors property: in addition to an array of CGColorRefs, + it also accepts an array of UIColor objects. Likewise, the getter returns an array of UIColors. + If you need CGColorRefs, access gradientLayer.colors instead. + */ + + +@interface OBGradientView : UIView { +} + +// Returns the view's layer. Useful if you want to access CAGradientLayer-specific properties +// because you can omit the typecast. +@property (nonatomic, readonly) CAGradientLayer *gradientLayer; + +// Gradient-related properties are forwarded to layer. +// colors also accepts array of UIColor objects (in addition to array of CGColorRefs). +@property (nonatomic, retain) NSArray *colors; +@property (nonatomic, retain) NSArray *locations; +@property (nonatomic) CGPoint startPoint; +@property (nonatomic) CGPoint endPoint; +@property (nonatomic, copy) NSString *type; + +@end diff --git a/OBGradientView/OBGradientView.m b/OBGradientView/OBGradientView.m new file mode 100755 index 0000000..05dfe09 --- /dev/null +++ b/OBGradientView/OBGradientView.m @@ -0,0 +1,141 @@ +/* + Copyright (c) 2010 Ole Begemann + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +/* + OBGradientView.m + + Created by Ole Begemann + April, 2010 + */ + +#import "OBGradientView.h" + + + +#pragma mark - +#pragma mark Implementation + +@implementation OBGradientView + +@dynamic gradientLayer; +@dynamic colors, locations, startPoint, endPoint, type; + + +// Make the view's layer a CAGradientLayer instance ++ (Class)layerClass +{ + return [CAGradientLayer class]; +} + + + +// Convenience property access to the layer help omit typecasts +- (CAGradientLayer *)gradientLayer +{ + return (CAGradientLayer *)self.layer; +} + + + +#pragma mark - +#pragma mark Gradient-related properties + +- (NSArray *)colors +{ + NSArray *cgColors = self.gradientLayer.colors; + if (cgColors == nil) { + return nil; + } + + // Convert CGColorRefs to UIColor objects + NSMutableArray *uiColors = [NSMutableArray arrayWithCapacity:[cgColors count]]; + for (id cgColor in cgColors) { + [uiColors addObject:[UIColor colorWithCGColor:(CGColorRef)cgColor]]; + } + return [NSArray arrayWithArray:uiColors]; +} + + +// The colors property accepts an array of CGColorRefs or UIColor objects (or mixes between the two). +// UIColors are converted to CGColor before forwarding the values to the layer. +- (void)setColors:(NSArray *)newColors +{ + NSMutableArray *newCGColors = nil; + + if (newColors != nil) { + newCGColors = [NSMutableArray arrayWithCapacity:[newColors count]]; + for (id color in newColors) { + // If the array contains a UIColor, convert it to CGColor. + // Leave all other types untouched. + if ([color isKindOfClass:[UIColor class]]) { + [newCGColors addObject:(id)[color CGColor]]; + } else { + [newCGColors addObject:color]; + } + } + } + + self.gradientLayer.colors = newCGColors; +} + + +- (NSArray *)locations +{ + return self.gradientLayer.locations; +} + +- (void)setLocations:(NSArray *)newLocations +{ + self.gradientLayer.locations = newLocations; +} + +- (CGPoint)startPoint +{ + return self.gradientLayer.startPoint; +} + +- (void)setStartPoint:(CGPoint)newStartPoint +{ + self.gradientLayer.startPoint = newStartPoint; +} + +- (CGPoint)endPoint +{ + return self.gradientLayer.endPoint; +} + +- (void)setEndPoint:(CGPoint)newEndPoint +{ + self.gradientLayer.endPoint = newEndPoint; +} + +- (NSString *)type +{ + return self.gradientLayer.type; +} + +- (void) setType:(NSString *)newType +{ + self.gradientLayer.type = newType; +} + +@end \ No newline at end of file