diff --git a/.swift-version b/.swift-version
index 9f55b2c..5186d07 100644
--- a/.swift-version
+++ b/.swift-version
@@ -1 +1 @@
-3.0
+4.0
diff --git a/.travis.yml b/.travis.yml
index 33b247e..058b6fd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,11 @@
language: objective-c
-osx_image: xcode8
+osx_image: xcode9
env:
global:
- LC_CTYPE=en_US.UTF-8
- LANG=en_US.UTF-8
before_install:
- - brew update
- - brew reinstall xctool
+ - bundle install
script:
- - xcodebuild -showsdks
- - xcodebuild -project ColorSlider/ColorSlider.xcodeproj -scheme ColorSlider -sdk iphonesimulator10.0 build analyze
+ - bundle exec pod lib lint --verbose
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..dab0d19
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,11 @@
+### One issue or bug per Pull Request
+
+Keep your Pull Requests small. Small PRs are easier to reason about which makes them significantly more likely to get merged.
+
+### Issues before features
+
+If you want to add a feature, please file an [Issue](issues) first. An Issue gives us the opportunity to discuss the requirements and implications of a feature with you before you start writing code.
+
+### Forwards compatibility
+
+Please do not write new code using deprecated APIs.
\ No newline at end of file
diff --git a/ColorSlider.gif b/ColorSlider.gif
index 9160262..6861102 100644
Binary files a/ColorSlider.gif and b/ColorSlider.gif differ
diff --git a/ColorSlider.podspec b/ColorSlider.podspec
index fb33f58..8b788df 100644
--- a/ColorSlider.podspec
+++ b/ColorSlider.podspec
@@ -1,14 +1,23 @@
Pod::Spec.new do |s|
s.name = 'ColorSlider'
- s.version = '3.0.1'
- s.summary = 'Snapchat-style color picker with live preview'
+ s.version = '4.0'
+ s.summary = 'Snapchat-style color picker in Swift'
s.homepage = 'http://github.com/gizmosachin/ColorSlider'
s.license = 'MIT'
+ s.documentation_url = 'http://gizmosachin.com/ColorSlider/'
+
s.social_media_url = 'http://twitter.com/gizmosachin'
s.author = { 'Sachin Patel' => 'me@gizmosachin.com' }
+
+ # source
s.source = { :git => 'https://github.com/gizmosachin/ColorSlider.git', :tag => s.version }
+ s.source_files = 'Sources/**', 'Sources/Internal/**'
+
+ # platform
+ s.platform = :ios
s.ios.deployment_target = '9.0'
- s.source_files = 'Sources/*.swift'
+
+ # build settings
s.requires_arc = true
s.frameworks = 'Foundation', 'UIKit', 'CoreGraphics', 'QuartzCore'
end
diff --git a/ColorSlider/ColorSlider.xcodeproj/project.pbxproj b/ColorSlider/ColorSlider.xcodeproj/project.pbxproj
index 290c118..cfa8a9a 100644
--- a/ColorSlider/ColorSlider.xcodeproj/project.pbxproj
+++ b/ColorSlider/ColorSlider.xcodeproj/project.pbxproj
@@ -7,13 +7,23 @@
objects = {
/* Begin PBXBuildFile section */
- 46E735CD1C63392800B63587 /* ColorSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46E735CC1C63392800B63587 /* ColorSlider.swift */; };
+ 038C445A1F70ED57009927DD /* PreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C44531F70ED52009927DD /* PreviewView.swift */; };
+ 038C445B1F70ED57009927DD /* ColorSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C44541F70ED52009927DD /* ColorSlider.swift */; };
+ 038C445C1F70ED57009927DD /* ColorSliderExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C44561F70ED52009927DD /* ColorSliderExtensions.swift */; };
+ 038C445D1F70ED57009927DD /* HSBColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C44571F70ED52009927DD /* HSBColor.swift */; };
+ 038C445E1F70ED57009927DD /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C44581F70ED52009927DD /* GradientView.swift */; };
+ 038C445F1F70ED57009927DD /* DefaultPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038C44591F70ED52009927DD /* DefaultPreviewView.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 038C44531F70ED52009927DD /* PreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewView.swift; sourceTree = ""; };
+ 038C44541F70ED52009927DD /* ColorSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorSlider.swift; sourceTree = ""; };
+ 038C44561F70ED52009927DD /* ColorSliderExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorSliderExtensions.swift; sourceTree = ""; };
+ 038C44571F70ED52009927DD /* HSBColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HSBColor.swift; sourceTree = ""; };
+ 038C44581F70ED52009927DD /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; };
+ 038C44591F70ED52009927DD /* DefaultPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultPreviewView.swift; sourceTree = ""; };
+ 038C44601F70ED5F009927DD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
46E735C11C6338F900B63587 /* ColorSlider.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ColorSlider.framework; sourceTree = BUILT_PRODUCTS_DIR; };
- 46E735C61C6338F900B63587 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- 46E735CC1C63392800B63587 /* ColorSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ColorSlider.swift; path = ../Sources/ColorSlider.swift; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -27,29 +37,43 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
- 46E735B71C6338F900B63587 = {
+ 038C44521F70ED52009927DD /* Sources */ = {
isa = PBXGroup;
children = (
- 46E735C31C6338F900B63587 /* ColorSlider */,
- 46E735C21C6338F900B63587 /* Products */,
+ 038C44531F70ED52009927DD /* PreviewView.swift */,
+ 038C44541F70ED52009927DD /* ColorSlider.swift */,
+ 038C44551F70ED52009927DD /* Internal */,
+ 038C44581F70ED52009927DD /* GradientView.swift */,
+ 038C44591F70ED52009927DD /* DefaultPreviewView.swift */,
);
+ name = Sources;
+ path = ../Sources;
sourceTree = "";
};
- 46E735C21C6338F900B63587 /* Products */ = {
+ 038C44551F70ED52009927DD /* Internal */ = {
isa = PBXGroup;
children = (
- 46E735C11C6338F900B63587 /* ColorSlider.framework */,
+ 038C44561F70ED52009927DD /* ColorSliderExtensions.swift */,
+ 038C44571F70ED52009927DD /* HSBColor.swift */,
);
- name = Products;
+ path = Internal;
sourceTree = "";
};
- 46E735C31C6338F900B63587 /* ColorSlider */ = {
+ 46E735B71C6338F900B63587 = {
isa = PBXGroup;
children = (
- 46E735CC1C63392800B63587 /* ColorSlider.swift */,
- 46E735C61C6338F900B63587 /* Info.plist */,
+ 038C44601F70ED5F009927DD /* Info.plist */,
+ 038C44521F70ED52009927DD /* Sources */,
+ 46E735C21C6338F900B63587 /* Products */,
);
- path = ColorSlider;
+ sourceTree = "";
+ };
+ 46E735C21C6338F900B63587 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 46E735C11C6338F900B63587 /* ColorSlider.framework */,
+ );
+ name = Products;
sourceTree = "";
};
/* End PBXGroup section */
@@ -130,7 +154,12 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 46E735CD1C63392800B63587 /* ColorSlider.swift in Sources */,
+ 038C445B1F70ED57009927DD /* ColorSlider.swift in Sources */,
+ 038C445D1F70ED57009927DD /* HSBColor.swift in Sources */,
+ 038C445E1F70ED57009927DD /* GradientView.swift in Sources */,
+ 038C445F1F70ED57009927DD /* DefaultPreviewView.swift in Sources */,
+ 038C445C1F70ED57009927DD /* ColorSliderExtensions.swift in Sources */,
+ 038C445A1F70ED57009927DD /* PreviewView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Demo/ColorSliderDemo.xcodeproj/project.pbxproj b/Demo/ColorSliderDemo.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..6e04d6c
--- /dev/null
+++ b/Demo/ColorSliderDemo.xcodeproj/project.pbxproj
@@ -0,0 +1,355 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 48;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 037094841F70C3A300C76883 /* ColorSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B2991F62850100603B8C /* ColorSlider.swift */; };
+ 037094851F70C3A300C76883 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B29D1F62850100603B8C /* GradientView.swift */; };
+ 037094861F70C3A300C76883 /* PreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B2981F62850100603B8C /* PreviewView.swift */; };
+ 037094871F70C3A300C76883 /* DefaultPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B2971F62850100603B8C /* DefaultPreviewView.swift */; };
+ 037094881F70C3A300C76883 /* ColorSliderExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B29B1F62850100603B8C /* ColorSliderExtensions.swift */; };
+ 037094891F70C3A300C76883 /* HSBColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B29C1F62850100603B8C /* HSBColor.swift */; };
+ 0370948A1F70C3A300C76883 /* DemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B2A21F62853D00603B8C /* DemoView.swift */; };
+ 038FED811F70C5A30093C751 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B2A51F62853D00603B8C /* AppDelegate.swift */; };
+ 038FED821F70C5A30093C751 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0301B2A01F62853D00603B8C /* ViewController.swift */; };
+ 038FED831F70D0410093C751 /* Spark.sks in Resources */ = {isa = PBXBuildFile; fileRef = 0301B2A41F62853D00603B8C /* Spark.sks */; };
+ 038FED841F70D0440093C751 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0301B2A31F62853D00603B8C /* Assets.xcassets */; };
+ 038FED851F70D7700093C751 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0301B2A11F62853D00603B8C /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 0301B2971F62850100603B8C /* DefaultPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DefaultPreviewView.swift; path = ../Sources/DefaultPreviewView.swift; sourceTree = ""; };
+ 0301B2981F62850100603B8C /* PreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PreviewView.swift; path = ../Sources/PreviewView.swift; sourceTree = ""; };
+ 0301B2991F62850100603B8C /* ColorSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ColorSlider.swift; path = ../Sources/ColorSlider.swift; sourceTree = ""; };
+ 0301B29B1F62850100603B8C /* ColorSliderExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorSliderExtensions.swift; sourceTree = ""; };
+ 0301B29C1F62850100603B8C /* HSBColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HSBColor.swift; sourceTree = ""; };
+ 0301B29D1F62850100603B8C /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GradientView.swift; path = ../Sources/GradientView.swift; sourceTree = ""; };
+ 0301B2A01F62853D00603B8C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
+ 0301B2A11F62853D00603B8C /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; };
+ 0301B2A21F62853D00603B8C /* DemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoView.swift; sourceTree = ""; };
+ 0301B2A31F62853D00603B8C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 0301B2A41F62853D00603B8C /* Spark.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Spark.sks; sourceTree = ""; };
+ 0301B2A51F62853D00603B8C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 0301B2A61F62853D00603B8C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 037094721F70C38400C76883 /* ColorSliderDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ColorSliderDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 0370946F1F70C38400C76883 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 0301B29A1F62850100603B8C /* Internal */ = {
+ isa = PBXGroup;
+ children = (
+ 0301B29B1F62850100603B8C /* ColorSliderExtensions.swift */,
+ 0301B29C1F62850100603B8C /* HSBColor.swift */,
+ );
+ name = Internal;
+ path = ../Sources/Internal;
+ sourceTree = "";
+ };
+ 0301B29F1F62853D00603B8C /* ColorSliderDemo */ = {
+ isa = PBXGroup;
+ children = (
+ 0301B2A51F62853D00603B8C /* AppDelegate.swift */,
+ 0301B2A01F62853D00603B8C /* ViewController.swift */,
+ 0301B2A21F62853D00603B8C /* DemoView.swift */,
+ 0301B2A11F62853D00603B8C /* LaunchScreen.storyboard */,
+ 0301B2A31F62853D00603B8C /* Assets.xcassets */,
+ 0301B2A41F62853D00603B8C /* Spark.sks */,
+ 0301B2A61F62853D00603B8C /* Info.plist */,
+ );
+ path = ColorSliderDemo;
+ sourceTree = "";
+ };
+ 032B68981F624990000B26F8 = {
+ isa = PBXGroup;
+ children = (
+ 032B68B71F624A02000B26F8 /* ColorSlider */,
+ 0301B29F1F62853D00603B8C /* ColorSliderDemo */,
+ 032B68A21F624990000B26F8 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 032B68A21F624990000B26F8 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 037094721F70C38400C76883 /* ColorSliderDemo.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 032B68B71F624A02000B26F8 /* ColorSlider */ = {
+ isa = PBXGroup;
+ children = (
+ 0301B2991F62850100603B8C /* ColorSlider.swift */,
+ 0301B29D1F62850100603B8C /* GradientView.swift */,
+ 0301B2981F62850100603B8C /* PreviewView.swift */,
+ 0301B2971F62850100603B8C /* DefaultPreviewView.swift */,
+ 0301B29A1F62850100603B8C /* Internal */,
+ );
+ name = ColorSlider;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 037094711F70C38400C76883 /* ColorSliderDemo */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 037094811F70C38400C76883 /* Build configuration list for PBXNativeTarget "ColorSliderDemo" */;
+ buildPhases = (
+ 0370946E1F70C38400C76883 /* Sources */,
+ 0370946F1F70C38400C76883 /* Frameworks */,
+ 037094701F70C38400C76883 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ColorSliderDemo;
+ productName = ColorSliderDemo;
+ productReference = 037094721F70C38400C76883 /* ColorSliderDemo.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 032B68991F624990000B26F8 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastSwiftUpdateCheck = 0900;
+ LastUpgradeCheck = 0900;
+ ORGANIZATIONNAME = "Sachin Patel";
+ TargetAttributes = {
+ 037094711F70C38400C76883 = {
+ CreatedOnToolsVersion = 9.0;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 032B689C1F624990000B26F8 /* Build configuration list for PBXProject "ColorSliderDemo" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 032B68981F624990000B26F8;
+ productRefGroup = 032B68A21F624990000B26F8 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 037094711F70C38400C76883 /* ColorSliderDemo */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 037094701F70C38400C76883 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 038FED851F70D7700093C751 /* LaunchScreen.storyboard in Resources */,
+ 038FED841F70D0440093C751 /* Assets.xcassets in Resources */,
+ 038FED831F70D0410093C751 /* Spark.sks in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 0370946E1F70C38400C76883 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 038FED811F70C5A30093C751 /* AppDelegate.swift in Sources */,
+ 037094861F70C3A300C76883 /* PreviewView.swift in Sources */,
+ 037094841F70C3A300C76883 /* ColorSlider.swift in Sources */,
+ 038FED821F70C5A30093C751 /* ViewController.swift in Sources */,
+ 037094881F70C3A300C76883 /* ColorSliderExtensions.swift in Sources */,
+ 0370948A1F70C3A300C76883 /* DemoView.swift in Sources */,
+ 037094871F70C3A300C76883 /* DefaultPreviewView.swift in Sources */,
+ 037094891F70C3A300C76883 /* HSBColor.swift in Sources */,
+ 037094851F70C3A300C76883 /* GradientView.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 032B68B11F624990000B26F8 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 032B68B21F624990000B26F8 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 037094821F70C38400C76883 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 9BZNV2TE99;
+ INFOPLIST_FILE = ColorSliderDemo/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.ColorSlider.ColorSliderDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 037094831F70C38400C76883 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 9BZNV2TE99;
+ INFOPLIST_FILE = ColorSliderDemo/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = com.ColorSlider.ColorSliderDemo;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 4.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 032B689C1F624990000B26F8 /* Build configuration list for PBXProject "ColorSliderDemo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 032B68B11F624990000B26F8 /* Debug */,
+ 032B68B21F624990000B26F8 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 037094811F70C38400C76883 /* Build configuration list for PBXNativeTarget "ColorSliderDemo" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 037094821F70C38400C76883 /* Debug */,
+ 037094831F70C38400C76883 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 032B68991F624990000B26F8 /* Project object */;
+}
diff --git a/Example/Sketchpad.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Demo/ColorSliderDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
similarity index 68%
rename from Example/Sketchpad.xcodeproj/project.xcworkspace/contents.xcworkspacedata
rename to Demo/ColorSliderDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index fa70cee..8b7e127 100644
--- a/Example/Sketchpad.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/Demo/ColorSliderDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
+ location = "self:ColorSliderDemo.xcodeproj">
diff --git a/Demo/ColorSliderDemo/AppDelegate.swift b/Demo/ColorSliderDemo/AppDelegate.swift
new file mode 100644
index 0000000..a338394
--- /dev/null
+++ b/Demo/ColorSliderDemo/AppDelegate.swift
@@ -0,0 +1,45 @@
+//
+// AppDelegate.swift
+// ColorSliderDemo
+//
+// Created by Sachin Patel on 1/11/15.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import UIKit
+
+@UIApplicationMain
+class AppDelegate: UIResponder, UIApplicationDelegate {
+ var window: UIWindow?
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
+
+ window = UIWindow(frame: UIScreen.main.bounds)
+ window?.backgroundColor = UIColor.white
+ window?.rootViewController = ViewController()
+ window?.makeKeyAndVisible()
+
+ return true
+ }
+}
+
diff --git a/Demo/ColorSliderDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Demo/ColorSliderDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..d8db8d6
--- /dev/null
+++ b/Demo/ColorSliderDemo/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "20x20",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "20x20",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "76x76",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "83.5x83.5",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "size" : "1024x1024",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/Demo/ColorSliderDemo/Assets.xcassets/Contents.json b/Demo/ColorSliderDemo/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..e678bea
--- /dev/null
+++ b/Demo/ColorSliderDemo/Assets.xcassets/Contents.json
@@ -0,0 +1,9 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "compression-type" : "gpu-optimized-smallest"
+ }
+}
\ No newline at end of file
diff --git a/Example/Sketchpad/Images.xcassets/Contents.json b/Demo/ColorSliderDemo/Assets.xcassets/Particle Sprite Atlas.spriteatlas/Contents.json
similarity index 100%
rename from Example/Sketchpad/Images.xcassets/Contents.json
rename to Demo/ColorSliderDemo/Assets.xcassets/Particle Sprite Atlas.spriteatlas/Contents.json
diff --git a/Demo/ColorSliderDemo/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/Contents.json b/Demo/ColorSliderDemo/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/Contents.json
new file mode 100644
index 0000000..07311ae
--- /dev/null
+++ b/Demo/ColorSliderDemo/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "spark.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/Demo/ColorSliderDemo/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/spark.png b/Demo/ColorSliderDemo/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/spark.png
new file mode 100644
index 0000000..3383a21
Binary files /dev/null and b/Demo/ColorSliderDemo/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/spark.png differ
diff --git a/Demo/ColorSliderDemo/DemoView.swift b/Demo/ColorSliderDemo/DemoView.swift
new file mode 100644
index 0000000..b7729cb
--- /dev/null
+++ b/Demo/ColorSliderDemo/DemoView.swift
@@ -0,0 +1,126 @@
+//
+// DemoView.swift
+// ColorSliderDemo
+//
+// Created by Sachin Patel on 9/7/17.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import UIKit
+import SpriteKit
+
+class DemoView: UIView {
+ private let colorSlider: ColorSlider
+ private let label: UILabel
+
+ private var particleEmitter: SKEmitterNode?
+
+ override init(frame: CGRect) {
+ // Set up ColorSlider and label
+ colorSlider = ColorSlider(orientation: .vertical, previewSide: .left)
+ label = UILabel()
+
+ super.init(frame: frame)
+
+ backgroundColor = .black
+
+ // Only add particle emitter on device (lags on iOS simulator).
+ #if !(arch(i386) || arch(x86_64))
+ setupParticleEmitter()
+ #endif
+
+ // Set up and add the label
+ label.textColor = .white
+ label.text = "ColorSlider"
+ label.textAlignment = .center
+ label.font = UIFont.systemFont(ofSize: 100, weight: .bold)
+ label.adjustsFontSizeToFitWidth = true
+ addSubview(label)
+
+ // Observe ColorSlider events
+ colorSlider.addTarget(self, action: #selector(changedColor(slider:)), for: .valueChanged)
+ addSubview(colorSlider)
+
+ setupConstraints()
+
+ }
+
+ required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ // Set up the particle emitter in the background.
+ // This is totally unnecessary for ColorSlider but makes for a fun demo.
+ func setupParticleEmitter() {
+ let particleView = SKView()
+ guard let emitter = SKEmitterNode(fileNamed: "Spark.sks") else { return }
+
+ emitter.particleColorBlendFactor = 1
+ emitter.particleColorSequence = nil
+ emitter.particleColor = .red
+ addSubview(particleView)
+
+ let scene = SKScene(size: UIScreen.main.bounds.size)
+ scene.scaleMode = .aspectFill
+ scene.backgroundColor = .clear
+
+ emitter.position = CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.height * 0.6)
+ scene.addChild(emitter)
+ particleView.presentScene(scene)
+
+ particleView.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ particleView.leftAnchor.constraint(equalTo: leftAnchor),
+ particleView.rightAnchor.constraint(equalTo: rightAnchor),
+ particleView.topAnchor.constraint(equalTo: topAnchor),
+ particleView.bottomAnchor.constraint(equalTo: bottomAnchor),
+ ])
+
+ particleEmitter = emitter
+ }
+
+ // Set up view constraints.
+ func setupConstraints() {
+ let inset = CGFloat(30)
+ let colorSliderHeight = CGFloat(150)
+ label.translatesAutoresizingMaskIntoConstraints = false
+ colorSlider.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ colorSlider.centerXAnchor.constraint(equalTo: centerXAnchor),
+ colorSlider.bottomAnchor.constraint(equalTo: centerYAnchor),
+ colorSlider.widthAnchor.constraint(equalToConstant: 15),
+ colorSlider.heightAnchor.constraint(equalToConstant: colorSliderHeight),
+
+ label.leftAnchor.constraint(equalTo: leftAnchor, constant: inset),
+ label.rightAnchor.constraint(equalTo: rightAnchor, constant: -inset),
+ label.topAnchor.constraint(equalTo: colorSlider.bottomAnchor, constant: inset),
+ label.heightAnchor.constraint(equalToConstant: 100),
+ ])
+ }
+
+ // Observe ColorSlider .valueChanged events.
+ @objc func changedColor(slider: ColorSlider) {
+ label.textColor = slider.color
+ particleEmitter?.particleColor = slider.color
+ }
+}
diff --git a/Example/Sketchpad/Info.plist b/Demo/ColorSliderDemo/Info.plist
similarity index 64%
rename from Example/Sketchpad/Info.plist
rename to Demo/ColorSliderDemo/Info.plist
index 764f7af..6595955 100644
--- a/Example/Sketchpad/Info.plist
+++ b/Demo/ColorSliderDemo/Info.plist
@@ -3,7 +3,7 @@
CFBundleDevelopmentRegion
- en
+ $(DEVELOPMENT_LANGUAGE)CFBundleExecutable$(EXECUTABLE_NAME)CFBundleIdentifier
@@ -16,8 +16,6 @@
APPLCFBundleShortVersionString1.0
- CFBundleSignature
- ????CFBundleVersion1LSRequiresIPhoneOS
@@ -28,10 +26,24 @@
armv7
+ UIStatusBarHidden
+
+ UIStatusBarStyle
+ UIStatusBarStyleLightContentUISupportedInterfaceOrientations
- UIInterfaceOrientationPortraitUpsideDownUIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeRight
+ UIInterfaceOrientationLandscapeLeft
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+ UIViewControllerBasedStatusBarAppearance
+
diff --git a/Demo/ColorSliderDemo/LaunchScreen.storyboard b/Demo/ColorSliderDemo/LaunchScreen.storyboard
new file mode 100644
index 0000000..d9be5ac
--- /dev/null
+++ b/Demo/ColorSliderDemo/LaunchScreen.storyboard
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demo/ColorSliderDemo/Main.storyboard b/Demo/ColorSliderDemo/Main.storyboard
new file mode 100644
index 0000000..03c13c2
--- /dev/null
+++ b/Demo/ColorSliderDemo/Main.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Demo/ColorSliderDemo/Spark.sks b/Demo/ColorSliderDemo/Spark.sks
new file mode 100644
index 0000000..e639499
Binary files /dev/null and b/Demo/ColorSliderDemo/Spark.sks differ
diff --git a/Demo/ColorSliderDemo/ViewController.swift b/Demo/ColorSliderDemo/ViewController.swift
new file mode 100644
index 0000000..c80b043
--- /dev/null
+++ b/Demo/ColorSliderDemo/ViewController.swift
@@ -0,0 +1,45 @@
+//
+// ViewController.swift
+// ColorSliderDemo
+//
+// Created by Sachin Patel on 9/7/17.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import UIKit
+import SpriteKit
+
+class ViewController: UIViewController {
+ let demoView = DemoView()
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ view.addSubview(demoView)
+ }
+
+ override func viewDidLayoutSubviews() {
+ demoView.frame = view.bounds
+ }
+}
+
diff --git a/Example/Podfile b/Example/Podfile
deleted file mode 100644
index e405519..0000000
--- a/Example/Podfile
+++ /dev/null
@@ -1,7 +0,0 @@
-platform :ios, '9.0'
-use_frameworks!
-
-target 'Sketchpad' do
- pod 'ACEDrawingView'
- pod 'UIImageTrim', :git => 'https://github.com/gizmosachin/UIImageTrim'
-end
\ No newline at end of file
diff --git a/Example/Sketchpad.xcodeproj/project.pbxproj b/Example/Sketchpad.xcodeproj/project.pbxproj
deleted file mode 100644
index 9c9c059..0000000
--- a/Example/Sketchpad.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,385 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 46;
- objects = {
-
-/* Begin PBXBuildFile section */
- 0375B1DC1A638D9B00990FEB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0375B1DB1A638D9B00990FEB /* AppDelegate.swift */; };
- 0375B1DE1A638D9B00990FEB /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0375B1DD1A638D9B00990FEB /* ViewController.swift */; };
- 0375B1E31A638D9B00990FEB /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0375B1E21A638D9B00990FEB /* Images.xcassets */; };
- 0375B1E61A638D9B00990FEB /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0375B1E41A638D9B00990FEB /* LaunchScreen.xib */; };
- 0375B1FC1A63975F00990FEB /* Podfile in Resources */ = {isa = PBXBuildFile; fileRef = 0375B1FB1A63975F00990FEB /* Podfile */; };
- 03E8FAC91A64B36D00568880 /* ColorSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E8FAC81A64B36D00568880 /* ColorSlider.swift */; };
- B3FA059FD42121421A47D005 /* Pods_Sketchpad.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F34F2292575946AD409A1952 /* Pods_Sketchpad.framework */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXFileReference section */
- 0375B1D61A638D9B00990FEB /* Sketchpad.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sketchpad.app; sourceTree = BUILT_PRODUCTS_DIR; };
- 0375B1DA1A638D9B00990FEB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- 0375B1DB1A638D9B00990FEB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
- 0375B1DD1A638D9B00990FEB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
- 0375B1E21A638D9B00990FEB /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
- 0375B1E51A638D9B00990FEB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
- 0375B1FB1A63975F00990FEB /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
- 03E8FAC81A64B36D00568880 /* ColorSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ColorSlider.swift; path = ../Sources/ColorSlider.swift; sourceTree = ""; };
- 1A5645136E2A8D6CDD41E5EA /* Pods-Sketchpad.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sketchpad.release.xcconfig"; path = "Pods/Target Support Files/Pods-Sketchpad/Pods-Sketchpad.release.xcconfig"; sourceTree = ""; };
- A6B406AA89D2722ECFF61230 /* Pods-Sketchpad.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sketchpad.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Sketchpad/Pods-Sketchpad.debug.xcconfig"; sourceTree = ""; };
- F34F2292575946AD409A1952 /* Pods_Sketchpad.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Sketchpad.framework; sourceTree = BUILT_PRODUCTS_DIR; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- 0375B1D31A638D9B00990FEB /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- B3FA059FD42121421A47D005 /* Pods_Sketchpad.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- 025C06A15DADAB529C5189F3 /* Pods */ = {
- isa = PBXGroup;
- children = (
- A6B406AA89D2722ECFF61230 /* Pods-Sketchpad.debug.xcconfig */,
- 1A5645136E2A8D6CDD41E5EA /* Pods-Sketchpad.release.xcconfig */,
- );
- name = Pods;
- sourceTree = "";
- };
- 0375B1CD1A638D9B00990FEB = {
- isa = PBXGroup;
- children = (
- 0375B1FB1A63975F00990FEB /* Podfile */,
- 03E8FAC81A64B36D00568880 /* ColorSlider.swift */,
- 0375B1D81A638D9B00990FEB /* Sketchpad */,
- 0375B1D71A638D9B00990FEB /* Products */,
- 025C06A15DADAB529C5189F3 /* Pods */,
- F26A43B04CD600DDA32CABF9 /* Frameworks */,
- );
- sourceTree = "";
- };
- 0375B1D71A638D9B00990FEB /* Products */ = {
- isa = PBXGroup;
- children = (
- 0375B1D61A638D9B00990FEB /* Sketchpad.app */,
- );
- name = Products;
- sourceTree = "";
- };
- 0375B1D81A638D9B00990FEB /* Sketchpad */ = {
- isa = PBXGroup;
- children = (
- 0375B1DB1A638D9B00990FEB /* AppDelegate.swift */,
- 0375B1DD1A638D9B00990FEB /* ViewController.swift */,
- 0375B1E41A638D9B00990FEB /* LaunchScreen.xib */,
- 0375B1D91A638D9B00990FEB /* Supporting Files */,
- );
- path = Sketchpad;
- sourceTree = "";
- };
- 0375B1D91A638D9B00990FEB /* Supporting Files */ = {
- isa = PBXGroup;
- children = (
- 0375B1E21A638D9B00990FEB /* Images.xcassets */,
- 0375B1DA1A638D9B00990FEB /* Info.plist */,
- );
- name = "Supporting Files";
- sourceTree = "";
- };
- F26A43B04CD600DDA32CABF9 /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- F34F2292575946AD409A1952 /* Pods_Sketchpad.framework */,
- );
- name = Frameworks;
- sourceTree = "";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- 0375B1D51A638D9B00990FEB /* Sketchpad */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 0375B1F51A638D9B00990FEB /* Build configuration list for PBXNativeTarget "Sketchpad" */;
- buildPhases = (
- 4CDA8EFADFA8F7E520896956 /* [CP] Check Pods Manifest.lock */,
- 0375B1D21A638D9B00990FEB /* Sources */,
- 0375B1D31A638D9B00990FEB /* Frameworks */,
- 0375B1D41A638D9B00990FEB /* Resources */,
- B2EBC2DEF85C56D7F5C974E5 /* [CP] Embed Pods Frameworks */,
- 9F618A6C1054FE161B885380 /* [CP] Copy Pods Resources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = Sketchpad;
- productName = Sketchpad;
- productReference = 0375B1D61A638D9B00990FEB /* Sketchpad.app */;
- productType = "com.apple.product-type.application";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- 0375B1CE1A638D9B00990FEB /* Project object */ = {
- isa = PBXProject;
- attributes = {
- LastSwiftMigration = 0710;
- LastSwiftUpdateCheck = 0710;
- LastUpgradeCheck = 0710;
- ORGANIZATIONNAME = "Sachin Patel";
- TargetAttributes = {
- 0375B1D51A638D9B00990FEB = {
- CreatedOnToolsVersion = 6.2;
- DevelopmentTeam = 9BZNV2TE99;
- LastSwiftMigration = 0800;
- };
- };
- };
- buildConfigurationList = 0375B1D11A638D9B00990FEB /* Build configuration list for PBXProject "Sketchpad" */;
- compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- Base,
- );
- mainGroup = 0375B1CD1A638D9B00990FEB;
- productRefGroup = 0375B1D71A638D9B00990FEB /* Products */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- 0375B1D51A638D9B00990FEB /* Sketchpad */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
- 0375B1D41A638D9B00990FEB /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 0375B1E61A638D9B00990FEB /* LaunchScreen.xib in Resources */,
- 0375B1FC1A63975F00990FEB /* Podfile in Resources */,
- 0375B1E31A638D9B00990FEB /* Images.xcassets in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXShellScriptBuildPhase section */
- 4CDA8EFADFA8F7E520896956 /* [CP] Check Pods Manifest.lock */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "[CP] Check Pods Manifest.lock";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- 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";
- showEnvVarsInLog = 0;
- };
- 9F618A6C1054FE161B885380 /* [CP] Copy Pods Resources */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "[CP] Copy Pods Resources";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sketchpad/Pods-Sketchpad-resources.sh\"\n";
- showEnvVarsInLog = 0;
- };
- B2EBC2DEF85C56D7F5C974E5 /* [CP] Embed Pods Frameworks */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "[CP] Embed Pods Frameworks";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Sketchpad/Pods-Sketchpad-frameworks.sh\"\n";
- showEnvVarsInLog = 0;
- };
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
- 0375B1D21A638D9B00990FEB /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 0375B1DE1A638D9B00990FEB /* ViewController.swift in Sources */,
- 03E8FAC91A64B36D00568880 /* ColorSlider.swift in Sources */,
- 0375B1DC1A638D9B00990FEB /* AppDelegate.swift in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXVariantGroup section */
- 0375B1E41A638D9B00990FEB /* LaunchScreen.xib */ = {
- isa = PBXVariantGroup;
- children = (
- 0375B1E51A638D9B00990FEB /* Base */,
- );
- name = LaunchScreen.xib;
- sourceTree = "";
- };
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
- 0375B1F31A638D9B00990FEB /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- ENABLE_TESTABILITY = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MTL_ENABLE_DEBUG_INFO = YES;
- ONLY_ACTIVE_ARCH = YES;
- SDKROOT = iphoneos;
- SWIFT_OBJC_BRIDGING_HEADER = Sketchpad/BridgingHeader.h;
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- };
- name = Debug;
- };
- 0375B1F41A638D9B00990FEB /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = YES;
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- MTL_ENABLE_DEBUG_INFO = NO;
- SDKROOT = iphoneos;
- SWIFT_OBJC_BRIDGING_HEADER = Sketchpad/BridgingHeader.h;
- VALIDATE_PRODUCT = YES;
- };
- name = Release;
- };
- 0375B1F61A638D9B00990FEB /* Debug */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = A6B406AA89D2722ECFF61230 /* Pods-Sketchpad.debug.xcconfig */;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CODE_SIGN_IDENTITY = "iPhone Developer";
- INFOPLIST_FILE = Sketchpad/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = "com.Sketchpad.$(PRODUCT_NAME:rfc1034identifier)";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "";
- SWIFT_VERSION = 3.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- };
- name = Debug;
- };
- 0375B1F71A638D9B00990FEB /* Release */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 1A5645136E2A8D6CDD41E5EA /* Pods-Sketchpad.release.xcconfig */;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CODE_SIGN_IDENTITY = "iPhone Developer";
- INFOPLIST_FILE = Sketchpad/Info.plist;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
- PRODUCT_BUNDLE_IDENTIFIER = "com.Sketchpad.$(PRODUCT_NAME:rfc1034identifier)";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "";
- SWIFT_VERSION = 3.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- 0375B1D11A638D9B00990FEB /* Build configuration list for PBXProject "Sketchpad" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 0375B1F31A638D9B00990FEB /* Debug */,
- 0375B1F41A638D9B00990FEB /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 0375B1F51A638D9B00990FEB /* Build configuration list for PBXNativeTarget "Sketchpad" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 0375B1F61A638D9B00990FEB /* Debug */,
- 0375B1F71A638D9B00990FEB /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = 0375B1CE1A638D9B00990FEB /* Project object */;
-}
diff --git a/Example/Sketchpad.xcodeproj/project.xcworkspace/xcshareddata/Sketchpad.xccheckout b/Example/Sketchpad.xcodeproj/project.xcworkspace/xcshareddata/Sketchpad.xccheckout
deleted file mode 100644
index a8bff45..0000000
--- a/Example/Sketchpad.xcodeproj/project.xcworkspace/xcshareddata/Sketchpad.xccheckout
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- IDESourceControlProjectFavoriteDictionaryKey
-
- IDESourceControlProjectIdentifier
- 4A257750-8538-42EA-A5DF-24B284C1F7D0
- IDESourceControlProjectName
- Sketchpad
- IDESourceControlProjectOriginsDictionary
-
- 7DF1354BDEC82B3B6861FD9E52F31A8F3147D3CA
- github.com:gizmosachin/ColorSlider.git
-
- IDESourceControlProjectPath
- Project/Sketchpad.xcodeproj
- IDESourceControlProjectRelativeInstallPathDictionary
-
- 7DF1354BDEC82B3B6861FD9E52F31A8F3147D3CA
- ../../..
-
- IDESourceControlProjectURL
- github.com:gizmosachin/ColorSlider.git
- IDESourceControlProjectVersion
- 111
- IDESourceControlProjectWCCIdentifier
- 7DF1354BDEC82B3B6861FD9E52F31A8F3147D3CA
- IDESourceControlProjectWCConfigurations
-
-
- IDESourceControlRepositoryExtensionIdentifierKey
- public.vcs.git
- IDESourceControlWCCIdentifierKey
- 7DF1354BDEC82B3B6861FD9E52F31A8F3147D3CA
- IDESourceControlWCCName
- ColorSlider
-
-
-
-
diff --git a/Example/Sketchpad.xcworkspace/contents.xcworkspacedata b/Example/Sketchpad.xcworkspace/contents.xcworkspacedata
deleted file mode 100644
index 9737a27..0000000
--- a/Example/Sketchpad.xcworkspace/contents.xcworkspacedata
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/Example/Sketchpad.xcworkspace/xcshareddata/Sketchpad.xccheckout b/Example/Sketchpad.xcworkspace/xcshareddata/Sketchpad.xccheckout
deleted file mode 100644
index 676cfda..0000000
--- a/Example/Sketchpad.xcworkspace/xcshareddata/Sketchpad.xccheckout
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
- IDESourceControlProjectFavoriteDictionaryKey
-
- IDESourceControlProjectIdentifier
- 085FCC32-1EF7-43DB-A5F6-33733D36F30A
- IDESourceControlProjectName
- Sketchpad
- IDESourceControlProjectOriginsDictionary
-
- 7DF1354BDEC82B3B6861FD9E52F31A8F3147D3CA
- github.com:gizmosachin/ColorSlider.git
-
- IDESourceControlProjectPath
- Project/Sketchpad.xcworkspace
- IDESourceControlProjectRelativeInstallPathDictionary
-
- 7DF1354BDEC82B3B6861FD9E52F31A8F3147D3CA
- ../..
-
- IDESourceControlProjectURL
- github.com:gizmosachin/ColorSlider.git
- IDESourceControlProjectVersion
- 111
- IDESourceControlProjectWCCIdentifier
- 7DF1354BDEC82B3B6861FD9E52F31A8F3147D3CA
- IDESourceControlProjectWCConfigurations
-
-
- IDESourceControlRepositoryExtensionIdentifierKey
- public.vcs.git
- IDESourceControlWCCIdentifierKey
- 7DF1354BDEC82B3B6861FD9E52F31A8F3147D3CA
- IDESourceControlWCCName
- ColorSlider
-
-
-
-
diff --git a/Example/Sketchpad/AppDelegate.swift b/Example/Sketchpad/AppDelegate.swift
deleted file mode 100644
index 5e92842..0000000
--- a/Example/Sketchpad/AppDelegate.swift
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// AppDelegate.swift
-// Sketchpad
-//
-// Created by Sachin Patel on 1/11/15.
-//
-// The MIT License (MIT)
-//
-// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-import UIKit
-
-@UIApplicationMain
-class AppDelegate: UIResponder, UIApplicationDelegate {
-
- var window: UIWindow?
-
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
- window = UIWindow(frame: UIScreen.main.bounds)
- window?.backgroundColor = UIColor.white
- window?.rootViewController = ViewController()
- window?.makeKeyAndVisible()
-
- return true
- }
-
- func applicationWillResignActive(_ application: UIApplication) {
- // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
- // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
- }
-
- func applicationDidEnterBackground(_ application: UIApplication) {
- // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
- // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
- }
-
- func applicationWillEnterForeground(_ application: UIApplication) {
- // 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.
- }
-
- func applicationDidBecomeActive(_ application: UIApplication) {
- // 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.
- }
-
- func applicationWillTerminate(_ application: UIApplication) {
- // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
- }
-}
-
diff --git a/Example/Sketchpad/Base.lproj/LaunchScreen.xib b/Example/Sketchpad/Base.lproj/LaunchScreen.xib
deleted file mode 100644
index 51fb384..0000000
--- a/Example/Sketchpad/Base.lproj/LaunchScreen.xib
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Example/Sketchpad/Images.xcassets/AppIcon.appiconset/Contents.json b/Example/Sketchpad/Images.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index 118c98f..0000000
--- a/Example/Sketchpad/Images.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "scale" : "3x"
- },
- {
- "idiom" : "iphone",
- "size" : "40x40",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "40x40",
- "scale" : "3x"
- },
- {
- "idiom" : "iphone",
- "size" : "60x60",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "60x60",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/Example/Sketchpad/ViewController.swift b/Example/Sketchpad/ViewController.swift
deleted file mode 100644
index 8848566..0000000
--- a/Example/Sketchpad/ViewController.swift
+++ /dev/null
@@ -1,163 +0,0 @@
-//
-// ViewController.swift
-// Sketchpad
-//
-// Created by Sachin Patel on 1/11/15.
-//
-// The MIT License (MIT)
-//
-// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-import UIKit
-import ACEDrawingView
-import UIImageTrim
-
-class ViewController: UIViewController, ACEDrawingViewDelegate {
- let drawingView: ACEDrawingView
- let colorSlider: ColorSlider
-
- let toolbar: UIToolbar
- var undoItem: UIBarButtonItem
- var shareItem: UIBarButtonItem
- let selectedColorView: UIView
- let selectedColorItem: UIBarButtonItem
-
- override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
- drawingView = ACEDrawingView()
- colorSlider = ColorSlider()
-
- toolbar = UIToolbar()
- undoItem = UIBarButtonItem()
- shareItem = UIBarButtonItem()
- selectedColorView = UIView()
- selectedColorItem = UIBarButtonItem(customView: selectedColorView)
-
- super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
- commonInit()
- }
-
- required init?(coder aDecoder: NSCoder) {
- fatalError("init(coder:) is not supported")
- }
-
- func commonInit() {
- drawingView.delegate = self
- drawingView.lineWidth = 3.0
- view.addSubview(drawingView)
-
- colorSlider.previewEnabled = true
- colorSlider.orientation = .vertical
- colorSlider.addTarget(self, action: #selector(ViewController.willChangeColor(_:)), for: .touchDown)
- colorSlider.addTarget(self, action: #selector(ViewController.isChangingColor(_:)), for: .valueChanged)
- colorSlider.addTarget(self, action: #selector(ViewController.didChangeColor(_:)), for: .touchUpOutside)
- colorSlider.addTarget(self, action: #selector(ViewController.didChangeColor(_:)), for: .touchUpInside)
- view.addSubview(colorSlider)
-
- undoItem = UIBarButtonItem(title: "Undo", style: .plain, target: self, action: #selector(ViewController.undo))
- shareItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(ViewController.share))
-
- let flexibleSpacingItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
- undoItem.isEnabled = false
- selectedColorView.backgroundColor = UIColor.black
- selectedColorItem.width = 30
- toolbar.items = [undoItem, flexibleSpacingItem, selectedColorItem, flexibleSpacingItem, shareItem]
- view.addSubview(toolbar)
- }
-
- override func viewDidLoad() {
- super.viewDidLoad()
- }
-
- override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
-
- let colorSliderWidth = CGFloat(12)
- let colorSliderHeight = CGFloat(150)
- let colorSliderPadding = CGFloat(15)
- drawingView.frame = view.bounds
- colorSlider.frame = CGRect(x: view.bounds.width - colorSliderWidth - colorSliderPadding, y: 20 + colorSliderPadding, width: colorSliderWidth, height: colorSliderHeight)
- toolbar.frame = CGRect(x: 0, y: view.bounds.height - 44, width: view.bounds.width, height: 44)
-
- selectedColorView.frame = CGRect(x: 0, y: 0, width: selectedColorItem.width, height: selectedColorItem.width)
- selectedColorView.layer.cornerRadius = selectedColorView.frame.width / 2.0
- selectedColorView.layer.borderColor = UIColor.black.withAlphaComponent(0.3).cgColor
- selectedColorView.layer.borderWidth = 1.0
- selectedColorView.clipsToBounds = true
- }
-
- override func didReceiveMemoryWarning() {
- super.didReceiveMemoryWarning()
- // Dispose of any resources that can be recreated.
- }
-
-
- // MARK: - ColorSlider Events
- func willChangeColor(_ slider: ColorSlider) {
- drawingView.isUserInteractionEnabled = false
- }
-
- func isChangingColor(_ slider: ColorSlider) {
- // Respond to a change in color.
- }
-
- func didChangeColor(_ slider: ColorSlider) {
- updateColorViews(slider.color)
- drawingView.isUserInteractionEnabled = true
- }
-
- func updateColorViews(_ color: UIColor) {
- selectedColorView.backgroundColor = color
- drawingView.lineColor = color
- }
-
-
- // MARK: - ACEDrawingView Delegate
- func drawingView(_ view: ACEDrawingView, didEndDrawUsingTool tool: AnyObject) {
- updateButtons()
- }
-
- // MARK: - Actions
- func undo() {
- drawingView.undoLatestStep()
- updateButtons()
- }
-
- func updateButtons() {
- undoItem.isEnabled = drawingView.canUndo()
- shareItem.isEnabled = drawingView.canUndo()
- }
-
- func share() {
- let trimmedImage = drawingView.image.trimmingTransparentPixels()
- let controller = UIActivityViewController(activityItems: [trimmedImage!], applicationActivities: nil)
- controller.completionWithItemsHandler = {
- activityType, completed, returnedItems, activityError in
- if completed {
- self.drawingView.clear()
- self.drawingView.lineColor = UIColor.black
- self.selectedColorView.backgroundColor = UIColor.black
- self.updateButtons()
- }
- }
- controller.popoverPresentationController?.barButtonItem = shareItem
- present(controller, animated: true, completion: nil)
- }
-}
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..09f9766
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org' do
+ gem 'cocoapods', '~> 1.3.1'
+end
\ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..b1299b0
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,72 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ CFPropertyList (2.3.5)
+ activesupport (4.2.9)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ claide (1.0.2)
+ cocoapods (1.3.1)
+ activesupport (>= 4.0.2, < 5)
+ claide (>= 1.0.2, < 2.0)
+ cocoapods-core (= 1.3.1)
+ cocoapods-deintegrate (>= 1.0.1, < 2.0)
+ cocoapods-downloader (>= 1.1.3, < 2.0)
+ cocoapods-plugins (>= 1.0.0, < 2.0)
+ cocoapods-search (>= 1.0.0, < 2.0)
+ cocoapods-stats (>= 1.0.0, < 2.0)
+ cocoapods-trunk (>= 1.2.0, < 2.0)
+ cocoapods-try (>= 1.1.0, < 2.0)
+ colored2 (~> 3.1)
+ escape (~> 0.0.4)
+ fourflusher (~> 2.0.1)
+ gh_inspector (~> 1.0)
+ molinillo (~> 0.5.7)
+ nap (~> 1.0)
+ ruby-macho (~> 1.1)
+ xcodeproj (>= 1.5.1, < 2.0)
+ cocoapods-core (1.3.1)
+ activesupport (>= 4.0.2, < 6)
+ fuzzy_match (~> 2.0.4)
+ nap (~> 1.0)
+ cocoapods-deintegrate (1.0.1)
+ cocoapods-downloader (1.1.3)
+ cocoapods-plugins (1.0.0)
+ nap
+ cocoapods-search (1.0.0)
+ cocoapods-stats (1.0.0)
+ cocoapods-trunk (1.2.0)
+ nap (>= 0.8, < 2.0)
+ netrc (= 0.7.8)
+ cocoapods-try (1.1.0)
+ colored2 (3.1.2)
+ escape (0.0.4)
+ fourflusher (2.0.1)
+ fuzzy_match (2.0.4)
+ gh_inspector (1.0.3)
+ i18n (0.8.6)
+ minitest (5.10.3)
+ molinillo (0.5.7)
+ nanaimo (0.2.3)
+ nap (1.1.0)
+ netrc (0.7.8)
+ ruby-macho (1.1.0)
+ thread_safe (0.3.6)
+ tzinfo (1.2.3)
+ thread_safe (~> 0.1)
+ xcodeproj (1.5.1)
+ CFPropertyList (~> 2.3.3)
+ claide (>= 1.0.2, < 2.0)
+ colored2 (~> 3.1)
+ nanaimo (~> 0.2.3)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ cocoapods (~> 1.3.1)!
+
+BUNDLED WITH
+ 1.15.4
diff --git a/LICENSE.txt b/LICENSE
similarity index 100%
rename from LICENSE.txt
rename to LICENSE
diff --git a/Package.swift b/Package.swift
deleted file mode 100644
index 1e9bd98..0000000
--- a/Package.swift
+++ /dev/null
@@ -1,5 +0,0 @@
-import PackageDescription
-
-let package = Package(
- name: "ColorSlider"
-)
diff --git a/README.md b/README.md
index c477e24..5abb645 100644
--- a/README.md
+++ b/README.md
@@ -1,44 +1,37 @@
-# ColorSlider
+
+
+
-ColorSlider is a [Swift](https://developer.apple.com/swift/) color picker with a live preview.
+---
-Inspired by Snapchat, ColorSlider lets you drag vertically to pick a range of colors and drag to the edges of the superview to select black and white. You can configure and customize `ColorSlider` via a simple API, and receive callbacks via `UIControlEvents`.
+ColorSlider is an iOS color picker with live preview written in [Swift](https://developer.apple.com/swift/).
-![ColorSlider](https://raw.githubusercontent.com/gizmosachin/ColorSlider/master/ColorSlider.gif)
+[![Build Status](https://travis-ci.org/gizmosachin/ColorSlider.svg?branch=master)](https://travis-ci.org/gizmosachin/ColorSlider) ![Pod Version](https://img.shields.io/cocoapods/v/ColorSlider.svg) [![Swift Version](https://img.shields.io/badge/language-swift%204.0-brightgreen.svg)](https://developer.apple.com/swift) [![GitHub license](https://img.shields.io/badge/license-MIT-lightgrey.svg)](LICENSE)
-![Pod Version](https://img.shields.io/cocoapods/v/ColorSlider.svg) [![Build Status](https://travis-ci.org/gizmosachin/ColorSlider.svg?branch=master)](https://travis-ci.org/gizmosachin/ColorSlider)
-
-## Version Compatibility
-
-Current Swift compatibility breakdown:
-
-| Swift Version | Framework Version |
-| ------------- | ----------------- |
-| 3.0 | master |
-| 2.3 | 2.5.1 |
+| | Features |
+| :-------: | :--------------------------------------- |
+| :ghost: | "[Snapchat](http://snapchat.com)-style" color picker |
+| :rainbow: | Extensible live preview |
+| :art: | Customizable appearance |
+| :cyclone: | Vertical and horizontal support |
+| :musical_keyboard: | Black and white colors included |
+| :books: | Fully [documented](http://gizmosachin.github.io/ColorSlider) |
+| :baby_chick: | [Swift 4](https://developer.apple.com/swift/) |
## Usage
-Create and add an instance of ColorSlider to your view hierarchy.
+Create and add a ColorSlider to your view:
``` Swift
-let colorSlider = ColorSlider()
+let colorSlider = ColorSlider(orientation: .vertical, previewSide: .left)
colorSlider.frame = CGRectMake(0, 0, 12, 150)
view.addSubview(colorSlider)
```
-ColorSlider is a subclass of `UIControl` and supports the following `UIControlEvents`:
-
-- `.touchDown`
-- `.valueChanged`
-- `.touchUpInside`
-- `.touchUpOutside`
-- `.touchCancel`
-
-You can get the currently selected color with the `color` property.
+Respond to changes in color using `UIControlEvents`:
``` Swift
-colorSlider.addTarget(self, action: #selector(ViewController.changedColor(_:)), forControlEvents: .valueChanged)
+colorSlider.addTarget(self, action: #selector(changedColor(_:)), forControlEvents: .valueChanged)
func changedColor(_ slider: ColorSlider) {
var color = slider.color
@@ -46,83 +39,82 @@ func changedColor(_ slider: ColorSlider) {
}
```
-Enable live color preview:
+Customize appearance attributes:
+
+``` Swift
+// Add a border
+colorSlider.gradientView.layer.borderWidth = 2.0
+colorSlider.gradientView.layer.borderColor = UIColor.white
-``` swift
-colorSlider.previewEnabled = true
+// Disable rounded corners
+colorSlider.gradientView.automaticallyAdjustsCornerRadius = false
```
-Use a horizontal slider:
+### Preview
+
+`ColorSlider` has a live preview that tracks touches along it. You can customize it:
-```swift
-colorSlider.orientation = .horizontal
+``` Swift
+let previewView = ColorSlider.DefaultPreviewView()
+previewView.side = .right
+previewView.animationDuration = 0.2
+previewView.offsetAmount = 50
+
+let colorSlider = ColorSlider(orientation: .vertical, previewView: previewView)
```
-Customize appearance attributes:
+Create your own live preview by subclassing `DefaultPreviewView` or implementing `ColorSliderPreviewing` in your `UIView` subclass.
+Then, just pass your preview instance to the initializer:
+``` Swift
+let customPreviewView = MyCustomPreviewView()
+let colorSlider = ColorSlider(orientation: .vertical, previewView: customPreviewView)
+```
+ColorSlider will automatically update your view's `center` as touches move on the slider.
+By default, it'll also resize your preview automatically. Set `colorSlider.autoresizesSubviews` to `false` to disable autoresizing.
+To disable the preview, simply pass `nil` to ColorSlider's initializer:
``` Swift
-colorSlider.borderWidth = 2.0
-colorSlider.borderColor = UIColor.white
+let colorSlider = ColorSlider(orientation: .vertical, previewView: nil)
```
-[Please see the documentation](http://gizmosachin.github.io/ColorSlider/) and check out the sample app (Sketchpad) for more details.
+See the [documentation](http://gizmosachin.github.io/ColorSlider) for more details on custom previews.
-## Installation
+### Documentation
-### CocoaPods
+ColorSlider is fully documented [here](http://gizmosachin.github.io/ColorSlider).
+
+## Installation
-ColorSlider is available for installation using [CocoaPods](http://cocoapods.org/). To integrate, add the following to your Podfile`:
+### [CocoaPods](https://cocoapods.org/)
``` ruby
platform :ios, '9.0'
-use_frameworks!
-
-pod 'ColorSlider', '~> 3.0.1'
+pod 'ColorSlider', '~> 4.0'
```
-### Carthage
-
-ColorSlider is also available for installation using [Carthage](https://github.com/Carthage/Carthage). To integrate, add the following to your `Cartfile`:
+### [Carthage](https://github.com/Carthage/Carthage)
``` odgl
-github "gizmosachin/ColorSlider" >= 3.0.1
-```
-
-### Swift Package Manager
-
-ColorSlider is also available for installation using the [Swift Package Manager](https://swift.org/package-manager/). Add the following to your `Package.swift`:
-
-``` swift
-import PackageDescription
-
-let package = Package(
- name: "MyProject",
- dependencies: [
- .Package(url: "https://github.com/gizmosachin/ColorSlider.git", majorVersion: 0),
- ]
-)
+github "gizmosachin/ColorSlider" >= 4.0
```
-### Manual
-
-You can also simply copy `ColorSlider.swift` into your Xcode project.
-
-## Example Project
+## Version Compatibility
-ColorSlider comes with an example project called Sketchpad, a simple drawing app. To try it, install [CocoaPods](http://cocoapods.org/) and run `pod install` under the `Example` directory. Then, open `Sketchpad.xcworkspace`.
+| Swift Version | Framework Version |
+| ------------- | ----------------- |
+| 4.0 | master |
+| 3.0 | 3.0.1 |
-## How it Works
+## Demo
-ColorSlider uses [HSB](https://en.wikipedia.org/wiki/HSB) and defaults to a saturation and brightness: 100%.
+Please see the `Demo` directory for a basic iOS project that uses `ColorSlider`.
-When the `orientation` is set to `.vertical`, dragging vertically adjusts the hue, and dragging outside adjusts the saturation and brightness as follows:
+## Contributing
-- Inside the frame, dragging vertically adjusts the hue
-- Outside the frame, dragging horizontally adjusts the saturation
-- Outside the frame, dragging vertically adjusts the brightness
+ColorSlider is a community - contributions and discussions are welcome!
-Adjusting the brightness lets you select black and white by first dragging on the slider, then moving your finger outside the frame to the top left (to select white) or bottom left (to select black) of the superview.
+Please read the [contributing guidelines](Contributing.md) prior to submitting a Pull Request.
## License
-ColorSlider is available under the MIT license, see the [LICENSE](https://github.com/gizmosachin/ColorSlider/blob/master/LICENSE) file for more information.
+ColorSlider is available under the MIT license, see the [LICENSE](LICENSE) file for more information.
diff --git a/Sources/ColorSlider.swift b/Sources/ColorSlider.swift
index ee4aa62..5a341ae 100644
--- a/Sources/ColorSlider.swift
+++ b/Sources/ColorSlider.swift
@@ -6,17 +6,17 @@
// The MIT License (MIT)
//
// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
-//
+//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
-//
+//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
-//
+//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -26,322 +26,298 @@
// SOFTWARE.
import UIKit
-import Foundation
-import CoreGraphics
-/// The main ColorSlider class.
-@IBDesignable final public class ColorSlider: UIControl {
- /// The current color of the `ColorSlider`.
- public var color: UIColor {
- return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1)
- }
-
- // MARK: Customization
- /// The display orientation of the `ColorSlider`.
- public enum Orientation {
- /// Displays `ColorSlider` vertically.
- case vertical
-
- /// Displays `ColorSlider` horizontally.
- case horizontal
- }
-
- /// The orientation of the `ColorSlider`. Defaults to `.Vertical`.
- public var orientation: Orientation = .vertical {
- didSet {
- switch orientation {
- case .vertical:
- drawLayer.startPoint = CGPoint(x: 0.5, y: 1)
- drawLayer.endPoint = CGPoint(x: 0.5, y: 0)
- case .horizontal:
- drawLayer.startPoint = CGPoint(x: 0, y: 0.5)
- drawLayer.endPoint = CGPoint(x: 1, y: 0.5)
- }
- }
- }
+/// The orientation in which the `ColorSlider` is drawn.
+public enum Orientation {
+ /// The horizontal orientation.
+ case horizontal
- /// A boolean value that determines whether or not a color preview is shown while dragging.
- @IBInspectable public var previewEnabled: Bool = false
-
- /// The width of the ColorSlider's border.
- @IBInspectable public var borderWidth: CGFloat = 1.0 {
- didSet {
- drawLayer.borderWidth = borderWidth
+ /// The vertical orientation.
+ case vertical
+}
+
+///
+/// ColorSlider is a customizable color picker with live preview.
+///
+/// Inspired by Snapchat, ColorSlider lets you drag to select black, white, or any color in between.
+/// Customize `ColorSlider` and its preview via a simple API, and receive callbacks via `UIControlEvents`.
+///
+/// Use the convenience initializer to create a `.vertical` ColorSlider with a live preview that appears to the `.left` of it:
+/// ```swift
+/// let colorSlider = ColorSlider(orientation: .vertical, previewSide: .left)
+/// ```
+///
+/// You can create a custom preview view using the `ColorSliderPreviewing` protocol, or by subclassing `DefaultPreviewView`.
+/// To pass in a custom preview view, simply use the default initializer instead:
+/// ```swift
+/// let myPreviewView = MyPreviewView()
+/// let colorSlider = ColorSlider(orientation: .vertical, previewView: myPreviewView)
+/// ```
+///
+/// ColorSlider is a `UIControl` subclass and fully supports the following `UIControlEvents`:
+/// * `.valueChanged`
+/// * `.touchDown`
+/// * `.touchUpInside`
+/// * `.touchUpOutside`
+/// * `.touchCancel`
+///
+/// Once adding your class as a target, you can get callbacks via the `color` property:
+/// ```swift
+/// colorSlider.addTarget(self, action: #selector(ViewController.changedColor(_:)), forControlEvents: .valueChanged)
+///
+/// func changedColor(_ slider: ColorSlider) {
+/// var color = slider.color
+/// // ...
+/// }
+/// ```
+///
+/// Customize the appearance of ColorSlider by setting properties on the `gradientView`:
+/// ```swift
+/// // Add a border
+/// colorSlider.gradientView.layer.borderWidth = 2.0
+/// colorSlider.gradientView.layer.borderColor = UIColor.white
+///
+/// // Disable rounded corners
+/// colorSlider.gradientView.automaticallyAdjustsCornerRadius = false
+/// ```
+///
+/// ColorSlider uses the [HSB](https://en.wikipedia.org/wiki/HSL_and_HSV) color standard internally.
+/// You can set the `saturation` of your ColorSlider's `gradientView` to change the saturation of colors on the slider.
+/// See the `GradientView` and `HSBColor` for more details on how colors are calculated.
+///
+
+public class ColorSlider: UIControl {
+ /// The selected color.
+ public var color: UIColor {
+ get {
+ return UIColor(hsbColor: internalColor)
}
- }
-
- /// The color of the ColorSlider's border.
- @IBInspectable public var borderColor: UIColor = UIColor.black {
- didSet {
- drawLayer.borderColor = borderColor.cgColor
+ set {
+ internalColor = HSBColor(color: newValue)
+ let sliderProgress = gradientView.calculateSliderProgress(for: internalColor)
+
+ // `centerPreview` only uses the `x` or `y` value based on the `orientation` and ignores the other value.
+ centerPreview(at: CGPoint(x: sliderProgress * bounds.width, y: sliderProgress * bounds.height))
+
+ previewView?.colorChanged(to: color)
+ previewView?.transition(to: .inactive)
+
+ sendActions(for: .valueChanged)
}
}
- /// The corner radius of the ColorSlider.
- /// seealso: setsCornerRadiusAutomatically
- @IBInspectable public var cornerRadius: CGFloat = 0.0 {
- didSet {
- updateCornerRadius()
- }
- }
-
- /// Whether the slider should automatically adjust its corner radius.
- /// When this value is `true`, `cornerRadius` is ignored.
- /// When this value is `false`, the `cornerRadius` is used.
- @IBInspectable public var setsCornerRadiusAutomatically: Bool = true {
- didSet {
- updateCornerRadius()
- }
- }
-
- // MARK: Internal
- /// Internal `CAGradientLayer` used for drawing the `ColorSlider`.
- private lazy var drawLayer: CAGradientLayer = {
- let drawLayer = CAGradientLayer()
- self.layer.insertSublayer(drawLayer, at: 0)
- return drawLayer
- }()
-
- /// The hue of the current color.
- private var hue: CGFloat = 0
+ /// The background gradient view.
+ public let gradientView: GradientView
- /// The saturation of the current color.
- private var saturation: CGFloat = 1
+ /// The preview view, passed in the required initializer.
+ public let previewView: PreviewView?
- /// The brightness of the current color.
- private var brightness: CGFloat = 1
+ /// The layout orientation of the slider, as defined in the required initializer.
+ internal let orientation: Orientation
- // MARK: Preview view
- /// The color preview view. Only shown if `previewEnabled` is set to `true`.
- private var previewView: UIView = UIView()
+ /// The internal HSBColor representation of `color`.
+ internal var internalColor: HSBColor
- /// The edge length of the preview view.
- private let previewDimension: CGFloat = 30
+ // Obsolete properties
+ @available(*, obsoleted: 4.0, message: "A preview is now enabled by default, pass a `nil` preview to the initializer to disable it")
+ public var previewEnabled: Bool = true
- /// The amount that the `previewView` is drawn away from the `ColorSlider` bar.
- private let previewOffset: CGFloat = 44
+ @available(*, obsoleted: 4.0, message: "Use layer.borderWidth instead")
+ public var borderWidth: CGFloat = 0
- /// The duration of the preview show or hide animation.
- private let previewAnimationDuration: TimeInterval = 0.10
+ @available(*, obsoleted: 4.0, message: "Use layer.borderColor instead")
+ public var borderColor: UIColor = .white
- // MARK: - Initializers
- /// Creates a `ColorSlider` with a frame of `CGRect.zero`.
- public init() {
- super.init(frame: CGRect.zero)
- commonInit()
- }
+ @available(*, obsoleted: 4.0, message: "Use gradientView.layer.cornerRadius")
+ public var cornerRadius: CGFloat = 0
- /// Creates a `ColorSlider` with a frame of `frame`.
- public override init(frame: CGRect) {
- super.init(frame: frame)
- commonInit()
+ @available(*, obsoleted: 4.0, message: "Use gradientView.automaticallyAdjustsCornerRadius instead")
+ public var setsCornerRadiusAutomatically: Bool = true
+
+ @available(*, obsoleted: 4.0, message: "init(coder:) and Interface Builder support have been removed, use init(orientation:)")
+ required public init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) and storyboard support have been removed, use init(orientation:)")
}
- /// Creates a `ColorSlider` from Interface Builder.
- public required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- commonInit()
- }
+ // MARK: - Init
- /// Sets up internal views.
- public func commonInit() {
- backgroundColor = UIColor.clear
-
- drawLayer.frame = layer.bounds
- drawLayer.masksToBounds = true
- drawLayer.borderColor = borderColor.cgColor
- drawLayer.borderWidth = borderWidth
- drawLayer.startPoint = CGPoint(x: 0.5, y: 1)
- drawLayer.endPoint = CGPoint(x: 0.5, y: 0)
- updateCornerRadius()
-
- // Draw gradient
- let hues: [CGFloat] = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
- drawLayer.locations = hues.map({ (hue) -> NSNumber in
- return NSNumber(floatLiteral: Double(hue))
- })
- drawLayer.colors = hues.map({ (hue) -> CGColor in
- return UIColor(hue: hue, saturation: 1, brightness: 1, alpha: 1).cgColor
- })
+ /// - parameter orientation: The orientation of the ColorSlider.
+ /// - parameter side: The side of the ColorSlider on which to anchor the live preview.
+ convenience init(orientation: Orientation = .vertical, previewSide side: DefaultPreviewView.Side = .left) {
+ // Check to ensure the side is valid for the given orientation
+ switch orientation {
+ case .horizontal:
+ assert(side == .top || side == .bottom, "The preview must be on the top or bottom for orientation \(orientation).")
+ case .vertical:
+ assert(side == .left || side == .right, "The preview must be on the left or right for orientation \(orientation).")
+ }
- previewView.clipsToBounds = true
- previewView.layer.cornerRadius = previewDimension / 2
- previewView.layer.borderColor = UIColor.black.withAlphaComponent(0.3).cgColor
- previewView.layer.borderWidth = 1.0
+ // Create the preview view
+ let previewView = DefaultPreviewView(side: side)
+ self.init(orientation: orientation, previewView: previewView)
}
- // MARK: - UIControl
- /// Begins tracking a touch when the user drags on the `ColorSlider`.
- public override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
- super.beginTracking(touch, with: event)
+ /// - parameter orientation: The orientation of the ColorSlider.
+ /// - parameter previewView: An optional preview view that stays anchored to the slider. See ColorSliderPreviewing.
+ required public init(orientation: Orientation, previewView: PreviewView?) {
+ self.orientation = orientation
+ self.previewView = previewView
- // Reset saturation and brightness
- saturation = 1.0
- brightness = 1.0
+ gradientView = GradientView(orientation: orientation)
+ internalColor = HSBColor(hue: 0, saturation: gradientView.saturation, brightness: 1)
- updateForTouch(touch, touchInside: true)
+ super.init(frame: .zero)
- showPreview(touch)
-
- sendActions(for: .touchDown)
- return true
- }
-
- /// Continues tracking a touch as the user drags on the `ColorSlider`.
- public override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
- super.continueTracking(touch, with: event)
-
- updateForTouch(touch, touchInside: isTouchInside)
+ addSubview(gradientView)
- updatePreview(touch)
-
- sendActions(for: .valueChanged)
- return true
- }
-
- /// Ends tracking a touch when the user finishes dragging on the `ColorSlider`.
- public override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
- super.endTracking(touch, with: event)
-
- guard let endTouch = touch else { return }
- updateForTouch(endTouch, touchInside: isTouchInside)
+ if let currentPreviewView = previewView {
+ currentPreviewView.isUserInteractionEnabled = false
+ addSubview(currentPreviewView)
+ }
+ }
+}
+
+/// :nodoc:
+// MARK: - Layout
+extension ColorSlider {
+ public override func layoutSubviews() {
+ super.layoutSubviews()
- removePreview()
+ gradientView.frame = bounds
- sendActions(for: isTouchInside ? .touchUpInside : .touchUpOutside)
- }
-
- /// Cancels tracking a touch when the user cancels dragging on the `ColorSlider`.
- public override func cancelTracking(with event: UIEvent?) {
- sendActions(for: .touchCancel)
- }
-
- // MARK: -
- /// Updates the `ColorSlider` color.
- ///
- /// - parameter touch: The touch that triggered the update.
- /// - parameter touchInside: A boolean value that is `true` if `touch` was inside the frame of the `ColorSlider`.
- private func updateForTouch(_ touch: UITouch, touchInside: Bool) {
- if touchInside {
- // Modify hue at constant brightness
- let locationInView = touch.location(in: self)
-
- // Calculate based on orientation
- if orientation == .vertical {
- hue = 1 - max(0, min(1, (locationInView.y / frame.height)))
- } else {
- hue = max(0, min(1, (locationInView.x / frame.width)))
- }
- brightness = 1
-
- } else {
- // Modify saturation and brightness for the current hue
- guard let _superview = superview else { return }
- let locationInSuperview = touch.location(in: _superview)
- let horizontalPercent = max(0, min(1, (locationInSuperview.x / _superview.frame.width)))
- let verticalPercent = max(0, min(1, (locationInSuperview.y / _superview.frame.height)))
-
- // Calculate based on orientation
- if orientation == .vertical {
- saturation = horizontalPercent
- brightness = 1 - verticalPercent
- } else {
- saturation = verticalPercent
- brightness = 1 - horizontalPercent
+ if let preview = previewView {
+ switch orientation {
+
+ // Set default preview center
+ case .horizontal where preview.center.y != bounds.midY,
+ .vertical where preview.center.x != bounds.midX:
+ centerPreview(at: .zero)
+
+ // Adjust preview view size if needed
+ case .horizontal where autoresizesSubviews:
+ preview.bounds.size = CGSize(width: 25, height: bounds.height + 10)
+ case .vertical where autoresizesSubviews:
+ preview.bounds.size = CGSize(width: bounds.width + 10, height: 25)
+
+ default:
+ break
}
- }
- }
-
- /// Draws necessary parts of the `ColorSlider`.
- private func layout(_ sublayer: CALayer, parent layer: CALayer) {
- guard sublayer != previewView.layer else { return }
- updateCornerRadius()
- sublayer.frame = layer.bounds
+ }
}
- public override func layoutSublayers(of layer: CALayer) {
- super.layoutSublayers(of: layer)
- layer.sublayers?.forEach { layout($0, parent: layer) }
+ /// Center the preview view at a particular point, given the orientation.
+ ///
+ /// * If orientation is `.horizontal`, the preview is centered at `(point.x, bounds.midY)`.
+ /// * If orientation is `.vertical`, the preview is centered at `(bounds.midX, point.y)`.
+ ///
+ /// The `x` and `y` values of `point` are constrained to the bounds of the slider.
+ /// - parameter point: The desired point at which to center the `previewView`.
+ internal func centerPreview(at point: CGPoint) {
+ switch orientation {
+ case .horizontal:
+ let boundedTouchX = (0.. bounds.height) ? bounds.height : bounds.width
- drawLayer.cornerRadius = shortestSide / 2.0
- } else {
- drawLayer.cornerRadius = cornerRadius
- }
- }
-
- // MARK: - Preview
- /// Shows the color preview.
- ///
- /// - parameter touch: The touch that triggered the update.
- private func showPreview(_ touch: UITouch) {
- if !previewEnabled { return }
+/// :nodoc:
+// MARK: - UIControlEvents
+extension ColorSlider {
+ /// Begins tracking a touch when the user starts dragging.
+ public override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
+ super.beginTracking(touch, with: event)
+
+ // Reset saturation to default value
+ internalColor.saturation = gradientView.saturation
+
+ update(touch: touch, touchInside: true)
- // Initialize preview in proper position, save frame
- updatePreview(touch)
- previewView.transform = minimizedTransform(for: previewView.frame)
-
- addSubview(previewView)
- UIView.animate(withDuration: previewAnimationDuration, delay: 0, options: [.beginFromCurrentState, .curveEaseInOut], animations: { () -> Void in
- self.previewView.transform = CGAffineTransform.identity
- }, completion: nil)
- }
+ let touchLocation = touch.location(in: self)
+ centerPreview(at: touchLocation)
+ previewView?.transition(to: .active)
+
+ sendActions(for: .touchDown)
+ sendActions(for: .valueChanged)
+ return true
+ }
- /// Updates the color preview.
- ///
- /// - parameter touch: The touch that triggered the update.
- private func updatePreview(_ touch: UITouch) {
- if !previewEnabled { return }
+ /// Continues tracking a touch as the user drags.
+ public override func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
+ super.continueTracking(touch, with: event)
- // Calculate the position of the preview
- let location = touch.location(in: self)
- var x = orientation == .vertical ? -previewOffset : location.x
- var y = orientation == .vertical ? location.y : -previewOffset
+ update(touch: touch, touchInside: isTouchInside)
- // Restrict preview frame to slider bounds
- if orientation == .vertical {
- y = max(0, location.y - (previewDimension / 2))
- y = min(bounds.height - previewDimension, y)
+ if isTouchInside {
+ let touchLocation = touch.location(in: self)
+ centerPreview(at: touchLocation)
} else {
- x = max(0, location.x - (previewDimension / 2))
- x = min(bounds.width - previewDimension, x)
+ previewView?.transition(to: .activeFixed)
}
- // Update the preview
- let previewFrame = CGRect(x: x, y: y, width: previewDimension, height: previewDimension)
- previewView.frame = previewFrame
- previewView.backgroundColor = color
- }
+ sendActions(for: .valueChanged)
+ return true
+ }
- /// Removes the color preview
- private func removePreview() {
- if !previewEnabled || previewView.superview == nil { return }
+ /// Ends tracking a touch when the user finishes dragging.
+ public override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
+ super.endTracking(touch, with: event)
- UIView.animate(withDuration: previewAnimationDuration, delay: 0, options: [.beginFromCurrentState, .curveEaseInOut], animations: { () -> Void in
- self.previewView.transform = self.minimizedTransform(for: self.previewView.frame)
- }, completion: { (completed: Bool) -> Void in
- self.previewView.removeFromSuperview()
- self.previewView.transform = CGAffineTransform.identity
- })
- }
-
- /// Calculates the transform from `rect` to the minimized preview view.
- ///
- /// - parameter rect: The actual frame of the preview view.
- /// - returns: The transform from `rect` to generate the minimized preview view.
- private func minimizedTransform(for rect: CGRect) -> CGAffineTransform {
- let minimizedDimension: CGFloat = 5.0
+ guard let endTouch = touch else { return }
+ update(touch: endTouch, touchInside: isTouchInside)
- let scale = minimizedDimension / previewDimension
- let scaleTransform = CGAffineTransform(scaleX: scale, y: scale)
+ previewView?.transition(to: .inactive)
- let tx = orientation == .vertical ? previewOffset : 0
- let ty = orientation == .vertical ? 0 : previewOffset
- let translationTransform = CGAffineTransform(translationX: tx, y: ty)
+ sendActions(for: isTouchInside ? .touchUpInside : .touchUpOutside)
+ }
+
+ /// Cancels tracking a touch when the user cancels dragging.
+ public override func cancelTracking(with event: UIEvent?) {
+ sendActions(for: .touchCancel)
+ }
+}
+
+/// :nodoc:
+/// MARK: - Internal Calculations
+fileprivate extension ColorSlider {
+ /// Updates the internal color and preview view when a touch event occurs.
+ /// - parameter touch: The touch that triggered the update.
+ /// - parameter touchInside: Whether the touch that triggered the update was inside the control when the event occurred.
+ fileprivate func update(touch: UITouch, touchInside: Bool) {
+ internalColor = gradientView.color(from: internalColor, after: touch, insideSlider: touchInside)
+ previewView?.colorChanged(to: color)
+ }
+}
+
+/// :nodoc:
+/// MARK: - Increase Tappable Area
+extension ColorSlider {
+ /// Increase the tappable area of `ColorSlider` to a minimum of 44 points on either edge.
+ override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
+ // Determine the delta between the width / height and 44, the iOS HIG minimum tap target size.
+ // If a side is already longer than 44, add 10 points of padding to either side of the slider along that axis.
+ let minimumSideLength: CGFloat = 44
+ let padding: CGFloat = -20
+ let dx: CGFloat = min(bounds.width - minimumSideLength, padding)
+ let dy: CGFloat = min(bounds.height - minimumSideLength, padding)
+
+ // If an increased tappable area is needed, respond appropriately
+ let increasedTapAreaNeeded = (dx < 0 || dy < 0)
+ let expandedBounds = bounds.insetBy(dx: dx / 2, dy: dy / 2)
- return scaleTransform.concatenating(translationTransform)
- }
+ if increasedTapAreaNeeded && expandedBounds.contains(point) {
+ for subview in subviews.reversed() {
+ let convertedPoint = subview.convert(point, from: self)
+ if let hitTestView = subview.hitTest(convertedPoint, with: event) {
+ return hitTestView
+ }
+ }
+ return self
+ } else {
+ return super.hitTest(point, with: event)
+ }
+ }
}
diff --git a/Sources/DefaultPreviewView.swift b/Sources/DefaultPreviewView.swift
new file mode 100644
index 0000000..f649259
--- /dev/null
+++ b/Sources/DefaultPreviewView.swift
@@ -0,0 +1,217 @@
+//
+// DefaultPreviewView.swift
+//
+// Created by Sachin Patel on 9/5/17.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import UIKit
+
+///
+/// The default preview view of a `ColorSlider`.
+///
+/// Appears to the given `side` of the associated `ColorSlider` at the point of the currently
+/// selected color with an offset of `offsetAmount` and a scale given by `scaleAmounts` for a given state.
+///
+/// You can subclass this class and pass it as a preview to `ColorSlider` to customize its appearance or animation.
+/// You may also create your own custom `UIView` and conform to the `PreviewView` protocol and pass that to `ColorSlider`'s initializer.
+///
+
+public class DefaultPreviewView: UIView {
+ /// The animation duration when showing the preview. Defaults to `0.15`.
+ public var animationDuration: TimeInterval = 0.15
+
+ /// The side of the `ColorSlider` on which to show the preview view.
+ public enum Side {
+ /// Show the preview to the left of the slider. Valid when the ColorSlider orientation is vertical.
+ case left
+
+ /// Show the preview to the right of the slider. Valid when the ColorSlider orientation is vertical.
+ case right
+
+ /// Show the preview to the top of the slider. Valid when the ColorSlider orientation is horizontal.
+ case top
+
+ /// Show the preview to the bottom of the slider. Valid when the ColorSlider orientation is horizontal.
+ case bottom
+ }
+
+ /// The side of the ColorSlider that the preview should show on. Defaults to `.left`.
+ public var side: Side {
+ didSet {
+ calculateOffset()
+ }
+ }
+
+ /// The scale of the slider for each preview state.
+ /// Defaults to:
+ /// * `.inactive`: `1`
+ /// * `.activeFixed`: `1.2`
+ /// * `.active`: `1.6`
+ public var scaleAmounts: [PreviewState: CGFloat] = [.inactive: 1.0,
+ .activeFixed: 1.2,
+ .active: 1.6]
+
+ /// The number of points to offset the preview view from the slider when the state is set to `.active`. Defaults to `50`.
+ public var offsetAmount: CGFloat = 50 {
+ didSet {
+ calculateOffset()
+ }
+ }
+
+ /// The actual offset of the preview view, calculated from `offsetAmount` and `side`.
+ /// This value is calculated automatically in `calculateOffset` and should only be modified externally by subclasses.
+ public var offset: CGPoint
+
+ /// The view that displays the current color as its `backgroundColor`.
+ public let colorView: UIView = UIView()
+
+ /// Enable haptics on iPhone 7 and above for state transitions to/from `.activeFixed`. Defaults to `true`.
+ public var hapticsEnabled: Bool = true
+
+ /// :nodoc:
+ /// The last state that occurred, used to trigger haptic feedback when a selection occurs.
+ fileprivate var lastState: PreviewState = .inactive
+
+ /// Initialize with a specific side.
+ /// - parameter side: The side of the `ColorSlider` to show on. Defaults to `.left`.
+ required public init(side: Side = .left) {
+ self.side = side
+ colorView.backgroundColor = .red
+ offset = CGPoint(x: -offsetAmount, y: 0)
+
+ super.init(frame: .zero)
+
+ backgroundColor = .white
+
+ // Outer shadow
+ layer.shadowColor = UIColor.black.cgColor
+ layer.shadowRadius = 3
+ layer.shadowOpacity = 0.2
+ layer.shadowOffset = CGSize(width: 2, height: 2)
+
+ // Borders
+ colorView.clipsToBounds = true
+ colorView.layer.borderWidth = 1.0
+ colorView.layer.borderColor = UIColor.black.withAlphaComponent(0.1).cgColor
+ addSubview(colorView)
+
+ calculateOffset()
+ }
+
+ /// :nodoc:
+ public required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ /// :nodoc:
+ override public func layoutSubviews() {
+ super.layoutSubviews()
+
+ // Automatically set the preview view corner radius based on the shortest side
+ layer.cornerRadius = min(bounds.width, bounds.height) / 2
+
+ // Inset the color view by 3 points, round the corners
+ let colorViewFrame = bounds.insetBy(dx: 3, dy: 3)
+ colorView.frame = colorViewFrame
+ colorView.layer.cornerRadius = min(colorViewFrame.width, colorViewFrame.height) / 2
+ }
+
+ /// Calculate the offset of the preview view when `offset` or `side` are set.
+ public func calculateOffset() {
+ switch side {
+ case .left:
+ offset = CGPoint(x: -offsetAmount, y: 0)
+ case .right:
+ offset = CGPoint(x: offsetAmount, y: 0)
+ case .top:
+ offset = CGPoint(x: 0, y: -offsetAmount)
+ case .bottom:
+ offset = CGPoint(x: 0, y: offsetAmount)
+ }
+ }
+}
+
+extension DefaultPreviewView: ColorSliderPreviewing {
+ /// Set the `backgroundColor` of `colorView` to the new `color`.
+ /// - parameter color: The new color.
+ public func colorChanged(to color: UIColor) {
+ colorView.backgroundColor = color
+ }
+
+ /// Animating to the `CGAffineTransform` with:
+ /// * Translation: `offset`
+ /// * Scale: `scaleAmounts[state]`
+ /// - seealso: `offsetAmount`
+ /// - seealso: `scaleAmounts`
+ /// - seealso: `offset`
+ /// - parameter state: The new state to transition to.
+ public func transition(to state: PreviewState) {
+ // The `.beginFromCurrentState` option allows there to be no delay when another touch occurs and a previous transition hasn't finished.
+ UIView.animate(withDuration: animationDuration, delay: 0, options: [.curveEaseInOut, .beginFromCurrentState], animations: {
+ // Only show the outer shadow when the state is inactive.
+ self.colorView.layer.borderWidth = (state == .inactive ? 0 : 1)
+
+ switch state {
+
+ // Set the transform based on `scaleAmounts`.
+ case .inactive,
+ .activeFixed:
+ let scaleAmount = self.scaleAmounts[state] ?? 1
+ let scaleTransform = CGAffineTransform(scaleX: scaleAmount, y: scaleAmount)
+ self.transform = scaleTransform
+
+ // Set the transform based on `scaleAmounts` and `offset`.
+ case .active:
+ let scaleAmount = self.scaleAmounts[state] ?? 1
+ let scaleTransform = CGAffineTransform(scaleX: scaleAmount, y: scaleAmount)
+ let translationTransform = CGAffineTransform(translationX: self.offset.x, y: self.offset.y)
+ self.transform = scaleTransform.concatenating(translationTransform)
+
+ }
+ }, completion: nil)
+
+ // Haptics
+ if hapticsEnabled, #available(iOS 10.0, *) {
+ switch (lastState, state) {
+
+ // Medium impact haptic when first drag outside bounds occurs.
+ case (.active, .activeFixed):
+ let impactFeedback = UIImpactFeedbackGenerator(style: .medium)
+ impactFeedback.impactOccurred()
+
+ // Light impact haptic when color selection outside bounds occurs.
+ case (.activeFixed, .inactive):
+ let impactFeedback = UIImpactFeedbackGenerator(style: .light)
+ impactFeedback.impactOccurred()
+
+ // No haptic feedback for other state transitions.
+ default:
+ break
+
+ }
+ }
+
+ lastState = state
+ }
+}
diff --git a/Sources/GradientView.swift b/Sources/GradientView.swift
new file mode 100644
index 0000000..e8d6eba
--- /dev/null
+++ b/Sources/GradientView.swift
@@ -0,0 +1,254 @@
+//
+// GradientView.swift
+//
+// Created by Sachin Patel on 8/12/17.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import UIKit
+
+/// A gradient view that acts as the background of any `ColorSlider`.
+/// This class draws colors based on the `orientation` passed to the initializer
+/// and determines the output color of `ColorSlider` after a touch event.
+///
+/// Customize the appearance of ColorSlider by setting layer properties on
+/// this class, including `borderWidth`, `borderColor`, and `cornerRadius`.
+
+public final class GradientView: UIView {
+ /// Whether the gradient should adjust its corner radius based on its bounds.
+ /// When `true`, the layer's corner radius is set to `min(bounds.width, bounds.height) / 2.0` in `layoutSubviews`.
+ public var automaticallyAdjustsCornerRadius: Bool = true {
+ didSet {
+ setNeedsLayout()
+ }
+ }
+
+ /// The saturation of all colors in the view.
+ /// Defaults to `1`.
+ public var saturation: CGFloat = 1 {
+ didSet {
+ setNeedsDisplay()
+ }
+ }
+
+ /// The percent of space at the beginning (top for orientation `.vertical` and left for orientation `.horizontal`) end of the slider reserved for the color white.
+ /// Defaults to `0.15`.
+ public var whiteInset: CGFloat = 0.15 {
+ didSet {
+ setNeedsDisplay()
+ }
+ }
+
+ /// The percent of space at the end (bottom for orientation `.vertical` and right for orientation `.horizontal`) end of the slider reserved for the color black.
+ /// Defaults to `0.15`.
+ public var blackInset: CGFloat = 0.15 {
+ didSet {
+ setNeedsDisplay()
+ }
+ }
+
+ /// :nodoc:
+ /// The orientation of the gradient view. This is always equal to the value of `orientation` in the corresponding `ColorSlider` instance.
+ fileprivate let orientation: Orientation
+
+ /// - parameter orientation: The orientation of the gradient view.
+ required public init(orientation: Orientation) {
+ self.orientation = orientation
+
+ super.init(frame: .zero)
+
+ backgroundColor = .clear
+ isUserInteractionEnabled = false
+
+ // By default, show a border
+ layer.masksToBounds = true
+ layer.borderColor = UIColor.white.cgColor
+ layer.borderWidth = 2
+
+ // Set up based on orientation
+ switch orientation {
+ case .vertical:
+ gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
+ gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
+ case .horizontal:
+ gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
+ gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
+ }
+ }
+
+ /// :nodoc:
+ public required init?(coder aDecoder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+}
+
+/// :nodoc:
+// MARK: - Layer and Internal Drawing
+public extension GradientView {
+ override public class var layerClass: AnyClass {
+ return CAGradientLayer.self
+ }
+
+ fileprivate var gradientLayer: CAGradientLayer {
+ guard let gradientLayer = self.layer as? CAGradientLayer else {
+ fatalError("Layer must be a gradient layer.")
+ }
+ return gradientLayer
+ }
+
+ override public func draw(_ rect: CGRect) {
+ // Values from 0 to 1 at intervals of 0.1
+ let values: [CGFloat] = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]
+
+ // Use these values as the hues for non-white and non-black colors
+ let hues = values
+ let nonGrayscaleColors = hues.map({ (hue) -> UIColor in
+ return UIColor(hue: hue, saturation: saturation, brightness: 1, alpha: 1)
+ }).reversed()
+
+ // Black and white are at the top and bottom of the slider, insert colors in between
+ let spaceForNonGrayscaleColors = 1 - whiteInset - blackInset
+ let nonGrayscaleLocations = values.map { (location) -> CGFloat in
+ return whiteInset + (location * spaceForNonGrayscaleColors)
+ }
+
+ // Add black and white to locations and colors, set up gradient layer
+ let locations = [0] + nonGrayscaleLocations + [1]
+ let colors = [UIColor.white] + nonGrayscaleColors + [UIColor.black]
+ gradientLayer.locations = locations as [NSNumber]
+ gradientLayer.colors = colors.map { $0.cgColor }
+ }
+
+ override public func layoutSubviews() {
+ super.layoutSubviews()
+
+ // Automatically adjust corner radius if needed
+ if automaticallyAdjustsCornerRadius {
+ let shortestSide = min(bounds.width, bounds.height)
+ let automaticCornerRadius = shortestSide / 2.0
+ if layer.cornerRadius != automaticCornerRadius {
+ layer.cornerRadius = automaticCornerRadius
+ }
+ }
+ }
+}
+
+// MARK: - Math
+/// :nodoc:
+internal extension GradientView {
+ /// Determines the new color value after a touch event occurs. The behavior is defined as follows:
+ /// **When `insideSlider == true`, if the touch is:**
+ /// * In the first `whiteInset` percent of the slider, return white.
+ /// * In the last `blackInset` percent of the slider, return black.
+ /// * In between, return the `HSBColor` with the following values:
+ /// * Hue: Determined based on the touch position within the slider, given the orientation.
+ /// * Saturation: `self.saturation`
+ /// * Brightness: `1`
+ /// **When `insideSlider == false`**:
+ /// * Hue: Keep constant.
+ /// * Saturation: Adjust based on touch location along axis parallel to `orientation`.
+ /// * Brightness: Adjust based on touch location along axis perpendicular to `orientation`.
+ ///
+ /// - parameter oldColor: The last color before the touch occurred.
+ /// - parameter touch: The touch that triggered the color change.
+ /// - parameter insideSlider: Whether the touch that triggered the color change was inside the slider.
+ /// - returns: The resulting color.
+ internal func color(from oldColor: HSBColor, after touch: UITouch, insideSlider: Bool) -> HSBColor {
+ var color = oldColor
+
+ if insideSlider {
+ // Hue: adjust based on touch location in ColorSlider bounds.
+ // Saturation: Keep constant.
+ // Brightness: Set equal to 100%.
+
+ // Determine the progress of a touch along the slider given self.orientation
+ let progress = touch.progress(in: self, withOrientation: orientation)
+
+ // Set hue based on percent
+ color = calculateColor(for: progress)
+ } else {
+ // Hue: Keep constant.
+ // Saturation: Adjust based on touch location along axis parallel to self.orientation.
+ // Brightness: Adjust based on touch location along axis perpendicular to self.orientation.
+
+ guard let containingView = touch.view?.superview else { return color }
+ let horizontalPercent = touch.progress(in: containingView, withOrientation: .horizontal)
+ let verticalPercent = touch.progress(in: containingView, withOrientation: .vertical)
+
+ switch orientation {
+ case .vertical:
+ color.saturation = horizontalPercent
+ color.brightness = 1 - verticalPercent
+ case .horizontal:
+ color.saturation = 1 - verticalPercent
+ color.brightness = horizontalPercent
+ }
+
+ // If `oldColor` is grayscale, black or white was selected before the touch exited the bounds of the slider.
+ // Maintain the grayscale color as the touch continues outside the bounds so gray colors can be selected.
+ if oldColor.isGrayscale {
+ color.saturation = 0
+ }
+ }
+
+ return color
+ }
+
+ /// Determines the corresponding HSBColor for a point the slider.
+ /// The `sliderProgress` (ranging from 0.0 to 1.0) is used in `color(from:after:insideSlider:)` for touches inside the slider.
+ /// - parameter sliderProgress: The "progress" of a touch relative to the width or height of the gradient view, given the `orientation`.
+ /// The hue is equal to `point.x / bounds.width` when `orientation == .horizontal` and `point.y / bounds.height` when `orientation == .vertical`.
+ /// - returns: The corresponding HSBColor.
+ internal func calculateColor(for sliderProgress: CGFloat) -> HSBColor {
+ if sliderProgress < whiteInset {
+ return .white
+ } else if sliderProgress > 1 - blackInset {
+ return .black
+ } else {
+ let spaceForNonGrayscaleColors = 1 - blackInset - whiteInset
+ let hue = (sliderProgress - whiteInset) / spaceForNonGrayscaleColors
+ return HSBColor(hue: 1 - hue, saturation: saturation, brightness: 1)
+ }
+ }
+
+ /// Determines the corresponding point on the slider for a HSBColor.
+ /// The `sliderProgress` (ranging from 0.0 to 1.0) is used in `color(from:after:insideSlider:)` for touches inside the slider.
+ /// - parameter color: A HSBColor value for which a closest-match "progress" value along the slider is to be determined.
+ /// - returns: The closest-match "progress" value along the slider for `color`.
+ internal func calculateSliderProgress(for color: HSBColor) -> CGFloat {
+ var sliderProgress: CGFloat = 0.0
+ if color.isGrayscale {
+ // If the color is grayscale, find the closest matching percent along the slider
+ if color.brightness > 0.5 {
+ sliderProgress = whiteInset / 2
+ } else {
+ sliderProgress = 1 - (blackInset / 2)
+ }
+ } else {
+ // Otherwise, calculate the percent corresponding to the color's hue in the non-grayscale part of the slider
+ let spaceForNonGrayscaleColors = 1 - blackInset - whiteInset
+ sliderProgress = ((1 - color.hue) * spaceForNonGrayscaleColors) + whiteInset
+ }
+ return sliderProgress
+ }
+}
diff --git a/Sources/Internal/ColorSliderExtensions.swift b/Sources/Internal/ColorSliderExtensions.swift
new file mode 100644
index 0000000..c7781a2
--- /dev/null
+++ b/Sources/Internal/ColorSliderExtensions.swift
@@ -0,0 +1,61 @@
+//
+// ColorSliderExtensions.swift
+//
+// Created by Sachin Patel on 5/27/17.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import UIKit
+
+/// :nodoc:
+internal extension Range {
+ /// Constrain a `Bound` value by `self`.
+ /// Equivalent to max(lowerBound, min(upperBound, value)).
+ /// - parameter value: The value to be clamped.
+ internal func clamp(_ value: Bound) -> Bound {
+ return lowerBound > value ? lowerBound
+ : upperBound < value ? upperBound
+ : value
+ }
+}
+
+/// :nodoc:
+internal extension UITouch {
+ /// Calculate the "progress" of a touch in a view with respect to an orientation.
+ /// - parameter view: The view to be used as a frame of reference.
+ /// - parameter orientation: The orientation with which to determine the return value.
+ /// - returns: The percent across the `view` that the receiver's location is, relative to the `orientation`. Constrained to (0, 1).
+ internal func progress(in view: UIView, withOrientation orientation: Orientation) -> CGFloat {
+ let touchLocation = self.location(in: view)
+ var progress: CGFloat = 0
+
+ switch orientation {
+ case .vertical:
+ progress = touchLocation.y / view.bounds.height
+ case .horizontal:
+ progress = touchLocation.x / view.bounds.width
+ }
+
+ return (0.0..<1.0).clamp(progress)
+ }
+}
diff --git a/Sources/Internal/HSBColor.swift b/Sources/Internal/HSBColor.swift
new file mode 100644
index 0000000..c6cb449
--- /dev/null
+++ b/Sources/Internal/HSBColor.swift
@@ -0,0 +1,67 @@
+//
+// HSBColor.swift
+//
+// Created by Sachin Patel on 8/11/17.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import UIKit
+
+/// :nodoc:
+/// An [HSB](https://en.wikipedia.org/wiki/HSL_and_HSV) color value type.
+internal struct HSBColor: Equatable {
+ static let black = HSBColor(hue: 1, saturation: 0, brightness: 0)
+ static let white = HSBColor(hue: 1, saturation: 0, brightness: 1)
+
+ var hue: CGFloat = 0
+ var saturation: CGFloat = 1
+ var brightness: CGFloat = 1
+
+ var isGrayscale: Bool {
+ return saturation == 0
+ }
+
+ init(hue: CGFloat, saturation: CGFloat, brightness: CGFloat) {
+ self.hue = hue
+ self.saturation = saturation
+ self.brightness = brightness
+ }
+
+ init(color: UIColor) {
+ color.getHue(&self.hue, saturation: &self.saturation, brightness: &self.brightness, alpha: nil)
+ }
+
+ static func ==(lhs: HSBColor, rhs: HSBColor) -> Bool {
+ return lhs.hue == rhs.hue &&
+ lhs.saturation == rhs.saturation &&
+ lhs.brightness == rhs.brightness
+ }
+}
+
+/// :nodoc:
+internal extension UIColor {
+ /// A convenience initializer to create a `UIColor` from an `HSBColor`.
+ convenience init(hsbColor: HSBColor) {
+ self.init(hue: hsbColor.hue, saturation: hsbColor.saturation, brightness: hsbColor.brightness, alpha: 1)
+ }
+}
diff --git a/Sources/PreviewView.swift b/Sources/PreviewView.swift
new file mode 100644
index 0000000..73cf0d2
--- /dev/null
+++ b/Sources/PreviewView.swift
@@ -0,0 +1,68 @@
+//
+// PreviewView.swift
+//
+// Created by Sachin Patel on 5/27/17.
+//
+// The MIT License (MIT)
+//
+// Copyright (c) 2015-Present Sachin Patel (http://gizmosachin.com/)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import UIKit
+
+public typealias PreviewView = UIView & ColorSliderPreviewing
+
+/// The display state of a preview view.
+public enum PreviewState {
+ /// The color is not being changed and the preview view is centered at the last modified point.
+ case inactive
+
+ /// The color is still being changed, but the preview view center is fixed.
+ /// This occurs when a touch begins inside the slider but continues outside of it.
+ /// In this case, the color is actively being modified, but the preview remains fixed at
+ /// the same position that it was when the touch moved outside of the slider.
+ case activeFixed
+
+ /// The color is being actively changed and the preview view center will be updated to match the current color.
+ case active
+}
+
+/// A protocol defining callback methods for a `ColorSlider` preview view.
+///
+/// To create a custom preview view, create a `UIView` subclass and implement `ColorSliderPreviewing`.
+/// Then, create an instance of your custom preview view and pass it to the `ColorSlider` initializer.
+/// As a user drags their finger, `ColorSlider` will automatically set your preview view's `center`
+/// to the point closest to the touch, centered along the axis perpendicular to the `ColorSlider`'s orientation.
+///
+/// If `autoresizesSubviews` is `true` (the default value on all `UIView`s) on your `ColorSlider`, your preview view
+/// will also be automatically resized when its `center` point is being set. To disable resizing your preview, set
+/// the `autoresizesSubviews` property on your `ColorSlider` to `false`.
+
+public protocol ColorSliderPreviewing {
+ /// Called when the color of the slider changes, so the preview can respond correctly.
+ /// - parameter color: The newly selected color.
+ func colorChanged(to color: UIColor)
+
+ /// Called when the preview changes state and should update its appearance appropriately.
+ /// Since `ColorSlider` sets the `center` of your preview automatically, you should use your
+ /// view's `transform` to adjust or animate most changes. See `DefaultPreviewView` for an example.
+ /// - parameter state: The new state of the preview view.
+ func transition(to state: PreviewState)
+}
diff --git a/docs/Classes.html b/docs/Classes.html
index 5176802..1be51ee 100644
--- a/docs/Classes.html
+++ b/docs/Classes.html
@@ -35,7 +35,32 @@
ColorSlider
ColorSlider is a customizable color picker with live preview.
+
+
Inspired by Snapchat, ColorSlider lets you drag to select black, white, or any color in between.
+Customize ColorSlider and its preview via a simple API, and receive callbacks via UIControlEvents.
+
+
Use the convenience initializer to create a .vertical ColorSlider with a live preview that appears to the .left of it:
You can create a custom preview view using the ColorSliderPreviewing protocol, or by subclassing DefaultPreviewView.
+To pass in a custom preview view, simply use the default initializer instead:
ColorSlider uses the HSB color standard internally.
+You can set the saturation of your ColorSlider’s gradientView to change the saturation of colors on the slider.
+See the GradientView and HSBColor for more details on how colors are calculated.
A gradient view that acts as the background of any ColorSlider.
+This class draws colors based on the orientation passed to the initializer
+and determines the output color of ColorSlider after a touch event.
+
+
Customize the appearance of ColorSlider by setting layer properties on
+this class, including borderWidth, borderColor, and cornerRadius.
Appears to the given side of the associated ColorSlider at the point of the currently
+selected color with an offset of offsetAmount and a scale given by scaleAmounts for a given state.
+
+
You can subclass this class and pass it as a preview to ColorSlider to customize its appearance or animation.
+You may also create your own custom UIView and conform to the PreviewView protocol and pass that to ColorSlider‘s initializer.
A boolean value that determines whether or not a color preview is shown while dragging.
+
Inspired by Snapchat, ColorSlider lets you drag to select black, white, or any color in between.
+Customize ColorSlider and its preview via a simple API, and receive callbacks via UIControlEvents.
-
-
-
Declaration
-
-
Swift
-
@IBInspectablepublicvarpreviewEnabled:Bool=false
+
Use the convenience initializer to create a .vertical ColorSlider with a live preview that appears to the .left of it:
You can create a custom preview view using the ColorSliderPreviewing protocol, or by subclassing DefaultPreviewView.
+To pass in a custom preview view, simply use the default initializer instead:
Whether the slider should automatically adjust its corner radius.
-When this value is true, cornerRadius is ignored.
-When this value is false, the cornerRadius is used.
ColorSlider uses the HSB color standard internally.
+You can set the saturation of your ColorSlider’s gradientView to change the saturation of colors on the slider.
+See the GradientView and HSBColor for more details on how colors are calculated.
Appears to the given side of the associated ColorSlider at the point of the currently
+selected color with an offset of offsetAmount and a scale given by scaleAmounts for a given state.
+
+
You can subclass this class and pass it as a preview to ColorSlider to customize its appearance or animation.
+You may also create your own custom UIView and conform to the PreviewView protocol and pass that to ColorSlider‘s initializer.
The actual offset of the preview view, calculated from offsetAmount and side.
+This value is calculated automatically in calculateOffset and should only be modified externally by subclasses.
A gradient view that acts as the background of any ColorSlider.
+This class draws colors based on the orientation passed to the initializer
+and determines the output color of ColorSlider after a touch event.
+
+
Customize the appearance of ColorSlider by setting layer properties on
+this class, including borderWidth, borderColor, and cornerRadius.
Whether the gradient should adjust its corner radius based on its bounds.
+When true, the layer’s corner radius is set to min(bounds.width, bounds.height) / 2.0 in layoutSubviews.
The percent of space at the beginning (top for orientation .vertical and left for orientation .horizontal) end of the slider reserved for the color white.
+Defaults to 0.15.
The percent of space at the end (bottom for orientation .vertical and right for orientation .horizontal) end of the slider reserved for the color black.
+Defaults to 0.15.
The color is still being changed, but the preview view center is fixed.
+This occurs when a touch begins inside the slider but continues outside of it.
+In this case, the color is actively being modified, but the preview remains fixed at
+the same position that it was when the touch moved outside of the slider.
A protocol defining callback methods for a ColorSlider preview view.
+
+
To create a custom preview view, create a UIView subclass and implement ColorSliderPreviewing.
+Then, create an instance of your custom preview view and pass it to the ColorSlider initializer.
+As a user drags their finger, ColorSlider will automatically set your preview view’s center
+to the point closest to the touch, centered along the axis perpendicular to the ColorSlider‘s orientation.
+
+
If autoresizesSubviews is true (the default value on all UIViews) on your ColorSlider, your preview view
+will also be automatically resized when its center point is being set. To disable resizing your preview, set
+the autoresizesSubviews property on your ColorSlider to false.
A protocol defining callback methods for a ColorSlider preview view.
+
+
To create a custom preview view, create a UIView subclass and implement ColorSliderPreviewing.
+Then, create an instance of your custom preview view and pass it to the ColorSlider initializer.
+As a user drags their finger, ColorSlider will automatically set your preview view’s center
+to the point closest to the touch, centered along the axis perpendicular to the ColorSlider‘s orientation.
+
+
If autoresizesSubviews is true (the default value on all UIViews) on your ColorSlider, your preview view
+will also be automatically resized when its center point is being set. To disable resizing your preview, set
+the autoresizesSubviews property on your ColorSlider to false.
Called when the preview changes state and should update its appearance appropriately.
+Since ColorSlider sets the center of your preview automatically, you should use your
+view’s transform to adjust or animate most changes. See DefaultPreviewView for an example.
ColorSlider is a customizable color picker with live preview.
+
+
Inspired by Snapchat, ColorSlider lets you drag to select black, white, or any color in between.
+Customize ColorSlider and its preview via a simple API, and receive callbacks via UIControlEvents.
+
+
Use the convenience initializer to create a .vertical ColorSlider with a live preview that appears to the .left of it:
You can create a custom preview view using the ColorSliderPreviewing protocol, or by subclassing DefaultPreviewView.
+To pass in a custom preview view, simply use the default initializer instead:
ColorSlider uses the HSB color standard internally.
+You can set the saturation of your ColorSlider’s gradientView to change the saturation of colors on the slider.
+See the GradientView and HSBColor for more details on how colors are calculated.
A gradient view that acts as the background of any ColorSlider.
+This class draws colors based on the orientation passed to the initializer
+and determines the output color of ColorSlider after a touch event.
+
+
Customize the appearance of ColorSlider by setting layer properties on
+this class, including borderWidth, borderColor, and cornerRadius.
Appears to the given side of the associated ColorSlider at the point of the currently
+selected color with an offset of offsetAmount and a scale given by scaleAmounts for a given state.
+
+
You can subclass this class and pass it as a preview to ColorSlider to customize its appearance or animation.
+You may also create your own custom UIView and conform to the PreviewView protocol and pass that to ColorSlider‘s initializer.
A boolean value that determines whether or not a color preview is shown while dragging.
+
Inspired by Snapchat, ColorSlider lets you drag to select black, white, or any color in between.
+Customize ColorSlider and its preview via a simple API, and receive callbacks via UIControlEvents.
-
-
-
Declaration
-
-
Swift
-
@IBInspectablepublicvarpreviewEnabled:Bool=false
+
Use the convenience initializer to create a .vertical ColorSlider with a live preview that appears to the .left of it:
You can create a custom preview view using the ColorSliderPreviewing protocol, or by subclassing DefaultPreviewView.
+To pass in a custom preview view, simply use the default initializer instead:
Whether the slider should automatically adjust its corner radius.
-When this value is true, cornerRadius is ignored.
-When this value is false, the cornerRadius is used.
ColorSlider uses the HSB color standard internally.
+You can set the saturation of your ColorSlider’s gradientView to change the saturation of colors on the slider.
+See the GradientView and HSBColor for more details on how colors are calculated.
Appears to the given side of the associated ColorSlider at the point of the currently
+selected color with an offset of offsetAmount and a scale given by scaleAmounts for a given state.
+
+
You can subclass this class and pass it as a preview to ColorSlider to customize its appearance or animation.
+You may also create your own custom UIView and conform to the PreviewView protocol and pass that to ColorSlider‘s initializer.
The actual offset of the preview view, calculated from offsetAmount and side.
+This value is calculated automatically in calculateOffset and should only be modified externally by subclasses.
A gradient view that acts as the background of any ColorSlider.
+This class draws colors based on the orientation passed to the initializer
+and determines the output color of ColorSlider after a touch event.
+
+
Customize the appearance of ColorSlider by setting layer properties on
+this class, including borderWidth, borderColor, and cornerRadius.
Whether the gradient should adjust its corner radius based on its bounds.
+When true, the layer’s corner radius is set to min(bounds.width, bounds.height) / 2.0 in layoutSubviews.
The percent of space at the beginning (top for orientation .vertical and left for orientation .horizontal) end of the slider reserved for the color white.
+Defaults to 0.15.
The percent of space at the end (bottom for orientation .vertical and right for orientation .horizontal) end of the slider reserved for the color black.
+Defaults to 0.15.
The color is still being changed, but the preview view center is fixed.
+This occurs when a touch begins inside the slider but continues outside of it.
+In this case, the color is actively being modified, but the preview remains fixed at
+the same position that it was when the touch moved outside of the slider.
A protocol defining callback methods for a ColorSlider preview view.
+
+
To create a custom preview view, create a UIView subclass and implement ColorSliderPreviewing.
+Then, create an instance of your custom preview view and pass it to the ColorSlider initializer.
+As a user drags their finger, ColorSlider will automatically set your preview view’s center
+to the point closest to the touch, centered along the axis perpendicular to the ColorSlider‘s orientation.
+
+
If autoresizesSubviews is true (the default value on all UIViews) on your ColorSlider, your preview view
+will also be automatically resized when its center point is being set. To disable resizing your preview, set
+the autoresizesSubviews property on your ColorSlider to false.
A protocol defining callback methods for a ColorSlider preview view.
+
+
To create a custom preview view, create a UIView subclass and implement ColorSliderPreviewing.
+Then, create an instance of your custom preview view and pass it to the ColorSlider initializer.
+As a user drags their finger, ColorSlider will automatically set your preview view’s center
+to the point closest to the touch, centered along the axis perpendicular to the ColorSlider‘s orientation.
+
+
If autoresizesSubviews is true (the default value on all UIViews) on your ColorSlider, your preview view
+will also be automatically resized when its center point is being set. To disable resizing your preview, set
+the autoresizesSubviews property on your ColorSlider to false.
Called when the preview changes state and should update its appearance appropriately.
+Since ColorSlider sets the center of your preview automatically, you should use your
+view’s transform to adjust or animate most changes. See DefaultPreviewView for an example.
ColorSlider is a Swift color picker with a live preview.
-
-
Inspired by Snapchat, ColorSlider lets you drag vertically to pick a range of colors and drag to the edges of the superview to select black and white. You can configure and customize ColorSlider via a simple API, and receive callbacks via UIControlEvents.
+
+
+
-
+
-
-
Version Compatibility
+
ColorSlider is an iOS color picker with live preview written in Swift.
-
Current Swift compatibility breakdown:
+
-
Swift Version
-
Framework Version
+
+
Features
-
3.0
-
master
+
:ghost:
+
[Snapchat](http://snapchat.com)-style color picker
ColorSlider is also available for installation using Carthage. To integrate, add the following to your Cartfile:
-
github "gizmosachin/ColorSlider" >= 3.0.1
+
Create your own live preview by subclassing DefaultPreviewView or implementing ColorSliderPreviewing in your UIView subclass.
+Then, just pass your preview instance to the initializer:
ColorSlider is also available for installation using the Swift Package Manager. Add the following to your Package.swift:
-
importPackageDescription
+
ColorSlider will automatically update your view’s center as touches move on the slider.
+By default, it’ll also resize your preview automatically. Set colorSlider.autoresizesSubviews to false to disable autoresizing.
To disable the preview, simply pass nil to ColorSlider’s initializer:
+
let colorSlider = ColorSlider(orientation: .vertical, previewView: nil)
-
Manual
-
You can also simply copy ColorSlider.swift into your Xcode project.
-
Example Project
+
See the documentation for more details on custom previews.
+
Documentation
-
ColorSlider comes with an example project called Sketchpad, a simple drawing app. To try it, install CocoaPods and run pod install under the Example directory. Then, open Sketchpad.xcworkspace.
ColorSlider uses HSB and defaults to a saturation and brightness: 100%.
+
+
+
Swift Version
+
Framework Version
+
+
+
+
4.0
+
master
+
+
+
3.0
+
3.0.1
+
+
+
Demo
-
When the orientation is set to .vertical, dragging vertically adjusts the hue, and dragging outside adjusts the saturation and brightness as follows:
+
Please see the Demo directory for a basic iOS project that uses ColorSlider.
+
Contributing
-
-
Inside the frame, dragging vertically adjusts the hue
-
Outside the frame, dragging horizontally adjusts the saturation
-
Outside the frame, dragging vertically adjusts the brightness
-
+
ColorSlider is a community - contributions and discussions are welcome!
-
Adjusting the brightness lets you select black and white by first dragging on the slider, then moving your finger outside the frame to the top left (to select white) or bottom left (to select black) of the superview.
The corner radius of the ColorSlider.","parent_name":"ColorSlider"},"Classes/ColorSlider.html#/s:vC11ColorSlider11ColorSlider29setsCornerRadiusAutomaticallySb":{"name":"setsCornerRadiusAutomatically","abstract":"
Whether the slider should automatically adjust its corner radius.","parent_name":"ColorSlider"},"Classes/ColorSlider.html#/s:FC11ColorSlider11ColorSlidercFT_S0_":{"name":"init()","abstract":"
Creates a ColorSlider with a frame of CGRect.zero.
"}}
\ No newline at end of file
+{"Protocols/ColorSliderPreviewing.html#/s:11ColorSlider0aB10PreviewingP12colorChangedySo7UIColorC2to_tF":{"name":"colorChanged(to:)","abstract":"
Called when the color of the slider changes, so the preview can respond correctly.
Called when the preview changes state and should update its appearance appropriately.","parent_name":"ColorSliderPreviewing"},"Protocols/ColorSliderPreviewing.html":{"name":"ColorSliderPreviewing","abstract":"
A protocol defining callback methods for a ColorSlider preview view.
The color is still being changed, but the preview view center is fixed.","parent_name":"PreviewState"},"Enums/PreviewState.html#/s:11ColorSlider12PreviewStateO6activeA2CmF":{"name":"active","abstract":"
The color is being actively changed and the preview view center will be updated to match the current color.
The scale of the slider for each preview state.","parent_name":"DefaultPreviewView"},"Classes/DefaultPreviewView.html#/c:@M@ColorSlider@objc(cs)DefaultPreviewView(py)offsetAmount":{"name":"offsetAmount","abstract":"
The number of points to offset the preview view from the slider when the state is set to .active. Defaults to 50.
The actual offset of the preview view, calculated from offsetAmount and side.","parent_name":"DefaultPreviewView"},"Classes/DefaultPreviewView.html#/c:@M@ColorSlider@objc(cs)DefaultPreviewView(py)colorView":{"name":"colorView","abstract":"
The view that displays the current color as its backgroundColor.
Whether the gradient should adjust its corner radius based on its bounds.","parent_name":"GradientView"},"Classes/GradientView.html#/c:@M@ColorSlider@objc(cs)GradientView(py)saturation":{"name":"saturation","abstract":"
The saturation of all colors in the view.","parent_name":"GradientView"},"Classes/GradientView.html#/c:@M@ColorSlider@objc(cs)GradientView(py)whiteInset":{"name":"whiteInset","abstract":"
The percent of space at the beginning (top for orientation .vertical and left for orientation .horizontal) end of the slider reserved for the color white.","parent_name":"GradientView"},"Classes/GradientView.html#/c:@M@ColorSlider@objc(cs)GradientView(py)blackInset":{"name":"blackInset","abstract":"
The percent of space at the end (bottom for orientation .vertical and right for orientation .horizontal) end of the slider reserved for the color black.","parent_name":"GradientView"},"Classes/GradientView.html#/s:11ColorSlider12GradientViewCAcA11OrientationO11orientation_tcfc":{"name":"init(orientation:)","parent_name":"GradientView"},"Classes/ColorSlider.html#/c:@M@ColorSlider@objc(cs)ColorSlider(py)color":{"name":"color","abstract":"
ColorSlider is a Swift color picker with a live preview.
-
-
Inspired by Snapchat, ColorSlider lets you drag vertically to pick a range of colors and drag to the edges of the superview to select black and white. You can configure and customize ColorSlider via a simple API, and receive callbacks via UIControlEvents.
+
+
ColorSlider
+
-
+
-
-
Version Compatibility
+
ColorSlider is an iOS color picker with live preview written in Swift.
-
Current Swift compatibility breakdown:
+
-
-
-
Swift Version
-
Framework Version
-
-
-
-
3.0
-
master
-
-
-
2.3
-
2.5.1
-
-
Usage
-
Create and add an instance of ColorSlider to your view hierarchy.
ColorSlider is also available for installation using Carthage. To integrate, add the following to your Cartfile:
-
github "gizmosachin/ColorSlider" >= 3.0.1
+
Create your own live preview by subclassing DefaultPreviewView or implementing ColorSliderPreviewing in your UIView subclass.
+Then, just pass your preview instance to the initializer:
ColorSlider is also available for installation using the Swift Package Manager. Add the following to your Package.swift:
-
importPackageDescription
+
ColorSlider will automatically update your view’s center as touches move on the slider.
+By default, it’ll also resize your preview automatically. Set colorSlider.autoresizesSubviews to false to disable autoresizing.
To disable the preview, simply pass nil to ColorSlider’s initializer:
+
let colorSlider = ColorSlider(orientation: .vertical, previewView: nil)
-
Manual
-
You can also simply copy ColorSlider.swift into your Xcode project.
-
Example Project
+
See the documentation for more details on custom previews.
+
Documentation
-
ColorSlider comes with an example project called Sketchpad, a simple drawing app. To try it, install CocoaPods and run pod install under the Example directory. Then, open Sketchpad.xcworkspace.
ColorSlider uses HSB and defaults to a saturation and brightness: 100%.
+
+
+
Swift Version
+
Framework Version
+
+
+
+
4.0
+
master
+
+
+
3.0
+
3.0.1
+
+
+
Demo
-
When the orientation is set to .vertical, dragging vertically adjusts the hue, and dragging outside adjusts the saturation and brightness as follows:
+
Please see the Demo directory for a basic iOS project that uses ColorSlider.
+
Contributing
-
-
Inside the frame, dragging vertically adjusts the hue
-
Outside the frame, dragging horizontally adjusts the saturation
-
Outside the frame, dragging vertically adjusts the brightness
-
+
ColorSlider is a community - contributions and discussions are welcome!
-
Adjusting the brightness lets you select black and white by first dragging on the slider, then moving your finger outside the frame to the top left (to select white) or bottom left (to select black) of the superview.
The corner radius of the ColorSlider.","parent_name":"ColorSlider"},"Classes/ColorSlider.html#/s:vC11ColorSlider11ColorSlider29setsCornerRadiusAutomaticallySb":{"name":"setsCornerRadiusAutomatically","abstract":"
Whether the slider should automatically adjust its corner radius.","parent_name":"ColorSlider"},"Classes/ColorSlider.html#/s:FC11ColorSlider11ColorSlidercFT_S0_":{"name":"init()","abstract":"
Creates a ColorSlider with a frame of CGRect.zero.
"}}
\ No newline at end of file
+{"Protocols/ColorSliderPreviewing.html#/s:11ColorSlider0aB10PreviewingP12colorChangedySo7UIColorC2to_tF":{"name":"colorChanged(to:)","abstract":"
Called when the color of the slider changes, so the preview can respond correctly.
Called when the preview changes state and should update its appearance appropriately.","parent_name":"ColorSliderPreviewing"},"Protocols/ColorSliderPreviewing.html":{"name":"ColorSliderPreviewing","abstract":"
A protocol defining callback methods for a ColorSlider preview view.
The color is still being changed, but the preview view center is fixed.","parent_name":"PreviewState"},"Enums/PreviewState.html#/s:11ColorSlider12PreviewStateO6activeA2CmF":{"name":"active","abstract":"
The color is being actively changed and the preview view center will be updated to match the current color.
The scale of the slider for each preview state.","parent_name":"DefaultPreviewView"},"Classes/DefaultPreviewView.html#/c:@M@ColorSlider@objc(cs)DefaultPreviewView(py)offsetAmount":{"name":"offsetAmount","abstract":"
The number of points to offset the preview view from the slider when the state is set to .active. Defaults to 50.
The actual offset of the preview view, calculated from offsetAmount and side.","parent_name":"DefaultPreviewView"},"Classes/DefaultPreviewView.html#/c:@M@ColorSlider@objc(cs)DefaultPreviewView(py)colorView":{"name":"colorView","abstract":"
The view that displays the current color as its backgroundColor.
Whether the gradient should adjust its corner radius based on its bounds.","parent_name":"GradientView"},"Classes/GradientView.html#/c:@M@ColorSlider@objc(cs)GradientView(py)saturation":{"name":"saturation","abstract":"
The saturation of all colors in the view.","parent_name":"GradientView"},"Classes/GradientView.html#/c:@M@ColorSlider@objc(cs)GradientView(py)whiteInset":{"name":"whiteInset","abstract":"
The percent of space at the beginning (top for orientation .vertical and left for orientation .horizontal) end of the slider reserved for the color white.","parent_name":"GradientView"},"Classes/GradientView.html#/c:@M@ColorSlider@objc(cs)GradientView(py)blackInset":{"name":"blackInset","abstract":"
The percent of space at the end (bottom for orientation .vertical and right for orientation .horizontal) end of the slider reserved for the color black.","parent_name":"GradientView"},"Classes/GradientView.html#/s:11ColorSlider12GradientViewCAcA11OrientationO11orientation_tcfc":{"name":"init(orientation:)","parent_name":"GradientView"},"Classes/ColorSlider.html#/c:@M@ColorSlider@objc(cs)ColorSlider(py)color":{"name":"color","abstract":"
"}}
\ No newline at end of file
diff --git a/docs/undocumented.json b/docs/undocumented.json
index 132904d..4b34eca 100644
--- a/docs/undocumented.json
+++ b/docs/undocumented.json
@@ -2,5 +2,5 @@
"warnings": [
],
- "source_directory": "/Users/sachin/Documents/ColorSlider/ColorSlider"
+ "source_directory": "/Users/sachin/Documents/Open Source/ColorSlider/ColorSlider"
}
\ No newline at end of file