├── .gitignore ├── .travis.yml ├── Example ├── .swift-version ├── JHColorPickerController.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── JHColorPickerController-Example.xcscheme ├── JHColorPickerController.xcworkspace │ └── contents.xcworkspacedata ├── JHColorPickerController │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ └── ViewController.swift ├── Podfile └── Podfile.lock ├── JHColorPicker-Demo.gif ├── JHColorPicker.podspec ├── LICENSE ├── Pod ├── Assets │ ├── .gitkeep │ ├── InfColorPickerView.xib │ ├── JHColorPickerController.xib │ ├── SwatchCell.xib │ ├── brightness_icon.png │ ├── brightness_icon@2x.png │ ├── brightness_icon@3x.png │ ├── brightness_icon_dark.png │ ├── brightness_icon_dark@2x.png │ └── brightness_icon_dark@3x.png └── Classes │ ├── .gitkeep │ ├── ColorLibraries.swift │ ├── InfColorBarPicker.h │ ├── InfColorBarPicker.m │ ├── InfColorIndicatorView.h │ ├── InfColorIndicatorView.m │ ├── InfColorPicker.h │ ├── InfColorPickerController.h │ ├── InfColorPickerController.m │ ├── InfColorPickerNavigationController.h │ ├── InfColorPickerNavigationController.m │ ├── InfColorSquarePicker.h │ ├── InfColorSquarePicker.m │ ├── InfHSBSupport.h │ ├── InfHSBSupport.m │ ├── InfSourceColorView.h │ ├── InfSourceColorView.m │ ├── JHColorPickerController.swift │ └── UIColorExtension.swift ├── README.md └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | Carthage 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 29 | # 30 | # Note: if you ignore the Pods directory, make sure to uncomment 31 | # `pod install` in .travis.yml 32 | # 33 | # Pods/ 34 | 35 | Example/Pods/ 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * http://www.objc.io/issue-6/travis-ci.html 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | language: objective-c 6 | # cache: cocoapods 7 | # podfile: Example/Podfile 8 | # before_install: 9 | # - gem install cocoapods # Since Travis is not always on latest version 10 | # - pod install --project-directory=Example 11 | install: 12 | - gem install xcpretty --no-rdoc --no-ri --no-document --quiet 13 | script: 14 | - set -o pipefail && xcodebuild test -workspace Example/JHColorPickerController.xcworkspace -scheme JHColorPickerController-Example -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO | xcpretty -c 15 | - pod lib lint --quick 16 | -------------------------------------------------------------------------------- /Example/.swift-version: -------------------------------------------------------------------------------- 1 | 2.3 2 | -------------------------------------------------------------------------------- /Example/JHColorPickerController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 11 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; 12 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 13 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 14 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 15 | 777EB9568BC78496596635AB /* Pods_JHColorPickerController_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0892FD4DA19DF4DEE10EA11B /* Pods_JHColorPickerController_Example.framework */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 0892FD4DA19DF4DEE10EA11B /* Pods_JHColorPickerController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_JHColorPickerController_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 4CEA6D221B8F340BA37C5CE2 /* Pods-JHColorPickerController_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JHColorPickerController_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-JHColorPickerController_Example/Pods-JHColorPickerController_Example.release.xcconfig"; sourceTree = ""; }; 21 | 607FACD01AFB9204008FA782 /* JHColorPickerController_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JHColorPickerController_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 23 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 24 | 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 25 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 27 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 28 | 6F554356E860386C3769F0A2 /* JHColorPickerController.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = JHColorPickerController.podspec; path = ../JHColorPickerController.podspec; sourceTree = ""; }; 29 | B3DCCC2838B34C7CC082B207 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 30 | D0677416471FBC0011515E6B /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 31 | EB36778DC773002ED4B028EA /* Pods-JHColorPickerController_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JHColorPickerController_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-JHColorPickerController_Example/Pods-JHColorPickerController_Example.debug.xcconfig"; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | 777EB9568BC78496596635AB /* Pods_JHColorPickerController_Example.framework in Frameworks */, 40 | ); 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXFrameworksBuildPhase section */ 44 | 45 | /* Begin PBXGroup section */ 46 | 607FACC71AFB9204008FA782 = { 47 | isa = PBXGroup; 48 | children = ( 49 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 50 | 607FACD21AFB9204008FA782 /* Example for JHColorPickerController */, 51 | 607FACD11AFB9204008FA782 /* Products */, 52 | E4AFB50F18D0A9A716543B67 /* Pods */, 53 | 786802F9FE93402601F1AC0E /* Frameworks */, 54 | ); 55 | sourceTree = ""; 56 | }; 57 | 607FACD11AFB9204008FA782 /* Products */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 607FACD01AFB9204008FA782 /* JHColorPickerController_Example.app */, 61 | ); 62 | name = Products; 63 | sourceTree = ""; 64 | }; 65 | 607FACD21AFB9204008FA782 /* Example for JHColorPickerController */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 69 | 607FACD71AFB9204008FA782 /* ViewController.swift */, 70 | 607FACD91AFB9204008FA782 /* Main.storyboard */, 71 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 72 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 73 | 607FACD31AFB9204008FA782 /* Supporting Files */, 74 | ); 75 | name = "Example for JHColorPickerController"; 76 | path = JHColorPickerController; 77 | sourceTree = ""; 78 | }; 79 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 607FACD41AFB9204008FA782 /* Info.plist */, 83 | ); 84 | name = "Supporting Files"; 85 | sourceTree = ""; 86 | }; 87 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 6F554356E860386C3769F0A2 /* JHColorPickerController.podspec */, 91 | B3DCCC2838B34C7CC082B207 /* README.md */, 92 | D0677416471FBC0011515E6B /* LICENSE */, 93 | ); 94 | name = "Podspec Metadata"; 95 | sourceTree = ""; 96 | }; 97 | 786802F9FE93402601F1AC0E /* Frameworks */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 0892FD4DA19DF4DEE10EA11B /* Pods_JHColorPickerController_Example.framework */, 101 | ); 102 | name = Frameworks; 103 | sourceTree = ""; 104 | }; 105 | E4AFB50F18D0A9A716543B67 /* Pods */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | EB36778DC773002ED4B028EA /* Pods-JHColorPickerController_Example.debug.xcconfig */, 109 | 4CEA6D221B8F340BA37C5CE2 /* Pods-JHColorPickerController_Example.release.xcconfig */, 110 | ); 111 | name = Pods; 112 | sourceTree = ""; 113 | }; 114 | /* End PBXGroup section */ 115 | 116 | /* Begin PBXNativeTarget section */ 117 | 607FACCF1AFB9204008FA782 /* JHColorPickerController_Example */ = { 118 | isa = PBXNativeTarget; 119 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "JHColorPickerController_Example" */; 120 | buildPhases = ( 121 | 2F21E665904797EB46494D72 /* [CP] Check Pods Manifest.lock */, 122 | 607FACCC1AFB9204008FA782 /* Sources */, 123 | 607FACCD1AFB9204008FA782 /* Frameworks */, 124 | 607FACCE1AFB9204008FA782 /* Resources */, 125 | 9DEC6BEBBE3B41B7768065E5 /* [CP] Embed Pods Frameworks */, 126 | B4299CEB9417C82326E6D793 /* [CP] Copy Pods Resources */, 127 | ); 128 | buildRules = ( 129 | ); 130 | dependencies = ( 131 | ); 132 | name = JHColorPickerController_Example; 133 | productName = JHColorPickerController; 134 | productReference = 607FACD01AFB9204008FA782 /* JHColorPickerController_Example.app */; 135 | productType = "com.apple.product-type.application"; 136 | }; 137 | /* End PBXNativeTarget section */ 138 | 139 | /* Begin PBXProject section */ 140 | 607FACC81AFB9204008FA782 /* Project object */ = { 141 | isa = PBXProject; 142 | attributes = { 143 | LastSwiftUpdateCheck = 0700; 144 | LastUpgradeCheck = 0800; 145 | ORGANIZATIONNAME = CocoaPods; 146 | TargetAttributes = { 147 | 607FACCF1AFB9204008FA782 = { 148 | CreatedOnToolsVersion = 6.3.1; 149 | LastSwiftMigration = 0800; 150 | }; 151 | }; 152 | }; 153 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "JHColorPickerController" */; 154 | compatibilityVersion = "Xcode 3.2"; 155 | developmentRegion = English; 156 | hasScannedForEncodings = 0; 157 | knownRegions = ( 158 | en, 159 | Base, 160 | ); 161 | mainGroup = 607FACC71AFB9204008FA782; 162 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 163 | projectDirPath = ""; 164 | projectRoot = ""; 165 | targets = ( 166 | 607FACCF1AFB9204008FA782 /* JHColorPickerController_Example */, 167 | ); 168 | }; 169 | /* End PBXProject section */ 170 | 171 | /* Begin PBXResourcesBuildPhase section */ 172 | 607FACCE1AFB9204008FA782 /* Resources */ = { 173 | isa = PBXResourcesBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, 177 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 178 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 179 | ); 180 | runOnlyForDeploymentPostprocessing = 0; 181 | }; 182 | /* End PBXResourcesBuildPhase section */ 183 | 184 | /* Begin PBXShellScriptBuildPhase section */ 185 | 2F21E665904797EB46494D72 /* [CP] Check Pods Manifest.lock */ = { 186 | isa = PBXShellScriptBuildPhase; 187 | buildActionMask = 2147483647; 188 | files = ( 189 | ); 190 | inputPaths = ( 191 | ); 192 | name = "[CP] Check Pods Manifest.lock"; 193 | outputPaths = ( 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | shellPath = /bin/sh; 197 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 198 | showEnvVarsInLog = 0; 199 | }; 200 | 9DEC6BEBBE3B41B7768065E5 /* [CP] Embed Pods Frameworks */ = { 201 | isa = PBXShellScriptBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | ); 205 | inputPaths = ( 206 | ); 207 | name = "[CP] Embed Pods Frameworks"; 208 | outputPaths = ( 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | shellPath = /bin/sh; 212 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-JHColorPickerController_Example/Pods-JHColorPickerController_Example-frameworks.sh\"\n"; 213 | showEnvVarsInLog = 0; 214 | }; 215 | B4299CEB9417C82326E6D793 /* [CP] Copy Pods Resources */ = { 216 | isa = PBXShellScriptBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | ); 220 | inputPaths = ( 221 | ); 222 | name = "[CP] Copy Pods Resources"; 223 | outputPaths = ( 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | shellPath = /bin/sh; 227 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-JHColorPickerController_Example/Pods-JHColorPickerController_Example-resources.sh\"\n"; 228 | showEnvVarsInLog = 0; 229 | }; 230 | /* End PBXShellScriptBuildPhase section */ 231 | 232 | /* Begin PBXSourcesBuildPhase section */ 233 | 607FACCC1AFB9204008FA782 /* Sources */ = { 234 | isa = PBXSourcesBuildPhase; 235 | buildActionMask = 2147483647; 236 | files = ( 237 | 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, 238 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | }; 242 | /* End PBXSourcesBuildPhase section */ 243 | 244 | /* Begin PBXVariantGroup section */ 245 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = { 246 | isa = PBXVariantGroup; 247 | children = ( 248 | 607FACDA1AFB9204008FA782 /* Base */, 249 | ); 250 | name = Main.storyboard; 251 | sourceTree = ""; 252 | }; 253 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 254 | isa = PBXVariantGroup; 255 | children = ( 256 | 607FACDF1AFB9204008FA782 /* Base */, 257 | ); 258 | name = LaunchScreen.xib; 259 | sourceTree = ""; 260 | }; 261 | /* End PBXVariantGroup section */ 262 | 263 | /* Begin XCBuildConfiguration section */ 264 | 607FACED1AFB9204008FA782 /* Debug */ = { 265 | isa = XCBuildConfiguration; 266 | buildSettings = { 267 | ALWAYS_SEARCH_USER_PATHS = NO; 268 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 269 | CLANG_CXX_LIBRARY = "libc++"; 270 | CLANG_ENABLE_MODULES = YES; 271 | CLANG_ENABLE_OBJC_ARC = YES; 272 | CLANG_WARN_BOOL_CONVERSION = YES; 273 | CLANG_WARN_CONSTANT_CONVERSION = YES; 274 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 275 | CLANG_WARN_EMPTY_BODY = YES; 276 | CLANG_WARN_ENUM_CONVERSION = YES; 277 | CLANG_WARN_INFINITE_RECURSION = YES; 278 | CLANG_WARN_INT_CONVERSION = YES; 279 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 280 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 281 | CLANG_WARN_UNREACHABLE_CODE = YES; 282 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 283 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 284 | COPY_PHASE_STRIP = NO; 285 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 286 | ENABLE_STRICT_OBJC_MSGSEND = YES; 287 | ENABLE_TESTABILITY = YES; 288 | GCC_C_LANGUAGE_STANDARD = gnu99; 289 | GCC_DYNAMIC_NO_PIC = NO; 290 | GCC_NO_COMMON_BLOCKS = YES; 291 | GCC_OPTIMIZATION_LEVEL = 0; 292 | GCC_PREPROCESSOR_DEFINITIONS = ( 293 | "DEBUG=1", 294 | "$(inherited)", 295 | ); 296 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 297 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 298 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 299 | GCC_WARN_UNDECLARED_SELECTOR = YES; 300 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 301 | GCC_WARN_UNUSED_FUNCTION = YES; 302 | GCC_WARN_UNUSED_VARIABLE = YES; 303 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 304 | MTL_ENABLE_DEBUG_INFO = YES; 305 | ONLY_ACTIVE_ARCH = YES; 306 | SDKROOT = iphoneos; 307 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 308 | }; 309 | name = Debug; 310 | }; 311 | 607FACEE1AFB9204008FA782 /* Release */ = { 312 | isa = XCBuildConfiguration; 313 | buildSettings = { 314 | ALWAYS_SEARCH_USER_PATHS = NO; 315 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 316 | CLANG_CXX_LIBRARY = "libc++"; 317 | CLANG_ENABLE_MODULES = YES; 318 | CLANG_ENABLE_OBJC_ARC = YES; 319 | CLANG_WARN_BOOL_CONVERSION = YES; 320 | CLANG_WARN_CONSTANT_CONVERSION = YES; 321 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 322 | CLANG_WARN_EMPTY_BODY = YES; 323 | CLANG_WARN_ENUM_CONVERSION = YES; 324 | CLANG_WARN_INFINITE_RECURSION = YES; 325 | CLANG_WARN_INT_CONVERSION = YES; 326 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 327 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 328 | CLANG_WARN_UNREACHABLE_CODE = YES; 329 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 330 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 331 | COPY_PHASE_STRIP = NO; 332 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 333 | ENABLE_NS_ASSERTIONS = NO; 334 | ENABLE_STRICT_OBJC_MSGSEND = YES; 335 | GCC_C_LANGUAGE_STANDARD = gnu99; 336 | GCC_NO_COMMON_BLOCKS = YES; 337 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 338 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 339 | GCC_WARN_UNDECLARED_SELECTOR = YES; 340 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 341 | GCC_WARN_UNUSED_FUNCTION = YES; 342 | GCC_WARN_UNUSED_VARIABLE = YES; 343 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 344 | MTL_ENABLE_DEBUG_INFO = NO; 345 | SDKROOT = iphoneos; 346 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 347 | VALIDATE_PRODUCT = YES; 348 | }; 349 | name = Release; 350 | }; 351 | 607FACF01AFB9204008FA782 /* Debug */ = { 352 | isa = XCBuildConfiguration; 353 | baseConfigurationReference = EB36778DC773002ED4B028EA /* Pods-JHColorPickerController_Example.debug.xcconfig */; 354 | buildSettings = { 355 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 356 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 357 | CODE_SIGN_IDENTITY = "iPhone Developer"; 358 | DEVELOPMENT_TEAM = ""; 359 | INFOPLIST_FILE = JHColorPickerController/Info.plist; 360 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 361 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 362 | MODULE_NAME = ExampleApp; 363 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 364 | PRODUCT_NAME = "$(TARGET_NAME)"; 365 | SWIFT_OBJC_BRIDGING_HEADER = ""; 366 | SWIFT_VERSION = 2.3; 367 | }; 368 | name = Debug; 369 | }; 370 | 607FACF11AFB9204008FA782 /* Release */ = { 371 | isa = XCBuildConfiguration; 372 | baseConfigurationReference = 4CEA6D221B8F340BA37C5CE2 /* Pods-JHColorPickerController_Example.release.xcconfig */; 373 | buildSettings = { 374 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 375 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 376 | CODE_SIGN_IDENTITY = "iPhone Developer"; 377 | DEVELOPMENT_TEAM = ""; 378 | INFOPLIST_FILE = JHColorPickerController/Info.plist; 379 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 380 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 381 | MODULE_NAME = ExampleApp; 382 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 383 | PRODUCT_NAME = "$(TARGET_NAME)"; 384 | SWIFT_OBJC_BRIDGING_HEADER = ""; 385 | SWIFT_VERSION = 2.3; 386 | }; 387 | name = Release; 388 | }; 389 | /* End XCBuildConfiguration section */ 390 | 391 | /* Begin XCConfigurationList section */ 392 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "JHColorPickerController" */ = { 393 | isa = XCConfigurationList; 394 | buildConfigurations = ( 395 | 607FACED1AFB9204008FA782 /* Debug */, 396 | 607FACEE1AFB9204008FA782 /* Release */, 397 | ); 398 | defaultConfigurationIsVisible = 0; 399 | defaultConfigurationName = Release; 400 | }; 401 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "JHColorPickerController_Example" */ = { 402 | isa = XCConfigurationList; 403 | buildConfigurations = ( 404 | 607FACF01AFB9204008FA782 /* Debug */, 405 | 607FACF11AFB9204008FA782 /* Release */, 406 | ); 407 | defaultConfigurationIsVisible = 0; 408 | defaultConfigurationName = Release; 409 | }; 410 | /* End XCConfigurationList section */ 411 | }; 412 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 413 | } 414 | -------------------------------------------------------------------------------- /Example/JHColorPickerController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/JHColorPickerController.xcodeproj/xcshareddata/xcschemes/JHColorPickerController-Example.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 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Example/JHColorPickerController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/JHColorPickerController/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // JHColorPickerController 4 | // 5 | // Created by JHays on 07/09/2015. 6 | // Copyright (c) 2015 JHays. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // 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. 24 | // 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. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // 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. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Example/JHColorPickerController/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/JHColorPickerController/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Example/JHColorPickerController/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/JHColorPickerController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | UIInterfaceOrientationPortraitUpsideDown 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example/JHColorPickerController/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // JHColorPickerController 4 | // 5 | // Created by JHays on 07/09/2015. 6 | // Copyright (c) 2015 JHays. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JHColorPicker 11 | 12 | class ViewController: UIViewController, JHColorPickerControllerDelegate { 13 | 14 | @IBOutlet weak var changeColorBtn:UIButton! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | // Do any additional setup after loading the view, typically from a nib. 19 | changeColorBtn.layer.borderColor = UIColor.whiteColor().CGColor 20 | changeColorBtn.layer.borderWidth = 1.0 21 | changeColorBtn.layer.cornerRadius = 4.0 22 | } 23 | 24 | override func viewWillAppear(animated: Bool) { 25 | super.viewWillAppear(animated) 26 | 27 | if let color = view.backgroundColor { 28 | applyViewableTextColorForColor(color) 29 | } 30 | } 31 | 32 | override func didReceiveMemoryWarning() { 33 | super.didReceiveMemoryWarning() 34 | // Dispose of any resources that can be recreated. 35 | } 36 | 37 | 38 | @IBAction func changeColorBtnPressed(sender: AnyObject) { 39 | let colorPickerController = JHColorPickerController() 40 | colorPickerController.delegate = self 41 | colorPickerController.previousColor = self.view.backgroundColor 42 | colorPickerController.completion = { selectedColor in 43 | self.view.backgroundColor = selectedColor 44 | } 45 | self.presentViewController(UINavigationController(rootViewController: colorPickerController), animated: true, completion: nil) 46 | } 47 | 48 | func applyViewableTextColorForColor(color:UIColor) { 49 | 50 | var textColor = UIColor.blackColor() 51 | var shadowColor = UIColor.whiteColor() 52 | 53 | if !color.isLight() { 54 | textColor = UIColor.whiteColor() 55 | shadowColor = UIColor.blackColor() 56 | } 57 | 58 | changeColorBtn.setTitleColor(textColor, forState: .Normal) 59 | changeColorBtn.layer.borderColor = textColor.CGColor 60 | changeColorBtn.layer.shadowColor = shadowColor.CGColor 61 | changeColorBtn.layer.shadowOffset = CGSize(width: 0, height: 0) 62 | changeColorBtn.layer.shadowOpacity = 1.0 63 | changeColorBtn.layer.shadowRadius = 2 64 | 65 | } 66 | 67 | func colorSaved(color:UIColor, name:String?) { 68 | self.dismissViewControllerAnimated(true, completion: nil) 69 | } 70 | 71 | func colorSelected(color: UIColor, name: String?) { 72 | //useful if you are displaying in a popover and you want to use the color as they change it 73 | } 74 | 75 | func colorPickerCancelled() { 76 | self.dismissViewControllerAnimated(true, completion: nil) 77 | } 78 | } 79 | 80 | extension UIColor { 81 | 82 | func isLight() -> Bool 83 | { 84 | let components = CGColorGetComponents(self.CGColor) 85 | let comp0 = components[0] * 299 86 | let comp1 = components[1] * 587 87 | let comp2 = components[2] * 114 88 | let brightness = (comp0 + comp1 + comp2) / 1000 89 | 90 | if brightness < 0.5 { 91 | return false 92 | } 93 | else { 94 | return true 95 | } 96 | } 97 | 98 | } 99 | 100 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | use_frameworks! 3 | 4 | target 'JHColorPickerController_Example' do 5 | pod "JHColorPicker", :path => "../" 6 | end 7 | 8 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ChameleonFramework/Default (2.1.0) 3 | - ChameleonFramework/Swift (2.1.0): 4 | - ChameleonFramework/Default 5 | - ColorUtils (1.1.3) 6 | - JHColorPicker (1.1): 7 | - ChameleonFramework/Swift 8 | - ColorUtils 9 | - UIColor-Crayola 10 | - UIColor-Pantone 11 | - UIColor-Crayola (1.0) 12 | - UIColor-Pantone (1.0) 13 | 14 | DEPENDENCIES: 15 | - JHColorPicker (from `../`) 16 | 17 | EXTERNAL SOURCES: 18 | JHColorPicker: 19 | :path: ../ 20 | 21 | SPEC CHECKSUMS: 22 | ChameleonFramework: d21a3cc247abfe5e37609a283a8238b03575cf64 23 | ColorUtils: f99c501f9caf5374b35480a281168565a24bdb6d 24 | JHColorPicker: 70a20c94f3827170b17dc10742df7274e596feb3 25 | UIColor-Crayola: 0d2f68032cbea6ba4669b360ffb641d203b41a0d 26 | UIColor-Pantone: b6e5ab4c032f704f75453cfc0e8a07f68624cff5 27 | 28 | PODFILE CHECKSUM: 1b0364d48458be3ce3bca567d01eeee47e7094c7 29 | 30 | COCOAPODS: 1.1.0.rc.2 31 | -------------------------------------------------------------------------------- /JHColorPicker-Demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/JHColorPicker-Demo.gif -------------------------------------------------------------------------------- /JHColorPicker.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "JHColorPicker" 3 | s.version = "1.1" 4 | s.summary = "Color picker with several swatch libraries and custom color picker" 5 | s.description = <<-DESC 6 | JHColorPickerController is a color picker that includes swatches from Crayola, Pantone, and ChameleonFramework flat colors, as well as custom color picker 7 | DESC 8 | s.homepage = "https://github.com/jhays/JHColorPicker" 9 | s.screenshots = "http://i.imgur.com/egH6Thw.gif" 10 | s.license = 'MIT' 11 | s.author = { "JHays" => "orbosphere@gmail.com" } 12 | s.source = { :git => "https://github.com/jhays/JHColorPicker.git", :tag => s.version } 13 | 14 | s.platform = :ios, '8.0' 15 | s.requires_arc = true 16 | 17 | s.source_files = 'Pod/Classes/**/*' 18 | s.resource_bundles = { 19 | 'JHColorPicker' => ['Pod/Assets/*.png','Pod/Assets/*.xib'] 20 | } 21 | 22 | # s.public_header_files = 'Pod/Classes/**/*.h' 23 | s.frameworks = 'UIKit' 24 | s.dependency 'ChameleonFramework/Swift' 25 | s.dependency 'UIColor-Crayola' 26 | s.dependency 'UIColor-Pantone' 27 | s.dependency 'ColorUtils' 28 | end 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 JHays 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Pod/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/Pod/Assets/.gitkeep -------------------------------------------------------------------------------- /Pod/Assets/InfColorPickerView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /Pod/Assets/JHColorPickerController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 123 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 158 | 159 | 160 | 161 | 171 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 209 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | -------------------------------------------------------------------------------- /Pod/Assets/SwatchCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Pod/Assets/brightness_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/Pod/Assets/brightness_icon.png -------------------------------------------------------------------------------- /Pod/Assets/brightness_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/Pod/Assets/brightness_icon@2x.png -------------------------------------------------------------------------------- /Pod/Assets/brightness_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/Pod/Assets/brightness_icon@3x.png -------------------------------------------------------------------------------- /Pod/Assets/brightness_icon_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/Pod/Assets/brightness_icon_dark.png -------------------------------------------------------------------------------- /Pod/Assets/brightness_icon_dark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/Pod/Assets/brightness_icon_dark@2x.png -------------------------------------------------------------------------------- /Pod/Assets/brightness_icon_dark@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/Pod/Assets/brightness_icon_dark@3x.png -------------------------------------------------------------------------------- /Pod/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhays/JHColorPicker/dfcf43ef131b10bf455806a8684239372553d94c/Pod/Classes/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/InfColorBarPicker.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorBarPicker.h 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 8/9/10. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | @interface InfColorBarView : UIView 18 | 19 | @end 20 | 21 | //------------------------------------------------------------------------------ 22 | 23 | @interface InfColorBarPicker : UIControl 24 | 25 | @property (nonatomic) float value; 26 | 27 | @end 28 | 29 | //------------------------------------------------------------------------------ 30 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorBarPicker.m: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorBarPicker.m 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 8/9/10. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import "InfColorBarPicker.h" 14 | 15 | #import "InfColorIndicatorView.h" 16 | #import "InfHSBSupport.h" 17 | 18 | //------------------------------------------------------------------------------ 19 | 20 | #if !__has_feature(objc_arc) 21 | #error This file must be compiled with ARC enabled (-fobjc-arc). 22 | #endif 23 | 24 | //------------------------------------------------------------------------------ 25 | 26 | #define kContentInsetX 20 27 | 28 | //============================================================================== 29 | 30 | @implementation InfColorBarView 31 | 32 | //------------------------------------------------------------------------------ 33 | 34 | static CGImageRef createContentImage() 35 | { 36 | float hsv[] = { 0.0f, 1.0f, 1.0f }; 37 | return createHSVBarContentImage(InfComponentIndexHue, hsv); 38 | } 39 | 40 | //------------------------------------------------------------------------------ 41 | 42 | - (void) drawRect: (CGRect) rect 43 | { 44 | CGImageRef image = createContentImage(); 45 | 46 | if (image) { 47 | CGContextRef context = UIGraphicsGetCurrentContext(); 48 | 49 | CGContextDrawImage(context, [self bounds], image); 50 | 51 | CGImageRelease(image); 52 | } 53 | } 54 | 55 | //------------------------------------------------------------------------------ 56 | 57 | @end 58 | 59 | //============================================================================== 60 | 61 | @implementation InfColorBarPicker { 62 | InfColorIndicatorView* indicator; 63 | } 64 | 65 | //------------------------------------------------------------------------------ 66 | #pragma mark Drawing 67 | //------------------------------------------------------------------------------ 68 | 69 | - (void) layoutSubviews 70 | { 71 | if (indicator == nil) { 72 | CGFloat kIndicatorSize = 24.0f; 73 | indicator = [[InfColorIndicatorView alloc] initWithFrame: CGRectMake(0, 0, kIndicatorSize, kIndicatorSize)]; 74 | [self addSubview: indicator]; 75 | } 76 | 77 | indicator.color = [UIColor colorWithHue: self.value 78 | saturation: 1.0f 79 | brightness: 1.0f 80 | alpha: 1.0f]; 81 | 82 | CGFloat indicatorLoc = kContentInsetX + (self.value * (self.bounds.size.width - 2 * kContentInsetX)); 83 | indicator.center = CGPointMake(indicatorLoc, CGRectGetMidY(self.bounds)); 84 | } 85 | 86 | //------------------------------------------------------------------------------ 87 | #pragma mark Properties 88 | //------------------------------------------------------------------------------ 89 | 90 | - (void) setValue: (float) newValue 91 | { 92 | if (newValue != _value) { 93 | _value = newValue; 94 | 95 | [self sendActionsForControlEvents: UIControlEventValueChanged]; 96 | [self setNeedsLayout]; 97 | } 98 | } 99 | 100 | //------------------------------------------------------------------------------ 101 | #pragma mark Tracking 102 | //------------------------------------------------------------------------------ 103 | 104 | - (void) trackIndicatorWithTouch: (UITouch*) touch 105 | { 106 | float percent = ([touch locationInView: self].x - kContentInsetX) 107 | / (self.bounds.size.width - 2 * kContentInsetX); 108 | 109 | self.value = pin(0.0f, percent, 1.0f); 110 | } 111 | 112 | //------------------------------------------------------------------------------ 113 | 114 | - (BOOL) beginTrackingWithTouch: (UITouch*) touch 115 | withEvent: (UIEvent*) event 116 | { 117 | [self trackIndicatorWithTouch: touch]; 118 | 119 | return YES; 120 | } 121 | 122 | //------------------------------------------------------------------------------ 123 | 124 | - (BOOL) continueTrackingWithTouch: (UITouch*) touch 125 | withEvent: (UIEvent*) event 126 | { 127 | [self trackIndicatorWithTouch: touch]; 128 | 129 | return YES; 130 | } 131 | 132 | //------------------------------------------------------------------------------ 133 | #pragma mark Accessibility 134 | //------------------------------------------------------------------------------ 135 | 136 | - (UIAccessibilityTraits) accessibilityTraits 137 | { 138 | UIAccessibilityTraits t = super.accessibilityTraits; 139 | 140 | t |= UIAccessibilityTraitAdjustable; 141 | 142 | return t; 143 | } 144 | 145 | //------------------------------------------------------------------------------ 146 | 147 | - (void) accessibilityIncrement 148 | { 149 | float newValue = self.value + 0.05; 150 | 151 | if (newValue > 1.0) 152 | newValue -= 1.0; 153 | 154 | self.value = newValue; 155 | } 156 | 157 | //------------------------------------------------------------------------------ 158 | 159 | - (void) accessibilityDecrement 160 | { 161 | float newValue = self.value - 0.05; 162 | 163 | if (newValue < 0) 164 | newValue += 1.0; 165 | 166 | self.value = newValue; 167 | } 168 | 169 | //------------------------------------------------------------------------------ 170 | 171 | - (NSString*) accessibilityValue 172 | { 173 | return [NSString stringWithFormat: @"%d degrees hue", (int) (self.value * 360.0)]; 174 | } 175 | 176 | //------------------------------------------------------------------------------ 177 | 178 | @end 179 | 180 | //============================================================================== 181 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorIndicatorView.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorIndicatorView.h 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 8/10/10. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | @interface InfColorIndicatorView : UIView 18 | 19 | @property (nonatomic) UIColor* color; 20 | 21 | @end 22 | 23 | //------------------------------------------------------------------------------ 24 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorIndicatorView.m: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorIndicatorView.m 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 8/10/10. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import "InfColorIndicatorView.h" 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | #if !__has_feature(objc_arc) 18 | #error This file must be compiled with ARC enabled (-fobjc-arc). 19 | #endif 20 | 21 | //============================================================================== 22 | 23 | @implementation InfColorIndicatorView 24 | 25 | //------------------------------------------------------------------------------ 26 | 27 | - (id) initWithFrame: (CGRect) frame 28 | { 29 | self = [super initWithFrame: frame]; 30 | 31 | if (self) { 32 | self.opaque = NO; 33 | self.userInteractionEnabled = NO; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | //------------------------------------------------------------------------------ 40 | 41 | - (void) setColor: (UIColor*) newColor 42 | { 43 | if (![_color isEqual: newColor]) { 44 | _color = newColor; 45 | 46 | [self setNeedsDisplay]; 47 | } 48 | } 49 | 50 | //------------------------------------------------------------------------------ 51 | 52 | - (void) drawRect: (CGRect) rect 53 | { 54 | CGContextRef context = UIGraphicsGetCurrentContext(); 55 | 56 | CGPoint center = { CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds) }; 57 | CGFloat radius = CGRectGetMidX(self.bounds); 58 | 59 | // Fill it: 60 | 61 | CGContextAddArc(context, center.x, center.y, radius - 1.0f, 0.0f, 2.0f * (float) M_PI, YES); 62 | [self.color setFill]; 63 | CGContextFillPath(context); 64 | 65 | // Stroke it (black transucent, inner): 66 | 67 | CGContextAddArc(context, center.x, center.y, radius - 1.0f, 0.0f, 2.0f * (float) M_PI, YES); 68 | CGContextSetGrayStrokeColor(context, 0.0f, 0.5f); 69 | CGContextSetLineWidth(context, 2.0f); 70 | CGContextStrokePath(context); 71 | 72 | // Stroke it (white, outer): 73 | 74 | CGContextAddArc(context, center.x, center.y, radius - 2.0f, 0.0f, 2.0f * (float) M_PI, YES); 75 | CGContextSetGrayStrokeColor(context, 1.0f, 1.0f); 76 | CGContextSetLineWidth(context, 2.0f); 77 | CGContextStrokePath(context); 78 | } 79 | 80 | //------------------------------------------------------------------------------ 81 | 82 | @end 83 | 84 | //============================================================================== 85 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorPicker.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorPicker.h 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 7 Aug 2010. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | /* 13 | 14 | The InfiniApps Color Picker, known as InfColorPicker, is a view controller 15 | for use in iOS applications to allow the selection of a color from RGB space, 16 | but using an HSB representation of that color space to make selection of a 17 | color easier for a human. 18 | 19 | InfColorPicker is distributed with an MIT license. It supports iPhone OS 3.x 20 | as well as iOS 4 and 5. 21 | 22 | Usage 23 | ----- 24 | 25 | The main component is the `InfColorPickerController` class, which can be 26 | instantiated and hosted in a few different ways, such as in a popover view 27 | controller for the iPad, pushed onto a navigation controller navigation 28 | stack, or presented modally on an iPhone. 29 | 30 | The initial color can be set via the property `sourceColor`, which will be 31 | shown alongside the user-selected `resultColor` color, and these can be 32 | accessed and changed while the color picker is visible. 33 | 34 | In order to receive the selected color(s) back from the controller, you have 35 | to have an object that implements one of the methods in the 36 | `InfColorPickerControllerDelegate` protocol. 37 | 38 | Example 39 | ------- 40 | 41 | - (IBAction) changeBackgroundColor 42 | { 43 | InfColorPickerController* picker = [InfColorPickerController colorPickerViewController]; 44 | 45 | picker.sourceColor = self.view.backgroundColor; 46 | picker.delegate = self; 47 | 48 | [picker presentModallyOverViewController: self]; 49 | } 50 | 51 | - (void) colorPickerControllerDidFinish: (InfColorPickerController*) picker 52 | { 53 | self.view.backgroundColor = picker.resultColor; 54 | 55 | [self dismissModalViewControllerAnimated: YES]; 56 | } 57 | 58 | */ 59 | 60 | #import "InfColorPickerController.h" 61 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorPickerController.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorPickerController.h 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 7 Aug 2010. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import 14 | 15 | @protocol InfColorPickerControllerDelegate; 16 | 17 | //------------------------------------------------------------------------------ 18 | 19 | @interface InfColorPickerController : UIViewController 20 | 21 | // Public API: 22 | 23 | + (InfColorPickerController*) colorPickerViewController; 24 | + (CGSize) idealSizeForViewInPopover; 25 | 26 | - (void) presentModallyOverViewController: (UIViewController*) controller; 27 | 28 | @property (nonatomic) UIColor* sourceColor; 29 | @property (nonatomic) UIColor* resultColor; 30 | 31 | @property (weak, nonatomic) id delegate; 32 | 33 | @end 34 | 35 | //------------------------------------------------------------------------------ 36 | 37 | @protocol InfColorPickerControllerDelegate 38 | 39 | @optional 40 | 41 | - (void) colorPickerControllerDidFinish: (InfColorPickerController*) controller; 42 | // This is only called when the color picker is presented modally. 43 | 44 | - (void) colorPickerControllerDidChangeColor: (InfColorPickerController*) controller; 45 | 46 | @end 47 | 48 | //------------------------------------------------------------------------------ 49 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorPickerController.m: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorPickerController.m 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 7 Aug 2010. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import "InfColorPickerController.h" 14 | 15 | #import "InfColorBarPicker.h" 16 | #import "InfColorSquarePicker.h" 17 | #import "InfColorPickerNavigationController.h" 18 | #import "InfHSBSupport.h" 19 | 20 | //------------------------------------------------------------------------------ 21 | 22 | #if !__has_feature(objc_arc) 23 | #error This file must be compiled with ARC enabled (-fobjc-arc). 24 | #endif 25 | 26 | //------------------------------------------------------------------------------ 27 | 28 | static void HSVFromUIColor(UIColor* color, float* h, float* s, float* v) 29 | { 30 | CGColorRef colorRef = [color CGColor]; 31 | 32 | const CGFloat* components = CGColorGetComponents(colorRef); 33 | size_t numComponents = CGColorGetNumberOfComponents(colorRef); 34 | 35 | CGFloat r, g, b; 36 | 37 | if (numComponents < 3) { 38 | r = g = b = components[0]; 39 | } 40 | else { 41 | r = components[0]; 42 | g = components[1]; 43 | b = components[2]; 44 | } 45 | 46 | RGBToHSV(r, g, b, h, s, v, YES); 47 | } 48 | 49 | //============================================================================== 50 | 51 | @interface InfColorPickerController () 52 | 53 | @property (nonatomic) IBOutlet InfColorBarView* barView; 54 | @property (nonatomic) IBOutlet InfColorSquareView* squareView; 55 | @property (nonatomic) IBOutlet InfColorBarPicker* barPicker; 56 | @property (nonatomic) IBOutlet InfColorSquarePicker* squarePicker; 57 | @property (nonatomic) IBOutlet UIView* sourceColorView; 58 | @property (nonatomic) IBOutlet UIView* resultColorView; 59 | @property (nonatomic) IBOutlet UINavigationController* navController; 60 | 61 | @end 62 | 63 | //============================================================================== 64 | 65 | @implementation InfColorPickerController { 66 | float _hue; 67 | float _saturation; 68 | float _brightness; 69 | } 70 | 71 | //------------------------------------------------------------------------------ 72 | #pragma mark Class methods 73 | //------------------------------------------------------------------------------ 74 | 75 | + (InfColorPickerController*) colorPickerViewController 76 | { 77 | return [[self alloc] initWithNibName: @"JHColorPicker.bundle/InfColorPickerView" bundle: [NSBundle bundleForClass:InfColorPickerController.class]]; 78 | } 79 | 80 | //------------------------------------------------------------------------------ 81 | 82 | + (CGSize) idealSizeForViewInPopover 83 | { 84 | return CGSizeMake(256 + (1 + 20) * 2, 420); 85 | } 86 | 87 | //------------------------------------------------------------------------------ 88 | #pragma mark Creation 89 | //------------------------------------------------------------------------------ 90 | 91 | - (id) initWithNibName: (NSString*) nibNameOrNil bundle: (NSBundle*) nibBundleOrNil 92 | { 93 | self = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil]; 94 | 95 | if (self) { 96 | self.navigationItem.title = NSLocalizedString(@"Set Color", 97 | @"InfColorPicker default nav item title"); 98 | } 99 | 100 | return self; 101 | } 102 | 103 | //------------------------------------------------------------------------------ 104 | 105 | - (void) presentModallyOverViewController: (UIViewController*) controller 106 | { 107 | UINavigationController* nav = [[InfColorPickerNavigationController alloc] initWithRootViewController: self]; 108 | 109 | nav.navigationBar.barStyle = UIBarStyleBlackOpaque; 110 | 111 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemDone 112 | target: self 113 | action: @selector(done:)]; 114 | 115 | [controller presentViewController: nav animated: YES completion: nil]; 116 | } 117 | 118 | //------------------------------------------------------------------------------ 119 | #pragma mark UIViewController methods 120 | //------------------------------------------------------------------------------ 121 | 122 | - (void) viewDidLoad 123 | { 124 | [super viewDidLoad]; 125 | 126 | self.modalTransitionStyle = UIModalTransitionStyleCoverVertical; 127 | 128 | _barPicker.value = _hue; 129 | _squareView.hue = _hue; 130 | _squarePicker.hue = _hue; 131 | _squarePicker.value = CGPointMake(_saturation, _brightness); 132 | 133 | if (_sourceColor) 134 | _sourceColorView.backgroundColor = _sourceColor; 135 | 136 | if (_resultColor) 137 | _resultColorView.backgroundColor = _resultColor; 138 | } 139 | 140 | //------------------------------------------------------------------------------ 141 | 142 | - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation 143 | { 144 | return UIInterfaceOrientationIsPortrait(interfaceOrientation); 145 | } 146 | 147 | //------------------------------------------------------------------------------ 148 | 149 | - (UIInterfaceOrientationMask) supportedInterfaceOrientations 150 | { 151 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 152 | return UIInterfaceOrientationMaskAll; 153 | else 154 | return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; 155 | } 156 | 157 | //------------------------------------------------------------------------------ 158 | 159 | - (UIRectEdge) edgesForExtendedLayout 160 | { 161 | return UIRectEdgeNone; 162 | } 163 | 164 | //------------------------------------------------------------------------------ 165 | #pragma mark IB actions 166 | //------------------------------------------------------------------------------ 167 | 168 | - (IBAction) takeBarValue: (InfColorBarPicker*) sender 169 | { 170 | _hue = sender.value; 171 | 172 | _squareView.hue = _hue; 173 | _squarePicker.hue = _hue; 174 | 175 | [self updateResultColor]; 176 | } 177 | 178 | //------------------------------------------------------------------------------ 179 | 180 | - (IBAction) takeSquareValue: (InfColorSquarePicker*) sender 181 | { 182 | _saturation = sender.value.x; 183 | _brightness = sender.value.y; 184 | 185 | [self updateResultColor]; 186 | } 187 | 188 | //------------------------------------------------------------------------------ 189 | 190 | - (IBAction) takeBackgroundColor: (UIView*) sender 191 | { 192 | self.resultColor = sender.backgroundColor; 193 | } 194 | 195 | //------------------------------------------------------------------------------ 196 | 197 | - (IBAction) done: (id) sender 198 | { 199 | [self.delegate colorPickerControllerDidFinish: self]; 200 | } 201 | 202 | //------------------------------------------------------------------------------ 203 | #pragma mark Properties 204 | //------------------------------------------------------------------------------ 205 | 206 | - (void) informDelegateDidChangeColor 207 | { 208 | if (self.delegate && [(id) self.delegate respondsToSelector: @selector(colorPickerControllerDidChangeColor:)]) { 209 | [self.delegate colorPickerControllerDidChangeColor: self]; 210 | } 211 | [[NSNotificationCenter defaultCenter] postNotificationName:@"CUSTOM_COLOR_DID_CHANGE" object:nil userInfo:@{@"resultColor" : self.resultColor}]; 212 | } 213 | 214 | //------------------------------------------------------------------------------ 215 | 216 | - (void) updateResultColor 217 | { 218 | // This is used when code internally causes the update. We do this so that 219 | // we don't cause push-back on the HSV values in case there are rounding 220 | // differences or anything. 221 | 222 | [self willChangeValueForKey: @"resultColor"]; 223 | 224 | _resultColor = [UIColor colorWithHue: _hue 225 | saturation: _saturation 226 | brightness: _brightness 227 | alpha: 1.0f]; 228 | 229 | [self didChangeValueForKey: @"resultColor"]; 230 | 231 | _resultColorView.backgroundColor = _resultColor; 232 | 233 | [self informDelegateDidChangeColor]; 234 | } 235 | 236 | //------------------------------------------------------------------------------ 237 | 238 | - (void) setResultColor: (UIColor*) newValue 239 | { 240 | if (![_resultColor isEqual: newValue]) { 241 | _resultColor = newValue; 242 | 243 | float h = _hue; 244 | HSVFromUIColor(newValue, &h, &_saturation, &_brightness); 245 | 246 | if ((h == 0.0 && _hue == 1.0) || (h == 1.0 && _hue == 0.0)) { 247 | // these are equivalent, so do nothing 248 | } 249 | else if (h != _hue) { 250 | _hue = h; 251 | 252 | _barPicker.value = _hue; 253 | _squareView.hue = _hue; 254 | _squarePicker.hue = _hue; 255 | } 256 | 257 | _squarePicker.value = CGPointMake(_saturation, _brightness); 258 | 259 | _resultColorView.backgroundColor = _resultColor; 260 | 261 | [self informDelegateDidChangeColor]; 262 | } 263 | } 264 | 265 | //------------------------------------------------------------------------------ 266 | 267 | - (void) setSourceColor: (UIColor*) newValue 268 | { 269 | if (![_sourceColor isEqual: newValue]) { 270 | _sourceColor = newValue; 271 | 272 | _sourceColorView.backgroundColor = _sourceColor; 273 | 274 | self.resultColor = newValue; 275 | } 276 | } 277 | 278 | //------------------------------------------------------------------------------ 279 | #pragma mark UIViewController(UIPopoverController) methods 280 | //------------------------------------------------------------------------------ 281 | 282 | - (CGSize) contentSizeForViewInPopover 283 | { 284 | return [[self class] idealSizeForViewInPopover]; 285 | } 286 | 287 | //------------------------------------------------------------------------------ 288 | 289 | @end 290 | 291 | //============================================================================== 292 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorPickerNavigationController.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorPickerNavigationController.h 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 11 Dec 2013. 7 | // 8 | // Copyright (c) 2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import 14 | 15 | //------------------------------------------------------------------------------ 16 | // This navigation controller subclass forwards orientation requests to 17 | // the top view controller hosted within it so that it can choose to limit 18 | // the orientations it is displayed in. 19 | 20 | @interface InfColorPickerNavigationController : UINavigationController 21 | 22 | @end 23 | 24 | //------------------------------------------------------------------------------ 25 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorPickerNavigationController.m: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorPickerNavigationController.m 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 11 Dec 2013. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import "InfColorPickerNavigationController.h" 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | #if !__has_feature(objc_arc) 18 | #error This file must be compiled with ARC enabled (-fobjc-arc). 19 | #endif 20 | 21 | //============================================================================== 22 | 23 | @implementation InfColorPickerNavigationController 24 | 25 | //------------------------------------------------------------------------------ 26 | 27 | - (BOOL) shouldAutorotate 28 | { 29 | return [self.topViewController shouldAutorotate]; 30 | } 31 | 32 | //------------------------------------------------------------------------------ 33 | 34 | - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation 35 | { 36 | return [self.topViewController shouldAutorotateToInterfaceOrientation: interfaceOrientation]; 37 | } 38 | 39 | //------------------------------------------------------------------------------ 40 | 41 | - (UIInterfaceOrientationMask) supportedInterfaceOrientations 42 | { 43 | return self.topViewController.supportedInterfaceOrientations; 44 | } 45 | 46 | //------------------------------------------------------------------------------ 47 | 48 | @end 49 | 50 | //============================================================================== 51 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorSquarePicker.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorSquarePicker.h 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 8/9/10. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | @interface InfColorSquareView : UIImageView 18 | 19 | @property (nonatomic) float hue; 20 | 21 | @end 22 | 23 | //------------------------------------------------------------------------------ 24 | 25 | @interface InfColorSquarePicker : UIControl 26 | 27 | @property (nonatomic) float hue; 28 | @property (nonatomic) CGPoint value; 29 | 30 | @end 31 | 32 | //------------------------------------------------------------------------------ 33 | -------------------------------------------------------------------------------- /Pod/Classes/InfColorSquarePicker.m: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfColorSquarePicker.m 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 8/9/10. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import "InfColorSquarePicker.h" 14 | 15 | #import "InfColorIndicatorView.h" 16 | #import "InfHSBSupport.h" 17 | 18 | //------------------------------------------------------------------------------ 19 | 20 | #if !__has_feature(objc_arc) 21 | #error This file must be compiled with ARC enabled (-fobjc-arc). 22 | #endif 23 | 24 | //------------------------------------------------------------------------------ 25 | 26 | #define kContentInsetX 20 27 | #define kContentInsetY 20 28 | 29 | #define kIndicatorSize 24 30 | 31 | //============================================================================== 32 | 33 | @implementation InfColorSquareView 34 | 35 | //------------------------------------------------------------------------------ 36 | 37 | - (void) updateContent 38 | { 39 | CGImageRef imageRef = createSaturationBrightnessSquareContentImageWithHue(self.hue * 360); 40 | self.image = [UIImage imageWithCGImage: imageRef]; 41 | CGImageRelease(imageRef); 42 | } 43 | 44 | //------------------------------------------------------------------------------ 45 | #pragma mark Properties 46 | //------------------------------------------------------------------------------ 47 | 48 | - (void) setHue: (float) value 49 | { 50 | if (value != _hue || self.image == nil) { 51 | _hue = value; 52 | 53 | [self updateContent]; 54 | } 55 | } 56 | 57 | //------------------------------------------------------------------------------ 58 | 59 | @end 60 | 61 | //============================================================================== 62 | 63 | @implementation InfColorSquarePicker { 64 | InfColorIndicatorView* indicator; 65 | } 66 | 67 | //------------------------------------------------------------------------------ 68 | #pragma mark Appearance 69 | //------------------------------------------------------------------------------ 70 | 71 | - (void) setIndicatorColor 72 | { 73 | if (indicator == nil) 74 | return; 75 | 76 | indicator.color = [UIColor colorWithHue: self.hue 77 | saturation: self.value.x 78 | brightness: self.value.y 79 | alpha: 1.0f]; 80 | } 81 | 82 | //------------------------------------------------------------------------------ 83 | 84 | - (NSString*) spokenValue 85 | { 86 | return [NSString stringWithFormat: @"%d%% saturation, %d%% brightness", 87 | (int) (self.value.x * 100), (int) (self.value.y * 100)]; 88 | } 89 | 90 | //------------------------------------------------------------------------------ 91 | 92 | - (void) layoutSubviews 93 | { 94 | if (indicator == nil) { 95 | CGRect indicatorRect = { CGPointZero, { kIndicatorSize, kIndicatorSize } }; 96 | indicator = [[InfColorIndicatorView alloc] initWithFrame: indicatorRect]; 97 | [self addSubview: indicator]; 98 | } 99 | 100 | [self setIndicatorColor]; 101 | 102 | CGFloat indicatorX = kContentInsetX + (self.value.x * (self.bounds.size.width - 2 * kContentInsetX)); 103 | CGFloat indicatorY = self.bounds.size.height - kContentInsetY 104 | - (self.value.y * (self.bounds.size.height - 2 * kContentInsetY)); 105 | 106 | indicator.center = CGPointMake(indicatorX, indicatorY); 107 | } 108 | 109 | //------------------------------------------------------------------------------ 110 | #pragma mark Properties 111 | //------------------------------------------------------------------------------ 112 | 113 | - (void) setHue: (float) newValue 114 | { 115 | if (newValue != _hue) { 116 | _hue = newValue; 117 | 118 | [self setIndicatorColor]; 119 | } 120 | } 121 | 122 | //------------------------------------------------------------------------------ 123 | 124 | - (void) setValue: (CGPoint) newValue 125 | { 126 | if (!CGPointEqualToPoint(newValue, _value)) { 127 | _value = newValue; 128 | 129 | [self sendActionsForControlEvents: UIControlEventValueChanged]; 130 | [self setNeedsLayout]; 131 | } 132 | } 133 | 134 | //------------------------------------------------------------------------------ 135 | #pragma mark Tracking 136 | //------------------------------------------------------------------------------ 137 | 138 | - (void) trackIndicatorWithTouch: (UITouch*) touch 139 | { 140 | CGRect bounds = self.bounds; 141 | 142 | CGPoint touchValue; 143 | 144 | touchValue.x = ([touch locationInView: self].x - kContentInsetX) 145 | / (bounds.size.width - 2 * kContentInsetX); 146 | 147 | touchValue.y = ([touch locationInView: self].y - kContentInsetY) 148 | / (bounds.size.height - 2 * kContentInsetY); 149 | 150 | touchValue.x = pin(0.0f, touchValue.x, 1.0f); 151 | touchValue.y = 1.0f - pin(0.0f, touchValue.y, 1.0f); 152 | 153 | self.value = touchValue; 154 | } 155 | 156 | //------------------------------------------------------------------------------ 157 | 158 | - (BOOL) beginTrackingWithTouch: (UITouch*) touch 159 | withEvent: (UIEvent*) event 160 | { 161 | [self trackIndicatorWithTouch: touch]; 162 | return YES; 163 | } 164 | 165 | //------------------------------------------------------------------------------ 166 | 167 | - (BOOL) continueTrackingWithTouch: (UITouch*) touch 168 | withEvent: (UIEvent*) event 169 | { 170 | [self trackIndicatorWithTouch: touch]; 171 | return YES; 172 | } 173 | 174 | //------------------------------------------------------------------------------ 175 | 176 | @end 177 | 178 | //============================================================================== 179 | -------------------------------------------------------------------------------- /Pod/Classes/InfHSBSupport.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfHSBSupport.h 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 7 Aug 2010. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | float pin(float minValue, float value, float maxValue); 18 | 19 | //------------------------------------------------------------------------------ 20 | 21 | // These functions convert between an RGB value with components in the 22 | // 0.0f..1.0f range to HSV where Hue is 0 .. 360 and Saturation and 23 | // Value (aka Brightness) are percentages expressed as 0.0f..1.0f. 24 | // 25 | // Note that HSB (B = Brightness) and HSV (V = Value) are interchangeable 26 | // names that mean the same thing. I use V here as it is unambiguous 27 | // relative to the B in RGB, which is Blue. 28 | 29 | void HSVtoRGB(float h, float s, float v, float* r, float* g, float* b); 30 | 31 | void RGBToHSV(float r, float g, float b, float* h, float* s, float* v, 32 | BOOL preserveHS); 33 | 34 | //------------------------------------------------------------------------------ 35 | 36 | CGImageRef createSaturationBrightnessSquareContentImageWithHue(float hue); 37 | // Generates a 256x256 image with the specified constant hue where the 38 | // Saturation and value vary in the X and Y axes respectively. 39 | 40 | //------------------------------------------------------------------------------ 41 | 42 | typedef enum { 43 | InfComponentIndexHue = 0, 44 | InfComponentIndexSaturation = 1, 45 | InfComponentIndexBrightness = 2, 46 | } InfComponentIndex; 47 | 48 | CGImageRef createHSVBarContentImage(InfComponentIndex barComponentIndex, float hsv[3]); 49 | // Generates an image where the specified barComponentIndex (0=H, 1=S, 2=V) 50 | // varies across the x-axis of the 256x1 pixel image and the other components 51 | // remain at the constant value specified in the hsv array. 52 | 53 | //------------------------------------------------------------------------------ 54 | -------------------------------------------------------------------------------- /Pod/Classes/InfHSBSupport.m: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfHSBSupport.m 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 7 Aug 2010. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import "InfHSBSupport.h" 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | float pin(float minValue, float value, float maxValue) 18 | { 19 | if (minValue > value) 20 | return minValue; 21 | else if (maxValue < value) 22 | return maxValue; 23 | else 24 | return value; 25 | } 26 | 27 | //------------------------------------------------------------------------------ 28 | #pragma mark Floating point conversion 29 | //------------------------------------------------------------------------------ 30 | 31 | static void hueToComponentFactors(float h, float* r, float* g, float* b) 32 | { 33 | float h_prime = h / 60.0f; 34 | float x = 1.0f - fabsf(fmodf(h_prime, 2.0f) - 1.0f); 35 | 36 | if (h_prime < 1.0f) { 37 | *r = 1; 38 | *g = x; 39 | *b = 0; 40 | } 41 | else if (h_prime < 2.0f) { 42 | *r = x; 43 | *g = 1; 44 | *b = 0; 45 | } 46 | else if (h_prime < 3.0f) { 47 | *r = 0; 48 | *g = 1; 49 | *b = x; 50 | } 51 | else if (h_prime < 4.0f) { 52 | *r = 0; 53 | *g = x; 54 | *b = 1; 55 | } 56 | else if (h_prime < 5.0f) { 57 | *r = x; 58 | *g = 0; 59 | *b = 1; 60 | } 61 | else { 62 | *r = 1; 63 | *g = 0; 64 | *b = x; 65 | } 66 | } 67 | 68 | //------------------------------------------------------------------------------ 69 | 70 | void HSVtoRGB(float h, float s, float v, float* r, float* g, float* b) 71 | { 72 | hueToComponentFactors(h, r, g, b); 73 | 74 | float c = v * s; 75 | float m = v - c; 76 | 77 | *r = *r * c + m; 78 | *g = *g * c + m; 79 | *b = *b * c + m; 80 | } 81 | 82 | //------------------------------------------------------------------------------ 83 | 84 | void RGBToHSV(float r, float g, float b, float* h, float* s, float* v, BOOL preserveHS) 85 | { 86 | float max = r; 87 | 88 | if (max < g) 89 | max = g; 90 | 91 | if (max < b) 92 | max = b; 93 | 94 | float min = r; 95 | 96 | if (min > g) 97 | min = g; 98 | 99 | if (min > b) 100 | min = b; 101 | 102 | // Brightness (aka Value) 103 | 104 | *v = max; 105 | 106 | // Saturation 107 | 108 | float sat; 109 | 110 | if (max != 0.0f) { 111 | sat = (max - min) / max; 112 | *s = sat; 113 | } 114 | else { 115 | sat = 0.0f; 116 | 117 | if (!preserveHS) 118 | *s = 0.0f; // Black, so sat is undefined, use 0 119 | } 120 | 121 | // Hue 122 | 123 | float delta; 124 | 125 | if (sat == 0.0f) { 126 | if (!preserveHS) 127 | *h = 0.0f; // No color, so hue is undefined, use 0 128 | } 129 | else { 130 | delta = max - min; 131 | 132 | float hue; 133 | 134 | if (r == max) 135 | hue = (g - b) / delta; 136 | else if (g == max) 137 | hue = 2 + (b - r) / delta; 138 | else 139 | hue = 4 + (r - g) / delta; 140 | 141 | hue /= 6.0f; 142 | 143 | if (hue < 0.0f) 144 | hue += 1.0f; 145 | 146 | if (!preserveHS || fabsf(hue - *h) != 1.0f) 147 | *h = hue; // 0.0 and 1.0 hues are actually both the same (red) 148 | } 149 | } 150 | 151 | //------------------------------------------------------------------------------ 152 | #pragma mark Square/Bar image creation 153 | //------------------------------------------------------------------------------ 154 | 155 | static UInt8 blend(UInt8 value, UInt8 percentIn255) 156 | { 157 | return (UInt8) ((int) value * percentIn255 / 255); 158 | } 159 | 160 | //------------------------------------------------------------------------------ 161 | 162 | static CGContextRef createBGRxImageContext(int w, int h, void* data) 163 | { 164 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 165 | 166 | CGBitmapInfo kBGRxBitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst; 167 | // BGRA is the most efficient on the iPhone. 168 | 169 | CGContextRef context = CGBitmapContextCreate(data, w, h, 8, w * 4, colorSpace, kBGRxBitmapInfo); 170 | 171 | CGColorSpaceRelease(colorSpace); 172 | 173 | return context; 174 | } 175 | 176 | //------------------------------------------------------------------------------ 177 | 178 | CGImageRef createSaturationBrightnessSquareContentImageWithHue(float hue) 179 | { 180 | void* data = malloc(256 * 256 * 4); 181 | if (data == nil) 182 | return nil; 183 | 184 | CGContextRef context = createBGRxImageContext(256, 256, data); 185 | 186 | if (context == nil) { 187 | free(data); 188 | return nil; 189 | } 190 | 191 | UInt8* dataPtr = data; 192 | size_t rowBytes = CGBitmapContextGetBytesPerRow(context); 193 | 194 | float r, g, b; 195 | hueToComponentFactors(hue, &r, &g, &b); 196 | 197 | UInt8 r_s = (UInt8) ((1.0f - r) * 255); 198 | UInt8 g_s = (UInt8) ((1.0f - g) * 255); 199 | UInt8 b_s = (UInt8) ((1.0f - b) * 255); 200 | 201 | for (int s = 0; s < 256; ++s) { 202 | register UInt8* ptr = dataPtr; 203 | 204 | register unsigned int r_hs = 255 - blend(s, r_s); 205 | register unsigned int g_hs = 255 - blend(s, g_s); 206 | register unsigned int b_hs = 255 - blend(s, b_s); 207 | 208 | for (register int v = 255; v >= 0; --v) { 209 | ptr[0] = (UInt8) (v * b_hs >> 8); 210 | ptr[1] = (UInt8) (v * g_hs >> 8); 211 | ptr[2] = (UInt8) (v * r_hs >> 8); 212 | 213 | // Really, these should all be of the form used in blend(), 214 | // which does a divide by 255. However, integer divide is 215 | // implemented in software on ARM, so a divide by 256 216 | // (done as a bit shift) will be *nearly* the same value, 217 | // and is faster. The more-accurate versions would look like: 218 | // ptr[0] = blend(v, b_hs); 219 | 220 | ptr += rowBytes; 221 | } 222 | 223 | dataPtr += 4; 224 | } 225 | 226 | // Return an image of the context's content: 227 | 228 | CGImageRef image = CGBitmapContextCreateImage(context); 229 | 230 | CGContextRelease(context); 231 | free(data); 232 | 233 | return image; 234 | } 235 | 236 | //------------------------------------------------------------------------------ 237 | 238 | CGImageRef createHSVBarContentImage(InfComponentIndex barComponentIndex, float hsv[3]) 239 | { 240 | UInt8 data[256 * 4]; 241 | 242 | // Set up the bitmap context for filling with color: 243 | 244 | CGContextRef context = createBGRxImageContext(256, 1, data); 245 | 246 | if (context == nil) 247 | return nil; 248 | 249 | // Draw into context here: 250 | 251 | UInt8* ptr = CGBitmapContextGetData(context); 252 | if (ptr == nil) { 253 | CGContextRelease(context); 254 | return nil; 255 | } 256 | 257 | float r, g, b; 258 | for (int x = 0; x < 256; ++x) { 259 | hsv[barComponentIndex] = (float) x / 255.0f; 260 | 261 | HSVtoRGB(hsv[0] * 360.0f, hsv[1], hsv[2], &r, &g, &b); 262 | 263 | ptr[0] = (UInt8) (b * 255.0f); 264 | ptr[1] = (UInt8) (g * 255.0f); 265 | ptr[2] = (UInt8) (r * 255.0f); 266 | 267 | ptr += 4; 268 | } 269 | 270 | // Return an image of the context's content: 271 | 272 | CGImageRef image = CGBitmapContextCreateImage(context); 273 | 274 | CGContextRelease(context); 275 | 276 | return image; 277 | } 278 | 279 | //------------------------------------------------------------------------------ 280 | -------------------------------------------------------------------------------- /Pod/Classes/InfSourceColorView.h: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfSourceColorView.h 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 8/10/10. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | @interface InfSourceColorView : UIControl 18 | 19 | @property (nonatomic) BOOL trackingInside; 20 | 21 | @end 22 | 23 | //------------------------------------------------------------------------------ 24 | -------------------------------------------------------------------------------- /Pod/Classes/InfSourceColorView.m: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // InfSourceColorView.m 4 | // InfColorPicker 5 | // 6 | // Created by Troy Gaul on 8/10/10. 7 | // 8 | // Copyright (c) 2011-2013 InfinitApps LLC: http://infinitapps.com 9 | // Some rights reserved: http://opensource.org/licenses/MIT 10 | // 11 | //============================================================================== 12 | 13 | #import "InfSourceColorView.h" 14 | 15 | //------------------------------------------------------------------------------ 16 | 17 | #if !__has_feature(objc_arc) 18 | #error This file must be compiled with ARC enabled (-fobjc-arc). 19 | #endif 20 | 21 | //============================================================================== 22 | 23 | @implementation InfSourceColorView 24 | 25 | //------------------------------------------------------------------------------ 26 | #pragma mark UIView overrides 27 | //------------------------------------------------------------------------------ 28 | 29 | - (void) drawRect: (CGRect) rect 30 | { 31 | [super drawRect: rect]; 32 | 33 | if (self.enabled && self.trackingInside) { 34 | CGRect bounds = [self bounds]; 35 | 36 | [[UIColor whiteColor] set]; 37 | CGContextStrokeRectWithWidth(UIGraphicsGetCurrentContext(), 38 | CGRectInset(bounds, 1, 1), 2); 39 | 40 | [[UIColor blackColor] set]; 41 | UIRectFrame(CGRectInset(bounds, 2, 2)); 42 | } 43 | } 44 | 45 | //------------------------------------------------------------------------------ 46 | #pragma mark UIControl overrides 47 | //------------------------------------------------------------------------------ 48 | 49 | - (void) setTrackingInside: (BOOL) newValue 50 | { 51 | if (newValue != _trackingInside) { 52 | _trackingInside = newValue; 53 | [self setNeedsDisplay]; 54 | } 55 | } 56 | 57 | //------------------------------------------------------------------------------ 58 | 59 | - (BOOL) beginTrackingWithTouch: (UITouch*) touch 60 | withEvent: (UIEvent*) event 61 | { 62 | if (self.enabled) { 63 | self.trackingInside = YES; 64 | 65 | return [super beginTrackingWithTouch: touch withEvent: event]; 66 | } 67 | else { 68 | return NO; 69 | } 70 | } 71 | 72 | //------------------------------------------------------------------------------ 73 | 74 | - (BOOL) continueTrackingWithTouch: (UITouch*) touch withEvent: (UIEvent*) event 75 | { 76 | BOOL isTrackingInside = CGRectContainsPoint([self bounds], [touch locationInView: self]); 77 | 78 | self.trackingInside = isTrackingInside; 79 | 80 | return [super continueTrackingWithTouch: touch withEvent: event]; 81 | } 82 | 83 | //------------------------------------------------------------------------------ 84 | 85 | - (void) endTrackingWithTouch: (UITouch*) touch withEvent: (UIEvent*) event 86 | { 87 | self.trackingInside = NO; 88 | 89 | [super endTrackingWithTouch: touch withEvent: event]; 90 | } 91 | 92 | //------------------------------------------------------------------------------ 93 | 94 | - (void) cancelTrackingWithEvent: (UIEvent*) event 95 | { 96 | self.trackingInside = NO; 97 | 98 | [super cancelTrackingWithEvent: event]; 99 | } 100 | 101 | //------------------------------------------------------------------------------ 102 | 103 | @end 104 | 105 | //============================================================================== 106 | -------------------------------------------------------------------------------- /Pod/Classes/JHColorPickerController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JHColorPickerController.swift 3 | // JHColorPickerController 4 | // 5 | // Created by Julian Hays on 7/8/15. 6 | // Copyright (c) 2015 orbosphere. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import ChameleonFramework 12 | import UIColor_Crayola 13 | import UIColor_Pantone 14 | 15 | public protocol JHColorPickerControllerDelegate { 16 | func colorSaved(color:UIColor, name:String?) 17 | func colorSelected(color:UIColor, name:String?) 18 | func colorPickerCancelled() 19 | } 20 | 21 | class SwatchCell: UICollectionViewCell { 22 | @IBOutlet weak var title: UILabel! 23 | @IBOutlet weak var colorView: UIView! 24 | 25 | override init(frame: CGRect) { 26 | super.init(frame: frame) 27 | colorView = UIView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height - 28)) 28 | title = UILabel(frame: CGRect(x: 0, y: frame.size.height - 28, width: frame.size.width, height: 28)) 29 | 30 | self.addSubview(colorView) 31 | self.addSubview(title) 32 | 33 | } 34 | 35 | required init?(coder aDecoder: NSCoder) { 36 | super.init(coder: aDecoder) 37 | } 38 | 39 | override func awakeFromNib() { 40 | contentView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight] 41 | title.font = UIFont(name: "HelveticaNeue-Light", size: 14.0) 42 | title.textAlignment = NSTextAlignment.Center 43 | title.numberOfLines = 2 44 | title.lineBreakMode = NSLineBreakMode.ByWordWrapping 45 | } 46 | 47 | } 48 | 49 | public class JHColorPickerController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate { 50 | 51 | enum ColorCategory{ 52 | case Crayola 53 | case Pantone 54 | case Flat 55 | case Custom 56 | } 57 | 58 | @IBOutlet weak var previousColorView:UIView! 59 | @IBOutlet weak var selectedColorView:UIView! 60 | @IBOutlet weak var previousColorLabel:UILabel! 61 | @IBOutlet weak var selectedColorLabel:UILabel! 62 | @IBOutlet weak var previousColorNameLabel: UILabel! 63 | @IBOutlet weak var selectedColorNameLabel: UILabel! 64 | @IBOutlet weak var categorySelectorSegmentedControl: UISegmentedControl! 65 | @IBOutlet weak var swatchView:UIView! 66 | @IBOutlet weak var swatchCollectionView:UICollectionView! 67 | @IBOutlet weak var customView:UIView! 68 | 69 | public var delegate:JHColorPickerControllerDelegate? 70 | public var completion : ((UIColor) -> ())? 71 | var colorSwatches = Array>() 72 | var infColorPicker : InfColorPickerController! 73 | 74 | var selectedColorCategory:ColorCategory = .Crayola { 75 | didSet { 76 | switch selectedColorCategory { 77 | case .Crayola: 78 | customView.hidden = true 79 | swatchView.hidden = false 80 | colorSwatches = ColorLibraries.crayolaColors 81 | case .Pantone: 82 | customView.hidden = true 83 | swatchView.hidden = false 84 | colorSwatches = ColorLibraries.pantoneColors 85 | case .Flat: 86 | customView.hidden = true 87 | swatchView.hidden = false 88 | colorSwatches = ColorLibraries.flatColors 89 | case .Custom: 90 | swatchView.hidden = true 91 | customView.hidden = false 92 | infColorPicker.view.hidden = false 93 | } 94 | swatchCollectionView.reloadData() 95 | } 96 | } 97 | var selectedColor: UIColor?{ 98 | didSet{ 99 | selectedColorView.backgroundColor = selectedColor 100 | infColorPicker.sourceColor = selectedColor 101 | delegate?.colorSelected(selectedColor!, name: selectedColorName) 102 | applyLabelColors() 103 | } 104 | } 105 | var selectedColorName: String? { 106 | didSet{ 107 | selectedColorNameLabel.text = selectedColorName 108 | } 109 | } 110 | 111 | public var previousColor: UIColor? 112 | public var previousColorName:String?{ 113 | didSet{ 114 | previousColorNameLabel.text = previousColorName 115 | } 116 | } 117 | 118 | convenience init() { 119 | let bundle = NSBundle(forClass:JHColorPickerController.self) 120 | self.init(nibName: "JHColorPicker.bundle/JHColorPickerController", bundle: bundle) 121 | } 122 | 123 | public override func viewDidLoad() { 124 | super.viewDidLoad() 125 | let bundle = NSBundle(forClass:JHColorPickerController.self) 126 | swatchCollectionView.registerNib(UINib(nibName: "JHColorPicker.bundle/SwatchCell", bundle: bundle), forCellWithReuseIdentifier: "swatchCell") 127 | // swatchCollectionView.registerClass(SwatchCell.self, forCellWithReuseIdentifier: "swatchCell") 128 | loadNavButtons() 129 | 130 | colorSwatches = ColorLibraries.crayolaColors 131 | 132 | infColorPicker = InfColorPickerController.colorPickerViewController() 133 | infColorPicker.willMoveToParentViewController(self) 134 | infColorPicker.view.hidden = true 135 | customView.addSubview(infColorPicker.view) 136 | infColorPicker.didMoveToParentViewController(self) 137 | 138 | 139 | 140 | //this is unfortunate, but any attempts to implement InfColorPickerDelegate have resulted in failure to compile. 141 | //must be something to do with communicating between ObjC and Swift... this notification will have to do for now. 142 | NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(JHColorPickerController.colorPickerDidChangeColor(_:)), name: "CUSTOM_COLOR_DID_CHANGE", object: nil) 143 | } 144 | 145 | deinit { 146 | NSNotificationCenter.defaultCenter().removeObserver(self) 147 | } 148 | 149 | public override func willTransitionToTraitCollection(newCollection: UITraitCollection, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 150 | coordinator.animateAlongsideTransition({ (context) -> Void in 151 | 152 | }, completion: { (context) -> Void in 153 | self.swatchCollectionView.collectionViewLayout.invalidateLayout() 154 | }) 155 | } 156 | 157 | public override func viewWillAppear(animated: Bool) { 158 | super.viewWillAppear(animated) 159 | self.navigationController?.setNavigationBarHidden(true, animated: false) 160 | if let previousColor = previousColor { 161 | previousColorView.backgroundColor = previousColor 162 | previousColorName = ColorLibraries.nameForColor(previousColor) 163 | infColorPicker.sourceColor = previousColor 164 | } 165 | applyLabelColors() 166 | } 167 | 168 | public override func viewDidAppear(animated:Bool) { 169 | super.viewDidAppear(animated) 170 | infColorPicker.view.frame = customView.bounds 171 | } 172 | 173 | func loadNavButtons() { 174 | let leftCancelBtn = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(JHColorPickerController.cancelBtnPressed(_:))) 175 | let rightSaveBtn = UIBarButtonItem(title: "Save", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(JHColorPickerController.saveBtnPressed(_:))) 176 | self.navigationItem.leftBarButtonItem = leftCancelBtn 177 | self.navigationItem.rightBarButtonItem = rightSaveBtn 178 | } 179 | 180 | func applyLabelColors() { 181 | 182 | var prevTextColor = UIColor.blackColor() 183 | var prevShadowColor = UIColor.whiteColor() 184 | 185 | if let previousColor = previousColor { 186 | if !previousColor.isLight() { 187 | prevTextColor = UIColor.whiteColor() 188 | prevShadowColor = UIColor.blackColor() 189 | } 190 | } 191 | 192 | var selectedTextColor = UIColor.blackColor() 193 | var selectedShadowColor = UIColor.whiteColor() 194 | 195 | if let selectedColor = selectedColor { 196 | if !selectedColor.isLight() { 197 | selectedTextColor = UIColor.whiteColor() 198 | selectedShadowColor = UIColor.blackColor() 199 | } 200 | } 201 | 202 | previousColorLabel.textColor = prevTextColor 203 | previousColorLabel.layer.shadowColor = prevShadowColor.CGColor 204 | previousColorLabel.layer.shadowOffset = CGSize(width: 0, height: 0) 205 | previousColorLabel.layer.shadowOpacity = 1.0 206 | previousColorLabel.layer.shadowRadius = 2 207 | 208 | previousColorNameLabel.textColor = prevTextColor 209 | previousColorNameLabel.layer.shadowColor = prevShadowColor.CGColor 210 | previousColorNameLabel.layer.shadowOffset = CGSize(width: 0, height: 0) 211 | previousColorNameLabel.layer.shadowOpacity = 1.0 212 | previousColorNameLabel.layer.shadowRadius = 2 213 | 214 | selectedColorLabel.textColor = selectedTextColor 215 | selectedColorLabel.layer.shadowColor = selectedShadowColor.CGColor 216 | selectedColorLabel.layer.shadowOffset = CGSize(width: 0, height: 0) 217 | selectedColorLabel.layer.shadowOpacity = 1.0 218 | selectedColorLabel.layer.shadowRadius = 2 219 | 220 | selectedColorNameLabel.textColor = selectedTextColor 221 | selectedColorNameLabel.layer.shadowColor = selectedShadowColor.CGColor 222 | selectedColorNameLabel.layer.shadowOffset = CGSize(width: 0, height: 0) 223 | selectedColorNameLabel.layer.shadowOpacity = 1.0 224 | selectedColorNameLabel.layer.shadowRadius = 2 225 | } 226 | 227 | @IBAction func cancelBtnPressed(sender:UIButton) { 228 | delegate?.colorPickerCancelled() 229 | } 230 | 231 | @IBAction func saveBtnPressed(sender:UIButton) { 232 | if let color = selectedColor { 233 | if let completion = completion { 234 | completion(color) 235 | } 236 | delegate?.colorSaved(color, name: selectedColorName) 237 | }else { 238 | 239 | } 240 | 241 | } 242 | 243 | @IBAction func colorCategorySegmentedControlValueChanged(sender: UISegmentedControl) { 244 | switch sender.selectedSegmentIndex { 245 | case 0: 246 | selectedColorCategory = .Crayola 247 | case 1: 248 | selectedColorCategory = .Pantone 249 | case 2: 250 | selectedColorCategory = .Flat 251 | case 3: 252 | selectedColorCategory = .Custom 253 | default: 254 | selectedColorCategory = .Custom 255 | } 256 | } 257 | 258 | @IBAction func darkBtnPressed(sender: UIButton) { 259 | 260 | selectedColor = selectedColor?.darkerColor(0.01) 261 | } 262 | 263 | 264 | @IBAction func brightBtnPressed(sender: AnyObject) { 265 | selectedColor = selectedColor?.lighterColor(0.01) 266 | } 267 | 268 | func colorPickerDidChangeColor(notification:NSNotification) { 269 | if let userInfo = notification.userInfo { 270 | if let resultColor = userInfo["resultColor"] as? UIColor { 271 | selectedColor = resultColor 272 | selectedColorName = selectedColor!.toHexString() 273 | } 274 | } 275 | applyLabelColors() 276 | } 277 | 278 | //MARK: UICollectionViewDelegate 279 | 280 | public func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { 281 | selectedColor = colorSwatches[indexPath.item]["color"] as? UIColor 282 | selectedColorName = colorSwatches[indexPath.item]["title"] as? String 283 | } 284 | 285 | // MARK: UICollectionViewDataSource 286 | 287 | public func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { 288 | //#warning Incomplete method implementation -- Return the number of sections 289 | return 1 290 | } 291 | 292 | 293 | public func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 294 | //#warning Incomplete method implementation -- Return the number of items in the section 295 | return colorSwatches.count 296 | } 297 | 298 | public func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 299 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier("swatchCell", forIndexPath: indexPath) as! SwatchCell 300 | //cell.title.text = self.colorSwatches[indexPath.row % 5] 301 | //let curr = indexPath.row % 5 + 1 302 | 303 | cell.title.text = colorSwatches[indexPath.item]["title"] as? String 304 | cell.colorView.backgroundColor = colorSwatches[indexPath.item]["color"] as? UIColor 305 | //cell.pinImage.image = UIImage(named: imgName) 306 | 307 | return cell 308 | } 309 | 310 | func collectionView(collectionView: UICollectionView!, 311 | layout collectionViewLayout: UICollectionViewLayout!, 312 | sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize { 313 | if self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClass.Compact { 314 | let height = (swatchCollectionView.frame.size.height - 16) / 2 315 | let width = (swatchCollectionView.frame.size.width - 16) / 2 316 | return CGSize(width: width, height: height) 317 | }else { 318 | let height = (swatchCollectionView.frame.size.height - 16) / 2 319 | let width = (self.view.frame.size.width - 48) / 2 320 | return CGSize(width: width, height: height) 321 | } 322 | } 323 | 324 | func collectionView(collectionView: UICollectionView!, 325 | layout collectionViewLayout: UICollectionViewLayout!, 326 | insetForSectionAtIndex section: Int) -> UIEdgeInsets { 327 | return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 328 | } 329 | 330 | } 331 | -------------------------------------------------------------------------------- /Pod/Classes/UIColorExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColorExtension.swift 3 | // Pods 4 | // 5 | // Created by Julian Hays on 7/10/15. 6 | // 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIColor { 13 | convenience init(hexString:String) { 14 | let hexString:NSString = hexString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) 15 | let scanner = NSScanner(string: hexString as String) 16 | 17 | if (hexString.hasPrefix("#")) { 18 | scanner.scanLocation = 1 19 | } 20 | 21 | var color:UInt32 = 0 22 | scanner.scanHexInt(&color) 23 | 24 | let mask = 0x000000FF 25 | let r = Int(color >> 16) & mask 26 | let g = Int(color >> 8) & mask 27 | let b = Int(color) & mask 28 | 29 | let red = CGFloat(r) / 255.0 30 | let green = CGFloat(g) / 255.0 31 | let blue = CGFloat(b) / 255.0 32 | 33 | self.init(red:red, green:green, blue:blue, alpha:1) 34 | } 35 | 36 | func toHexString() -> String { 37 | var r:CGFloat = 0 38 | var g:CGFloat = 0 39 | var b:CGFloat = 0 40 | var a:CGFloat = 0 41 | 42 | getRed(&r, green: &g, blue: &b, alpha: &a) 43 | 44 | let rgb:Int = (Int)(r*255)<<16 | (Int)(g*255)<<8 | (Int)(b*255)<<0 45 | 46 | return NSString(format:"#%06x", rgb) as String 47 | } 48 | 49 | /** 50 | Returns a lighter color by the provided percentage 51 | 52 | :param: lighting percent percentage 53 | :returns: lighter UIColor 54 | */ 55 | func lighterColor(percent : Double) -> UIColor { 56 | return colorWithBrightnessFactor(CGFloat(1 + percent)); 57 | } 58 | 59 | /** 60 | Returns a darker color by the provided percentage 61 | 62 | :param: darking percent percentage 63 | :returns: darker UIColor 64 | */ 65 | func darkerColor(percent : Double) -> UIColor { 66 | return colorWithBrightnessFactor(CGFloat(1 - percent)); 67 | } 68 | 69 | /** 70 | Return a modified color using the brightness factor provided 71 | 72 | :param: factor brightness factor 73 | :returns: modified color 74 | */ 75 | func colorWithBrightnessFactor(factor: CGFloat) -> UIColor { 76 | var hue : CGFloat = 0 77 | var saturation : CGFloat = 0 78 | var brightness : CGFloat = 0 79 | var alpha : CGFloat = 0 80 | 81 | if getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) { 82 | return UIColor(hue: hue, saturation: saturation, brightness: brightness * factor, alpha: alpha) 83 | } else { 84 | return self; 85 | } 86 | } 87 | 88 | 89 | func isLight() -> Bool 90 | { 91 | let components = CGColorGetComponents(self.CGColor) 92 | let comp0 = components[0] * 299 93 | let comp1 = components[1] * 587 94 | let comp2 = components[2] * 114 95 | let brightness = (comp0 + comp1 + comp2) / 1000 96 | 97 | if brightness < 0.5 { 98 | return false 99 | } 100 | else { 101 | return true 102 | } 103 | } 104 | 105 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JHColorPicker 2 | 3 | [![Version](https://img.shields.io/cocoapods/v/JHColorPicker.svg?style=flat)](http://cocoapods.org/pods/JHColorPicker) 4 | [![License](https://img.shields.io/cocoapods/l/JHColorPicker.svg?style=flat)](http://cocoapods.org/pods/JHColorPicker) 5 | [![Platform](https://img.shields.io/cocoapods/p/JHColorPicker.svg?style=flat)](http://cocoapods.org/pods/JHColorPicker) 6 | 7 | JHColorPicker is a color picker that includes swatches from Crayola, Pantone, and ChameleonFramework flat colors, as well as a custom color picker 8 | 9 | ![Screenshot](https://raw.githubusercontent.com/jhays/JHColorPicker/master/JHColorPicker-Demo.gif) 10 | 11 | This color picker is a combination of the following pods: 12 | 13 | InfinitApps/InfColorPicker 14 | https://github.com/InfinitApps/InfColorPicker 15 | 16 | ViccAlexander/Chameleon 17 | https://github.com/ViccAlexander/Chameleon 18 | 19 | mihaelamj/uicolor-crayola 20 | https://github.com/mihaelamj/uicolor-crayola 21 | 22 | mihaelamj/uicolor-pantone 23 | https://github.com/mihaelamj/uicolor-pantone 24 | 25 | ## Usage 26 | 27 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 28 | 29 | ```swift 30 | let colorPickerController = JHColorPickerController() 31 | colorPickerController.delegate = self 32 | colorPickerController.previousColor = self.view.backgroundColor 33 | colorPickerController.completion = { selectedColor in 34 | self.view.backgroundColor = selectedColor 35 | } 36 | self.presentViewController(UINavigationController(rootViewController: colorPickerController), animated: true, completion: nil) 37 | ``` 38 | ## Requirements 39 | iOS 8+, XCode 7+ 40 | 41 | (Included via pod dependency): 42 | * ChameleonFramework 43 | * ColorUtils 44 | * UIColor-Crayola 45 | * UIColor-Pantone 46 | 47 | ## Installation 48 | 49 | JHColorPicker is available through [CocoaPods](http://cocoapods.org). To install 50 | it, simply add the following line to your Podfile: 51 | 52 | ```ruby 53 | pod "JHColorPicker" 54 | ``` 55 | 56 | ## Author 57 | 58 | JHays, orbosphere@gmail.com 59 | 60 | ## License 61 | 62 | JHColorPicker is available under the MIT license. See the LICENSE file for more info. 63 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------