Deintegrated cocoapods as XCTest will be used. Temporarily remove legacy source from build target.

This commit is contained in:
Jonathan Cardasis 2019-04-11 21:38:30 -04:00
parent 0713349ed7
commit 5a8f85fbcd
15 changed files with 848 additions and 685 deletions

View File

@ -15,16 +15,10 @@
35C376D61D5CF5300069D7A1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D41D5CF5300069D7A1 /* Main.storyboard */; };
35C376D81D5CF5300069D7A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D71D5CF5300069D7A1 /* Assets.xcassets */; };
35C376DB1D5CF5300069D7A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D91D5CF5300069D7A1 /* LaunchScreen.storyboard */; };
5F1C3CC9B7FD9F7F4B9C94BA /* Pods_ChromaColorPicker_Tests_ChromaColorPickerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9389AEF26357BC9EC5DB8488 /* Pods_ChromaColorPicker_Tests_ChromaColorPickerTests.framework */; };
B229F68E819E318E9A4D9B22 /* Pods_ChromaColorPicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B0C16EA18555BA1F96C07DB /* Pods_ChromaColorPicker.framework */; };
FC1BD8C02207D7B700817AF3 /* ChromaColorPickerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8BF2207D7B700817AF3 /* ChromaColorPickerSpec.swift */; };
FC1BD8C02207D7B700817AF3 /* ChromaColorPickerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8BF2207D7B700817AF3 /* ChromaColorPickerTests.swift */; };
FC1BD8C22207D7B700817AF3 /* ChromaColorPicker.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3503B82F1F2689BC00750356 /* ChromaColorPicker.framework */; };
FC1BD8CE2207FCE100817AF3 /* ChromaHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8C82207FCE100817AF3 /* ChromaHandle.swift */; };
FC1BD8CF2207FCE100817AF3 /* ChromaShadeSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8C92207FCE100817AF3 /* ChromaShadeSlider.swift */; };
FC1BD8D02207FCE100817AF3 /* ChromaColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8CA2207FCE100817AF3 /* ChromaColorPicker.swift */; };
FC1BD8D12207FCE100817AF3 /* UIColor+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8CB2207FCE100817AF3 /* UIColor+Utilities.swift */; };
FC1BD8D22207FCE100817AF3 /* ChromaAddButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8CC2207FCE100817AF3 /* ChromaAddButton.swift */; };
FC1BD8D32207FCE100817AF3 /* ColorModeToggleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC1BD8CD2207FCE100817AF3 /* ColorModeToggleButton.swift */; };
FCCA42A5226022A800BE2FF9 /* ColorWheelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCCA42A4226022A800BE2FF9 /* ColorWheelView.swift */; };
FCEA4E272235AAA200C0A1B6 /* ChromaColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCEA4E262235AAA200C0A1B6 /* ChromaColorPicker.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -59,12 +53,6 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0722B34CBD5489ADC94F7B91 /* Pods-ChromaColorPickerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChromaColorPickerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ChromaColorPickerTests/Pods-ChromaColorPickerTests.release.xcconfig"; sourceTree = "<group>"; };
097AE9DDB2DC9AF89E2EDE5A /* Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ChromaColorPicker-Tests-ChromaColorPickerTests/Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.debug.xcconfig"; sourceTree = "<group>"; };
0A7B83C96B02042BB70821D7 /* Pods-ChromaColorPicker.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChromaColorPicker.release.xcconfig"; path = "Pods/Target Support Files/Pods-ChromaColorPicker/Pods-ChromaColorPicker.release.xcconfig"; sourceTree = "<group>"; };
0A7F02F440BE6423B319B578 /* Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-ChromaColorPicker-Tests-ChromaColorPickerTests/Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.release.xcconfig"; sourceTree = "<group>"; };
2B0C16EA18555BA1F96C07DB /* Pods_ChromaColorPicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ChromaColorPicker.framework; sourceTree = BUILT_PRODUCTS_DIR; };
2E61508E4135F0CC9078125D /* Pods-ChromaColorPicker.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChromaColorPicker.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ChromaColorPicker/Pods-ChromaColorPicker.debug.xcconfig"; sourceTree = "<group>"; };
3503B82F1F2689BC00750356 /* ChromaColorPicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ChromaColorPicker.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3503B8311F2689BC00750356 /* ChromaColorPicker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChromaColorPicker.h; sourceTree = "<group>"; };
3503B8321F2689BC00750356 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -75,11 +63,8 @@
35C376D71D5CF5300069D7A1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
35C376DA1D5CF5300069D7A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
35C376DC1D5CF5300069D7A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
91485B6B5C58777417441794 /* Pods_ChromaColorPickerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ChromaColorPickerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9389AEF26357BC9EC5DB8488 /* Pods_ChromaColorPicker_Tests_ChromaColorPickerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ChromaColorPicker_Tests_ChromaColorPickerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E0C887E58E73DFD65E9DEB81 /* Pods-ChromaColorPickerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChromaColorPickerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ChromaColorPickerTests/Pods-ChromaColorPickerTests.debug.xcconfig"; sourceTree = "<group>"; };
FC1BD8BD2207D7B700817AF3 /* ChromaColorPickerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChromaColorPickerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
FC1BD8BF2207D7B700817AF3 /* ChromaColorPickerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromaColorPickerSpec.swift; sourceTree = "<group>"; };
FC1BD8BF2207D7B700817AF3 /* ChromaColorPickerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromaColorPickerTests.swift; sourceTree = "<group>"; };
FC1BD8C12207D7B700817AF3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
FC1BD8C82207FCE100817AF3 /* ChromaHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChromaHandle.swift; sourceTree = "<group>"; };
FC1BD8C92207FCE100817AF3 /* ChromaShadeSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChromaShadeSlider.swift; sourceTree = "<group>"; };
@ -87,6 +72,8 @@
FC1BD8CB2207FCE100817AF3 /* UIColor+Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+Utilities.swift"; sourceTree = "<group>"; };
FC1BD8CC2207FCE100817AF3 /* ChromaAddButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChromaAddButton.swift; sourceTree = "<group>"; };
FC1BD8CD2207FCE100817AF3 /* ColorModeToggleButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorModeToggleButton.swift; sourceTree = "<group>"; };
FCCA42A4226022A800BE2FF9 /* ColorWheelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorWheelView.swift; sourceTree = "<group>"; };
FCEA4E262235AAA200C0A1B6 /* ChromaColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromaColorPicker.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -94,7 +81,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B229F68E819E318E9A4D9B22 /* Pods_ChromaColorPicker.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -111,7 +97,6 @@
buildActionMask = 2147483647;
files = (
FC1BD8C22207D7B700817AF3 /* ChromaColorPicker.framework in Frameworks */,
5F1C3CC9B7FD9F7F4B9C94BA /* Pods_ChromaColorPicker_Tests_ChromaColorPickerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -121,14 +106,11 @@
3503B8301F2689BC00750356 /* Source */ = {
isa = PBXGroup;
children = (
FC1BD8CC2207FCE100817AF3 /* ChromaAddButton.swift */,
FC1BD8CA2207FCE100817AF3 /* ChromaColorPicker.swift */,
FC1BD8C82207FCE100817AF3 /* ChromaHandle.swift */,
FC1BD8C92207FCE100817AF3 /* ChromaShadeSlider.swift */,
FC1BD8CD2207FCE100817AF3 /* ColorModeToggleButton.swift */,
FC1BD8CB2207FCE100817AF3 /* UIColor+Utilities.swift */,
FCCA427822601F8800BE2FF9 /* Legacy */,
3503B8311F2689BC00750356 /* ChromaColorPicker.h */,
3503B8321F2689BC00750356 /* Info.plist */,
FCEA4E262235AAA200C0A1B6 /* ChromaColorPicker.swift */,
FCCA42A4226022A800BE2FF9 /* ColorWheelView.swift */,
);
path = Source;
sourceTree = "<group>";
@ -140,8 +122,6 @@
3503B8301F2689BC00750356 /* Source */,
FC1BD8BE2207D7B700817AF3 /* Tests */,
35C376CE1D5CF5300069D7A1 /* Products */,
A890856BC0D0DD14D667AEA1 /* Pods */,
A18D889CBAEF3E0FD0A65ADB /* Frameworks */,
);
sourceTree = "<group>";
};
@ -168,38 +148,28 @@
path = Example;
sourceTree = "<group>";
};
A18D889CBAEF3E0FD0A65ADB /* Frameworks */ = {
isa = PBXGroup;
children = (
91485B6B5C58777417441794 /* Pods_ChromaColorPickerTests.framework */,
2B0C16EA18555BA1F96C07DB /* Pods_ChromaColorPicker.framework */,
9389AEF26357BC9EC5DB8488 /* Pods_ChromaColorPicker_Tests_ChromaColorPickerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
A890856BC0D0DD14D667AEA1 /* Pods */ = {
isa = PBXGroup;
children = (
E0C887E58E73DFD65E9DEB81 /* Pods-ChromaColorPickerTests.debug.xcconfig */,
0722B34CBD5489ADC94F7B91 /* Pods-ChromaColorPickerTests.release.xcconfig */,
2E61508E4135F0CC9078125D /* Pods-ChromaColorPicker.debug.xcconfig */,
0A7B83C96B02042BB70821D7 /* Pods-ChromaColorPicker.release.xcconfig */,
097AE9DDB2DC9AF89E2EDE5A /* Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.debug.xcconfig */,
0A7F02F440BE6423B319B578 /* Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
};
FC1BD8BE2207D7B700817AF3 /* Tests */ = {
isa = PBXGroup;
children = (
FC1BD8BF2207D7B700817AF3 /* ChromaColorPickerSpec.swift */,
FC1BD8BF2207D7B700817AF3 /* ChromaColorPickerTests.swift */,
FC1BD8C12207D7B700817AF3 /* Info.plist */,
);
path = Tests;
sourceTree = "<group>";
};
FCCA427822601F8800BE2FF9 /* Legacy */ = {
isa = PBXGroup;
children = (
FC1BD8CC2207FCE100817AF3 /* ChromaAddButton.swift */,
FC1BD8CA2207FCE100817AF3 /* ChromaColorPicker.swift */,
FC1BD8C82207FCE100817AF3 /* ChromaHandle.swift */,
FC1BD8C92207FCE100817AF3 /* ChromaShadeSlider.swift */,
FC1BD8CD2207FCE100817AF3 /* ColorModeToggleButton.swift */,
FC1BD8CB2207FCE100817AF3 /* UIColor+Utilities.swift */,
);
path = Legacy;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@ -218,12 +188,10 @@
isa = PBXNativeTarget;
buildConfigurationList = 3503B83A1F2689BC00750356 /* Build configuration list for PBXNativeTarget "ChromaColorPicker" */;
buildPhases = (
15254D6200BBBBE8871C2B25 /* [CP] Check Pods Manifest.lock */,
3503B82A1F2689BC00750356 /* Sources */,
3503B82B1F2689BC00750356 /* Frameworks */,
3503B82C1F2689BC00750356 /* Headers */,
3503B82D1F2689BC00750356 /* Resources */,
F26B6B5B0BB0F852318ADC06 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -257,12 +225,9 @@
isa = PBXNativeTarget;
buildConfigurationList = FC1BD8C52207D7B700817AF3 /* Build configuration list for PBXNativeTarget "ChromaColorPickerTests" */;
buildPhases = (
BE626E9F9FF56ED9E5B4A858 /* [CP] Check Pods Manifest.lock */,
FC1BD8B92207D7B700817AF3 /* Sources */,
FC1BD8BA2207D7B700817AF3 /* Frameworks */,
FC1BD8BB2207D7B700817AF3 /* Resources */,
77B1C2C1CC97939E1F7DB18E /* [CP] Embed Pods Frameworks */,
D1F2D465C9F2D952C7B15251 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -291,7 +256,7 @@
};
35C376CC1D5CF5300069D7A1 = {
CreatedOnToolsVersion = 7.3;
DevelopmentTeam = 43DKZUY8C6;
DevelopmentTeam = 9H97MWKJ22;
LastSwiftMigration = 1000;
};
FC1BD8BC2207D7B700817AF3 = {
@ -348,115 +313,13 @@
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
15254D6200BBBBE8871C2B25 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/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;
};
77B1C2C1CC97939E1F7DB18E /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ChromaColorPicker-Tests-ChromaColorPickerTests/Pods-ChromaColorPicker-Tests-ChromaColorPickerTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
BE626E9F9FF56ED9E5B4A858 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/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;
};
D1F2D465C9F2D952C7B15251 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ChromaColorPicker-Tests-ChromaColorPickerTests/Pods-ChromaColorPicker-Tests-ChromaColorPickerTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
F26B6B5B0BB0F852318ADC06 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-ChromaColorPicker/Pods-ChromaColorPicker-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
3503B82A1F2689BC00750356 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FC1BD8CF2207FCE100817AF3 /* ChromaShadeSlider.swift in Sources */,
FC1BD8CE2207FCE100817AF3 /* ChromaHandle.swift in Sources */,
FC1BD8D32207FCE100817AF3 /* ColorModeToggleButton.swift in Sources */,
FC1BD8D12207FCE100817AF3 /* UIColor+Utilities.swift in Sources */,
FC1BD8D22207FCE100817AF3 /* ChromaAddButton.swift in Sources */,
FC1BD8D02207FCE100817AF3 /* ChromaColorPicker.swift in Sources */,
FCEA4E272235AAA200C0A1B6 /* ChromaColorPicker.swift in Sources */,
FCCA42A5226022A800BE2FF9 /* ColorWheelView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -473,7 +336,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FC1BD8C02207D7B700817AF3 /* ChromaColorPickerSpec.swift in Sources */,
FC1BD8C02207D7B700817AF3 /* ChromaColorPickerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -514,7 +377,6 @@
/* Begin XCBuildConfiguration section */
3503B8381F2689BC00750356 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2E61508E4135F0CC9078125D /* Pods-ChromaColorPicker.debug.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@ -543,7 +405,6 @@
};
3503B8391F2689BC00750356 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0A7B83C96B02042BB70821D7 /* Pods-ChromaColorPicker.release.xcconfig */;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
@ -681,7 +542,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEFINES_MODULE = NO;
DEVELOPMENT_TEAM = 9H97MWKJ22;
INFOPLIST_FILE = Example/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.jonathancardasis.ChromaColorPickerExample;
PRODUCT_NAME = ChromaColorPickerExample;
@ -696,7 +559,9 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEFINES_MODULE = NO;
DEVELOPMENT_TEAM = 9H97MWKJ22;
INFOPLIST_FILE = Example/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.jonathancardasis.ChromaColorPickerExample;
PRODUCT_NAME = ChromaColorPickerExample;
@ -706,7 +571,6 @@
};
FC1BD8C62207D7B700817AF3 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 097AE9DDB2DC9AF89E2EDE5A /* Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
@ -733,7 +597,6 @@
};
FC1BD8C72207D7B700817AF3 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0A7F02F440BE6423B319B578 /* Pods-ChromaColorPicker-Tests-ChromaColorPickerTests.release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:ChromaColorPicker.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@ -9,6 +9,30 @@
import UIKit
import ChromaColorPicker
class ViewController: UIViewController {
@IBOutlet weak var colorDisplayView: UIView!
let colorPicker = ChromaColorPicker2()
override func viewDidLoad() {
super.viewDidLoad()
colorPicker.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(colorPicker)
NSLayoutConstraint.activate([
colorPicker.centerXAnchor.constraint(equalTo: view.centerXAnchor),
colorPicker.centerYAnchor.constraint(equalTo: view.centerYAnchor),
colorPicker.widthAnchor.constraint(equalToConstant: 400),
colorPicker.heightAnchor.constraint(equalToConstant: 400)
])
}
}
/*
class ViewController: UIViewController {
@IBOutlet weak var colorDisplayView: UIView!
@ -61,3 +85,4 @@ extension ViewController: ChromaColorPickerDelegate {
}
}
*/

11
Podfile
View File

@ -1,11 +0,0 @@
use_frameworks!
target "ChromaColorPicker" do
abstract_target 'Tests' do
target "ChromaColorPickerTests"
pod 'Quick'
pod 'Nimble'
end
end

View File

@ -1,15 +0,0 @@
PODS:
- Nimble (7.3.1)
- Quick (1.3.2)
DEPENDENCIES:
- Nimble
- Quick
SPEC CHECKSUMS:
Nimble: 04f732da099ea4d153122aec8c2a88fd0c7219ae
Quick: 2623cb30d7a7f41ca62f684f679586558f483d46
PODFILE CHECKSUM: d1da65bf2e6463426e9b04a5b850dc7caffbc72b
COCOAPODS: 1.2.1

View File

@ -1,69 +1,45 @@
//
// ChromaColorPicker.swift
// ChromaColorPicker2.swift
// ChromaColorPicker
//
// Copyright © 2016 Jonathan Cardasis. All rights reserved.
//
// 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.
// Created by Jon Cardasis on 3/10/19.
// Copyright © 2019 Jonathan Cardasis. All rights reserved.
//
import UIKit
import Accelerate
public protocol ChromaColorPickerDelegate {
/* Called when the user taps the add button in the center */
/// When the control has changed
func colorPickerDidChooseColor(_ colorPicker: ChromaColorPicker, color: UIColor)
}
open class ChromaColorPicker: UIControl {
open var hexLabel: UILabel!
open var shadeSlider: ChromaShadeSlider!
open var handleView: ChromaHandle!
open var handleLine: CAShapeLayer!
open var addButton: ChromaAddButton!
open var colorToggleButton: ColorModeToggleButton!
func timeElapsedInSecondsWhenRunningCode(operation: ()->()) -> Double { //TEMP - DEBUG
let startTime = CFAbsoluteTimeGetCurrent()
operation()
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
return Double(timeElapsed)
}
private var modeIsGrayscale: Bool {
return colorToggleButton.colorState == .grayscale
}
private enum ColorSpace {
case rainbow
case grayscale
}
open private(set) var currentColor = UIColor.red
open var supportsShadesOfGray: Bool = false {
didSet {
if supportsShadesOfGray {
colorToggleButton.isHidden = false
}
else {
colorToggleButton.isHidden = true
}
}
}
open var delegate: ChromaColorPickerDelegate?
open var currentAngle: Float = 0
open private(set) var radius: CGFloat = 0
open var stroke: CGFloat = 1
open var padding: CGFloat = 15
open var handleSize: CGSize{
get{ return CGSize(width: self.bounds.width * 0.1, height: self.bounds.height * 0.1) }
public class ChromaColorHandle {
/// Current selected color of the handle.
fileprivate(set) var color: UIColor
/// An image to display above the handle.
var popoverImage: UIImage?
/// A view to display above the handle. Overrides any provided `popoverImage`.
var popoverView: UIView?
init(color: UIColor) {
self.color = color
}
}
@IBDesignable
public class ChromaColorPicker: UIControl {
//MARK: - Initialization
override public init(frame: CGRect) {
@ -76,445 +52,250 @@ open class ChromaColorPicker: UIControl {
self.commonInit()
}
private func commonInit(){
public override func setNeedsDisplay() {
super.setNeedsDisplay()
print("called")
}
public override func layoutSubviews() {
super.layoutSubviews()
let minDimensionSize = min(bounds.width, bounds.height)
let colorWheelImage = makeColorWheel(radius: minDimensionSize * 3.0) // TEMP?
colorWheelImageView.image = colorWheelImage
}
public func addHandle(at color: UIColor? = nil) -> ChromaColorHandle {
return ChromaColorHandle(color: color ?? defaultHandleColorPosition)
}
// MARK: - Private
internal var colorWheelImageView: UIImageView!
internal func commonInit() {
self.backgroundColor = UIColor.clear
self.layer.masksToBounds = false
setupColorWheel()
applySmoothingMaskToColorWheel()
setupGestures()
let minDimension = min(self.bounds.size.width, self.bounds.size.height)
radius = minDimension/2 - handleSize.width/2
/* Setup Handle */
handleView = ChromaHandle(frame: CGRect(x: 0,y: 0, width: handleSize.width, height: handleSize.height))
handleView.shadowOffset = CGSize(width: 0,height: 2)
/* Setup pan gesture for handle */
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(ChromaColorPicker.handleWasMoved(_:)))
handleView.addGestureRecognizer(panRecognizer)
/* Setup Add Button */
addButton = ChromaAddButton()
self.layoutAddButton() //layout frame
addButton.addTarget(self, action: #selector(ChromaColorPicker.addButtonPressed(_:)), for: .touchUpInside)
/* Setup Handle Line */
handleLine = CAShapeLayer()
handleLine.lineWidth = 2
handleLine.strokeColor = UIColor.white.withAlphaComponent(0.2).cgColor
/* Setup Color Hex Label */
hexLabel = UILabel()
self.layoutHexLabel() //layout frame
hexLabel.layer.cornerRadius = 2
hexLabel.adjustsFontSizeToFitWidth = true
hexLabel.textAlignment = .center
hexLabel.textColor = UIColor(red: 51/255.0, green:51/255.0, blue: 51/255.0, alpha: 0.65)
/* Setup Shade Slider */
shadeSlider = ChromaShadeSlider()
shadeSlider.delegate = self
self.layoutShadeSlider()
shadeSlider.addTarget(self, action: #selector(ChromaColorPicker.sliderEditingDidEnd(_:)), for: .editingDidEnd)
/* Setup Color Mode Toggle Button */
colorToggleButton = ColorModeToggleButton()
self.layoutColorToggleButton() //layout frame
colorToggleButton.colorState = .hue // Default as starting state is hue
colorToggleButton.addTarget(self, action: #selector(togglePickerColorMode), for: .touchUpInside)
colorToggleButton.isHidden = !supportsShadesOfGray // default to hiding if not supported
/* Add components to view */
self.layer.addSublayer(handleLine)
self.addSubview(shadeSlider)
self.addSubview(hexLabel)
self.addSubview(handleView)
self.addSubview(addButton)
self.addSubview(colorToggleButton)
// DEBUG - BENCHMARK
func timeElapsedInSecondsWhenRunningCode(operation: ()->()) -> Double {
let startTime = CFAbsoluteTimeGetCurrent()
operation()
let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
return Double(timeElapsed)
}
override open func willMove(toSuperview newSuperview: UIView?) {
/* Get the starting color */
currentColor = colorOnWheelFromAngle(currentAngle)
handleView.center = positionOnWheelFromAngle(currentAngle) //update pos for angle
self.layoutHandleLine() //layout the lines positioning
handleView.color = currentColor
addButton.color = currentColor
shadeSlider.primaryColor = currentColor
self.updateHexLabel() //update for hex value
var times = [Double]()
for _ in 0..<10 {
let time = timeElapsedInSecondsWhenRunningCode {
_ = makeColorWheel(radius: 1400)
}
times.append(time)
print(time)
}
open func adjustToColor(_ color: UIColor){
/* Apply saturation and brightness from previous color to current one */
var saturation: CGFloat = 0.0
var brightness: CGFloat = 0.0
var hue: CGFloat = 0.0
var alpha: CGFloat = 0.0
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
let newColor = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
/* Set the slider value for the new color and update addButton */
shadeSlider.primaryColor = UIColor(hue: hue, saturation: 1, brightness: 1, alpha: 1) //Set a color recognzied on the color wheel
/* Update the angle and currentColor */
currentAngle = angleForColor(newColor)
currentColor = newColor
if brightness < 1.0 && saturation < 1.0 {
/* Modifies the Shade Slider to handle adjusting to colors outside of the Chroma scope */
shadeSlider.primaryColor = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1)
shadeSlider.currentValue = 0
} else if brightness < 1.0 { //currentValue is on the left side of the slider
shadeSlider.currentValue = brightness-1
}else{
shadeSlider.currentValue = -(saturation-1)
}
shadeSlider.updateHandleLocation() //update the handle location now that the value is set
addButton.color = newColor
/* Will layout based on new angle */
self.layoutHandle()
self.layoutHandleLine()
self.updateHexLabel()
let avgTime = times.reduce(0, +) / Double(times.count)
print("\n\nAvgTime: \(avgTime)")
// END DEBUG
}
//MARK: - Handle Touches
override open func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
//Overriden to prevent uicontrolevents being called from the super
}
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
let touchPoint = touches.first!.location(in: self)
if handleView.frame.contains(touchPoint) {
self.sendActions(for: .touchDown)
internal func setupColorWheel() {
colorWheelImageView = UIImageView(image: nil)
colorWheelImageView.contentMode = .scaleAspectFit
/* Enlarge Animation */
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseIn, animations: { () -> Void in
self.handleView.transform = CGAffineTransform(scaleX: 1.45, y: 1.45)
}, completion: nil)
}
}
override open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
//Run this animation after a pan or here if touches are released
if handleView.transform.d > 1 { //if scale is larger than 1 (already animated)
self.executeHandleShrinkAnimation()
}
colorWheelImageView.translatesAutoresizingMaskIntoConstraints = false
addSubview(colorWheelImageView)
NSLayoutConstraint.activate([
colorWheelImageView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
colorWheelImageView.centerYAnchor.constraint(equalTo: self.centerYAnchor),
colorWheelImageView.widthAnchor.constraint(equalTo: self.widthAnchor),
colorWheelImageView.heightAnchor.constraint(equalTo: colorWheelImageView.widthAnchor),
])
}
@objc func handleWasMoved(_ recognizer: UIPanGestureRecognizer) {
switch(recognizer.state){
/// Applys a smoothing mask to the color wheel to account for CIFilter's image dithering at the edges.
internal func applySmoothingMaskToColorWheel() {
case UIGestureRecognizer.State.changed:
let touchPosition = recognizer.location(in: self)
self.moveHandleTowardPoint(touchPosition)
self.sendActions(for: .touchDragInside)
break
case UIGestureRecognizer.State.ended:
/* Shrink Animation */
self.executeHandleShrinkAnimation()
break
default:
break
}
}
private func executeHandleShrinkAnimation(){
self.sendActions(for: .touchUpInside)
self.sendActions(for: .editingDidEnd)
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseOut, animations: { () -> Void in
self.handleView.transform = CGAffineTransform(scaleX: 1, y: 1)
}, completion: nil)
internal func setupGestures() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(colorWheelTapped(_:)))
colorWheelImageView.isUserInteractionEnabled = true
colorWheelImageView.addGestureRecognizer(tapGesture)
}
private func moveHandleTowardPoint(_ point: CGPoint){
currentAngle = angleToCenterFromPoint(point) //Find the angle of point to the frames center
//Layout Handle
self.layoutHandle()
//Layout Line
self.layoutHandleLine()
if modeIsGrayscale {
// If mode is grayscale do not update colors and end early
return
@objc
internal func colorWheelTapped(_ gesture: UITapGestureRecognizer) {
let location = gesture.location(in: colorWheelImageView)
let pixelColor = colorWheelImageView.getPixelColor(at: location)
print()
}
//Update color for shade slider
shadeSlider.primaryColor = handleView.color//currentColor
//Update color for add button if a shade isnt selected
if shadeSlider.currentValue == 0 {
self.updateCurrentColor(shadeSlider.currentColor)
/**
Generates a color wheel image from a given radius.
- Parameters:
- radius: The radius of the wheel in points. A radius of 100 would generate an
image of 200x200 (400x400 pixels on a device with 2x scaling.)
*/
internal func makeColorWheel(radius: CGFloat) -> UIImage {
let filter = CIFilter(name: "CIHueSaturationValueGradient", parameters: [
"inputColorSpace": CGColorSpaceCreateDeviceRGB(),
"inputDither": 0,
"inputRadius": radius,
"inputSoftness": 0,
"inputValue": 1
])!
return UIImage(ciImage: filter.outputImage!)
}
//Update Text Field display value
self.updateHexLabel()
}
@objc func addButtonPressed(_ sender: ChromaAddButton){
//Do a 'bob' animation
UIView.animate(withDuration: 0.2,
delay: 0,
options: .curveEaseIn,
animations: { () -> Void in
sender.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
}, completion: { (done) -> Void in
UIView.animate(withDuration: 0.1, animations: { () -> Void in
sender.transform = CGAffineTransform(scaleX: 1, y: 1)
})
})
delegate?.colorPickerDidChooseColor(self, color: sender.color) //Delegate call
}
@objc func sliderEditingDidEnd(_ sender: ChromaShadeSlider){
self.sendActions(for: .editingDidEnd)
}
//MARK: - Drawing
override open func draw(_ rect: CGRect) {
super.draw(rect)
let ctx = UIGraphicsGetCurrentContext()
let colorSpace: ColorSpace = (modeIsGrayscale) ? .grayscale : .rainbow
drawCircleRing(in: ctx, outerRadius: radius - padding, innerRadius: radius - stroke - padding, resolution: 1, colorSpace: colorSpace)
}
/*
Resolution should be between 0.1 and 1
colorSpace - either rainbow or grayscale
internal lazy var context = makeMetalContext()
internal func makeMetalContext() -> CIContext {
let mtlDevice = MTLCreateSystemDefaultDevice()
if let device = mtlDevice, device.supportsFeatureSet(.iOS_GPUFamily1_v1) {
return CIContext(mtlDevice: device, options: [CIContextOption.useSoftwareRenderer: false])
} else if let eaglContext = EAGLContext(api: .openGLES2) {
return CIContext(eaglContext: eaglContext)
} else {
return CIContext()
}
}
internal lazy var lookupImage: CGImage = {
let colorWheelCIImage = makeColorWheel(radius: 50).ciImage!
return context.createCGImage(colorWheelCIImage, from: colorWheelCIImage.extent)!
}()
internal func location(of color: UIColor) -> CGPoint? {
// guard let image = colorWheelImageView.image else { return nil }
//
// let ci = image.ciImage!
// let cgImage = context.createCGImage(ci, from: ci.extent)!
let cgImage = self.lookupImage
var red : CGFloat = 0
var green : CGFloat = 0
var blue : CGFloat = 0
color.getRed(&red, green: &green, blue: &blue, alpha: nil)
let r = UInt8(red * 255.0)
let g = UInt8(green * 255.0)
let b = UInt8(blue * 255.0)
let width = 100 //Int(image.size.width)
let height = 100 //Int(image.size.height)
if let cfData = cgImage.dataProvider?.data, let pointer = CFDataGetBytePtr(cfData) {
for x in 0..<width {
for y in 0..<height {
// TODO: do a DISTANCE calc and find closest distance
let pixelAddress = x * 4 + y * width * 4
if pointer.advanced(by: pixelAddress).pointee == r && //Red
pointer.advanced(by: pixelAddress + 1).pointee == g && //Green
pointer.advanced(by: pixelAddress + 2).pointee == b { //Blue
print(CGPoint(x: x, y: y)) //temp
return CGPoint(x: x, y: y)
}
}
}
}
return nil
}
*/
private func drawCircleRing(in context: CGContext?, outerRadius: CGFloat, innerRadius: CGFloat, resolution: Float, colorSpace: ColorSpace){
context?.saveGState()
context?.translateBy(x: self.bounds.midX, y: self.bounds.midY) //Move context to center
let subdivisions:CGFloat = CGFloat(resolution * 512) //Max subdivisions of 512
}
let innerHeight = (CGFloat.pi*innerRadius)/subdivisions //height of the inner wall for each segment
let outterHeight = (CGFloat.pi*outerRadius)/subdivisions
let segment = UIBezierPath()
segment.move(to: CGPoint(x: innerRadius, y: -innerHeight/2))
segment.addLine(to: CGPoint(x: innerRadius, y: innerHeight/2))
segment.addLine(to: CGPoint(x: outerRadius, y: outterHeight/2))
segment.addLine(to: CGPoint(x: outerRadius, y: -outterHeight/2))
segment.close()
private let defaultHandleColorPosition: UIColor = .black
//Draw each segment and rotate around the center
for i in 0 ..< Int(ceil(subdivisions)) {
if modeIsGrayscale {
UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1).set() //Gray
}
else { // Draw rainbow
UIColor(hue: CGFloat(i)/subdivisions, saturation: 1, brightness: 1, alpha: 1).set()
internal extension UIImageView {
internal func getPixelColor(at point: CGPoint) -> UIColor {
let pixel = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: 4)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
guard let context = CGContext(
data: pixel,
width: 1,
height: 1,
bitsPerComponent: 8,
bytesPerRow: 4,
space: colorSpace,
bitmapInfo: bitmapInfo.rawValue
) else {
return UIColor.white
}
segment.fill()
let lineTailSpace = (CGFloat.pi*2)*outerRadius/subdivisions //The amount of space between the tails of each segment
segment.lineWidth = lineTailSpace //allows for seemless scaling
segment.stroke()
context.translateBy(x: -point.x, y: -point.y)
layer.render(in: context)
let color = UIColor(
red: CGFloat(pixel[0]) / 255.0,
green: CGFloat(pixel[1]) / 255.0,
blue: CGFloat(pixel[2]) / 255.0,
alpha: CGFloat(pixel[3]) / 255.0
)
//Rotate to correct location
let rotate = CGAffineTransform(rotationAngle: -((CGFloat.pi*2)/subdivisions)) //rotates each segment
segment.apply(rotate)
pixel.deallocate()
return color
}
}
context?.translateBy(x: -self.bounds.midX, y: -self.bounds.midY) //Move context back to original position
context?.restoreGState()
}
extension UIImage {
func resized(newWidth: CGFloat, context: CIContext) -> UIImage? {
let scale = newWidth / self.size.width
let newHeight = self.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
self.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//MARK: - Layout Updates
/* Re-layout view and all its subview and drawings */
open func layout() {
self.setNeedsDisplay() //mark view as dirty
let minDimension = min(self.bounds.size.width, self.bounds.size.height)
radius = minDimension/2 - handleSize.width/2 //create radius for new size
self.layoutAddButton()
//Update handle's size
handleView.frame = CGRect(origin: .zero, size: handleSize)
self.layoutHandle()
//Ensure colors are updated
self.updateCurrentColor(handleView.color)
shadeSlider.primaryColor = handleView.color
self.layoutShadeSlider()
self.layoutHandleLine()
self.layoutHexLabel()
self.layoutColorToggleButton()
}
open func layoutAddButton(){
let addButtonSize = CGSize(width: self.bounds.width/5, height: self.bounds.height/5)
addButton.frame = CGRect(x: self.bounds.midX - addButtonSize.width/2, y: self.bounds.midY - addButtonSize.height/2, width: addButtonSize.width, height: addButtonSize.height)
}
/*
Update the handleView's position and color for the currentAngle
*/
func layoutHandle(){
let angle = currentAngle //Preserve value in case it changes
let newPosition = positionOnWheelFromAngle(angle) //find the correct position on the color wheel
//Update handle position
handleView.center = newPosition
if !modeIsGrayscale {
//Update color for the movement when color mode is hue
handleView.color = colorOnWheelFromAngle(angle)
}
}
/*
Updates the line view's position for the current angle
Pre: dependant on addButtons position & current angle
*/
func layoutHandleLine(){
let linePath = UIBezierPath()
linePath.move(to: addButton.center)
linePath.addLine(to: positionOnWheelFromAngle(currentAngle))
handleLine.path = linePath.cgPath
}
/*
Pre: dependant on addButtons position
*/
func layoutHexLabel(){
hexLabel.frame = CGRect(x: 0, y: 0, width: addButton.bounds.width*1.5, height: addButton.bounds.height/3)
hexLabel.center = CGPoint(x: self.bounds.midX, y: (addButton.frame.origin.y + (padding + handleView.frame.height/2 + stroke/2))/1.75) //Divided by 1.75 not 2 to make it a bit lower
hexLabel.font = UIFont(name: "Menlo-Regular", size: hexLabel.bounds.height)
}
/*
Pre: dependant on radius
*/
func layoutShadeSlider(){
/* Calculate proper length for slider */
let centerPoint = CGPoint(x: bounds.midX, y: bounds.midY)
let insideRadius = radius - padding
let pointLeft = CGPoint(x: centerPoint.x + insideRadius*CGFloat(cos(7*Double.pi/6)), y: centerPoint.y - insideRadius*CGFloat(sin(7*Double.pi/6)))
let pointRight = CGPoint(x: centerPoint.x + insideRadius*CGFloat(cos(11*Double.pi/6)), y: centerPoint.y - insideRadius*CGFloat(sin(11*Double.pi/6)))
let deltaX = pointRight.x - pointLeft.x //distance on circle between points at 7pi/6 and 11pi/6
let sliderSize = CGSize(width: deltaX * 0.75, height: 0.08 * (bounds.height - padding*2))//bounds.height
shadeSlider.frame = CGRect(x: bounds.midX - sliderSize.width/2, y: pointLeft.y - sliderSize.height/2, width: sliderSize.width, height: sliderSize.height)
shadeSlider.handleCenterX = shadeSlider.bounds.width/2 //set handle starting position
shadeSlider.layoutLayerFrames() //call sliders' layout function
}
/*
Pre: dependant on addButton
*/
func layoutColorToggleButton() {
let inset = bounds.height/16
colorToggleButton.frame = CGRect(x: inset, y: inset, width: addButton.frame.width/2.5, height: addButton.frame.width/2.5)
colorToggleButton.layoutSubviews()
}
func updateHexLabel(){
hexLabel.text = "#" + currentColor.hexCode
}
func updateCurrentColor(_ color: UIColor){
currentColor = color
addButton.color = color
self.sendActions(for: .valueChanged)
}
@objc open func togglePickerColorMode() {
colorToggleButton.isEnabled = false // Lock
// Redraw Assets (i.e. Large circle ring)
setNeedsDisplay()
// Update subcomponents for color change
if modeIsGrayscale {
//Change color of colorToggleButton to the last handle color
let lightColor = handleView.color
let shadedColor = handleView.color.darkerColor(0.25)
colorToggleButton.hueColorGradientLayer.colors = [lightColor.cgColor, shadedColor.cgColor]
let gray = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1)
self.handleView.color = gray
self.updateCurrentColor(gray)
self.updateHexLabel()
//Update color for shade slider
shadeSlider.primaryColor = gray
}
else {
// Update for normal rainbow
// Use color stored in toggle button (set above), or else default to the angle it is at
var hueColor: UIColor
if let storedColor = colorToggleButton.hueColorGradientLayer.colors?[0] {
hueColor = UIColor(cgColor: (storedColor as! CGColor))
currentAngle = angleForColor(hueColor)
self.layoutHandleLine()
self.layoutHandle()
}
else {
let currentAngle = self.angleToCenterFromPoint(self.handleView.center)
hueColor = self.colorOnWheelFromAngle(currentAngle)
}
self.handleView.color = hueColor
self.updateCurrentColor(hueColor)
self.updateHexLabel()
//Update color for shade slider
shadeSlider.primaryColor = hueColor
}
colorToggleButton.isEnabled = true // Unlock
}
//MARK: - Helper Methods
private func angleToCenterFromPoint(_ point: CGPoint) -> Float {
let deltaX = Float(self.bounds.midX - point.x)
let deltaY = Float(self.bounds.midY - point.y)
let angle = atan2f(deltaX, deltaY)
// Convert the angle to be between 0 and 2PI
var adjustedAngle = angle + Float.pi/2
if (adjustedAngle < 0){ //Left side (Q2 and Q3)
adjustedAngle += Float.pi*2
}
return adjustedAngle
}
/* Find the angle relative to the center of the frame and uses the angle to find what color lies there */
private func colorOnWheelFromAngle(_ angle: Float) -> UIColor {
return UIColor(hue: CGFloat(Double(angle)/(2*Double.pi)), saturation: 1, brightness: 1, alpha: 1)
}
private func angleForColor(_ color: UIColor) -> Float {
var hue: CGFloat = 0
color.getHue(&hue, saturation: nil, brightness: nil, alpha: nil)
return Float(hue * CGFloat.pi * 2)
}
/* Returns a position centered on the wheel for a given angle */
private func positionOnWheelFromAngle(_ angle: Float) -> CGPoint{
let buffer = padding + stroke/2
return CGPoint(x: self.bounds.midX + ((radius - buffer) * CGFloat(cos(-angle))), y: self.bounds.midY + ((radius - buffer) * CGFloat(sin(-angle))))
return newImage
}
}
extension ChromaColorPicker: ChromaShadeSliderDelegate{
public func shadeSliderChoseColor(_ slider: ChromaShadeSlider, color: UIColor) {
self.updateCurrentColor(color) //update main controller for selected color
self.updateHexLabel()
extension CGImage {
func resizeImageUsingVImage(size:CGSize) -> CGImage? {
let cgImage = self
var format = vImage_CGImageFormat(bitsPerComponent: 8, bitsPerPixel: 32, colorSpace: nil, bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.first.rawValue), version: 0, decode: nil, renderingIntent: CGColorRenderingIntent.defaultIntent)
var sourceBuffer = vImage_Buffer()
defer {
free(sourceBuffer.data)
}
var error = vImageBuffer_InitWithCGImage(&sourceBuffer, &format, nil, cgImage, numericCast(kvImageNoFlags))
guard error == kvImageNoError else { return nil }
// create a destination buffer
//let scale = self.scale
let destWidth = Int(size.width)
let destHeight = Int(size.height)
let bytesPerPixel = self.bitsPerPixel/8
let destBytesPerRow = destWidth * bytesPerPixel
let destData = UnsafeMutablePointer<UInt8>.allocate(capacity: destHeight * destBytesPerRow)
defer {
destData.deallocate(capacity: destHeight * destBytesPerRow)
}
var destBuffer = vImage_Buffer(data: destData, height: vImagePixelCount(destHeight), width: vImagePixelCount(destWidth), rowBytes: destBytesPerRow)
// scale the image
error = vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, numericCast(kvImageHighQualityResampling))
guard error == kvImageNoError else { return nil }
// create a CGImage from vImage_Buffer
var destCGImage = vImageCreateCGImageFromBuffer(&destBuffer, &format, nil, nil, numericCast(kvImageNoFlags), &error)?.takeRetainedValue()
guard error == kvImageNoError else { return nil }
// create a UIImage
// defer {
// destCGImage = nil
// }
return destCGImage
// let resizedImage = destCGImage.flatMap { UIImage(cgImage: $0, scale: 0.0, orientation: self.imageOrientation) }
// destCGImage = nil
// return resizedImage
}
}

View File

@ -0,0 +1,13 @@
//
// ColorWheelView.swift
// ChromaColorPicker
//
// Created by Jon Cardasis on 4/11/19.
// Copyright © 2019 Jonathan Cardasis. All rights reserved.
//
import UIKit
public class ColorWheelView: UIView {
}

View File

@ -0,0 +1,520 @@
//
// ChromaColorPicker.swift
//
// Copyright © 2016 Jonathan Cardasis. All rights reserved.
//
// 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 protocol ChromaColorPickerDelegate {
/* Called when the user taps the add button in the center */
func colorPickerDidChooseColor(_ colorPicker: ChromaColorPicker, color: UIColor)
}
open class ChromaColorPicker: UIControl {
open var hexLabel: UILabel!
open var shadeSlider: ChromaShadeSlider!
open var handleView: ChromaHandle!
open var handleLine: CAShapeLayer!
open var addButton: ChromaAddButton!
open var colorToggleButton: ColorModeToggleButton!
private var modeIsGrayscale: Bool {
return colorToggleButton.colorState == .grayscale
}
private enum ColorSpace {
case rainbow
case grayscale
}
open private(set) var currentColor = UIColor.red
open var supportsShadesOfGray: Bool = false {
didSet {
if supportsShadesOfGray {
colorToggleButton.isHidden = false
}
else {
colorToggleButton.isHidden = true
}
}
}
open var delegate: ChromaColorPickerDelegate?
open var currentAngle: Float = 0
open private(set) var radius: CGFloat = 0
open var stroke: CGFloat = 1
open var padding: CGFloat = 15
open var handleSize: CGSize{
get{ return CGSize(width: self.bounds.width * 0.1, height: self.bounds.height * 0.1) }
}
//MARK: - Initialization
override public init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}
private func commonInit(){
self.backgroundColor = UIColor.clear
let minDimension = min(self.bounds.size.width, self.bounds.size.height)
radius = minDimension/2 - handleSize.width/2
/* Setup Handle */
handleView = ChromaHandle(frame: CGRect(x: 0,y: 0, width: handleSize.width, height: handleSize.height))
handleView.shadowOffset = CGSize(width: 0,height: 2)
/* Setup pan gesture for handle */
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(ChromaColorPicker.handleWasMoved(_:)))
handleView.addGestureRecognizer(panRecognizer)
/* Setup Add Button */
addButton = ChromaAddButton()
self.layoutAddButton() //layout frame
addButton.addTarget(self, action: #selector(ChromaColorPicker.addButtonPressed(_:)), for: .touchUpInside)
/* Setup Handle Line */
handleLine = CAShapeLayer()
handleLine.lineWidth = 2
handleLine.strokeColor = UIColor.white.withAlphaComponent(0.2).cgColor
/* Setup Color Hex Label */
hexLabel = UILabel()
self.layoutHexLabel() //layout frame
hexLabel.layer.cornerRadius = 2
hexLabel.adjustsFontSizeToFitWidth = true
hexLabel.textAlignment = .center
hexLabel.textColor = UIColor(red: 51/255.0, green:51/255.0, blue: 51/255.0, alpha: 0.65)
/* Setup Shade Slider */
shadeSlider = ChromaShadeSlider()
shadeSlider.delegate = self
self.layoutShadeSlider()
shadeSlider.addTarget(self, action: #selector(ChromaColorPicker.sliderEditingDidEnd(_:)), for: .editingDidEnd)
/* Setup Color Mode Toggle Button */
colorToggleButton = ColorModeToggleButton()
self.layoutColorToggleButton() //layout frame
colorToggleButton.colorState = .hue // Default as starting state is hue
colorToggleButton.addTarget(self, action: #selector(togglePickerColorMode), for: .touchUpInside)
colorToggleButton.isHidden = !supportsShadesOfGray // default to hiding if not supported
/* Add components to view */
self.layer.addSublayer(handleLine)
self.addSubview(shadeSlider)
self.addSubview(hexLabel)
self.addSubview(handleView)
self.addSubview(addButton)
self.addSubview(colorToggleButton)
}
override open func willMove(toSuperview newSuperview: UIView?) {
/* Get the starting color */
currentColor = colorOnWheelFromAngle(currentAngle)
handleView.center = positionOnWheelFromAngle(currentAngle) //update pos for angle
self.layoutHandleLine() //layout the lines positioning
handleView.color = currentColor
addButton.color = currentColor
shadeSlider.primaryColor = currentColor
self.updateHexLabel() //update for hex value
}
open func adjustToColor(_ color: UIColor){
/* Apply saturation and brightness from previous color to current one */
var saturation: CGFloat = 0.0
var brightness: CGFloat = 0.0
var hue: CGFloat = 0.0
var alpha: CGFloat = 0.0
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
let newColor = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
/* Set the slider value for the new color and update addButton */
shadeSlider.primaryColor = UIColor(hue: hue, saturation: 1, brightness: 1, alpha: 1) //Set a color recognzied on the color wheel
/* Update the angle and currentColor */
currentAngle = angleForColor(newColor)
currentColor = newColor
if brightness < 1.0 && saturation < 1.0 {
/* Modifies the Shade Slider to handle adjusting to colors outside of the Chroma scope */
shadeSlider.primaryColor = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: 1)
shadeSlider.currentValue = 0
} else if brightness < 1.0 { //currentValue is on the left side of the slider
shadeSlider.currentValue = brightness-1
}else{
shadeSlider.currentValue = -(saturation-1)
}
shadeSlider.updateHandleLocation() //update the handle location now that the value is set
addButton.color = newColor
/* Will layout based on new angle */
self.layoutHandle()
self.layoutHandleLine()
self.updateHexLabel()
}
//MARK: - Handle Touches
override open func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
//Overriden to prevent uicontrolevents being called from the super
}
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
let touchPoint = touches.first!.location(in: self)
if handleView.frame.contains(touchPoint) {
self.sendActions(for: .touchDown)
/* Enlarge Animation */
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseIn, animations: { () -> Void in
self.handleView.transform = CGAffineTransform(scaleX: 1.45, y: 1.45)
}, completion: nil)
}
}
override open func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
//Run this animation after a pan or here if touches are released
if handleView.transform.d > 1 { //if scale is larger than 1 (already animated)
self.executeHandleShrinkAnimation()
}
}
@objc func handleWasMoved(_ recognizer: UIPanGestureRecognizer) {
switch(recognizer.state){
case UIGestureRecognizer.State.changed:
let touchPosition = recognizer.location(in: self)
self.moveHandleTowardPoint(touchPosition)
self.sendActions(for: .touchDragInside)
break
case UIGestureRecognizer.State.ended:
/* Shrink Animation */
self.executeHandleShrinkAnimation()
break
default:
break
}
}
private func executeHandleShrinkAnimation(){
self.sendActions(for: .touchUpInside)
self.sendActions(for: .editingDidEnd)
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseOut, animations: { () -> Void in
self.handleView.transform = CGAffineTransform(scaleX: 1, y: 1)
}, completion: nil)
}
private func moveHandleTowardPoint(_ point: CGPoint){
currentAngle = angleToCenterFromPoint(point) //Find the angle of point to the frames center
//Layout Handle
self.layoutHandle()
//Layout Line
self.layoutHandleLine()
if modeIsGrayscale {
// If mode is grayscale do not update colors and end early
return
}
//Update color for shade slider
shadeSlider.primaryColor = handleView.color//currentColor
//Update color for add button if a shade isnt selected
if shadeSlider.currentValue == 0 {
self.updateCurrentColor(shadeSlider.currentColor)
}
//Update Text Field display value
self.updateHexLabel()
}
@objc func addButtonPressed(_ sender: ChromaAddButton){
//Do a 'bob' animation
UIView.animate(withDuration: 0.2,
delay: 0,
options: .curveEaseIn,
animations: { () -> Void in
sender.transform = CGAffineTransform(scaleX: 1.1, y: 1.1)
}, completion: { (done) -> Void in
UIView.animate(withDuration: 0.1, animations: { () -> Void in
sender.transform = CGAffineTransform(scaleX: 1, y: 1)
})
})
delegate?.colorPickerDidChooseColor(self, color: sender.color) //Delegate call
}
@objc func sliderEditingDidEnd(_ sender: ChromaShadeSlider){
self.sendActions(for: .editingDidEnd)
}
//MARK: - Drawing
override open func draw(_ rect: CGRect) {
super.draw(rect)
let ctx = UIGraphicsGetCurrentContext()
let colorSpace: ColorSpace = (modeIsGrayscale) ? .grayscale : .rainbow
drawCircleRing(in: ctx, outerRadius: radius - padding, innerRadius: radius - stroke - padding, resolution: 1, colorSpace: colorSpace)
}
/*
Resolution should be between 0.1 and 1
colorSpace - either rainbow or grayscale
*/
private func drawCircleRing(in context: CGContext?, outerRadius: CGFloat, innerRadius: CGFloat, resolution: Float, colorSpace: ColorSpace){
context?.saveGState()
context?.translateBy(x: self.bounds.midX, y: self.bounds.midY) //Move context to center
let subdivisions:CGFloat = CGFloat(resolution * 512) //Max subdivisions of 512
let innerHeight = (CGFloat.pi*innerRadius)/subdivisions //height of the inner wall for each segment
let outterHeight = (CGFloat.pi*outerRadius)/subdivisions
let segment = UIBezierPath()
segment.move(to: CGPoint(x: innerRadius, y: -innerHeight/2))
segment.addLine(to: CGPoint(x: innerRadius, y: innerHeight/2))
segment.addLine(to: CGPoint(x: outerRadius, y: outterHeight/2))
segment.addLine(to: CGPoint(x: outerRadius, y: -outterHeight/2))
segment.close()
//Draw each segment and rotate around the center
for i in 0 ..< Int(ceil(subdivisions)) {
if modeIsGrayscale {
UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1).set() //Gray
}
else { // Draw rainbow
UIColor(hue: CGFloat(i)/subdivisions, saturation: 1, brightness: 1, alpha: 1).set()
}
segment.fill()
let lineTailSpace = (CGFloat.pi*2)*outerRadius/subdivisions //The amount of space between the tails of each segment
segment.lineWidth = lineTailSpace //allows for seemless scaling
segment.stroke()
//Rotate to correct location
let rotate = CGAffineTransform(rotationAngle: -((CGFloat.pi*2)/subdivisions)) //rotates each segment
segment.apply(rotate)
}
context?.translateBy(x: -self.bounds.midX, y: -self.bounds.midY) //Move context back to original position
context?.restoreGState()
}
//MARK: - Layout Updates
/* Re-layout view and all its subview and drawings */
open func layout() {
self.setNeedsDisplay() //mark view as dirty
let minDimension = min(self.bounds.size.width, self.bounds.size.height)
radius = minDimension/2 - handleSize.width/2 //create radius for new size
self.layoutAddButton()
//Update handle's size
handleView.frame = CGRect(origin: .zero, size: handleSize)
self.layoutHandle()
//Ensure colors are updated
self.updateCurrentColor(handleView.color)
shadeSlider.primaryColor = handleView.color
self.layoutShadeSlider()
self.layoutHandleLine()
self.layoutHexLabel()
self.layoutColorToggleButton()
}
open func layoutAddButton(){
let addButtonSize = CGSize(width: self.bounds.width/5, height: self.bounds.height/5)
addButton.frame = CGRect(x: self.bounds.midX - addButtonSize.width/2, y: self.bounds.midY - addButtonSize.height/2, width: addButtonSize.width, height: addButtonSize.height)
}
/*
Update the handleView's position and color for the currentAngle
*/
func layoutHandle(){
let angle = currentAngle //Preserve value in case it changes
let newPosition = positionOnWheelFromAngle(angle) //find the correct position on the color wheel
//Update handle position
handleView.center = newPosition
if !modeIsGrayscale {
//Update color for the movement when color mode is hue
handleView.color = colorOnWheelFromAngle(angle)
}
}
/*
Updates the line view's position for the current angle
Pre: dependant on addButtons position & current angle
*/
func layoutHandleLine(){
let linePath = UIBezierPath()
linePath.move(to: addButton.center)
linePath.addLine(to: positionOnWheelFromAngle(currentAngle))
handleLine.path = linePath.cgPath
}
/*
Pre: dependant on addButtons position
*/
func layoutHexLabel(){
hexLabel.frame = CGRect(x: 0, y: 0, width: addButton.bounds.width*1.5, height: addButton.bounds.height/3)
hexLabel.center = CGPoint(x: self.bounds.midX, y: (addButton.frame.origin.y + (padding + handleView.frame.height/2 + stroke/2))/1.75) //Divided by 1.75 not 2 to make it a bit lower
hexLabel.font = UIFont(name: "Menlo-Regular", size: hexLabel.bounds.height)
}
/*
Pre: dependant on radius
*/
func layoutShadeSlider(){
/* Calculate proper length for slider */
let centerPoint = CGPoint(x: bounds.midX, y: bounds.midY)
let insideRadius = radius - padding
let pointLeft = CGPoint(x: centerPoint.x + insideRadius*CGFloat(cos(7*Double.pi/6)), y: centerPoint.y - insideRadius*CGFloat(sin(7*Double.pi/6)))
let pointRight = CGPoint(x: centerPoint.x + insideRadius*CGFloat(cos(11*Double.pi/6)), y: centerPoint.y - insideRadius*CGFloat(sin(11*Double.pi/6)))
let deltaX = pointRight.x - pointLeft.x //distance on circle between points at 7pi/6 and 11pi/6
let sliderSize = CGSize(width: deltaX * 0.75, height: 0.08 * (bounds.height - padding*2))//bounds.height
shadeSlider.frame = CGRect(x: bounds.midX - sliderSize.width/2, y: pointLeft.y - sliderSize.height/2, width: sliderSize.width, height: sliderSize.height)
shadeSlider.handleCenterX = shadeSlider.bounds.width/2 //set handle starting position
shadeSlider.layoutLayerFrames() //call sliders' layout function
}
/*
Pre: dependant on addButton
*/
func layoutColorToggleButton() {
let inset = bounds.height/16
colorToggleButton.frame = CGRect(x: inset, y: inset, width: addButton.frame.width/2.5, height: addButton.frame.width/2.5)
colorToggleButton.layoutSubviews()
}
func updateHexLabel(){
hexLabel.text = "#" + currentColor.hexCode
}
func updateCurrentColor(_ color: UIColor){
currentColor = color
addButton.color = color
self.sendActions(for: .valueChanged)
}
@objc open func togglePickerColorMode() {
colorToggleButton.isEnabled = false // Lock
// Redraw Assets (i.e. Large circle ring)
setNeedsDisplay()
// Update subcomponents for color change
if modeIsGrayscale {
//Change color of colorToggleButton to the last handle color
let lightColor = handleView.color
let shadedColor = handleView.color.darkerColor(0.25)
colorToggleButton.hueColorGradientLayer.colors = [lightColor.cgColor, shadedColor.cgColor]
let gray = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1)
self.handleView.color = gray
self.updateCurrentColor(gray)
self.updateHexLabel()
//Update color for shade slider
shadeSlider.primaryColor = gray
}
else {
// Update for normal rainbow
// Use color stored in toggle button (set above), or else default to the angle it is at
var hueColor: UIColor
if let storedColor = colorToggleButton.hueColorGradientLayer.colors?[0] {
hueColor = UIColor(cgColor: (storedColor as! CGColor))
currentAngle = angleForColor(hueColor)
self.layoutHandleLine()
self.layoutHandle()
}
else {
let currentAngle = self.angleToCenterFromPoint(self.handleView.center)
hueColor = self.colorOnWheelFromAngle(currentAngle)
}
self.handleView.color = hueColor
self.updateCurrentColor(hueColor)
self.updateHexLabel()
//Update color for shade slider
shadeSlider.primaryColor = hueColor
}
colorToggleButton.isEnabled = true // Unlock
}
//MARK: - Helper Methods
private func angleToCenterFromPoint(_ point: CGPoint) -> Float {
let deltaX = Float(self.bounds.midX - point.x)
let deltaY = Float(self.bounds.midY - point.y)
let angle = atan2f(deltaX, deltaY)
// Convert the angle to be between 0 and 2PI
var adjustedAngle = angle + Float.pi/2
if (adjustedAngle < 0){ //Left side (Q2 and Q3)
adjustedAngle += Float.pi*2
}
return adjustedAngle
}
/* Find the angle relative to the center of the frame and uses the angle to find what color lies there */
private func colorOnWheelFromAngle(_ angle: Float) -> UIColor {
return UIColor(hue: CGFloat(Double(angle)/(2*Double.pi)), saturation: 1, brightness: 1, alpha: 1)
}
private func angleForColor(_ color: UIColor) -> Float {
var hue: CGFloat = 0
color.getHue(&hue, saturation: nil, brightness: nil, alpha: nil)
return Float(hue * CGFloat.pi * 2)
}
/* Returns a position centered on the wheel for a given angle */
private func positionOnWheelFromAngle(_ angle: Float) -> CGPoint{
let buffer = padding + stroke/2
return CGPoint(x: self.bounds.midX + ((radius - buffer) * CGFloat(cos(-angle))), y: self.bounds.midY + ((radius - buffer) * CGFloat(sin(-angle))))
}
}
extension ChromaColorPicker: ChromaShadeSliderDelegate{
public func shadeSliderChoseColor(_ slider: ChromaShadeSlider, color: UIColor) {
self.updateCurrentColor(color) //update main controller for selected color
self.updateHexLabel()
}
}

View File

@ -1,20 +1,17 @@
//
// ChromaColorPickerSpec.swift
// ChromaColorPickerTest.swift
// ChromaColorPickerTests
//
// Created by Jon Cardasis on 2/3/19.
// Copyright © 2019 Jonathan Cardasis. All rights reserved.
//
import Quick
import Nimble
import XCTest
@testable import ChromaColorPicker
class ChromaColorPickerSpec: QuickSpec {
override func spec() {
class ChromaColorPickerTests: XCTestCase {
it("is an empty test") {
func testDefault() {
}
}
}