Removed legacy code and updated Fastfile to push podspec

This commit is contained in:
Jonathan Cardasis 2019-05-02 17:14:16 -04:00
parent b41d2e0cd0
commit fb0d1e8462
12 changed files with 31 additions and 1260 deletions

1
.swift-version Normal file
View File

@ -0,0 +1 @@
4.2

View File

@ -12,6 +12,6 @@ Pod::Spec.new do |s|
s.author = "Jonathan Cardasis"
s.platform = :ios, "9.0"
s.source = { :git => "https://github.com/joncardasis/ChromaColorPicker.git", :tag => "#{s.version}" }
s.source_files = "Source/*.swift"
s.source_files = "Source/**/*.swift"
end

View File

@ -78,12 +78,6 @@
FC1BD8BD2207D7B700817AF3 /* ChromaColorPickerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChromaColorPickerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
FC1BD8CA2207FCE100817AF3 /* ChromaColorPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChromaColorPicker.swift; sourceTree = "<group>"; };
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>"; };
FC4387C52262556600F739F1 /* ChromaBrightnessSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromaBrightnessSlider.swift; sourceTree = "<group>"; };
FC4387C822625C7000F739F1 /* SliderTrackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderTrackView.swift; sourceTree = "<group>"; };
FC4387CA22625DA800F739F1 /* SliderHandleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderHandleView.swift; sourceTree = "<group>"; };
@ -132,7 +126,6 @@
children = (
FC4387C722625C5F00F739F1 /* Helpers */,
FCCA42A82260325F00BE2FF9 /* Extensions */,
FCCA427822601F8800BE2FF9 /* Legacy */,
3503B8311F2689BC00750356 /* ChromaColorPicker.h */,
3503B8321F2689BC00750356 /* Info.plist */,
FCEA4E262235AAA200C0A1B6 /* ChromaColorPicker.swift */,
@ -200,19 +193,6 @@
path = Helpers;
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>";
};
FCCA42A82260325F00BE2FF9 /* Extensions */ = {
isa = PBXGroup;
children = (

View File

@ -1,125 +0,0 @@
# ChromaColorPicker :art:
![Supported Version](https://img.shields.io/badge/Swift-4.2-yellow.svg)
![Platform](https://img.shields.io/badge/platform-iOS-lightgray.svg)
![License](https://img.shields.io/badge/license-MIT-blue.svg)
![Carthage](https://img.shields.io/badge/Carthage-✔-green.svg)
![CocoaPods](https://img.shields.io/badge/CocoaPods-1.7.1-green.svg)
![CocoaPods](https://img.shields.io/badge/CocoaPods-1.7.1-green.svg)
[![Travis CI](https://travis-ci.com/joncardasis/ChromaColorPicker.svg?branch=develop)](https://travis-ci.com/joncardasis/ChromaColorPicker)
*An intuitive iOS color picker built in Swift.*
Supports hue and grayscale modes to make choosing the right color easy and fun!
<div>
<img src="../assets/Screenshot-With-BG.png?raw=true" height="350" style="margin:8px;">
<img src="../assets/Screenshot-Grayscale.png?raw=true" height="350" style="margin:8px;">
</div>
## Installation
### Carthage
```
github "joncardasis/ChromaColorPicker"
```
### Cocoapods
```
pod 'ChromaColorPicker'
```
### Manually
Add all files from the ChromaColorPicker folder to your project.
## Examples
```Swift
let neatColorPicker = ChromaColorPicker(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
neatColorPicker.delegate = self //ChromaColorPickerDelegate
neatColorPicker.padding = 5
neatColorPicker.stroke = 3
neatColorPicker.hexLabel.textColor = UIColor.white
view.addSubview(neatColorPicker)
```
<img src="../assets/demo.gif?raw=true" width="225">
If the ChromaColorPicker or any of its properties are later updated after being added to a view, the `layout()` function should be called to update the view.
```Swift
let neatColorPicker = ChromaColorPicker(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
view.addSubview(neatColorPicker)
neatColorPicker.padding = 0
neatColorPicker.hexLabel.hidden = true
neatColorPicker.layout()
```
You can also set the color of the picker anytime by using the `adjustToColor(color:)` function.
```Swift
let neatColorPicker = ChromaColorPicker(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
...
neatColorPicker.adjustToColor(UIColor.green)
...
```
### Enable Grayscale Support
A toggle button can be enabled/disabled to allow for grayscale selections by using the `supportsShadesOfGray` property.
```Swift
let neatColorPicker = ChromaColorPicker(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
...
neatColorPicker.supportsShadesOfGray = true // Normally false be default
```
## Customization
<img src="../assets/Design_Breakdown.png?raw=true" width="350">
### Properties
| Property | Description |
| :-------------: |:-------------|
| delegate | ChromaColorPickerDelegate |
| padding | The padding on each side of the view (default=10) |
| stroke | The stroke of the rainbow track (default=1) |
| currentColor | The currently set color by the control. It is displayed in the add button. Use `adjustToColor(color: UIColor)` to update the color.|
| currentAngle | The angle which the handle is currently sitting at. Can be changed and the view can be re-drawn using `layout()` to show the change.
| handleSize | Returns the size of the handle. |
| supportsShadesOfGray | True/False if a toggle for supporting grayscale colors should be shown. |
### Functions
| Function | Description |
| :-------------: |:-------------|
|layout() | Layout the entire picker and all its subviews.|
|adjustToColor(color: ) | Updates the picker to a specific color.|
### Sub-Components
Sub-Components can be hidden and customized to the preferred liking.
| Component | Description |
| :-------------: |:-------------|
| hexLabel | A UILabel which displays the hex value of the current color. |
| shadeSlider | A custom slider which adjusts the shade of the current color. |
| addButton | A custom UIButton in the center of the control. The `colorPickerDidChooseColor(colorPicker: color:)` delegate function is called when this is tapped. |
| handleView | A ChromaHandle (custom UIView) which displays the current color and can be moved around the circle.|
| handleLine | A line which is drawn from the addButton to the handleView. |
| colorToggleButton | A custom UIButton which appears if `supportsShadesOfGray` is set to true and will switch the picker to a grayscale mode if pressed.|
### Supported UIControlEvents
`.touchDown` -> called when the handle is first grabbed
`.touchUpInside` -> called when handle is let go
`.valueChanged` -> called whenever the color has changed hue or shade
`.touchDragInside` -> called when the handle has moved by a drag action
`.editingDidEnd` -> called when either the handle is let go or slider is let go
## Additional Info
Check out the [Wiki](https://github.com/joncardasis/ChromaColorPicker/wiki/Challenges-and-Solutions) if you're interested in reading into how the color wheel was created.
## License
ChromaColorPicker is available under the MIT license. See the LICENSE file for more info.

View File

@ -1,94 +0,0 @@
//
// ChromaAddButton.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
open class ChromaAddButton: UIButton {
open var color = UIColor.gray{
didSet{
if let layer = circleLayer{
layer.fillColor = color.cgColor
layer.strokeColor = color.darkerColor(0.075).cgColor
}
}
}
override open var frame: CGRect{ //update on frame change
didSet{
self.layoutCircleLayer()
self.layoutPlusIconLayer()
}
}
open var circleLayer: CAShapeLayer?
open var plusIconLayer: CAShapeLayer?
override public init(frame: CGRect) {
super.init(frame: frame)
self.createGraphics()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.createGraphics()
}
open func createGraphics(){
circleLayer = CAShapeLayer()
self.layoutCircleLayer()
circleLayer!.fillColor = color.cgColor
self.layer.addSublayer(circleLayer!)
/* Create Plus Icon */
let plusPath = UIBezierPath()
plusPath.move(to: CGPoint(x: self.bounds.width/2 - self.bounds.width/8, y: self.bounds.height/2))
plusPath.addLine(to: CGPoint(x: self.bounds.width/2 + self.bounds.width/8, y: self.bounds.height/2))
plusPath.move(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 + self.bounds.height/8))
plusPath.addLine(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 - self.bounds.height/8))
plusIconLayer = CAShapeLayer()
self.layoutPlusIconLayer()
plusIconLayer!.strokeColor = UIColor.white.cgColor
self.layer.addSublayer(plusIconLayer!)
}
open func layoutCircleLayer(){
if let layer = circleLayer{
layer.path = UIBezierPath(ovalIn: self.bounds).cgPath
layer.lineWidth = frame.width * 0.04 //4 for size (100,100)
}
}
open func layoutPlusIconLayer(){
if let layer = plusIconLayer{
let plusPath = UIBezierPath()
plusPath.move(to: CGPoint(x: self.bounds.width/2 - self.bounds.width/8, y: self.bounds.height/2))
plusPath.addLine(to: CGPoint(x: self.bounds.width/2 + self.bounds.width/8, y: self.bounds.height/2))
plusPath.move(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 + self.bounds.height/8))
plusPath.addLine(to: CGPoint(x: self.bounds.width/2, y: self.bounds.height/2 - self.bounds.height/8))
layer.path = plusPath.cgPath
layer.lineWidth = frame.width * 0.03
}
}
}

View File

@ -1,520 +0,0 @@
//
// 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,74 +0,0 @@
//
// ChromaHandle.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
open class ChromaHandle: UIView {
open var color = UIColor.black {
didSet{
circleLayer.fillColor = color.cgColor
}
}
override open var frame: CGRect{
didSet { self.layoutCircleLayer() }
}
open var circleLayer = CAShapeLayer()
open var shadowOffset: CGSize?{
set{
if let offset = newValue {
circleLayer.shadowColor = UIColor.black.cgColor
circleLayer.shadowRadius = 3
circleLayer.shadowOpacity = 0.3
circleLayer.shadowOffset = offset
}
}
get{
return circleLayer.shadowOffset
}
}
override public init(frame: CGRect) {
super.init(frame:frame)
self.backgroundColor = UIColor.clear
/* Add Shape Layer */
//circleLayer.shouldRasterize = true
self.layoutCircleLayer()
circleLayer.strokeColor = UIColor.white.cgColor
circleLayer.fillColor = color.cgColor
self.layer.addSublayer(circleLayer)
}
open func layoutCircleLayer(){
circleLayer.path = UIBezierPath(ovalIn: self.bounds).cgPath
circleLayer.strokeColor = UIColor.white.cgColor
circleLayer.lineWidth = frame.width/8.75 //4
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@ -1,216 +0,0 @@
//
// ChromaShadeSlider.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
open class ChromaSliderTrackLayer: CALayer{
public let gradient = CAGradientLayer()
override public init() {
super.init()
gradient.actions = ["position" : NSNull(), "bounds" : NSNull(), "path" : NSNull()]
self.addSublayer(gradient)
}
override init(layer: Any) {
super.init(layer: layer)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
public protocol ChromaShadeSliderDelegate {
func shadeSliderChoseColor(_ slider: ChromaShadeSlider, color: UIColor)
}
open class ChromaShadeSlider: UIControl {
open var currentValue: CGFloat = 0.0 //range of {-1,1}
public let trackLayer = ChromaSliderTrackLayer()
public let handleView = ChromaHandle()
open var handleWidth: CGFloat{ return self.bounds.height }
open var handleCenterX: CGFloat = 0.0
open var delegate: ChromaShadeSliderDelegate?
open var primaryColor = UIColor.gray{
didSet{
self.changeColorHue(to: currentColor)
self.updateGradientTrack(for: primaryColor)
}
}
/* The computed color of the primary color with shading based on the currentValue */
open var currentColor: UIColor{
get{
if currentValue < 0 {//darken
return primaryColor.darkerColor(-currentValue)
}
else{ //lighten
return primaryColor.lighterColor(currentValue)
}
}
}
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 = nil
handleCenterX = self.bounds.width/2
trackLayer.backgroundColor = UIColor.blue.cgColor
trackLayer.masksToBounds = true
trackLayer.actions = ["position" : NSNull(), "bounds" : NSNull(), "path" : NSNull()] //disable implicit animations
self.layer.addSublayer(trackLayer)
handleView.color = UIColor.blue
handleView.circleLayer.borderWidth = 3
handleView.isUserInteractionEnabled = false //disable interaction for touch events
self.addSubview(handleView)
let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(doubleTapRecognized))
doubleTapGesture.numberOfTapsRequired = 2
self.addGestureRecognizer(doubleTapGesture)
self.layoutLayerFrames()
self.changeColorHue(to: currentColor)
self.updateGradientTrack(for: primaryColor)
}
override open func didMoveToSuperview() {
self.updateGradientTrack(for: primaryColor)
}
open func layoutLayerFrames(){
trackLayer.frame = self.bounds.insetBy(dx: handleWidth/2, dy: self.bounds.height/4) //Make half the height of the bounds
trackLayer.cornerRadius = trackLayer.bounds.height/2
self.updateGradientTrack(for: primaryColor)
self.updateHandleLocation()
self.layoutHandleFrame()
}
//Lays out handle according to the currentValue on slider
open func layoutHandleFrame(){
handleView.frame = CGRect(x: handleCenterX - handleWidth/2, y: self.bounds.height/2 - handleWidth/2, width: handleWidth, height: handleWidth)
}
open func changeColorHue(to newColor: UIColor){
handleView.color = newColor
if currentValue != 0 { //Don't call delegate if the color hasnt changed
self.delegate?.shadeSliderChoseColor(self, color: newColor)
}
}
open func updateGradientTrack(for color: UIColor){
trackLayer.gradient.frame = trackLayer.bounds
trackLayer.gradient.startPoint = CGPoint(x: 0, y: 0.5)
trackLayer.gradient.endPoint = CGPoint(x: 1, y: 0.5)
//Gradient is for astetics - the slider is actually between black and white
trackLayer.gradient.colors = [color.darkerColor(0.65).cgColor, color.cgColor, color.lighterColor(0.65).cgColor]
}
//Updates handeles location based on currentValue
open func updateHandleLocation(){
handleCenterX = (currentValue+1)/2 * (bounds.width - handleView.bounds.width) + handleView.bounds.width/2
handleView.color = currentColor
self.layoutHandleFrame()
}
override open func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let location = touch.location(in: self)
if handleView.frame.contains(location) {
return true
}
return false
}
override open func continueTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
let location = touch.location(in: self)
//Update for center point
handleCenterX = location.x
handleCenterX = fittedValueInBounds(handleCenterX) //adjust value to fit in bounds if needed
//Update current value
currentValue = ((handleCenterX - handleWidth/2)/trackLayer.bounds.width - 0.5) * 2 //find current value between {-1,1} of the slider
//Update handle color
self.changeColorHue(to: currentColor)
//Update layers frames
CATransaction.begin()
CATransaction.setDisableActions(true)
self.layoutHandleFrame()
CATransaction.commit()
self.sendActions(for: .valueChanged)
return true
}
override open func endTracking(_ touch: UITouch?, with event: UIEvent?) {
self.sendActions(for: .editingDidEnd)
}
@objc func doubleTapRecognized(_ recognizer: UITapGestureRecognizer){
let location = recognizer.location(in: self)
guard handleView.frame.contains(location) else {
return
}
//Tap is on handle
resetHandleToCenter()
}
open func resetHandleToCenter(){
handleCenterX = self.bounds.width/2
self.layoutHandleFrame()
handleView.color = primaryColor
currentValue = 0.0
self.sendActions(for: .valueChanged)
self.delegate?.shadeSliderChoseColor(self, color: currentColor)
}
/* Helper Methods */
//Returns a CGFloat for the highest/lowest possble value such that it is inside the views bounds
private func fittedValueInBounds(_ value: CGFloat) -> CGFloat {
return min(max(value, trackLayer.frame.minX), trackLayer.frame.maxX)
}
}

View File

@ -1,119 +0,0 @@
//
// ColorModeToggleButton.swift
//
// Copyright © 2017 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
open class ColorModeToggleButton: UIButton {
public enum ColorState {
case hue
case grayscale
}
open var colorState: ColorState = .hue
open lazy var hueColorGradientLayer: CAGradientLayer = {
let gradient = CAGradientLayer()
let colorUpperLeft = UIColor(red: 250/255.0, green: 217/255.0, blue: 97/255.0, alpha: 1)
let colorLowerRight = UIColor(red: 247/255.0, green: 107/255.0, blue: 28/255.0, alpha: 1)
gradient.colors = [colorUpperLeft.cgColor, colorLowerRight.cgColor]
gradient.startPoint = .zero
gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
gradient.frame = self.bounds
return gradient
}()
open lazy var grayColorGradientLayer: CAGradientLayer = {
let gradient = CAGradientLayer()
let gray = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1)
let colorUpperLeft = gray
let colorLowerRight = gray.darkerColor(0.25)
gradient.colors = [colorUpperLeft.cgColor, colorLowerRight.cgColor]
gradient.startPoint = .zero
gradient.endPoint = CGPoint(x: 1.0, y: 1.0)
gradient.frame = self.bounds
return gradient
}()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
private func commonInit() {
layer.backgroundColor = UIColor.clear.cgColor
layer.addSublayer(hueColorGradientLayer)
layer.addSublayer(grayColorGradientLayer)
addTarget(self, action: #selector(toggleState), for: .touchUpInside)
}
// override open func sendActions(for controlEvents: UIControlEvents) {
// if controlEvents == .touchUpInside {
// toggleState()
// }
// super.sendActions(for: controlEvents)
// }
//
override open func layoutSubviews() {
super.layoutSubviews()
layer.masksToBounds = true
layer.cornerRadius = bounds.width/2
layoutGradientLayer()
}
@objc open func toggleState() {
if colorState == .hue {
colorState = .grayscale
}
else {
colorState = .hue
}
layoutGradientLayer()
}
private func layoutGradientLayer() {
hueColorGradientLayer.frame = bounds
grayColorGradientLayer.frame = bounds
if colorState == .hue {
// Display inverse gradients. (i.e. Gray is displayed when hue is active)
grayColorGradientLayer.isHidden = false
hueColorGradientLayer.isHidden = true
}
else {
hueColorGradientLayer.isHidden = false
grayColorGradientLayer.isHidden = true
}
}
}

View File

@ -1,78 +0,0 @@
//
// UIColor+Utilities.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 extension UIColor{
public var hexCode: String {
get{
let colorComponents = self.cgColor.components!
if colorComponents.count < 4 {
return String(format: "%02x%02x%02x", Int(colorComponents[0]*255.0), Int(colorComponents[0]*255.0),Int(colorComponents[0]*255.0)).uppercased()
}
return String(format: "%02x%02x%02x", Int(colorComponents[0]*255.0), Int(colorComponents[1]*255.0),Int(colorComponents[2]*255.0)).uppercased()
}
}
//Amount should be between 0 and 1
public func lighterColor(_ amount: CGFloat) -> UIColor{
return UIColor.blendColors(color: self, destinationColor: UIColor.white, amount: amount)
}
public func darkerColor(_ amount: CGFloat) -> UIColor{
return UIColor.blendColors(color: self, destinationColor: UIColor.black, amount: amount)
}
public static func blendColors(color: UIColor, destinationColor: UIColor, amount : CGFloat) -> UIColor{
var amountToBlend = amount;
if amountToBlend > 1{
amountToBlend = 1.0
}
else if amountToBlend < 0{
amountToBlend = 0
}
var r,g,b, alpha : CGFloat
r = 0
g = 0
b = 0
alpha = 0
color.getRed(&r, green: &g, blue: &b, alpha: &alpha) //gets the rgba values (0-1)
//Get the destination rgba values
var dest_r, dest_g, dest_b, dest_alpha : CGFloat
dest_r = 0
dest_g = 0
dest_b = 0
dest_alpha = 0
destinationColor.getRed(&dest_r, green: &dest_g, blue: &dest_b, alpha: &dest_alpha)
r = amountToBlend * (dest_r * 255) + (1 - amountToBlend) * (r * 255)
g = amountToBlend * (dest_g * 255) + (1 - amountToBlend) * (g * 255)
b = amountToBlend * (dest_b * 255) + (1 - amountToBlend) * (b * 255)
alpha = abs(alpha / dest_alpha)
return UIColor(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: alpha)
}
}

View File

@ -4,29 +4,28 @@ default_platform(:ios)
platform :ios do
desc "Runs unit tests, publishing a new pod version if tests succeed."
lane :test_and_publish do
test
publish_pod
end
desc "Publish podspec, incrementing the patch version."
lane :publish_pod do
publish_podspec
end
desc "Runs unit tests. Installs pods if needed."
desc "Runs unit tests."
lane :test do
run_tests(scheme: "ChromaColorPickerTests")
publish_pod
end
end
def app_unit_tests(options)
unit_tests(options)
generate_tests_coverage(options) if options[:code_coverage]
end
def publish_podspec
podspec = ENV['PODSPEC']
version = bump_podspec_version(podspec)
version = version_bump_podspec(path: podspec, bump_type: "patch")
puts "HERE: #{version}"
commit(podspec, 'Updated Podspec version.')
push_to_git_remote(local_branch: git_branch)
tag_build(version)
@ -48,3 +47,15 @@ def tag_build(tag)
)
push_git_tags
end
def commit(path, message)
# Ensure we are on the correct branch before committing.
sh "git checkout #{git_branch}"
ensure_git_branch(branch: git_branch)
message = "Fastfile: #{message}"
#git_commit(
# path: path,
# message: message
#)
end

View File

@ -16,16 +16,21 @@ or alternatively using `brew cask install fastlane`
# Available Actions
## iOS
### ios pod_publish
### ios test_and_publish
```
fastlane ios pod_publish
fastlane ios test_and_publish
```
Runs unit tests, publishing a new pod version if tests succeed.
### ios publish_pod
```
fastlane ios publish_pod
```
Publish podspec, incrementing the patch version.
### ios test
```
fastlane ios test
```
Runs unit tests. Installs pods if needed.
Runs unit tests.
----