Repository: kaunteya/ProgressKit Branch: master Commit: f19f111ec32a Files: 28 Total size: 194.9 KB Directory structure: gitextract_lvo65_ut/ ├── .gitignore ├── .swift-version ├── BaseView.swift ├── Determinate/ │ ├── CircularProgressView.swift │ ├── DeterminateAnimation.swift │ └── ProgressBar.swift ├── InDeterminate/ │ ├── Crawler.swift │ ├── IndeterminateAnimation.swift │ ├── MaterialProgress.swift │ ├── Rainbow.swift │ ├── RotatingArc.swift │ ├── ShootingStars.swift │ └── Spinner.swift ├── LICENSE ├── ProgressKit/ │ ├── AppDelegate.swift │ ├── Base.lproj/ │ │ └── Main.storyboard │ ├── Determinate.swift │ ├── DeterminateVC.swift │ ├── InDeterminate.swift │ ├── InDeterminateVC.swift │ └── Info.plist ├── ProgressKit.podspec ├── ProgressKit.xcodeproj/ │ ├── project.pbxproj │ └── project.xcworkspace/ │ └── contents.xcworkspacedata ├── ProgressKitTests/ │ ├── Info.plist │ └── ProgressKitTests.swift ├── ProgressUtils.swift └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .DS_Store # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate # CocoaPods # # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control # # Pods/ # Carthage # # Add this line if you want to avoid checking in source code from Carthage dependencies. # Carthage/Checkouts Carthage/Build ================================================ FILE: .swift-version ================================================ 3.0 ================================================ FILE: BaseView.swift ================================================ // // BaseView.swift // ProgressKit // // Created by Kauntey Suryawanshi on 04/10/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import AppKit @IBDesignable open class BaseView : NSView { override public init(frame frameRect: NSRect) { super.init(frame: frameRect) self.configureLayers() } required public init?(coder: NSCoder) { super.init(coder: coder) self.configureLayers() } /// Configure the Layers func configureLayers() { self.wantsLayer = true notifyViewRedesigned() } @IBInspectable open var background: NSColor = NSColor(red: 88.3 / 256, green: 104.4 / 256, blue: 118.5 / 256, alpha: 1.0) { didSet { self.notifyViewRedesigned() } } @IBInspectable open var foreground: NSColor = NSColor(red: 66.3 / 256, green: 173.7 / 256, blue: 106.4 / 256, alpha: 1.0) { didSet { self.notifyViewRedesigned() } } @IBInspectable open var cornerRadius: CGFloat = 5.0 { didSet { self.notifyViewRedesigned() } } /// Call when any IBInspectable variable is changed func notifyViewRedesigned() { self.layer?.backgroundColor = background.cgColor self.layer?.cornerRadius = cornerRadius } } ================================================ FILE: Determinate/CircularProgressView.swift ================================================ // // CircularView.swift // Animo // // Created by Kauntey Suryawanshi on 29/06/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa @IBDesignable open class CircularProgressView: DeterminateAnimation { open var backgroundCircle = CAShapeLayer() open var progressLayer = CAShapeLayer() open var percentLabelLayer = CATextLayer() @IBInspectable open var strokeWidth: CGFloat = -1 { didSet { notifyViewRedesigned() } } @IBInspectable open var showPercent: Bool = true { didSet { notifyViewRedesigned() } } override func notifyViewRedesigned() { super.notifyViewRedesigned() backgroundCircle.lineWidth = self.strokeWidth / 2 progressLayer.lineWidth = strokeWidth percentLabelLayer.isHidden = !showPercent backgroundCircle.strokeColor = foreground.withAlphaComponent(0.5).cgColor progressLayer.strokeColor = foreground.cgColor percentLabelLayer.foregroundColor = foreground.cgColor } override func updateProgress() { CATransaction.begin() if animated { CATransaction.setAnimationDuration(0.5) } else { CATransaction.setDisableActions(true) } let timing = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) CATransaction.setAnimationTimingFunction(timing) progressLayer.strokeEnd = max(0, min(progress, 1)) percentLabelLayer.string = "\(Int(progress * 100))%" CATransaction.commit() } override func configureLayers() { super.configureLayers() let rect = self.bounds let radius = (rect.width / 2) * 0.75 let strokeScalingFactor = CGFloat(0.05) // Add background Circle do { backgroundCircle.frame = rect backgroundCircle.lineWidth = strokeWidth == -1 ? (rect.width * strokeScalingFactor / 2) : strokeWidth / 2 backgroundCircle.strokeColor = foreground.withAlphaComponent(0.5).cgColor backgroundCircle.fillColor = NSColor.clear.cgColor let backgroundPath = NSBezierPath() backgroundPath.appendArc(withCenter: rect.mid, radius: radius, startAngle: 0, endAngle: 360) backgroundCircle.path = backgroundPath.CGPath self.layer?.addSublayer(backgroundCircle) } // Progress Layer do { progressLayer.strokeEnd = 0 //REMOVe this progressLayer.fillColor = NSColor.clear.cgColor progressLayer.lineCap = .round progressLayer.lineWidth = strokeWidth == -1 ? (rect.width * strokeScalingFactor) : strokeWidth progressLayer.frame = rect progressLayer.strokeColor = foreground.cgColor let arcPath = NSBezierPath() let startAngle = CGFloat(90) arcPath.appendArc(withCenter: rect.mid, radius: radius, startAngle: startAngle, endAngle: (startAngle - 360), clockwise: true) progressLayer.path = arcPath.CGPath self.layer?.addSublayer(progressLayer) } // Percentage Layer do { percentLabelLayer.string = "0%" percentLabelLayer.foregroundColor = foreground.cgColor percentLabelLayer.frame = rect percentLabelLayer.font = "Helvetica Neue Light" as CFTypeRef percentLabelLayer.alignmentMode = CATextLayerAlignmentMode.center percentLabelLayer.position.y = rect.midY * 0.25 percentLabelLayer.fontSize = rect.width * 0.2 self.layer?.addSublayer(percentLabelLayer) } } } ================================================ FILE: Determinate/DeterminateAnimation.swift ================================================ // // DeterminateAnimation.swift // ProgressKit // // Created by Kauntey Suryawanshi on 09/07/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa protocol DeterminableAnimation { func updateProgress() } @IBDesignable open class DeterminateAnimation: BaseView, DeterminableAnimation { @IBInspectable open var animated: Bool = true /// Value of progress now. Range 0..1 @IBInspectable open var progress: CGFloat = 0 { didSet { updateProgress() } } /// This function will only be called by didSet of progress. Every subclass will have its own implementation func updateProgress() { fatalError("Must be overriden in subclass") } } ================================================ FILE: Determinate/ProgressBar.swift ================================================ // // ProgressBar.swift // ProgressKit // // Created by Kauntey Suryawanshi on 31/07/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa @IBDesignable open class ProgressBar: DeterminateAnimation { open var borderLayer = CAShapeLayer() open var progressLayer = CAShapeLayer() @IBInspectable open var borderColor: NSColor = .black { didSet { notifyViewRedesigned() } } override func notifyViewRedesigned() { super.notifyViewRedesigned() self.layer?.cornerRadius = self.frame.height / 2 borderLayer.borderColor = borderColor.cgColor progressLayer.backgroundColor = foreground.cgColor } override func configureLayers() { super.configureLayers() borderLayer.frame = self.bounds borderLayer.cornerRadius = borderLayer.frame.height / 2 borderLayer.borderWidth = 1.0 self.layer?.addSublayer(borderLayer) progressLayer.frame = NSInsetRect(borderLayer.bounds, 3, 3) progressLayer.frame.size.width = (borderLayer.bounds.width - 6) progressLayer.cornerRadius = progressLayer.frame.height / 2 progressLayer.backgroundColor = foreground.cgColor borderLayer.addSublayer(progressLayer) } override func updateProgress() { CATransaction.begin() if animated { CATransaction.setAnimationDuration(0.5) } else { CATransaction.setDisableActions(true) } let timing = CAMediaTimingFunction(name: .easeOut) CATransaction.setAnimationTimingFunction(timing) progressLayer.frame.size.width = (borderLayer.bounds.width - 6) * progress CATransaction.commit() } } ================================================ FILE: InDeterminate/Crawler.swift ================================================ // // Crawler.swift // ProgressKit // // Created by Kauntey Suryawanshi on 11/07/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa private let defaultForegroundColor = NSColor.white private let defaultBackgroundColor = NSColor(white: 0.0, alpha: 0.4) private let duration = 1.2 @IBDesignable open class Crawler: IndeterminateAnimation { var starList = [CAShapeLayer]() var smallCircleSize: Double { return Double(self.bounds.width) * 0.2 } var animationGroups = [CAAnimation]() override func notifyViewRedesigned() { super.notifyViewRedesigned() for star in starList { star.backgroundColor = foreground.cgColor } } override func configureLayers() { super.configureLayers() let rect = self.bounds let insetRect = NSInsetRect(rect, rect.width * 0.15, rect.width * 0.15) for i in 0 ..< 5 { let starShape = CAShapeLayer() starList.append(starShape) starShape.backgroundColor = foreground.cgColor let circleWidth = smallCircleSize - Double(i) * 2 starShape.bounds = CGRect(x: 0, y: 0, width: circleWidth, height: circleWidth) starShape.cornerRadius = CGFloat(circleWidth / 2) starShape.position = CGPoint(x: rect.midX, y: rect.midY + insetRect.height / 2) self.layer?.addSublayer(starShape) let arcPath = NSBezierPath() arcPath.appendArc(withCenter: insetRect.mid, radius: insetRect.width / 2, startAngle: 90, endAngle: -360 + 90, clockwise: true) let rotationAnimation = CAKeyframeAnimation(keyPath: "position") rotationAnimation.path = arcPath.CGPath rotationAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) rotationAnimation.beginTime = (duration * 0.075) * Double(i) rotationAnimation.calculationMode = .cubicPaced let animationGroup = CAAnimationGroup() animationGroup.animations = [rotationAnimation] animationGroup.duration = duration animationGroup.repeatCount = .infinity animationGroups.append(animationGroup) } } override func startAnimation() { for (index, star) in starList.enumerated() { star.add(animationGroups[index], forKey: "") } } override func stopAnimation() { for star in starList { star.removeAllAnimations() } } } ================================================ FILE: InDeterminate/IndeterminateAnimation.swift ================================================ // // InDeterminateAnimation.swift // ProgressKit // // Created by Kauntey Suryawanshi on 09/07/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Cocoa protocol AnimationStatusDelegate { func startAnimation() func stopAnimation() } open class IndeterminateAnimation: BaseView, AnimationStatusDelegate { /// View is hidden when *animate* property is false @IBInspectable open var displayAfterAnimationEnds: Bool = false /** Control point for all Indeterminate animation True invokes `startAnimation()` on subclass of IndeterminateAnimation False invokes `stopAnimation()` on subclass of IndeterminateAnimation */ open var animate: Bool = false { didSet { guard animate != oldValue else { return } if animate { self.isHidden = false startAnimation() } else { if !displayAfterAnimationEnds { self.isHidden = true } stopAnimation() } } } /** Every function that extends Indeterminate animation must define startAnimation(). `animate` property of Indeterminate animation will indynamically invoke the subclass method */ func startAnimation() { fatalError("This is an abstract function") } /** Every function that extends Indeterminate animation must define **stopAnimation()**. *animate* property of Indeterminate animation will dynamically invoke the subclass method */ func stopAnimation() { fatalError("This is an abstract function") } } ================================================ FILE: InDeterminate/MaterialProgress.swift ================================================ // // MaterialProgress.swift // ProgressKit // // Created by Kauntey Suryawanshi on 30/06/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa private let duration = 1.5 private let strokeRange = (start: 0.0, end: 0.8) @IBDesignable open class MaterialProgress: IndeterminateAnimation { @IBInspectable open var lineWidth: CGFloat = -1 { didSet { progressLayer.lineWidth = lineWidth } } override func notifyViewRedesigned() { super.notifyViewRedesigned() progressLayer.strokeColor = foreground.cgColor } var backgroundRotationLayer = CAShapeLayer() var progressLayer: CAShapeLayer = { var tempLayer = CAShapeLayer() tempLayer.strokeEnd = CGFloat(strokeRange.end) tempLayer.lineCap = .round tempLayer.fillColor = NSColor.clear.cgColor return tempLayer }() //MARK: Animation Declaration var animationGroup: CAAnimationGroup = { var tempGroup = CAAnimationGroup() tempGroup.repeatCount = 1 tempGroup.duration = duration return tempGroup }() var rotationAnimation: CABasicAnimation = { var tempRotation = CABasicAnimation(keyPath: "transform.rotation") tempRotation.repeatCount = Float.infinity tempRotation.fromValue = 0 tempRotation.toValue = 1 tempRotation.isCumulative = true tempRotation.duration = duration / 2 return tempRotation }() /// Makes animation for Stroke Start and Stroke End func makeStrokeAnimationGroup() { var strokeStartAnimation: CABasicAnimation! var strokeEndAnimation: CABasicAnimation! func makeAnimationforKeyPath(_ keyPath: String) -> CABasicAnimation { let tempAnimation = CABasicAnimation(keyPath: keyPath) tempAnimation.repeatCount = 1 tempAnimation.speed = 2.0 tempAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) tempAnimation.fromValue = strokeRange.start tempAnimation.toValue = strokeRange.end tempAnimation.duration = duration return tempAnimation } strokeEndAnimation = makeAnimationforKeyPath("strokeEnd") strokeStartAnimation = makeAnimationforKeyPath("strokeStart") strokeStartAnimation.beginTime = duration / 2 animationGroup.animations = [strokeEndAnimation, strokeStartAnimation, ] animationGroup.delegate = self } override func configureLayers() { super.configureLayers() makeStrokeAnimationGroup() let rect = self.bounds backgroundRotationLayer.frame = rect self.layer?.addSublayer(backgroundRotationLayer) // Progress Layer let radius = (rect.width / 2) * 0.75 progressLayer.frame = rect progressLayer.lineWidth = lineWidth == -1 ? radius / 10: lineWidth let arcPath = NSBezierPath() arcPath.appendArc(withCenter: rect.mid, radius: radius, startAngle: 0, endAngle: 360, clockwise: false) progressLayer.path = arcPath.CGPath backgroundRotationLayer.addSublayer(progressLayer) } var currentRotation = 0.0 let π2 = Double.pi * 2 override func startAnimation() { progressLayer.add(animationGroup, forKey: "strokeEnd") backgroundRotationLayer.add(rotationAnimation, forKey: rotationAnimation.keyPath) } override func stopAnimation() { backgroundRotationLayer.removeAllAnimations() progressLayer.removeAllAnimations() } } extension MaterialProgress: CAAnimationDelegate { open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { if !animate { return } CATransaction.begin() CATransaction.setDisableActions(true) currentRotation += strokeRange.end * π2 currentRotation = currentRotation.truncatingRemainder(dividingBy: π2) progressLayer.setAffineTransform(CGAffineTransform(rotationAngle: CGFloat( currentRotation))) CATransaction.commit() progressLayer.add(animationGroup, forKey: "strokeEnd") } } ================================================ FILE: InDeterminate/Rainbow.swift ================================================ // // Rainbow.swift // ProgressKit // // Created by Kauntey Suryawanshi on 09/07/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa @IBDesignable open class Rainbow: MaterialProgress { @IBInspectable open var onLightOffDark: Bool = false override func configureLayers() { super.configureLayers() self.background = NSColor.clear } override open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { super.animationDidStop(anim, finished: flag) if onLightOffDark { progressLayer.strokeColor = lightColorList[Int(arc4random()) % lightColorList.count].cgColor } else { progressLayer.strokeColor = darkColorList[Int(arc4random()) % darkColorList.count].cgColor } } } var randomColor: NSColor { let red = CGFloat(Double(arc4random()).truncatingRemainder(dividingBy: 256.0) / 256.0) let green = CGFloat(Double(arc4random()).truncatingRemainder(dividingBy: 256.0) / 256.0) let blue = CGFloat(Double(arc4random()).truncatingRemainder(dividingBy: 256.0) / 256.0) return NSColor(calibratedRed: red, green: green, blue: blue, alpha: 1.0) } private let lightColorList:[NSColor] = [ NSColor(red: 0.9461, green: 0.6699, blue: 0.6243, alpha: 1.0), NSColor(red: 0.8625, green: 0.7766, blue: 0.8767, alpha: 1.0), NSColor(red: 0.6676, green: 0.6871, blue: 0.8313, alpha: 1.0), NSColor(red: 0.7263, green: 0.6189, blue: 0.8379, alpha: 1.0), NSColor(red: 0.8912, green: 0.9505, blue: 0.9971, alpha: 1.0), NSColor(red: 0.7697, green: 0.9356, blue: 0.9692, alpha: 1.0), NSColor(red: 0.3859, green: 0.7533, blue: 0.9477, alpha: 1.0), NSColor(red: 0.6435, green: 0.8554, blue: 0.8145, alpha: 1.0), NSColor(red: 0.8002, green: 0.936, blue: 0.7639, alpha: 1.0), NSColor(red: 0.5362, green: 0.8703, blue: 0.8345, alpha: 1.0), NSColor(red: 0.9785, green: 0.8055, blue: 0.4049, alpha: 1.0), NSColor(red: 1.0, green: 0.8667, blue: 0.6453, alpha: 1.0), NSColor(red: 0.9681, green: 0.677, blue: 0.2837, alpha: 1.0), NSColor(red: 0.9898, green: 0.7132, blue: 0.1746, alpha: 1.0), NSColor(red: 0.8238, green: 0.84, blue: 0.8276, alpha: 1.0), NSColor(red: 0.8532, green: 0.8763, blue: 0.883, alpha: 1.0), ] let darkColorList: [NSColor] = [ NSColor(red: 0.9472, green: 0.2496, blue: 0.0488, alpha: 1.0), NSColor(red: 0.8098, green: 0.1695, blue: 0.0467, alpha: 1.0), NSColor(red: 0.853, green: 0.2302, blue: 0.3607, alpha: 1.0), NSColor(red: 0.8152, green: 0.3868, blue: 0.5021, alpha: 1.0), NSColor(red: 0.96, green: 0.277, blue: 0.3515, alpha: 1.0), NSColor(red: 0.3686, green: 0.3069, blue: 0.6077, alpha: 1.0), NSColor(red: 0.5529, green: 0.3198, blue: 0.5409, alpha: 1.0), NSColor(red: 0.2132, green: 0.4714, blue: 0.7104, alpha: 1.0), NSColor(red: 0.1706, green: 0.2432, blue: 0.3106, alpha: 1.0), NSColor(red: 0.195, green: 0.2982, blue: 0.3709, alpha: 1.0), NSColor(red: 0.0, green: 0.3091, blue: 0.5859, alpha: 1.0), NSColor(red: 0.2261, green: 0.6065, blue: 0.3403, alpha: 1.0), NSColor(red: 0.1101, green: 0.5694, blue: 0.4522, alpha: 1.0), NSColor(red: 0.1716, green: 0.4786, blue: 0.2877, alpha: 1.0), NSColor(red: 0.8289, green: 0.33, blue: 0.0, alpha: 1.0), NSColor(red: 0.4183, green: 0.4842, blue: 0.5372, alpha: 1.0), NSColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0), ] ================================================ FILE: InDeterminate/RotatingArc.swift ================================================ // // RotatingArc.swift // ProgressKit // // Created by Kauntey Suryawanshi on 26/10/15. // Copyright © 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa private let duration = 0.25 @IBDesignable open class RotatingArc: IndeterminateAnimation { var backgroundCircle = CAShapeLayer() var arcLayer = CAShapeLayer() @IBInspectable open var strokeWidth: CGFloat = 5 { didSet { notifyViewRedesigned() } } @IBInspectable open var arcLength: Int = 35 { didSet { notifyViewRedesigned() } } @IBInspectable open var clockWise: Bool = true { didSet { notifyViewRedesigned() } } var radius: CGFloat { return (self.frame.width / 2) * CGFloat(0.75) } var rotationAnimation: CABasicAnimation = { var tempRotation = CABasicAnimation(keyPath: "transform.rotation") tempRotation.repeatCount = .infinity tempRotation.fromValue = 0 tempRotation.toValue = 1 tempRotation.isCumulative = true tempRotation.duration = duration return tempRotation }() override func notifyViewRedesigned() { super.notifyViewRedesigned() arcLayer.strokeColor = foreground.cgColor backgroundCircle.strokeColor = foreground.withAlphaComponent(0.4).cgColor backgroundCircle.lineWidth = self.strokeWidth arcLayer.lineWidth = strokeWidth rotationAnimation.toValue = clockWise ? -1 : 1 let arcPath = NSBezierPath() let endAngle: CGFloat = CGFloat(-360) * CGFloat(arcLength) / 100 arcPath.appendArc(withCenter: self.bounds.mid, radius: radius, startAngle: 0, endAngle: endAngle, clockwise: true) arcLayer.path = arcPath.CGPath } override func configureLayers() { super.configureLayers() let rect = self.bounds // Add background Circle do { backgroundCircle.frame = rect backgroundCircle.lineWidth = strokeWidth backgroundCircle.strokeColor = foreground.withAlphaComponent(0.5).cgColor backgroundCircle.fillColor = NSColor.clear.cgColor let backgroundPath = NSBezierPath() backgroundPath.appendArc(withCenter: rect.mid, radius: radius, startAngle: 0, endAngle: 360) backgroundCircle.path = backgroundPath.CGPath self.layer?.addSublayer(backgroundCircle) } // Arc Layer do { arcLayer.fillColor = NSColor.clear.cgColor arcLayer.lineWidth = strokeWidth arcLayer.frame = rect arcLayer.strokeColor = foreground.cgColor self.layer?.addSublayer(arcLayer) } } override func startAnimation() { arcLayer.add(rotationAnimation, forKey: "") } override func stopAnimation() { arcLayer.removeAllAnimations() } } ================================================ FILE: InDeterminate/ShootingStars.swift ================================================ // // ShootingStars.swift // ProgressKit // // Created by Kauntey Suryawanshi on 09/07/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa @IBDesignable open class ShootingStars: IndeterminateAnimation { fileprivate let animationDuration = 1.0 var starLayer1 = CAShapeLayer() var starLayer2 = CAShapeLayer() var animation = CABasicAnimation(keyPath: "position.x") var tempAnimation = CABasicAnimation(keyPath: "position.x") override func notifyViewRedesigned() { super.notifyViewRedesigned() starLayer1.backgroundColor = foreground.cgColor starLayer2.backgroundColor = foreground.cgColor } override func configureLayers() { super.configureLayers() let rect = self.bounds let dimension = rect.height let starWidth = dimension * 1.5 self.layer?.cornerRadius = 0 /// Add Stars do { starLayer1.position = CGPoint(x: dimension / 2, y: dimension / 2) starLayer1.bounds.size = CGSize(width: starWidth, height: dimension) starLayer1.backgroundColor = foreground.cgColor self.layer?.addSublayer(starLayer1) starLayer2.position = CGPoint(x: rect.midX, y: dimension / 2) starLayer2.bounds.size = CGSize(width: starWidth, height: dimension) starLayer2.backgroundColor = foreground.cgColor self.layer?.addSublayer(starLayer2) } /// Add default animation do { animation.fromValue = -dimension animation.toValue = rect.width * 0.9 animation.duration = animationDuration animation.timingFunction = CAMediaTimingFunction(name: .easeIn) animation.isRemovedOnCompletion = false animation.repeatCount = .infinity } /** Temp animation will be removed after first animation After finishing it will invoke animationDidStop and starLayer2 is also given default animation. The purpose of temp animation is to generate an temporary offset */ tempAnimation.fromValue = rect.midX tempAnimation.toValue = rect.width tempAnimation.delegate = self tempAnimation.duration = animationDuration / 2 tempAnimation.timingFunction = CAMediaTimingFunction(name: .easeIn) } //MARK: Indeterminable protocol override func startAnimation() { starLayer1.add(animation, forKey: "default") starLayer2.add(tempAnimation, forKey: "tempAnimation") } override func stopAnimation() { starLayer1.removeAllAnimations() starLayer2.removeAllAnimations() } } extension ShootingStars: CAAnimationDelegate { open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { starLayer2.add(animation, forKey: "default") } } ================================================ FILE: InDeterminate/Spinner.swift ================================================ // // Spinner.swift // ProgressKit // // Created by Kauntey Suryawanshi on 28/07/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa @IBDesignable open class Spinner: IndeterminateAnimation { var basicShape = CAShapeLayer() var containerLayer = CAShapeLayer() var starList = [CAShapeLayer]() var animation: CAKeyframeAnimation = { var animation = CAKeyframeAnimation(keyPath: "transform.rotation") animation.repeatCount = .infinity animation.calculationMode = .discrete return animation }() @IBInspectable open var starSize:CGSize = CGSize(width: 6, height: 15) { didSet { notifyViewRedesigned() } } @IBInspectable open var roundedCorners: Bool = true { didSet { notifyViewRedesigned() } } @IBInspectable open var distance: CGFloat = CGFloat(20) { didSet { notifyViewRedesigned() } } @IBInspectable open var starCount: Int = 10 { didSet { notifyViewRedesigned() } } @IBInspectable open var duration: Double = 1 { didSet { animation.duration = duration } } @IBInspectable open var clockwise: Bool = false { didSet { notifyViewRedesigned() } } override func configureLayers() { super.configureLayers() containerLayer.frame = self.bounds containerLayer.cornerRadius = frame.width / 2 self.layer?.addSublayer(containerLayer) animation.duration = duration } override func notifyViewRedesigned() { super.notifyViewRedesigned() starList.removeAll(keepingCapacity: true) containerLayer.sublayers = nil animation.values = [Double]() var i = 0.0 while i < 360 { var iRadian = CGFloat(i * Double.pi / 180.0) if clockwise { iRadian = -iRadian } animation.values?.append(iRadian) let starShape = CAShapeLayer() starShape.cornerRadius = roundedCorners ? starSize.width / 2 : 0 let centerLocation = CGPoint(x: frame.width / 2 - starSize.width / 2, y: frame.width / 2 - starSize.height / 2) starShape.frame = CGRect(origin: centerLocation, size: starSize) starShape.backgroundColor = foreground.cgColor starShape.anchorPoint = CGPoint(x: 0.5, y: 0) var rotation: CATransform3D = CATransform3DMakeTranslation(0, 0, 0.0); rotation = CATransform3DRotate(rotation, -iRadian, 0.0, 0.0, 1.0); rotation = CATransform3DTranslate(rotation, 0, distance, 0.0); starShape.transform = rotation starShape.opacity = Float(360 - i) / 360 containerLayer.addSublayer(starShape) starList.append(starShape) i = i + Double(360 / starCount) } } override func startAnimation() { containerLayer.add(animation, forKey: "rotation") } override func stopAnimation() { containerLayer.removeAllAnimations() } } ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 Kaunteya Suryawanshi 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. ================================================ FILE: ProgressKit/AppDelegate.swift ================================================ // // AppDelegate.swift // ProgressKit // // Created by Kauntey Suryawanshi on 30/06/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Cocoa @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { // Insert code here to initialize your application } func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } } ================================================ FILE: ProgressKit/Base.lproj/Main.storyboard ================================================ Default Left to Right Right to Left Default Left to Right Right to Left ================================================ FILE: ProgressKit/Determinate.swift ================================================ // // ViewController.swift // ProgressKit // // Created by Kauntey Suryawanshi on 30/06/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Cocoa class DeterminateViewController: NSViewController { dynamic var liveProgress: Bool = true dynamic var labelPercentage: String = "30%" @IBOutlet weak var circularView1: CircularProgressView! @IBOutlet weak var circularView2: CircularProgressView! @IBOutlet weak var circularView3: CircularProgressView! @IBOutlet weak var circularView4: CircularProgressView! @IBOutlet weak var circularView5: CircularProgressView! @IBOutlet weak var slider: NSSlider! @IBAction func sliderDragged(sender: NSSlider) { let event = NSApplication.sharedApplication().currentEvent let dragStart = event!.type == NSEventType.LeftMouseDown let dragEnd = event!.type == NSEventType.LeftMouseUp let dragging = event!.type == NSEventType.LeftMouseDragged if liveProgress || dragEnd { setProgress(CGFloat(sender.floatValue)) } labelPercentage = "\(Int(sender.floatValue * 100))%" } func setProgress(progress: CGFloat) { circularView1.setProgressValue(progress, animated: true) circularView2.setProgressValue(progress, animated: true) circularView3.setProgressValue(progress, animated: true) circularView4.setProgressValue(progress, animated: true) circularView5.setProgressValue(progress, animated: false) } override func viewDidLoad() { preferredContentSize = NSMakeSize(500, 500) } } ================================================ FILE: ProgressKit/DeterminateVC.swift ================================================ // // ViewController.swift // ProgressKit // // Created by Kauntey Suryawanshi on 30/06/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Cocoa class DeterminateViewController: NSViewController { @objc dynamic var liveProgress: Bool = true @objc dynamic var labelPercentage: String = "30%" override func viewDidLoad() { preferredContentSize = NSMakeSize(500, 300) } @IBOutlet weak var slider: NSSlider! @IBAction func sliderDragged(_ sender: NSSlider) { let event = NSApplication.shared.currentEvent // let dragStart = event!.type == NSEventType.LeftMouseDown let dragEnd = event!.type == NSEvent.EventType.leftMouseUp // let dragging = event!.type == NSEventType.LeftMouseDragged if liveProgress || dragEnd { setProgress(CGFloat(sender.floatValue)) } labelPercentage = "\(Int(sender.floatValue * 100))%" } func setProgress(_ progress: CGFloat) { for view in self.view.subviews { if view is DeterminateAnimation { (view as! DeterminateAnimation).progress = progress } } } } ================================================ FILE: ProgressKit/InDeterminate.swift ================================================ // // WhatsAppCircular.swift // ProgressKit // // Created by Kauntey Suryawanshi on 30/06/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa class InDeterminateViewController: NSViewController { @IBOutlet weak var doing1: DoingCircular! @IBOutlet weak var doing2: DoingCircular! @IBOutlet weak var doing3: DoingCircular! @IBOutlet weak var doing4: DoingCircular! override func viewDidLoad() { preferredContentSize = NSMakeSize(500, 500) } @IBAction func startStopAnimation(sender: NSButton) { let isOn = sender.state == NSOnState doing1.animate = isOn doing2.animate = isOn doing3.animate = isOn doing4.animate = isOn } } ================================================ FILE: ProgressKit/InDeterminateVC.swift ================================================ // // WhatsAppCircular.swift // ProgressKit // // Created by Kauntey Suryawanshi on 30/06/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Foundation import Cocoa class InDeterminateViewController: NSViewController { override func viewDidAppear() { for view in self.view.subviews { (view as? IndeterminateAnimation)?.animate = true } } override func viewWillDisappear() { for view in self.view.subviews { (view as? IndeterminateAnimation)?.animate = false } } } ================================================ FILE: ProgressKit/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIconFile CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSMinimumSystemVersion $(MACOSX_DEPLOYMENT_TARGET) NSHumanReadableCopyright Copyright © 2015 Kauntey Suryawanshi. All rights reserved. NSMainStoryboardFile Main NSPrincipalClass NSApplication ================================================ FILE: ProgressKit.podspec ================================================ Pod::Spec.new do |spec| spec.name = 'ProgressKit' spec.version = '0.8' spec.license = 'MIT' spec.summary = 'Animated ProgressViews for macOS' spec.homepage = 'https://github.com/kaunteya/ProgressKit' spec.authors = { 'Kaunteya Suryawanshi' => 'k.suryawanshi@gmail.com' } spec.source = { :git => 'https://github.com/kaunteya/ProgressKit.git', :tag => spec.version } spec.platform = :osx, '10.10' spec.requires_arc = true spec.source_files = 'Determinate/*.swift', 'InDeterminate/*.swift', 'ProgressUtils.swift', 'BaseView.swift' end ================================================ FILE: ProgressKit.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ E31617A61BC0596C007AD70F /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E31617A51BC0596C007AD70F /* BaseView.swift */; }; E340FDB81BDE45F000CE6550 /* RotatingArc.swift in Sources */ = {isa = PBXBuildFile; fileRef = E340FDB71BDE45F000CE6550 /* RotatingArc.swift */; }; E35D1C6C1B676889001DBAF2 /* Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = E35D1C6B1B676889001DBAF2 /* Spinner.swift */; }; E37568DF1B6AAB530073E26F /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = E37568DE1B6AAB530073E26F /* ProgressBar.swift */; }; E3918F811B4E88CF00558DAB /* CircularProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F801B4E88CF00558DAB /* CircularProgressView.swift */; }; E3918F841B4E88DE00558DAB /* MaterialProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F821B4E88DE00558DAB /* MaterialProgress.swift */; }; E3918F851B4E88DE00558DAB /* ShootingStars.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F831B4E88DE00558DAB /* ShootingStars.swift */; }; E3918F8D1B4E8AB100558DAB /* IndeterminateAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F8C1B4E8AB100558DAB /* IndeterminateAnimation.swift */; }; E3918F8F1B4E8C2900558DAB /* DeterminateAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918F8E1B4E8C2900558DAB /* DeterminateAnimation.swift */; }; E3918FA81B4ECF7100558DAB /* Rainbow.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3918FA71B4ECF7100558DAB /* Rainbow.swift */; }; E3A468521B5434F7006DDE31 /* Crawler.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3A468511B5434F7006DDE31 /* Crawler.swift */; }; E3AD65D81B426758009541CD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD65D71B426758009541CD /* AppDelegate.swift */; }; E3AD65DA1B426758009541CD /* DeterminateVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD65D91B426758009541CD /* DeterminateVC.swift */; }; E3AD65DF1B426758009541CD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E3AD65DD1B426758009541CD /* Main.storyboard */; }; E3AD65EB1B426758009541CD /* ProgressKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD65EA1B426758009541CD /* ProgressKitTests.swift */; }; E3AD65F71B427511009541CD /* InDeterminateVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD65F61B427511009541CD /* InDeterminateVC.swift */; }; E3CCD59A1BBC2B9B00F7DB9A /* ProgressUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3CCD5991BBC2B9B00F7DB9A /* ProgressUtils.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ E3AD65E51B426758009541CD /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E3AD65CA1B426758009541CD /* Project object */; proxyType = 1; remoteGlobalIDString = E3AD65D11B426758009541CD; remoteInfo = ProgressKit; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ E310B1D21D7AB2D4008DEF62 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; E310B1D41D7AB2EA008DEF62 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = SOURCE_ROOT; }; E31617A51BC0596C007AD70F /* BaseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseView.swift; sourceTree = ""; }; E340FDB71BDE45F000CE6550 /* RotatingArc.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RotatingArc.swift; path = InDeterminate/RotatingArc.swift; sourceTree = ""; }; E35D1C6B1B676889001DBAF2 /* Spinner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Spinner.swift; path = InDeterminate/Spinner.swift; sourceTree = ""; }; E37568DE1B6AAB530073E26F /* ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProgressBar.swift; path = Determinate/ProgressBar.swift; sourceTree = ""; }; E3918F801B4E88CF00558DAB /* CircularProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CircularProgressView.swift; path = Determinate/CircularProgressView.swift; sourceTree = ""; }; E3918F821B4E88DE00558DAB /* MaterialProgress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MaterialProgress.swift; path = InDeterminate/MaterialProgress.swift; sourceTree = ""; }; E3918F831B4E88DE00558DAB /* ShootingStars.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ShootingStars.swift; path = InDeterminate/ShootingStars.swift; sourceTree = ""; }; E3918F8C1B4E8AB100558DAB /* IndeterminateAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = IndeterminateAnimation.swift; path = InDeterminate/IndeterminateAnimation.swift; sourceTree = ""; }; E3918F8E1B4E8C2900558DAB /* DeterminateAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DeterminateAnimation.swift; path = Determinate/DeterminateAnimation.swift; sourceTree = ""; }; E3918FA71B4ECF7100558DAB /* Rainbow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Rainbow.swift; path = InDeterminate/Rainbow.swift; sourceTree = ""; }; E3A468511B5434F7006DDE31 /* Crawler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Crawler.swift; path = InDeterminate/Crawler.swift; sourceTree = ""; }; E3AD65D21B426758009541CD /* ProgressKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ProgressKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; E3AD65D61B426758009541CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E3AD65D71B426758009541CD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E3AD65D91B426758009541CD /* DeterminateVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeterminateVC.swift; sourceTree = ""; }; E3AD65DE1B426758009541CD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; E3AD65E41B426758009541CD /* ProgressKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ProgressKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E3AD65E91B426758009541CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E3AD65EA1B426758009541CD /* ProgressKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressKitTests.swift; sourceTree = ""; }; E3AD65F61B427511009541CD /* InDeterminateVC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InDeterminateVC.swift; sourceTree = ""; }; E3CCD5971BBC19ED00F7DB9A /* ProgressKit.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ProgressKit.podspec; sourceTree = SOURCE_ROOT; }; E3CCD5991BBC2B9B00F7DB9A /* ProgressUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressUtils.swift; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ E3AD65CF1B426758009541CD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; E3AD65E11B426758009541CD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ E316CCAA1B4E8633005A9A31 /* Indeterminate */ = { isa = PBXGroup; children = ( E3918F8C1B4E8AB100558DAB /* IndeterminateAnimation.swift */, E3918F821B4E88DE00558DAB /* MaterialProgress.swift */, E3918FA71B4ECF7100558DAB /* Rainbow.swift */, E3A468511B5434F7006DDE31 /* Crawler.swift */, E3918F831B4E88DE00558DAB /* ShootingStars.swift */, E35D1C6B1B676889001DBAF2 /* Spinner.swift */, E340FDB71BDE45F000CE6550 /* RotatingArc.swift */, ); name = Indeterminate; sourceTree = ""; }; E316CCAB1B4E8642005A9A31 /* Determinate */ = { isa = PBXGroup; children = ( E3918F8E1B4E8C2900558DAB /* DeterminateAnimation.swift */, E3918F801B4E88CF00558DAB /* CircularProgressView.swift */, E37568DE1B6AAB530073E26F /* ProgressBar.swift */, ); name = Determinate; sourceTree = ""; }; E3AD65C91B426758009541CD = { isa = PBXGroup; children = ( E31617A51BC0596C007AD70F /* BaseView.swift */, E316CCAA1B4E8633005A9A31 /* Indeterminate */, E316CCAB1B4E8642005A9A31 /* Determinate */, E3AD65D41B426758009541CD /* ProgressKit */, E3AD65E71B426758009541CD /* ProgressKitTests */, E3AD65D31B426758009541CD /* Products */, ); sourceTree = ""; }; E3AD65D31B426758009541CD /* Products */ = { isa = PBXGroup; children = ( E3AD65D21B426758009541CD /* ProgressKit.app */, E3AD65E41B426758009541CD /* ProgressKitTests.xctest */, ); name = Products; sourceTree = ""; }; E3AD65D41B426758009541CD /* ProgressKit */ = { isa = PBXGroup; children = ( E3AD65D71B426758009541CD /* AppDelegate.swift */, E3AD65D91B426758009541CD /* DeterminateVC.swift */, E3AD65F61B427511009541CD /* InDeterminateVC.swift */, E3AD65DD1B426758009541CD /* Main.storyboard */, E3AD65D51B426758009541CD /* Supporting Files */, ); path = ProgressKit; sourceTree = ""; }; E3AD65D51B426758009541CD /* Supporting Files */ = { isa = PBXGroup; children = ( E310B1D21D7AB2D4008DEF62 /* README.md */, E310B1D41D7AB2EA008DEF62 /* LICENSE */, E3CCD5991BBC2B9B00F7DB9A /* ProgressUtils.swift */, E3CCD5971BBC19ED00F7DB9A /* ProgressKit.podspec */, E3AD65D61B426758009541CD /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; E3AD65E71B426758009541CD /* ProgressKitTests */ = { isa = PBXGroup; children = ( E3AD65EA1B426758009541CD /* ProgressKitTests.swift */, E3AD65E81B426758009541CD /* Supporting Files */, ); path = ProgressKitTests; sourceTree = ""; }; E3AD65E81B426758009541CD /* Supporting Files */ = { isa = PBXGroup; children = ( E3AD65E91B426758009541CD /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ E3AD65D11B426758009541CD /* ProgressKit */ = { isa = PBXNativeTarget; buildConfigurationList = E3AD65EE1B426758009541CD /* Build configuration list for PBXNativeTarget "ProgressKit" */; buildPhases = ( E3AD65CE1B426758009541CD /* Sources */, E3AD65CF1B426758009541CD /* Frameworks */, E3AD65D01B426758009541CD /* Resources */, ); buildRules = ( ); dependencies = ( ); name = ProgressKit; productName = ProgressKit; productReference = E3AD65D21B426758009541CD /* ProgressKit.app */; productType = "com.apple.product-type.application"; }; E3AD65E31B426758009541CD /* ProgressKitTests */ = { isa = PBXNativeTarget; buildConfigurationList = E3AD65F11B426758009541CD /* Build configuration list for PBXNativeTarget "ProgressKitTests" */; buildPhases = ( E3AD65E01B426758009541CD /* Sources */, E3AD65E11B426758009541CD /* Frameworks */, E3AD65E21B426758009541CD /* Resources */, ); buildRules = ( ); dependencies = ( E3AD65E61B426758009541CD /* PBXTargetDependency */, ); name = ProgressKitTests; productName = ProgressKitTests; productReference = E3AD65E41B426758009541CD /* ProgressKitTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ E3AD65CA1B426758009541CD /* Project object */ = { isa = PBXProject; attributes = { LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 1000; ORGANIZATIONNAME = "Kauntey Suryawanshi"; TargetAttributes = { E3AD65D11B426758009541CD = { CreatedOnToolsVersion = 6.3.2; LastSwiftMigration = 0920; }; E3AD65E31B426758009541CD = { CreatedOnToolsVersion = 6.3.2; LastSwiftMigration = 0920; TestTargetID = E3AD65D11B426758009541CD; }; }; }; buildConfigurationList = E3AD65CD1B426758009541CD /* Build configuration list for PBXProject "ProgressKit" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = E3AD65C91B426758009541CD; productRefGroup = E3AD65D31B426758009541CD /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( E3AD65D11B426758009541CD /* ProgressKit */, E3AD65E31B426758009541CD /* ProgressKitTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ E3AD65D01B426758009541CD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( E3AD65DF1B426758009541CD /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; E3AD65E21B426758009541CD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ E3AD65CE1B426758009541CD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E3A468521B5434F7006DDE31 /* Crawler.swift in Sources */, E3AD65DA1B426758009541CD /* DeterminateVC.swift in Sources */, E3918F8D1B4E8AB100558DAB /* IndeterminateAnimation.swift in Sources */, E3AD65F71B427511009541CD /* InDeterminateVC.swift in Sources */, E3918F851B4E88DE00558DAB /* ShootingStars.swift in Sources */, E3918F811B4E88CF00558DAB /* CircularProgressView.swift in Sources */, E35D1C6C1B676889001DBAF2 /* Spinner.swift in Sources */, E3918F841B4E88DE00558DAB /* MaterialProgress.swift in Sources */, E3AD65D81B426758009541CD /* AppDelegate.swift in Sources */, E37568DF1B6AAB530073E26F /* ProgressBar.swift in Sources */, E340FDB81BDE45F000CE6550 /* RotatingArc.swift in Sources */, E3CCD59A1BBC2B9B00F7DB9A /* ProgressUtils.swift in Sources */, E31617A61BC0596C007AD70F /* BaseView.swift in Sources */, E3918FA81B4ECF7100558DAB /* Rainbow.swift in Sources */, E3918F8F1B4E8C2900558DAB /* DeterminateAnimation.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E3AD65E01B426758009541CD /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E3AD65EB1B426758009541CD /* ProgressKitTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ E3AD65E61B426758009541CD /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = E3AD65D11B426758009541CD /* ProgressKit */; targetProxy = E3AD65E51B426758009541CD /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ E3AD65DD1B426758009541CD /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( E3AD65DE1B426758009541CD /* Base */, ); name = Main.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ E3AD65EC1B426758009541CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; E3AD65ED1B426758009541CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; }; name = Release; }; E3AD65EF1B426758009541CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = ProgressKit/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.kaunteya.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Debug; }; E3AD65F01B426758009541CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = ProgressKit/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.kaunteya.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.2; }; name = Release; }; E3AD65F21B426758009541CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = ProgressKitTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.kaunteya.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ProgressKit.app/Contents/MacOS/ProgressKit"; }; name = Debug; }; E3AD65F31B426758009541CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", ); INFOPLIST_FILE = ProgressKitTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.kaunteya.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ProgressKit.app/Contents/MacOS/ProgressKit"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ E3AD65CD1B426758009541CD /* Build configuration list for PBXProject "ProgressKit" */ = { isa = XCConfigurationList; buildConfigurations = ( E3AD65EC1B426758009541CD /* Debug */, E3AD65ED1B426758009541CD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; E3AD65EE1B426758009541CD /* Build configuration list for PBXNativeTarget "ProgressKit" */ = { isa = XCConfigurationList; buildConfigurations = ( E3AD65EF1B426758009541CD /* Debug */, E3AD65F01B426758009541CD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; E3AD65F11B426758009541CD /* Build configuration list for PBXNativeTarget "ProgressKitTests" */ = { isa = XCConfigurationList; buildConfigurations = ( E3AD65F21B426758009541CD /* Debug */, E3AD65F31B426758009541CD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = E3AD65CA1B426758009541CD /* Project object */; } ================================================ FILE: ProgressKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: ProgressKitTests/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType BNDL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 ================================================ FILE: ProgressKitTests/ProgressKitTests.swift ================================================ // // ProgressKitTests.swift // ProgressKitTests // // Created by Kauntey Suryawanshi on 30/06/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import Cocoa import XCTest class ProgressKitTests: XCTestCase { override func setUp() { super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } override func tearDown() { // Put teardown code here. This method is called after the invocation of each test method in the class. super.tearDown() } func testExample() { // This is an example of a functional test case. XCTAssert(true, "Pass") } func testPerformanceExample() { // This is an example of a performance test case. } } ================================================ FILE: ProgressUtils.swift ================================================ // // ProgressUtils.swift // ProgressKit // // Created by Kauntey Suryawanshi on 09/07/15. // Copyright (c) 2015 Kauntey Suryawanshi. All rights reserved. // import AppKit extension NSRect { var mid: CGPoint { return CGPoint(x: self.midX, y: self.midY) } } extension NSBezierPath { /// Converts NSBezierPath to CGPath var CGPath: CGPath { let path = CGMutablePath() let points = UnsafeMutablePointer.allocate(capacity: 3) let numElements = self.elementCount for index in 0.. Double { return Double(degree) * (Double.pi / 180) } func radianToDegree(_ radian: Double) -> Int { return Int(radian * (180 / Double.pi)) } func + (p1: CGPoint, p2: CGPoint) -> CGPoint { return CGPoint(x: p1.x + p2.x, y: p1.y + p2.y) } ================================================ FILE: README.md ================================================ ![ProgressKit Banner](/Images/banner.gif) [![Cocoapods Compatible](https://img.shields.io/cocoapods/v/ProgressKit.svg)](https://img.shields.io/cocoapods/v/ProgressKit.svg) [![Platform](https://img.shields.io/cocoapods/p/ProgressKit.svg?style=flat)](http://cocoadocs.org/docsets/ProgressKit) [![License](https://img.shields.io/cocoapods/l/ProgressKit.svg?style=flat)](http://cocoadocs.org/docsets/ProgressKit) `ProgressKit` has set of cool `IBDesignable` progress views, with huge customisation options. You can now make spinners, progress bar, crawlers etc, which can be finely customised according to your app palette. # Contents - [Installation](#installation) - [Usage](#usage) - [Indeterminate Progress](#indeterminate-progress) - [MaterialProgress](#MaterialProgress) - [Rainbow](#rainbow) - [Crawler](#crawler) - [Spinner](#spinner) - [Shooting Stars](#shooting-stars) - [Rotating Arc](#rotating-arc) - [Determinate Progress](#determinate-progress) - [Circular Progress](#circular-progress) - [Progress Bar](#progress-bar) - [Other Apps](#other-apps) - [License](#license) # Installation ##CocoaPods [CocoaPods](http://cocoapods.org) adds supports for Swift and embedded frameworks. To integrate ProgressKit into your Xcode project using CocoaPods, specify it in your `Podfile`: ```ruby use_frameworks! pod 'ProgressKit' ``` For Swift 3 install directly from `swift-3` branch form github ```ruby pod 'ProgressKit', :git => "https://github.com/kaunteya/ProgressKit.git", :branch => 'swift-3' ``` Then, run the following command: ```bash $ pod install ``` # Usage - Drag a View at desired location in `XIB` or `Storyboard` - Change the Class to any of the desired progress views - Set the size such that width and height are equal - Drag `IBOutlet` to View Controller - For `Indeterminate` Progress Views - Set `true / false` to `view.animate` - For `Determinate` Progress Views: - Set `view.progress` to value in `0...1` # Indeterminate Progress ![Indeterminate](/Images/indeterminate.gif) Progress indicators which animate indefinately are `Indeterminate Progress` Views. This are the set of Indeterminate Progress Indicators. ## MaterialProgress ![CircularSnail](/Images/CircularSnail.gif) ## Rainbow ![Rainbow](/Images/Rainbow.gif) ## Crawler ![Crawler](/Images/Crawler.gif) ## Spinner ![Spinner](/Images/Spinner.gif) ## Shooting Stars ![Shooting Stars](/Images/ShootingStars.gif) ## Rotating Arc ![Rotating Arc](/Images/RotatingArc.gif) # Determinate Progress Determinate progress views can be used for tasks whos progress can be seen and determined. ## Circular Progress ![Circular Progress](/Images/CircularProgress.png) ## Progress Bar ![Progress Bar](/Images/ProgressBar.png) # Other Apps for Mac Apart from making Open source libraries I also make apps for Mac OS. Please have a look. ## [Lexi](https://apps.apple.com/tr/app/lexi-visual-json-browser/id1462580127?mt=12) Lexi is a split screen app that lets you browse large JSON with ease. It also has other featuers like `Prettify JSON`, `Minify JSON` `Copy JSON Path` and `Pin Large JSON` to narrow your visibility [View on Mac AppStore](https://apps.apple.com/tr/app/lexi-visual-json-browser/id1462580127?mt=12) ## [Quick Note](https://apps.apple.com/in/app/quicknote-one-click-notes/id1472935217?mt=12) Quick Note is a Mac OS app, lets you quickly add text either from Menu bar or from Shortcut. The text floats on other windows so that they are always visible It also supports `Auto Save` and `Pinned Notes` [View on Mac AppStore](https://apps.apple.com/in/app/quicknote-one-click-notes/id1472935217?mt=12) # License `ProgressKit` is released under the MIT license. See LICENSE for details.