8 Commits

Author SHA1 Message Date
Brandon McQuilkin 64128d4703 Experimenting with property animators to control the animation. 2016-08-09 11:06:38 -04:00
Brandon McQuilkin 26cf461a5d Started progress bar.
Added base progress view class.
2016-08-09 08:16:55 -04:00
Brandon McQuilkin 6d88f8afa0 Started the base of M13ProgressSuite 2 2016-08-07 16:24:47 -04:00
Brandon McQuilkin 299f96ca60 Starting with a clean slate. 2016-08-07 11:04:30 -04:00
Brandon McQuilkin 71c237eec6 Merge pull request #82 from sunkehappy/patch-1
Remove one useless variable height
2015-09-13 14:23:13 -04:00
Calvin 53a3c25f91 Remove one useless variable height
The `height` variable is set but never used later in `UINavigationController+M13ProgressViewBar.m`. So I suggest to delete it currently. If we need this variable later, get the old logic from Git history.
2015-09-10 18:04:54 +08:00
Brandon McQuilkin 56f020ced6 Merge pull request #81 from mhaleem/master
Use Preprocessor Macro for App Extension target to avoid compile erro…
2015-09-07 18:55:20 -04:00
Mina 6000d1de0f Use Preprocessor Macro for App Extension target to avoid compile error due to [UIApplication sharedApplication].statusBarOrientation] - instead using simple solution based on Device size 2015-08-24 12:23:13 +02:00
41 changed files with 635 additions and 5777 deletions
-236
View File
@@ -1,236 +0,0 @@
//
// M13HUDController.swift
// M13ProgressSuite
//
// Created by Brandon McQuilkin on 10/8/15.
// Copyright © 2015 Brandon McQuilkin. All rights reserved.
//
import UIKit
/**
The possible positions the status title and message can be in.
- BelowProgress: The text will be below the progress view.
- AboveProgress: The text will be above the progress view.
- LeadingProgress: The text will lead the progress view.
- TrailingProgress: The text will trail the progress view.
*/
public enum M13HUDStatusTextPosition: Int, RawRepresentable {
/// The text will be below the progress view.
case BelowProgress
/// The text will be above the progress view.
case AboveProgress
/// The text will lead the progress view.
case LeadingProgress
/// The text will trail the progress view.
case TrailingProgress
}
/**
The pre-defined background styles for the HUD. Pass one of these values on initalization to have the background view set up for you.
- None: Do not add any content to the `backgroundView`.
- SolidColor: Set up the `backgroundView` with a solid color background.
- LightVisualEffectView: Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with `UIBlurEffectStyleLight` as an option.
- ExtraLightVisualEffectView: Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with `UIBlurEffectStyleExtraLight` as an option.
- DarkVisualEffectView: Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with `UIBlurEffectStyleDark` as an option.
- LightVibrantVisualEffectView: Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with a `UIVibrancyEffect` with `UIBlurEffectStyleLight` as an option.
- ExtraLightVibrantVisualEffectView: Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with a `UIVibrancyEffect` with `UIBlurEffectStyleExtraLight` as an option.
- DarkVibrantVisualEffectView: Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with a `UIVibrancyEffect` with `UIBlurEffectStyleDark` as an option.
*/
public enum M13HUDBackgroundStyle: Int, RawRepresentable {
/// Do not add any content to the `backgroundView`.
case None
/// Set up the `backgroundView` with a solid color background.
case SolidColor
/// Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with `UIBlurEffectStyleLight` as an option.
case LightVisualEffectView
/// Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with `UIBlurEffectStyleExtraLight` as an option.
case ExtraLightVisualEffectView
/// Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with `UIBlurEffectStyleDark` as an option.
case DarkVisualEffectView
/// Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with a `UIVibrancyEffect` with `UIBlurEffectStyleLight` as an option.
case LightVibrantVisualEffectView
/// Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with a `UIVibrancyEffect` with `UIBlurEffectStyleExtraLight` as an option.
case ExtraLightVibrantVisualEffectView
/// Set up the `backgroundView` with a `UIVisualEffectView` subview initalized with a `UIVibrancyEffect` with `UIBlurEffectStyleDark` as an option.
case DarkVibrantVisualEffectView
}
/**
The possible overlay styles of the HUD.
- FullScreen: The HUD extends over the entire screen.
- Rect: The HUD will be a rectangle.
- SquareRect: The HUD will be a square.
- RoundedRect: The HUD will be a rectangle with rounded corners.
- RoundedSquareRect: The HUD will be a square with rounded corners.
*/
public enum M13HUDOverlayStyle: Int, RawRepresentable {
/// The HUD extends over the entire screen.
case FullScreen
/// The HUD will be a rectangle.
case Rect
/// The HUD will be a square.
case SquareRect
/// The HUD will be a rectangle with rounded corners.
case RoundedRect
/// The HUD will be a square with rounded corners.
case RoundedSquareRect
}
/**
A customizable view controller that presents an HUD. Works similarly to `UIAlertController`.
*/
public class M13HUDController: UIViewController {
//-------------------------------
// MARK: Appearance
//-------------------------------
/**
The position of the title text relative to the progress view.
*/
public var titlePosition: M13HUDStatusTextPosition = M13HUDStatusTextPosition.AboveProgress
/**
The position of the message text relative to the progress view.
*/
public var messagePosition: M13HUDStatusTextPosition = M13HUDStatusTextPosition.BelowProgress
//-------------------------------
// MARK: Properties
//-------------------------------
/**
The message to the user.
*/
public var message: String?
/**
The view that contains the background view and the content view.
*/
public let containerView: UIView = UIView()
/**
The view that is the background view. Add any background content to this view.
*/
public let backgroundView: UIView = UIView()
//-------------------------------
// MARK: Initalization
//-------------------------------
convenience init(backgroundStyle: M13HUDBackgroundStyle) {
self.init(overlayStyle: M13HUDOverlayStyle.RoundedSquareRect, backgroundStyle: backgroundStyle)
}
convenience init(overlayStyle: M13HUDOverlayStyle) {
self.init(overlayStyle: overlayStyle, backgroundStyle: M13HUDBackgroundStyle.LightVisualEffectView)
}
convenience init(overlayStyle: M13HUDOverlayStyle, backgroundStyle: M13HUDBackgroundStyle) {
self.init(nibName: nil, bundle: nil)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sharedSetup()
}
override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
sharedSetup()
}
private func sharedSetup() {
// Present over a full screen, as this has the posibility of being semi-transparent.
modalPresentationStyle = UIModalPresentationStyle.OverFullScreen
// Add the necessary views
view.addSubview(containerView)
containerView.addSubview(backgroundView)
var constraints: [NSLayoutConstraint] = NSLayoutConstraint.constraintsWithVisualFormat("H:|[backgroundView]|", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: ["backgroundView": backgroundView])
constraints += NSLayoutConstraint.constraintsWithVisualFormat("V:|[backgroundView]|", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: ["backgroundView": backgroundView])
NSLayoutConstraint.activateConstraints(constraints)
}
//-------------------------------
// MARK: Initalization Presets
//-------------------------------
private func setupPresetBackground(backgroundStyle: M13HUDBackgroundStyle) {
switch(backgroundStyle) {
case .SolidColor:
backgroundView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3)
break
case .LightVisualEffectView:
setupBackgroundViewWithVisualEffectView(UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Light)))
break
case .ExtraLightVisualEffectView:
setupBackgroundViewWithVisualEffectView(UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.ExtraLight)))
break
case .DarkVisualEffectView:
setupBackgroundViewWithVisualEffectView(UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Dark)))
break
case .LightVibrantVisualEffectView:
setupBackgroundViewWithVisualEffectView(UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: UIBlurEffect(style: UIBlurEffectStyle.Light))))
break
case .ExtraLightVibrantVisualEffectView:
setupBackgroundViewWithVisualEffectView(UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: UIBlurEffect(style: UIBlurEffectStyle.ExtraLight))))
break
case .DarkVibrantVisualEffectView:
setupBackgroundViewWithVisualEffectView(UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: UIBlurEffect(style: UIBlurEffectStyle.Dark))))
break
case .None:
// Do nothing
break
}
}
private func setupBackgroundViewWithVisualEffectView(view: UIVisualEffectView) {
backgroundView.addSubview(view)
var constraints: [NSLayoutConstraint] = NSLayoutConstraint.constraintsWithVisualFormat("H:|[view]|", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: ["view": view])
constraints += NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: ["view": view])
NSLayoutConstraint.activateConstraints(constraints)
}
private func setupConstraintsForOverlayStyle(style: M13HUDOverlayStyle) {
switch(style) {
case .FullScreen:
break
case .Rect:
break
case .SquareRect:
break
case .RoundedRect:
break
case .RoundedSquareRect:
break
}
}
//-------------------------------
// MARK: Actions
//-------------------------------
//-------------------------------
// MARK: Layout
//-------------------------------
//-------------------------------
// MARK: Other
//-------------------------------
}
@@ -1,266 +0,0 @@
//
// M13BorderedProgressBar.swift
// M13ProgressSuite
//
// Created by Brandon McQuilkin on 9/13/15.
// Copyright © 2015 Brandon McQuilkin. All rights reserved.
//
import UIKit
/**
A wrapper around M13ProgressBar that adds a border around the bar.
*/
@IBDesignable
public class M13BorderedProgressBar: M13ProgressView {
//-------------------------------
// MARK: Appearance
//-------------------------------
/**
The corner radius of the progress bar.
*/
@IBInspectable public var cornerRadius: CGFloat = CGFloat.max {
didSet {
progressBar.cornerRadius = cornerRadius
setNeedsLayout()
}
}
/**
The width of the border around the progress bar.
*/
@IBInspectable public var borderWidth: CGFloat = 1.0 {
didSet {
borderView.layer.borderWidth = borderWidth
}
}
/**
The spacing between the border and the progress bar.
*/
@IBInspectable public var borderPadding: CGFloat = 1.0
override public var secondaryColor: UIColor {
didSet {
progressBar.secondaryColor = secondaryColor
}
}
override public var successColor: UIColor {
didSet {
progressBar.successColor = successColor
if state == M13ProgressViewState.Success {
borderView.layer.borderColor = successColor.CGColor
}
}
}
override public var failureColor: UIColor {
didSet {
progressBar.failureColor = failureColor
if state == M13ProgressViewState.Failure {
borderView.layer.borderColor = failureColor.CGColor
}
}
}
//-------------------------------
// MARK: Properties
//-------------------------------
/**
The progress bar that displays the progress.
*/
public var progressBar: M13ProgressBar = M13ProgressBar() {
willSet(newValue) {
// Remove the current progress bar from the view.
progressBar.removeFromSuperview()
}
didSet(oldValue) {
// Set the current parameters
progressBar.cornerRadius = cornerRadius
progressBar.secondaryColor = secondaryColor
progressBar.successColor = successColor
progressBar.failureColor = failureColor
progressBar.progressDirection = progressDirection
progressBar.indeterminate = indeterminate
// Add the new progress bar to the view.
addSubview(progressBar)
}
}
/**
The view that displays the border layer.
*/
private var borderView: UIView = UIView()
/**
The direction the progress bar travels in as the progress nears completion.
*/
@IBInspectable public var progressDirection: M13ProgressBarProgressDirection = M13ProgressBarProgressDirection.LeadingToTrailing {
didSet {
progressBar.progressDirection = progressDirection
}
}
override public var indeterminate: Bool {
didSet {
progressBar.indeterminate = indeterminate
}
}
//-------------------------------
// MARK: Initalization
//-------------------------------
override public init() {
super.init()
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
if aDecoder.containsValueForKey("borderWidth") {
borderWidth = CGFloat(aDecoder.decodeDoubleForKey("borderWidth"))
}
if aDecoder.containsValueForKey("borderPadding") {
borderWidth = CGFloat(aDecoder.decodeDoubleForKey("borderPadding"))
}
if aDecoder.containsValueForKey("progressBar") {
progressBar = aDecoder.decodeObjectOfClass(M13ProgressBar.self, forKey: "progressBar")!
}
super.init(coder: aDecoder)
sharedSetup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
private func sharedSetup() {
// Set the defaults.
//self.clipsToBounds = true
// Set border
borderView.clipsToBounds = true
borderView.layer.borderColor = tintColor.CGColor
borderView.layer.borderWidth = borderWidth
borderView.backgroundColor = UIColor.clearColor()
// Set background
secondaryColor = UIColor.clearColor()
// Add views
addSubview(progressBar)
addSubview(borderView)
// Set the progress and indeterminate animations.
weak var weakSelf: M13BorderedProgressBar? = self;
progressUpdate = {() -> Void in
if let weakSelf = weakSelf {
weakSelf.progressBar.setProgress(weakSelf.progress, animated: false)
}
}
indeterminateUpdate = {(frameDuration: CFTimeInterval) -> Void in
weakSelf?.progressBar.indeterminateUpdate?(frameDuration: frameDuration)
}
setNeedsLayout()
}
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeDouble(Double(borderWidth), forKey: "borderWidth")
aCoder.encodeDouble(Double(borderPadding), forKey: "borderPadding")
aCoder.encodeObject(progressBar, forKey: "progressBar")
}
public override func prepareForInterfaceBuilder() {
sharedSetup()
super.prepareForInterfaceBuilder()
}
//-------------------------------
// MARK: Layout
//-------------------------------
public override func intrinsicContentSize() -> CGSize {
return CGSizeMake((borderWidth * 2) + (borderPadding * 2), (borderWidth * 2) + (borderPadding * 2))
}
public override func layoutSubviews() {
super.layoutSubviews()
// Update the corner radius
var appropiateCornerRadius: CGFloat = frame.size.width < frame.size.height ? frame.size.width / 2.0 : frame.size.height / 2.0
appropiateCornerRadius = appropiateCornerRadius > cornerRadius ? cornerRadius : appropiateCornerRadius
borderView.layer.cornerRadius = appropiateCornerRadius
// Layout
borderView.frame = CGRectMake(0.0, 0.0, frame.size.width, frame.size.height)
progressBar.frame = CGRectMake(borderWidth + borderPadding, borderWidth + borderPadding, frame.size.width - (2 * (borderWidth + borderPadding)), frame.size.height - (2 * (borderWidth + borderPadding)))
// Update progress
progressUpdate?()
}
//-------------------------------
// MARK: Actions
//-------------------------------
public override func setState(state: M13ProgressViewState, animated: Bool) {
super.setState(state, animated: animated)
if !animated {
switch state {
case .Normal:
borderView.layer.borderColor = tintColor.CGColor
progressBar.setState(state, animated: false)
break
case .Success:
borderView.layer.borderColor = successColor.CGColor
progressBar.setState(state, animated: false)
break
case .Failure:
borderView.layer.borderColor = failureColor.CGColor
progressBar.setState(state, animated: false)
break
}
} else {
let colorAnimation: CABasicAnimation = CABasicAnimation(keyPath: "borderColor")
colorAnimation.fromValue = borderView.layer.borderColor!
colorAnimation.fillMode = kCAFillModeForwards
colorAnimation.removedOnCompletion = false
colorAnimation.duration = animationDuration
var toColor: UIColor = tintColor
switch state {
case .Normal:
toColor = tintColor
break
case .Success:
toColor = successColor
break
case .Failure:
toColor = failureColor
break
}
colorAnimation.toValue = toColor.CGColor
borderView.layer.addAnimation(colorAnimation, forKey: "borderColor")
progressBar.setState(state, animated: true)
borderView.layer.borderColor = toColor.CGColor
}
}
//-------------------------------
// MARK: Other
//-------------------------------
public override func tintColorDidChange() {
super.tintColorDidChange()
borderView.layer.borderColor = tintColor.CGColor
}
}
-376
View File
@@ -1,376 +0,0 @@
//
// M13ProgressBar.swift
// M13ProgressSuite
//
/*
Copyright (c) 2015 Brandon McQuilkin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import UIKit
/**
The possible directions a progress bar can travel in.
- LeadingToTrailing: The progress bar will travel from leading to trailing as the progress nears completion.
- TrailingToLeading: The progress bar will travel from trailing to leading as the progress nears completion.
- BottomToTop: The progress bar will travel from the bottom to the top as the progress nears completion.
- TopToBottom: The progress bar will travel from the top to the bottom as the progress nears completion.
*/
public enum M13ProgressBarProgressDirection: Int, RawRepresentable {
/// The progress bar will travel from leading to trailing as the progress nears completion.
case LeadingToTrailing
/// The progress bar will travel from trailing to leading as the progress nears completion.
case TrailingToLeading
/// The progress bar will travel from the bottom to the top as the progress nears completion.
case BottomToTop
/// The progress bar will travel from the top to the bottom as the progress nears completion.
case TopToBottom
}
/**
A simple progress bar similar to UIProgressBar, but with an indeterminate state.
*/
@IBDesignable
public class M13ProgressBar: M13ProgressView {
//-------------------------------
// MARK: Appearance
//-------------------------------
/**
The corner radius of the progress bar.
*/
@IBInspectable public var cornerRadius: CGFloat = CGFloat.max {
didSet {
var appropiateCornerRadius: CGFloat = frame.size.width < frame.size.height ? frame.size.width / 2.0 : frame.size.height / 2.0
appropiateCornerRadius = appropiateCornerRadius > cornerRadius ? cornerRadius : appropiateCornerRadius
layer.cornerRadius = appropiateCornerRadius
progressLayer.cornerRadius = appropiateCornerRadius
indeterminateLayer.cornerRadius = appropiateCornerRadius
}
}
/**
The secondary color of the progress view.
*/
override public var secondaryColor: UIColor {
didSet {
layer.backgroundColor = secondaryColor.CGColor
}
}
/**
The primary color when the progress view is in the success state.
*/
override public var successColor: UIColor {
didSet {
if state == M13ProgressViewState.Success {
progressLayer.backgroundColor = successColor.CGColor
indeterminateLayer.backgroundColor = successColor.CGColor
}
}
}
/**
The primary color when the progress view is in the failure state.
*/
override public var failureColor: UIColor {
didSet {
if state == M13ProgressViewState.Failure {
progressLayer.backgroundColor = failureColor.CGColor
indeterminateLayer.backgroundColor = failureColor.CGColor
}
}
}
//-------------------------------
// MARK: Properties
//-------------------------------
/**
The direction the progress bar travels in as the progress nears completion.
*/
@IBInspectable public var progressDirection: M13ProgressBarProgressDirection = M13ProgressBarProgressDirection.LeadingToTrailing {
didSet {
progressUpdate?()
}
}
/**
The layer that makes up the progress bar.
*/
internal var progressLayer: CALayer = CALayer()
/**
The layer that makes up the indeterminate progress bar.
*/
internal var indeterminateLayer: CAShapeLayer = CAShapeLayer()
override public var indeterminate: Bool {
didSet {
// Add the indeterminate layer.
if indeterminate && indeterminateLayer.superlayer == nil {
progressLayer.removeFromSuperlayer()
layer.addSublayer(indeterminateLayer)
}
// Add the progress layer
if !indeterminate && progressLayer.superlayer == nil {
indeterminateLayer.removeFromSuperlayer()
layer.addSublayer(progressLayer)
}
}
}
//-------------------------------
// MARK: Initalization
//-------------------------------
override public init() {
super.init()
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
if aDecoder.containsValueForKey("cornerRadius") {
cornerRadius = CGFloat(aDecoder.decodeDoubleForKey("cornerRadius"))
}
if aDecoder.containsValueForKey("progressDirection") {
if let direction = M13ProgressBarProgressDirection(rawValue: aDecoder.decodeIntegerForKey("progressDirection")) {
progressDirection = direction
}
}
super.init(coder: aDecoder)
sharedSetup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
private func sharedSetup() {
// Set the defaults.
self.clipsToBounds = true
layer.cornerRadius = cornerRadius
layer.backgroundColor = secondaryColor.CGColor
progressLayer.cornerRadius = cornerRadius
indeterminateLayer.cornerRadius = cornerRadius
progressLayer.backgroundColor = tintColor.CGColor
indeterminateLayer.backgroundColor = tintColor.CGColor
// Disable default animations
progressLayer.actions = [
"frame": NSNull(),
"anchorPoint": NSNull(),
"bounds": NSNull(),
"position": NSNull(),
"cornerRadius": NSNull()
]
indeterminateLayer.actions = [
"frame": NSNull(),
"anchorPoint": NSNull(),
"bounds": NSNull(),
"position": NSNull(),
"cornerRadius": NSNull()
]
// Add the layers
self.layer.addSublayer(progressLayer)
// Set the progress and indeterminate animations.
weak var weakSelf: M13ProgressBar? = self;
progressUpdate = {() -> Void in
if let weakSelf = weakSelf {
// Get the frame of the progress layer
var progressFrame: CGRect = CGRectZero
switch weakSelf.progressDirection {
case .LeadingToTrailing:
let xPosition = UIView.userInterfaceLayoutDirectionForSemanticContentAttribute(UISemanticContentAttribute.Spatial) == UIUserInterfaceLayoutDirection.LeftToRight ? 0.0 : weakSelf.frame.size.width - (weakSelf.frame.size.width * weakSelf.progress)
progressFrame = CGRectMake(xPosition, 0.0, weakSelf.frame.size.width * weakSelf.progress, weakSelf.frame.size.height)
break
case .TrailingToLeading:
let xPosition = UIView.userInterfaceLayoutDirectionForSemanticContentAttribute(UISemanticContentAttribute.Spatial) == UIUserInterfaceLayoutDirection.RightToLeft ? 0.0 : weakSelf.frame.size.width - (weakSelf.frame.size.width * weakSelf.progress)
progressFrame = CGRectMake(xPosition, 0.0, weakSelf.frame.size.width * weakSelf.progress, weakSelf.frame.size.height)
break
case .BottomToTop:
progressFrame = CGRectMake(0.0, weakSelf.frame.size.height - (weakSelf.frame.size.height * weakSelf.progress), weakSelf.frame.size.width, weakSelf.frame.size.height * weakSelf.progress)
break
case .TopToBottom:
progressFrame = CGRectMake(0.0, 0.0, weakSelf.frame.size.width, weakSelf.frame.size.height * weakSelf.progress)
break
}
weakSelf.progressLayer.frame = progressFrame
}
}
indeterminateUpdate = {(frameDuration: CFTimeInterval) -> Void in
if let weakSelf = weakSelf {
let horizontallyTraveling: Bool = weakSelf.progressDirection == M13ProgressBarProgressDirection.LeadingToTrailing || weakSelf.progressDirection == M13ProgressBarProgressDirection.TrailingToLeading
let barPosition: CGFloat = horizontallyTraveling ? weakSelf.indeterminateLayer.frame.origin.x : weakSelf.indeterminateLayer.frame.origin.y
let barLength: CGFloat = horizontallyTraveling ? weakSelf.frame.size.width * 0.2 : weakSelf.frame.size.height * 0.2
let totalTravelDistance: CGFloat = horizontallyTraveling ? weakSelf.frame.size.width + (2.0 * barLength) : weakSelf.frame.size.height + (2.0 * barLength)
let totalAnimationFrames: CGFloat = CGFloat(weakSelf.indeterminateAnimationDuration) / CGFloat(frameDuration)
let travelDelta: CGFloat = totalTravelDistance / totalAnimationFrames
// Set the new frame of the bar: either move it by the travel delta, or move it back to the begining.
switch weakSelf.progressDirection {
case .LeadingToTrailing:
let leftToRight: Bool = UIView.userInterfaceLayoutDirectionForSemanticContentAttribute(UISemanticContentAttribute.Spatial) == UIUserInterfaceLayoutDirection.LeftToRight
if leftToRight {
if barPosition >= weakSelf.frame.size.width {
weakSelf.indeterminateLayer.frame = CGRectMake(-barLength, 0.0, barLength, weakSelf.frame.size.height)
} else {
weakSelf.indeterminateLayer.frame = CGRectMake(weakSelf.indeterminateLayer.frame.origin.x + travelDelta, 0.0, barLength, weakSelf.frame.size.height)
}
} else {
if barPosition <= -barLength {
weakSelf.indeterminateLayer.frame = CGRectMake(weakSelf.frame.size.width, 0.0, barLength, weakSelf.frame.size.height)
} else {
weakSelf.indeterminateLayer.frame = CGRectMake(weakSelf.indeterminateLayer.frame.origin.x - travelDelta, 0.0, barLength, weakSelf.frame.size.height)
}
}
break
case .TrailingToLeading:
var rightToLeft: Bool = UIView.userInterfaceLayoutDirectionForSemanticContentAttribute(UISemanticContentAttribute.Spatial) == UIUserInterfaceLayoutDirection.RightToLeft
if rightToLeft {
if barPosition <= -barLength {
weakSelf.indeterminateLayer.frame = CGRectMake(weakSelf.frame.size.width, 0.0, barLength, weakSelf.frame.size.height)
} else {
weakSelf.indeterminateLayer.frame = CGRectMake(weakSelf.indeterminateLayer.frame.origin.x - travelDelta, 0.0, barLength, weakSelf.frame.size.height)
}
} else {
if barPosition >= weakSelf.frame.size.width {
weakSelf.indeterminateLayer.frame = CGRectMake(-barLength, 0.0, barLength, weakSelf.frame.size.height)
} else {
weakSelf.indeterminateLayer.frame = CGRectMake(weakSelf.indeterminateLayer.frame.origin.x + travelDelta, 0.0, barLength, weakSelf.frame.size.height)
}
}
break
case .BottomToTop:
if barPosition <= -barLength {
weakSelf.indeterminateLayer.frame = CGRectMake(0.0, weakSelf.frame.size.height, weakSelf.frame.size.width, barLength)
} else {
weakSelf.indeterminateLayer.frame = CGRectMake(0.0, weakSelf.indeterminateLayer.frame.origin.y - travelDelta, weakSelf.frame.size.width, barLength)
}
break
case .TopToBottom:
if barPosition >= weakSelf.frame.size.height {
weakSelf.indeterminateLayer.frame = CGRectMake(0.0, -barLength, weakSelf.frame.size.width, barLength)
} else {
weakSelf.indeterminateLayer.frame = CGRectMake(0.0, weakSelf.indeterminateLayer.frame.origin.y + travelDelta, weakSelf.frame.size.width, barLength)
}
break
}
}
}
}
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeDouble(Double(cornerRadius), forKey: "cornerRadius")
aCoder.encodeInteger(progressDirection.rawValue, forKey: "progressDirection")
}
public override func prepareForInterfaceBuilder() {
sharedSetup()
super.prepareForInterfaceBuilder()
}
//-------------------------------
// MARK: Actions
//-------------------------------
public override func setState(state: M13ProgressViewState, animated: Bool) {
super.setState(state, animated: animated)
if !animated {
switch state {
case .Normal:
progressLayer.backgroundColor = tintColor.CGColor
indeterminateLayer.backgroundColor = tintColor.CGColor
break
case .Success:
progressLayer.backgroundColor = successColor.CGColor
indeterminateLayer.backgroundColor = successColor.CGColor
break
case .Failure:
progressLayer.backgroundColor = failureColor.CGColor
indeterminateLayer.backgroundColor = failureColor.CGColor
break
}
} else {
let colorAnimation: CABasicAnimation = CABasicAnimation(keyPath: "backgroundColor")
colorAnimation.fromValue = progressLayer.backgroundColor!
colorAnimation.fillMode = kCAFillModeForwards
colorAnimation.removedOnCompletion = false
colorAnimation.duration = animationDuration
var toColor: UIColor = tintColor
switch state {
case .Normal:
toColor = tintColor
break
case .Success:
toColor = successColor
break
case .Failure:
toColor = failureColor
break
}
colorAnimation.toValue = toColor.CGColor
progressLayer.addAnimation(colorAnimation, forKey: "backgroundColor")
indeterminateLayer.addAnimation(colorAnimation, forKey: "backgroundColor")
progressLayer.backgroundColor = toColor.CGColor
indeterminateLayer.backgroundColor = toColor.CGColor
}
}
//-------------------------------
// MARK: Layout
//-------------------------------
public override func intrinsicContentSize() -> CGSize {
return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric)
}
public override func layoutSubviews() {
super.layoutSubviews()
//Update the corner radius
var appropiateCornerRadius: CGFloat = frame.size.width < frame.size.height ? frame.size.width / 2.0 : frame.size.height / 2.0
appropiateCornerRadius = appropiateCornerRadius > cornerRadius ? cornerRadius : appropiateCornerRadius
layer.cornerRadius = appropiateCornerRadius
progressLayer.cornerRadius = appropiateCornerRadius
indeterminateLayer.cornerRadius = appropiateCornerRadius
//Update progress frame
progressUpdate?()
}
//-------------------------------
// MARK: Other
//-------------------------------
public override func tintColorDidChange() {
super.tintColorDidChange()
progressLayer.backgroundColor = tintColor.CGColor
indeterminateLayer.backgroundColor = tintColor.CGColor
}
}
@@ -1,379 +0,0 @@
//
// M13ProgressCircular.swift
// M13ProgressSuite
//
/*
Copyright (c) 2015 Brandon McQuilkin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import UIKit
/**
The possible directions a circular progress indicator can travel in.
- Clockwise: The progress ring will travel clockwise as the progress nears completion.
- CounterClockwise: The progress ring will travel counter-clockwise as the progress nears completion.
*/
public enum M13ProgressCircularProgressDirection: Int, RawRepresentable {
/// The progress ring will travel clockwise as the progress nears completion.
case Clockwise
/// The progress ring will travel counter-clockwise as the progress nears completion.
case CounterClockwise
}
/**
Base class for circular progress views.
Ring and Pie progress views are derived from this class. Do not instantiate directly.
*/
@IBDesignable
public class M13ProgressCircular: M13ProgressView {
//-------------------------------
// MARK: Properties
//-------------------------------
/**
The direction the progress bar travels in as the progress nears completion.
*/
@IBInspectable public var progressDirection: M13ProgressCircularProgressDirection = .Clockwise {
didSet {
progressUpdate?()
}
}
@IBInspectable public var backgroundRingWidth :Int = 0 {
didSet {
setNeedsLayout()
progressUpdate?()
}
}
//-------------------------------
// MARK: Property Overrides
//-------------------------------
/**
The secondary color of the progress view.
*/
override public var secondaryColor: UIColor {
didSet {
indeterminateLayer.strokeColor = secondaryColor.CGColor
}
}
/**
The primary color when the progress view is in the success state.
*/
override public var successColor: UIColor {
didSet {
if state == .Success {
iconLayer.fillColor = successColor.CGColor
}
}
}
/**
The primary color when the progress view is in the failure state.
*/
override public var failureColor: UIColor {
didSet {
if state == .Failure {
iconLayer.fillColor = failureColor.CGColor
}
}
}
//-------------------------------
// MARK: Layers
//-------------------------------
/**
The layer that makes up the progress ring.
*/
internal var progressLayer: CAShapeLayer = CAShapeLayer()
/**
The layer that makes up the indeterminate ring, and the background for the progress ring.
*/
internal var indeterminateLayer: CAShapeLayer = CAShapeLayer()
/**
The layer that is used to render icons for success or failure.
*/
internal var iconLayer: CAShapeLayer = CAShapeLayer()
//-------------------------------
// MARK: Protected Variables
//-------------------------------
/** The starting angle for drawing the indeterminate animation ring. */
internal var indeterminateAnimationAngle :CGFloat = 0
/** Ring widths after validation and bounds adjustments */
internal var adjustedBackgroundRingWidth :CGFloat = 0
//-------------------------------
// MARK: Initalization
//-------------------------------
override public init() {
super.init()
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
if aDecoder.containsValueForKey("progressDirection") {
if let direction = M13ProgressCircularProgressDirection(rawValue: aDecoder.decodeIntegerForKey("progressDirection")) {
progressDirection = direction
}
}
if aDecoder.containsValueForKey("backgroundRingWidth") {
backgroundRingWidth = aDecoder.decodeIntegerForKey("backgroundRingWidth")
}
super.init(coder: aDecoder)
sharedSetup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
internal func sharedSetup() {
// Set the defaults.
self.clipsToBounds = false
layer.backgroundColor = UIColor.clearColor().CGColor
// Set up the indeterminate layer
indeterminateLayer = CAShapeLayer()
indeterminateLayer.backgroundColor = UIColor.clearColor().CGColor
indeterminateLayer.strokeColor = secondaryColor.CGColor
indeterminateLayer.fillColor = nil
indeterminateLayer.lineCap = kCALineCapRound
// Set up the progress layer
progressLayer = CAShapeLayer()
progressLayer.backgroundColor = UIColor.clearColor().CGColor
progressLayer.strokeColor = nil
progressLayer.fillColor = tintColor.CGColor
progressLayer.lineCap = kCALineCapButt
adjustBackgroundRingWidth()
// Set up the icon layer
iconLayer = CAShapeLayer()
iconLayer.backgroundColor = UIColor.clearColor().CGColor
iconLayer.strokeColor = nil
iconLayer.fillColor = nil
iconLayer.lineCap = kCALineCapButt
// Disable default animations
progressLayer.actions = [
"frame": NSNull(),
"anchorPoint": NSNull(),
"bounds": NSNull(),
"position": NSNull(),
]
indeterminateLayer.actions = [
"frame": NSNull(),
"anchorPoint": NSNull(),
"bounds": NSNull(),
"position": NSNull(),
]
iconLayer.actions = [
"frame": NSNull(),
"anchorPoint": NSNull(),
"bounds": NSNull(),
"position": NSNull(),
]
// Add the layers
layer.addSublayer(indeterminateLayer)
layer.addSublayer(progressLayer)
layer.addSublayer(iconLayer)
// Be sure to implement progressUpdate() and indeterminateUpdate in child classes.
}
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeInteger(progressDirection.rawValue, forKey: "progressDirection")
aCoder.encodeInteger(backgroundRingWidth, forKey: "backgroundRingWidth")
super.encodeWithCoder(aCoder)
}
public override func prepareForInterfaceBuilder() {
sharedSetup()
super.prepareForInterfaceBuilder()
}
//-------------------------------
// MARK: Actions
//-------------------------------
public override func setState(state: M13ProgressViewState, animated: Bool) {
super.setState(state, animated: animated)
switch state {
case .Normal:
hideIcon()
break
case .Success:
drawSuccess()
break
case .Failure:
drawFailure()
break
}
setNeedsLayout()
progressUpdate?()
}
//-------------------------------
// MARK: Layout
//-------------------------------
public override func intrinsicContentSize() -> CGSize {
return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric)
}
public override func layoutSubviews() {
super.layoutSubviews()
adjustBackgroundRingWidth()
// Update progress frame
progressUpdate?()
}
public func adjustBackgroundRingWidth()
{
if backgroundRingWidth > 0 {
adjustedBackgroundRingWidth = CGFloat(backgroundRingWidth)
} else {
adjustedBackgroundRingWidth = max(self.bounds.size.width * 0.025, 1.0)
}
indeterminateLayer.lineWidth = adjustedBackgroundRingWidth
}
//-------------------------------
// MARK: Draw Functions
//-------------------------------
public func maxRadius() -> CGFloat
{
return min(self.bounds.size.width, self.bounds.size.height) / 2.0
}
public func centerOfCircle() -> CGPoint
{
return CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0)
}
public func createPieSlicePath(center: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool) -> UIBezierPath {
let path = UIBezierPath()
path.moveToPoint(center)
path.addLineToPoint(CGPointMake(center.x + radius * cos(startAngle), center.y + radius * sin(startAngle)))
path.addArcWithCenter(center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: clockwise)
path.closePath()
return path
}
public func drawBackground()
{
// Draw a circle
let center = centerOfCircle()
let radius = maxRadius() - adjustedBackgroundRingWidth / 2.0
let path = UIBezierPath()
path.addArcWithCenter(center, radius: radius, startAngle: 0, endAngle: 2.0 * CGFloat(M_PI), clockwise: true)
indeterminateLayer.path = path.CGPath
}
public func drawSuccess()
{
// Draw relative to a base size and percentage, that way the check can be drawn for any size.
let radius = maxRadius()
let size = radius * 0.3
// Create the path for the Checkmark
let path = UIBezierPath()
path.moveToPoint(CGPointMake(0, 0))
path.addLineToPoint(CGPointMake(0, size * 2))
path.addLineToPoint(CGPointMake(size * 3, size * 2))
path.addLineToPoint(CGPointMake(size * 3, size))
path.addLineToPoint(CGPointMake(size, size))
path.addLineToPoint(CGPointMake(size, 0))
path.closePath()
// Rotate it through -45 degrees...
path.applyTransform(CGAffineTransformMakeRotation(CGFloat(-M_PI_4)))
// Center it
path.applyTransform(CGAffineTransformMakeTranslation(radius * 0.46, radius * 1.02))
// Set path and fill color
iconLayer.path = path.CGPath
iconLayer.fillColor = successColor.CGColor
}
public func drawFailure()
{
// Calculate the size of the X
let radius = maxRadius()
let size = radius * 0.3
// Create the path for the X
let path = UIBezierPath()
path.moveToPoint(CGPointMake(size, 0))
path.addLineToPoint(CGPointMake(2 * size, 0))
path.addLineToPoint(CGPointMake(2 * size, size))
path.addLineToPoint(CGPointMake(3 * size, size))
path.addLineToPoint(CGPointMake(3 * size, 2 * size))
path.addLineToPoint(CGPointMake(2 * size, 2 * size))
path.addLineToPoint(CGPointMake(2 * size, 3 * size))
path.addLineToPoint(CGPointMake(size, 3 * size))
path.addLineToPoint(CGPointMake(size, 2 * size))
path.addLineToPoint(CGPointMake(0, 2 * size))
path.addLineToPoint(CGPointMake(0, size))
path.addLineToPoint(CGPointMake(size, size))
path.closePath()
// Center it
path.applyTransform(CGAffineTransformMakeTranslation(radius - (1.5 * size), radius - (1.5 * size)))
// Rotate path
let a = CGFloat(cos(M_PI_4))
let b = CGFloat(sin(M_PI_4))
let c = CGFloat(-sin(M_PI_4))
let d = CGFloat(cos(M_PI_4))
let tx = radius * CGFloat(1 - cos(M_PI_4) + sin(M_PI_4))
let ty = radius * CGFloat(1 - sin(M_PI_4) - cos(M_PI_4))
path.applyTransform(CGAffineTransformMake(a, b, c, d, tx, ty))
// Set path and fill color
iconLayer.path = path.CGPath
iconLayer.fillColor = failureColor.CGColor
}
public func hideIcon()
{
iconLayer.path = nil
}
//-------------------------------
// MARK: Other
//-------------------------------
public override func tintColorDidChange() {
super.tintColorDidChange()
progressLayer.fillColor = tintColor.CGColor
progressLayer.strokeColor = nil
}
}
@@ -1,302 +0,0 @@
//
// M13ProgressFilteredImage.swift
// M13ProgressSuite
//
/*
Copyright (c) 2015 Brandon McQuilkin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import UIKit
/**
The possible filters that can be applied to a progress image.
- Blur: The image goes from blurry to in-focus as progress nears completion.
- LightTunnel:
- SepiaTone: The image goes from Sepia Tone to full-color as progress nears completion.
*/
public enum M13ProgressImageProgressFilter: Int, RawRepresentable {
///
case Blur
///
case LightTunnel
///
case SepiaTone
}
/**
A progress view where progress is shown by changes in CIFilters.
@note This progress bar does not have in indeterminate mode and does not respond to actions.
*/
@IBDesignable
public class M13ProgressFilteredImage: M13ProgressView {
//-------------------------------
// MARK: Properties
//-------------------------------
/**
The direction the progress bar travels in as the progress nears completion. (What direction the fill proceeds in.)
*/
@IBInspectable public var progressFilter: M13ProgressImageProgressFilter = .Blur {
didSet {
switch (progressFilter) {
case .Blur:
setBlurFilter()
case .LightTunnel:
setLightTunnelFilter()
case .SepiaTone:
setSepiaToneFilter()
}
progressUpdate?()
}
}
/**
The image to use when showing progress.
*/
@IBInspectable public var progressImage: UIImage! {
didSet {
progressUpdate?()
}
}
//-------------------------------
// MARK: Filter Variables
//-------------------------------
/**
The array of CIFilters to apply to the image.
*/
public var filters :[AnyObject] = []
/**
The dictionaries of dictionaries that correspond to filter properties to be changed.
NSArray
|------ NSDictionary (Index matches the coresponding CIFilter in filters)
| |---- "Parameter Key" -> NSDictionary
| | |------ "Start Value" -> NSNumber
| | |------ "End Value" -> NSNumber
| |---- "Parameter Key" -> NSDictionary
| |------ "Start Value" -> NSNumber
| |------ "End Value" -> NSNumber
|------ NSDictionary ...
*/
public var filterParameters :[ [String:AnyObject] ] = []
/**
Keys for the filterParameters dictionary.
*/
public let FilterStartValuesKey = "StartValues"
public let FilterEndValuesKey = "EndValues"
//-------------------------------
// MARK: Protected Variables
//-------------------------------
/**
The UIImageView that shows the progress image.
*/
internal var progressView: UIImageView!
/**
Link to the display to keep animations in sync.
*/
internal var displayLink: CADisplayLink!
//-------------------------------
// MARK: Initalization
//-------------------------------
override public init() {
super.init()
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
if aDecoder.containsValueForKey("progressFilter") {
if let filter = M13ProgressImageProgressFilter(rawValue: aDecoder.decodeIntegerForKey("progressFilter")) {
progressFilter = filter
}
}
if aDecoder.containsValueForKey("progressImage") {
if let img = aDecoder.decodeObjectForKey("progressImage") as? UIImage {
progressImage = img
}
}
super.init(coder: aDecoder)
sharedSetup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
internal func sharedSetup() {
// Set the defaults
self.clipsToBounds = false
layer.backgroundColor = UIColor.clearColor().CGColor
// Set the progress image view
progressView = UIImageView(frame: self.bounds)
progressView.contentMode = .ScaleAspectFit
addSubview(progressView)
// Layout
layoutSubviews()
// Set the progress animation.
weak var weakSelf: M13ProgressFilteredImage? = self
progressUpdate = {() -> Void in
if let retainedSelf = weakSelf {
retainedSelf.progressView.image = retainedSelf.createImageForCurrentProgress()
}
}
// There is no indeterminate animation.
}
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeInteger(progressFilter.rawValue, forKey: "progressFilter")
aCoder.encodeObject(progressImage)
super.encodeWithCoder(aCoder)
}
public override func prepareForInterfaceBuilder() {
sharedSetup()
super.prepareForInterfaceBuilder()
}
//-------------------------------
// MARK: Filters
//-------------------------------
internal func setBlurFilter()
{
guard let blurFilter = CIFilter(name: "CIGaussianBlur") else {
return
}
blurFilter.setDefaults()
filters = [ blurFilter ]
filterParameters = [
[
"inputRadius" : [
FilterStartValuesKey : CGFloat(100.0),
FilterEndValuesKey : CGFloat(0.0)
]
]
]
}
internal func setSepiaToneFilter()
{
guard let sepiaFilter = CIFilter(name: "CISepiaTone") else {
return
}
sepiaFilter.setDefaults()
// Set filter intensity
sepiaFilter.setValue(1.0, forKey: kCIInputIntensityKey)
filters = [ sepiaFilter ]
filterParameters = [
[
kCIInputIntensityKey : [
FilterStartValuesKey : CGFloat(1.0),
FilterEndValuesKey : CGFloat(0.0)
]
]
]
}
internal func setLightTunnelFilter()
{
if false { "TODO: CILightTunnel filter does not work yet" }
guard let lightTunnelFilter = CIFilter(name: "CILightTunnel") else {
return
}
lightTunnelFilter.setDefaults()
// Get center
let center = CIVector(CGPoint: CGPointMake(progressImage.size.width / 2.0, progressImage.size.height / 2.0))
lightTunnelFilter.setValue(center, forKey: "inputCenter")
filters = [ lightTunnelFilter ]
filterParameters = [
[
"inputRotation" : [
FilterStartValuesKey : CGFloat(10.0),
FilterEndValuesKey : CGFloat(0.0)
],
"inputRadius" : [
FilterStartValuesKey : CGFloat(20.0),
FilterEndValuesKey : CGFloat(0.0)
]
]
]
}
//-------------------------------
// MARK: Layout
//-------------------------------
public override func intrinsicContentSize() -> CGSize {
return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric)
}
//-------------------------------
// MARK: Draw Functions
//-------------------------------
public func createImageForCurrentProgress() -> UIImage? {
guard let cgimage = progressImage.CGImage else {
return nil
}
// Create the base CIImage
var ciimage = CIImage(CGImage: cgimage)
// Change the values of the CIFilters before drawing
for (var i = 0; i < filters.count; ++i) {
let filter = filters[i]
// For each filter
let parameters = filterParameters[i]
// For each parameter
for parameterKey in parameters.keys {
// Retrieve the values
let obj = parameters[parameterKey]
if let parameterDict = obj as? [String:CGFloat] {
if let startValue = parameterDict[FilterStartValuesKey], let endValue = parameterDict[FilterEndValuesKey] {
// Calculate the current value
let value = startValue + ((endValue - startValue) * self.progress)
// Set the value
filter.setValue(value, forKey: parameterKey)
}
}
}
// Set the input image
filter.setValue(ciimage, forKey: kCIInputImageKey)
if let img0 = filter.outputImage, let img1 = img0 {
ciimage = img1
}
}
return UIImage(CIImage: ciimage)
}
}
@@ -1,243 +0,0 @@
//
// M13ProgressImage.swift
// M13ProgressSuite
//
/*
Copyright (c) 2015 Brandon McQuilkin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import UIKit
/**
A progress bar where progress is shown by cutting an image.
@note This progress bar does not have in indeterminate mode and does not respond to actions.
*/
@IBDesignable
public class M13ProgressImage: M13ProgressView {
//-------------------------------
// MARK: Properties
//-------------------------------
/**
The direction the progress bar travels in as the progress nears completion. (What direction the fill proceeds in.)
*/
@IBInspectable public var progressDirection: M13ProgressBarProgressDirection = .LeadingToTrailing {
didSet {
progressUpdate?()
}
}
/**
The image to use when showing progress.
*/
@IBInspectable public var progressImage: UIImage! {
didSet {
progressUpdate?()
}
}
/**
Whether or not to draw the greyscale background.
*/
@IBInspectable public var drawGreyscaleBackground: Bool = true {
didSet {
progressUpdate?()
}
}
//-------------------------------
// MARK: Protected Variables
//-------------------------------
/**
The UIImageView that shows the progress image.
*/
internal var progressView: UIImageView!
/**
Link to the display to keep animations in sync.
*/
internal var displayLink: CADisplayLink!
//-------------------------------
// MARK: Initalization
//-------------------------------
override public init() {
super.init()
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
if aDecoder.containsValueForKey("progressDirection") {
if let direction = M13ProgressBarProgressDirection(rawValue: aDecoder.decodeIntegerForKey("progressDirection")) {
progressDirection = direction
}
}
if aDecoder.containsValueForKey("progressImage") {
if let img = aDecoder.decodeObjectForKey("progressImage") as? UIImage {
progressImage = img
}
}
if aDecoder.containsValueForKey("drawGreyscaleBackground") {
drawGreyscaleBackground = aDecoder.decodeBoolForKey("drawGreyscaleBackground")
}
super.init(coder: aDecoder)
sharedSetup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
internal func sharedSetup() {
// Set the defaults
self.clipsToBounds = false
layer.backgroundColor = UIColor.clearColor().CGColor
// Set the progress image view
progressView = UIImageView(frame: self.bounds)
progressView.contentMode = .ScaleAspectFit
addSubview(progressView)
// Layout
layoutSubviews()
// Set the progress animation.
weak var weakSelf: M13ProgressImage? = self
progressUpdate = {() -> Void in
if let retainedSelf = weakSelf {
retainedSelf.progressView.image = retainedSelf.createImageForCurrentProgress()
}
}
// There is no indeterminate animation.
}
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeInteger(progressDirection.rawValue, forKey: "progressDirection")
aCoder.encodeObject(progressImage, forKey: "progressImage")
aCoder.encodeBool(drawGreyscaleBackground, forKey: "drawGreyscaleBackground")
super.encodeWithCoder(aCoder)
}
public override func prepareForInterfaceBuilder() {
sharedSetup()
super.prepareForInterfaceBuilder()
}
//-------------------------------
// MARK: Actions
//-------------------------------
//-------------------------------
// MARK: Layout
//-------------------------------
public override func intrinsicContentSize() -> CGSize {
return CGSizeMake(UIViewNoIntrinsicMetric, UIViewNoIntrinsicMetric)
}
//-------------------------------
// MARK: Draw Functions
//-------------------------------
public func createImageForCurrentProgress() -> UIImage?
{
// Create image rectangle with current image width/height
let imageRect = CGRectMake(0, 0, progressImage.size.width * progressImage.scale, progressImage.size.height * progressImage.scale)
let width = imageRect.size.width
let height = imageRect.size.height
// The pixels will be painted to this array
let BPP = 4 // 4 bytes per pixel (alpha-red-green-blue)
let memsize = Int(width) * Int(height)
let pixels = UnsafeMutablePointer<UInt32>.alloc(memsize)
// Clear the pixels so any transparency is preserved
pixels.initializeFrom(Repeat(count: memsize, repeatedValue: 0))
//Create a context with ARGB pixels
let colorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo.ByteOrder32Little.rawValue | CGImageAlphaInfo.PremultipliedLast.rawValue
let context = CGBitmapContextCreate(pixels, Int(width), Int(height), 8, Int(width) * BPP, colorSpace, bitmapInfo)
// Paint the bitmap to our context which will fill in the pixels array
CGContextDrawImage(context, CGRectMake(0, 0, width, height), progressImage.CGImage)
// Calculate the ranges to make greyscale or transparent
var xFrom: Int = 0
var xTo : Int = Int(width)
var yFrom: Int = 0
var yTo : Int = Int(height)
if (progressDirection == .BottomToTop) {
yTo = Int(height * (1 - self.progress))
} else if (progressDirection == .TopToBottom) {
yFrom = Int(height * self.progress)
} else if (progressDirection == .LeadingToTrailing) {
xFrom = Int(width * self.progress)
} else if (progressDirection == .TrailingToLeading) {
xTo = Int(width * (1 - self.progress))
}
for (var x = xFrom; x < xTo; ++x) {
for (var y = yFrom; y < yTo; ++y) {
// Get the pixel
let index = (y * Int(width) + x)
// Convert
if drawGreyscaleBackground {
let value = pixels[index]
// Mask out the alpha component
let alpha = value & 0x000000FF
// Mask out the red-green-blue component values, and bitshift them down to one byte
let r0 = UInt8((value & 0x0000FF00) >> 8)
let g0 = UInt8((value & 0x00FF0000) >> 16)
let b0 = UInt8((value & 0xFF000000) >> 24)
if false { "TODO: grayscale has a very green hue to it -- should be more gray" }
// Convert each red-green-blue component value to grayscale using luma coding
// http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale
let r1 = UInt8(0.299 * CGFloat(r0))
let g1 = UInt8(0.587 * CGFloat(g0))
let b1 = UInt8(0.114 * CGFloat(b0))
// Set the current pixel to gray
// Bitshift the red-green-blue component values left so we can OR them into a 4-byte pixel value
let r2 = UInt32(r1) << 8
let g2 = UInt32(g1) << 16
let b2 = UInt32(b1) << 24
pixels[index] = alpha | r2 | g2 | b2
} else {
// Convert the current pixel to transparent
pixels[index] = 0
}
}
}
// We're done with the pixel array, so release it
pixels.dealloc(memsize)
// Create a new CGImageRef from our context with the modified pixels, then
// Make a new UIImage to return
if let image = CGBitmapContextCreateImage(context) {
return UIImage(CGImage: image, scale: progressImage.scale, orientation: .Up)
}
return nil
}
}
-109
View File
@@ -1,109 +0,0 @@
//
// M13ProgressPie.swift
// M13ProgressSuite
//
/*
Copyright (c) 2015 Brandon McQuilkin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import UIKit
/**
A progress view that shows progress with a pie chart.
*/
@IBDesignable
public class M13ProgressPie: M13ProgressCircular {
//-------------------------------
// MARK: Initalization
//-------------------------------
override public init() {
super.init()
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sharedSetup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
override internal func sharedSetup() {
super.sharedSetup()
// Set the defaults.
self.clipsToBounds = false
layer.backgroundColor = UIColor.clearColor().CGColor
// Set the progress animation.
weak var weakSelf: M13ProgressPie? = self
progressUpdate = {() -> Void in
if let retainedSelf = weakSelf {
// Create parameters to draw ring
var startAngle = CGFloat(-M_PI_2)
var endAngle = startAngle + (2.0 * CGFloat(M_PI) * retainedSelf.progress)
let clockwise = (retainedSelf.progressDirection == .Clockwise)
if !clockwise {
// For counter-clockwise, subtract angles from 360 degrees, and swap start-end
let tmp = CGFloat(M_PI) - startAngle
startAngle = CGFloat(M_PI) - endAngle
endAngle = tmp
}
// Draw background
retainedSelf.drawBackground()
// Draw progress ring
let center = retainedSelf.centerOfCircle()
let radius = retainedSelf.maxRadius()
let path = retainedSelf.createPieSlicePath(center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
retainedSelf.progressLayer.path = path.CGPath
}
}
// Set the indeterminate animation.
indeterminateUpdate = {(frameDuration: CFTimeInterval) -> Void in
if let retainedSelf = weakSelf {
// Create parameters to draw progress
let startAngle = CGFloat(retainedSelf.indeterminateAnimationAngle)
let endAngle = startAngle + CGFloat(M_PI) * 2.0 * 0.8 // 80% of a circle
let deltaAngle = CGFloat(frameDuration * 2.0 * M_PI)
if retainedSelf.progressDirection == .CounterClockwise {
// CounterClockwise
retainedSelf.indeterminateAnimationAngle -= deltaAngle
} else {
// Clockwise
retainedSelf.indeterminateAnimationAngle += deltaAngle
}
// Draw background
retainedSelf.drawBackground()
// Draw path
let center = retainedSelf.centerOfCircle()
let radius = retainedSelf.maxRadius()
let path = retainedSelf.createPieSlicePath(center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: false)
retainedSelf.progressLayer.path = path.CGPath
}
}
}
}
@@ -1,315 +0,0 @@
//
// M13ProgressRing.swift
// M13ProgressSuite
//
/*
Copyright (c) 2015 Brandon McQuilkin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import UIKit
/**
A progress view stylized similarly to the iOS 7 App store progress view.
*/
@IBDesignable
public class M13ProgressRing: M13ProgressCircular {
//-------------------------------
// MARK: Properties
//-------------------------------
@IBInspectable public var percentage: Bool = false {
didSet {
percentageLabel.hidden = !percentage
setNeedsLayout()
progressUpdate?()
}
}
@IBInspectable public var progressRingWidth :Int = 0 {
didSet {
setNeedsLayout()
progressUpdate?()
}
}
//-------------------------------
// MARK: Property Overrides
//-------------------------------
override public var indeterminate: Bool {
didSet {
let tmp = indeterminate
super.indeterminate = tmp
if indeterminate {
progressLayer.hidden = true
percentageLabel.hidden = true
} else {
progressLayer.hidden = false
percentageLabel.hidden = !percentage
}
setNeedsLayout()
progressUpdate?()
}
}
//-------------------------------
// MARK: Protected Variables
//-------------------------------
/** The number formatter to display the progress percentage. */
internal var percentageFormatter: NSNumberFormatter!
/** The label that shows the percentage. */
internal var percentageLabel: UILabel!
/** Ring widths after validation and bounds adjustments */
internal var adjustedProgressRingWidth :CGFloat = 0
//-------------------------------
// MARK: Initalization
//-------------------------------
override public init() {
super.init()
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
if aDecoder.containsValueForKey("percentage") {
percentage = aDecoder.decodeBoolForKey("percentage")
}
if aDecoder.containsValueForKey("progressRingWidth") {
progressRingWidth = aDecoder.decodeIntegerForKey("progressRingWidth")
}
super.init(coder: aDecoder)
sharedSetup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
internal override func sharedSetup() {
super.sharedSetup()
// Set the defaults.
self.clipsToBounds = false
layer.backgroundColor = UIColor.clearColor().CGColor
// Set up the indeterminate layer
indeterminateLayer.strokeColor = secondaryColor.CGColor
indeterminateLayer.fillColor = nil
// Set up the progress layer
progressLayer.strokeColor = tintColor.CGColor
progressLayer.fillColor = nil
adjustProgressRingWidth()
// Set up the number formatter
percentageFormatter = NSNumberFormatter()
percentageFormatter.numberStyle = .PercentStyle
// Set the percentage label
percentageLabel = UILabel(frame: self.bounds)
percentageLabel.textAlignment = .Center
percentageLabel.contentMode = .Center
self.addSubview(percentageLabel)
// Set the progress animation.
weak var weakSelf: M13ProgressRing? = self
progressUpdate = {() -> Void in
if let retainedSelf = weakSelf {
// Create parameters to draw ring
let clockwise = (retainedSelf.progressDirection == .Clockwise)
var startAngle = CGFloat(-M_PI_2)
var endAngle = startAngle + (2.0 * CGFloat(M_PI) * retainedSelf.progress)
if !clockwise {
// For counter-clockwise, subtract angles from 360 degrees, and swap start-end
let tmp = CGFloat(M_PI) - startAngle
startAngle = CGFloat(M_PI) - endAngle
endAngle = tmp
}
// Draw background
retainedSelf.drawBackground()
// Draw progress ring
let center = retainedSelf.centerOfCircle()
let radius = retainedSelf.maxRadius() - retainedSelf.adjustedProgressRingWidth / 2.0
let path = UIBezierPath()
path.addArcWithCenter(center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
retainedSelf.progressLayer.path = path.CGPath
// Draw percentage
if retainedSelf.percentage && retainedSelf.state == .Normal {
retainedSelf.drawPercentage()
}
}
}
// Set the indeterminate animation.
indeterminateUpdate = {(frameDuration: CFTimeInterval) -> Void in
if let retainedSelf = weakSelf {
retainedSelf.hidePercentage()
// Create parameters to draw progress
let startAngle = CGFloat(retainedSelf.indeterminateAnimationAngle)
let endAngle = startAngle + CGFloat(M_PI) * 2.0 * 0.8 // 80% of a circle
let deltaAngle = CGFloat(frameDuration * 2.0 * M_PI)
if retainedSelf.progressDirection == .CounterClockwise {
// CounterClockwise
retainedSelf.indeterminateAnimationAngle -= deltaAngle
} else {
// Clockwise
retainedSelf.indeterminateAnimationAngle += deltaAngle
}
// Draw path
let center = retainedSelf.centerOfCircle()
let radius = retainedSelf.maxRadius() - retainedSelf.adjustedBackgroundRingWidth / 2.0
let path = UIBezierPath()
path.addArcWithCenter(center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
retainedSelf.indeterminateLayer.path = path.CGPath
}
}
}
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeBool(percentage, forKey: "percentage")
aCoder.encodeInteger(progressRingWidth, forKey: "progressRingWidth")
super.encodeWithCoder(aCoder)
}
//-------------------------------
// MARK: Actions
//-------------------------------
public override func setState(state: M13ProgressViewState, animated: Bool) {
super.setState(state, animated: animated)
var toColor1: UIColor = tintColor
var toColor2: UIColor = secondaryColor
switch state {
case .Normal:
hideIcon()
if percentage {
drawPercentage()
}
break
case .Success:
hidePercentage()
drawSuccess()
toColor1 = successColor
if indeterminate {
toColor2 = successColor
}
break
case .Failure:
hidePercentage()
drawFailure()
toColor1 = failureColor
if indeterminate {
toColor2 = failureColor
}
break
}
if !animated {
progressLayer.strokeColor = toColor1.CGColor
indeterminateLayer.strokeColor = toColor2.CGColor
} else {
let colorAnimation1: CABasicAnimation = CABasicAnimation(keyPath: "strokeColor")
colorAnimation1.fromValue = progressLayer.backgroundColor!
colorAnimation1.fillMode = kCAFillModeForwards
colorAnimation1.removedOnCompletion = false
colorAnimation1.duration = animationDuration
let colorAnimation2: CABasicAnimation = CABasicAnimation(keyPath: "strokeColor")
colorAnimation2.fromValue = indeterminateLayer.backgroundColor!
colorAnimation2.fillMode = kCAFillModeForwards
colorAnimation2.removedOnCompletion = false
colorAnimation2.duration = animationDuration
colorAnimation1.toValue = toColor1.CGColor
progressLayer.addAnimation(colorAnimation1, forKey: "strokeColor")
progressLayer.strokeColor = toColor1.CGColor
colorAnimation2.toValue = toColor2.CGColor
indeterminateLayer.addAnimation(colorAnimation2, forKey: "strokeColor")
indeterminateLayer.strokeColor = toColor2.CGColor
}
setNeedsLayout()
progressUpdate?()
}
//-------------------------------
// MARK: Layout
//-------------------------------
public override func layoutSubviews() {
super.layoutSubviews()
adjustProgressRingWidth()
// Percentage label
if percentage {
percentageLabel.frame = self.bounds
percentageLabel.font = UIFont.systemFontOfSize(self.bounds.size.width / 5)
percentageLabel.textColor = tintColor
}
// Update progress frame
progressUpdate?()
}
public func adjustProgressRingWidth()
{
if progressRingWidth > 0 {
adjustedProgressRingWidth = CGFloat(progressRingWidth)
} else {
adjustedProgressRingWidth = adjustedBackgroundRingWidth * 3.0
}
progressLayer.lineWidth = adjustedProgressRingWidth
}
//-------------------------------
// MARK: Draw Functions
//-------------------------------
public func drawPercentage()
{
percentageLabel.text = percentageFormatter.stringFromNumber(self.progress)
}
public func hidePercentage()
{
percentageLabel.text = ""
}
//-------------------------------
// MARK: Other
//-------------------------------
public override func tintColorDidChange() {
super.tintColorDidChange()
progressLayer.fillColor = nil
progressLayer.strokeColor = tintColor.CGColor
percentageLabel.textColor = tintColor
}
}
@@ -1,391 +0,0 @@
//
// M13ProgressSegmentedRing.swift
// M13ProgressSuite
//
/*
Copyright (c) 2015 Brandon McQuilkin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import UIKit
/**
The segment boundary types.
- Wedge:
- Rectangle:
*/
public enum M13ProgressViewSegmentedRingSegmentBoundaryType: Int, RawRepresentable {
///
case Wedge
///
case Rectangle
}
/**
Progress is shown by a ring split up into segments.
*/
@IBDesignable
public class M13ProgressSegmentedRing: M13ProgressRing {
//-------------------------------
// MARK: Properties
//-------------------------------
/**
The number of segments to display in the progress view.
*/
@IBInspectable public var numberOfSegments: Int = 10
/**
The angle of the separation between the segments in radians.
*/
@IBInspectable public var segmentSeparationAngle :CGFloat = 0.1
/**
The type of boundary between segments.
*/
@IBInspectable public var segmentBoundaryType: M13ProgressViewSegmentedRingSegmentBoundaryType = .Wedge {
didSet {
updateAngles()
progressUpdate?()
}
}
//-------------------------------
// MARK: Property Overrides
//-------------------------------
/**
The secondary color of the progress view.
*/
override public var secondaryColor: UIColor {
didSet {
indeterminateLayer.strokeColor = nil
indeterminateLayer.fillColor = secondaryColor.CGColor
}
}
//-------------------------------
// MARK: Protected Variables
//-------------------------------
// The calculated angles of the concentric rings
internal var outerRingAngle :CGFloat = 0.1
internal var innerRingAngle :CGFloat = 0.1
internal var segmentSeparationInnerAngle :CGFloat = 0.1
//-------------------------------
// MARK: Initalization
//-------------------------------
override public init() {
super.init()
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
if aDecoder.containsValueForKey("numberOfSegments") {
numberOfSegments = aDecoder.decodeIntegerForKey("numberOfSegments")
}
if aDecoder.containsValueForKey("segmentSeparationAngle") {
segmentSeparationAngle = CGFloat(aDecoder.decodeDoubleForKey("segmentSeparationAngle"))
}
if aDecoder.containsValueForKey("segmentBoundaryType") {
if let aSegmentBoundaryType = M13ProgressViewSegmentedRingSegmentBoundaryType(rawValue: aDecoder.decodeIntegerForKey("segmentBoundaryType")) {
segmentBoundaryType = aSegmentBoundaryType
}
}
super.init(coder: aDecoder)
sharedSetup()
}
override public init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
internal override func sharedSetup() {
super.sharedSetup()
// Set the defaults.
self.clipsToBounds = false
layer.backgroundColor = UIColor.clearColor().CGColor
// Set up the indeterminate layer
indeterminateLayer.strokeColor = nil
indeterminateLayer.fillColor = secondaryColor.CGColor
// Set up the progress layer
progressLayer.strokeColor = nil
progressLayer.fillColor = tintColor.CGColor
adjustProgressRingWidth()
// Set the progress animation.
weak var weakSelf: M13ProgressSegmentedRing? = self
progressUpdate = {() -> Void in
if let retainedSelf = weakSelf {
// Draw background
retainedSelf.drawSegmentedBackground()
// Draw progress ring
retainedSelf.drawSegmentedProgress()
// Draw percentage
if retainedSelf.percentage && retainedSelf.state == .Normal {
retainedSelf.drawPercentage()
}
}
}
// Set the indeterminate animation.
indeterminateUpdate = {(frameDuration: CFTimeInterval) -> Void in
if let retainedSelf = weakSelf {
retainedSelf.hidePercentage()
// Create parameters to draw progress
let startAngle = CGFloat(retainedSelf.indeterminateAnimationAngle)
let deltaAngle = CGFloat(frameDuration * M_PI)
if retainedSelf.progressDirection == .CounterClockwise {
// CounterClockwise
retainedSelf.indeterminateAnimationAngle -= deltaAngle
} else {
// Clockwise
retainedSelf.indeterminateAnimationAngle += deltaAngle
}
// Draw animated background
retainedSelf.drawSegmentedIndeterminate(startAngle, segmentsToDraw: retainedSelf.numberOfSegments)
}
}
}
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeInteger(numberOfSegments, forKey: "numberOfSegments")
aCoder.encodeDouble(Double(segmentSeparationAngle), forKey: "segmentSeparationAngle")
aCoder.encodeInteger(segmentBoundaryType.rawValue, forKey: "segmentBoundaryType")
super.encodeWithCoder(aCoder)
}
//-------------------------------
// MARK: Actions
//-------------------------------
public override func setState(state: M13ProgressViewState, animated: Bool) {
super.setState(state, animated: animated)
// Remove strokeColor animations and assignments that were added during super.setState()
progressLayer.removeAnimationForKey("strokeColor")
progressLayer.strokeColor = nil
indeterminateLayer.removeAnimationForKey("strokeColor")
indeterminateLayer.strokeColor = nil
// Select colors based on state
var toColor1: UIColor = tintColor
var toColor2: UIColor = secondaryColor
switch state {
case .Normal:
break
case .Success:
toColor1 = successColor
if indeterminate {
toColor2 = successColor
}
break
case .Failure:
toColor1 = failureColor
if indeterminate {
toColor2 = failureColor
}
break
}
if !animated {
progressLayer.fillColor = toColor1.CGColor
indeterminateLayer.fillColor = toColor2.CGColor
} else {
let colorAnimation1: CABasicAnimation = CABasicAnimation(keyPath: "fillColor")
colorAnimation1.fromValue = progressLayer.backgroundColor!
colorAnimation1.fillMode = kCAFillModeForwards
colorAnimation1.removedOnCompletion = false
colorAnimation1.duration = animationDuration
let colorAnimation2: CABasicAnimation = CABasicAnimation(keyPath: "fillColor")
colorAnimation2.fromValue = indeterminateLayer.backgroundColor!
colorAnimation2.fillMode = kCAFillModeForwards
colorAnimation2.removedOnCompletion = false
colorAnimation2.duration = animationDuration
colorAnimation1.toValue = toColor1.CGColor
progressLayer.addAnimation(colorAnimation1, forKey: "fillColor")
progressLayer.fillColor = toColor1.CGColor
colorAnimation2.toValue = toColor2.CGColor
indeterminateLayer.addAnimation(colorAnimation2, forKey: "fillColor")
indeterminateLayer.fillColor = toColor2.CGColor
}
setNeedsLayout()
progressUpdate?()
}
//-------------------------------
// MARK: Layout
//-------------------------------
public override func layoutSubviews() {
super.layoutSubviews()
updateAngles()
// Update progress frame
progressUpdate?()
}
internal func updateAngles() {
// Calculate the outer ring angle for the progress segment.
outerRingAngle = CGFloat(2.0 * M_PI) / CGFloat(numberOfSegments) - segmentSeparationAngle
// Calculate the angle gap for the inner ring
let radius = maxRadius()
segmentSeparationInnerAngle = 2.0 * asin((radius * sin(segmentSeparationAngle / 2.0)) / (radius - CGFloat(progressRingWidth)))
// Calculate the inner ring angle for the progress segment.
innerRingAngle = CGFloat(2.0 * M_PI) / CGFloat(numberOfSegments) - segmentSeparationInnerAngle
}
public func numberOfFullSegments() -> Int
{
return Int(floor(progress * CGFloat(numberOfSegments)))
}
//-------------------------------
// MARK: Draw Functions
//-------------------------------
public func drawSegmentedIndeterminate(startAngle: CGFloat, segmentsToDraw: Int)
{
// Create parameters to draw background
// The background segments are drawn counterclockwise, start with the outer ring, add an arc counterclockwise. Then add the coresponding arc for the inner ring clockwise. Then close the path. The line connecting the two arcs is not needed. From tests it seems to be created automatically.
var outerStartAngle = CGFloat(-M_PI_2) + startAngle
// Skip half of a separation angle, since the first separation will be centered upward.
outerStartAngle -= segmentSeparationAngle / 2.0
// Calculate the inner start angle position
var innerStartAngle = CGFloat(-M_PI_2) + startAngle
innerStartAngle -= segmentSeparationInnerAngle / 2.0 + innerRingAngle
// Create the path ref that all the paths will be appended
let pathListRef = CGPathCreateMutable()
// Create each segment
let center = centerOfCircle()
let radius = maxRadius()
let radiusInner = radius - CGFloat(progressRingWidth)
for (var i = 0; i < segmentsToDraw; ++i) {
// Create the outer ring segment
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: outerStartAngle, endAngle: (outerStartAngle - outerRingAngle), clockwise: false)
// Create the inner ring segment
if (segmentBoundaryType == .Wedge) {
path.addArcWithCenter(center, radius: radiusInner, startAngle: (outerStartAngle - outerRingAngle), endAngle: outerStartAngle, clockwise: true)
} else if (segmentBoundaryType == .Rectangle) {
path.addArcWithCenter(center, radius: radiusInner, startAngle: innerStartAngle, endAngle: (innerStartAngle + innerRingAngle), clockwise: true)
}
path.closePath()
// Add the segment to the path ref
CGPathAddPath(pathListRef, nil, path.CGPath)
// Setup for the next segment
outerStartAngle -= outerRingAngle + segmentSeparationAngle
innerStartAngle -= innerRingAngle + segmentSeparationInnerAngle
}
// Set the path
indeterminateLayer.path = pathListRef
indeterminateLayer.transform = getTransformation()
}
public func drawSegmentedBackground()
{
let segmentsToDraw = numberOfSegments - numberOfFullSegments()
drawSegmentedIndeterminate(0, segmentsToDraw: segmentsToDraw)
}
public func drawSegmentedProgress()
{
// Create parameters to draw background
// The progress segments are drawn clockwise, start with the outer ring, add an arc clockwise. Then add the coresponding arc for the inner ring counterclockwise. Then close the path. The line connecting the two arcs is not needed. From tests it seems to be created automatically.
var outerStartAngle = CGFloat(-M_PI_2)
// Skip half of a separation angle, since the first separation will be centered upward.
outerStartAngle += segmentSeparationAngle / 2.0
// Calculate the inner start angle position
var innerStartAngle = CGFloat(-M_PI_2)
innerStartAngle += segmentSeparationInnerAngle / 2.0 + innerRingAngle
// Create the path ref that all the paths will be appended
let pathListRef = CGPathCreateMutable()
// Create each segment
let center = centerOfCircle()
let radius = maxRadius()
let radiusInner = radius - CGFloat(progressRingWidth)
let stopper = numberOfFullSegments()
for (var i = 0; i < stopper; ++i) {
// Create the outer ring segment
let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: outerStartAngle, endAngle: (outerStartAngle + outerRingAngle), clockwise: true)
// Create the inner ring segment
if (segmentBoundaryType == .Wedge) {
path.addArcWithCenter(center, radius: radiusInner, startAngle: (outerStartAngle + outerRingAngle), endAngle: outerStartAngle, clockwise: false)
} else if (segmentBoundaryType == .Rectangle) {
path.addArcWithCenter(center, radius: radiusInner, startAngle: innerStartAngle, endAngle: (innerStartAngle - innerRingAngle), clockwise: false)
}
path.closePath()
// Add the segment to the path ref
CGPathAddPath(pathListRef, nil, path.CGPath)
// Setup for the next segment
outerStartAngle += outerRingAngle + segmentSeparationAngle
innerStartAngle += innerRingAngle + segmentSeparationInnerAngle
}
// Set the path
progressLayer.path = pathListRef
progressLayer.transform = getTransformation()
}
public func getTransformation() -> CATransform3D
{
if progressDirection == .CounterClockwise {
let rotation = CATransform3DMakeRotation(CGFloat(M_PI), 0.0, 1.0, 0.0)
let x = self.bounds.size.width
let translation = CATransform3DMakeTranslation(x, 0, 0)
return CATransform3DConcat(rotation, translation)
}
return CATransform3DIdentity
}
//-------------------------------
// MARK: Other
//-------------------------------
public override func tintColorDidChange() {
super.tintColorDidChange()
progressLayer.fillColor = tintColor.CGColor
progressLayer.strokeColor = nil
}
}
@@ -1,295 +0,0 @@
//
// M13ProgressView.swift
// M13ProgressSuite
//
/*
Copyright (c) 2015 Brandon McQuilkin
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import UIKit
/**
The possible states a progress view can be in.
- None: The default state of a progress bar.
- Success: The state that shows an action completed successfully.
- Failure: The state that shows an action failed to complete.
*/
public enum M13ProgressViewState: Int, RawRepresentable {
/// The default state of a progress bar.
case Normal
/// The state that shows an action completed successfully.
case Success
/// The state that shows an action failed to complete.
case Failure
}
/**
A standardized base upon which to build progress views.
*/
@IBDesignable
public class M13ProgressView: UIView {
//-------------------------------
// MARK: Appearance
//-------------------------------
/**
The secondary color of the progress view.
*/
@IBInspectable public var secondaryColor: UIColor = UIColor.lightGrayColor()
/**
The primary color when the progress view is in the success state.
*/
@IBInspectable public var successColor: UIColor = UIColor(red: 63.0/255.0, green: 226.0/255.0, blue: 80.0/255.0, alpha: 1.0)
/**
The primary color when the progress view is in the failure state.
*/
@IBInspectable public var failureColor: UIColor = UIColor(red: 249.0/255.0, green: 37.0/255.0, blue: 0.0, alpha: 1.0)
//-------------------------------
// MARK: Properties
//-------------------------------
/**
Wether or not the progress view is in an indeterminate state.
*/
@IBInspectable public var indeterminate: Bool = false {
didSet {
if indeterminate && indeterminateDisplayLink == nil {
// Create the display link
indeterminateDisplayLink = CADisplayLink(target: self, selector: "animateIndeterminate:")
indeterminateDisplayLink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
} else if !indeterminate && indeterminateDisplayLink != nil {
// Remove the display link as the animation is not needed anymore.
indeterminateDisplayLink?.invalidate()
indeterminateDisplayLink = nil
}
}
}
/**
The duration of the animations performed by the progress view in seconds.
*/
@IBInspectable public var animationDuration: NSTimeInterval = 0.3
/**
The duration of the indeterminate animation loop in seconds.
*/
@IBInspectable public var indeterminateAnimationDuration: NSTimeInterval = 2.0
/**
The progress displayed by the progress view.
*/
@IBInspectable public private(set) var progress: CGFloat = 0.0
/**
The current state of the progress view
*/
@IBInspectable public private(set) var state: M13ProgressViewState = M13ProgressViewState.Normal
//-------------------------------
// MARK: Animation
//-------------------------------
/**
The progress at the beginning of the animation.
*/
private var progressFromValue: CGFloat = 0.0
/**
The progress at the end of the animation.
*/
private var progressToValue: CGFloat = 0.0
/**
The start time of the animation.
*/
private var animationStartTime: CFTimeInterval?
/**
The display link controlling progress animations.
*/
private var determinateDisplayLink: CADisplayLink?
/**
The display link controlling indeterminate animations.
*/
private var indeterminateDisplayLink: CADisplayLink?
/**
The block of code that updates the user interface when the progress is set, animated or not. The changes made should reflect the current value of the progress variable.
- note: If capturing variable that is linked to `self`, be sure to do a "weak self" conversion.
*/
internal var progressUpdate: (() -> Void)?
/**
The block of code that update the user interface during the indeterminate state. This code is tied into a CADisplayLink that will run this code each frame.
- note: If capturing variable that is linked to `self`, be sure to do a "weak self" conversion.
*/
internal var indeterminateUpdate: ((frameDuration: CFTimeInterval) -> Void)?
//-------------------------------
// MARK: Initalization
//-------------------------------
public init() {
super.init(frame: CGRectZero)
}
required public init?(coder aDecoder: NSCoder) {
if aDecoder.containsValueForKey("indeterminate") {
indeterminate = aDecoder.decodeBoolForKey("indeterminate")
}
if aDecoder.containsValueForKey("animationDuration") {
animationDuration = aDecoder.decodeDoubleForKey("animationDuration")
}
if aDecoder.containsValueForKey("progress") {
progress = CGFloat(aDecoder.decodeFloatForKey("progress"))
}
if aDecoder.containsValueForKey("state") {
if let aState = M13ProgressViewState(rawValue: aDecoder.decodeIntegerForKey("state")) {
state = aState
}
}
if let color: UIColor = aDecoder.decodeObjectOfClass(UIColor.self, forKey: "secondaryColor") {
secondaryColor = color
}
if let color: UIColor = aDecoder.decodeObjectOfClass(UIColor.self, forKey: "successColor") {
successColor = color
}
if let color: UIColor = aDecoder.decodeObjectOfClass(UIColor.self, forKey: "failureColor") {
failureColor = color
}
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
public override func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(secondaryColor, forKey: "secondaryColor")
aCoder.encodeObject(successColor, forKey: "successColor")
aCoder.encodeObject(failureColor, forKey: "failureColor")
aCoder.encodeBool(indeterminate, forKey: "indeterminate")
aCoder.encodeDouble(animationDuration, forKey: "animationDuration")
aCoder.encodeFloat(Float(progress), forKey: "progress")
aCoder.encodeInteger(state.rawValue, forKey: "state")
super.encodeWithCoder(aCoder)
}
//-------------------------------
// MARK: Actions
//-------------------------------
/**
Set the progress displayed in the progress view.
- parameter progress: The progress to be displayed by the progress view.
- parameter animated: Wether or not to animate the change.
*/
public func setProgress(progress: CGFloat, animated: Bool) {
if animated == false {
// Remove the display link as the animation is not needed anymore.
determinateDisplayLink?.invalidate()
determinateDisplayLink = nil
animationStartTime = nil
// Update the progress
self.progress = progress
progressUpdate?()
} else {
// If the display link does not exist, create it.
if determinateDisplayLink == nil {
determinateDisplayLink = CADisplayLink(target: self, selector: "animateProgress:")
determinateDisplayLink?.addToRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
}
// Update the values for the animation.
progressFromValue = self.progress
progressToValue = progress > 1.0 ? 1.0 : progress
}
}
/**
Updates the progress in sync with the `CADisplayLink`, such that any changes are animated.
- parameter displayLink: The display link that is asking to calculate changes before the next render cycle.
*/
internal func animateProgress(displayLink: CADisplayLink) {
// Set the animation start time on the first displayed frame. The timestamp will read 0.0 until the first frame.
if animationStartTime == nil {
animationStartTime = displayLink.timestamp
return
}
weak var weakSelf: M13ProgressView? = self
dispatch_async(dispatch_get_main_queue()) { () -> Void in
if let weakSelf = weakSelf {
let dt: Double = (weakSelf.determinateDisplayLink!.timestamp - weakSelf.animationStartTime!) / weakSelf.animationDuration
if dt >= 1.0 {
// The animation is complete.
// Order is important! Otherwise concurrency will cause errors, because setProgress: will detect an animation in progress and try to stop it by itself. Once over one, set to actual progress amount. Animation is over.
weakSelf.determinateDisplayLink?.invalidate()
weakSelf.determinateDisplayLink = nil
weakSelf.setProgress(weakSelf.progressToValue, animated: false)
} else {
//Update the progress and the display
weakSelf.progress = weakSelf.progressFromValue + (CGFloat(dt) * (weakSelf.progressToValue - weakSelf.progressFromValue))
weakSelf.progressUpdate?()
}
}
}
}
/**
Updates the indeterminate animation in sync with the `CADisplayLink`, such that any changes are animated.
- parameter displayLink: The display link that is asking to calculate changes before the next render cycle.
*/
internal func animateIndeterminate(displayLink: CADisplayLink) {
weak var weakSelf: M13ProgressView? = self
dispatch_async(dispatch_get_main_queue()) { () -> Void in
weakSelf?.indeterminateUpdate?(frameDuration: displayLink.duration)
}
}
/**
Perform the given action.
- note: Not all progress views support all actions.
- seealso: `M13ProgressViewState`
- parameter action: The action to perform.
- parameter animated: Wether or not to animate the change.
*/
public func setState(state: M13ProgressViewState, animated: Bool) {
self.state = state
}
//-------------------------------
// MARK: Layout and Drawing
//-------------------------------
public override func layoutSubviews() {
super.layoutSubviews()
// Just update the progress in case it is not currently animating. The indeterminate animation will update on the next frame.
progressUpdate?()
}
}
-52
View File
@@ -1,52 +0,0 @@
New Progress Views
==================
Gradient Progress Views
-----------------------
A gradient along the direction of progress.
- Option to show 100% of the gradient range, or cut off the gradient to only the visible progress percentage. (If that makes any sense.)
- Add as a subclass of each progress view class?
Bordered Segmented Progress Views
---------------------------------
Bordered segmented progress views (Each segment has its own outline)
Size Based Segmented Progress Views
-----------------------------------
Size based segmented progress view that increases the size of the segments as progress increases.
Image Sequence
--------------
Maps progress information to images in an array.
- Accepts an array of UIImages for determinate, indeterminate, animating between determinate and indeterminate, success (and animating to/from), and failure (and animating to/from.)
- Accepts gif file paths?
- Accepts asset image sequence name?
- Accepts an array of arrays of UIImages, such that each progress amount is also animated?
Custom Path Progress "Bar"
------------------------
Takes a custom path and animates the stroke of the path to denote progress.
- Possibly animate between paths for different states.
Liquid
------
Fills a shape with liquid
- Add dynamics based on device tilt?
Text
----
Animates text to show progress.
- Fill
- Stroke
- Size?
Features
--------
- Switch the primary color to a function that could change the primary color based on the percentage completed? By default it would just return the tint color.
- Add more states like "warning", "error"
-37
View File
@@ -1,37 +0,0 @@
Pod::Spec.new do |s|
s.name = "M13ProgressSuite"
s.version = "2.0.0"
s.summary = "A suite containing many tools to display progress information on iOS."
s.description = <<-DESC
M13ProgressSuite includes many diffrent of styles of progress views: bar, ring, pie, etc. It also includes a HUD overlay and a UINavigationController with progress bar built in.
DESC
s.homepage = "https://github.com/Marxon13/M13ProgressSuite"
s.license = {:type => 'MIT',
:text => <<-LICENSE
Copyright (c) 2015 Brandon McQuilkin
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.
LICENSE
}
s.author = { "Brandon McQuilkin" => "brandon.mcquilkin@gmail.com" }
s.platform = :ios, '8.0'
s.source = { :git => "https://github.com/Marxon13/M13ProgressSuite.git", :tag => "v2.0.0"}
s.source_files = 'Classes/**/*'
s.frameworks = 'Foundation', 'UIKit', 'QuartzCore', 'CoreImage', 'Accelerate', 'CoreGraphics'
s.requires_arc = true
end
+138 -231
View File
@@ -7,65 +7,27 @@
objects = {
/* Begin PBXBuildFile section */
EA9045701C0649AF006C692A /* M13HUDController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9045651C0649AF006C692A /* M13HUDController.swift */; };
EA9045711C0649AF006C692A /* M13BorderedProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9045671C0649AF006C692A /* M13BorderedProgressBar.swift */; };
EA9045721C0649AF006C692A /* M13ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9045681C0649AF006C692A /* M13ProgressBar.swift */; };
EA9045731C0649AF006C692A /* M13ProgressCircular.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA9045691C0649AF006C692A /* M13ProgressCircular.swift */; };
EA9045741C0649AF006C692A /* M13ProgressFilteredImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA90456A1C0649AF006C692A /* M13ProgressFilteredImage.swift */; };
EA9045751C0649AF006C692A /* M13ProgressImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA90456B1C0649AF006C692A /* M13ProgressImage.swift */; };
EA9045761C0649AF006C692A /* M13ProgressPie.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA90456C1C0649AF006C692A /* M13ProgressPie.swift */; };
EA9045771C0649AF006C692A /* M13ProgressRing.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA90456D1C0649AF006C692A /* M13ProgressRing.swift */; };
EA9045781C0649AF006C692A /* M13ProgressSegmentedRing.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA90456E1C0649AF006C692A /* M13ProgressSegmentedRing.swift */; };
EA9045791C0649AF006C692A /* M13ProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA90456F1C0649AF006C692A /* M13ProgressView.swift */; };
EA90457F1C065733006C692A /* Examples.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EA90457E1C065733006C692A /* Examples.storyboard */; };
EABA2F6A1C08B25C006FA498 /* BorderedBarExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABA2F691C08B25C006FA498 /* BorderedBarExampleViewController.swift */; };
EABA2F6C1C08B44C006FA498 /* RingExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABA2F6B1C08B44C006FA498 /* RingExampleViewController.swift */; };
EABA2F6E1C08B9EE006FA498 /* SegmentedRingExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABA2F6D1C08B9EE006FA498 /* SegmentedRingExampleViewController.swift */; };
EABA2F701C08BD02006FA498 /* PieExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABA2F6F1C08BD02006FA498 /* PieExampleViewController.swift */; };
EABA2F721C09F651006FA498 /* GreyscaleImageExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABA2F711C09F651006FA498 /* GreyscaleImageExampleViewController.swift */; };
EABA2F741C09FA1E006FA498 /* FilteredImageExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABA2F731C09FA1E006FA498 /* FilteredImageExampleViewController.swift */; };
EADD11311C06A2F4001862B2 /* BaseExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EADD11301C06A2F4001862B2 /* BaseExampleViewController.swift */; };
EADD11331C06AEFA001862B2 /* BarExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EADD11321C06AEFA001862B2 /* BarExampleViewController.swift */; };
EAF117331C0647D0003616CD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF117321C0647D0003616CD /* AppDelegate.swift */; };
EAF117351C0647D0003616CD /* MasterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF117341C0647D0003616CD /* MasterViewController.swift */; };
EAF117371C0647D0003616CD /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAF117361C0647D0003616CD /* DetailViewController.swift */; };
EAF1173A1C0647D0003616CD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EAF117381C0647D0003616CD /* Main.storyboard */; };
EAF1173C1C0647D0003616CD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EAF1173B1C0647D0003616CD /* Assets.xcassets */; };
EAF1173F1C0647D0003616CD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EAF1173D1C0647D0003616CD /* LaunchScreen.storyboard */; };
43E4A70D1D58E77100030A4F /* M13ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E4A70C1D58E77100030A4F /* M13ProgressBar.swift */; };
43E4A70F1D58ECAE00030A4F /* M13ProgressViewBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E4A70E1D58ECAE00030A4F /* M13ProgressViewBase.swift */; };
EAC2CA591D578B5D0007D30D /* M13ProgressSuite.h in Headers */ = {isa = PBXBuildFile; fileRef = EAC2CA571D578B5D0007D30D /* M13ProgressSuite.h */; settings = {ATTRIBUTES = (Public, ); }; };
EAC2CA611D578BFA0007D30D /* M13ProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC2CA601D578BFA0007D30D /* M13ProgressView.swift */; };
EAC2CA631D578C330007D30D /* M13ProgressState.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC2CA621D578C330007D30D /* M13ProgressState.swift */; };
EAC2CA661D57BA140007D30D /* M13ProgressType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC2CA651D57BA140007D30D /* M13ProgressType.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
EA9045651C0649AF006C692A /* M13HUDController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13HUDController.swift; sourceTree = "<group>"; };
EA9045671C0649AF006C692A /* M13BorderedProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13BorderedProgressBar.swift; sourceTree = "<group>"; };
EA9045681C0649AF006C692A /* M13ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13ProgressBar.swift; sourceTree = "<group>"; };
EA9045691C0649AF006C692A /* M13ProgressCircular.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13ProgressCircular.swift; sourceTree = "<group>"; };
EA90456A1C0649AF006C692A /* M13ProgressFilteredImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13ProgressFilteredImage.swift; sourceTree = "<group>"; };
EA90456B1C0649AF006C692A /* M13ProgressImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13ProgressImage.swift; sourceTree = "<group>"; };
EA90456C1C0649AF006C692A /* M13ProgressPie.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13ProgressPie.swift; sourceTree = "<group>"; };
EA90456D1C0649AF006C692A /* M13ProgressRing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13ProgressRing.swift; sourceTree = "<group>"; };
EA90456E1C0649AF006C692A /* M13ProgressSegmentedRing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13ProgressSegmentedRing.swift; sourceTree = "<group>"; };
EA90456F1C0649AF006C692A /* M13ProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = M13ProgressView.swift; sourceTree = "<group>"; };
EA90457E1C065733006C692A /* Examples.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Examples.storyboard; sourceTree = "<group>"; };
EABA2F691C08B25C006FA498 /* BorderedBarExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BorderedBarExampleViewController.swift; sourceTree = "<group>"; };
EABA2F6B1C08B44C006FA498 /* RingExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RingExampleViewController.swift; sourceTree = "<group>"; };
EABA2F6D1C08B9EE006FA498 /* SegmentedRingExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedRingExampleViewController.swift; sourceTree = "<group>"; };
EABA2F6F1C08BD02006FA498 /* PieExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PieExampleViewController.swift; sourceTree = "<group>"; };
EABA2F711C09F651006FA498 /* GreyscaleImageExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GreyscaleImageExampleViewController.swift; sourceTree = "<group>"; };
EABA2F731C09FA1E006FA498 /* FilteredImageExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilteredImageExampleViewController.swift; sourceTree = "<group>"; };
EADD11301C06A2F4001862B2 /* BaseExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BaseExampleViewController.swift; path = Examples/BaseExampleViewController.swift; sourceTree = "<group>"; };
EADD11321C06AEFA001862B2 /* BarExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarExampleViewController.swift; sourceTree = "<group>"; };
EAF1172F1C0647D0003616CD /* M13ProgressSuite.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = M13ProgressSuite.app; sourceTree = BUILT_PRODUCTS_DIR; };
EAF117321C0647D0003616CD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
EAF117341C0647D0003616CD /* MasterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasterViewController.swift; sourceTree = "<group>"; };
EAF117361C0647D0003616CD /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = "<group>"; };
EAF117391C0647D0003616CD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
EAF1173B1C0647D0003616CD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
EAF1173E1C0647D0003616CD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
EAF117401C0647D0003616CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
43E4A70C1D58E77100030A4F /* M13ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = M13ProgressBar.swift; path = Sources/M13ProgressBar.swift; sourceTree = "<group>"; };
43E4A70E1D58ECAE00030A4F /* M13ProgressViewBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = M13ProgressViewBase.swift; path = Sources/M13ProgressViewBase.swift; sourceTree = "<group>"; };
EAC2CA541D578B5D0007D30D /* M13ProgressSuite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = M13ProgressSuite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
EAC2CA571D578B5D0007D30D /* M13ProgressSuite.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = M13ProgressSuite.h; sourceTree = "<group>"; };
EAC2CA581D578B5D0007D30D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
EAC2CA601D578BFA0007D30D /* M13ProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = M13ProgressView.swift; path = Sources/M13ProgressView.swift; sourceTree = "<group>"; };
EAC2CA621D578C330007D30D /* M13ProgressState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = M13ProgressState.swift; path = Sources/M13ProgressState.swift; sourceTree = "<group>"; };
EAC2CA651D57BA140007D30D /* M13ProgressType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = M13ProgressType.swift; path = Sources/M13ProgressType.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
EAF1172C1C0647D0003616CD /* Frameworks */ = {
EAC2CA501D578B5D0007D30D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -75,129 +37,82 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
EA9045621C06499A006C692A /* Example App */ = {
43E4A70B1D58E75300030A4F /* Progress Views */ = {
isa = PBXGroup;
children = (
EA90457A1C0649C5006C692A /* Example Views */,
EAF117321C0647D0003616CD /* AppDelegate.swift */,
EAF117341C0647D0003616CD /* MasterViewController.swift */,
EAF117361C0647D0003616CD /* DetailViewController.swift */,
EAF117381C0647D0003616CD /* Main.storyboard */,
EA90457E1C065733006C692A /* Examples.storyboard */,
EAF1173B1C0647D0003616CD /* Assets.xcassets */,
EAF1173D1C0647D0003616CD /* LaunchScreen.storyboard */,
EAF117401C0647D0003616CD /* Info.plist */,
43E4A70C1D58E77100030A4F /* M13ProgressBar.swift */,
);
name = "Example App";
name = "Progress Views";
sourceTree = "<group>";
};
EA9045631C0649AF006C692A /* Classes */ = {
EAC2CA4A1D578B5D0007D30D = {
isa = PBXGroup;
children = (
EA9045641C0649AF006C692A /* HUD */,
EA9045661C0649AF006C692A /* Progress Views */,
);
path = Classes;
sourceTree = SOURCE_ROOT;
};
EA9045641C0649AF006C692A /* HUD */ = {
isa = PBXGroup;
children = (
EA9045651C0649AF006C692A /* M13HUDController.swift */,
);
path = HUD;
sourceTree = "<group>";
};
EA9045661C0649AF006C692A /* Progress Views */ = {
isa = PBXGroup;
children = (
EA90456F1C0649AF006C692A /* M13ProgressView.swift */,
EA90457B1C0651FD006C692A /* Bar */,
EA90457C1C065232006C692A /* Circular */,
EA90457D1C065258006C692A /* Image */,
);
path = "Progress Views";
sourceTree = "<group>";
};
EA90457A1C0649C5006C692A /* Example Views */ = {
isa = PBXGroup;
children = (
EADD11301C06A2F4001862B2 /* BaseExampleViewController.swift */,
EADD11321C06AEFA001862B2 /* BarExampleViewController.swift */,
EABA2F691C08B25C006FA498 /* BorderedBarExampleViewController.swift */,
EABA2F6B1C08B44C006FA498 /* RingExampleViewController.swift */,
EABA2F6D1C08B9EE006FA498 /* SegmentedRingExampleViewController.swift */,
EABA2F6F1C08BD02006FA498 /* PieExampleViewController.swift */,
EABA2F711C09F651006FA498 /* GreyscaleImageExampleViewController.swift */,
EABA2F731C09FA1E006FA498 /* FilteredImageExampleViewController.swift */,
);
name = "Example Views";
sourceTree = "<group>";
};
EA90457B1C0651FD006C692A /* Bar */ = {
isa = PBXGroup;
children = (
EA9045681C0649AF006C692A /* M13ProgressBar.swift */,
EA9045671C0649AF006C692A /* M13BorderedProgressBar.swift */,
);
name = Bar;
sourceTree = "<group>";
};
EA90457C1C065232006C692A /* Circular */ = {
isa = PBXGroup;
children = (
EA9045691C0649AF006C692A /* M13ProgressCircular.swift */,
EA90456C1C0649AF006C692A /* M13ProgressPie.swift */,
EA90456D1C0649AF006C692A /* M13ProgressRing.swift */,
EA90456E1C0649AF006C692A /* M13ProgressSegmentedRing.swift */,
);
name = Circular;
sourceTree = "<group>";
};
EA90457D1C065258006C692A /* Image */ = {
isa = PBXGroup;
children = (
EA90456A1C0649AF006C692A /* M13ProgressFilteredImage.swift */,
EA90456B1C0649AF006C692A /* M13ProgressImage.swift */,
);
name = Image;
sourceTree = "<group>";
};
EAF117261C0647D0003616CD = {
isa = PBXGroup;
children = (
EAF117311C0647D0003616CD /* M13ProgressSuite */,
EAF117301C0647D0003616CD /* Products */,
EAC2CA5F1D578BE70007D30D /* Sources */,
EAC2CA561D578B5D0007D30D /* M13ProgressSuite */,
EAC2CA551D578B5D0007D30D /* Products */,
);
sourceTree = "<group>";
};
EAF117301C0647D0003616CD /* Products */ = {
EAC2CA551D578B5D0007D30D /* Products */ = {
isa = PBXGroup;
children = (
EAF1172F1C0647D0003616CD /* M13ProgressSuite.app */,
EAC2CA541D578B5D0007D30D /* M13ProgressSuite.framework */,
);
name = Products;
sourceTree = "<group>";
};
EAF117311C0647D0003616CD /* M13ProgressSuite */ = {
EAC2CA561D578B5D0007D30D /* M13ProgressSuite */ = {
isa = PBXGroup;
children = (
EA9045631C0649AF006C692A /* Classes */,
EA9045621C06499A006C692A /* Example App */,
EAC2CA571D578B5D0007D30D /* M13ProgressSuite.h */,
EAC2CA581D578B5D0007D30D /* Info.plist */,
);
path = M13ProgressSuite;
sourceTree = "<group>";
};
EAC2CA5F1D578BE70007D30D /* Sources */ = {
isa = PBXGroup;
children = (
EAC2CA641D57B9E30007D30D /* Base */,
43E4A70B1D58E75300030A4F /* Progress Views */,
);
name = Sources;
sourceTree = "<group>";
};
EAC2CA641D57B9E30007D30D /* Base */ = {
isa = PBXGroup;
children = (
EAC2CA601D578BFA0007D30D /* M13ProgressView.swift */,
EAC2CA621D578C330007D30D /* M13ProgressState.swift */,
EAC2CA651D57BA140007D30D /* M13ProgressType.swift */,
43E4A70E1D58ECAE00030A4F /* M13ProgressViewBase.swift */,
);
name = Base;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
EAC2CA511D578B5D0007D30D /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
EAC2CA591D578B5D0007D30D /* M13ProgressSuite.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
EAF1172E1C0647D0003616CD /* M13ProgressSuite */ = {
EAC2CA531D578B5D0007D30D /* M13ProgressSuite */ = {
isa = PBXNativeTarget;
buildConfigurationList = EAF117431C0647D0003616CD /* Build configuration list for PBXNativeTarget "M13ProgressSuite" */;
buildConfigurationList = EAC2CA5C1D578B5D0007D30D /* Build configuration list for PBXNativeTarget "M13ProgressSuite" */;
buildPhases = (
EAF1172B1C0647D0003616CD /* Sources */,
EAF1172C1C0647D0003616CD /* Frameworks */,
EAF1172D1C0647D0003616CD /* Resources */,
EAC2CA4F1D578B5D0007D30D /* Sources */,
EAC2CA501D578B5D0007D30D /* Frameworks */,
EAC2CA511D578B5D0007D30D /* Headers */,
EAC2CA521D578B5D0007D30D /* Resources */,
);
buildRules = (
);
@@ -205,112 +120,74 @@
);
name = M13ProgressSuite;
productName = M13ProgressSuite;
productReference = EAF1172F1C0647D0003616CD /* M13ProgressSuite.app */;
productType = "com.apple.product-type.application";
productReference = EAC2CA541D578B5D0007D30D /* M13ProgressSuite.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
EAF117271C0647D0003616CD /* Project object */ = {
EAC2CA4B1D578B5D0007D30D /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0710;
LastUpgradeCheck = 0710;
ORGANIZATIONNAME = Marxon13;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = "Brandon McQuilkin";
TargetAttributes = {
EAF1172E1C0647D0003616CD = {
CreatedOnToolsVersion = 7.1.1;
EAC2CA531D578B5D0007D30D = {
CreatedOnToolsVersion = 8.0;
DevelopmentTeam = 3RCGQ2RRJJ;
LastSwiftMigration = 0800;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = EAF1172A1C0647D0003616CD /* Build configuration list for PBXProject "M13ProgressSuite" */;
buildConfigurationList = EAC2CA4E1D578B5D0007D30D /* Build configuration list for PBXProject "M13ProgressSuite" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = EAF117261C0647D0003616CD;
productRefGroup = EAF117301C0647D0003616CD /* Products */;
mainGroup = EAC2CA4A1D578B5D0007D30D;
productRefGroup = EAC2CA551D578B5D0007D30D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
EAF1172E1C0647D0003616CD /* M13ProgressSuite */,
EAC2CA531D578B5D0007D30D /* M13ProgressSuite */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
EAF1172D1C0647D0003616CD /* Resources */ = {
EAC2CA521D578B5D0007D30D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EAF1173F1C0647D0003616CD /* LaunchScreen.storyboard in Resources */,
EA90457F1C065733006C692A /* Examples.storyboard in Resources */,
EAF1173C1C0647D0003616CD /* Assets.xcassets in Resources */,
EAF1173A1C0647D0003616CD /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
EAF1172B1C0647D0003616CD /* Sources */ = {
EAC2CA4F1D578B5D0007D30D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EABA2F701C08BD02006FA498 /* PieExampleViewController.swift in Sources */,
EABA2F721C09F651006FA498 /* GreyscaleImageExampleViewController.swift in Sources */,
EA9045721C0649AF006C692A /* M13ProgressBar.swift in Sources */,
EA9045741C0649AF006C692A /* M13ProgressFilteredImage.swift in Sources */,
EAF117371C0647D0003616CD /* DetailViewController.swift in Sources */,
EA9045771C0649AF006C692A /* M13ProgressRing.swift in Sources */,
EA9045731C0649AF006C692A /* M13ProgressCircular.swift in Sources */,
EA9045711C0649AF006C692A /* M13BorderedProgressBar.swift in Sources */,
EA9045751C0649AF006C692A /* M13ProgressImage.swift in Sources */,
EA9045791C0649AF006C692A /* M13ProgressView.swift in Sources */,
EABA2F6E1C08B9EE006FA498 /* SegmentedRingExampleViewController.swift in Sources */,
EABA2F6A1C08B25C006FA498 /* BorderedBarExampleViewController.swift in Sources */,
EAF117351C0647D0003616CD /* MasterViewController.swift in Sources */,
EA9045761C0649AF006C692A /* M13ProgressPie.swift in Sources */,
EAF117331C0647D0003616CD /* AppDelegate.swift in Sources */,
EA9045701C0649AF006C692A /* M13HUDController.swift in Sources */,
EADD11331C06AEFA001862B2 /* BarExampleViewController.swift in Sources */,
EADD11311C06A2F4001862B2 /* BaseExampleViewController.swift in Sources */,
EABA2F6C1C08B44C006FA498 /* RingExampleViewController.swift in Sources */,
EABA2F741C09FA1E006FA498 /* FilteredImageExampleViewController.swift in Sources */,
EA9045781C0649AF006C692A /* M13ProgressSegmentedRing.swift in Sources */,
EAC2CA631D578C330007D30D /* M13ProgressState.swift in Sources */,
EAC2CA661D57BA140007D30D /* M13ProgressType.swift in Sources */,
43E4A70F1D58ECAE00030A4F /* M13ProgressViewBase.swift in Sources */,
43E4A70D1D58E77100030A4F /* M13ProgressBar.swift in Sources */,
EAC2CA611D578BFA0007D30D /* M13ProgressView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
EAF117381C0647D0003616CD /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
EAF117391C0647D0003616CD /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
EAF1173D1C0647D0003616CD /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
EAF1173E1C0647D0003616CD /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
EAF117411C0647D0003616CD /* Debug */ = {
EAC2CA5A1D578B5D0007D30D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -318,14 +195,18 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -343,19 +224,23 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
EAF117421C0647D0003616CD /* Release */ = {
EAC2CA5B1D578B5D0007D30D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -363,14 +248,18 @@
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -382,62 +271,80 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.1;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
EAF117441C0647D0003616CD /* Debug */ = {
EAC2CA5D1D578B5D0007D30D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 3RCGQ2RRJJ;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = M13ProgressSuite/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.marxon13.M13ProgressSuite;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.BrandonMcQuilkin.M13ProgressSuite;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
EAF117451C0647D0003616CD /* Release */ = {
EAC2CA5E1D578B5D0007D30D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 3RCGQ2RRJJ;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = M13ProgressSuite/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.marxon13.M13ProgressSuite;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.BrandonMcQuilkin.M13ProgressSuite;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
EAF1172A1C0647D0003616CD /* Build configuration list for PBXProject "M13ProgressSuite" */ = {
EAC2CA4E1D578B5D0007D30D /* Build configuration list for PBXProject "M13ProgressSuite" */ = {
isa = XCConfigurationList;
buildConfigurations = (
EAF117411C0647D0003616CD /* Debug */,
EAF117421C0647D0003616CD /* Release */,
EAC2CA5A1D578B5D0007D30D /* Debug */,
EAC2CA5B1D578B5D0007D30D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
EAF117431C0647D0003616CD /* Build configuration list for PBXNativeTarget "M13ProgressSuite" */ = {
EAC2CA5C1D578B5D0007D30D /* Build configuration list for PBXNativeTarget "M13ProgressSuite" */ = {
isa = XCConfigurationList;
buildConfigurations = (
EAF117441C0647D0003616CD /* Debug */,
EAF117451C0647D0003616CD /* Release */,
EAC2CA5D1D578B5D0007D30D /* Debug */,
EAC2CA5E1D578B5D0007D30D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = EAF117271C0647D0003616CD /* Project object */;
rootObject = EAC2CA4B1D578B5D0007D30D /* Project object */;
}
-61
View File
@@ -1,61 +0,0 @@
//
// AppDelegate.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/25/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let splitViewController = self.window!.rootViewController as! UISplitViewController
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
splitViewController.delegate = self
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
// MARK: - Split view
func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController:UIViewController, ontoPrimaryViewController primaryViewController:UIViewController) -> Bool {
guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }
guard let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController else { return false }
if topAsDetailController.detailViewController == nil {
// Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
return true
}
return false
}
}
@@ -1,68 +0,0 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -1,6 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -1,23 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "Striped_apple_logo.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "Striped_apple_logo-1.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "Striped_apple_logo-2.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

@@ -1,67 +0,0 @@
//
// BarExampleViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/25/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
class BarExampleViewController: BaseExampleViewController {
//-------------------------------
// MARK: Properties
//-------------------------------
/// The vertical progress bar.
@IBOutlet var verticalProgressBar: M13ProgressBar?
/// The horizontal progress bar.
@IBOutlet var horizontalProgressBar: M13ProgressBar?
override var progressViews: [M13ProgressView] {
if let verticalProgressBar = verticalProgressBar, horizontalProgressBar = horizontalProgressBar {
return [verticalProgressBar, horizontalProgressBar]
}
return []
}
//-------------------------------
// MARK: Initalization
//-------------------------------
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
verticalProgressBar?.progressDirection = .BottomToTop
}
//-------------------------------
// MARK: Actions
//-------------------------------
/**
Updates the corner radius of the progress views.
- parameter sender: The slider that updated its value.
*/
@IBAction func updateCornerRadius(sender: UISlider) {
horizontalProgressBar?.cornerRadius = CGFloat(sender.value)
verticalProgressBar?.cornerRadius = CGFloat(sender.value)
}
/**
Updates the direction of the progress views.
*/
@IBAction func updateProgressDirection(sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
horizontalProgressBar?.progressDirection = .LeadingToTrailing
verticalProgressBar?.progressDirection = .BottomToTop
} else if sender.selectedSegmentIndex == 1 {
horizontalProgressBar?.progressDirection = .TrailingToLeading
verticalProgressBar?.progressDirection = .TopToBottom
}
}
}
@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
-160
View File
@@ -1,160 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="H1p-Uh-vWS">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
<!--Master-->
<scene sceneID="pY4-Hu-kfo">
<objects>
<navigationController title="Master" id="RMx-3f-FxP" sceneMemberID="viewController">
<navigationBar key="navigationBar" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="Pmd-2v-anx">
<autoresizingMask key="autoresizingMask"/>
<animations/>
</navigationBar>
<connections>
<segue destination="7bK-jq-Zjz" kind="relationship" relationship="rootViewController" id="tsl-Nk-0bq"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8fS-aE-onr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-38" y="-630"/>
</scene>
<!--Detail-->
<scene sceneID="yUG-lL-AsK">
<objects>
<viewController title="Detail" id="JEX-9P-axG" customClass="DetailViewController" customModule="M13ProgressSuite" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="SYR-Wa-9uf"/>
<viewControllerLayoutGuide type="bottom" id="GAO-Cl-Wes"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="svH-Pt-448">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Select an Example" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Q3I-gn-7hF">
<rect key="frame" x="193" y="284" width="214.5" height="32.5"/>
<animations/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" bounces="NO" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" delaysContentTouches="NO" canCancelContentTouches="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Vrn-fU-KbN">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<animations/>
</scrollView>
</subviews>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="Vrn-fU-KbN" firstAttribute="leading" secondItem="svH-Pt-448" secondAttribute="leadingMargin" constant="-20" id="5MK-tF-sRx"/>
<constraint firstItem="Q3I-gn-7hF" firstAttribute="centerX" secondItem="svH-Pt-448" secondAttribute="centerX" id="E89-pa-1Nj"/>
<constraint firstItem="Vrn-fU-KbN" firstAttribute="leading" secondItem="svH-Pt-448" secondAttribute="leading" id="Hjb-Fk-zsC"/>
<constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="Q3I-gn-7hF" secondAttribute="trailing" constant="20" id="M5W-qA-gpV"/>
<constraint firstItem="GAO-Cl-Wes" firstAttribute="top" secondItem="Vrn-fU-KbN" secondAttribute="bottom" id="P0m-Ed-ymG"/>
<constraint firstItem="Q3I-gn-7hF" firstAttribute="centerY" secondItem="svH-Pt-448" secondAttribute="centerY" id="fqT-YV-TDr"/>
<constraint firstAttribute="trailing" secondItem="Vrn-fU-KbN" secondAttribute="trailing" id="gX0-Wk-Z8b"/>
<constraint firstAttribute="trailingMargin" secondItem="Vrn-fU-KbN" secondAttribute="trailing" constant="-20" id="p2i-kz-b78"/>
<constraint firstItem="Q3I-gn-7hF" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="svH-Pt-448" secondAttribute="leadingMargin" constant="20" id="sdY-8C-5jS"/>
<constraint firstItem="Vrn-fU-KbN" firstAttribute="top" secondItem="svH-Pt-448" secondAttribute="topMargin" id="vqs-tW-Yle"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="5MK-tF-sRx"/>
<exclude reference="p2i-kz-b78"/>
</mask>
</variation>
</view>
<toolbarItems/>
<navigationItem key="navigationItem" title="Example" id="mOI-FS-AaM"/>
<connections>
<outlet property="progressContentScrollView" destination="Vrn-fU-KbN" id="NIa-NU-bti"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="FJe-Yq-33r" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="709" y="129"/>
</scene>
<!--Split View Controller-->
<scene sceneID="Nki-YV-4Qg">
<objects>
<splitViewController id="H1p-Uh-vWS" sceneMemberID="viewController">
<toolbarItems/>
<connections>
<segue destination="RMx-3f-FxP" kind="relationship" relationship="masterViewController" id="BlO-5A-QYV"/>
<segue destination="vC3-pB-5Vb" kind="relationship" relationship="detailViewController" id="Tll-UG-LXB"/>
</connections>
</splitViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="cZU-Oi-B1e" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-856" y="-330"/>
</scene>
<!--Master-->
<scene sceneID="smW-Zh-WAh">
<objects>
<tableViewController title="Master" clearsSelectionOnViewWillAppear="NO" id="7bK-jq-Zjz" customClass="MasterViewController" customModule="M13ProgressSuite" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="r7i-6Z-zg0">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="calibratedRGB"/>
<prototypes>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="Cell" textLabel="Arm-wq-HPj" style="IBUITableViewCellStyleDefault" id="WCw-Qf-5nD">
<rect key="frame" x="0.0" y="113.5" width="600" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WCw-Qf-5nD" id="37f-cq-3Eg">
<rect key="frame" x="0.0" y="0.0" width="600" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Arm-wq-HPj">
<rect key="frame" x="15" y="0.0" width="570" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<color key="highlightedColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
</label>
</subviews>
<animations/>
</tableViewCellContentView>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<connections>
<segue destination="vC3-pB-5Vb" kind="showDetail" identifier="showDetail" id="6S0-TO-JiA"/>
</connections>
</tableViewCell>
</prototypes>
<sections/>
<connections>
<outlet property="dataSource" destination="7bK-jq-Zjz" id="Gho-Na-rnu"/>
<outlet property="delegate" destination="7bK-jq-Zjz" id="RA6-mI-bju"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Examples" id="Zdf-7t-Un8"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Rux-fX-hf1" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="709" y="-630"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="r7l-gg-dq7">
<objects>
<navigationController id="vC3-pB-5Vb" sceneMemberID="viewController">
<navigationBar key="navigationBar" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="DjV-YW-jjY">
<autoresizingMask key="autoresizingMask"/>
<animations/>
</navigationBar>
<connections>
<segue destination="JEX-9P-axG" kind="relationship" relationship="rootViewController" id="GKi-kA-LjT"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="SLD-UC-DBI" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-45" y="129"/>
</scene>
</scenes>
<inferredMetricsTieBreakers>
<segue reference="6S0-TO-JiA"/>
</inferredMetricsTieBreakers>
</document>
@@ -1,69 +0,0 @@
//
// BorderedBarExampleViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/27/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
class BorderedBarExampleViewController: BaseExampleViewController {
//-------------------------------
// MARK: Properties
//-------------------------------
/// The vertical progress bar.
@IBOutlet var verticalProgressBar: M13BorderedProgressBar?
/// The horizontal progress bar.
@IBOutlet var horizontalProgressBar: M13BorderedProgressBar?
override var progressViews: [M13ProgressView] {
if let verticalProgressBar = verticalProgressBar, horizontalProgressBar = horizontalProgressBar {
return [verticalProgressBar, horizontalProgressBar]
}
return []
}
//-------------------------------
// MARK: Initalization
//-------------------------------
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
verticalProgressBar?.progressDirection = .BottomToTop
}
//-------------------------------
// MARK: Actions
//-------------------------------
/**
Updates the corner radius of the progress views.
- parameter sender: The slider that updated its value.
*/
@IBAction func updateCornerRadius(sender: UISlider) {
horizontalProgressBar?.cornerRadius = CGFloat(sender.value)
verticalProgressBar?.cornerRadius = CGFloat(sender.value)
}
/**
Updates the direction of the progress views.
- parameter sender: The segmented control that updated its value.
*/
@IBAction func updateProgressDirection(sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
horizontalProgressBar?.progressDirection = .LeadingToTrailing
verticalProgressBar?.progressDirection = .BottomToTop
} else if sender.selectedSegmentIndex == 1 {
horizontalProgressBar?.progressDirection = .TrailingToLeading
verticalProgressBar?.progressDirection = .TopToBottom
}
}
}
@@ -1,69 +0,0 @@
//
// DetailViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/25/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
/// The view controller that presents the progress examples.
class DetailViewController: UIViewController {
//-----------------------------
// MARK: - Properties
//-----------------------------
/// The scroll view that will containt the progress view examples.
@IBOutlet weak var progressContentScrollView: UIScrollView?
/// The view that is currently displayed in the content scroll view.
var detailViewController: UIViewController? {
willSet {
detailViewController?.willMoveToParentViewController(nil)
detailViewController?.view.removeFromSuperview()
detailViewController?.removeFromParentViewController()
}
didSet {
configureView()
}
}
//-----------------------------
// MARK: - Configuration
//-----------------------------
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.configureView()
}
/// Sets up the autolayout constraints for the content view.
func configureView() {
// Add the view if necessary
if let detailViewController = detailViewController, let scrollView = progressContentScrollView where detailViewController.view.superview == nil {
addChildViewController(detailViewController)
detailViewController.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(detailViewController.view)
detailViewController.didMoveToParentViewController(self)
}
// Setup the constraints
if let detail = detailViewController?.view, let scrollView = progressContentScrollView {
// Create the constraints between the content view and the scroll view.
detail.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
detail.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
detail.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
detail.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
// Create the constraints between the content view and the main view.
detail.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
detail.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true
detail.bottomAnchor.constraintGreaterThanOrEqualToAnchor(view.bottomAnchor).active = true
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,171 +0,0 @@
//
// BaseExampleViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/25/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
/**
Runs the given closure after a delay.
- parameter delay: The amount of time in seconds before the closure is run.
- parameter closure: The closure to run after the delay.
*/
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
/// The base view controller for example view controllers.
class BaseExampleViewController: UIViewController {
//-------------------------------
// MARK: Properties
//-------------------------------
/// The button that will start a progress animation.
@IBOutlet var progressButton: UIButton?
/// The slider that allows the user to control the progress manually.
@IBOutlet var progressSlider: UISlider?
/// The switch that allows the user to switch the progress view between a determinate and indeterminate state.
@IBOutlet var indeterminateSwitch: UISwitch?
/// The segmented control that allows the user to switch between the different possible states.
@IBOutlet var stateControl: UISegmentedControl?
/// Returns the progress views controlled by the view controller.
var progressViews: [M13ProgressView] {
return []
}
//-------------------------------
// MARK: Initalization
//-------------------------------
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//-------------------------------
// MARK: Actions
//-------------------------------
/**
The action that will run the progress animation for the progress views. This should be overriden and `animateProgressForProgressViews:completion:` should be called.
- parameter sender: The button that called the action.
*/
@IBAction func beginProgressAnimation(sender: UIButton) {
animateProgress({})
}
/**
The action that will update the progress of the progress views.
- parameter sender: The slider whose value has changed.
*/
@IBAction func updateProgress(sender: UISlider) {
for progressView in progressViews {
progressView.setProgress(CGFloat(sender.value), animated: false)
}
}
/**
The action that will update the indeterminate state of the progress views.
- parameter sender: The switch whose value has changed.
*/
@IBAction func updateIndeterminate(sender: UISwitch) {
for progressView in progressViews {
progressView.indeterminate = sender.on
}
}
/**
The action that will update the state of the progress views.
- parameter sender: The switch whose value has changed.
*/
@IBAction func updateState(sender: UISegmentedControl) {
var state: M13ProgressViewState = .Normal
if sender.selectedSegmentIndex == 1 {
state = .Success
} else if sender.selectedSegmentIndex == 2 {
state = .Failure
}
for progressView in progressViews {
progressView.setState(state, animated: true)
}
}
//-------------------------------
// MARK: Animations
//-------------------------------
/**
Animates the progress of the progress views passed into the function. Once the animation completes, the completion block will be run.
- parameter completion: The block of code to run on completion.
- note: The completion block should be used to enable any controls that were disabled before the animation.
*/
func animateProgress(completion:()->()) {
// Disable controls for the duration of the animation.
progressButton?.enabled = false
progressSlider?.enabled = false
indeterminateSwitch?.enabled = false
stateControl?.enabled = false
// Set the initial progress to zero
for progressView in progressViews {
progressView.setProgress(0.0, animated: false)
}
// Weak self to prevent retain loop.
weak var weakSelf: BaseExampleViewController? = self
let shownProgressViews: [M13ProgressView] = progressViews
delay(1.0) { () -> () in
for progressView in shownProgressViews {
progressView.setProgress(0.3, animated: true)
}
delay(2.0, closure: { () -> () in
for progressView in shownProgressViews {
progressView.setProgress(0.5, animated: true)
}
delay(3.0, closure: { () -> () in
for progressView in shownProgressViews {
progressView.setProgress(1.0, animated: true)
}
if let aProgressView = shownProgressViews.first {
delay(aProgressView.animationDuration, closure: { () -> () in
for progressView in shownProgressViews {
progressView.setState(.Success, animated: true)
}
delay(2.0, closure: { () -> () in
if let retainedSelf = weakSelf {
for progressView in shownProgressViews {
progressView.setState(.Normal, animated: true)
progressView.setProgress(CGFloat(retainedSelf.progressSlider!.value), animated: true)
}
retainedSelf.progressButton?.enabled = true
retainedSelf.progressSlider?.enabled = true
retainedSelf.indeterminateSwitch?.enabled = true
retainedSelf.stateControl?.enabled = true
completion()
}
})
})
}
})
})
}
}
}
@@ -1,44 +0,0 @@
//
// FilteredImageExampleViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/28/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
class FilteredImageExampleViewController: BaseExampleViewController {
//-------------------------------
// MARK: Properties
//-------------------------------
/// The progress view.
@IBOutlet var filteredImageProgressView: M13ProgressFilteredImage?
/// The control that allows the user to select a filter.
@IBOutlet var filterControl: UISegmentedControl?
override var progressViews: [M13ProgressView] {
if let filteredImageProgressView = filteredImageProgressView {
return [filteredImageProgressView]
}
return []
}
//-------------------------------
// MARK: Actions
//-------------------------------
@IBAction func updateFilter(sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
filteredImageProgressView?.progressFilter = .Blur
} else if sender.selectedSegmentIndex == 1 {
filteredImageProgressView?.progressFilter = .LightTunnel
} else if sender.selectedSegmentIndex == 2 {
filteredImageProgressView?.progressFilter = .SepiaTone
}
}
}
@@ -1,57 +0,0 @@
//
// GreyscaleImageExampleViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/28/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
class GreyscaleImageExampleViewController: BaseExampleViewController {
//-------------------------------
// MARK: Properties
//-------------------------------
/// The progress view.
@IBOutlet var greyscaleImageProgressView: M13ProgressImage?
/// Changes the direction of the progress
@IBOutlet var directionControl: UISegmentedControl?
/// Shows the gresscale background
@IBOutlet var showBackgroundSwitch: UISwitch?
override var progressViews: [M13ProgressView] {
if let greyscaleImageProgressView = greyscaleImageProgressView {
return [greyscaleImageProgressView]
}
return []
}
//-------------------------------
// MARK: Actions
//-------------------------------
/**
Changes the direction progress travels in.
- parameter sender: The segmented control whose value has changed.
*/
@IBAction func updateDirection(sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
greyscaleImageProgressView?.progressDirection = .LeadingToTrailing
} else if sender.selectedSegmentIndex == 1 {
greyscaleImageProgressView?.progressDirection = .BottomToTop
} else if sender.selectedSegmentIndex == 2 {
greyscaleImageProgressView?.progressDirection = .TrailingToLeading
} else if sender.selectedSegmentIndex == 3 {
greyscaleImageProgressView?.progressDirection = .TopToBottom
}
}
@IBAction func updateBackgroundSwitch(sender: UISwitch) {
greyscaleImageProgressView?.drawGreyscaleBackground = sender.on
}
}
+5 -38
View File
@@ -13,45 +13,12 @@
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
+19
View File
@@ -0,0 +1,19 @@
//
// M13ProgressSuite.h
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 8/7/16.
// Copyright © 2016 Brandon McQuilkin. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for M13ProgressSuite.
FOUNDATION_EXPORT double M13ProgressSuiteVersionNumber;
//! Project version string for M13ProgressSuite.
FOUNDATION_EXPORT const unsigned char M13ProgressSuiteVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <M13ProgressSuite/PublicHeader.h>
-128
View File
@@ -1,128 +0,0 @@
//
// MasterViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/25/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
/// An object that represents an example that the user can display.
struct ProgressExample {
/// The title of the example.
let title: String
/// The identifier of the example view controller.
let viewControllerIdentifier: String
}
/// An object that represents a group of examples that the user can display.
struct ProgressExampleGroup {
/// The title of the group.
let title: String
/// The examples contained within the section.
let examples: [ProgressExample]
}
/// The view controller that presents the menu allowing one to select a progress example.
class MasterViewController: UITableViewController {
//-----------------------------
// MARK: - Properties
//-----------------------------
/// The currently presented detail view controller.
var detailViewController: DetailViewController? = nil
/// The list of possible examples.
var exampleGroups: [ProgressExampleGroup] = [
ProgressExampleGroup(title: "Progress Bars", examples: [
ProgressExample(title: "Basic Progress Bar", viewControllerIdentifier: "basicBarViewController"),
ProgressExample(title: "Bordered Progress Bar", viewControllerIdentifier: "borderedBarViewController")
]),
ProgressExampleGroup(title: "Circular Progress Indicators", examples: [
ProgressExample(title: "Pie", viewControllerIdentifier: "pieViewController"),
ProgressExample(title: "Ring", viewControllerIdentifier: "ringViewController"),
ProgressExample(title: "Segmented Ring", viewControllerIdentifier: "segmentedRingViewController")
]),
ProgressExampleGroup(title: "Image Based Progress Indicators", examples: [
ProgressExample(title: "Greyscale Image", viewControllerIdentifier: "greyscaleImageViewController"),
ProgressExample(title: "Filtered Image", viewControllerIdentifier: "filteredImageViewController")
])
]
var objects = [AnyObject]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
}
override func viewWillAppear(animated: Bool) {
self.clearsSelectionOnViewWillAppear = self.splitViewController!.collapsed
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func insertNewObject(sender: AnyObject) {
objects.insert(NSDate(), atIndex: 0)
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
// MARK: - Segues
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Segue to update the detail view controller.
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
// Get the example.
let example = exampleGroups[indexPath.section].examples[indexPath.row]
let exampleViewController = UIStoryboard(name: "Examples", bundle: nil).instantiateViewControllerWithIdentifier(example.viewControllerIdentifier)
// Set it to the detail controller.
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.detailViewController = exampleViewController
controller.title = example.title
// Update the navigation items.
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return exampleGroups.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return exampleGroups[section].examples.count
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return exampleGroups[section].title
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let example = exampleGroups[indexPath.section].examples[indexPath.row]
cell.textLabel!.text = example.title
return cell
}
}
@@ -1,56 +0,0 @@
//
// PieExampleViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/27/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
class PieExampleViewController: BaseExampleViewController {
//-------------------------------
// MARK: Properties
//-------------------------------
/// The progress view.
@IBOutlet var pieProgressView: M13ProgressPie?
/// The control to change the direction of the progress.
@IBOutlet var directionControl: UISegmentedControl?
override var progressViews: [M13ProgressView] {
if let pieProgressView = pieProgressView {
return [pieProgressView]
}
return []
}
//-------------------------------
// MARK: Initalization
//-------------------------------
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//-------------------------------
// MARK: Actions
//-------------------------------
/**
Changes the direction progress travels in.
- parameter sender: The segmented control whose value has changed.
*/
@IBAction func updateDirection(sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
pieProgressView?.progressDirection = .Clockwise
} else if sender.selectedSegmentIndex == 1 {
pieProgressView?.progressDirection = .CounterClockwise
}
}
}
@@ -1,67 +0,0 @@
//
// RingExampleViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/27/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
class RingExampleViewController: BaseExampleViewController {
//-------------------------------
// MARK: Properties
//-------------------------------
/// The progress view.
@IBOutlet var ringProgressView: M13ProgressRing?
/// The switch to control whether or not the percentage is shown.
@IBOutlet var showPercentageSwitch: UISwitch?
/// The control to change the direction of the progress.
@IBOutlet var directionControl: UISegmentedControl?
override var progressViews: [M13ProgressView] {
if let ringProgressView = ringProgressView {
return [ringProgressView]
}
return []
}
//-------------------------------
// MARK: Initalization
//-------------------------------
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//-------------------------------
// MARK: Actions
//-------------------------------
/**
Shows and hides the percentage label in the progress ring.
- parameter sender: The switch whose value has changed.
*/
@IBAction func updatePercentage(sender: UISwitch) {
ringProgressView?.percentage = sender.on
}
/**
Changes the direction progress travels in.
- parameter sender: The segmented control whose value has changed.
*/
@IBAction func updateDirection(sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
ringProgressView?.progressDirection = .Clockwise
} else if sender.selectedSegmentIndex == 1 {
ringProgressView?.progressDirection = .CounterClockwise
}
}
}
@@ -1,82 +0,0 @@
//
// SegmentedRingExampleViewController.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 11/27/15.
// Copyright © 2015 Marxon13. All rights reserved.
//
import UIKit
class SegmentedRingExampleViewController: BaseExampleViewController {
//-------------------------------
// MARK: Properties
//-------------------------------
/// The progress view.
@IBOutlet var segmentedRingProgressView: M13ProgressSegmentedRing?
/// The switch to control whether or not the percentage is shown.
@IBOutlet var showPercentageSwitch: UISwitch?
/// The control to control the segment shape
@IBOutlet var segmentBoundaryControl: UISegmentedControl?
/// The control to change the direction of the progress.
@IBOutlet var directionControl: UISegmentedControl?
override var progressViews: [M13ProgressView] {
if let ringProgressView = segmentedRingProgressView {
return [ringProgressView]
}
return []
}
//-------------------------------
// MARK: Initalization
//-------------------------------
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//-------------------------------
// MARK: Actions
//-------------------------------
/**
Shows and hides the percentage label in the progress ring.
- parameter sender: The switch whose value has changed.
*/
@IBAction func updatePercentage(sender: UISwitch) {
segmentedRingProgressView?.percentage = sender.on
}
/**
Changes the direction progress travels in.
- parameter sender: The segmented control whose value has changed.
*/
@IBAction func updateDirection(sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
segmentedRingProgressView?.progressDirection = .Clockwise
} else if sender.selectedSegmentIndex == 1 {
segmentedRingProgressView?.progressDirection = .CounterClockwise
}
}
/**
Updates the shape of the segment wedges.
- parameter sender: The control whose value was updated.
*/
@IBAction func updateSegmentBoundary(sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
segmentedRingProgressView?.segmentBoundaryType = .Wedge
} else if sender.selectedSegmentIndex == 1 {
segmentedRingProgressView?.segmentBoundaryType = .Rectangle
}
}
}
-111
View File
@@ -1,111 +0,0 @@
2.0.0
=====
The 2.0.0 update is coming! Now that I have some time, I'll be updating M13ProgressSuite to Swift. Along with the conversion, I'll be making some updates under the hood to make M13ProgressSuite more reliable. Interface Builder support is also on its way. Even though I have time to do this update, I don't have unlimited time to work on the library. So all fixes and feature requests that are not pull requests will be added to version 2.0.0. I've published the base project, as all that needs to happen now is converting the individual progress views to swift. If anyone wants to lend a hand that would be greatly appreciated.
Thanks,
Brandon
TODO
====
**Repo**
- Update readme to include small gifs.
- Add .io site for complete example list and property examples, with images of what property changes will do.
- Add generated documentation to .io site.
- Add CI service.
- Add direction and ideas list to .io site.
**Overall**
- Support NSCoding protocol on all classes.
- Support NSCopying protocol on all classes.
- Add animations and transitions for all possible visual changes that would be user-visible.
- Move icon generation into own class. Pass draw rect for icon, size of icon. Make it easier to override with custom icons.
- New icons that fit iOS 7+ style.
- Add optional animation completion blocks to setState and setProgress.
- Possibly move some requirements from M13ProgressView class / subclasses to protocols. Like some shared requirements for the segmented progress views.
- Add wrapper to display percentage outside of progress view: leading, trailing, above, below.
**Examples**
- Fix crash when phone is in portrait mode.
- Make layouts of all examples vertically scrollable.
- Include controls to change all parameters except for color.
- Make layouts dynamic. No controls should overlap.
- Add app extension example.
- Research and Add watch OS example. (After everything else is done)
**Ring**
- Add stroke animation for x and "check" when shown, fade when hide.
- Add boolean to set the bar background color to the tint color instead of secondary.
- Multistage animation for indeterminate transition.
- Decrease width of progress bar.
- Animate in the gap in the progress background.
- Start rotating the progress background.
- When finished, complete a revolution before closing the gap.
**Navigation Bar**
- Custom height of progress bar.
- Custom progress bar offset.
- Prefix all methods with "m13_" to avoid conflicts.
**Segmented Progress Views**
- Add support for an array of primary colors.
**Console**
- Remove? Not up to par with the rest of the controls. Can't see use case for it.
**Filtered Image**
- Pre-render images? Provide hook for ΔProgress to render images for? Therefore fixing issues with lag.
**Image**
- Rename to greyscale image.
**Pie**
- Better indeterminate animation.
- Hide progress once finished when switching to non-normal state.
**HUD**
- Add option of buttons to allow cancelation of current activity.
M13ProgressSuite
================
A collection of easy to use progress views for iOS applications. The collection includes progress views of many types (bar, ring, etc.), an UINavigationBar with progress bar, and a HUD overlay. Everything in the collection is easily styled through code or Interface Builder, and is simple to update.
Checkout the [M13ProgressSuite website](marxon13.github.io/M13ProgressSuite) to see more examples and documentation.
Features:
---------
* All progress views inherit from the same base class, making it easy to use multiple kinds of progress views in a project, or swap kinds of progress views.
* The progress views have a determinate state, indeterminate state, success state, and failure state.
* All the progress views are IBDesignable.
* It is very easy to make custom progress views, as the base class handles the grunt work of the animation. Just write the code to display a specific progress value, as well as the indeterminate, success and failure states.
Contact Me:
-------------
If you have any questions comments or suggestions, send me a message. If you find a bug, or want to submit a pull request, let me know.
License:
--------
MIT License
> Copyright (c) 2015 Brandon McQuilkin
>
> 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.
+279
View File
@@ -0,0 +1,279 @@
//
// M13ProgressBar.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon (NonEmp) on 8/8/16.
// Copyright © 2016 Brandon McQuilkin. All rights reserved.
//
import UIKit
/**
The possible directions a progress bar can travel in.
- **leadingToTrailing**: The progress bar will travel from leading to trailing as the progress nears completion.
- **trailingToLeading**: The progress bar will travel from trailing to leading as the progress nears completion.
- **bottomToTop**: The progress bar will travel from the bottom to the top as the progress nears completion.
- **topToBottom**: The progress bar will travel from the top to the bottom as the progress nears completion.
*/
public enum M13ProgressBarProgressDirection: Int, RawRepresentable {
/// The progress bar will travel from leading to trailing as the progress nears completion.
case leadingToTrailing
/// The progress bar will travel from trailing to leading as the progress nears completion.
case trailingToLeading
/// The progress bar will travel from the bottom to the top as the progress nears completion.
case bottomToTop
/// The progress bar will travel from the top to the bottom as the progress nears completion.
case topToBottom
}
/**
A simple progress bar that can display determinate and indeterminate progress.
*/
@IBDesignable
public class M13ProgressBar: M13ProgressViewBase, M13ProgressViewMultipleType {
// ---------------------------------
// MARK: - Initalization
// ---------------------------------
override init() {
super.init(frame: CGRect.zero)
sharedSetup()
}
override init(frame: CGRect) {
super.init(frame: frame)
sharedSetup()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
cornerRadius = CGFloat(aDecoder.decodeDouble(forKey: "cornerRadius"))
if let direction = aDecoder.decodeObject(forKey: "progressDirection") as? String {
_IBprogressDirection = direction
}
sharedSetup()
}
public override func encode(with aCoder: NSCoder) {
super.encode(with: aCoder)
aCoder.encode(cornerRadius, forKey: "cornerRadius")
aCoder.encode(_IBprogressDirection, forKey: "progressDirection")
}
override func sharedSetup() {
super.sharedSetup()
// Setup the defaults
clipsToBounds = true
setAppropiateCornerRadius()
layer.backgroundColor = secondaryTintColor?.cgColor
progressLayer.backgroundColor = tintColor.cgColor
progressLayer.actions = [
"frame": NSNull(),
"anchorPoint": NSNull(),
"bounds": NSNull(),
"position": NSNull(),
"cornerRadius": NSNull()
]
layer.addSublayer(progressLayer)
}
public override func prepareForInterfaceBuilder() {
sharedSetup()
super.prepareForInterfaceBuilder()
}
// ---------------------------------
// MARK: - Properties
// ---------------------------------
@IBInspectable override public var secondaryTintColor: UIColor? {
didSet {
layer.backgroundColor = secondaryTintColor?.cgColor
}
}
@IBInspectable public var cornerRadius: CGFloat = CGFloat.greatestFiniteMagnitude {
didSet {
setAppropiateCornerRadius()
}
}
public var progressDirection: M13ProgressBarProgressDirection = .leadingToTrailing {
didSet {
}
}
public var determinatePropertyAnimator: UIViewPropertyAnimator = UIViewPropertyAnimator(duration: 0.3, curve: .easeIn, animations: nil)
public var indeterminatePropertyAnimator: UIViewPropertyAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .easeInOut, animations: nil)
// ---------------------------------
// MARK: - Progress
// ---------------------------------
private var _progress: CGFloat = 0.0
@IBInspectable public var progress: CGFloat {
get {
return _progress
}
set {
setProgress(newValue, animated: false, completion: nil)
}
}
public func setProgress(_ progress: CGFloat, animated: Bool, completion: ((progress: CGFloat) -> Void)?) {
// Only adjust if we are showing determinate progress.
guard type == .determinate else {
return
}
// Adjusted progress
let adjustedProgress = max(min(progress, 1.0), 0.0)
// If we are not animated, end any animations and set the proper frame to the progress layer
if !animated {
determinatePropertyAnimator.stopAnimation(false)
progressLayer.frame = CGRect(x: 0.0, y: 0.0, width: frame.size.width * adjustedProgress, height: frame.height)
return
}
// Adjust the animation for the new progress value.
let durationFactor = determinatePropertyAnimator.fractionComplete
determinatePropertyAnimator.stopAnimation(false)
determinatePropertyAnimator.finishAnimation(at: .current)
determinatePropertyAnimator.addAnimations { [unowned self] in
self._progress = adjustedProgress
self.progressLayer.frame = CGRect(x: 0.0, y: 0.0, width: self.frame.size.width * adjustedProgress, height: self.frame.height)
}
determinatePropertyAnimator.addCompletion { (position) in
completion?(progress: adjustedProgress)
}
// Restart the animation.
determinatePropertyAnimator.startAnimation()
determinatePropertyAnimator.pauseAnimation()
determinatePropertyAnimator.continueAnimation(withTimingParameters: nil, durationFactor: durationFactor)
}
private var _type: M13ProgressType = .determinate
public var type: M13ProgressType {
get {
return _type
}
set {
setType(newValue, animated: false, completion: nil)
}
}
public func setType(_ type: M13ProgressType, animated: Bool, completion: ((type: M13ProgressType) -> Void)?) {
}
// ---------------------------------
// MARK: - UI
// ---------------------------------
private var progressLayer: CAShapeLayer = CAShapeLayer()
public override func tintColorDidChange() {
super.tintColorDidChange()
progressLayer.backgroundColor = tintColor.cgColor
}
// ---------------------------------
// MARK: - Layout
// ---------------------------------
public override var intrinsicContentSize: CGSize {
return CGSize(width: UIViewNoIntrinsicMetric, height: UIViewNoIntrinsicMetric)
}
public override func layoutSubviews() {
super.layoutSubviews()
setAppropiateCornerRadius()
}
// ---------------------------------
// MARK: - Other
// ---------------------------------
private func setAppropiateCornerRadius() {
var appropiateCornerRadius = min(frame.size.width / 2.0, frame.size.height / 2.0)
appropiateCornerRadius = min(appropiateCornerRadius, cornerRadius)
progressLayer.cornerRadius = appropiateCornerRadius
layer.cornerRadius = appropiateCornerRadius
}
}
// Interface builder support extension.
extension M13ProgressBar {
@IBInspectable public var _IBprogressDirection: String {
get {
switch progressDirection {
case .leadingToTrailing:
return "leadingToTrailing"
case .trailingToLeading:
return "trailingToLeading"
case .bottomToTop:
return "bottomToTop"
case .topToBottom:
return "topToBottom"
}
}
set {
switch newValue {
case "leadingToTrailing":
progressDirection = .leadingToTrailing
break
case "trailingToLeading":
progressDirection = .trailingToLeading
break
case "bottomToTop":
progressDirection = .bottomToTop
break
case "topToBottom":
progressDirection = .topToBottom
break
default:
progressDirection = .leadingToTrailing
break
}
}
}
@IBInspectable public var _IBIndeterminate: Bool {
get {
switch type {
case .determinate:
return false
case .indeterminate:
return true
}
}
set {
if newValue {
type = .indeterminate
} else {
type = .determinate
}
}
}
}
+43
View File
@@ -0,0 +1,43 @@
//
// M13ProgressState.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 8/7/16.
// Copyright © 2016 Brandon McQuilkin. All rights reserved.
//
/**
The possible states of progress views.
- **normal**: The progress view is in its normal state of displaying progress.
- **success**: The progress view displays an indicator that the operation completed successfully.
- **failure**: The progress view displays an indicator that the operation failed.
*/
public enum M13ProgressState {
/// The progress view is in its normal state of displaying progress.
case progressing
/// The progress view displays an indicator that the operation completed successfully.
case success
/// The progress view displays an indicator that the operation failed.
case failure
}
/**
A protocol that provides structure for progress views that have success and failure states.
*/
public protocol M13ProgressViewState {
/**
The current state of the progress view.
*/
var state: M13ProgressState { get set }
/**
Set the state of the progress view, with the option of animating the state change.
- parameter state: The new state of the progress view.
- parameter animated: Whether or no to animate the change.
- parameter completion: The completion block to run once the animation has finsihed.
*/
func setState(_ state: M13ProgressState, animated: Bool, completion: ((state: M13ProgressState) -> Void)?)
}
+79
View File
@@ -0,0 +1,79 @@
//
// M13ProgressIndeterminate.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 8/7/16.
// Copyright © 2016 Brandon McQuilkin. All rights reserved.
//
import UIKit
/**
The possible types of progress the progress views can display.
- **determinate**: The amount of progress made or the time remaining is known.
- **indeterminate**: The amount of progress and the remaining time is unknown.
*/
public enum M13ProgressType {
/// The amount of progress made or the time remaining is known.
case determinate
/// The amount of progress and the remaining time is unknown.
case indeterminate
}
/**
A protocol that provides the structure for determinate progress views.
*/
public protocol M13ProgressViewDeterminate {
/**
The progress displayed to the user as a percentage from 0.0 to 1.0.
*/
var progress: CGFloat { get set }
/**
Set the progress of the progress view, with the option of animating the change.
- parameter progress: The amount of progress that has been made.
- parameter animated: Whether or no to animate the change.
- parameter completion: The completion block to run once the animation has finished.
*/
func setProgress(_ progress: CGFloat, animated: Bool, completion: ((progress: CGFloat) -> Void)?)
/**
The property animator that controls the determinate progress animations.
- warning: Wait until all animations are complete before changing the property animator.
*/
var determinatePropertyAnimator: UIViewPropertyAnimator { get set }
}
/**
A protocol that provides the structure for indeterminate progress views.
*/
public protocol M13ProgressViewIndeterminate {
/**
The property animator that controls the indeterminate progress animations.
- warning: Wait until all animations are complete before changing the property animator.
*/
var indeterminatePropertyAnimator: UIViewPropertyAnimator { get set }
}
/**
A protocol that provides structure for progress views that can show both determinate and indeterminate progress.
*/
public protocol M13ProgressViewMultipleType: M13ProgressViewDeterminate, M13ProgressViewIndeterminate {
/**
The type of progress the progress view is displaying.
*/
var type: M13ProgressType { get set }
/**
Set the type of progress the progress view is displaying, with the option of animating the change.
- parameter type: The new type of the progress the progress view will display.
- parameter animated: Whether or no to animate the change.
- parameter completion: The completion block to run once the animation has finished.
*/
func setType(_ type: M13ProgressType, animated: Bool, completion: ((type: M13ProgressType) -> Void)?)
}
+20
View File
@@ -0,0 +1,20 @@
//
// M13ProgressView.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon on 8/7/16.
// Copyright © 2016 Brandon McQuilkin. All rights reserved.
//
import UIKit
/**
A standardized base upon which to build progress views for applications. This allows one to use any progress view in any component that use this standard.
*/
public protocol M13ProgressView {
/// A secondary tint color for the progress view.
var secondaryTintColor: UIColor? { get set }
}
+52
View File
@@ -0,0 +1,52 @@
//
// M13ProgressViewBase.swift
// M13ProgressSuite
//
// Created by McQuilkin, Brandon (NonEmp) on 8/8/16.
// Copyright © 2016 Brandon McQuilkin. All rights reserved.
//
import UIKit
@IBDesignable
public class M13ProgressViewBase: UIView, M13ProgressView {
// ---------------------------------
// MARK: - Initalization
// ---------------------------------
init() {
super.init(frame: CGRect.zero)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
secondaryTintColor = aDecoder.decodeObject(forKey: "secondaryTintColor") as? UIColor
}
public override func encode(with aCoder: NSCoder) {
super.encode(with: aCoder)
aCoder.encode(secondaryTintColor, forKey: "secondaryTintColor")
}
/**
The setup shared between the various initalizers.
*/
internal func sharedSetup() {
}
// ---------------------------------
// MARK: - Properties
// ---------------------------------
@IBInspectable public var secondaryTintColor: UIColor?
}