├── Pods ├── Reveal-iOS-SDK │ └── Reveal-Framework-1.5.1 │ │ └── Reveal.framework │ │ ├── Versions │ │ ├── Current │ │ └── A │ │ │ ├── Reveal │ │ │ └── Headers │ │ │ ├── Reveal.h │ │ │ ├── IBARevealLoader.h │ │ │ ├── IBANetServiceTypes.h │ │ │ └── IBARevealLogger.h │ │ ├── Headers │ │ └── Reveal ├── Target Support Files │ ├── Pods-KTSecretTextView │ │ ├── Pods-KTSecretTextView.xcconfig │ │ ├── Pods-KTSecretTextView-prefix.pch │ │ ├── Pods-KTSecretTextView-dummy.m │ │ └── Pods-KTSecretTextView-Private.xcconfig │ ├── Pods-UIImage-Resize │ │ ├── Pods-UIImage-Resize.xcconfig │ │ ├── Pods-UIImage-Resize-prefix.pch │ │ ├── Pods-UIImage-Resize-dummy.m │ │ └── Pods-UIImage-Resize-Private.xcconfig │ ├── Pods-Reveal-iOS-SDK │ │ ├── Pods-Reveal-iOS-SDK-prefix.pch │ │ ├── Pods-Reveal-iOS-SDK-dummy.m │ │ ├── Pods-Reveal-iOS-SDK.xcconfig │ │ └── Pods-Reveal-iOS-SDK-Private.xcconfig │ └── Pods │ │ ├── Pods-dummy.m │ │ ├── Pods.debug.xcconfig │ │ ├── Pods.release.xcconfig │ │ ├── Pods-environment.h │ │ ├── Pods-resources.sh │ │ └── Pods-acknowledgements.markdown ├── Headers │ ├── Build │ │ ├── UIImage-Resize │ │ │ └── UIImage+Resize.h │ │ └── KTSecretTextView │ │ │ ├── KTImageUtil.h │ │ │ ├── KTNumberUtil.h │ │ │ ├── KTSecretTextView.h │ │ │ ├── KTSecretViewController.h │ │ │ ├── UIColor+KTColorUtils.h │ │ │ ├── KTSecretColorChooserViewController.h │ │ │ ├── KTSecretPhotosEditorViewController.h │ │ │ └── KTSecretTextureChooserViewController.h │ └── Public │ │ ├── UIImage-Resize │ │ └── UIImage+Resize.h │ │ └── KTSecretTextView │ │ ├── KTImageUtil.h │ │ ├── KTNumberUtil.h │ │ ├── KTSecretTextView.h │ │ ├── KTSecretViewController.h │ │ ├── UIColor+KTColorUtils.h │ │ ├── KTSecretColorChooserViewController.h │ │ ├── KTSecretPhotosEditorViewController.h │ │ └── KTSecretTextureChooserViewController.h ├── UIImage-Resize │ ├── README │ ├── UIImage+Resize.h │ ├── LICENSE │ └── UIImage+Resize.m └── KTSecretTextView │ ├── SecretTextView │ ├── Utils │ │ ├── KTNumberUtil.h │ │ ├── KTNumberUtil.m │ │ ├── UIColor+KTColorUtils.h │ │ ├── KTImageUtil.h │ │ ├── UIColor+KTColorUtils.m │ │ └── KTImageUtil.m │ ├── KTSecretViewController.h │ ├── KTSecretPhotosEditorViewController.h │ ├── KTSecretTextView.h │ ├── KTSecretColorChooserViewController.h │ ├── KTSecretTextureChooserViewController.h │ ├── KTSecretTextureChooserViewController.m │ ├── KTSecretTextView.m │ ├── KTSecretPhotosEditorViewController.m │ └── KTSecretColorChooserViewController.m │ ├── LICENSE │ └── README.md ├── SecretTextViewSampleApp ├── en.lproj │ └── InfoPlist.strings ├── Images.xcassets │ └── AppIcon.appiconset │ │ ├── app_icon-1.png │ │ ├── app_icon.png │ │ └── Contents.json ├── KTSecretTextViewSampleViewController.h ├── KTAppDelegate.h ├── SecretTextViewSampleApp-Prefix.pch ├── main.m ├── SecretTextViewSampleApp-Info.plist ├── KTAppDelegate.m └── KTSecretTextViewSampleViewController.m ├── SecretTextViewSampleAppTests ├── en.lproj │ └── InfoPlist.strings ├── SecretTextViewSampleAppTests-Info.plist └── SecretTextViewSampleAppTests.m ├── Podfile ├── .travis.yml ├── SecretTextView ├── Resources │ ├── Screenshots │ │ ├── KTSecretTextView-screencast.gif │ │ ├── KTSecretTextView-screenshot1.png │ │ ├── KTSecretTextView-screenshot2.png │ │ ├── KTSecretTextView-screenshot3.png │ │ └── KTSecretTextView-screenshot4.png │ └── SecretTextImages.xcassets │ │ ├── Default-568h@2x.png │ │ ├── camera_icon.imageset │ │ ├── camera_icon@2x.png │ │ └── Contents.json │ │ ├── LaunchImage.launchimage │ │ ├── Default-568h@2x.png │ │ └── Contents.json │ │ ├── linen_texture.imageset │ │ ├── linen_texture@2x.png │ │ └── Contents.json │ │ ├── lines_texture.imageset │ │ ├── lines_texture@2x.png │ │ └── Contents.json │ │ ├── noise_texture.imageset │ │ ├── noise_texture@2x.png │ │ └── Contents.json │ │ ├── LaunchImage-2.launchimage │ │ ├── Default-568h@2x.png │ │ └── Contents.json │ │ ├── default_texture.imageset │ │ ├── default_texture@2x.png │ │ └── Contents.json │ │ ├── squared_texture.imageset │ │ ├── squared_texture@2x.png │ │ └── Contents.json │ │ └── squares2_texture.imageset │ │ ├── squares2_texture@2x.png │ │ └── Contents.json ├── Utils │ ├── KTNumberUtil.h │ ├── KTNumberUtil.m │ ├── UIColor+KTColorUtils.h │ ├── KTImageUtil.h │ ├── UIColor+KTColorUtils.m │ └── KTImageUtil.m ├── KTSecretViewController.h ├── KTSecretPhotosEditorViewController.h ├── KTSecretTextView.h ├── KTSecretTextView.podspec ├── KTSecretColorChooserViewController.h ├── KTSecretTextureChooserViewController.h ├── KTSecretTextureChooserViewController.m ├── CodingStyle.md ├── KTSecretTextView.m ├── KTSecretPhotosEditorViewController.m └── KTSecretColorChooserViewController.m ├── .gitignore ├── SecretTextViewSampleApp.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── SecretTextViewSampleApp.xccheckout ├── SecretTextViewSampleApp.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── SecretTextViewSampleApp.xcscheme ├── LICENSE └── README.md /Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Versions/Current: -------------------------------------------------------------------------------- 1 | A -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-KTSecretTextView/Pods-KTSecretTextView.xcconfig: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-UIImage-Resize/Pods-UIImage-Resize.xcconfig: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Pods/Headers/Build/UIImage-Resize/UIImage+Resize.h: -------------------------------------------------------------------------------- 1 | ../../../UIImage-Resize/UIImage+Resize.h -------------------------------------------------------------------------------- /Pods/Headers/Public/UIImage-Resize/UIImage+Resize.h: -------------------------------------------------------------------------------- 1 | ../../../UIImage-Resize/UIImage+Resize.h -------------------------------------------------------------------------------- /Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Headers: -------------------------------------------------------------------------------- 1 | Versions/Current/Headers -------------------------------------------------------------------------------- /Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Reveal: -------------------------------------------------------------------------------- 1 | Versions/Current/Reveal -------------------------------------------------------------------------------- /SecretTextViewSampleApp/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /SecretTextViewSampleAppTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Pods/Headers/Build/KTSecretTextView/KTImageUtil.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/Utils/KTImageUtil.h -------------------------------------------------------------------------------- /Pods/Headers/Build/KTSecretTextView/KTNumberUtil.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/Utils/KTNumberUtil.h -------------------------------------------------------------------------------- /Pods/Headers/Build/KTSecretTextView/KTSecretTextView.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretTextView.h -------------------------------------------------------------------------------- /Pods/Headers/Public/KTSecretTextView/KTImageUtil.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/Utils/KTImageUtil.h -------------------------------------------------------------------------------- /Pods/Headers/Public/KTSecretTextView/KTNumberUtil.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/Utils/KTNumberUtil.h -------------------------------------------------------------------------------- /Pods/Headers/Public/KTSecretTextView/KTSecretTextView.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretTextView.h -------------------------------------------------------------------------------- /Pods/Headers/Build/KTSecretTextView/KTSecretViewController.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretViewController.h -------------------------------------------------------------------------------- /Pods/Headers/Build/KTSecretTextView/UIColor+KTColorUtils.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/Utils/UIColor+KTColorUtils.h -------------------------------------------------------------------------------- /Pods/Headers/Public/KTSecretTextView/KTSecretViewController.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretViewController.h -------------------------------------------------------------------------------- /Pods/Headers/Public/KTSecretTextView/UIColor+KTColorUtils.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/Utils/UIColor+KTColorUtils.h -------------------------------------------------------------------------------- /Pods/Headers/Build/KTSecretTextView/KTSecretColorChooserViewController.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretColorChooserViewController.h -------------------------------------------------------------------------------- /Pods/Headers/Build/KTSecretTextView/KTSecretPhotosEditorViewController.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretPhotosEditorViewController.h -------------------------------------------------------------------------------- /Pods/Headers/Build/KTSecretTextView/KTSecretTextureChooserViewController.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretTextureChooserViewController.h -------------------------------------------------------------------------------- /Pods/Headers/Public/KTSecretTextView/KTSecretColorChooserViewController.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretColorChooserViewController.h -------------------------------------------------------------------------------- /Pods/Headers/Public/KTSecretTextView/KTSecretPhotosEditorViewController.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretPhotosEditorViewController.h -------------------------------------------------------------------------------- /Pods/Headers/Public/KTSecretTextView/KTSecretTextureChooserViewController.h: -------------------------------------------------------------------------------- 1 | ../../../KTSecretTextView/SecretTextView/KTSecretTextureChooserViewController.h -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Reveal-iOS-SDK/Pods-Reveal-iOS-SDK-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Pods-environment.h" 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-UIImage-Resize/Pods-UIImage-Resize-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Pods-environment.h" 6 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '7.0' 2 | 3 | pod 'Reveal-iOS-SDK' 4 | pod 'KTSecretTextView' 5 | #pod 'KTSecretTextView', :podspec => './SecretTextView/KTSecretTextView.podspec' 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-KTSecretTextView/Pods-KTSecretTextView-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | #import "Pods-environment.h" 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods : NSObject 3 | @end 4 | @implementation PodsDummy_Pods 5 | @end 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | script: xcodebuild -workspace SecretTextViewSampleApp.xcworkspace -scheme SecretTextViewSampleApp -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO 3 | -------------------------------------------------------------------------------- /SecretTextView/Resources/Screenshots/KTSecretTextView-screencast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/Screenshots/KTSecretTextView-screencast.gif -------------------------------------------------------------------------------- /SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot1.png -------------------------------------------------------------------------------- /SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot2.png -------------------------------------------------------------------------------- /SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot3.png -------------------------------------------------------------------------------- /SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot4.png -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/Default-568h@2x.png -------------------------------------------------------------------------------- /SecretTextViewSampleApp/Images.xcassets/AppIcon.appiconset/app_icon-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextViewSampleApp/Images.xcassets/AppIcon.appiconset/app_icon-1.png -------------------------------------------------------------------------------- /SecretTextViewSampleApp/Images.xcassets/AppIcon.appiconset/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextViewSampleApp/Images.xcassets/AppIcon.appiconset/app_icon.png -------------------------------------------------------------------------------- /Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Versions/A/Reveal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Versions/A/Reveal -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata 3 | /build/ 4 | instruments.out 5 | instrumentscli*.trace 6 | *.pbxuser 7 | *.mode2v3 8 | *.mode1v3 9 | xcuserdata 10 | profile 11 | *~ 12 | *.lock 13 | *.DS_Store 14 | *.swp 15 | *.out 16 | -------------------------------------------------------------------------------- /Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Versions/A/Headers/Reveal.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Itty Bitty Apps Pty Ltd. All rights reserved. 2 | // 3 | 4 | #import "IBARevealLogger.h" 5 | #import "IBARevealLoader.h" 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Reveal-iOS-SDK/Pods-Reveal-iOS-SDK-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Reveal_iOS_SDK : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Reveal_iOS_SDK 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-UIImage-Resize/Pods-UIImage-Resize-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_UIImage_Resize : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_UIImage_Resize 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-KTSecretTextView/Pods-KTSecretTextView-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_KTSecretTextView : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_KTSecretTextView 5 | @end 6 | -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/camera_icon.imageset/camera_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/camera_icon.imageset/camera_icon@2x.png -------------------------------------------------------------------------------- /SecretTextViewSampleApp.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/LaunchImage.launchimage/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/LaunchImage.launchimage/Default-568h@2x.png -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/linen_texture.imageset/linen_texture@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/linen_texture.imageset/linen_texture@2x.png -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/lines_texture.imageset/lines_texture@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/lines_texture.imageset/lines_texture@2x.png -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/noise_texture.imageset/noise_texture@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/noise_texture.imageset/noise_texture@2x.png -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/LaunchImage-2.launchimage/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/LaunchImage-2.launchimage/Default-568h@2x.png -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/default_texture.imageset/default_texture@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/default_texture.imageset/default_texture@2x.png -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/squared_texture.imageset/squared_texture@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/squared_texture.imageset/squared_texture@2x.png -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/squares2_texture.imageset/squares2_texture@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTSecretTextView/HEAD/SecretTextView/Resources/SecretTextImages.xcassets/squares2_texture.imageset/squares2_texture@2x.png -------------------------------------------------------------------------------- /SecretTextViewSampleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Reveal-iOS-SDK/Pods-Reveal-iOS-SDK.xcconfig: -------------------------------------------------------------------------------- 1 | PODS_REVEAL_IOS_SDK_FRAMEWORK_SEARCH_PATHS = "$(PODS_ROOT)/Reveal-iOS-SDK/Reveal-Framework-1.5.1" 2 | PODS_REVEAL_IOS_SDK_OTHER_LDFLAGS = -l"z" -framework "CFNetwork" -framework "CoreGraphics" -framework "QuartzCore" -framework "Reveal" -------------------------------------------------------------------------------- /SecretTextViewSampleApp/KTSecretTextViewSampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextViewSampleViewController.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTSecretTextViewSampleViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SecretTextViewSampleApp/KTAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTAppDelegate.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 4/29/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Pods/UIImage-Resize/README: -------------------------------------------------------------------------------- 1 | This category allows you to resize an UIImage at a constraint size, or proportionally so that it fits in a given CGSize. 2 | 3 | This category defines the following methods : 4 | -(UIImage*)resizedImageToSize:(CGSize*)size; 5 | -(UIImage*)resizedImageToFitInSize:(CGSize*)size resizeIfSmaller:(BOOL)resizeIfSmaller; 6 | 7 | This methods takes correctly the imageOrientation / EXIF orientation into account. 8 | 9 | -------------------------------------------------------------------------------- /SecretTextView/Utils/KTNumberUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTNumberUtil.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/1/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTNumberUtil : NSObject 12 | 13 | + (float)remapNumbersToRange:(float)inputNumber fromMin:(float)fromMin fromMax:(float)fromMax toMin:(float)toMin toMax:(float)toMax; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SecretTextViewSampleApp/SecretTextViewSampleApp-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /SecretTextViewSampleApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 4/29/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "KTAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([KTAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/Utils/KTNumberUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTNumberUtil.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/1/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTNumberUtil : NSObject 12 | 13 | + (float)remapNumbersToRange:(float)inputNumber fromMin:(float)fromMin fromMax:(float)fromMax toMin:(float)toMin toMax:(float)toMax; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/camera_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "camera_icon@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-UIImage-Resize/Pods-UIImage-Resize-Private.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods-UIImage-Resize.xcconfig" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/UIImage-Resize" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/KTSecretTextView" "${PODS_ROOT}/Headers/Public/Reveal-iOS-SDK" "${PODS_ROOT}/Headers/Public/UIImage-Resize" 4 | OTHER_LDFLAGS = -ObjC 5 | PODS_ROOT = ${SRCROOT} -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/linen_texture.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "linen_texture@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/lines_texture.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "lines_texture@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/noise_texture.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "noise_texture@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-KTSecretTextView/Pods-KTSecretTextView-Private.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods-KTSecretTextView.xcconfig" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/KTSecretTextView" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/KTSecretTextView" "${PODS_ROOT}/Headers/Public/Reveal-iOS-SDK" "${PODS_ROOT}/Headers/Public/UIImage-Resize" 4 | OTHER_LDFLAGS = -ObjC 5 | PODS_ROOT = ${SRCROOT} -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/default_texture.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "default_texture@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/squared_texture.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "squared_texture@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/squares2_texture.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "squares2_texture@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SecretTextView/Utils/KTNumberUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTNumberUtil.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/1/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTNumberUtil.h" 10 | 11 | @implementation KTNumberUtil 12 | 13 | 14 | + (float)remapNumbersToRange:(float)inputNumber fromMin:(float)fromMin fromMax:(float)fromMax toMin:(float)toMin toMax:(float)toMax { 15 | return (inputNumber - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/Utils/KTNumberUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTNumberUtil.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/1/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTNumberUtil.h" 10 | 11 | @implementation KTNumberUtil 12 | 13 | 14 | + (float)remapNumbersToRange:(float)inputNumber fromMin:(float)fromMin fromMax:(float)fromMax toMin:(float)toMin toMax:(float)toMax { 15 | return (inputNumber - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /SecretTextView/Utils/UIColor+KTColorUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+KTColorUtils.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (KTColorUtils) 12 | 13 | /** 14 | * Returns a boolean to indicate whether the color is a light or dark color 15 | * Implementation from http://stackoverflow.com/questions/2509443/check-if-uicolor-is-dark-or-bright 16 | * 17 | * @return BOOL 18 | */ 19 | - (BOOL)isLightColor; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-Reveal-iOS-SDK/Pods-Reveal-iOS-SDK-Private.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods-Reveal-iOS-SDK.xcconfig" 2 | FRAMEWORK_SEARCH_PATHS = ${PODS_REVEAL_IOS_SDK_FRAMEWORK_SEARCH_PATHS} 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Build" "${PODS_ROOT}/Headers/Build/Reveal-iOS-SDK" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/KTSecretTextView" "${PODS_ROOT}/Headers/Public/Reveal-iOS-SDK" "${PODS_ROOT}/Headers/Public/UIImage-Resize" 5 | OTHER_LDFLAGS = ${PODS_REVEAL_IOS_SDK_OTHER_LDFLAGS} -ObjC 6 | PODS_ROOT = ${SRCROOT} -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/LaunchImage-2.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "filename" : "Default-568h@2x.png", 7 | "minimum-system-version" : "7.0", 8 | "subtype" : "retina4", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "orientation" : "portrait", 13 | "idiom" : "iphone", 14 | "minimum-system-version" : "7.0", 15 | "scale" : "2x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/Utils/UIColor+KTColorUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+KTColorUtils.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (KTColorUtils) 12 | 13 | /** 14 | * Returns a boolean to indicate whether the color is a light or dark color 15 | * Implementation from http://stackoverflow.com/questions/2509443/check-if-uicolor-is-dark-or-bright 16 | * 17 | * @return BOOL 18 | */ 19 | - (BOOL)isLightColor; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Versions/A/Headers/IBARevealLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2013 Itty Bitty Apps. All rights reserved. 3 | 4 | #import 5 | 6 | extern NSString * const IBARevealLoaderRequestStartNotification; 7 | extern NSString * const IBARevealLoaderRequestStopNotification; 8 | 9 | extern NSString * const IBARevealLoaderSetOptionsNotification; 10 | extern NSString * const IBARevealLoaderOptionsLogLevelMaskKey; 11 | 12 | @interface IBARevealLoader : NSObject 13 | 14 | + (void)startServer; 15 | + (void)stopServer; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Versions/A/Headers/IBANetServiceTypes.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2014 Itty Bitty Apps Pty Ltd. All rights reserved. 3 | 4 | #ifndef reveal_core_IBANetServiceTypes_h 5 | #define reveal_core_IBANetServiceTypes_h 6 | #import 7 | 8 | typedef NS_ENUM(uint32_t, IBANetServiceInterface) { 9 | IBANetServiceInterfaceAny = kDNSServiceInterfaceIndexAny, 10 | IBANetServiceInterfaceLocalOnly = kDNSServiceInterfaceIndexLocalOnly, 11 | IBANetServiceInterfaceUnicast = kDNSServiceInterfaceIndexUnicast, 12 | IBANetServiceInterfaceP2P = kDNSServiceInterfaceIndexP2P 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /SecretTextView/Resources/SecretTextImages.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "extent" : "full-screen", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "filename" : "Default-568h@2x.png", 15 | "minimum-system-version" : "7.0", 16 | "orientation" : "portrait", 17 | "scale" : "2x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /SecretTextViewSampleApp/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "app_icon.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "idiom" : "iphone", 11 | "size" : "40x40", 12 | "scale" : "2x" 13 | }, 14 | { 15 | "size" : "60x60", 16 | "idiom" : "iphone", 17 | "filename" : "app_icon-1.png", 18 | "scale" : "2x" 19 | }, 20 | { 21 | "idiom" : "iphone", 22 | "size" : "60x60", 23 | "scale" : "3x" 24 | } 25 | ], 26 | "info" : { 27 | "version" : 1, 28 | "author" : "xcode" 29 | } 30 | } -------------------------------------------------------------------------------- /SecretTextView/Utils/KTImageUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTImageUtil.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | @import AssetsLibrary; 11 | 12 | /** 13 | * Util class for resizing image effectively. Method implementation taken from 14 | * http://mindsea.com/2012/12/18/downscaling-huge-alassets-without-fear-of-sigkill 15 | */ 16 | 17 | @interface KTImageUtil : NSObject 18 | 19 | + (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size; 20 | + (UIImage*) cropImage:(UIImage*)image toRect:(CGRect)rect; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/Utils/KTImageUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTImageUtil.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | @import AssetsLibrary; 11 | 12 | /** 13 | * Util class for resizing image effectively. Method implementation taken from 14 | * http://mindsea.com/2012/12/18/downscaling-huge-alassets-without-fear-of-sigkill 15 | */ 16 | 17 | @interface KTImageUtil : NSObject 18 | 19 | + (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size; 20 | + (UIImage*) cropImage:(UIImage*)image toRect:(CGRect)rect; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /SecretTextView/Utils/UIColor+KTColorUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+KTColorUtils.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "UIColor+KTColorUtils.h" 10 | 11 | @implementation UIColor (KTColorUtils) 12 | 13 | - (BOOL)isLightColor; 14 | { 15 | BOOL isLight = NO; 16 | const CGFloat *componentColors = CGColorGetComponents(self.CGColor); 17 | CGFloat colorBrightness = ((componentColors[0] * 299) + (componentColors[1] * 587) + (componentColors[2] * 114)) / 1000; 18 | if (colorBrightness < 0.6) { 19 | isLight = NO; 20 | }else { 21 | isLight = YES; 22 | } 23 | return isLight; 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/Utils/UIColor+KTColorUtils.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+KTColorUtils.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "UIColor+KTColorUtils.h" 10 | 11 | @implementation UIColor (KTColorUtils) 12 | 13 | - (BOOL)isLightColor; 14 | { 15 | BOOL isLight = NO; 16 | const CGFloat *componentColors = CGColorGetComponents(self.CGColor); 17 | CGFloat colorBrightness = ((componentColors[0] * 299) + (componentColors[1] * 587) + (componentColors[2] * 114)) / 1000; 18 | if (colorBrightness < 0.6) { 19 | isLight = NO; 20 | }else { 21 | isLight = YES; 22 | } 23 | return isLight; 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /SecretTextView/KTSecretViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretViewController.h 3 | // 4 | // Created by Kenny Tang on 4/30/14. 5 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @protocol KTSecretViewControllerDelegate; 11 | 12 | /*! 13 | * View Controller that hosts the secret view. 14 | */ 15 | @interface KTSecretViewController : UIViewController 16 | 17 | @property (nonatomic, weak) id delegate; 18 | 19 | @end 20 | 21 | 22 | @protocol KTSecretViewControllerDelegate 23 | 24 | - (void)secretViewController:(KTSecretViewController*)vc secretViewSnapshot:(UIView*)snapshotView backgroundImage:(UIImage*)backgroundImage attributedString:(NSAttributedString*)attributedString; 25 | 26 | @end -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretViewController.h 3 | // 4 | // Created by Kenny Tang on 4/30/14. 5 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @protocol KTSecretViewControllerDelegate; 11 | 12 | /*! 13 | * View Controller that hosts the secret view. 14 | */ 15 | @interface KTSecretViewController : UIViewController 16 | 17 | @property (nonatomic, weak) id delegate; 18 | 19 | @end 20 | 21 | 22 | @protocol KTSecretViewControllerDelegate 23 | 24 | - (void)secretViewController:(KTSecretViewController*)vc secretViewSnapshot:(UIView*)snapshotView backgroundImage:(UIImage*)backgroundImage attributedString:(NSAttributedString*)attributedString; 25 | 26 | @end -------------------------------------------------------------------------------- /SecretTextViewSampleAppTests/SecretTextViewSampleAppTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.corgitoergosum.net.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = "$(PODS_ROOT)/Reveal-iOS-SDK/Reveal-Framework-1.5.1" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/KTSecretTextView" "${PODS_ROOT}/Headers/Public/Reveal-iOS-SDK" "${PODS_ROOT}/Headers/Public/UIImage-Resize" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/KTSecretTextView" -isystem "${PODS_ROOT}/Headers/Public/Reveal-iOS-SDK" -isystem "${PODS_ROOT}/Headers/Public/UIImage-Resize" 5 | OTHER_LDFLAGS = -ObjC -l"Pods-KTSecretTextView" -l"Pods-Reveal-iOS-SDK" -l"Pods-UIImage-Resize" -l"z" -framework "CFNetwork" -framework "CoreGraphics" -framework "QuartzCore" -framework "Reveal" 6 | OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) 7 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = "$(PODS_ROOT)/Reveal-iOS-SDK/Reveal-Framework-1.5.1" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/KTSecretTextView" "${PODS_ROOT}/Headers/Public/Reveal-iOS-SDK" "${PODS_ROOT}/Headers/Public/UIImage-Resize" 4 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/KTSecretTextView" -isystem "${PODS_ROOT}/Headers/Public/Reveal-iOS-SDK" -isystem "${PODS_ROOT}/Headers/Public/UIImage-Resize" 5 | OTHER_LDFLAGS = -ObjC -l"Pods-KTSecretTextView" -l"Pods-Reveal-iOS-SDK" -l"Pods-UIImage-Resize" -l"z" -framework "CFNetwork" -framework "CoreGraphics" -framework "QuartzCore" -framework "Reveal" 6 | OTHER_LIBTOOLFLAGS = $(OTHER_LDFLAGS) 7 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /SecretTextViewSampleAppTests/SecretTextViewSampleAppTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SecretTextViewSampleAppTests.m 3 | // SecretTextViewSampleAppTests 4 | // 5 | // Created by Kenny Tang on 4/29/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SecretTextViewSampleAppTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation SecretTextViewSampleAppTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /SecretTextView/KTSecretPhotosEditorViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretPhotosEditorViewController.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/1/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol KTSecretPhotosEditorViewControllerDelegate; 12 | 13 | 14 | @interface KTSecretPhotosEditorViewController : UIViewController 15 | 16 | @property (nonatomic, strong) UIImage *selectedImage; 17 | @property (nonatomic, readonly) UIImage *finalImage; 18 | @property (nonatomic, weak) id delegate; 19 | 20 | @end 21 | 22 | 23 | @protocol KTSecretPhotosEditorViewControllerDelegate 24 | 25 | @optional 26 | 27 | - (void)secretPhotosEditorViewController:(KTSecretPhotosEditorViewController*)vc didUpdateFilters:(CGFloat)blurLevel brightnessLevel:(CGFloat)brightnessLevel; 28 | 29 | 30 | @end -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretPhotosEditorViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretPhotosEditorViewController.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/1/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol KTSecretPhotosEditorViewControllerDelegate; 12 | 13 | 14 | @interface KTSecretPhotosEditorViewController : UIViewController 15 | 16 | @property (nonatomic, strong) UIImage *selectedImage; 17 | @property (nonatomic, readonly) UIImage *finalImage; 18 | @property (nonatomic, weak) id delegate; 19 | 20 | @end 21 | 22 | 23 | @protocol KTSecretPhotosEditorViewControllerDelegate 24 | 25 | @optional 26 | 27 | - (void)secretPhotosEditorViewController:(KTSecretPhotosEditorViewController*)vc didUpdateFilters:(CGFloat)blurLevel brightnessLevel:(CGFloat)brightnessLevel; 28 | 29 | 30 | @end -------------------------------------------------------------------------------- /SecretTextView/KTSecretTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextView.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/4/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @protocol KTSecretTextViewDelegate; 13 | 14 | /** 15 | * UITextView subclass that takes care of vertically center aligning the text and setting attributed on the NSAttributedString contained. 16 | */ 17 | @interface KTSecretTextView : UITextView 18 | 19 | @property (nonatomic, weak) id secretTextViewDelegate; 20 | 21 | - (void)setText:(NSString *)text; 22 | 23 | @end 24 | 25 | 26 | 27 | @protocol KTSecretTextViewDelegate 28 | 29 | - (UIView*)secretTextView:(KTSecretTextView*)view viewForHitTest:(CGPoint)point withEvent:(UIEvent *)event; 30 | 31 | @optional 32 | - (void)secretTextView:(KTSecretTextView*)view textViewDidChange:(UITextView *)textView; 33 | 34 | @end -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretTextView.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextView.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/4/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @protocol KTSecretTextViewDelegate; 13 | 14 | /** 15 | * UITextView subclass that takes care of vertically center aligning the text and setting attributed on the NSAttributedString contained. 16 | */ 17 | @interface KTSecretTextView : UITextView 18 | 19 | @property (nonatomic, weak) id secretTextViewDelegate; 20 | 21 | - (void)setText:(NSString *)text; 22 | 23 | @end 24 | 25 | 26 | 27 | @protocol KTSecretTextViewDelegate 28 | 29 | - (UIView*)secretTextView:(KTSecretTextView*)view viewForHitTest:(CGPoint)point withEvent:(UIEvent *)event; 30 | 31 | @optional 32 | - (void)secretTextView:(KTSecretTextView*)view textViewDidChange:(UITextView *)textView; 33 | 34 | @end -------------------------------------------------------------------------------- /SecretTextView/KTSecretTextView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.platform = :ios, '7.0' 3 | s.name = "KTSecretTextView" 4 | s.version = "0.0.1" 5 | s.summary = "Secret Text View" 6 | s.homepage = 'https://github.com/kenshin03/KTSecretTextView' 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = { 'Kenny Tang' => 'https://github.com/kenshin03' } 9 | s.source = { :git => "https://github.com/kenshin03/KTSecretTextView.git", :tag => '0.0.1' } 10 | s.screenshots = ["https://raw.githubusercontent.com/kenshin03/KTSecretTextView/master/SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot1.png", "https://raw.githubusercontent.com/kenshin03/KTSecretTextView/master/SecretTextView/Resources/Screenshots/KTSecretTextView-screenshot3.png"] 11 | s.resources = 'SecretTextView/Resources/**/*.*' 12 | s.source_files = 'SecretTextView/**/*.{h,m}' 13 | s.requires_arc = true 14 | s.dependency 'UIImage-Resize' 15 | end 16 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-environment.h: -------------------------------------------------------------------------------- 1 | 2 | // To check if a library is compiled with CocoaPods you 3 | // can use the `COCOAPODS` macro definition which is 4 | // defined in the xcconfigs so it is available in 5 | // headers also when they are imported in the client 6 | // project. 7 | 8 | 9 | // KTSecretTextView 10 | #define COCOAPODS_POD_AVAILABLE_KTSecretTextView 11 | #define COCOAPODS_VERSION_MAJOR_KTSecretTextView 0 12 | #define COCOAPODS_VERSION_MINOR_KTSecretTextView 0 13 | #define COCOAPODS_VERSION_PATCH_KTSecretTextView 1 14 | 15 | // Reveal-iOS-SDK 16 | #define COCOAPODS_POD_AVAILABLE_Reveal_iOS_SDK 17 | #define COCOAPODS_VERSION_MAJOR_Reveal_iOS_SDK 1 18 | #define COCOAPODS_VERSION_MINOR_Reveal_iOS_SDK 5 19 | #define COCOAPODS_VERSION_PATCH_Reveal_iOS_SDK 1 20 | 21 | // UIImage-Resize 22 | #define COCOAPODS_POD_AVAILABLE_UIImage_Resize 23 | #define COCOAPODS_VERSION_MAJOR_UIImage_Resize 1 24 | #define COCOAPODS_VERSION_MINOR_UIImage_Resize 0 25 | #define COCOAPODS_VERSION_PATCH_UIImage_Resize 1 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy 2 | of this software and associated documentation files (the "Software"), to deal 3 | in the Software without restriction, including without limitation the rights 4 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5 | copies of the Software, and to permit persons to whom the Software is 6 | furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in 9 | all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17 | THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/LICENSE: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy 2 | of this software and associated documentation files (the "Software"), to deal 3 | in the Software without restriction, including without limitation the rights 4 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5 | copies of the Software, and to permit persons to whom the Software is 6 | furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in 9 | all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17 | THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /SecretTextView/KTSecretColorChooserViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretColorChooserViewController.h 3 | // 4 | // Created by Kenny Tang on 4/29/14. 5 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @protocol KTSecretColorChooserViewControllerDelegate; 11 | 12 | /*! 13 | * View Controller that displays a rainbow of colors for selection. The user can swipe between colors or long press and pan to see an index of colors and select one. It was implemented with a UICollectionView that switches layouts when a long press is detected. 14 | */ 15 | @interface KTSecretColorChooserViewController : UIViewController 16 | 17 | @property (nonatomic, weak) id delegate; 18 | @property (nonatomic, readonly) UICollectionView *collectionView; 19 | 20 | @end 21 | 22 | /** 23 | * Protocol for delegates to handle color selection and swipe up/down gestures 24 | */ 25 | @protocol KTSecretColorChooserViewControllerDelegate 26 | 27 | @optional 28 | 29 | - (void)secretColorChooserViewController:(KTSecretColorChooserViewController*)vc didSelectColor:(UIColor*)color name:(NSString*)name; 30 | 31 | - (void)secretColorChooserViewController:(KTSecretColorChooserViewController*)vc didSwipeUp:(BOOL)swipedUp; 32 | 33 | - (void)secretColorChooserViewController:(KTSecretColorChooserViewController*)vc didSwipeDown:(BOOL)swipedDown; 34 | 35 | 36 | @end -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretColorChooserViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretColorChooserViewController.h 3 | // 4 | // Created by Kenny Tang on 4/29/14. 5 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | @protocol KTSecretColorChooserViewControllerDelegate; 11 | 12 | /*! 13 | * View Controller that displays a rainbow of colors for selection. The user can swipe between colors or long press and pan to see an index of colors and select one. It was implemented with a UICollectionView that switches layouts when a long press is detected. 14 | */ 15 | @interface KTSecretColorChooserViewController : UIViewController 16 | 17 | @property (nonatomic, weak) id delegate; 18 | @property (nonatomic, readonly) UICollectionView *collectionView; 19 | 20 | @end 21 | 22 | /** 23 | * Protocol for delegates to handle color selection and swipe up/down gestures 24 | */ 25 | @protocol KTSecretColorChooserViewControllerDelegate 26 | 27 | @optional 28 | 29 | - (void)secretColorChooserViewController:(KTSecretColorChooserViewController*)vc didSelectColor:(UIColor*)color name:(NSString*)name; 30 | 31 | - (void)secretColorChooserViewController:(KTSecretColorChooserViewController*)vc didSwipeUp:(BOOL)swipedUp; 32 | 33 | - (void)secretColorChooserViewController:(KTSecretColorChooserViewController*)vc didSwipeDown:(BOOL)swipedDown; 34 | 35 | 36 | @end -------------------------------------------------------------------------------- /SecretTextViewSampleApp/SecretTextViewSampleApp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | KTSecretTextView 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.corgitoergosum.net.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIStatusBarHidden 28 | 29 | UIViewControllerBasedStatusBarAppearance 30 | 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UIAppFonts 36 | 37 | OpenSans-CondLight.ttf 38 | OpenSans-CondBold.ttf 39 | OpenSans-Regular.ttf 40 | 41 | UISupportedInterfaceOrientations 42 | 43 | UIInterfaceOrientationPortrait 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /SecretTextView/KTSecretTextureChooserViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextureChooserViewController.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 4/30/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol KTSecretTextureChooserViewControllerDelegate; 12 | 13 | typedef NS_ENUM(NSUInteger, KTSecretTexture) 14 | { 15 | KTSecretTextureGlow = 0, 16 | KTSecretTextureLinen, 17 | KTSecretTextureLines, 18 | KTSecretTextureNoise, 19 | KTSecretTextureSquared, 20 | KTSecretTextureSquared2, 21 | }; 22 | 23 | /** 24 | * View Controller for controlling which texture to use as the foreground for the background 25 | */ 26 | @interface KTSecretTextureChooserViewController : UIViewController 27 | 28 | @property (nonatomic, weak) id delegate; 29 | 30 | /** 31 | * Method to select the previous texture 32 | * 33 | * @param previousTexture 34 | */ 35 | - (void)selectPreviousTexture:(BOOL)previousTexture; 36 | 37 | /** 38 | * Method to select the next texture 39 | * 40 | * @param nextTexture 41 | */ 42 | - (void)selectNextTexture:(BOOL)nextTexture; 43 | 44 | @end 45 | 46 | 47 | /** 48 | * Protocol for delegates to be informed of texture selection events 49 | */ 50 | @protocol KTSecretTextureChooserViewControllerDelegate 51 | 52 | @optional 53 | 54 | - (void)secretTextureChooserViewController:(KTSecretTextureChooserViewController*)vc didSelectTexture:(UIImage*)textureImage name:(NSString*)name; 55 | 56 | @end -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretTextureChooserViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextureChooserViewController.h 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 4/30/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol KTSecretTextureChooserViewControllerDelegate; 12 | 13 | typedef NS_ENUM(NSUInteger, KTSecretTexture) 14 | { 15 | KTSecretTextureGlow = 0, 16 | KTSecretTextureLinen, 17 | KTSecretTextureLines, 18 | KTSecretTextureNoise, 19 | KTSecretTextureSquared, 20 | KTSecretTextureSquared2, 21 | }; 22 | 23 | /** 24 | * View Controller for controlling which texture to use as the foreground for the background 25 | */ 26 | @interface KTSecretTextureChooserViewController : UIViewController 27 | 28 | @property (nonatomic, weak) id delegate; 29 | 30 | /** 31 | * Method to select the previous texture 32 | * 33 | * @param previousTexture 34 | */ 35 | - (void)selectPreviousTexture:(BOOL)previousTexture; 36 | 37 | /** 38 | * Method to select the next texture 39 | * 40 | * @param nextTexture 41 | */ 42 | - (void)selectNextTexture:(BOOL)nextTexture; 43 | 44 | @end 45 | 46 | 47 | /** 48 | * Protocol for delegates to be informed of texture selection events 49 | */ 50 | @protocol KTSecretTextureChooserViewControllerDelegate 51 | 52 | @optional 53 | 54 | - (void)secretTextureChooserViewController:(KTSecretTextureChooserViewController*)vc didSelectTexture:(UIImage*)textureImage name:(NSString*)name; 55 | 56 | @end -------------------------------------------------------------------------------- /SecretTextViewSampleApp.xcworkspace/xcshareddata/SecretTextViewSampleApp.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | E40D67D5-CB61-4B10-93FE-655E8DD4B256 9 | IDESourceControlProjectName 10 | SecretTextViewSampleApp 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 103F7FB6AB4A00D87CEEED3738194B43CB552C2F 14 | https://github.com/kenshin03/KTSecretTextView.git 15 | 16 | IDESourceControlProjectPath 17 | SecretTextViewSampleApp.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 103F7FB6AB4A00D87CEEED3738194B43CB552C2F 21 | .. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/kenshin03/KTSecretTextView.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 103F7FB6AB4A00D87CEEED3738194B43CB552C2F 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 103F7FB6AB4A00D87CEEED3738194B43CB552C2F 36 | IDESourceControlWCCName 37 | KTSecretTextView 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Pods/UIImage-Resize/UIImage+Resize.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************************** 2 | * 3 | * Copyright (c) 2010 Olivier Halligon 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | * 23 | *********************************************************************************** 24 | * 25 | * Any comment or suggestion welcome. Referencing this project in your AboutBox is appreciated. 26 | * Please tell me if you use this class so we can cross-reference our projects. 27 | * 28 | ***********************************************************************************/ 29 | 30 | 31 | #import 32 | 33 | 34 | @interface UIImage(ResizeCategory) 35 | -(UIImage*)resizedImageToSize:(CGSize)dstSize; 36 | -(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale; 37 | @end 38 | -------------------------------------------------------------------------------- /Pods/UIImage-Resize/LICENSE: -------------------------------------------------------------------------------- 1 | Without any further information, all the sources provided here are under the MIT License 2 | quoted below. 3 | 4 | Anyway, please contact me by email (olivier.halligon+ae@gmail.com) if you plan to use my work and the provided classes 5 | in your own software. Thanks. 6 | 7 | 8 | /*********************************************************************************** 9 | * 10 | * Copyright (c) 2010 Olivier Halligon 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | * THE SOFTWARE. 29 | * 30 | *********************************************************************************** 31 | * 32 | * Any comment or suggestion welcome. Referencing this project in your AboutBox is appreciated. 33 | * Please tell me if you use this class so we can cross-reference our projects. 34 | * 35 | ***********************************************************************************/ 36 | -------------------------------------------------------------------------------- /Pods/Reveal-iOS-SDK/Reveal-Framework-1.5.1/Reveal.framework/Versions/A/Headers/IBARevealLogger.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013 Itty Bitty Apps Pty Ltd. All rights reserved. 2 | // 3 | 4 | #import 5 | 6 | CF_EXTERN_C_BEGIN 7 | 8 | /*! 9 | \brief The Reveal Log level bit flags. 10 | \discussion These flags are additive. i.e. you should bitwise OR them together. 11 | 12 | \seealso IBARevealLoggerSetLevelMask 13 | \seealso IBARevealLoggerGetLevelMask 14 | 15 | Example: 16 | 17 | // Enable Error, Warning and Info logger levels. 18 | IBARevealLoggerSetLevelMask(IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo); 19 | 20 | */ 21 | typedef NS_OPTIONS(int32_t, IBARevealLogLevel) 22 | { 23 | IBARevealLogLevelNone = 0, 24 | IBARevealLogLevelDebug = (1 << 0), 25 | IBARevealLogLevelInfo = (1 << 1), 26 | IBARevealLogLevelWarn = (1 << 2), 27 | IBARevealLogLevelError = (1 << 3) 28 | }; 29 | 30 | /*! 31 | \brief Set the Reveal logger level mask. 32 | \param mask A bit mask which is a combination of the IBARevealLogLevel enum options. 33 | 34 | \discussion If you do not wish to see log messages from Reveal you should call this function with an appropriate level mask as early in your application's lifecycle as possible. For example in your application's main() function. 35 | 36 | Example: 37 | 38 | // Enable Error, Warning and Info logger levels. 39 | IBARevealLoggerSetLevelMask(IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo); 40 | 41 | */ 42 | CF_EXPORT void IBARevealLoggerSetLevelMask(int32_t mask); 43 | 44 | /*! 45 | \brief Get the current Reveal logger level mask. 46 | \return A bit mask representing the levels at which Reveal is currently logging. 47 | \discussion The default Reveal Logger level mask is IBARevealLogLevelError|IBARevealLogLevelWarn|IBARevealLogLevelInfo. 48 | 49 | Example: 50 | 51 | // Turn off the Info log level. 52 | IBARevealLoggerSetLevelMask(IBARevealLoggerGetLevelMask() & ~IBARevealLogLevelInfo); 53 | 54 | */ 55 | CF_EXPORT int32_t IBARevealLoggerGetLevelMask(void); 56 | 57 | CF_EXTERN_C_END 58 | -------------------------------------------------------------------------------- /SecretTextViewSampleApp/KTAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTAppDelegate.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 4/29/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTAppDelegate.h" 10 | #import "KTSecretTextViewSampleViewController.h" 11 | 12 | 13 | @implementation KTAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | [[UIApplication sharedApplication] setStatusBarHidden:YES]; 18 | 19 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 20 | 21 | // Override point for customization after application launch. 22 | self.window.backgroundColor = [UIColor whiteColor]; 23 | 24 | KTSecretTextViewSampleViewController *secretVC = [KTSecretTextViewSampleViewController new]; 25 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:secretVC];; 26 | self.window.rootViewController = navigationController; 27 | 28 | [self.window makeKeyAndVisible]; 29 | return YES; 30 | } 31 | 32 | - (void)applicationWillResignActive:(UIApplication *)application 33 | { 34 | // 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. 35 | // 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. 36 | } 37 | 38 | - (void)applicationDidEnterBackground:(UIApplication *)application 39 | { 40 | // 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. 41 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 42 | } 43 | 44 | - (void)applicationWillEnterForeground:(UIApplication *)application 45 | { 46 | // 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. 47 | } 48 | 49 | - (void)applicationDidBecomeActive:(UIApplication *)application 50 | { 51 | // 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. 52 | } 53 | 54 | - (void)applicationWillTerminate:(UIApplication *)application 55 | { 56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/README.md: -------------------------------------------------------------------------------- 1 | #KTSecretTextView 2 | 3 | `KTSecretTextView` is an attempt to re-create the text view in the app [Secret](http://secret.ly). Its clever designs and heavy use of gestures makes it very intuitive for users to customize their secret texts with textured backgrounds or photos. 4 | 5 | 17 | 18 | --- 19 | ##Installation 20 | 21 | Add this to your Podfile to use `KTSecretTextView`: 22 | 23 | pod 'KTSecretTextView', '~> 0.0.1' 24 | 25 | 26 | ##Usage 27 | 28 | The`KTSecretViewController` class is a wrapper you can present or push to your view controller stack. The provided sample app simply presents it as a modal as shown below. 29 | 30 | Adding `KTSecretViewController` to imports: 31 | 32 | #import "KTSecretViewController.h" 33 | 34 | Presenting the view controller on the tap of a button: 35 | 36 | KTSecretViewController *secretVC = self.secretViewController; 37 | 38 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:secretVC]; 39 | 40 | [self presentViewController:navigationController animated:YES completion:nil]; 41 | 42 | To capture outputs from `KTSecretTextView`, vend for a delegate: 43 | 44 | @interface KTSecretTextViewSampleViewController ()< 45 | KTSecretViewControllerDelegate 46 | > 47 | 48 | And implement the delegate method which provides a convenient snapshot view containing the edited background and text, as well as the actual attributed string and processed background image. You can make a `UIImage` from the snapshot view and save it as needed. 49 | 50 | - (void)secretViewController:(KTSecretViewController*)vc secretViewSnapshot:(UIView*)snapshotView backgroundImage:(UIImage*)backgroundImage attributedString:(NSAttributedString*)attributedString 51 | 52 | 53 | 54 | --- 55 | ##Background 56 | 57 | 61 | 62 | 63 | --- 64 | ##Credits 65 | The following Pods are used: 66 | 67 | * [UIImage-Resize](https://github.com/AliSoftware/UIImage-Resize) by [AliSoftware](olivier.halligon+ae@gmail.com) 68 | 69 | 70 | ___ 71 | ##License 72 | `KTSecretTextView` is available under the MIT license. 73 | 74 | ___ 75 | ##Feedback 76 | File an issue or pull request. Or ping me at [@kenshin03](http://twitter.com/kenshin03). 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /SecretTextViewSampleApp/KTSecretTextViewSampleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextViewSampleViewController.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTSecretTextViewSampleViewController.h" 10 | #import "KTSecretViewController.h" 11 | #import "KTImageUtil.h" 12 | 13 | @interface KTSecretTextViewSampleViewController ()< 14 | KTSecretViewControllerDelegate 15 | > 16 | 17 | @property (nonatomic, strong) UIBarButtonItem *editBarButton; 18 | @property (nonatomic, strong) KTSecretViewController *secretViewController; 19 | @property (nonatomic, strong) UIView *secretSnapshotView; 20 | 21 | @end 22 | 23 | 24 | @implementation KTSecretTextViewSampleViewController 25 | 26 | #pragma mark - Public 27 | 28 | #pragma mark - View lifecycle 29 | 30 | - (void)viewDidLoad 31 | { 32 | [super viewDidLoad]; 33 | [self addSubviewTree]; 34 | } 35 | 36 | - (void)loadView 37 | { 38 | self.view = [self mainView]; 39 | } 40 | 41 | 42 | #pragma mark - Initialization 43 | 44 | - (UIView *)mainView 45 | { 46 | UIView *mainView = [UIView new]; 47 | mainView.frame = [[UIScreen mainScreen] bounds]; 48 | mainView.alpha = 0.9; 49 | mainView.tintColor = [UIColor blueColor]; 50 | return mainView; 51 | } 52 | 53 | - (void)addSubviewTree 54 | { 55 | self.navigationItem.rightBarButtonItem = self.editBarButton; 56 | } 57 | 58 | #pragma mark - Private 59 | 60 | #pragma mark - Private properties 61 | 62 | - (KTSecretViewController*) secretViewController 63 | { 64 | if (!_secretViewController) { 65 | _secretViewController = [KTSecretViewController new]; 66 | _secretViewController.delegate = self; 67 | } 68 | return _secretViewController; 69 | } 70 | 71 | - (UIBarButtonItem*) editBarButton 72 | { 73 | if (!_editBarButton) { 74 | _editBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(editBarButtonTapped:)]; 75 | } 76 | return _editBarButton; 77 | } 78 | 79 | #pragma mark - Event Handler methods 80 | 81 | - (void)editBarButtonTapped:(id)sender 82 | { 83 | [self.secretSnapshotView removeFromSuperview]; 84 | KTSecretViewController *secretVC = self.secretViewController; 85 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:secretVC]; 86 | [self presentViewController:navigationController animated:YES completion:nil]; 87 | } 88 | 89 | 90 | #pragma mark - KTSecretViewControllerDelegate methods 91 | 92 | - (void)secretViewController:(KTSecretViewController *)vc secretViewSnapshot:(UIView *)snapshotView backgroundImage:(UIImage *)backgroundImage attributedString:(NSAttributedString *)attributedString 93 | { 94 | snapshotView.translatesAutoresizingMaskIntoConstraints = NO; 95 | [self.view addSubview:snapshotView]; 96 | self.secretSnapshotView = snapshotView; 97 | 98 | NSDictionary *viewsDict = @{@"snapshotView":snapshotView}; 99 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[snapshotView(568)]" options:0 metrics:nil views:viewsDict]]; 100 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[snapshotView]|" options:0 metrics:nil views:viewsDict]]; 101 | [self.secretViewController dismissViewControllerAnimated:YES completion:nil]; 102 | } 103 | 104 | 105 | @end 106 | -------------------------------------------------------------------------------- /SecretTextView/Utils/KTImageUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTImageUtil.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTImageUtil.h" 10 | @import ImageIO; 11 | 12 | 13 | @implementation KTImageUtil 14 | 15 | // Helper methods for thumbnailForAsset:maxPixelSize: 16 | static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count) { 17 | ALAssetRepresentation *rep = (__bridge id)info; 18 | 19 | NSError *error = nil; 20 | size_t countRead = [rep getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error]; 21 | 22 | if (countRead == 0 && error) { 23 | // We have no way of passing this info back to the caller, so we log it, at least. 24 | NSLog(@"thumbnailForAsset:maxPixelSize: got an error reading an asset: %@", error); 25 | } 26 | 27 | return countRead; 28 | } 29 | 30 | static void releaseAssetCallback(void *info) { 31 | // The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:maxPixelSize:. 32 | // This release balances that retain. 33 | CFRelease(info); 34 | } 35 | 36 | // Returns a UIImage for the given asset, with size length at most the passed size. 37 | // The resulting UIImage will be already rotated to UIImageOrientationUp, so its CGImageRef 38 | // can be used directly without additional rotation handling. 39 | // This is done synchronously, so you should call this method on a background queue/thread. 40 | + (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size { 41 | 42 | NSParameterAssert(asset != nil); 43 | NSParameterAssert(size > 0); 44 | 45 | ALAssetRepresentation *rep = [asset defaultRepresentation]; 46 | 47 | CGDataProviderDirectCallbacks callbacks = { 48 | .version = 0, 49 | .getBytePointer = NULL, 50 | .releaseBytePointer = NULL, 51 | .getBytesAtPosition = getAssetBytesCallback, 52 | .releaseInfo = releaseAssetCallback, 53 | }; 54 | 55 | CGDataProviderRef provider = CGDataProviderCreateDirect((void *)CFBridgingRetain(rep), [rep size], &callbacks); 56 | CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL); 57 | 58 | CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, (__bridge CFDictionaryRef) @{ 59 | (NSString *)kCGImageSourceCreateThumbnailFromImageAlways : @YES, 60 | (NSString *)kCGImageSourceThumbnailMaxPixelSize :@(size), 61 | (NSString *)kCGImageSourceCreateThumbnailWithTransform : @YES, 62 | }); 63 | CFRelease(source); 64 | CFRelease(provider); 65 | 66 | if (!imageRef) { 67 | return nil; 68 | } 69 | 70 | UIImage *toReturn = [UIImage imageWithCGImage:imageRef]; 71 | 72 | CFRelease(imageRef); 73 | 74 | return toReturn; 75 | } 76 | 77 | 78 | // http://stackoverflow.com/a/18602671 79 | + (UIImage*) cropImage:(UIImage*)image toRect:(CGRect)rect 80 | { 81 | UIGraphicsBeginImageContextWithOptions(rect.size, false, [image scale]); 82 | [image drawAtPoint:CGPointMake(-rect.origin.x, -rect.origin.y)]; 83 | UIImage * croppedImage = UIGraphicsGetImageFromCurrentImageContext(); 84 | UIGraphicsEndImageContext(); 85 | return croppedImage; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/Utils/KTImageUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTImageUtil.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/5/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTImageUtil.h" 10 | @import ImageIO; 11 | 12 | 13 | @implementation KTImageUtil 14 | 15 | // Helper methods for thumbnailForAsset:maxPixelSize: 16 | static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count) { 17 | ALAssetRepresentation *rep = (__bridge id)info; 18 | 19 | NSError *error = nil; 20 | size_t countRead = [rep getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error]; 21 | 22 | if (countRead == 0 && error) { 23 | // We have no way of passing this info back to the caller, so we log it, at least. 24 | NSLog(@"thumbnailForAsset:maxPixelSize: got an error reading an asset: %@", error); 25 | } 26 | 27 | return countRead; 28 | } 29 | 30 | static void releaseAssetCallback(void *info) { 31 | // The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:maxPixelSize:. 32 | // This release balances that retain. 33 | CFRelease(info); 34 | } 35 | 36 | // Returns a UIImage for the given asset, with size length at most the passed size. 37 | // The resulting UIImage will be already rotated to UIImageOrientationUp, so its CGImageRef 38 | // can be used directly without additional rotation handling. 39 | // This is done synchronously, so you should call this method on a background queue/thread. 40 | + (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size { 41 | 42 | NSParameterAssert(asset != nil); 43 | NSParameterAssert(size > 0); 44 | 45 | ALAssetRepresentation *rep = [asset defaultRepresentation]; 46 | 47 | CGDataProviderDirectCallbacks callbacks = { 48 | .version = 0, 49 | .getBytePointer = NULL, 50 | .releaseBytePointer = NULL, 51 | .getBytesAtPosition = getAssetBytesCallback, 52 | .releaseInfo = releaseAssetCallback, 53 | }; 54 | 55 | CGDataProviderRef provider = CGDataProviderCreateDirect((void *)CFBridgingRetain(rep), [rep size], &callbacks); 56 | CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL); 57 | 58 | CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, (__bridge CFDictionaryRef) @{ 59 | (NSString *)kCGImageSourceCreateThumbnailFromImageAlways : @YES, 60 | (NSString *)kCGImageSourceThumbnailMaxPixelSize :@(size), 61 | (NSString *)kCGImageSourceCreateThumbnailWithTransform : @YES, 62 | }); 63 | CFRelease(source); 64 | CFRelease(provider); 65 | 66 | if (!imageRef) { 67 | return nil; 68 | } 69 | 70 | UIImage *toReturn = [UIImage imageWithCGImage:imageRef]; 71 | 72 | CFRelease(imageRef); 73 | 74 | return toReturn; 75 | } 76 | 77 | 78 | // http://stackoverflow.com/a/18602671 79 | + (UIImage*) cropImage:(UIImage*)image toRect:(CGRect)rect 80 | { 81 | UIGraphicsBeginImageContextWithOptions(rect.size, false, [image scale]); 82 | [image drawAtPoint:CGPointMake(-rect.origin.x, -rect.origin.y)]; 83 | UIImage * croppedImage = UIGraphicsGetImageFromCurrentImageContext(); 84 | UIGraphicsEndImageContext(); 85 | return croppedImage; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | install_resource() 10 | { 11 | case $1 in 12 | *.storyboard) 13 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 14 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 15 | ;; 16 | *.xib) 17 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 18 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 19 | ;; 20 | *.framework) 21 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 22 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 23 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 24 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 25 | ;; 26 | *.xcdatamodel) 27 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 28 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 29 | ;; 30 | *.xcdatamodeld) 31 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 32 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 33 | ;; 34 | *.xcmappingmodel) 35 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 36 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 37 | ;; 38 | *.xcassets) 39 | ;; 40 | /*) 41 | echo "$1" 42 | echo "$1" >> "$RESOURCES_TO_COPY" 43 | ;; 44 | *) 45 | echo "${PODS_ROOT}/$1" 46 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 47 | ;; 48 | esac 49 | } 50 | 51 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 52 | if [[ "${ACTION}" == "install" ]]; then 53 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 54 | fi 55 | rm -f "$RESOURCES_TO_COPY" 56 | 57 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ `find . -name '*.xcassets' | wc -l` -ne 0 ] 58 | then 59 | case "${TARGETED_DEVICE_FAMILY}" in 60 | 1,2) 61 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 62 | ;; 63 | 1) 64 | TARGET_DEVICE_ARGS="--target-device iphone" 65 | ;; 66 | 2) 67 | TARGET_DEVICE_ARGS="--target-device ipad" 68 | ;; 69 | *) 70 | TARGET_DEVICE_ARGS="--target-device mac" 71 | ;; 72 | esac 73 | find "${PWD}" -name "*.xcassets" -print0 | xargs -0 actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 74 | fi 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/kenshin03/KTSecretTextView.svg?branch=master)](https://travis-ci.org/kenshin03/KTSecretTextView) 2 | 3 | #KTSecretTextView 4 | 5 | `KTSecretTextView` is an attempt to re-create the text view in the app [Secret](http://secret.ly). Its clever designs and heavy use of gestures makes it very intuitive for users to customize their secret texts with textured backgrounds or photos. 6 | 7 | More on the creation of this text view here - http://corgitoergosum.net/2014/05/07/good-enough-isnt-replicating-the-secret-ios-app-text-view/. 8 | 9 | --- 10 | ##Video 11 | 12 | 13 | 14 | --- 15 | ##Screenshots 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 | --- 37 | 38 | ##Features 39 | 40 | - Scroll horizontally to choose between 8 types of background colors (Emerald Sea, Hopscotch, Lavender, Burst, Cupid, Peony, Midnight, White). 41 | - Long Press to choose color from a compressed palette. 42 | - Swipe vertically to choose between 6 types of textures (Glow, Linen, Lines, Noise, Squares, Squares2) 43 | - Take a photo or choose one from Camera Roll as background. 44 | - Pan left/right/up/down to vary the blurriness and dimmness of the background image. 45 | - Text will attempt to align to the center vertically. 46 | 47 | ##Installation 48 | 49 | Add this to your Podfile to use `KTSecretTextView`: 50 | 51 | pod 'KTSecretTextView', '~> 0.0.1' 52 | 53 | 54 | ##Usage 55 | 56 | The`KTSecretViewController` class is a wrapper you can present or push to your view controller stack. The provided sample app simply presents it as a modal as shown below. 57 | 58 | Adding `KTSecretViewController` to imports: 59 | 60 | #import "KTSecretViewController.h" 61 | 62 | Presenting the view controller on the tap of a button: 63 | 64 | KTSecretViewController *secretVC = self.secretViewController; 65 | 66 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:secretVC]; 67 | 68 | [self presentViewController:navigationController animated:YES completion:nil]; 69 | 70 | To capture outputs from `KTSecretTextView`, vend for a delegate: 71 | 72 | @interface KTSecretTextViewSampleViewController ()< 73 | KTSecretViewControllerDelegate 74 | > 75 | 76 | And implement the delegate method which provides a convenient snapshot view containing the edited background and text, as well as the actual attributed string and processed background image. You can make a `UIImage` from the snapshot view and save it as needed. 77 | 78 | - (void)secretViewController:(KTSecretViewController*)vc secretViewSnapshot:(UIView*)snapshotView backgroundImage:(UIImage*)backgroundImage attributedString:(NSAttributedString*)attributedString 79 | 80 | 81 | 82 | --- 83 | ##Background 84 | 85 | Read [my post](http://corgitoergosum.net/2014/05/07/good-enough-isnt-replicating-the-secret-ios-app-text-view/) on how the Text View was built. 86 | 87 | --- 88 | ##Credits 89 | The following Pods are used: 90 | 91 | * [UIImage-Resize](https://github.com/AliSoftware/UIImage-Resize) by [AliSoftware](olivier.halligon+ae@gmail.com) 92 | 93 | 94 | ___ 95 | ##License 96 | `KTSecretTextView` is available under the MIT license. 97 | 98 | ___ 99 | ##Feedback 100 | File an issue or pull request. Or ping me at [@kenshin03](http://twitter.com/kenshin03). 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /SecretTextViewSampleApp.xcodeproj/xcshareddata/xcschemes/SecretTextViewSampleApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Pods/UIImage-Resize/UIImage+Resize.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Resize.m 3 | // 4 | // Created by Olivier Halligon on 12/08/09. 5 | // Copyright 2009 AliSoftware. All rights reserved. 6 | // 7 | 8 | #import "UIImage+Resize.h" 9 | 10 | @implementation UIImage (ResizeCategory) 11 | 12 | -(UIImage*)resizedImageToSize:(CGSize)dstSize 13 | { 14 | CGImageRef imgRef = self.CGImage; 15 | // the below values are regardless of orientation : for UIImages from Camera, width>height (landscape) 16 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which is dependant on the imageOrientation)! 17 | 18 | /* Don't resize if we already meet the required destination size. */ 19 | if (CGSizeEqualToSize(srcSize, dstSize)) { 20 | return self; 21 | } 22 | 23 | CGFloat scaleRatio = dstSize.width / srcSize.width; 24 | UIImageOrientation orient = self.imageOrientation; 25 | CGAffineTransform transform = CGAffineTransformIdentity; 26 | switch(orient) { 27 | 28 | case UIImageOrientationUp: //EXIF = 1 29 | transform = CGAffineTransformIdentity; 30 | break; 31 | 32 | case UIImageOrientationUpMirrored: //EXIF = 2 33 | transform = CGAffineTransformMakeTranslation(srcSize.width, 0.0); 34 | transform = CGAffineTransformScale(transform, -1.0, 1.0); 35 | break; 36 | 37 | case UIImageOrientationDown: //EXIF = 3 38 | transform = CGAffineTransformMakeTranslation(srcSize.width, srcSize.height); 39 | transform = CGAffineTransformRotate(transform, M_PI); 40 | break; 41 | 42 | case UIImageOrientationDownMirrored: //EXIF = 4 43 | transform = CGAffineTransformMakeTranslation(0.0, srcSize.height); 44 | transform = CGAffineTransformScale(transform, 1.0, -1.0); 45 | break; 46 | 47 | case UIImageOrientationLeftMirrored: //EXIF = 5 48 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 49 | transform = CGAffineTransformMakeTranslation(srcSize.height, srcSize.width); 50 | transform = CGAffineTransformScale(transform, -1.0, 1.0); 51 | transform = CGAffineTransformRotate(transform, 3.0 * M_PI_2); 52 | break; 53 | 54 | case UIImageOrientationLeft: //EXIF = 6 55 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 56 | transform = CGAffineTransformMakeTranslation(0.0, srcSize.width); 57 | transform = CGAffineTransformRotate(transform, 3.0 * M_PI_2); 58 | break; 59 | 60 | case UIImageOrientationRightMirrored: //EXIF = 7 61 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 62 | transform = CGAffineTransformMakeScale(-1.0, 1.0); 63 | transform = CGAffineTransformRotate(transform, M_PI_2); 64 | break; 65 | 66 | case UIImageOrientationRight: //EXIF = 8 67 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 68 | transform = CGAffineTransformMakeTranslation(srcSize.height, 0.0); 69 | transform = CGAffineTransformRotate(transform, M_PI_2); 70 | break; 71 | 72 | default: 73 | [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 74 | 75 | } 76 | 77 | ///////////////////////////////////////////////////////////////////////////// 78 | // The actual resize: draw the image on a new context, applying a transform matrix 79 | UIGraphicsBeginImageContextWithOptions(dstSize, NO, self.scale); 80 | 81 | CGContextRef context = UIGraphicsGetCurrentContext(); 82 | 83 | if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 84 | CGContextScaleCTM(context, -scaleRatio, scaleRatio); 85 | CGContextTranslateCTM(context, -srcSize.height, 0); 86 | } else { 87 | CGContextScaleCTM(context, scaleRatio, -scaleRatio); 88 | CGContextTranslateCTM(context, 0, -srcSize.height); 89 | } 90 | 91 | CGContextConcatCTM(context, transform); 92 | 93 | // we use srcSize (and not dstSize) as the size to specify is in user space (and we use the CTM to apply a scaleRatio) 94 | CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, srcSize.width, srcSize.height), imgRef); 95 | UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext(); 96 | UIGraphicsEndImageContext(); 97 | 98 | return resizedImage; 99 | } 100 | 101 | 102 | 103 | ///////////////////////////////////////////////////////////////////////////// 104 | 105 | 106 | 107 | -(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale 108 | { 109 | // get the image size (independant of imageOrientation) 110 | CGImageRef imgRef = self.CGImage; 111 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which depends on the imageOrientation)! 112 | 113 | // adjust boundingSize to make it independant on imageOrientation too for farther computations 114 | UIImageOrientation orient = self.imageOrientation; 115 | switch (orient) { 116 | case UIImageOrientationLeft: 117 | case UIImageOrientationRight: 118 | case UIImageOrientationLeftMirrored: 119 | case UIImageOrientationRightMirrored: 120 | boundingSize = CGSizeMake(boundingSize.height, boundingSize.width); 121 | break; 122 | default: 123 | // NOP 124 | break; 125 | } 126 | 127 | // Compute the target CGRect in order to keep aspect-ratio 128 | CGSize dstSize; 129 | 130 | if ( !scale && (srcSize.width < boundingSize.width) && (srcSize.height < boundingSize.height) ) { 131 | //NSLog(@"Image is smaller, and we asked not to scale it in this case (scaleIfSmaller:NO)"); 132 | dstSize = srcSize; // no resize (we could directly return 'self' here, but we draw the image anyway to take image orientation into account) 133 | } else { 134 | CGFloat wRatio = boundingSize.width / srcSize.width; 135 | CGFloat hRatio = boundingSize.height / srcSize.height; 136 | 137 | if (wRatio < hRatio) { 138 | //NSLog(@"Width imposed, Height scaled ; ratio = %f",wRatio); 139 | dstSize = CGSizeMake(boundingSize.width, floorf(srcSize.height * wRatio)); 140 | } else { 141 | //NSLog(@"Height imposed, Width scaled ; ratio = %f",hRatio); 142 | dstSize = CGSizeMake(floorf(srcSize.width * hRatio), boundingSize.height); 143 | } 144 | } 145 | 146 | return [self resizedImageToSize:dstSize]; 147 | } 148 | 149 | @end 150 | -------------------------------------------------------------------------------- /SecretTextView/KTSecretTextureChooserViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextureChooserViewController.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 4/30/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTSecretTextureChooserViewController.h" 10 | 11 | @interface KTSecretTextureChooserViewController () 12 | 13 | @property (nonatomic, strong) UIImageView *textureImageView; 14 | @property (atomic) NSInteger selectedTextureIndex; 15 | @property (nonatomic, strong) NSDictionary *texturesDictionary; 16 | @property (nonatomic, strong) NSDictionary *textureNamesDictionary; 17 | 18 | 19 | @end 20 | 21 | @implementation KTSecretTextureChooserViewController 22 | 23 | 24 | #pragma mark - Public 25 | 26 | #pragma mark - View lifecycle 27 | 28 | - (void)viewDidLoad 29 | { 30 | [super viewDidLoad]; 31 | self.selectedTextureIndex = 0; 32 | [self addSubviewTree]; 33 | [self constrainViews]; 34 | } 35 | 36 | - (void)loadView 37 | { 38 | self.view = [self mainView]; 39 | } 40 | 41 | 42 | #pragma mark - Initialization 43 | 44 | - (UIView *)mainView 45 | { 46 | UIView *mainView = [UIView new]; 47 | mainView.translatesAutoresizingMaskIntoConstraints = NO; 48 | mainView.alpha = 0.9; 49 | mainView.userInteractionEnabled = NO; 50 | return mainView; 51 | } 52 | 53 | - (void)addSubviewTree 54 | { 55 | [self.view addSubview:self.textureImageView]; 56 | } 57 | 58 | - (void)constrainViews 59 | { 60 | NSDictionary *viewsDict = @{ 61 | @"textureImageView":self.textureImageView 62 | }; 63 | 64 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[textureImageView]|" options:0 metrics:nil views:viewsDict]]; 65 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[textureImageView(380)]" options:0 metrics:nil views:viewsDict]]; 66 | 67 | } 68 | 69 | #pragma mark - Public Methods 70 | 71 | - (void)selectPreviousTexture:(BOOL)previousTexture 72 | { 73 | self.selectedTextureIndex += 1; 74 | 75 | // reset index 76 | if (self.selectedTextureIndex > 5) { 77 | self.selectedTextureIndex = 0; 78 | } 79 | UIImage *textureImage = self.texturesDictionary[@(self.selectedTextureIndex)]; 80 | self.textureImageView.image = textureImage; 81 | 82 | [self updateDelegateOnSelectedTexture:self.selectedTextureIndex]; 83 | } 84 | 85 | - (void)selectNextTexture:(BOOL)nextTexture 86 | { 87 | self.selectedTextureIndex -= 1; 88 | // reset index 89 | if (self.selectedTextureIndex < 0) { 90 | self.selectedTextureIndex = 5; 91 | } 92 | UIImage *textureImage = self.texturesDictionary[@(self.selectedTextureIndex)]; 93 | self.textureImageView.image = textureImage; 94 | 95 | [self updateDelegateOnSelectedTexture:self.selectedTextureIndex]; 96 | } 97 | 98 | 99 | #pragma mark - Private 100 | 101 | #pragma mark - Private properties 102 | 103 | - (NSDictionary*)texturesDictionary 104 | { 105 | if (!_texturesDictionary) { 106 | _texturesDictionary = @{ 107 | @(KTSecretTextureGlow):[[UIImage imageNamed:@"default_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 108 | 109 | @(KTSecretTextureLinen):[[UIImage imageNamed:@"linen_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 110 | 111 | @(KTSecretTextureLines):[[UIImage imageNamed:@"lines_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 112 | 113 | @(KTSecretTextureNoise):[[UIImage imageNamed:@"noise_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 114 | 115 | @(KTSecretTextureSquared):[[UIImage imageNamed:@"squared_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 116 | 117 | @(KTSecretTextureSquared2):[[UIImage imageNamed:@"squares2_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 118 | 119 | }; 120 | } 121 | return _texturesDictionary; 122 | } 123 | 124 | - (NSDictionary*)textureNamesDictionary 125 | { 126 | if (!_textureNamesDictionary) { 127 | _textureNamesDictionary = @{ 128 | @(KTSecretTextureGlow): NSLocalizedString(@"Glow", nil), 129 | 130 | @(KTSecretTextureLinen): NSLocalizedString(@"Linen", nil), 131 | 132 | @(KTSecretTextureLines): NSLocalizedString(@"Lines", nil), 133 | 134 | @(KTSecretTextureNoise): NSLocalizedString(@"Noise", nil), 135 | 136 | @(KTSecretTextureSquared): NSLocalizedString(@"Squares", nil), 137 | 138 | @(KTSecretTextureSquared2): NSLocalizedString(@"Squares 2", nil), 139 | 140 | }; 141 | } 142 | return _textureNamesDictionary; 143 | } 144 | 145 | 146 | - (UIImageView*) textureImageView 147 | { 148 | if (!_textureImageView) { 149 | _textureImageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"default_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile]]; 150 | _textureImageView.translatesAutoresizingMaskIntoConstraints = NO; 151 | _textureImageView.alpha = 0.4f; 152 | } 153 | return _textureImageView; 154 | } 155 | 156 | #pragma mark - Initialization helpers 157 | 158 | - (void)updateDelegateOnSelectedTexture:(NSInteger)selectedIndex 159 | { 160 | UIImage *textureImage = self.texturesDictionary[@(selectedIndex)]; 161 | NSString *textureName = self.textureNamesDictionary[@(selectedIndex)]; 162 | 163 | [self.delegate secretTextureChooserViewController:self didSelectTexture:textureImage name:textureName]; 164 | 165 | } 166 | 167 | 168 | @end 169 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretTextureChooserViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextureChooserViewController.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 4/30/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTSecretTextureChooserViewController.h" 10 | 11 | @interface KTSecretTextureChooserViewController () 12 | 13 | @property (nonatomic, strong) UIImageView *textureImageView; 14 | @property (atomic) NSInteger selectedTextureIndex; 15 | @property (nonatomic, strong) NSDictionary *texturesDictionary; 16 | @property (nonatomic, strong) NSDictionary *textureNamesDictionary; 17 | 18 | 19 | @end 20 | 21 | @implementation KTSecretTextureChooserViewController 22 | 23 | 24 | #pragma mark - Public 25 | 26 | #pragma mark - View lifecycle 27 | 28 | - (void)viewDidLoad 29 | { 30 | [super viewDidLoad]; 31 | self.selectedTextureIndex = 0; 32 | [self addSubviewTree]; 33 | [self constrainViews]; 34 | } 35 | 36 | - (void)loadView 37 | { 38 | self.view = [self mainView]; 39 | } 40 | 41 | 42 | #pragma mark - Initialization 43 | 44 | - (UIView *)mainView 45 | { 46 | UIView *mainView = [UIView new]; 47 | mainView.translatesAutoresizingMaskIntoConstraints = NO; 48 | mainView.alpha = 0.9; 49 | mainView.userInteractionEnabled = NO; 50 | return mainView; 51 | } 52 | 53 | - (void)addSubviewTree 54 | { 55 | [self.view addSubview:self.textureImageView]; 56 | } 57 | 58 | - (void)constrainViews 59 | { 60 | NSDictionary *viewsDict = @{ 61 | @"textureImageView":self.textureImageView 62 | }; 63 | 64 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[textureImageView]|" options:0 metrics:nil views:viewsDict]]; 65 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[textureImageView(380)]" options:0 metrics:nil views:viewsDict]]; 66 | 67 | } 68 | 69 | #pragma mark - Public Methods 70 | 71 | - (void)selectPreviousTexture:(BOOL)previousTexture 72 | { 73 | self.selectedTextureIndex += 1; 74 | 75 | // reset index 76 | if (self.selectedTextureIndex > 5) { 77 | self.selectedTextureIndex = 0; 78 | } 79 | UIImage *textureImage = self.texturesDictionary[@(self.selectedTextureIndex)]; 80 | self.textureImageView.image = textureImage; 81 | 82 | [self updateDelegateOnSelectedTexture:self.selectedTextureIndex]; 83 | } 84 | 85 | - (void)selectNextTexture:(BOOL)nextTexture 86 | { 87 | self.selectedTextureIndex -= 1; 88 | // reset index 89 | if (self.selectedTextureIndex < 0) { 90 | self.selectedTextureIndex = 5; 91 | } 92 | UIImage *textureImage = self.texturesDictionary[@(self.selectedTextureIndex)]; 93 | self.textureImageView.image = textureImage; 94 | 95 | [self updateDelegateOnSelectedTexture:self.selectedTextureIndex]; 96 | } 97 | 98 | 99 | #pragma mark - Private 100 | 101 | #pragma mark - Private properties 102 | 103 | - (NSDictionary*)texturesDictionary 104 | { 105 | if (!_texturesDictionary) { 106 | _texturesDictionary = @{ 107 | @(KTSecretTextureGlow):[[UIImage imageNamed:@"default_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 108 | 109 | @(KTSecretTextureLinen):[[UIImage imageNamed:@"linen_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 110 | 111 | @(KTSecretTextureLines):[[UIImage imageNamed:@"lines_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 112 | 113 | @(KTSecretTextureNoise):[[UIImage imageNamed:@"noise_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 114 | 115 | @(KTSecretTextureSquared):[[UIImage imageNamed:@"squared_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 116 | 117 | @(KTSecretTextureSquared2):[[UIImage imageNamed:@"squares2_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile], 118 | 119 | }; 120 | } 121 | return _texturesDictionary; 122 | } 123 | 124 | - (NSDictionary*)textureNamesDictionary 125 | { 126 | if (!_textureNamesDictionary) { 127 | _textureNamesDictionary = @{ 128 | @(KTSecretTextureGlow): NSLocalizedString(@"Glow", nil), 129 | 130 | @(KTSecretTextureLinen): NSLocalizedString(@"Linen", nil), 131 | 132 | @(KTSecretTextureLines): NSLocalizedString(@"Lines", nil), 133 | 134 | @(KTSecretTextureNoise): NSLocalizedString(@"Noise", nil), 135 | 136 | @(KTSecretTextureSquared): NSLocalizedString(@"Squares", nil), 137 | 138 | @(KTSecretTextureSquared2): NSLocalizedString(@"Squares 2", nil), 139 | 140 | }; 141 | } 142 | return _textureNamesDictionary; 143 | } 144 | 145 | 146 | - (UIImageView*) textureImageView 147 | { 148 | if (!_textureImageView) { 149 | _textureImageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"default_texture"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile]]; 150 | _textureImageView.translatesAutoresizingMaskIntoConstraints = NO; 151 | _textureImageView.alpha = 0.4f; 152 | } 153 | return _textureImageView; 154 | } 155 | 156 | #pragma mark - Initialization helpers 157 | 158 | - (void)updateDelegateOnSelectedTexture:(NSInteger)selectedIndex 159 | { 160 | UIImage *textureImage = self.texturesDictionary[@(selectedIndex)]; 161 | NSString *textureName = self.textureNamesDictionary[@(selectedIndex)]; 162 | 163 | [self.delegate secretTextureChooserViewController:self didSelectTexture:textureImage name:textureName]; 164 | 165 | } 166 | 167 | 168 | @end 169 | -------------------------------------------------------------------------------- /SecretTextView/CodingStyle.md: -------------------------------------------------------------------------------- 1 | ### View management 2 | 3 | Do not use interface builder for production code; instead, override -loadView. 4 | Use autolayout when possible. 5 | 6 | ### Comments 7 | 8 | ``` 9 | /*! 10 |  *  Method comment. 11 |  *  Start this with a command verb (i.e. “Initialize”, “Compare”). 12 |  *  Use periods. 13 |  * 14 |  *   @param 15 |  * 16 |  *   @return 17 |  */ 18 | ``` 19 | 20 | Public interface should contain comments for methods. Private methods that aren’t implementing protocol methods should have comments. Don’t declare private methods outside of the implementation. 21 | 22 | 23 | // Private comment. Again, make sure to use periods. 24 | 25 | Comment confusing or non-trivial code inside a method. Reference issues on GitHub if code fixes a specific bug. 26 | 27 | 28 | // TODO: Fix this problem. #42 29 | 30 | If a method is missing code pending a later fix or feature, reference the GitHub issue. 31 | 32 | ### Constants 33 | 34 | .h: extern NSString *const kPREFIXPublicConstantString 35 | 36 | .m: NSString *const kPREFIXPublicConstantString = @”My Constant String”; 37 | 38 | .m: NSString *const kMyPrivateConstantString = @”My Private String”; 39 | 40 | 41 | 42 | ### Static variables 43 | 44 | static UIInteger sMyStaticVar; 45 | 46 | ### Imports 47 | 48 | ``` 49 | #import “MyClass.h” 50 | #import “Alphabetical.h” 51 | #import “Order.h” 52 | #import 53 | 54 | ``` 55 | Alphabetize header imports by section. Start with the class definition, then internal imports, then external imports with angle brackets. 56 | 57 | ### Delegates/protocols 58 | 59 | Self should always be the first parameter in delegate methods. 60 | 61 | ``` 62 | - (void)myObject:(PREFIXMyObject *) didDoSomethingWithNumber:(NSNumber *)number; 63 | ``` 64 | 65 | In interface declarations implementing more than one delegate, put each delegate name on its own line, in alphabetical order i.e. 66 | 67 | ``` 68 | @interface MyInterface () < 69 | ADelegate, 70 | BDelegate 71 | > 72 | ``` 73 | ### Event/action handlers 74 | Noun describing view followed by past tense verb describing event. Optionally take sender or gesture recognizer if it’s used. 75 | 76 | ``` 77 | buttonTapped 78 | cellSwipedRightWithGestureRecognizer: 79 | ``` 80 | 81 | ### Properties 82 | Use lazy instantiation pattern (in the getter) as much as possible. 83 | 84 | Try to use private properties always instead of raw ivars. This is for consistency - we should be using lazy instantiation even on private variables (for example, private subviews), so let’s just use private properties for all private variables so we’re not mentally toggling between _privateVar1 and self.privateVar2.* Major exception is in init methods, where you should access the ivar directly (and obviously in the getter and setter). Avoid synthesize statements - use the default synthesizer provide by XCode 4.4+ (underscore + property name). 85 | 86 | If you declare a property as readonly in the public .h @interface, redeclare it as readwrite in the private @interface. This ensures that the backing store ivar is actually created, and allows code in the .m file to write to the property without accessing the ivar directly. 87 | 88 | Modifier order (for consistency): strong/weak, atomic/nonatomic, readonly/readwrite. 89 | 90 | ### Method calling syntax 91 | Always use the dot syntax for setters and getters. Never use it for other methods. 92 | 93 | ### Initialization 94 | Access ivars directly in initializers (this is the one place to do that). 95 | 96 | All initialization must go through an explicitly-documented designated initializer. The comment should contain the string “This is the designated initializer.” If the designated initializer has a different method signature than its superclass's designated initializer, an initializer must be written that matches the method signature of the superclass's designated initializer (and calls the designated initializer, needless to say). 97 | 98 | 99 | ### Controller communication 100 | Rules of thumb: 101 | 102 | * Use delegates to communicate back to a controller some action/event that originated in the view (or whatever class). 103 | * Use block to communicate back to a controller the result of some action explicitly taken by the controller on the view (or whatever class) 104 | 105 | 106 | ### File sections 107 | Create hierarchy as follows: 108 | 109 | ``` 110 | #pragma mark - Public 111 | #pragma mark - Class methods 112 | 113 | Public 114 | Class methods 115 | Initialization 116 | Public properties 117 | Instance methods 118 | Overrides 119 | View lifecycle 120 | Private 121 | Private properties 122 | Event handlers 123 | protocols (datasource then delegate) 124 | helpers (e.g. View lifecycle helpers) 125 | 126 | ``` 127 | 128 | #Misc. naming conventions 129 | 130 | * “Count” variables should always end with the word “count” (fooCount, barCount, etc.) 131 | * Methods for updating core data from the server should be called “With:” and return the created object or array of objects. 132 | 133 | 134 | #Colors and styles 135 | 136 | * Use a Stylesheet class with class methods. 137 | * Style names should be specific to their usage. 138 | 139 | #Brackets 140 | 141 | * Always use curly braces around code blocks, even one liners. 142 | * Put the opening curly brace on the same line except for methods. 143 | * Use parentheses around multi-line expressions to help the auto-indenter do it’s thing. 144 | 145 | #Auto layout 146 | Use AutoLayoutShorthand and AutoLayoutHelpers to construct views. Construct initial view properties, like style, in a memoized property getter, i.e.: 147 | 148 | ``` 149 | - (UILabel *)topicLabel 150 | { 151 |     if (!_topicLabel) { 152 |         _topicLabel = [UILabel new]; 153 |         _topicLabel.translatesAutoresizingMaskIntoConstraints = NO; 154 |         _topicLabel.font = [PREFIXFont searchResultCellSecondaryFont]; 155 |         _topicLabel.textColor = [PREFIXColor secondaryTextColor]; 156 |     } 157 |     return _topicLabel; 158 | } 159 | 160 | ``` 161 | 162 | View construction should be done in the following stages, in loadView for a view controller or init for a view: 163 | 164 | ``` 165 | self.view = [self mainView]; // View controllers 166 | [self addSubviewTree]; // Add each view to the hierarchy 167 | [self constrainViews]; // Individual methods to constrain each view 168 | [self setupNavigationBar]; // Any navigation bar view/button/title customization 169 | 170 | ``` 171 | 172 | 173 | #Style 174 | Colors should be defined in PREFIXColor. Prefer global themed style colors like secondaryBackgroundColor to custom defined colors per view. 175 | 176 | Fonts should be defined inline in a view’s getter with UIFont fontWithName:size:. PREFIXFont is deprecated. 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /SecretTextView/KTSecretTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextView.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/4/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTSecretTextView.h" 10 | 11 | // default container inset. this is to vertically center text in the text view 12 | 13 | static NSString* const kKTSecretViewControllerTextViewPlaceholderText = @"Share a thought"; 14 | static CGFloat const kKTSecretTextViewDefaultContainerInsetFromTop = 150.0f; 15 | static CGFloat const kKTSecretTextViewDefaultContainerInsetFromTopMinimum = 30.9f; 16 | static NSUInteger const kKTSecretTextViewMaxNumberOfLines = 10; 17 | 18 | static UIEdgeInsets const kKTSecretTextViewDefaultTextContainerInset = {kKTSecretTextViewDefaultContainerInsetFromTop, 10.0f, 20.0f, 10.0f}; 19 | 20 | 21 | @interface KTSecretTextView()< 22 | UITextViewDelegate 23 | > 24 | 25 | @property (nonatomic) CGFloat defaultSingleLineHeight; 26 | @property (nonatomic, strong) NSDictionary *textAttributes; 27 | 28 | @end 29 | 30 | 31 | @implementation KTSecretTextView 32 | 33 | #pragma mark - Public 34 | 35 | - (instancetype)init 36 | { 37 | if (self = [super init]) { 38 | self.delegate = self; 39 | self.textAlignment = NSTextAlignmentCenter; 40 | self.backgroundColor = [UIColor clearColor]; 41 | self.tintColor = [UIColor whiteColor]; 42 | self.autocorrectionType = UITextAutocorrectionTypeNo; 43 | self.text = kKTSecretViewControllerTextViewPlaceholderText; 44 | [self setupDefaultContentInset]; 45 | } 46 | return self; 47 | } 48 | 49 | - (void)setText:(NSString *)text 50 | { 51 | self.attributedText = [[NSAttributedString alloc] initWithString:text attributes:self.textAttributes]; 52 | } 53 | 54 | #pragma mark - Override 55 | 56 | - (void)setTintColor:(UIColor *)tintColor 57 | { 58 | [super setTintColor:tintColor]; 59 | self.textColor = tintColor; 60 | } 61 | 62 | #pragma mark - Private 63 | 64 | #pragma mark - Private properties 65 | 66 | - (NSDictionary*)textAttributes 67 | { 68 | if (!_textAttributes) { 69 | 70 | NSMutableParagraphStyle *paragrahStyle = [NSMutableParagraphStyle new]; 71 | paragrahStyle.lineSpacing = 6.0f; 72 | paragrahStyle.alignment = NSTextAlignmentCenter; 73 | 74 | NSShadow *shadow = [NSShadow new]; 75 | shadow.shadowColor = [UIColor blackColor]; 76 | shadow.shadowOffset = CGSizeMake(1, 1); 77 | shadow.shadowBlurRadius = 2.0f; 78 | 79 | _textAttributes = @{ 80 | NSFontAttributeName: [UIFont fontWithName:@"AvenirNextCondensed-Medium" size:22.0f], 81 | NSParagraphStyleAttributeName: paragrahStyle, 82 | NSForegroundColorAttributeName: [UIColor whiteColor], 83 | NSShadowAttributeName: shadow 84 | }; 85 | } 86 | return _textAttributes; 87 | } 88 | 89 | #pragma mark - Initialization Helpers 90 | 91 | 92 | - (void)setupDefaultContentInset 93 | { 94 | self.textContainerInset = kKTSecretTextViewDefaultTextContainerInset; 95 | } 96 | 97 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 98 | { 99 | UIView *viewToReceiveTouch = nil; 100 | 101 | CGRect rectForCurrentText = [self.layoutManager usedRectForTextContainer:self.textContainer]; 102 | rectForCurrentText.origin.x += self.textContainerInset.left; 103 | rectForCurrentText.origin.y += self.textContainerInset.top; 104 | 105 | if (!CGRectContainsPoint(rectForCurrentText, point)) { 106 | viewToReceiveTouch = [self.secretTextViewDelegate secretTextView:self viewForHitTest:point withEvent:event]; 107 | if (self.isFirstResponder) { 108 | [self resignFirstResponder]; 109 | } 110 | } 111 | // consume event if delegate doesnt provide a view or is inside tect 112 | if (!viewToReceiveTouch) { 113 | viewToReceiveTouch = self; 114 | } 115 | return viewToReceiveTouch; 116 | } 117 | 118 | #pragma mark - UITextViewDelegate methods 119 | 120 | -(void)textViewDidBeginEditing:(UITextView *)textView 121 | { 122 | NSString *text = textView.text; 123 | if ([text isEqualToString:kKTSecretViewControllerTextViewPlaceholderText]) { 124 | 125 | // clear placeholder text 126 | textView.text = @""; 127 | 128 | // save the line height for single line text for calculation 129 | [self updateSingleLineHeightFromTextContainer]; 130 | 131 | } 132 | } 133 | 134 | -(void)textViewDidEndEditing:(UITextView *)textView 135 | { 136 | // reset to placeholder text if empty 137 | NSString *text = textView.text; 138 | if (![text length]) { 139 | textView.text = kKTSecretViewControllerTextViewPlaceholderText; 140 | } 141 | } 142 | 143 | - (void)textViewDidChange:(UITextView *)textView 144 | { 145 | [self updateContentInsetOnContentChange:textView]; 146 | if ([self.secretTextViewDelegate respondsToSelector:@selector(secretTextView:textViewDidChange:)]) { 147 | [self.secretTextViewDelegate secretTextView:self textViewDidChange:textView]; 148 | } 149 | 150 | } 151 | 152 | - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text 153 | { 154 | BOOL shouldChangeText = YES; 155 | CGRect rectForCurrentText = [self.layoutManager usedRectForTextContainer:self.textContainer]; 156 | NSUInteger numberOfLines = round(rectForCurrentText.size.height/self.defaultSingleLineHeight); 157 | 158 | // do not allow adding new text if reached maximum line limit 159 | if (numberOfLines > kKTSecretTextViewMaxNumberOfLines) { 160 | if ([text length]) { 161 | shouldChangeText = NO; 162 | } 163 | } 164 | return shouldChangeText; 165 | } 166 | 167 | #pragma makr - text container resize methods 168 | 169 | - (void)updateSingleLineHeightFromTextContainer 170 | { 171 | // save default single line height which is useful for calculating insets later on 172 | CGRect rectForCurrentText = [self.layoutManager usedRectForTextContainer:self.textContainer]; 173 | self.defaultSingleLineHeight = rectForCurrentText.size.height; 174 | 175 | } 176 | 177 | - (void)updateContentInsetOnContentChange:(UITextView *)textView 178 | { 179 | CGRect rectForCurrentText = [self.layoutManager usedRectForTextContainer:self.textContainer]; 180 | 181 | CGFloat containerInsetFromTop = kKTSecretTextViewDefaultContainerInsetFromTop; 182 | UIEdgeInsets containerInsets = kKTSecretTextViewDefaultTextContainerInset; 183 | 184 | NSUInteger numberOfLines = round(rectForCurrentText.size.height/self.defaultSingleLineHeight); 185 | 186 | // when text starts to fill up the textview, change the content inset allowing the text to move up 187 | if (numberOfLines > 2) { 188 | containerInsetFromTop = numberOfLines*self.defaultSingleLineHeight + kKTSecretTextViewDefaultContainerInsetFromTopMinimum; 189 | } 190 | // set to default value if calculation went beyond or below alloweed thresholds 191 | if ( (containerInsetFromTop < kKTSecretTextViewDefaultContainerInsetFromTopMinimum) || 192 | (containerInsetFromTop > kKTSecretTextViewDefaultContainerInsetFromTop) ){ 193 | containerInsetFromTop = kKTSecretTextViewDefaultContainerInsetFromTopMinimum; 194 | } 195 | containerInsets.top = containerInsetFromTop; 196 | self.textContainerInset = containerInsets; 197 | } 198 | 199 | @end 200 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretTextView.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretTextView.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/4/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTSecretTextView.h" 10 | 11 | // default container inset. this is to vertically center text in the text view 12 | 13 | static NSString* const kKTSecretViewControllerTextViewPlaceholderText = @"Share a thought"; 14 | static CGFloat const kKTSecretTextViewDefaultContainerInsetFromTop = 150.0f; 15 | static CGFloat const kKTSecretTextViewDefaultContainerInsetFromTopMinimum = 30.9f; 16 | static NSUInteger const kKTSecretTextViewMaxNumberOfLines = 10; 17 | 18 | static UIEdgeInsets const kKTSecretTextViewDefaultTextContainerInset = {kKTSecretTextViewDefaultContainerInsetFromTop, 10.0f, 20.0f, 10.0f}; 19 | 20 | 21 | @interface KTSecretTextView()< 22 | UITextViewDelegate 23 | > 24 | 25 | @property (nonatomic) CGFloat defaultSingleLineHeight; 26 | @property (nonatomic, strong) NSDictionary *textAttributes; 27 | 28 | @end 29 | 30 | 31 | @implementation KTSecretTextView 32 | 33 | #pragma mark - Public 34 | 35 | - (instancetype)init 36 | { 37 | if (self = [super init]) { 38 | self.delegate = self; 39 | self.textAlignment = NSTextAlignmentCenter; 40 | self.backgroundColor = [UIColor clearColor]; 41 | self.tintColor = [UIColor whiteColor]; 42 | self.autocorrectionType = UITextAutocorrectionTypeNo; 43 | self.text = kKTSecretViewControllerTextViewPlaceholderText; 44 | [self setupDefaultContentInset]; 45 | } 46 | return self; 47 | } 48 | 49 | - (void)setText:(NSString *)text 50 | { 51 | self.attributedText = [[NSAttributedString alloc] initWithString:text attributes:self.textAttributes]; 52 | } 53 | 54 | #pragma mark - Override 55 | 56 | - (void)setTintColor:(UIColor *)tintColor 57 | { 58 | [super setTintColor:tintColor]; 59 | self.textColor = tintColor; 60 | } 61 | 62 | #pragma mark - Private 63 | 64 | #pragma mark - Private properties 65 | 66 | - (NSDictionary*)textAttributes 67 | { 68 | if (!_textAttributes) { 69 | 70 | NSMutableParagraphStyle *paragrahStyle = [NSMutableParagraphStyle new]; 71 | paragrahStyle.lineSpacing = 6.0f; 72 | paragrahStyle.alignment = NSTextAlignmentCenter; 73 | 74 | NSShadow *shadow = [NSShadow new]; 75 | shadow.shadowColor = [UIColor blackColor]; 76 | shadow.shadowOffset = CGSizeMake(1, 1); 77 | shadow.shadowBlurRadius = 2.0f; 78 | 79 | _textAttributes = @{ 80 | NSFontAttributeName: [UIFont fontWithName:@"AvenirNextCondensed-Medium" size:22.0f], 81 | NSParagraphStyleAttributeName: paragrahStyle, 82 | NSForegroundColorAttributeName: [UIColor whiteColor], 83 | NSShadowAttributeName: shadow 84 | }; 85 | } 86 | return _textAttributes; 87 | } 88 | 89 | #pragma mark - Initialization Helpers 90 | 91 | 92 | - (void)setupDefaultContentInset 93 | { 94 | self.textContainerInset = kKTSecretTextViewDefaultTextContainerInset; 95 | } 96 | 97 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 98 | { 99 | UIView *viewToReceiveTouch = nil; 100 | 101 | CGRect rectForCurrentText = [self.layoutManager usedRectForTextContainer:self.textContainer]; 102 | rectForCurrentText.origin.x += self.textContainerInset.left; 103 | rectForCurrentText.origin.y += self.textContainerInset.top; 104 | 105 | if (!CGRectContainsPoint(rectForCurrentText, point)) { 106 | viewToReceiveTouch = [self.secretTextViewDelegate secretTextView:self viewForHitTest:point withEvent:event]; 107 | if (self.isFirstResponder) { 108 | [self resignFirstResponder]; 109 | } 110 | } 111 | // consume event if delegate doesnt provide a view or is inside tect 112 | if (!viewToReceiveTouch) { 113 | viewToReceiveTouch = self; 114 | } 115 | return viewToReceiveTouch; 116 | } 117 | 118 | #pragma mark - UITextViewDelegate methods 119 | 120 | -(void)textViewDidBeginEditing:(UITextView *)textView 121 | { 122 | NSString *text = textView.text; 123 | if ([text isEqualToString:kKTSecretViewControllerTextViewPlaceholderText]) { 124 | 125 | // clear placeholder text 126 | textView.text = @""; 127 | 128 | // save the line height for single line text for calculation 129 | [self updateSingleLineHeightFromTextContainer]; 130 | 131 | } 132 | } 133 | 134 | -(void)textViewDidEndEditing:(UITextView *)textView 135 | { 136 | // reset to placeholder text if empty 137 | NSString *text = textView.text; 138 | if (![text length]) { 139 | textView.text = kKTSecretViewControllerTextViewPlaceholderText; 140 | } 141 | } 142 | 143 | - (void)textViewDidChange:(UITextView *)textView 144 | { 145 | [self updateContentInsetOnContentChange:textView]; 146 | if ([self.secretTextViewDelegate respondsToSelector:@selector(secretTextView:textViewDidChange:)]) { 147 | [self.secretTextViewDelegate secretTextView:self textViewDidChange:textView]; 148 | } 149 | 150 | } 151 | 152 | - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text 153 | { 154 | BOOL shouldChangeText = YES; 155 | CGRect rectForCurrentText = [self.layoutManager usedRectForTextContainer:self.textContainer]; 156 | NSUInteger numberOfLines = round(rectForCurrentText.size.height/self.defaultSingleLineHeight); 157 | 158 | // do not allow adding new text if reached maximum line limit 159 | if (numberOfLines > kKTSecretTextViewMaxNumberOfLines) { 160 | if ([text length]) { 161 | shouldChangeText = NO; 162 | } 163 | } 164 | return shouldChangeText; 165 | } 166 | 167 | #pragma makr - text container resize methods 168 | 169 | - (void)updateSingleLineHeightFromTextContainer 170 | { 171 | // save default single line height which is useful for calculating insets later on 172 | CGRect rectForCurrentText = [self.layoutManager usedRectForTextContainer:self.textContainer]; 173 | self.defaultSingleLineHeight = rectForCurrentText.size.height; 174 | 175 | } 176 | 177 | - (void)updateContentInsetOnContentChange:(UITextView *)textView 178 | { 179 | CGRect rectForCurrentText = [self.layoutManager usedRectForTextContainer:self.textContainer]; 180 | 181 | CGFloat containerInsetFromTop = kKTSecretTextViewDefaultContainerInsetFromTop; 182 | UIEdgeInsets containerInsets = kKTSecretTextViewDefaultTextContainerInset; 183 | 184 | NSUInteger numberOfLines = round(rectForCurrentText.size.height/self.defaultSingleLineHeight); 185 | 186 | // when text starts to fill up the textview, change the content inset allowing the text to move up 187 | if (numberOfLines > 2) { 188 | containerInsetFromTop = numberOfLines*self.defaultSingleLineHeight + kKTSecretTextViewDefaultContainerInsetFromTopMinimum; 189 | } 190 | // set to default value if calculation went beyond or below alloweed thresholds 191 | if ( (containerInsetFromTop < kKTSecretTextViewDefaultContainerInsetFromTopMinimum) || 192 | (containerInsetFromTop > kKTSecretTextViewDefaultContainerInsetFromTop) ){ 193 | containerInsetFromTop = kKTSecretTextViewDefaultContainerInsetFromTopMinimum; 194 | } 195 | containerInsets.top = containerInsetFromTop; 196 | self.textContainerInset = containerInsets; 197 | } 198 | 199 | @end 200 | -------------------------------------------------------------------------------- /SecretTextView/KTSecretPhotosEditorViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretPhotosEditorViewController.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/1/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTSecretPhotosEditorViewController.h" 10 | #import "KTNumberUtil.h" 11 | 12 | static const CGFloat kKTSecretPhotosEditorViewControllerHorizontalPanThreshold = 3.0f; 13 | static const CGFloat kKTSecretPhotosEditorViewControllerHorizontalPanLimit = 150.0f; 14 | static const CGFloat kKTSecretPhotosEditorViewControllerHorizontalBlurLimit = 3.0f; 15 | 16 | static const CGFloat kKTSecretPhotosEditorViewControllerVerticalPanThreshold = 3.0f; 17 | static const CGFloat kKTSecretPhotosEditorViewControllerVerticalPanLimit = 180.0f; 18 | static const CGFloat kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMin = 1.0f; 19 | static const CGFloat kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMax = 3.0f; 20 | 21 | 22 | @interface KTSecretPhotosEditorViewController () 23 | 24 | @property (nonatomic, strong) UIImage *finalImage; 25 | 26 | @property (nonatomic, strong) UIImageView *photoImageView; 27 | @property (nonatomic, strong) UIImage *selectedImageOriginal; 28 | 29 | @property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer; 30 | 31 | @property (nonatomic) CGFloat blurLevel; 32 | @property (nonatomic) CGFloat brightnessLevel; 33 | 34 | // core image 35 | @property (nonatomic, strong) CIContext *coreImageContext; 36 | @property (nonatomic, strong) CIFilter *gammaFilter; 37 | @property (nonatomic, strong) CIFilter *blurFilter; 38 | 39 | @property (nonatomic) CGFloat currentGammaFilterValue; 40 | @property (nonatomic) CGFloat currentBlurFilterValue; 41 | 42 | @property (nonatomic) CGFloat lastPositionX; 43 | @property (nonatomic) CGFloat lastPositionY; 44 | 45 | 46 | @end 47 | 48 | 49 | @implementation KTSecretPhotosEditorViewController 50 | 51 | #pragma mark - Public 52 | 53 | #pragma mark - View lifecycle 54 | 55 | - (void)viewDidLoad 56 | { 57 | [super viewDidLoad]; 58 | self.blurLevel = 0.0f; 59 | self.brightnessLevel = 1.0f; 60 | self.currentGammaFilterValue = 1.0f; 61 | self.currentBlurFilterValue = 1.0f; 62 | self.lastPositionX = 0.0f; 63 | self.lastPositionY = 0.0f; 64 | 65 | 66 | [self addSubviewTree]; 67 | [self constrainViews]; 68 | [self setUpGestureRecognizers]; 69 | } 70 | 71 | - (void)loadView 72 | { 73 | self.view = [self mainView]; 74 | } 75 | 76 | #pragma mark - Public Properties 77 | 78 | - (void)setSelectedImage:(UIImage *)selectedImage 79 | { 80 | _selectedImage = nil; 81 | _selectedImage = selectedImage; 82 | self.selectedImageOriginal = selectedImage; 83 | self.photoImageView.image = selectedImage; 84 | } 85 | 86 | 87 | #pragma mark - Initialization 88 | 89 | - (UIView *)mainView 90 | { 91 | UIView *mainView = [UIView new]; 92 | mainView.translatesAutoresizingMaskIntoConstraints = NO; 93 | mainView.userInteractionEnabled = YES; 94 | mainView.backgroundColor = [UIColor blackColor]; 95 | return mainView; 96 | } 97 | 98 | - (void)addSubviewTree 99 | { 100 | [self.view addSubview:self.photoImageView]; 101 | } 102 | 103 | - (void)constrainViews 104 | { 105 | NSDictionary *viewsDict = @{ 106 | @"photoImageView":self.photoImageView 107 | }; 108 | 109 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[photoImageView]|" options:0 metrics:nil views:viewsDict]]; 110 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[photoImageView]|" options:0 metrics:nil views:viewsDict]]; 111 | 112 | } 113 | 114 | - (void)setUpGestureRecognizers 115 | { 116 | UIView *view = self.view; 117 | [view addGestureRecognizer:self.panGestureRecognizer]; 118 | } 119 | 120 | #pragma mark - Private 121 | 122 | #pragma mark - Private properties 123 | 124 | - (CIFilter*) gammaFilter 125 | { 126 | if (!_gammaFilter) { 127 | _gammaFilter = [CIFilter filterWithName:@"CIGammaAdjust"]; 128 | } 129 | return _gammaFilter; 130 | } 131 | 132 | - (CIFilter*) blurFilter 133 | { 134 | if (!_blurFilter) { 135 | _blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; 136 | } 137 | return _blurFilter; 138 | } 139 | 140 | - (CIContext*) coreImageContext 141 | { 142 | if (!_coreImageContext) { 143 | _coreImageContext = [CIContext contextWithOptions:nil]; 144 | } 145 | return _coreImageContext; 146 | } 147 | 148 | - (UIImageView*) photoImageView 149 | { 150 | if (!_photoImageView) { 151 | _photoImageView = [UIImageView new]; 152 | _photoImageView.contentMode = UIViewContentModeScaleAspectFill; 153 | _photoImageView.clipsToBounds = YES; 154 | _photoImageView.translatesAutoresizingMaskIntoConstraints = NO; 155 | } 156 | return _photoImageView; 157 | } 158 | 159 | - (UIPanGestureRecognizer*)panGestureRecognizer 160 | { 161 | if (!_panGestureRecognizer) { 162 | _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; 163 | } 164 | return _panGestureRecognizer; 165 | } 166 | 167 | #pragma mark - UIPanGestureRecognizer handling methods 168 | 169 | - (void)handlePanGesture:(UIPanGestureRecognizer*)panGestureRecognizer 170 | { 171 | CGPoint translationInView = [panGestureRecognizer translationInView:self.view]; 172 | CGPoint positionInView = [panGestureRecognizer locationInView:self.view]; 173 | 174 | CGFloat translationX = translationInView.x; 175 | CGFloat translationY = translationInView.y; 176 | CGFloat positionX = positionInView.x; 177 | CGFloat positionY = positionInView.y; 178 | 179 | if (panGestureRecognizer.state == UIGestureRecognizerStateChanged) { 180 | 181 | // don't trigger too often to improve performance 182 | CGFloat positionXDiff = self.lastPositionX - positionX; 183 | CGFloat positionYDiff = self.lastPositionY - positionY; 184 | 185 | if ((abs(positionXDiff) > kKTSecretPhotosEditorViewControllerHorizontalPanThreshold) || 186 | (abs(positionYDiff) > kKTSecretPhotosEditorViewControllerVerticalPanThreshold) 187 | ){ 188 | [self updateFiltersOnImage:translationX translationY:translationY]; 189 | } 190 | 191 | }else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) { 192 | [self updateFiltersOnImage:translationX translationY:translationY]; 193 | } 194 | 195 | self.lastPositionX = positionX; 196 | self.lastPositionY = positionY; 197 | 198 | } 199 | 200 | - (void)updateFiltersOnImage:(CGFloat)translationX translationY:(CGFloat)translationY 201 | { 202 | if (abs(translationX) > kKTSecretPhotosEditorViewControllerHorizontalPanThreshold) { 203 | CGFloat blurLevel = [self blurLevelFromTranslationX:translationX]; 204 | self.currentBlurFilterValue = blurLevel; 205 | } 206 | if (abs(translationY) > kKTSecretPhotosEditorViewControllerVerticalPanThreshold) { 207 | CGFloat brightnessLevel = [self brightnessLevelFromTranslationY:translationY]; 208 | self.currentGammaFilterValue = brightnessLevel; 209 | } 210 | [self updatePhotoImageFilters]; 211 | [self updateDelegetOnImageFilterChanges]; 212 | } 213 | 214 | - (void)updateDelegetOnImageFilterChanges 215 | { 216 | static CGFloat kKTSecretPhotosEditorViewControllerPercentageLimit = 100.0f; 217 | 218 | CGFloat blurPercentage = [KTNumberUtil remapNumbersToRange:self.currentBlurFilterValue fromMin:0.0f fromMax:kKTSecretPhotosEditorViewControllerHorizontalBlurLimit toMin:0 toMax:kKTSecretPhotosEditorViewControllerPercentageLimit]; 219 | 220 | CGFloat dimPercentage = [KTNumberUtil remapNumbersToRange:self.currentGammaFilterValue fromMin:kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMin fromMax:kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMax toMin:0 toMax:kKTSecretPhotosEditorViewControllerPercentageLimit]; 221 | 222 | [self.delegate secretPhotosEditorViewController:self didUpdateFilters:blurPercentage brightnessLevel:dimPercentage]; 223 | } 224 | 225 | - (CGFloat)blurLevelFromTranslationX:(CGFloat)translationX 226 | { 227 | // translate 0-250 to 0-3.0 228 | CGFloat blurLevelScaled = [KTNumberUtil remapNumbersToRange:translationX fromMin:0.0f fromMax:kKTSecretPhotosEditorViewControllerHorizontalPanLimit toMin:0.0f toMax:kKTSecretPhotosEditorViewControllerHorizontalBlurLimit]; 229 | 230 | blurLevelScaled = MAX(0.0f, blurLevelScaled); 231 | blurLevelScaled = MIN(kKTSecretPhotosEditorViewControllerHorizontalBlurLimit, blurLevelScaled); 232 | return blurLevelScaled; 233 | } 234 | 235 | - (CGFloat)brightnessLevelFromTranslationY:(CGFloat)translationY 236 | { 237 | // invert it as we want the image to dim with a upwards pan 238 | translationY = -1 * translationY; 239 | 240 | CGFloat brightnessLevelScaled = [KTNumberUtil remapNumbersToRange:translationY fromMin:0.0f fromMax:kKTSecretPhotosEditorViewControllerVerticalPanLimit toMin:kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMin toMax:kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMax]; 241 | 242 | brightnessLevelScaled = MAX(1.0f, brightnessLevelScaled); 243 | brightnessLevelScaled = MIN(kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMax, brightnessLevelScaled); 244 | 245 | return brightnessLevelScaled; 246 | } 247 | 248 | - (void)updatePhotoImageFilters 249 | { 250 | CIImage *ciImage = [CIImage imageWithCGImage:self.selectedImageOriginal.CGImage]; 251 | CIImage *result = nil; 252 | 253 | CIFilter *blurFilter = self.blurFilter; 254 | [blurFilter setValue:ciImage forKey:kCIInputImageKey]; 255 | [blurFilter setValue:@(self.currentBlurFilterValue) forKey:@"inputRadius"]; 256 | result = [blurFilter valueForKey:kCIOutputImageKey]; 257 | 258 | CIFilter *gammaFilter = self.gammaFilter; 259 | [gammaFilter setValue:result forKey:kCIInputImageKey]; 260 | [gammaFilter setValue:@(self.currentGammaFilterValue) forKey:@"inputPower"]; 261 | result = [gammaFilter valueForKey:kCIOutputImageKey]; 262 | 263 | 264 | CGImageRef cgImage = [self.coreImageContext createCGImage:result fromRect:[ciImage extent]]; 265 | UIImage *outputImage = [UIImage imageWithCGImage:cgImage]; 266 | CGImageRelease(cgImage); 267 | 268 | self.photoImageView.image = outputImage; 269 | self.finalImage = outputImage; 270 | } 271 | 272 | @end 273 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretPhotosEditorViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretPhotosEditorViewController.m 3 | // SecretTextViewSampleApp 4 | // 5 | // Created by Kenny Tang on 5/1/14. 6 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 7 | // 8 | 9 | #import "KTSecretPhotosEditorViewController.h" 10 | #import "KTNumberUtil.h" 11 | 12 | static const CGFloat kKTSecretPhotosEditorViewControllerHorizontalPanThreshold = 3.0f; 13 | static const CGFloat kKTSecretPhotosEditorViewControllerHorizontalPanLimit = 150.0f; 14 | static const CGFloat kKTSecretPhotosEditorViewControllerHorizontalBlurLimit = 3.0f; 15 | 16 | static const CGFloat kKTSecretPhotosEditorViewControllerVerticalPanThreshold = 3.0f; 17 | static const CGFloat kKTSecretPhotosEditorViewControllerVerticalPanLimit = 180.0f; 18 | static const CGFloat kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMin = 1.0f; 19 | static const CGFloat kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMax = 3.0f; 20 | 21 | 22 | @interface KTSecretPhotosEditorViewController () 23 | 24 | @property (nonatomic, strong) UIImage *finalImage; 25 | 26 | @property (nonatomic, strong) UIImageView *photoImageView; 27 | @property (nonatomic, strong) UIImage *selectedImageOriginal; 28 | 29 | @property (nonatomic, strong) UIPanGestureRecognizer *panGestureRecognizer; 30 | 31 | @property (nonatomic) CGFloat blurLevel; 32 | @property (nonatomic) CGFloat brightnessLevel; 33 | 34 | // core image 35 | @property (nonatomic, strong) CIContext *coreImageContext; 36 | @property (nonatomic, strong) CIFilter *gammaFilter; 37 | @property (nonatomic, strong) CIFilter *blurFilter; 38 | 39 | @property (nonatomic) CGFloat currentGammaFilterValue; 40 | @property (nonatomic) CGFloat currentBlurFilterValue; 41 | 42 | @property (nonatomic) CGFloat lastPositionX; 43 | @property (nonatomic) CGFloat lastPositionY; 44 | 45 | 46 | @end 47 | 48 | 49 | @implementation KTSecretPhotosEditorViewController 50 | 51 | #pragma mark - Public 52 | 53 | #pragma mark - View lifecycle 54 | 55 | - (void)viewDidLoad 56 | { 57 | [super viewDidLoad]; 58 | self.blurLevel = 0.0f; 59 | self.brightnessLevel = 1.0f; 60 | self.currentGammaFilterValue = 1.0f; 61 | self.currentBlurFilterValue = 1.0f; 62 | self.lastPositionX = 0.0f; 63 | self.lastPositionY = 0.0f; 64 | 65 | 66 | [self addSubviewTree]; 67 | [self constrainViews]; 68 | [self setUpGestureRecognizers]; 69 | } 70 | 71 | - (void)loadView 72 | { 73 | self.view = [self mainView]; 74 | } 75 | 76 | #pragma mark - Public Properties 77 | 78 | - (void)setSelectedImage:(UIImage *)selectedImage 79 | { 80 | _selectedImage = nil; 81 | _selectedImage = selectedImage; 82 | self.selectedImageOriginal = selectedImage; 83 | self.photoImageView.image = selectedImage; 84 | } 85 | 86 | 87 | #pragma mark - Initialization 88 | 89 | - (UIView *)mainView 90 | { 91 | UIView *mainView = [UIView new]; 92 | mainView.translatesAutoresizingMaskIntoConstraints = NO; 93 | mainView.userInteractionEnabled = YES; 94 | mainView.backgroundColor = [UIColor blackColor]; 95 | return mainView; 96 | } 97 | 98 | - (void)addSubviewTree 99 | { 100 | [self.view addSubview:self.photoImageView]; 101 | } 102 | 103 | - (void)constrainViews 104 | { 105 | NSDictionary *viewsDict = @{ 106 | @"photoImageView":self.photoImageView 107 | }; 108 | 109 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[photoImageView]|" options:0 metrics:nil views:viewsDict]]; 110 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[photoImageView]|" options:0 metrics:nil views:viewsDict]]; 111 | 112 | } 113 | 114 | - (void)setUpGestureRecognizers 115 | { 116 | UIView *view = self.view; 117 | [view addGestureRecognizer:self.panGestureRecognizer]; 118 | } 119 | 120 | #pragma mark - Private 121 | 122 | #pragma mark - Private properties 123 | 124 | - (CIFilter*) gammaFilter 125 | { 126 | if (!_gammaFilter) { 127 | _gammaFilter = [CIFilter filterWithName:@"CIGammaAdjust"]; 128 | } 129 | return _gammaFilter; 130 | } 131 | 132 | - (CIFilter*) blurFilter 133 | { 134 | if (!_blurFilter) { 135 | _blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; 136 | } 137 | return _blurFilter; 138 | } 139 | 140 | - (CIContext*) coreImageContext 141 | { 142 | if (!_coreImageContext) { 143 | _coreImageContext = [CIContext contextWithOptions:nil]; 144 | } 145 | return _coreImageContext; 146 | } 147 | 148 | - (UIImageView*) photoImageView 149 | { 150 | if (!_photoImageView) { 151 | _photoImageView = [UIImageView new]; 152 | _photoImageView.contentMode = UIViewContentModeScaleAspectFill; 153 | _photoImageView.clipsToBounds = YES; 154 | _photoImageView.translatesAutoresizingMaskIntoConstraints = NO; 155 | } 156 | return _photoImageView; 157 | } 158 | 159 | - (UIPanGestureRecognizer*)panGestureRecognizer 160 | { 161 | if (!_panGestureRecognizer) { 162 | _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; 163 | } 164 | return _panGestureRecognizer; 165 | } 166 | 167 | #pragma mark - UIPanGestureRecognizer handling methods 168 | 169 | - (void)handlePanGesture:(UIPanGestureRecognizer*)panGestureRecognizer 170 | { 171 | CGPoint translationInView = [panGestureRecognizer translationInView:self.view]; 172 | CGPoint positionInView = [panGestureRecognizer locationInView:self.view]; 173 | 174 | CGFloat translationX = translationInView.x; 175 | CGFloat translationY = translationInView.y; 176 | CGFloat positionX = positionInView.x; 177 | CGFloat positionY = positionInView.y; 178 | 179 | if (panGestureRecognizer.state == UIGestureRecognizerStateChanged) { 180 | 181 | // don't trigger too often to improve performance 182 | CGFloat positionXDiff = self.lastPositionX - positionX; 183 | CGFloat positionYDiff = self.lastPositionY - positionY; 184 | 185 | if ((abs(positionXDiff) > kKTSecretPhotosEditorViewControllerHorizontalPanThreshold) || 186 | (abs(positionYDiff) > kKTSecretPhotosEditorViewControllerVerticalPanThreshold) 187 | ){ 188 | [self updateFiltersOnImage:translationX translationY:translationY]; 189 | } 190 | 191 | }else if (panGestureRecognizer.state == UIGestureRecognizerStateEnded) { 192 | [self updateFiltersOnImage:translationX translationY:translationY]; 193 | } 194 | 195 | self.lastPositionX = positionX; 196 | self.lastPositionY = positionY; 197 | 198 | } 199 | 200 | - (void)updateFiltersOnImage:(CGFloat)translationX translationY:(CGFloat)translationY 201 | { 202 | if (abs(translationX) > kKTSecretPhotosEditorViewControllerHorizontalPanThreshold) { 203 | CGFloat blurLevel = [self blurLevelFromTranslationX:translationX]; 204 | self.currentBlurFilterValue = blurLevel; 205 | } 206 | if (abs(translationY) > kKTSecretPhotosEditorViewControllerVerticalPanThreshold) { 207 | CGFloat brightnessLevel = [self brightnessLevelFromTranslationY:translationY]; 208 | self.currentGammaFilterValue = brightnessLevel; 209 | } 210 | [self updatePhotoImageFilters]; 211 | [self updateDelegetOnImageFilterChanges]; 212 | } 213 | 214 | - (void)updateDelegetOnImageFilterChanges 215 | { 216 | static CGFloat kKTSecretPhotosEditorViewControllerPercentageLimit = 100.0f; 217 | 218 | CGFloat blurPercentage = [KTNumberUtil remapNumbersToRange:self.currentBlurFilterValue fromMin:0.0f fromMax:kKTSecretPhotosEditorViewControllerHorizontalBlurLimit toMin:0 toMax:kKTSecretPhotosEditorViewControllerPercentageLimit]; 219 | 220 | CGFloat dimPercentage = [KTNumberUtil remapNumbersToRange:self.currentGammaFilterValue fromMin:kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMin fromMax:kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMax toMin:0 toMax:kKTSecretPhotosEditorViewControllerPercentageLimit]; 221 | 222 | [self.delegate secretPhotosEditorViewController:self didUpdateFilters:blurPercentage brightnessLevel:dimPercentage]; 223 | } 224 | 225 | - (CGFloat)blurLevelFromTranslationX:(CGFloat)translationX 226 | { 227 | // translate 0-250 to 0-3.0 228 | CGFloat blurLevelScaled = [KTNumberUtil remapNumbersToRange:translationX fromMin:0.0f fromMax:kKTSecretPhotosEditorViewControllerHorizontalPanLimit toMin:0.0f toMax:kKTSecretPhotosEditorViewControllerHorizontalBlurLimit]; 229 | 230 | blurLevelScaled = MAX(0.0f, blurLevelScaled); 231 | blurLevelScaled = MIN(kKTSecretPhotosEditorViewControllerHorizontalBlurLimit, blurLevelScaled); 232 | return blurLevelScaled; 233 | } 234 | 235 | - (CGFloat)brightnessLevelFromTranslationY:(CGFloat)translationY 236 | { 237 | // invert it as we want the image to dim with a upwards pan 238 | translationY = -1 * translationY; 239 | 240 | CGFloat brightnessLevelScaled = [KTNumberUtil remapNumbersToRange:translationY fromMin:0.0f fromMax:kKTSecretPhotosEditorViewControllerVerticalPanLimit toMin:kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMin toMax:kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMax]; 241 | 242 | brightnessLevelScaled = MAX(1.0f, brightnessLevelScaled); 243 | brightnessLevelScaled = MIN(kKTSecretPhotosEditorViewControllerVerticalBrightnessLimitMax, brightnessLevelScaled); 244 | 245 | return brightnessLevelScaled; 246 | } 247 | 248 | - (void)updatePhotoImageFilters 249 | { 250 | CIImage *ciImage = [CIImage imageWithCGImage:self.selectedImageOriginal.CGImage]; 251 | CIImage *result = nil; 252 | 253 | CIFilter *blurFilter = self.blurFilter; 254 | [blurFilter setValue:ciImage forKey:kCIInputImageKey]; 255 | [blurFilter setValue:@(self.currentBlurFilterValue) forKey:@"inputRadius"]; 256 | result = [blurFilter valueForKey:kCIOutputImageKey]; 257 | 258 | CIFilter *gammaFilter = self.gammaFilter; 259 | [gammaFilter setValue:result forKey:kCIInputImageKey]; 260 | [gammaFilter setValue:@(self.currentGammaFilterValue) forKey:@"inputPower"]; 261 | result = [gammaFilter valueForKey:kCIOutputImageKey]; 262 | 263 | 264 | CGImageRef cgImage = [self.coreImageContext createCGImage:result fromRect:[ciImage extent]]; 265 | UIImage *outputImage = [UIImage imageWithCGImage:cgImage]; 266 | CGImageRelease(cgImage); 267 | 268 | self.photoImageView.image = outputImage; 269 | self.finalImage = outputImage; 270 | } 271 | 272 | @end 273 | -------------------------------------------------------------------------------- /SecretTextView/KTSecretColorChooserViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretColorChooserViewController.m 3 | // 4 | // Created by Kenny Tang on 4/29/14. 5 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 6 | // 7 | 8 | #import "KTSecretColorChooserViewController.h" 9 | 10 | typedef NS_ENUM(NSUInteger, KTSecretDefaultColor) 11 | { 12 | KTSecretDefaultColorEmeraldSea = 0, 13 | KTSecretDefaultColorHopscotch, 14 | KTSecretDefaultColorLavender, 15 | KTSecretDefaultColorBurst, 16 | KTSecretDefaultColorCupid, 17 | KTSecretDefaultColorPeony, 18 | KTSecretDefaultColorMidnight, 19 | KTSecretDefaultColorWhite 20 | }; 21 | 22 | static NSString * const kKTSecretColorChooserViewControllerCellIdentifier = @"kKTSecretColorChooserViewControllerCellIdentifier"; 23 | static CGFloat const kKTSecretColorChooserViewControllerDefaultCellHeight = 380.0f; 24 | 25 | 26 | @interface KTSecretColorChooserViewController ()< 27 | UICollectionViewDataSource, 28 | UICollectionViewDelegate 29 | > 30 | 31 | /** 32 | * Collection view which holds each color as a cell. 33 | */ 34 | @property (nonatomic, strong) UICollectionView *collectionView; 35 | 36 | /** 37 | * Normal layout: each cell is wide as the screen bounds' width. 38 | */ 39 | @property (nonatomic, strong) UICollectionViewFlowLayout *defaultLayout; 40 | 41 | /** 42 | * Compressed layout: this is what makes the "rainbow" view. All cells resized to fit on the screen bounds' width. 43 | */ 44 | @property (nonatomic, strong) UICollectionViewFlowLayout *paletteLayout; 45 | 46 | /** 47 | * Long Press gesture recognizer toggles between the two layout modes. 48 | */ 49 | @property (nonatomic, strong) UILongPressGestureRecognizer *longPressGestureRecognizer; 50 | 51 | /** 52 | * Gesture recognizers for vertical swipes. Mainly for passing through to delegate. 53 | */ 54 | @property (nonatomic, strong) UISwipeGestureRecognizer *swipeUpGestureRecognizer; 55 | @property (nonatomic, strong) UISwipeGestureRecognizer *swipeDownGestureRecognizer; 56 | 57 | 58 | /** 59 | * The various cell sizes for each layout 60 | */ 61 | @property (nonatomic) CGSize defaultCellSize; 62 | @property (nonatomic) CGSize paletteCellSize; 63 | 64 | /** 65 | * The currently selected cell size 66 | */ 67 | @property (nonatomic) CGSize currentCellSize; 68 | 69 | /** 70 | * Tap gesture recognizer decides whether to propagate tap gestures to a delegate. 71 | */ 72 | @property (nonatomic, strong) UITapGestureRecognizer *tapGestureRecognizer; 73 | 74 | /** 75 | * Semi-transparent view that is displayed on a long press to indicate which color is being selected. 76 | */ 77 | @property (nonatomic, strong) UIView *hoverColorView; 78 | 79 | /** 80 | * NSDictionary of colors made available for selection 81 | */ 82 | @property (nonatomic, strong) NSDictionary *colorsDict; 83 | 84 | /** 85 | * Array of color names made available for selection 86 | */ 87 | @property (nonatomic, strong) NSDictionary *colorNamesDict; 88 | 89 | 90 | @end 91 | 92 | 93 | 94 | @implementation KTSecretColorChooserViewController 95 | 96 | #pragma mark - Public 97 | 98 | #pragma mark - View lifecycle 99 | 100 | - (void)viewDidLoad 101 | { 102 | [super viewDidLoad]; 103 | [self addSubviewTree]; 104 | [self constrainViews]; 105 | 106 | [self setUpGestureRecognizers]; 107 | 108 | self.currentCellSize = self.defaultCellSize; 109 | [self.collectionView reloadData]; 110 | 111 | } 112 | 113 | 114 | - (void)loadView 115 | { 116 | self.view = [self mainView]; 117 | } 118 | 119 | - (void)didReceiveMemoryWarning 120 | { 121 | [super didReceiveMemoryWarning]; 122 | // Dispose of any resources that can be recreated. 123 | } 124 | 125 | #pragma mark - Initialization 126 | 127 | - (void)setUpGestureRecognizers 128 | { 129 | UIView *collectionView = self.collectionView; 130 | [collectionView addGestureRecognizer:self.longPressGestureRecognizer]; 131 | [collectionView addGestureRecognizer:self.tapGestureRecognizer]; 132 | [collectionView addGestureRecognizer:self.swipeUpGestureRecognizer]; 133 | [collectionView addGestureRecognizer:self.swipeDownGestureRecognizer]; 134 | 135 | [self.swipeUpGestureRecognizer requireGestureRecognizerToFail:self.longPressGestureRecognizer]; 136 | [self.swipeDownGestureRecognizer requireGestureRecognizerToFail:self.longPressGestureRecognizer]; 137 | 138 | } 139 | 140 | - (UIView *)mainView 141 | { 142 | UIView *mainView = [UIView new]; 143 | mainView.translatesAutoresizingMaskIntoConstraints = NO; 144 | mainView.alpha = 0.9; 145 | mainView.clipsToBounds = YES; 146 | return mainView; 147 | } 148 | 149 | - (void)addSubviewTree 150 | { 151 | [self.view addSubview:self.collectionView]; 152 | [self.collectionView addSubview:self.hoverColorView]; 153 | } 154 | 155 | - (void)constrainViews 156 | { 157 | NSDictionary *viewsDict = @{@"collectionView":self.collectionView}; 158 | 159 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[collectionView]|" options:0 metrics:nil views:viewsDict]]; 160 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[collectionView]|" options:0 metrics:nil views:viewsDict]]; 161 | 162 | } 163 | 164 | #pragma mark - Private 165 | 166 | #pragma mark - Private properties 167 | 168 | - (UISwipeGestureRecognizer*) swipeUpGestureRecognizer 169 | { 170 | if (!_swipeUpGestureRecognizer) { 171 | _swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleUpSwipe:)]; 172 | _swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp; 173 | } 174 | return _swipeUpGestureRecognizer; 175 | } 176 | 177 | - (UISwipeGestureRecognizer*) swipeDownGestureRecognizer 178 | { 179 | if (!_swipeDownGestureRecognizer) { 180 | _swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleDownSwipe:)]; 181 | _swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown; 182 | } 183 | return _swipeDownGestureRecognizer; 184 | } 185 | 186 | 187 | - (UICollectionViewFlowLayout*) defaultLayout 188 | { 189 | if (!_defaultLayout){ 190 | _defaultLayout = [UICollectionViewFlowLayout new]; 191 | _defaultLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 192 | _defaultLayout.itemSize = self.defaultCellSize; 193 | _defaultLayout.minimumInteritemSpacing = 0.0f; 194 | _defaultLayout.minimumLineSpacing = 0.0f; 195 | } 196 | return _defaultLayout; 197 | } 198 | 199 | - (UICollectionViewFlowLayout*) paletteLayout 200 | { 201 | if (!_paletteLayout){ 202 | _paletteLayout = [UICollectionViewFlowLayout new]; 203 | _paletteLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 204 | _paletteLayout.itemSize = self.paletteCellSize; 205 | _paletteLayout.minimumInteritemSpacing = 0.0f; 206 | _paletteLayout.minimumLineSpacing = 0.0f; 207 | } 208 | return _paletteLayout; 209 | } 210 | 211 | - (UICollectionView*)collectionView 212 | { 213 | if (!_collectionView){ 214 | _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.defaultLayout]; 215 | _collectionView.translatesAutoresizingMaskIntoConstraints = NO; 216 | _collectionView.showsHorizontalScrollIndicator = NO; 217 | _collectionView.showsVerticalScrollIndicator = NO; 218 | _collectionView.clipsToBounds = YES; 219 | _collectionView.dataSource = self; 220 | _collectionView.delegate = self; 221 | _collectionView.pagingEnabled = YES; 222 | _collectionView.backgroundColor = [UIColor clearColor]; 223 | [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kKTSecretColorChooserViewControllerCellIdentifier]; 224 | } 225 | return _collectionView; 226 | } 227 | 228 | - (NSDictionary*) colorsDict 229 | { 230 | if (!_colorsDict){ 231 | _colorsDict = @{ 232 | @(KTSecretDefaultColorWhite) : [UIColor whiteColor], 233 | @(KTSecretDefaultColorEmeraldSea) : [UIColor colorWithRed:18.0f/255.0f green:133.0f/255.0f blue:116.0/255.0f alpha:1.0], 234 | @(KTSecretDefaultColorHopscotch) : [UIColor colorWithRed:157.0f/255.0f green:105.0f/255.0f blue:183.0/255.0f alpha:1.0], 235 | @(KTSecretDefaultColorLavender) : [UIColor colorWithRed:100.0f/255.0f green:57.0f/255.0f blue:144.0/255.0f alpha:1.0], 236 | @(KTSecretDefaultColorBurst) : [UIColor colorWithRed:213.0f/255.0f green:100.0f/255.0f blue:12.0f/255.0f alpha:1.0], 237 | @(KTSecretDefaultColorCupid) : [UIColor colorWithRed:157.0f/255.0f green:30.0f/255.0f blue:38.0f/255.0f alpha:1.0], 238 | @(KTSecretDefaultColorPeony) : [UIColor colorWithRed:220.0f/255.0f green:72.0f/255.0f blue:99.0f/255.0f alpha:1.0], 239 | @(KTSecretDefaultColorMidnight) : [UIColor colorWithRed:39.0f/255.0f green:36.0f/255.0f blue:32.0f/255.0f alpha:1.0] 240 | }; 241 | } 242 | return _colorsDict; 243 | } 244 | 245 | - (NSDictionary*) colorNamesDict 246 | { 247 | if (!_colorNamesDict){ 248 | _colorNamesDict = @{ 249 | @(KTSecretDefaultColorEmeraldSea) : NSLocalizedString(@"Emerald Sea", nil), 250 | @(KTSecretDefaultColorHopscotch) : NSLocalizedString(@"Hopscotch", nil), 251 | @(KTSecretDefaultColorLavender) : NSLocalizedString(@"Lavender", nil), 252 | @(KTSecretDefaultColorBurst) : NSLocalizedString(@"Burst", nil), 253 | @(KTSecretDefaultColorCupid) : NSLocalizedString(@"Cupid", nil), 254 | @(KTSecretDefaultColorPeony) : NSLocalizedString(@"Peony", nil), 255 | @(KTSecretDefaultColorMidnight) : NSLocalizedString(@"Midnight", nil), 256 | @(KTSecretDefaultColorWhite) : NSLocalizedString(@"Default", nil) 257 | }; 258 | } 259 | return _colorNamesDict; 260 | } 261 | 262 | - (UILongPressGestureRecognizer*) longPressGestureRecognizer 263 | { 264 | if (!_longPressGestureRecognizer) { 265 | _longPressGestureRecognizer = [UILongPressGestureRecognizer new]; 266 | [_longPressGestureRecognizer addTarget:self action:@selector(handleLongPressGesture:)]; 267 | } 268 | return _longPressGestureRecognizer; 269 | } 270 | 271 | - (UITapGestureRecognizer*) tapGestureRecognizer 272 | { 273 | if (!_tapGestureRecognizer) { 274 | _tapGestureRecognizer = [UITapGestureRecognizer new]; 275 | [_tapGestureRecognizer addTarget:self action:@selector(handleTapGesture:)]; 276 | } 277 | return _tapGestureRecognizer; 278 | } 279 | 280 | - (CGSize) defaultCellSize 281 | { 282 | return CGSizeMake([[UIScreen mainScreen] bounds].size.width, kKTSecretColorChooserViewControllerDefaultCellHeight); 283 | } 284 | 285 | - (CGSize) paletteCellSize 286 | { 287 | return CGSizeMake(([[UIScreen mainScreen] bounds].size.width)/[self.colorsDict count], kKTSecretColorChooserViewControllerDefaultCellHeight); 288 | } 289 | 290 | - (UIView*)hoverColorView 291 | { 292 | if (!_hoverColorView) { 293 | _hoverColorView = [UIView new]; 294 | 295 | float screenWidth = [[UIScreen mainScreen] bounds].size.width; 296 | float hoverViewWidth = screenWidth/[self.colorsDict count]; 297 | 298 | _hoverColorView.frame = CGRectMake(0, 0, hoverViewWidth, self.view.frame.size.height); 299 | _hoverColorView.backgroundColor = [UIColor lightTextColor]; 300 | _hoverColorView.alpha = 0.4; 301 | _hoverColorView.hidden = YES; 302 | } 303 | return _hoverColorView; 304 | } 305 | 306 | 307 | #pragma mark - Initialization helpers 308 | 309 | #pragma mark - Event handlers 310 | 311 | - (void)handleLongPressGesture:(UILongPressGestureRecognizer*)sender 312 | { 313 | if (sender.state == UIGestureRecognizerStateEnded) { 314 | [self handleLongPressEnded:sender]; 315 | 316 | }else if (sender.state == UIGestureRecognizerStateChanged) { 317 | [self handleLongPressMoved:sender]; 318 | 319 | }else { 320 | [self handleLongPressStarted:sender]; 321 | } 322 | } 323 | 324 | - (void)handleTapGesture:(UITapGestureRecognizer*)sender 325 | { 326 | // [self.delegate sec 327 | } 328 | 329 | #pragma mark - Long Press Activated handlers 330 | 331 | - (void)handleLongPressEnded:(UILongPressGestureRecognizer*)sender 332 | { 333 | self.currentCellSize = self.defaultCellSize; 334 | 335 | // find the selected color 336 | CGPoint locationInView = [sender locationInView:self.collectionView]; 337 | NSIndexPath *selectedCellIndexPath = [self.collectionView indexPathForItemAtPoint:locationInView]; 338 | UIColor *selectedColor = self.colorsDict[@(selectedCellIndexPath.item)]; 339 | 340 | // change to default layout 341 | CGFloat selectedCellRectX = self.currentCellSize.width*selectedCellIndexPath.item+1; 342 | self.hoverColorView.hidden = YES; 343 | [self.collectionView setCollectionViewLayout:self.defaultLayout animated:YES]; 344 | [self.collectionView scrollRectToVisible:CGRectMake(selectedCellRectX, 0, [[UIScreen mainScreen] bounds].size.width, 20.0f) animated:NO]; 345 | 346 | // update delegate on selected color 347 | NSString *colorName = self.colorNamesDict[@(selectedCellIndexPath.item)]; 348 | [self updateDelegateSelectedColor:selectedColor name:colorName]; 349 | } 350 | 351 | - (void)handleLongPressStarted:(UILongPressGestureRecognizer*)sender 352 | { 353 | // change to palette layout 354 | [self.collectionView setCollectionViewLayout:self.paletteLayout animated:YES]; 355 | } 356 | 357 | - (void)handleLongPressMoved:(UILongPressGestureRecognizer*)sender 358 | { 359 | // find the cell at touch point 360 | CGPoint locationInView = [sender locationInView:self.collectionView]; 361 | NSIndexPath *hoverCellIndexPath = [self.collectionView indexPathForItemAtPoint:locationInView]; 362 | UICollectionViewCell *colorCell = [self.collectionView cellForItemAtIndexPath:hoverCellIndexPath]; 363 | 364 | // move hover view over cell at touch point 365 | self.hoverColorView.frame = colorCell.frame; 366 | self.hoverColorView.hidden = NO; 367 | 368 | } 369 | 370 | #pragma mark - UIScrollViewDelegate methods 371 | 372 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 373 | { 374 | // find the cell at touch point 375 | UICollectionViewCell *cell = [[self.collectionView visibleCells] firstObject]; 376 | NSIndexPath *cellIndexPath = [self.collectionView indexPathForCell:cell]; 377 | 378 | // use index to find color 379 | UIColor *selectedColor = self.colorsDict[@(cellIndexPath.item)]; 380 | 381 | // update delegate on selected color 382 | NSString *colorName = self.colorNamesDict[@(cellIndexPath.item)]; 383 | [self updateDelegateSelectedColor:selectedColor name:colorName]; 384 | } 385 | 386 | #pragma mark - UICollectionViewDataSource methods 387 | 388 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView*)collectionView { 389 | return 1; 390 | } 391 | 392 | - (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section { 393 | return [self.colorsDict count]; 394 | } 395 | 396 | -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 397 | { 398 | UICollectionViewCell *cell = (UICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kKTSecretColorChooserViewControllerCellIdentifier forIndexPath:indexPath]; 399 | cell.backgroundColor = self.colorsDict[@(indexPath.item)]; 400 | 401 | 402 | return cell; 403 | } 404 | 405 | #pragma mark - Long Press Ended helper 406 | 407 | - (void)updateDelegateSelectedColor:(UIColor*)color name:(NSString*)name 408 | { 409 | if ([self.delegate respondsToSelector:@selector(secretColorChooserViewController:didSelectColor:name:)]) { 410 | 411 | [self.delegate secretColorChooserViewController:self didSelectColor:color name:name]; 412 | } 413 | } 414 | 415 | 416 | #pragma mark - UISwipeGestureRecognizer delegate methods 417 | 418 | - (void)handleUpSwipe:(UISwipeGestureRecognizer*)gestureRecognizer 419 | { 420 | if ([self.delegate respondsToSelector:@selector(secretColorChooserViewController:didSwipeUp:)]) { 421 | [self.delegate secretColorChooserViewController:self didSwipeUp:YES]; 422 | } 423 | } 424 | 425 | - (void)handleDownSwipe:(UISwipeGestureRecognizer*)gestureRecognizer 426 | { 427 | if ([self.delegate respondsToSelector:@selector(secretColorChooserViewController:didSwipeDown:)]) { 428 | [self.delegate secretColorChooserViewController:self didSwipeDown:YES]; 429 | } 430 | } 431 | 432 | 433 | @end 434 | -------------------------------------------------------------------------------- /Pods/KTSecretTextView/SecretTextView/KTSecretColorChooserViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSecretColorChooserViewController.m 3 | // 4 | // Created by Kenny Tang on 4/29/14. 5 | // Copyright (c) 2014 Corgitoergosum. All rights reserved. 6 | // 7 | 8 | #import "KTSecretColorChooserViewController.h" 9 | 10 | typedef NS_ENUM(NSUInteger, KTSecretDefaultColor) 11 | { 12 | KTSecretDefaultColorEmeraldSea = 0, 13 | KTSecretDefaultColorHopscotch, 14 | KTSecretDefaultColorLavender, 15 | KTSecretDefaultColorBurst, 16 | KTSecretDefaultColorCupid, 17 | KTSecretDefaultColorPeony, 18 | KTSecretDefaultColorMidnight, 19 | KTSecretDefaultColorWhite 20 | }; 21 | 22 | static NSString * const kKTSecretColorChooserViewControllerCellIdentifier = @"kKTSecretColorChooserViewControllerCellIdentifier"; 23 | static CGFloat const kKTSecretColorChooserViewControllerDefaultCellHeight = 380.0f; 24 | 25 | 26 | @interface KTSecretColorChooserViewController ()< 27 | UICollectionViewDataSource, 28 | UICollectionViewDelegate 29 | > 30 | 31 | /** 32 | * Collection view which holds each color as a cell. 33 | */ 34 | @property (nonatomic, strong) UICollectionView *collectionView; 35 | 36 | /** 37 | * Normal layout: each cell is wide as the screen bounds' width. 38 | */ 39 | @property (nonatomic, strong) UICollectionViewFlowLayout *defaultLayout; 40 | 41 | /** 42 | * Compressed layout: this is what makes the "rainbow" view. All cells resized to fit on the screen bounds' width. 43 | */ 44 | @property (nonatomic, strong) UICollectionViewFlowLayout *paletteLayout; 45 | 46 | /** 47 | * Long Press gesture recognizer toggles between the two layout modes. 48 | */ 49 | @property (nonatomic, strong) UILongPressGestureRecognizer *longPressGestureRecognizer; 50 | 51 | /** 52 | * Gesture recognizers for vertical swipes. Mainly for passing through to delegate. 53 | */ 54 | @property (nonatomic, strong) UISwipeGestureRecognizer *swipeUpGestureRecognizer; 55 | @property (nonatomic, strong) UISwipeGestureRecognizer *swipeDownGestureRecognizer; 56 | 57 | 58 | /** 59 | * The various cell sizes for each layout 60 | */ 61 | @property (nonatomic) CGSize defaultCellSize; 62 | @property (nonatomic) CGSize paletteCellSize; 63 | 64 | /** 65 | * The currently selected cell size 66 | */ 67 | @property (nonatomic) CGSize currentCellSize; 68 | 69 | /** 70 | * Tap gesture recognizer decides whether to propagate tap gestures to a delegate. 71 | */ 72 | @property (nonatomic, strong) UITapGestureRecognizer *tapGestureRecognizer; 73 | 74 | /** 75 | * Semi-transparent view that is displayed on a long press to indicate which color is being selected. 76 | */ 77 | @property (nonatomic, strong) UIView *hoverColorView; 78 | 79 | /** 80 | * NSDictionary of colors made available for selection 81 | */ 82 | @property (nonatomic, strong) NSDictionary *colorsDict; 83 | 84 | /** 85 | * Array of color names made available for selection 86 | */ 87 | @property (nonatomic, strong) NSDictionary *colorNamesDict; 88 | 89 | 90 | @end 91 | 92 | 93 | 94 | @implementation KTSecretColorChooserViewController 95 | 96 | #pragma mark - Public 97 | 98 | #pragma mark - View lifecycle 99 | 100 | - (void)viewDidLoad 101 | { 102 | [super viewDidLoad]; 103 | [self addSubviewTree]; 104 | [self constrainViews]; 105 | 106 | [self setUpGestureRecognizers]; 107 | 108 | self.currentCellSize = self.defaultCellSize; 109 | [self.collectionView reloadData]; 110 | 111 | } 112 | 113 | 114 | - (void)loadView 115 | { 116 | self.view = [self mainView]; 117 | } 118 | 119 | - (void)didReceiveMemoryWarning 120 | { 121 | [super didReceiveMemoryWarning]; 122 | // Dispose of any resources that can be recreated. 123 | } 124 | 125 | #pragma mark - Initialization 126 | 127 | - (void)setUpGestureRecognizers 128 | { 129 | UIView *collectionView = self.collectionView; 130 | [collectionView addGestureRecognizer:self.longPressGestureRecognizer]; 131 | [collectionView addGestureRecognizer:self.tapGestureRecognizer]; 132 | [collectionView addGestureRecognizer:self.swipeUpGestureRecognizer]; 133 | [collectionView addGestureRecognizer:self.swipeDownGestureRecognizer]; 134 | 135 | [self.swipeUpGestureRecognizer requireGestureRecognizerToFail:self.longPressGestureRecognizer]; 136 | [self.swipeDownGestureRecognizer requireGestureRecognizerToFail:self.longPressGestureRecognizer]; 137 | 138 | } 139 | 140 | - (UIView *)mainView 141 | { 142 | UIView *mainView = [UIView new]; 143 | mainView.translatesAutoresizingMaskIntoConstraints = NO; 144 | mainView.alpha = 0.9; 145 | mainView.clipsToBounds = YES; 146 | return mainView; 147 | } 148 | 149 | - (void)addSubviewTree 150 | { 151 | [self.view addSubview:self.collectionView]; 152 | [self.collectionView addSubview:self.hoverColorView]; 153 | } 154 | 155 | - (void)constrainViews 156 | { 157 | NSDictionary *viewsDict = @{@"collectionView":self.collectionView}; 158 | 159 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[collectionView]|" options:0 metrics:nil views:viewsDict]]; 160 | [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[collectionView]|" options:0 metrics:nil views:viewsDict]]; 161 | 162 | } 163 | 164 | #pragma mark - Private 165 | 166 | #pragma mark - Private properties 167 | 168 | - (UISwipeGestureRecognizer*) swipeUpGestureRecognizer 169 | { 170 | if (!_swipeUpGestureRecognizer) { 171 | _swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleUpSwipe:)]; 172 | _swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp; 173 | } 174 | return _swipeUpGestureRecognizer; 175 | } 176 | 177 | - (UISwipeGestureRecognizer*) swipeDownGestureRecognizer 178 | { 179 | if (!_swipeDownGestureRecognizer) { 180 | _swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleDownSwipe:)]; 181 | _swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown; 182 | } 183 | return _swipeDownGestureRecognizer; 184 | } 185 | 186 | 187 | - (UICollectionViewFlowLayout*) defaultLayout 188 | { 189 | if (!_defaultLayout){ 190 | _defaultLayout = [UICollectionViewFlowLayout new]; 191 | _defaultLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 192 | _defaultLayout.itemSize = self.defaultCellSize; 193 | _defaultLayout.minimumInteritemSpacing = 0.0f; 194 | _defaultLayout.minimumLineSpacing = 0.0f; 195 | } 196 | return _defaultLayout; 197 | } 198 | 199 | - (UICollectionViewFlowLayout*) paletteLayout 200 | { 201 | if (!_paletteLayout){ 202 | _paletteLayout = [UICollectionViewFlowLayout new]; 203 | _paletteLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 204 | _paletteLayout.itemSize = self.paletteCellSize; 205 | _paletteLayout.minimumInteritemSpacing = 0.0f; 206 | _paletteLayout.minimumLineSpacing = 0.0f; 207 | } 208 | return _paletteLayout; 209 | } 210 | 211 | - (UICollectionView*)collectionView 212 | { 213 | if (!_collectionView){ 214 | _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.defaultLayout]; 215 | _collectionView.translatesAutoresizingMaskIntoConstraints = NO; 216 | _collectionView.showsHorizontalScrollIndicator = NO; 217 | _collectionView.showsVerticalScrollIndicator = NO; 218 | _collectionView.clipsToBounds = YES; 219 | _collectionView.dataSource = self; 220 | _collectionView.delegate = self; 221 | _collectionView.pagingEnabled = YES; 222 | _collectionView.backgroundColor = [UIColor clearColor]; 223 | [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:kKTSecretColorChooserViewControllerCellIdentifier]; 224 | } 225 | return _collectionView; 226 | } 227 | 228 | - (NSDictionary*) colorsDict 229 | { 230 | if (!_colorsDict){ 231 | _colorsDict = @{ 232 | @(KTSecretDefaultColorWhite) : [UIColor whiteColor], 233 | @(KTSecretDefaultColorEmeraldSea) : [UIColor colorWithRed:18.0f/255.0f green:133.0f/255.0f blue:116.0/255.0f alpha:1.0], 234 | @(KTSecretDefaultColorHopscotch) : [UIColor colorWithRed:157.0f/255.0f green:105.0f/255.0f blue:183.0/255.0f alpha:1.0], 235 | @(KTSecretDefaultColorLavender) : [UIColor colorWithRed:100.0f/255.0f green:57.0f/255.0f blue:144.0/255.0f alpha:1.0], 236 | @(KTSecretDefaultColorBurst) : [UIColor colorWithRed:213.0f/255.0f green:100.0f/255.0f blue:12.0f/255.0f alpha:1.0], 237 | @(KTSecretDefaultColorCupid) : [UIColor colorWithRed:157.0f/255.0f green:30.0f/255.0f blue:38.0f/255.0f alpha:1.0], 238 | @(KTSecretDefaultColorPeony) : [UIColor colorWithRed:220.0f/255.0f green:72.0f/255.0f blue:99.0f/255.0f alpha:1.0], 239 | @(KTSecretDefaultColorMidnight) : [UIColor colorWithRed:39.0f/255.0f green:36.0f/255.0f blue:32.0f/255.0f alpha:1.0] 240 | }; 241 | } 242 | return _colorsDict; 243 | } 244 | 245 | - (NSDictionary*) colorNamesDict 246 | { 247 | if (!_colorNamesDict){ 248 | _colorNamesDict = @{ 249 | @(KTSecretDefaultColorEmeraldSea) : NSLocalizedString(@"Emerald Sea", nil), 250 | @(KTSecretDefaultColorHopscotch) : NSLocalizedString(@"Hopscotch", nil), 251 | @(KTSecretDefaultColorLavender) : NSLocalizedString(@"Lavender", nil), 252 | @(KTSecretDefaultColorBurst) : NSLocalizedString(@"Burst", nil), 253 | @(KTSecretDefaultColorCupid) : NSLocalizedString(@"Cupid", nil), 254 | @(KTSecretDefaultColorPeony) : NSLocalizedString(@"Peony", nil), 255 | @(KTSecretDefaultColorMidnight) : NSLocalizedString(@"Midnight", nil), 256 | @(KTSecretDefaultColorWhite) : NSLocalizedString(@"Default", nil) 257 | }; 258 | } 259 | return _colorNamesDict; 260 | } 261 | 262 | - (UILongPressGestureRecognizer*) longPressGestureRecognizer 263 | { 264 | if (!_longPressGestureRecognizer) { 265 | _longPressGestureRecognizer = [UILongPressGestureRecognizer new]; 266 | [_longPressGestureRecognizer addTarget:self action:@selector(handleLongPressGesture:)]; 267 | } 268 | return _longPressGestureRecognizer; 269 | } 270 | 271 | - (UITapGestureRecognizer*) tapGestureRecognizer 272 | { 273 | if (!_tapGestureRecognizer) { 274 | _tapGestureRecognizer = [UITapGestureRecognizer new]; 275 | [_tapGestureRecognizer addTarget:self action:@selector(handleTapGesture:)]; 276 | } 277 | return _tapGestureRecognizer; 278 | } 279 | 280 | - (CGSize) defaultCellSize 281 | { 282 | return CGSizeMake([[UIScreen mainScreen] bounds].size.width, kKTSecretColorChooserViewControllerDefaultCellHeight); 283 | } 284 | 285 | - (CGSize) paletteCellSize 286 | { 287 | return CGSizeMake(([[UIScreen mainScreen] bounds].size.width)/[self.colorsDict count], kKTSecretColorChooserViewControllerDefaultCellHeight); 288 | } 289 | 290 | - (UIView*)hoverColorView 291 | { 292 | if (!_hoverColorView) { 293 | _hoverColorView = [UIView new]; 294 | 295 | float screenWidth = [[UIScreen mainScreen] bounds].size.width; 296 | float hoverViewWidth = screenWidth/[self.colorsDict count]; 297 | 298 | _hoverColorView.frame = CGRectMake(0, 0, hoverViewWidth, self.view.frame.size.height); 299 | _hoverColorView.backgroundColor = [UIColor lightTextColor]; 300 | _hoverColorView.alpha = 0.4; 301 | _hoverColorView.hidden = YES; 302 | } 303 | return _hoverColorView; 304 | } 305 | 306 | 307 | #pragma mark - Initialization helpers 308 | 309 | #pragma mark - Event handlers 310 | 311 | - (void)handleLongPressGesture:(UILongPressGestureRecognizer*)sender 312 | { 313 | if (sender.state == UIGestureRecognizerStateEnded) { 314 | [self handleLongPressEnded:sender]; 315 | 316 | }else if (sender.state == UIGestureRecognizerStateChanged) { 317 | [self handleLongPressMoved:sender]; 318 | 319 | }else { 320 | [self handleLongPressStarted:sender]; 321 | } 322 | } 323 | 324 | - (void)handleTapGesture:(UITapGestureRecognizer*)sender 325 | { 326 | // [self.delegate sec 327 | } 328 | 329 | #pragma mark - Long Press Activated handlers 330 | 331 | - (void)handleLongPressEnded:(UILongPressGestureRecognizer*)sender 332 | { 333 | self.currentCellSize = self.defaultCellSize; 334 | 335 | // find the selected color 336 | CGPoint locationInView = [sender locationInView:self.collectionView]; 337 | NSIndexPath *selectedCellIndexPath = [self.collectionView indexPathForItemAtPoint:locationInView]; 338 | UIColor *selectedColor = self.colorsDict[@(selectedCellIndexPath.item)]; 339 | 340 | // change to default layout 341 | CGFloat selectedCellRectX = self.currentCellSize.width*selectedCellIndexPath.item+1; 342 | self.hoverColorView.hidden = YES; 343 | [self.collectionView setCollectionViewLayout:self.defaultLayout animated:YES]; 344 | [self.collectionView scrollRectToVisible:CGRectMake(selectedCellRectX, 0, [[UIScreen mainScreen] bounds].size.width, 20.0f) animated:NO]; 345 | 346 | // update delegate on selected color 347 | NSString *colorName = self.colorNamesDict[@(selectedCellIndexPath.item)]; 348 | [self updateDelegateSelectedColor:selectedColor name:colorName]; 349 | } 350 | 351 | - (void)handleLongPressStarted:(UILongPressGestureRecognizer*)sender 352 | { 353 | // change to palette layout 354 | [self.collectionView setCollectionViewLayout:self.paletteLayout animated:YES]; 355 | } 356 | 357 | - (void)handleLongPressMoved:(UILongPressGestureRecognizer*)sender 358 | { 359 | // find the cell at touch point 360 | CGPoint locationInView = [sender locationInView:self.collectionView]; 361 | NSIndexPath *hoverCellIndexPath = [self.collectionView indexPathForItemAtPoint:locationInView]; 362 | UICollectionViewCell *colorCell = [self.collectionView cellForItemAtIndexPath:hoverCellIndexPath]; 363 | 364 | // move hover view over cell at touch point 365 | self.hoverColorView.frame = colorCell.frame; 366 | self.hoverColorView.hidden = NO; 367 | 368 | } 369 | 370 | #pragma mark - UIScrollViewDelegate methods 371 | 372 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 373 | { 374 | // find the cell at touch point 375 | UICollectionViewCell *cell = [[self.collectionView visibleCells] firstObject]; 376 | NSIndexPath *cellIndexPath = [self.collectionView indexPathForCell:cell]; 377 | 378 | // use index to find color 379 | UIColor *selectedColor = self.colorsDict[@(cellIndexPath.item)]; 380 | 381 | // update delegate on selected color 382 | NSString *colorName = self.colorNamesDict[@(cellIndexPath.item)]; 383 | [self updateDelegateSelectedColor:selectedColor name:colorName]; 384 | } 385 | 386 | #pragma mark - UICollectionViewDataSource methods 387 | 388 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView*)collectionView { 389 | return 1; 390 | } 391 | 392 | - (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section { 393 | return [self.colorsDict count]; 394 | } 395 | 396 | -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 397 | { 398 | UICollectionViewCell *cell = (UICollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:kKTSecretColorChooserViewControllerCellIdentifier forIndexPath:indexPath]; 399 | cell.backgroundColor = self.colorsDict[@(indexPath.item)]; 400 | 401 | 402 | return cell; 403 | } 404 | 405 | #pragma mark - Long Press Ended helper 406 | 407 | - (void)updateDelegateSelectedColor:(UIColor*)color name:(NSString*)name 408 | { 409 | if ([self.delegate respondsToSelector:@selector(secretColorChooserViewController:didSelectColor:name:)]) { 410 | 411 | [self.delegate secretColorChooserViewController:self didSelectColor:color name:name]; 412 | } 413 | } 414 | 415 | 416 | #pragma mark - UISwipeGestureRecognizer delegate methods 417 | 418 | - (void)handleUpSwipe:(UISwipeGestureRecognizer*)gestureRecognizer 419 | { 420 | if ([self.delegate respondsToSelector:@selector(secretColorChooserViewController:didSwipeUp:)]) { 421 | [self.delegate secretColorChooserViewController:self didSwipeUp:YES]; 422 | } 423 | } 424 | 425 | - (void)handleDownSwipe:(UISwipeGestureRecognizer*)gestureRecognizer 426 | { 427 | if ([self.delegate respondsToSelector:@selector(secretColorChooserViewController:didSwipeDown:)]) { 428 | [self.delegate secretColorChooserViewController:self didSwipeDown:YES]; 429 | } 430 | } 431 | 432 | 433 | @end 434 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods/Pods-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## KTSecretTextView 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | 25 | ## Reveal-iOS-SDK 26 | 27 | # REVEAL LICENSE AGREEMENT v1.1 28 | 29 | ## NOTICE TO USER: 30 | 31 | This is a legally enforceable agreement between you (__"you"__ or __"yours"__ and other grammatical equivalents) and Itty Bitty Apps Pty Ltd. (__"the Company"__), which covers your use of the Reveal software product that accompanies this Agreement and related software components, which may include associated media, printed materials, and "online" or electronic documentation. All such software and materials are referred to herein as the __"Software"__ or __"the Reveal Software"__. If you do not agree to the terms of this License Agreement, then do not install or use the Software. By explicitly accepting this License Agreement, or by installing, copying, downloading, accessing, or otherwise using the Software, you are acknowledging and agreeing to be bound by the following terms: 32 | 33 | ## 1. DEFINITIONS 34 | 35 | __(a) "Software"__ shall mean the Reveal software including any Updates thereto, in object and source form, and the media and Documentation provided by the Company to you and for which you are granted a license pursuant to this Agreement. 36 | 37 | __(b) "Documentation"__ shall mean the printed or online written reference material furnished to you in conjunction with the Software, including, without limitation, instructions, guidelines, and end user guides. 38 | 39 | __(c) "Intellectual Property Rights"__ shall mean all intellectual property rights, including, without limitation, patent, copyright, trademark, and trade secret. 40 | 41 | __(d) "Updates"__ shall mean a modification, error correction, bug fix, new release, or other update to or for the Software. 42 | 43 | 44 | ## 2. LICENSE GRANT 45 | 46 | The Company may, at its sole discretion, grant you a Trial License, a Personal License, an Educational License, a Commercial Seat License, a Site License or an Enterprise License. 47 | 48 | If you have not purchased or otherwise rightfully obtained a Personal License, an Educational License, a Commercial Seat License, a Site License or an Enterprise License for the Reveal Software, the Trial License Terms (2.1) are applicable to your use of the Reveal Software. The Trial License Terms are also applicable to any usage of the Reveal Software by you that is not covered under any other licenses you may have. 49 | 50 | The Personal License Terms (2.2) apply if you have a Personal License. The Commercial Seat License Terms (2.3) apply if you have a Commercial Seat License. The Educational License Terms (2.4) apply if you have an Educational License. The Site License Terms (2.5) apply if you have a Site License. The Enterprise License Terms (2.6) apply if you have an Enterprise License. 51 | 52 | The General Terms (3) apply in all cases. 53 | 54 | ### 2.1 TRIAL LICENSE TERMS 55 | 56 | The Company grants you a non-exclusive license to use the Software for time-limited evaluation purposes, only in accordance with the terms and conditions set forth herein. The Software may be used for a period of 30 calendar days from the first time you run the Software. Upon lapse of such trial period all of or part of the functionality of the Software will be disabled automatically. 57 | 58 | If you wish to use the Software after the trial period, you must purchase a Personal License, a Commercial Seat License, an Educational License, a Site License or an Enterprise License. The Company may extend to you an expiring license key, in which event such a license key will be considered a means to extend the trial period under the Trial License Terms. 59 | 60 | 61 | ### 2.2 PERSONAL LICENSE TERMS 62 | 63 | The Company grants you a non-exclusive license to use the Software, only in accordance with the terms and conditions set forth herein. This License grants you the right to activate and use the Software on no more than 2 computers primarily used by you. Use of the Software under this license may be for both commercial and non-commercial purposes. Personal licences are not available to companies, commercial institutions, government agencies or business entities. 64 | 65 | 66 | ### 2.3 COMMERCIAL SEAT LICENSE TERMS 67 | 68 | The Company grants you a non-exclusive license to use the Software, only in accordance with the terms and conditions set forth herein. This License is only available to companies, commercial institutions, government agencies and business entities. 69 | 70 | This License does not allow the Software to be activated and used on computers that are not either a) owned by you, b) owned by any fully owned subsidiary of yours, c) owned by or operated primarily by your employees or employees of any fully owned subsidiary of yours. A Commercial Seat License must be purchased for every person employed by you or employed by any fully owned subsidiary of yours wishing to use the Software. 71 | 72 | This license is granted exclusively on a per-employee basis within your organisation and is not transferable to another current employee without written permission. 73 | 74 | This License does not allow the use of the Software other than for business purposes of your company. If entering into a Commercial Seat License you personally warrant that you have full legal authority to enter into this agreement on behalf of your employer. 75 | 76 | 77 | ### 2.4 EDUCATIONAL LICENSE TERMS 78 | 79 | The Company grants you a non-exclusive license to use the Software, only in accordance with the terms and conditions set forth herein. This License grants you the right to activate and use the Software on no more than 2 computers primarily used by you. 80 | 81 | Educational Licenses are available only to individual students and teaching staff. Use of the Software under this license must be for non-commercial purposes only, including education and research. 82 | 83 | 84 | ### 2.5 SITE LICENSE TERMS 85 | 86 | The Company grants you a non-exclusive license to use the Software, only in accordance with the terms and conditions set forth herein. This License is only available to companies, commercial institutions, government agencies and business entities. 87 | 88 | This License does not allow the Software to be activated and used on computers that are not either a) owned by you, b) owned by any fully owned subsidiary of yours, c) owned by or operated primarily by your employees or employees of any fully owned subsidiary of yours. 89 | 90 | Unless otherwise specified, any Site License you acquire from the Company is valid only for use at the business locations listed on your sales invoice. 91 | 92 | This License does not allow the use of the Software other than for business purposes of your company. If entering into a Site License you personally warrant that you have full legal authority to enter into this agreement on behalf of your employer. 93 | 94 | 95 | ### 2.6 ENTERPRISE LICENSE TERMS 96 | 97 | The Company grants you a non-exclusive license to use the Software, only in accordance with the terms and conditions set forth herein. This License is only available to companies, commercial institutions, government agencies and business entities. 98 | 99 | This License does not allow the Software to be activated and used on computers that are not either a) owned by you, b) owned by any fully owned subsidiary of yours, c) owned by or operated primarily by your employees or employees of any fully owned subsidiary of yours. 100 | 101 | This License allows global use of the Software by all employees or employees of any fully owned subsidiary of the company, commercial institution, government agency or business entity listed in your sales invoice. 102 | 103 | This License does not allow the use of the Software other than for business purposes of your company. If entering into an Enterprise License you personally warrant that you have full legal authority to enter into this agreement on behalf of your employer. 104 | 105 | 106 | ## 3. GENERAL TERMS 107 | 108 | ### 3.1 TITLE 109 | 110 | ‘REVEAL’™ and ‘ITTY BITTY APPS’™ represent proprietary common law trademarks owned by the Company and must not be used without written permission. 111 | 112 | The Company shall own and retain all right, title and interest in and to all Intellectual Property Rights related to the Software, the Documentation and all improvements to any of them however so created. You do not acquire any other rights, express or implied, in the Software. ALL RIGHTS NOT EXPRESSLY GRANTED HEREUNDER ARE RESERVED TO THE COMPANY. 113 | 114 | ### 3.2 ARCHIVAL OR BACKUP COPIES 115 | 116 | You may copy the Software for backup and archival purposes only, provided that the original and each copy is kept in your possession and that your installation and use of the Software does not exceed that allowed in the "License Grant" section above. 117 | 118 | ### 3.3 THINGS YOU MUST NOT DO 119 | 120 | The Software and Documentation are protected by Australian and international copyright law. You must treat the Software and Documentation like any other copyrighted material—for example, a book. You may not: 121 | 122 | * copy the Documentation, 123 | * copy the Software except to make archival or backup copies as provided above, 124 | * modify or adapt the Software or merge it into another program, 125 | * reverse engineer, disassemble, decompile or make any attempt to discover the source code of the Software, 126 | * place the Software onto a server so that it is accessible via a public network such as the Internet, or 127 | * sublicense, rent, lease, sublicense or lend any portion of the Software or Documentation. 128 | 129 | ### 3.4 LIMITATION OF LICENSE VALIDITY 130 | 131 | Any License to use the Software granted to you under this License Agreement is limited to the current major release of the Software exclusively. The Company will at its sole discretion decide when a version of the Software will be considered a new major release. The Company reserves the right to change the terms of this agreement in any future major or minor release of the software. 132 | 133 | ### 3.5 ADDITIONAL SERVICES 134 | 135 | Fees may apply for additional services and products offered by the company and others, such as services that integrate with the Software or extend the functionality of the Software. 136 | 137 | ### 3.6 TECHNICAL AND RELATED INFORMATION 138 | 139 | The Company and its subsidiaries may collect and use technical and related information, such as technical information concerning your computer, system and application software. The Company does not collect (a) any information that identifies your work, (b) any file names or file contents of anything you work on using the Software. The Company and its subsidiaries are free to use the collected information in any form that does not personally identify you. 140 | 141 | ### 3.7 PRIVACY 142 | 143 | The Company will not sell or in any way license usage of your personal information to third parties. The Company will make reasonable efforts to keep your personal information secure. 144 | 145 | ### 3.8 TRANSFERS 146 | 147 | With prior notice to the Company, you may transfer all your rights to use the Software and Documentation only once and permanently to another person or legal entity provided you transfer this License Agreement, the Software and Documentation, including all copies, updates and prior versions to such person or entity and that you retain no copies, including copies stored on computer. The receiving person or legal entity must satisfy the conditions of the applicable license terms set out in section 2. 148 | 149 | ### 3.9 LIMITED WARRANTY 150 | 151 | We warrant that for a period of 14 days after delivery of this copy of the Software to you the Software will perform in substantial accordance with the Documentation. 152 | 153 | To the extent permitted by applicable law, THE FOREGOING LIMITED WARRANTY IS IN LIEU OF ALL OTHER WARRANTIES OR CONDITIONS, EXPRESS OR IMPLIED, AND WE DISCLAIM ANY AND ALL IMPLIED WARRANTIES OR CONDITIONS, INCLUDING ANY IMPLIED WARRANTY OF TITLE, NONINFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, regardless of whether we know or had reason to know of your particular needs. No employee, agent, dealer or distributor of ours is authorized to modify this limited warranty, nor to make any additional warranties. 154 | SOME STATES DO NOT ALLOW THE LIMITATION OR EXCLUSION OF LIABILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATION MAY NOT APPLY TO YOU. 155 | 156 | ### 3.10 LIMITED REMEDY 157 | 158 | Our entire liability and your exclusive remedy for breach of the foregoing warranty shall be, at our option, to return the price you paid minus fees incurred to transfer those funds to you. 159 | 160 | IN NO EVENT WILL WE BE LIABLE TO YOU FOR ANY DIRECT OR INDIRECT DAMAGES, INCLUDING ANY LOST PROFITS, LOST SAVINGS, OR OTHER INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING FROM THE USE OR THE INABILITY TO USE THE SOFTWARE (EVEN IF WE OR AN AUTHORIZED DEALER OR DISTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF THESE DAMAGES), OR FOR ANY CLAIM BY ANY OTHER PARTY. 161 | SOME STATES DO NOT ALLOW THE LIMITATION OR EXCLUSION OF LIABILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATION MAY NOT APPLY TO YOU. 162 | 163 | ### 3.11 TERM AND TERMINATION 164 | 165 | This license agreement takes effect upon your use of the software and remains effective until terminated. You may terminate it at any time by destroying all copies of the Software and Documentation in your possession. It will also automatically terminate if you fail to comply with any term or condition of this license agreement. You hereby agree that on termination of this license to permanently destroy all copies of the Software and Documentation in your possession. 166 | 167 | ### 3.12 CONFIDENTIALITY 168 | 169 | The Software contains trade secrets and proprietary know-how that belong to the Company and it is being made available to you in strict confidence. ANY USE OR DISCLOSURE OF THE SOFTWARE, OR OF ITS ALGORITHMS, PROTOCOLS OR INTERFACES, OTHER THAN IN STRICT ACCORDANCE WITH THIS LICENSE AGREEMENT, MAY BE ACTIONABLE AS A VIOLATION OF THE COMPANY'S TRADE SECRET RIGHTS. 170 | 171 | ### 3.13 GENERAL PROVISIONS 172 | 173 | __3.13.1__ This written license agreement is the exclusive agreement between you and the Company concerning the Software and Documentation and supersedes any prior purchase order, communication, advertising or representation concerning the Software. 174 | 175 | __3.13.2__ This is the entire agreement between the parties relating to the subject matter hereof and all other terms are rejected. No waiver or modification of this Agreement shall be valid unless in writing signed by each party. The waiver of a breach of any term hereof shall in no way be construed as a waiver of any term or other breach hereof. If any provision of this Agreement is held by a court of competent jurisdiction to be contrary to law the remaining provisions of this Agreement shall remain in full force and effect. 176 | 177 | __3.13.3__ In the event of litigation between you and the Company concerning the Software or Documentation, the prevailing party in the litigation will be entitled to recover attorney fees and expenses from the other party. 178 | 179 | __3.13.4__ This Agreement, and all disputes arising out of or related thereto, shall be governed by and construed under the laws of the State of Victoria, Australia, without reference to conflict of laws principles. All such disputes shall be subject to the exclusive jurisdiction of the state and federal courts located in Australia, and the parties agree and submit to the personal and exclusive jurisdiction and venue of these courts. 180 | 181 | 182 | ## 4. CONTACT INFORMATION 183 | 184 | If you have any questions about this License Agreement, or if you want to contact the Company for any reason, please direct all mail correspondence to: Itty Bitty Apps Pty. Ltd. Level 2, 27 Hardware Lane, Melbourne, Victoria, Australia, 3000, or electronic correspondence to info@ittybittyapps.com. 185 | 186 | Do you agree to be bound by the terms of this agreement? 187 | 188 | 189 | ## UIImage-Resize 190 | 191 | Without any further information, all the sources provided here are under the MIT License 192 | quoted below. 193 | 194 | Anyway, please contact me by email (olivier.halligon+ae@gmail.com) if you plan to use my work and the provided classes 195 | in your own software. Thanks. 196 | 197 | 198 | /*********************************************************************************** 199 | * 200 | * Copyright (c) 2010 Olivier Halligon 201 | * 202 | * Permission is hereby granted, free of charge, to any person obtaining a copy 203 | * of this software and associated documentation files (the "Software"), to deal 204 | * in the Software without restriction, including without limitation the rights 205 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 206 | * copies of the Software, and to permit persons to whom the Software is 207 | * furnished to do so, subject to the following conditions: 208 | * 209 | * The above copyright notice and this permission notice shall be included in 210 | * all copies or substantial portions of the Software. 211 | * 212 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 213 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 214 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 215 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 216 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 217 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 218 | * THE SOFTWARE. 219 | * 220 | *********************************************************************************** 221 | * 222 | * Any comment or suggestion welcome. Referencing this project in your AboutBox is appreciated. 223 | * Please tell me if you use this class so we can cross-reference our projects. 224 | * 225 | ***********************************************************************************/ 226 | 227 | Generated by CocoaPods - http://cocoapods.org 228 | --------------------------------------------------------------------------------