diff --git a/LinearProgressBar.xcodeproj/project.pbxproj b/LinearProgressBar.xcodeproj/project.pbxproj index 22938e3..03094d4 100644 --- a/LinearProgressBar.xcodeproj/project.pbxproj +++ b/LinearProgressBar.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 057FB7FC1FD785FC00F420F5 /* Clamp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 057FB7FB1FD785FC00F420F5 /* Clamp.swift */; }; 058891B51C40F24100C1CC61 /* LinearProgressBar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05AC61B31BF6AE1D00BFA053 /* LinearProgressBar.framework */; }; 058891B61C40F24100C1CC61 /* LinearProgressBar.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05AC61B31BF6AE1D00BFA053 /* LinearProgressBar.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 05AC61B71BF6AE1D00BFA053 /* LinearProgressBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 05AC61B61BF6AE1D00BFA053 /* LinearProgressBar.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -60,7 +59,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 057FB7FB1FD785FC00F420F5 /* Clamp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Clamp.swift; sourceTree = ""; }; 05AC61B31BF6AE1D00BFA053 /* LinearProgressBar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LinearProgressBar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 05AC61B61BF6AE1D00BFA053 /* LinearProgressBar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LinearProgressBar.h; sourceTree = ""; }; 05AC61B81BF6AE1D00BFA053 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -130,7 +128,6 @@ 05AC61B61BF6AE1D00BFA053 /* LinearProgressBar.h */, 05AC61B81BF6AE1D00BFA053 /* Info.plist */, 05AC61CD1BF6B35900BFA053 /* LinearProgressBar.swift */, - 057FB7FB1FD785FC00F420F5 /* Clamp.swift */, ); path = LinearProgressBar; sourceTree = ""; @@ -306,7 +303,6 @@ buildActionMask = 2147483647; files = ( 05AC61CE1BF6B35900BFA053 /* LinearProgressBar.swift in Sources */, - 057FB7FC1FD785FC00F420F5 /* Clamp.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/LinearProgressBar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/LinearProgressBar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/LinearProgressBar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/LinearProgressBar/Clamp.swift b/LinearProgressBar/Clamp.swift deleted file mode 100644 index b567b89..0000000 --- a/LinearProgressBar/Clamp.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// Clamp.swift -// LinearProgressBar -// -// Created by Eliel A. Gordon on 12/5/17. -// Copyright © 2017 Eliel Gordon. All rights reserved. -// - -import Foundation - -extension Comparable { - func clamped(lowerBound: Self, upperBound: Self) -> Self { - return min(max(self, lowerBound), upperBound) - } -} diff --git a/LinearProgressBar/LinearProgressBar.swift b/LinearProgressBar/LinearProgressBar.swift index 7d836e3..f9d59ed 100644 --- a/LinearProgressBar/LinearProgressBar.swift +++ b/LinearProgressBar/LinearProgressBar.swift @@ -6,103 +6,131 @@ // Copyright © 2015 Eliel Gordon. All rights reserved. // -import UIKit +#if os(iOS) || os(tvOS) +public typealias LPBView = UIView +public typealias LPBColor = UIColor +#elseif os(macOS) +public typealias LPBView = NSView +public typealias LPBColor = NSColor +#endif -/// Draws a progress bar -@IBDesignable -open class LinearProgressBar: UIView { - - /// The color of the progress bar - @IBInspectable public var barColor: UIColor = UIColor.green - /// The color of the base layer of the bar - @IBInspectable public var trackColor: UIColor = UIColor.yellow - /// The thickness of the bar - @IBInspectable public var barThickness: CGFloat = 10 - /// Padding on the left, right, top and bottom of the bar, in relation to the track of the progress bar - @IBInspectable public var barPadding: CGFloat = 0 - - /// Padding on the track on the progress bar - @IBInspectable public var trackPadding: CGFloat = 6 { +fileprivate extension Comparable { + + func clamped(lowerBound: Self, upperBound: Self) -> Self { + return min(max(self, lowerBound), upperBound) + } + +} + +open class LinearProgressBar: LPBView { + + /// The color of the progress bar. + public var barColor: LPBColor = LPBColor.green + /// The color of the base layer of the bar. + public var trackColor: LPBColor = LPBColor.yellow + /// The thickness of the bar. + public var barThickness: CGFloat = 10 + /// Padding on the left, right, top and bottom of the bar, in relation to the track of the progress bar. + public var barPadding: CGFloat = 0 + /// Line cap of the bar. + public var lineCap: CGLineCap = .round + + /// Padding on the track on the progress bar. + public var trackPadding: CGFloat = 6 { didSet { if trackPadding < 0 { trackPadding = 0 - }else if trackPadding > barThickness { + } else if trackPadding > barThickness { trackPadding = 0 } } } - @IBInspectable public var progressValue: CGFloat = 0 { + public var progressValue: CGFloat = 0 { didSet { progressValue = progressValue.clamped(lowerBound: 0, upperBound: 100) + #if os(iOS) || os(tvOS) setNeedsDisplay() + #elseif os(macOS) + needsDisplay = true + #endif } } - open var barColorForValue: ((Float)->UIColor)? + open var barColorForValue: ((Double) -> LPBColor)? fileprivate var trackHeight: CGFloat { return barThickness + trackPadding } - + fileprivate var trackOffset: CGFloat { return trackHeight / 2 } - + public override init(frame: CGRect) { super.init(frame: frame) setup() } - + public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } - open override func draw(_ rect: CGRect) { - super.draw(rect) - + open override func draw(_ dirtyRect: CGRect) { + super.draw(dirtyRect) + #if os(macOS) + NSGraphicsContext.current?.cgContext.clear(dirtyRect) + #endif drawProgressView() } - /// Draws a line representing the progress bar + /// Draws a line representing the progress bar. /// /// - Parameters: - /// - context: context to be mutated - /// - lineWidth: width of track or bar - /// - begin: point to begin drawing - /// - end: point to end drawing - /// - lineCap: lineCap style - /// - strokeColor: color of bar - func drawOn(context: CGContext, lineWidth: CGFloat, begin: CGPoint, end: CGPoint, lineCap: CGLineCap, strokeColor: UIColor) { + /// - context: Context to be mutated. + /// - lineWidth: Width of track or bar. + /// - begin: Point to begin drawing. + /// - end: Point to end drawing. + /// - lineCap: Line cap style. + /// - strokeColor: Bar color. + func drawOn(context: CGContext, + lineWidth: CGFloat, + begin: CGPoint, + end: CGPoint, + lineCap: CGLineCap, + strokeColor: LPBColor) { context.setStrokeColor(strokeColor.cgColor) context.beginPath() context.setLineWidth(lineWidth) context.move(to: begin) context.addLine(to: end) - context.setLineCap(.round) + context.setLineCap(lineCap) context.strokePath() } - + func drawProgressView() { - guard let context = UIGraphicsGetCurrentContext() else {return} - + #if os(iOS) || os(tvOS) + guard let context = UIGraphicsGetCurrentContext() else { + return + } + #elseif os(macOS) + guard let context = NSGraphicsContext.current?.cgContext else { + return + } + #endif let beginPoint = CGPoint(x: barPadding + trackOffset, y: frame.size.height / 2) - - // Progress Bar Track drawOn( context: context, lineWidth: barThickness + trackPadding, begin: beginPoint, end: CGPoint(x: frame.size.width - barPadding - trackOffset, y: frame.size.height / 2), - lineCap: .round, + lineCap: lineCap, strokeColor: trackColor ) - // Progress bar - let colorForBar = barColorForValue?(Float(progressValue)) ?? barColor - + let colorForBar = barColorForValue?(Double(progressValue)) ?? barColor drawOn( context: context, lineWidth: barThickness, @@ -113,19 +141,25 @@ open class LinearProgressBar: UIView { ) } - /// Clear graphics context and redraw on bounds change + /// Clear graphics context and redraw on bounds change. func setup() { + #if os(iOS) || os(tvOS) clearsContextBeforeDrawing = true self.contentMode = .redraw clipsToBounds = false + #elseif os(macOS) + wantsLayer = true + layer!.masksToBounds = true + #endif } - /// Calculates the percent value of the progress bar + /// Calculates the percent value of the progress bar. /// - /// - Returns: The percentage of progress + /// - Returns: The percentage of progress. func calculatePercentage() -> CGFloat { let screenWidth = frame.size.width - (barPadding * 2) - (trackOffset * 2) let progress = ((progressValue / 100) * screenWidth) return progress < 0 ? barPadding : progress } + }