├── .swift-version
├── graphics
├── Logo.gif
├── logo.pcvd
├── Activity.pcvd
├── Progress.pcvd
├── example.gif
├── tripleGears.gif
├── OrbitIndicator.gif
├── OrbitIndicator2.gif
├── OrbitIndicator3.gif
├── ProgressBarDisplay.gif
├── ProgressCircleDisplay.gif
├── anotated_storyboard_screenshot.png
└── anotated_storyboard_screenshot.afdesign
├── Example
├── Resources
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-76.png
│ │ │ ├── Icon-167.png
│ │ │ ├── Icon-60@2x.png
│ │ │ ├── Icon-60@3x.png
│ │ │ ├── Icon-76@2x.png
│ │ │ ├── Icon-Small.png
│ │ │ ├── Icon-Small@2x.png
│ │ │ ├── Icon-Small@3x.png
│ │ │ ├── Icon-Small-40@2x.png
│ │ │ ├── Icon-Small-40@3x.png
│ │ │ ├── iTunesArtwork@2x.png
│ │ │ └── Contents.json
│ ├── Info.plist
│ └── Base.lproj
│ │ └── LaunchScreen.storyboard
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── ViewController.swift
└── AppDelegate.swift
├── .jazzy.yaml
├── .gitlab-ci.yml
├── Tests
└── ShowSomeProgressTests.swift
├── .github
└── ISSUE_TEMPLATE
│ ├── feature-request.md
│ ├── bug-report.md
│ ├── feature_request.md
│ └── bug_report.md
├── .swiftlint.yml
├── Sources
├── Extensions.swift
├── ActivityAnimationHelper.swift
├── BarProgressView.swift
├── CircleProgressView.swift
├── OrbitActivityIndicatorView.swift
├── AnimationHelper.swift
└── stylekit
│ ├── ProgressStyleKit.swift
│ └── ActivityStyleKit.swift
├── Package.swift
├── ShowSomeProgress.podspec
├── Configs
├── ShowSomeProgressTests.plist
└── ShowSomeProgress.plist
├── LICENSE
├── .gitignore
├── fastlane
└── Fastfile
├── CODE_OF_CONDUCT.md
└── README.md
/.swift-version:
--------------------------------------------------------------------------------
1 | 5.0
2 |
--------------------------------------------------------------------------------
/graphics/Logo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/Logo.gif
--------------------------------------------------------------------------------
/graphics/logo.pcvd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/logo.pcvd
--------------------------------------------------------------------------------
/graphics/Activity.pcvd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/Activity.pcvd
--------------------------------------------------------------------------------
/graphics/Progress.pcvd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/Progress.pcvd
--------------------------------------------------------------------------------
/graphics/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/example.gif
--------------------------------------------------------------------------------
/graphics/tripleGears.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/tripleGears.gif
--------------------------------------------------------------------------------
/graphics/OrbitIndicator.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/OrbitIndicator.gif
--------------------------------------------------------------------------------
/graphics/OrbitIndicator2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/OrbitIndicator2.gif
--------------------------------------------------------------------------------
/graphics/OrbitIndicator3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/OrbitIndicator3.gif
--------------------------------------------------------------------------------
/graphics/ProgressBarDisplay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/ProgressBarDisplay.gif
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/graphics/ProgressCircleDisplay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/ProgressCircleDisplay.gif
--------------------------------------------------------------------------------
/graphics/anotated_storyboard_screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/anotated_storyboard_screenshot.png
--------------------------------------------------------------------------------
/graphics/anotated_storyboard_screenshot.afdesign:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/graphics/anotated_storyboard_screenshot.afdesign
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-167.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-167.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stoneburner/ShowSomeProgress/HEAD/Example/Resources/Assets.xcassets/AppIcon.appiconset/iTunesArtwork@2x.png
--------------------------------------------------------------------------------
/.jazzy.yaml:
--------------------------------------------------------------------------------
1 | # ShowSomeProgress document generator jazzy settings
2 |
3 | copyright: Copyright 2019 ShowSomeProgress
4 | author: Alexander Kasimir
5 | xcodebuild_arguments: [-target, ShowSomeProgress-iOS]
6 | clean: true
7 | output: ./Documentation
8 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | stages:
2 | - Tests
3 | - Compatibility
4 |
5 | UnitTests:
6 | stage: Tests
7 | only:
8 | - master
9 | - develop
10 | - /^hotfix.*$/
11 | - /^feature.*$/
12 | script:
13 | fastlane ios tests
14 |
15 | DependencyManagerCompatibility:
16 | stage: Compatibility
17 | only:
18 | - master
19 | - develop
20 | - /^hotfix.*$/
21 | - /^feature.*$/
22 | script:
23 | fastlane ios compatibilityTests
--------------------------------------------------------------------------------
/Tests/ShowSomeProgressTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShowSomeProgressTests.swift
3 | // ShowSomeProgressTests
4 | //
5 | // Created by Alexander Kasimir on 04.08.2019.
6 | // Copyright © 2019 ShowSomeProgress. All rights reserved.
7 | //
8 |
9 | @testable import ShowSomeProgress
10 | import XCTest
11 |
12 | class ShowSomeProgressTests: XCTestCase {
13 |
14 | static var allTests = [
15 | ("testExample", testExample),
16 | ]
17 |
18 | func testExample() {}
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for ShowSomeProgress
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | # Motivation
11 | > ℹ Please replace this with your motivation. For example if your feature request is related to a problem.
12 |
13 | # Solution
14 | > ℹ Please replace this with your proposed solution.
15 |
16 | # Additional context
17 | > ℹ Please replace this with any other context or screenshots about your feature request (optional).
18 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | opt_in_rules: # some rules are only opt-in
2 | - empty_count
3 | - redundant_nil_coalescing
4 | - switch_case_on_newline
5 | - force_unwrapping
6 | - closure_spacing
7 | - implicitly_unwrapped_optional
8 | - sorted_imports
9 | - valid_docs
10 | - nslocalizedstring_require_bundle
11 |
12 | included:
13 | - Sources
14 |
15 | excluded: # paths to ignore during linting. Takes precedence over `included`.
16 | - Tests
17 | - Example
18 | - Sources/stylekit # stylekits are auto generated
19 | disabled_rules: # rule identifiers to exclude from running
20 | - line_length
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a bug report
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## ShowSomeProgress Environment
11 |
12 | - ShowSomeProgress version:
13 | - macOS version:
14 | - Xcode version:
15 | - Dependency manager (Carthage, CocoaPods, SPM, Manually):
16 |
17 | ## What did you do?
18 |
19 | > ℹ Please replace this with what you did.
20 |
21 | ## What did you expect to happen?
22 |
23 | > ℹ Please replace this with what you expected to happen.
24 |
25 | ## What happened instead?
26 |
27 | > ℹ Please replace this with of what happened instead.
28 |
--------------------------------------------------------------------------------
/Sources/Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Extensions.swift
3 | // ShowSomeProgress-iOS
4 | //
5 | // Created by Alexander Kasimir on 04.08.19.
6 | // Copyright © 2019 ShowSomeProgress. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | extension UIColor {
12 |
13 | //swiftlint:disable:next large_tuple
14 | var components: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
15 | var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
16 | self.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
17 | return (red: red, green: green, blue: blue, alpha: alpha)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:4.0
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "ShowSomeProgress",
7 | products: [
8 | .library(
9 | name: "ShowSomeProgress",
10 | targets: ["ShowSomeProgress"]
11 | ),
12 | ],
13 | dependencies: [],
14 | targets: [
15 | .target(
16 | name: "ShowSomeProgress",
17 | dependencies: [],
18 | path: "Sources"
19 | ),
20 | .testTarget(
21 | name: "ShowSomeProgressTests",
22 | dependencies: ["ShowSomeProgress"],
23 | path: "Tests"
24 | ),
25 | ]
26 | )
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/ShowSomeProgress.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "ShowSomeProgress"
3 | s.version = "1.0.0"
4 | s.summary = "ShowSomeProgress"
5 | s.homepage = "https://github.com/AlexanderKasimir/ShowSomeProgress"
6 | s.license = { :type => "MIT", :file => "LICENSE" }
7 | s.author = { "Alexander Kasimir" => "alexander@kasimir.at" }
8 | s.source = { :git => "https://github.com/AlexanderKasimir/ShowSomeProgress.git", :tag => s.version.to_s }
9 | s.ios.deployment_target = "8.0"
10 | s.tvos.deployment_target = "9.0"
11 | s.watchos.deployment_target = "2.0"
12 | s.osx.deployment_target = "10.10"
13 | s.source_files = "Sources/**/*"
14 | s.frameworks = "Foundation"
15 | end
16 |
--------------------------------------------------------------------------------
/Configs/ShowSomeProgressTests.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/Configs/ShowSomeProgress.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ShowSomeProgress
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | NSHumanReadableCopyright
26 | Copyright © 2019 ShowSomeProgress. All rights reserved.
27 | NSPrincipalClass
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Alexander Kasimir
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Sources/ActivityAnimationHelper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ActivityAnimationHelper.swift
3 | // ShowSomeProgress-iOS
4 | //
5 | // Created by Alexander Kasimir on 06.08.19.
6 | // Copyright © 2019 ShowSomeProgress. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public protocol AnimatedActivityUIView: UIView {
12 | var timer: Timer? { get set }
13 | var animationProgress: CGFloat { get set }
14 | var frameRate: TimeInterval { get set }
15 | func startAnimation()
16 | func stopAnimation()
17 | func animationStep()
18 | }
19 |
20 | extension AnimatedActivityUIView {
21 |
22 | public func startAnimation() {
23 | guard timer == nil else { return } // if timer is not nill, the animation is already running
24 | timer = Timer.scheduledTimer(withTimeInterval: frameRate, repeats: true) { _ in self.animationStep() }
25 | }
26 |
27 | public func stopAnimation() {
28 | timer?.invalidate()
29 | timer = nil
30 | setNeedsDisplay()
31 | }
32 |
33 | public func animationStep() {
34 | animationProgress += 0.01
35 | if animationProgress >= 1 {
36 | animationProgress = 0
37 | }
38 | setNeedsDisplay()
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/BarProgressView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BarProgressView.swift
3 | // AnimationTest
4 | //
5 | // Created by Alexander Kasimir on 31.07.19.
6 | // Copyright © 2019 Alexander Kasimir. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @IBDesignable public class BarProgressView: UIView, AnimatedUIView {
12 | @IBInspectable public var progress: CGFloat = 0.5 { didSet { updateValue() } }
13 | @IBInspectable public var progressColor: UIColor = UIColor.blue { didSet { updateValue() } }
14 | @IBInspectable public var showTriangle: Bool = false
15 |
16 | var animatedLayer: Progressable = ProgressBarAnimationLayer()
17 | var stateKeyName = "state"
18 |
19 | override public func layoutSubviews() {
20 | setupAnimationLayer(progressColor: progressColor, showTriangle: showTriangle)
21 | updateValue()
22 | animatedLayer.frame = self.bounds
23 | }
24 | }
25 |
26 | public class ProgressBarAnimationLayer: ProgressAnimationLayer {
27 |
28 | override public func draw(in ctx: CGContext) {
29 | UIGraphicsPushContext(ctx)
30 | let size = ctx.convertToUserSpace(CGSize(width: ctx.width, height: ctx.height))
31 | let rect = CGRect(origin: CGPoint.zero, size: size)
32 |
33 | let color = progressColor.components
34 | ProgressStyleKit.drawProgressBarDisplay(frame: rect, resizing: .aspectFit, progress: progress, showTriangle: showTriangle, progressColorRed: color.red, progressColorGreen: color.green, progressColorBlue: color.blue)
35 |
36 | UIGraphicsPopContext()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/CircleProgressView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomProgressView.swift
3 | // AnimationTest
4 | //
5 | // Created by Alexander Kasimir on 28.07.19.
6 | // Copyright © 2019 Alexander Kasimir. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | public class CircleProgressAnimationLayer: ProgressAnimationLayer {
12 |
13 | override public func draw(in ctx: CGContext) {
14 | UIGraphicsPushContext(ctx)
15 | let size = ctx.convertToUserSpace(CGSize(width: ctx.width, height: ctx.height))
16 | let rect = CGRect(origin: CGPoint.zero, size: size)
17 |
18 | let colors = progressColor.components
19 | ProgressStyleKit.drawProgressCircleDisplay(frame: rect, resizing: .aspectFit, progress: progress, showTriangle: showTriangle, progressColorRed: colors.red, progressColorGreen: colors.green, progressColorBlue: colors.blue)
20 | UIGraphicsPopContext()
21 | }
22 | }
23 |
24 | @IBDesignable public class CircleProgressView: UIView, AnimatedUIView {
25 | @IBInspectable public var progress: CGFloat = 0.5 { didSet { updateValue() } }
26 | @IBInspectable public var progressColor: UIColor = UIColor.blue { didSet { updateValue() } }
27 | @IBInspectable public var showTriangle: Bool = false { didSet { updateValue() } }
28 |
29 | var animatedLayer: Progressable = CircleProgressAnimationLayer()
30 | var stateKeyName = "state"
31 |
32 | override public func layoutSubviews() {
33 | setupAnimationLayer(progressColor: progressColor, showTriangle: showTriangle)
34 | animatedLayer.frame = self.bounds
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/Example/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | ShowSomeProgress
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeRight
37 | UIInterfaceOrientationLandscapeLeft
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Example/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/Resources/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // AnimationTest
4 | //
5 | // Created by Alexander Kasimir on 28.07.19.
6 | // Copyright © 2019 Alexander Kasimir. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import ShowSomeProgress
11 |
12 | class ViewController: UIViewController {
13 |
14 | @IBOutlet weak var gearView: GearActivityIndicatorView!
15 |
16 | @IBOutlet weak var smallCircleView: CircleProgressView!
17 | @IBOutlet weak var smallCircleView2: CircleProgressView!
18 | @IBOutlet weak var smallCircleView3: CircleProgressView!
19 | @IBOutlet weak var smallCircleView4: CircleProgressView!
20 |
21 | @IBOutlet weak var barProgressView: BarProgressView!
22 | @IBOutlet weak var barProgressView2: BarProgressView!
23 |
24 | @IBOutlet weak var orbitActivityIndicator: OrbitActivityIndicatorView!
25 | @IBOutlet weak var orbitActivityIndicator2: OrbitActivityIndicatorView2!
26 | @IBOutlet weak var orbitActivityIndicator3: OrbitActivityIndicatorView3!
27 | @IBAction func setRandomValueTapped(_ sender: Any) {
28 | smallCircleView.progress = CGFloat(Double.random(in: 0...1))
29 | smallCircleView2.progress = CGFloat(Double.random(in: 0...1))
30 | smallCircleView3.progress = CGFloat(Double.random(in: 0...1))
31 | smallCircleView4.progress = CGFloat(Double.random(in: 0...1))
32 | barProgressView.progress = CGFloat(Double.random(in: 0...1))
33 | barProgressView2.progress = CGFloat(Double.random(in: 0...1))
34 | }
35 |
36 | override func viewDidAppear(_ animated: Bool) {
37 | super.viewDidAppear(animated)
38 | gearView.startAnimation()
39 | orbitActivityIndicator.startAnimation()
40 | orbitActivityIndicator2.startAnimation()
41 | orbitActivityIndicator3.startAnimation()
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Example
4 | //
5 | // Created by Alexander Kasimir on 04.08.2019.
6 | // Copyright © 2019 ShowSomeProgress. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | // MARK: - AppDelegate
12 |
13 | /// The AppDelegate
14 | @UIApplicationMain
15 | class AppDelegate: UIResponder, UIApplicationDelegate {
16 |
17 | var window: UIWindow?
18 |
19 |
20 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
21 | // Override point for customization after application launch.
22 | return true
23 | }
24 |
25 | func applicationWillResignActive(_ application: UIApplication) {
26 | // 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.
27 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
28 | }
29 |
30 | func applicationDidEnterBackground(_ application: UIApplication) {
31 | // 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.
32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
33 | }
34 |
35 | func applicationWillEnterForeground(_ application: UIApplication) {
36 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
37 | }
38 |
39 | func applicationDidBecomeActive(_ application: UIApplication) {
40 | // 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.
41 | }
42 |
43 | func applicationWillTerminate(_ application: UIApplication) {
44 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "size" : "29x29",
15 | "idiom" : "iphone",
16 | "filename" : "Icon-Small@2x.png",
17 | "scale" : "2x"
18 | },
19 | {
20 | "size" : "29x29",
21 | "idiom" : "iphone",
22 | "filename" : "Icon-Small@3x.png",
23 | "scale" : "3x"
24 | },
25 | {
26 | "size" : "40x40",
27 | "idiom" : "iphone",
28 | "filename" : "Icon-Small-40@2x.png",
29 | "scale" : "2x"
30 | },
31 | {
32 | "size" : "40x40",
33 | "idiom" : "iphone",
34 | "filename" : "Icon-Small-40@3x.png",
35 | "scale" : "3x"
36 | },
37 | {
38 | "size" : "60x60",
39 | "idiom" : "iphone",
40 | "filename" : "Icon-60@2x.png",
41 | "scale" : "2x"
42 | },
43 | {
44 | "size" : "60x60",
45 | "idiom" : "iphone",
46 | "filename" : "Icon-60@3x.png",
47 | "scale" : "3x"
48 | },
49 | {
50 | "idiom" : "ipad",
51 | "size" : "20x20",
52 | "scale" : "1x"
53 | },
54 | {
55 | "idiom" : "ipad",
56 | "size" : "20x20",
57 | "scale" : "2x"
58 | },
59 | {
60 | "size" : "29x29",
61 | "idiom" : "ipad",
62 | "filename" : "Icon-Small.png",
63 | "scale" : "1x"
64 | },
65 | {
66 | "size" : "29x29",
67 | "idiom" : "ipad",
68 | "filename" : "Icon-Small@2x.png",
69 | "scale" : "2x"
70 | },
71 | {
72 | "idiom" : "ipad",
73 | "size" : "40x40",
74 | "scale" : "1x"
75 | },
76 | {
77 | "idiom" : "ipad",
78 | "size" : "40x40",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "76x76",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-76.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "76x76",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-76@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "83.5x83.5",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-167.png",
97 | "scale" : "2x"
98 | },
99 | {
100 | "size" : "1024x1024",
101 | "idiom" : "ios-marketing",
102 | "filename" : "iTunesArtwork@2x.png",
103 | "scale" : "1x"
104 | }
105 | ],
106 | "info" : {
107 | "version" : 1,
108 | "author" : "xcode"
109 | },
110 | "properties" : {
111 | "pre-rendered" : true
112 | }
113 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/xcode,swift,swiftpackagemanager
3 | # Edit at https://www.gitignore.io/?templates=xcode,swift,swiftpackagemanager
4 |
5 | ### Swift ###
6 | # Xcode
7 | #
8 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
9 |
10 | ## Build generated
11 | build/
12 | DerivedData/
13 |
14 | ## Various settings
15 | *.pbxuser
16 | !default.pbxuser
17 | *.mode1v3
18 | !default.mode1v3
19 | *.mode2v3
20 | !default.mode2v3
21 | *.perspectivev3
22 | !default.perspectivev3
23 | xcuserdata/
24 |
25 | ## Other
26 | *.moved-aside
27 | *.xccheckout
28 | *.xcscmblueprint
29 |
30 | ## Obj-C/Swift specific
31 | *.hmap
32 | *.ipa
33 | *.dSYM.zip
34 | *.dSYM
35 |
36 | ## Playgrounds
37 | timeline.xctimeline
38 | playground.xcworkspace
39 |
40 | # Swift Package Manager
41 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
42 | # Packages/
43 | # Package.pins
44 | # Package.resolved
45 | .build/
46 |
47 | # CocoaPods
48 | # We recommend against adding the Pods directory to your .gitignore. However
49 | # you should judge for yourself, the pros and cons are mentioned at:
50 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
51 | # Pods/
52 | # Add this line if you want to avoid checking in source code from the Xcode workspace
53 | # *.xcworkspace
54 |
55 | # Carthage
56 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
57 | # Carthage/Checkouts
58 |
59 | Carthage/Build
60 |
61 | # Accio dependency management
62 | Dependencies/
63 | .accio/
64 |
65 | # fastlane
66 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
67 | # screenshots whenever they are needed.
68 | # For more information about the recommended setup visit:
69 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
70 |
71 | fastlane/report.xml
72 | fastlane/Preview.html
73 | fastlane/screenshots/**/*.png
74 | fastlane/test_output
75 |
76 | # Code Injection
77 | # After new code Injection tools there's a generated folder /iOSInjectionProject
78 | # https://github.com/johnno1962/injectionforxcode
79 |
80 | iOSInjectionProject/
81 |
82 | ### SwiftPackageManager ###
83 | Packages
84 | xcuserdata
85 | *.xcodeproj
86 |
87 |
88 | ### Xcode ###
89 | # Xcode
90 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
91 |
92 | ## User settings
93 |
94 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
95 |
96 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
97 |
98 | ## Xcode Patch
99 | *.xcodeproj/*
100 | !*.xcodeproj/project.pbxproj
101 | !*.xcodeproj/xcshareddata/
102 | !*.xcworkspace/contents.xcworkspacedata
103 | /*.gcno
104 |
105 | ### Xcode Patch ###
106 | **/xcshareddata/WorkspaceSettings.xcsettings
107 |
108 | # End of https://www.gitignore.io/api/xcode,swift,swiftpackagemanager
109 |
--------------------------------------------------------------------------------
/fastlane/Fastfile:
--------------------------------------------------------------------------------
1 | fastlane_version "2.120.0"
2 |
3 | default_platform :ios
4 |
5 | platform :ios do
6 |
7 | desc "Release a new version of ShowSomeProgress"
8 | lane :release do |options|
9 | # Ensure Git status is clean
10 | ensure_git_status_clean
11 | # Ensure Git branch is master
12 | ensure_git_branch(branch: 'master')
13 | # Perform Dependency-Manager compatibility tests
14 | compatibilityTests
15 | # Perform Tests
16 | tests
17 | # Retrieve Version from options
18 | version = options[:version]
19 | # Increment Version
20 | increment(version: version)
21 | # Add Git Tag
22 | add_git_tag(tag: version)
23 | # Push Git Tag
24 | push_git_tags()
25 | # Push Git commit
26 | push_to_git_remote()
27 | # Pod push / Pod trunk
28 | pod_push()
29 | end
30 |
31 | desc "Increment Version"
32 | lane :increment do |options|
33 | # Retrieve Version from options
34 | version = options[:version]
35 | # Set Podspec version
36 | version_bump_podspec(
37 | path: "ShowSomeProgress.podspec",
38 | version_number: version
39 | )
40 | # Set Framework plist version
41 | set_info_plist_value(
42 | path: "Configs/ShowSomeProgress.plist",
43 | key: "CFBundleShortVersionString",
44 | value: version
45 | )
46 | # Set Framework Tests plist version
47 | set_info_plist_value(
48 | path: "Configs/ShowSomeProgressTests.plist",
49 | key: "CFBundleShortVersionString",
50 | value: version
51 | )
52 | # Set Example plist version
53 | set_info_plist_value(
54 | path: "Example/Resources/Info.plist",
55 | key: "CFBundleShortVersionString",
56 | value: version
57 | )
58 | # Commit modified files
59 | git_commit(
60 | path: [
61 | "ShowSomeProgress.podspec",
62 | "Configs/ShowSomeProgress.plist",
63 | "Configs/ShowSomeProgressTests.plist",
64 | "Example/Resources/Info.plist"
65 | ],
66 | message: "ShowSomeProgress Version #{version} 🚀"
67 | )
68 | end
69 |
70 | desc "Runs tests"
71 | lane :tests do
72 | # Perform iOS Tests
73 | scan(
74 | project: "ShowSomeProgress.xcodeproj",
75 | scheme: "ShowSomeProgress-iOS",
76 | clean: true
77 | )
78 | # Perform tvOS Tests
79 | scan(
80 | project: "ShowSomeProgress.xcodeproj",
81 | scheme: "ShowSomeProgress-tvOS",
82 | clean: true
83 | )
84 | # Perform macOS Tests
85 | spm(command: "test")
86 | # Delete SPM build artifacts
87 | spm(command: "clean")
88 | end
89 |
90 | desc "Run Dependency-Manager compatibility tests"
91 | lane :compatibilityTests do
92 | # Carthage build to ensure Carthage compatibility
93 | carthage(
94 | command: "build",
95 | no_skip_current: true,
96 | cache_builds: true
97 | )
98 | # Pod lib lint to ensure CocoaPods compatibility
99 | pod_lib_lint(allow_warnings: true)
100 | # SPM Build to ensure Swift Package Manager compatibility
101 | spm(command: "build")
102 | # Delete SPM build artifacts
103 | spm(command: "clean")
104 | end
105 |
106 | end
107 |
--------------------------------------------------------------------------------
/Sources/OrbitActivityIndicatorView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OrbitActivityIndicatorView.swift
3 | // ShowSomeProgress-iOS
4 | //
5 | // Created by Alexander Kasimir on 06.08.19.
6 | // Copyright © 2019 ShowSomeProgress. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @IBDesignable public class OrbitActivityIndicatorView: UIView, AnimatedActivityUIView {
12 |
13 | public var timer: Timer?
14 | public var frameRate: TimeInterval = 1/30
15 | public var animationProgress: CGFloat = 0.0
16 |
17 | override public func draw(_ rect: CGRect) {
18 | let colorParts = tintColor.components
19 | ActivityStyleKit.drawOrbitIndicator(frame: rect,
20 | resizing: .aspectFit,
21 | animationProgress: animationProgress,
22 | progressColorRed: colorParts.red,
23 | progressColorGreen: colorParts.green,
24 | progressColorBlue: colorParts.blue)
25 | }
26 |
27 | }
28 |
29 | @IBDesignable public class OrbitActivityIndicatorView2: UIView, AnimatedActivityUIView {
30 |
31 | public var timer: Timer?
32 | public var frameRate: TimeInterval = 1/30
33 | public var animationProgress: CGFloat = 0.0
34 |
35 | override public func draw(_ rect: CGRect) {
36 | let colorParts = tintColor.components
37 | ActivityStyleKit.drawOrbitIndicator2(frame: rect,
38 | resizing: .aspectFit,
39 | animationProgress: animationProgress,
40 | progressColorRed: colorParts.red,
41 | progressColorGreen: colorParts.green,
42 | progressColorBlue: colorParts.blue)
43 | }
44 | }
45 |
46 | @IBDesignable public class OrbitActivityIndicatorView3: UIView, AnimatedActivityUIView {
47 |
48 | public var timer: Timer?
49 | public var frameRate: TimeInterval = 1/30
50 | public var animationProgress: CGFloat = 0.0
51 |
52 | override public func draw(_ rect: CGRect) {
53 | let colorParts = tintColor.components
54 | ActivityStyleKit.drawOrbitIndicator3(frame: rect,
55 | resizing: .aspectFit,
56 | animationProgress: animationProgress,
57 | progressColorRed: colorParts.red,
58 | progressColorGreen: colorParts.green,
59 | progressColorBlue: colorParts.blue)
60 | }
61 | }
62 |
63 | @IBDesignable public class GearActivityIndicatorView: UIView, AnimatedActivityUIView {
64 |
65 | public var timer: Timer?
66 | public var frameRate: TimeInterval = 1/30
67 | public var animationProgress: CGFloat = 0.0
68 |
69 | override public func draw(_ rect: CGRect) {
70 | let colorParts = tintColor.components
71 | ActivityStyleKit.drawTripleGears(frame: rect,
72 | resizing: .aspectFit,
73 | animationProgress: animationProgress,
74 | progressColorRed: colorParts.red,
75 | progressColorGreen: colorParts.green,
76 | progressColorBlue: colorParts.blue)
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at alexander@kasimir.at. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/Sources/AnimationHelper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AnimationHelper.swift
3 | // AnimationTest
4 | //
5 | // Created by Alexander Kasimir on 29.07.19.
6 | // Copyright © 2019 Alexander Kasimir. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | protocol Progressable: CALayer {
12 | var progress: CGFloat { get set }
13 | var progressColor: UIColor { get set }
14 | var showTriangle: Bool { get set }
15 | }
16 |
17 | public class ProgressAnimationLayer: CALayer, Progressable {
18 | @NSManaged var progress: CGFloat
19 | private static let keyName = "progress"
20 | var progressColor: UIColor = UIColor.blue
21 | var showTriangle: Bool = false
22 |
23 | override init() {
24 | super.init()
25 | progress = 0
26 | needsDisplayOnBoundsChange = true
27 | }
28 |
29 | override init(layer: Any) {
30 | super.init(layer: layer)
31 | if let layer = layer as? Progressable {
32 | progress = layer.progress
33 | progressColor = layer.progressColor
34 | showTriangle = layer.showTriangle
35 | }
36 | }
37 |
38 | override public class func needsDisplay(forKey key: (String?)) -> Bool {
39 | guard let key = key else { return false }
40 | if key == keyName {
41 | return true
42 | } else {
43 | return super.needsDisplay(forKey: key)
44 | }
45 | }
46 |
47 | override public func action(forKey event: String) -> CAAction? {
48 | if event == ProgressAnimationLayer.keyName {
49 | let animation = CABasicAnimation(keyPath: event)
50 | animation.fromValue = self.presentation()?.value(forKey: event)
51 | return animation
52 | } else {
53 | return super.action(forKey: event)
54 | }
55 | }
56 |
57 | required init?(coder aDecoder: NSCoder) {
58 | super.init(coder: aDecoder)
59 | fatalError("init(coder:) has not been implemented")
60 | }
61 | }
62 |
63 | protocol AnimatedUIView: UIView {
64 | var animatedLayer: Progressable { get set }
65 | var progress: CGFloat { get set }
66 | var progressColor: UIColor { get set }
67 | var showTriangle: Bool { get set }
68 | var stateKeyName: String { get set }
69 | }
70 |
71 | extension AnimatedUIView {
72 |
73 | func setupAnimationLayer(progressColor: UIColor, showTriangle: Bool = false) {
74 | guard self.layer.sublayers == nil || self.layer.sublayers?.contains(animatedLayer) == false else { return }
75 | animatedLayer.contentsScale = UIScreen.main.scale
76 | animatedLayer.frame = self.bounds
77 | animatedLayer.setValue(false, forKey: stateKeyName)
78 | animatedLayer.progressColor = progressColor
79 | animatedLayer.showTriangle = showTriangle
80 |
81 | self.layer.addSublayer(animatedLayer)
82 | animatedLayer.setNeedsDisplay()
83 | }
84 |
85 | internal func updateValue() {
86 | // in the storyboard preview the state is not set
87 | guard let layerState = ((animatedLayer.value(forKey: stateKeyName) as AnyObject).boolValue) else {
88 | animatedLayer.progress = progress
89 | animatedLayer.progressColor = self.progressColor
90 | animatedLayer.showTriangle = self.showTriangle
91 | animatedLayer.setValue(false, forKey: stateKeyName)
92 | return
93 | }
94 |
95 | let timing: CAMediaTimingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
96 | CATransaction.begin()
97 | CATransaction.setAnimationTimingFunction(timing)
98 | animatedLayer.progress = progress
99 | animatedLayer.progressColor = self.progressColor
100 | animatedLayer.showTriangle = self.showTriangle
101 |
102 | CATransaction.commit()
103 | animatedLayer.setValue(!layerState, forKey: stateKeyName)
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | Progress Indicators and Activity Views for iOS Apps
26 |
27 |
28 | ## Features
29 |
30 | - [x] Storyboard compatible, configure apprearance with the property inspector.
31 | - [x] fully animated, just set a new progress value and the view will update itself smoothly
32 |
33 | ## Currenty Implemented Progress Indicators
34 |
35 | `CircleProgressView` - A circular indicator
36 |
37 | 
38 |
39 | `BarProgressView` - A bar indicator
40 |
41 | 
42 |
43 | ### Configurable properties:
44 | * `progress` - progress value - 0.0 - 1.0
45 | * `progressColor` - UIColor of the progress indicator
46 | * `showTriangle` - Bool, selects visibility of the small triangle
47 |
48 | ## Currently Implemented Activity Indicators
49 |
50 | `OrbitActivityIndicatorView` - Shows a simplifed planetary system during Activity
51 |
52 | 
53 |
54 | `OrbitActivityIndicatorView2` - Shows a planetary system during Activity
55 |
56 | 
57 |
58 | `OrbitActivityIndicatorView3` - Shows chasing dots system during Activity
59 |
60 | 
61 |
62 | `GearActivityIndicatorView` - Shows three gears during Activity
63 |
64 | 
65 |
66 | ### Configurable properties:
67 | * `tintColor` - color of the view
68 |
69 | ## Usage
70 |
71 | 
72 |
73 | Just import the framework and use the views like you would use `UIProgressView`
74 |
75 | ```swift
76 | import UIKit
77 | import ShowSomeProgress
78 |
79 | class ViewController: UIViewController {
80 |
81 | @IBOutlet weak var circleProgressView: CircleProgressView!
82 |
83 | @IBAction func setRandomValueTapped(_ sender: Any) {
84 | circleProgressView.progress = CGFloat(Double.random(in: 0...1))
85 | }
86 | }
87 | ```
88 |
89 | ## Example
90 |
91 | The example application is the best way to see `ShowSomeProgress` in action. Simply open the `ShowSomeProgress.xcodeproj` and run the `Example` scheme.
92 |
93 | 
94 |
95 |
96 | ## Installation
97 |
107 |
108 | ### Carthage
109 |
110 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
111 |
112 | To integrate ShowSomeProgress into your Xcode project using Carthage, specify it in your `Cartfile`:
113 |
114 | ```ogdl
115 | github "stoneburner/ShowSomeProgress"
116 | ```
117 |
118 | Run `carthage update` to build the framework and drag the built `ShowSomeProgress.framework` into your Xcode project.
119 |
120 | On your application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase” and add the Framework path as mentioned in [Carthage Getting started Step 4, 5 and 6](https://github.com/Carthage/Carthage/blob/master/README.md#if-youre-building-for-ios-tvos-or-watchos)
121 |
122 | ### Swift Package Manager
123 |
124 | To integrate using Apple's [Swift Package Manager](https://swift.org/package-manager/), add the following as a dependency to your `Package.swift`:
125 |
126 | ```swift
127 | dependencies: [
128 | .package(url: "https://github.com/stoneburner/ShowSomeProgress.git", from: "1.0.0")
129 | ]
130 | ```
131 |
132 | ### Manually
133 |
134 | If you prefer not to use any of the aforementioned dependency managers, you can integrate ShowSomeProgress into your project manually. Simply drag the `Sources` Folder into your Xcode project.
135 |
136 | ## Contributing
137 | Contributions are very welcome 🙌
138 |
139 | ## License
140 |
141 | ```
142 | ShowSomeProgress
143 | Copyright (c) 2019 ShowSomeProgress alexander@kasimir.at
144 |
145 | Permission is hereby granted, free of charge, to any person obtaining a copy
146 | of this software and associated documentation files (the "Software"), to deal
147 | in the Software without restriction, including without limitation the rights
148 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
149 | copies of the Software, and to permit persons to whom the Software is
150 | furnished to do so, subject to the following conditions:
151 |
152 | The above copyright notice and this permission notice shall be included in
153 | all copies or substantial portions of the Software.
154 |
155 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
157 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
158 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
159 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
160 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
161 | THE SOFTWARE.
162 | ```
163 |
--------------------------------------------------------------------------------
/Sources/stylekit/ProgressStyleKit.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressStyleKit.swift
3 | // ShowSomeProgress
4 | //
5 | // Created by Alexander Kasimir on 04.08.19.
6 | // Copyright © 2019 Alexander Kasimir. All rights reserved.
7 | //
8 | // Generated by PaintCode
9 | // http://www.paintcodeapp.com
10 | //
11 |
12 |
13 |
14 | import UIKit
15 |
16 | public class ProgressStyleKit : NSObject {
17 |
18 | //// Drawing Methods
19 |
20 | @objc dynamic public class func drawProgressBarDisplay(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 136, height: 16), resizing: ResizingBehavior = .aspectFit, progress: CGFloat = 0.723, showTriangle: Bool = true, progressColorRed: CGFloat = 0, progressColorGreen: CGFloat = 0.475, progressColorBlue: CGFloat = 1) {
21 | //// General Declarations
22 | let context = UIGraphicsGetCurrentContext()!
23 |
24 | //// Resize to Target Frame
25 | context.saveGState()
26 | let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 136, height: 16), target: targetFrame)
27 | context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
28 | context.scaleBy(x: resizedFrame.width / 136, y: resizedFrame.height / 16)
29 | let resizedShadowScale: CGFloat = min(resizedFrame.width / 136, resizedFrame.height / 16)
30 |
31 |
32 |
33 | //// Shadow Declarations
34 | let shadow = NSShadow()
35 | shadow.shadowColor = UIColor.black.withAlphaComponent(0.23)
36 | shadow.shadowOffset = CGSize(width: 1, height: 1)
37 | shadow.shadowBlurRadius = 1
38 |
39 | //// Variable Declarations
40 | let percentText = "\(Int(round(round(progress * 100))))" + "%"
41 | let progressWidth: CGFloat = 136 * progress
42 | let progressWidthOffset: CGFloat = progressWidth - 3.5
43 | let progressVisible = progress > 0
44 | let progressBarColor = UIColor(red: progressColorRed, green: progressColorGreen, blue: progressColorBlue, alpha: 1)
45 |
46 | //// Rectangle 2 Drawing
47 | context.saveGState()
48 | context.setAlpha(0.2)
49 | context.beginTransparencyLayer(auxiliaryInfo: nil)
50 |
51 | let rectangle2Path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 136, height: 9), cornerRadius: 3)
52 | context.saveGState()
53 | context.setShadow(offset: CGSize(width: shadow.shadowOffset.width * resizedShadowScale, height: shadow.shadowOffset.height * resizedShadowScale), blur: shadow.shadowBlurRadius * resizedShadowScale, color: (shadow.shadowColor as! UIColor).cgColor)
54 | progressBarColor.setFill()
55 | rectangle2Path.fill()
56 | context.restoreGState()
57 |
58 |
59 | context.endTransparencyLayer()
60 | context.restoreGState()
61 |
62 |
63 | //// Group
64 | context.saveGState()
65 | context.beginTransparencyLayer(auxiliaryInfo: nil)
66 |
67 | //// Clip Rectangle 3
68 | let rectangle3Path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 136, height: 9), cornerRadius: 3)
69 | rectangle3Path.addClip()
70 |
71 |
72 | if (progressVisible) {
73 | //// Rectangle Drawing
74 | let rectanglePath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: progressWidth, height: 9), cornerRadius: 3)
75 | progressBarColor.setFill()
76 | rectanglePath.fill()
77 | }
78 |
79 |
80 | context.endTransparencyLayer()
81 | context.restoreGState()
82 |
83 |
84 | //// Text Drawing
85 | let textRect = CGRect(x: 3, y: 0, width: 130, height: 9)
86 | let textStyle = NSMutableParagraphStyle()
87 | textStyle.alignment = .center
88 | let textFontAttributes = [
89 | .font: UIFont.systemFont(ofSize: 7),
90 | .foregroundColor: UIColor.black,
91 | .paragraphStyle: textStyle,
92 | ] as [NSAttributedString.Key: Any]
93 |
94 | let textTextHeight: CGFloat = percentText.boundingRect(with: CGSize(width: textRect.width, height: CGFloat.infinity), options: .usesLineFragmentOrigin, attributes: textFontAttributes, context: nil).height
95 | context.saveGState()
96 | context.clip(to: textRect)
97 | percentText.draw(in: CGRect(x: textRect.minX, y: textRect.minY + (textRect.height - textTextHeight) / 2, width: textRect.width, height: textTextHeight), withAttributes: textFontAttributes)
98 | context.restoreGState()
99 |
100 |
101 | if (showTriangle) {
102 | //// Polygon Drawing
103 | context.saveGState()
104 | context.translateBy(x: progressWidthOffset, y: 9.5)
105 |
106 | let polygonPath = UIBezierPath()
107 | polygonPath.move(to: CGPoint(x: 3.5, y: 0))
108 | polygonPath.addLine(to: CGPoint(x: 6.53, y: 5.25))
109 | polygonPath.addLine(to: CGPoint(x: 0.47, y: 5.25))
110 | polygonPath.close()
111 | progressBarColor.setFill()
112 | polygonPath.fill()
113 |
114 | context.restoreGState()
115 | }
116 |
117 | context.restoreGState()
118 |
119 | }
120 |
121 | @objc dynamic public class func drawProgressCircleDisplay(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 140, height: 140), resizing: ResizingBehavior = .aspectFit, progress: CGFloat = 0.723, showTriangle: Bool = true, progressColorRed: CGFloat = 0, progressColorGreen: CGFloat = 0.475, progressColorBlue: CGFloat = 1) {
122 | //// General Declarations
123 | let context = UIGraphicsGetCurrentContext()!
124 |
125 | //// Resize to Target Frame
126 | context.saveGState()
127 | let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 140, height: 140), target: targetFrame)
128 | context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
129 | context.scaleBy(x: resizedFrame.width / 140, y: resizedFrame.height / 140)
130 | let resizedShadowScale: CGFloat = min(resizedFrame.width / 140, resizedFrame.height / 140)
131 |
132 |
133 |
134 | //// Shadow Declarations
135 | let shadow = NSShadow()
136 | shadow.shadowColor = UIColor.black.withAlphaComponent(0.23)
137 | shadow.shadowOffset = CGSize(width: 1, height: 1)
138 | shadow.shadowBlurRadius = 1
139 |
140 | //// Variable Declarations
141 | let progressEndAngle: CGFloat = progress == 1 ? 0.001 : 360 * (1 - progress)
142 | let percentText = "\(Int(round(round(progress * 100))))" + "%"
143 | let progressBarColor = UIColor(red: progressColorRed, green: progressColorGreen, blue: progressColorBlue, alpha: 1)
144 |
145 | //// Text Drawing
146 | let textRect = CGRect(x: 10, y: 56, width: 130, height: 28)
147 | let textStyle = NSMutableParagraphStyle()
148 | textStyle.alignment = .center
149 | let textFontAttributes = [
150 | .font: UIFont.systemFont(ofSize: 31),
151 | .foregroundColor: UIColor.black,
152 | .paragraphStyle: textStyle,
153 | ] as [NSAttributedString.Key: Any]
154 |
155 | let textTextHeight: CGFloat = percentText.boundingRect(with: CGSize(width: textRect.width, height: CGFloat.infinity), options: .usesLineFragmentOrigin, attributes: textFontAttributes, context: nil).height
156 | context.saveGState()
157 | context.clip(to: textRect)
158 | percentText.draw(in: CGRect(x: textRect.minX, y: textRect.minY + (textRect.height - textTextHeight) / 2, width: textRect.width, height: textTextHeight), withAttributes: textFontAttributes)
159 | context.restoreGState()
160 |
161 |
162 | //// progressRingBackground Drawing
163 | context.saveGState()
164 | context.translateBy(x: 70, y: 70)
165 | context.rotate(by: -90 * CGFloat.pi/180)
166 |
167 | context.saveGState()
168 | context.setAlpha(0.2)
169 | context.beginTransparencyLayer(auxiliaryInfo: nil)
170 |
171 | let progressRingBackgroundPath = UIBezierPath(ovalIn: CGRect(x: -60, y: -60, width: 120, height: 120))
172 | context.saveGState()
173 | context.setShadow(offset: CGSize(width: shadow.shadowOffset.width * resizedShadowScale, height: shadow.shadowOffset.height * resizedShadowScale), blur: shadow.shadowBlurRadius * resizedShadowScale, color: (shadow.shadowColor as! UIColor).cgColor)
174 | progressBarColor.setStroke()
175 | progressRingBackgroundPath.lineWidth = 7.5
176 | progressRingBackgroundPath.stroke()
177 | context.restoreGState()
178 |
179 | context.endTransparencyLayer()
180 | context.restoreGState()
181 |
182 | context.restoreGState()
183 |
184 |
185 | //// Oval Drawing
186 | context.saveGState()
187 | context.translateBy(x: 70, y: 70)
188 | context.rotate(by: -90 * CGFloat.pi/180)
189 |
190 | let ovalRect = CGRect(x: -60, y: -60, width: 120, height: 120)
191 | let ovalPath = UIBezierPath()
192 | ovalPath.addArc(withCenter: CGPoint(x: ovalRect.midX, y: ovalRect.midY), radius: ovalRect.width / 2, startAngle: 0 * CGFloat.pi/180, endAngle: -progressEndAngle * CGFloat.pi/180, clockwise: true)
193 |
194 | context.saveGState()
195 | context.setShadow(offset: CGSize(width: shadow.shadowOffset.width * resizedShadowScale, height: shadow.shadowOffset.height * resizedShadowScale), blur: shadow.shadowBlurRadius * resizedShadowScale, color: (shadow.shadowColor as! UIColor).cgColor)
196 | progressBarColor.setStroke()
197 | ovalPath.lineWidth = 7.5
198 | ovalPath.lineCapStyle = .round
199 | ovalPath.stroke()
200 | context.restoreGState()
201 |
202 | context.restoreGState()
203 |
204 |
205 | if (showTriangle) {
206 | //// Polygon Drawing
207 | context.saveGState()
208 | context.translateBy(x: 70, y: 70)
209 | context.rotate(by: -progressEndAngle * CGFloat.pi/180)
210 |
211 | let polygonPath = UIBezierPath()
212 | polygonPath.move(to: CGPoint(x: 0, y: -54))
213 | polygonPath.addLine(to: CGPoint(x: 5.63, y: -43.5))
214 | polygonPath.addLine(to: CGPoint(x: -5.63, y: -43.5))
215 | polygonPath.close()
216 | progressBarColor.setFill()
217 | polygonPath.fill()
218 |
219 | context.restoreGState()
220 | }
221 |
222 | context.restoreGState()
223 |
224 | }
225 |
226 | @objc dynamic public class func drawProgressCircleDisplayWithTicks(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 140, height: 140), resizing: ResizingBehavior = .aspectFit, progress: CGFloat = 0.723, showTriangle: Bool = true, progressColorRed: CGFloat = 0, progressColorGreen: CGFloat = 0.475, progressColorBlue: CGFloat = 1) {
227 | //// General Declarations
228 | let context = UIGraphicsGetCurrentContext()!
229 |
230 | //// Resize to Target Frame
231 | context.saveGState()
232 | let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 140, height: 140), target: targetFrame)
233 | context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
234 | context.scaleBy(x: resizedFrame.width / 140, y: resizedFrame.height / 140)
235 | let resizedShadowScale: CGFloat = min(resizedFrame.width / 140, resizedFrame.height / 140)
236 |
237 |
238 |
239 | //// Shadow Declarations
240 | let shadow = NSShadow()
241 | shadow.shadowColor = UIColor.black.withAlphaComponent(0.23)
242 | shadow.shadowOffset = CGSize(width: 1, height: 1)
243 | shadow.shadowBlurRadius = 1
244 |
245 | //// Variable Declarations
246 | let progressEndAngle: CGFloat = progress == 1 ? 0.001 : 360 * (1 - progress)
247 | let percentText = "\(Int(round(round(progress * 100))))" + "%"
248 | let progressBarColor = UIColor(red: progressColorRed, green: progressColorGreen, blue: progressColorBlue, alpha: 1)
249 |
250 | //// Text Drawing
251 | let textRect = CGRect(x: 10, y: 56, width: 130, height: 28)
252 | let textStyle = NSMutableParagraphStyle()
253 | textStyle.alignment = .center
254 | let textFontAttributes = [
255 | .font: UIFont.systemFont(ofSize: 31),
256 | .foregroundColor: UIColor.black,
257 | .paragraphStyle: textStyle,
258 | ] as [NSAttributedString.Key: Any]
259 |
260 | let textTextHeight: CGFloat = percentText.boundingRect(with: CGSize(width: textRect.width, height: CGFloat.infinity), options: .usesLineFragmentOrigin, attributes: textFontAttributes, context: nil).height
261 | context.saveGState()
262 | context.clip(to: textRect)
263 | percentText.draw(in: CGRect(x: textRect.minX, y: textRect.minY + (textRect.height - textTextHeight) / 2, width: textRect.width, height: textTextHeight), withAttributes: textFontAttributes)
264 | context.restoreGState()
265 |
266 |
267 | //// progressRingBackground Drawing
268 | context.saveGState()
269 | context.translateBy(x: 70, y: 70)
270 | context.rotate(by: -90 * CGFloat.pi/180)
271 |
272 | let progressRingBackgroundPath = UIBezierPath(ovalIn: CGRect(x: -60, y: -60, width: 120, height: 120))
273 | context.saveGState()
274 | context.setShadow(offset: CGSize(width: shadow.shadowOffset.width * resizedShadowScale, height: shadow.shadowOffset.height * resizedShadowScale), blur: shadow.shadowBlurRadius * resizedShadowScale, color: (shadow.shadowColor as! UIColor).cgColor)
275 | UIColor.black.setStroke()
276 | progressRingBackgroundPath.lineWidth = 5.5
277 | context.saveGState()
278 | context.setLineDash(phase: 0, lengths: [1, 5])
279 | progressRingBackgroundPath.stroke()
280 | context.restoreGState()
281 | context.restoreGState()
282 |
283 | context.restoreGState()
284 |
285 |
286 | //// Oval Drawing
287 | context.saveGState()
288 | context.translateBy(x: 70, y: 70)
289 | context.rotate(by: -90 * CGFloat.pi/180)
290 |
291 | let ovalRect = CGRect(x: -60, y: -60, width: 120, height: 120)
292 | let ovalPath = UIBezierPath()
293 | ovalPath.addArc(withCenter: CGPoint(x: ovalRect.midX, y: ovalRect.midY), radius: ovalRect.width / 2, startAngle: 0 * CGFloat.pi/180, endAngle: -progressEndAngle * CGFloat.pi/180, clockwise: true)
294 |
295 | context.saveGState()
296 | context.setShadow(offset: CGSize(width: shadow.shadowOffset.width * resizedShadowScale, height: shadow.shadowOffset.height * resizedShadowScale), blur: shadow.shadowBlurRadius * resizedShadowScale, color: (shadow.shadowColor as! UIColor).cgColor)
297 | progressBarColor.setStroke()
298 | ovalPath.lineWidth = 7.5
299 | ovalPath.lineCapStyle = .round
300 | ovalPath.stroke()
301 | context.restoreGState()
302 |
303 | context.restoreGState()
304 |
305 |
306 | if (showTriangle) {
307 | //// Polygon Drawing
308 | context.saveGState()
309 | context.translateBy(x: 70, y: 70)
310 | context.rotate(by: -progressEndAngle * CGFloat.pi/180)
311 |
312 | let polygonPath = UIBezierPath()
313 | polygonPath.move(to: CGPoint(x: 0, y: -54))
314 | polygonPath.addLine(to: CGPoint(x: 5.63, y: -43.5))
315 | polygonPath.addLine(to: CGPoint(x: -5.63, y: -43.5))
316 | polygonPath.close()
317 | progressBarColor.setFill()
318 | polygonPath.fill()
319 |
320 | context.restoreGState()
321 | }
322 |
323 | context.restoreGState()
324 |
325 | }
326 |
327 |
328 |
329 |
330 | @objc(ProgressStyleKitResizingBehavior)
331 | public enum ResizingBehavior: Int {
332 | case aspectFit /// The content is proportionally resized to fit into the target rectangle.
333 | case aspectFill /// The content is proportionally resized to completely fill the target rectangle.
334 | case stretch /// The content is stretched to match the entire target rectangle.
335 | case center /// The content is centered in the target rectangle, but it is NOT resized.
336 |
337 | public func apply(rect: CGRect, target: CGRect) -> CGRect {
338 | if rect == target || target == CGRect.zero {
339 | return rect
340 | }
341 |
342 | var scales = CGSize.zero
343 | scales.width = abs(target.width / rect.width)
344 | scales.height = abs(target.height / rect.height)
345 |
346 | switch self {
347 | case .aspectFit:
348 | scales.width = min(scales.width, scales.height)
349 | scales.height = scales.width
350 | case .aspectFill:
351 | scales.width = max(scales.width, scales.height)
352 | scales.height = scales.width
353 | case .stretch:
354 | break
355 | case .center:
356 | scales.width = 1
357 | scales.height = 1
358 | }
359 |
360 | var result = rect.standardized
361 | result.size.width *= scales.width
362 | result.size.height *= scales.height
363 | result.origin.x = target.minX + (target.width - result.width) / 2
364 | result.origin.y = target.minY + (target.height - result.height) / 2
365 | return result
366 | }
367 | }
368 | }
369 |
--------------------------------------------------------------------------------
/Example/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
--------------------------------------------------------------------------------
/Sources/stylekit/ActivityStyleKit.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ActivityStyleKit.swift
3 | // ShowSomeProgress
4 | //
5 | // Created by Alexander Kasimir on 06.08.19.
6 | // Copyright © 2019 Alexander Kasimir. All rights reserved.
7 | //
8 | // Generated by PaintCode
9 | // http://www.paintcodeapp.com
10 | //
11 |
12 |
13 |
14 | import UIKit
15 |
16 | public class ActivityStyleKit : NSObject {
17 |
18 | //// Drawing Methods
19 |
20 | @objc dynamic public class func drawOrbitIndicator(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 78, height: 78), resizing: ResizingBehavior = .aspectFit, animationProgress: CGFloat = 0, progressColorRed: CGFloat = 0, progressColorGreen: CGFloat = 0.475, progressColorBlue: CGFloat = 1) {
21 | //// General Declarations
22 | let context = UIGraphicsGetCurrentContext()!
23 |
24 | //// Resize to Target Frame
25 | context.saveGState()
26 | let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 78, height: 78), target: targetFrame)
27 | context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
28 | context.scaleBy(x: resizedFrame.width / 78, y: resizedFrame.height / 78)
29 |
30 |
31 |
32 | //// Variable Declarations
33 | let rotationOnce: CGFloat = 360 * animationProgress
34 | let rotationTwice: CGFloat = 360 * 2 * animationProgress
35 | let rotationThrice: CGFloat = 360 * 3 * animationProgress
36 | let progressBarColor = UIColor(red: progressColorRed, green: progressColorGreen, blue: progressColorBlue, alpha: 1)
37 |
38 | //// Outer Drawing
39 | context.saveGState()
40 | context.translateBy(x: 38.5, y: 38.5)
41 | context.rotate(by: -rotationOnce * CGFloat.pi/180)
42 |
43 | let outerPath = UIBezierPath(ovalIn: CGRect(x: -3.57, y: -33.42, width: 7, height: 7))
44 | progressBarColor.setFill()
45 | outerPath.fill()
46 |
47 | context.restoreGState()
48 |
49 |
50 | //// Middle Drawing
51 | context.saveGState()
52 | context.translateBy(x: 38.5, y: 38.5)
53 | context.rotate(by: -rotationTwice * CGFloat.pi/180)
54 |
55 | let middlePath = UIBezierPath(ovalIn: CGRect(x: -3.5, y: -23.5, width: 7, height: 7))
56 | progressBarColor.setFill()
57 | middlePath.fill()
58 |
59 | context.restoreGState()
60 |
61 |
62 | //// Inner Drawing
63 | context.saveGState()
64 | context.translateBy(x: 38.5, y: 38.5)
65 | context.rotate(by: -rotationThrice * CGFloat.pi/180)
66 |
67 | let innerPath = UIBezierPath(ovalIn: CGRect(x: -3.5, y: -13.5, width: 7, height: 7))
68 | progressBarColor.setFill()
69 | innerPath.fill()
70 |
71 | context.restoreGState()
72 |
73 |
74 | //// Group
75 | //// OuterRing Drawing
76 | let outerRingPath = UIBezierPath(ovalIn: CGRect(x: 8.5, y: 8.5, width: 60, height: 60))
77 | progressBarColor.setStroke()
78 | outerRingPath.lineWidth = 1
79 | outerRingPath.stroke()
80 |
81 |
82 | //// MiddleRing Drawing
83 | let middleRingPath = UIBezierPath(ovalIn: CGRect(x: 18.5, y: 18.5, width: 40, height: 40))
84 | progressBarColor.setStroke()
85 | middleRingPath.lineWidth = 1
86 | middleRingPath.stroke()
87 |
88 |
89 | //// InnerRing Drawing
90 | let innerRingPath = UIBezierPath(ovalIn: CGRect(x: 28.5, y: 28.5, width: 20, height: 20))
91 | progressBarColor.setStroke()
92 | innerRingPath.lineWidth = 1
93 | innerRingPath.stroke()
94 |
95 | context.restoreGState()
96 |
97 | }
98 |
99 | @objc dynamic public class func drawOrbitIndicator2(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 78, height: 78), resizing: ResizingBehavior = .aspectFit, animationProgress: CGFloat = 0, progressColorRed: CGFloat = 0, progressColorGreen: CGFloat = 0.475, progressColorBlue: CGFloat = 1) {
100 | //// General Declarations
101 | let context = UIGraphicsGetCurrentContext()!
102 |
103 | //// Resize to Target Frame
104 | context.saveGState()
105 | let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 78, height: 78), target: targetFrame)
106 | context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
107 | context.scaleBy(x: resizedFrame.width / 78, y: resizedFrame.height / 78)
108 |
109 |
110 |
111 | //// Variable Declarations
112 | let rotationOnce: CGFloat = 360 * animationProgress
113 | let rotationTwice: CGFloat = 360 * 2 * animationProgress
114 | let rotationThrice: CGFloat = 360 * 3 * animationProgress
115 | let progressBarColor = UIColor(red: progressColorRed, green: progressColorGreen, blue: progressColorBlue, alpha: 1)
116 |
117 | //// Outer Drawing
118 | context.saveGState()
119 | context.translateBy(x: 39.01, y: 38.89)
120 | context.rotate(by: -rotationOnce * CGFloat.pi/180)
121 |
122 | let outerPath = UIBezierPath(ovalIn: CGRect(x: -3.52, y: -36.26, width: 7, height: 7))
123 | progressBarColor.setFill()
124 | outerPath.fill()
125 |
126 | context.restoreGState()
127 |
128 |
129 | //// Inner Drawing
130 | context.saveGState()
131 | context.translateBy(x: 39.01, y: 38.89)
132 | context.rotate(by: -rotationThrice * CGFloat.pi/180)
133 |
134 | let innerPath = UIBezierPath(ovalIn: CGRect(x: -2.51, y: -14.52, width: 5, height: 5))
135 | progressBarColor.setFill()
136 | innerPath.fill()
137 |
138 | context.restoreGState()
139 |
140 |
141 | //// Group 2
142 | context.saveGState()
143 | context.translateBy(x: 39.01, y: 38.89)
144 | context.rotate(by: -rotationTwice * CGFloat.pi/180)
145 |
146 |
147 |
148 | //// Middle Drawing
149 | context.saveGState()
150 | context.translateBy(x: 0.02, y: -0.26)
151 | context.rotate(by: -720 * CGFloat.pi/180)
152 |
153 | let middlePath = UIBezierPath(ovalIn: CGRect(x: -2.5, y: -22.5, width: 5, height: 5))
154 | progressBarColor.setFill()
155 | middlePath.fill()
156 |
157 | context.restoreGState()
158 |
159 |
160 | //// Moon Drawing
161 | context.saveGState()
162 | context.translateBy(x: 0.1, y: -20.38)
163 | context.rotate(by: -rotationThrice * CGFloat.pi/180)
164 |
165 | let moonPath = UIBezierPath(ovalIn: CGRect(x: -1.14, y: -5.47, width: 2, height: 2))
166 | progressBarColor.setFill()
167 | moonPath.fill()
168 |
169 | context.restoreGState()
170 |
171 |
172 |
173 | context.restoreGState()
174 |
175 |
176 | //// Center Drawing
177 | let centerPath = UIBezierPath(ovalIn: CGRect(x: 34.5, y: 34.5, width: 9, height: 9))
178 | progressBarColor.setFill()
179 | centerPath.fill()
180 |
181 |
182 | //// Group
183 | //// OuterRing Drawing
184 | let outerRingPath = UIBezierPath(ovalIn: CGRect(x: 5.9, y: 6.29, width: 66.12, height: 65.62))
185 | progressBarColor.setStroke()
186 | outerRingPath.lineWidth = 1
187 | outerRingPath.stroke()
188 |
189 |
190 | //// MiddleRing Drawing
191 | let middleRingPath = UIBezierPath(ovalIn: CGRect(x: 18.47, y: 18.66, width: 40.87, height: 40.87))
192 | progressBarColor.setStroke()
193 | middleRingPath.lineWidth = 1
194 | middleRingPath.stroke()
195 |
196 |
197 | //// InnerRing Drawing
198 | let innerRingPath = UIBezierPath(ovalIn: CGRect(x: 27, y: 27, width: 24, height: 24))
199 | progressBarColor.setStroke()
200 | innerRingPath.lineWidth = 1
201 | innerRingPath.stroke()
202 |
203 | context.restoreGState()
204 |
205 | }
206 |
207 | @objc dynamic public class func drawOrbitIndicator3(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 78, height: 78), resizing: ResizingBehavior = .aspectFit, animationProgress: CGFloat = 0, progressColorRed: CGFloat = 0, progressColorGreen: CGFloat = 0.475, progressColorBlue: CGFloat = 1) {
208 | //// General Declarations
209 | let context = UIGraphicsGetCurrentContext()!
210 |
211 | //// Resize to Target Frame
212 | context.saveGState()
213 | let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 78, height: 78), target: targetFrame)
214 | context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
215 | context.scaleBy(x: resizedFrame.width / 78, y: resizedFrame.height / 78)
216 |
217 |
218 |
219 | //// Variable Declarations
220 | let rotationOnce: CGFloat = 360 * animationProgress
221 | let rotationTwice: CGFloat = 360 * 2 * animationProgress
222 | let rotationThrice: CGFloat = 360 * 3 * animationProgress
223 | let progressBarColor = UIColor(red: progressColorRed, green: progressColorGreen, blue: progressColorBlue, alpha: 1)
224 |
225 | //// OuterRing Drawing
226 | let outerRingPath = UIBezierPath(ovalIn: CGRect(x: 9, y: 8.5, width: 60, height: 60))
227 | progressBarColor.setStroke()
228 | outerRingPath.lineWidth = 2
229 | outerRingPath.stroke()
230 |
231 |
232 | //// Outer Drawing
233 | context.saveGState()
234 | context.translateBy(x: 38.5, y: 38.5)
235 | context.rotate(by: -rotationOnce * CGFloat.pi/180)
236 |
237 | let outerPath = UIBezierPath(ovalIn: CGRect(x: -2.78, y: -33.3, width: 7, height: 7))
238 | progressBarColor.setFill()
239 | outerPath.fill()
240 |
241 | context.restoreGState()
242 |
243 |
244 | //// Outer 2 Drawing
245 | context.saveGState()
246 | context.translateBy(x: 38.5, y: 38.5)
247 | context.rotate(by: -rotationTwice * CGFloat.pi/180)
248 |
249 | let outer2Path = UIBezierPath(ovalIn: CGRect(x: -2.78, y: -33.3, width: 7, height: 7))
250 | progressBarColor.setFill()
251 | outer2Path.fill()
252 |
253 | context.restoreGState()
254 |
255 |
256 | //// Outer 3 Drawing
257 | context.saveGState()
258 | context.translateBy(x: 38.5, y: 38.5)
259 | context.rotate(by: -rotationThrice * CGFloat.pi/180)
260 |
261 | let outer3Path = UIBezierPath(ovalIn: CGRect(x: -2.78, y: -33.3, width: 7, height: 7))
262 | progressBarColor.setFill()
263 | outer3Path.fill()
264 |
265 | context.restoreGState()
266 |
267 | context.restoreGState()
268 |
269 | }
270 |
271 | @objc dynamic public class func drawTripleGears(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 168, height: 177), resizing: ResizingBehavior = .aspectFit, animationProgress: CGFloat = 0, progressColorRed: CGFloat = 0, progressColorGreen: CGFloat = 0.475, progressColorBlue: CGFloat = 1) {
272 | //// General Declarations
273 | let context = UIGraphicsGetCurrentContext()!
274 |
275 | //// Resize to Target Frame
276 | context.saveGState()
277 | let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 168, height: 177), target: targetFrame)
278 | context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
279 | context.scaleBy(x: resizedFrame.width / 168, y: resizedFrame.height / 177)
280 |
281 |
282 |
283 | //// Variable Declarations
284 | let gear1Rotation: CGFloat = animationProgress * 360 * 2
285 | let gear2Rotation: CGFloat = -(animationProgress * 360)
286 | let progressBarColor = UIColor(red: progressColorRed, green: progressColorGreen, blue: progressColorBlue, alpha: 1)
287 | let lightProgressBarColor = UIColor(red: progressColorRed + 0.2, green: progressColorGreen + 0.2, blue: progressColorBlue + 0.2, alpha: 1)
288 |
289 | //// Small Top Gear Drawing
290 | context.saveGState()
291 | context.translateBy(x: 36.02, y: 38.27)
292 | context.rotate(by: -gear1Rotation * CGFloat.pi/180)
293 |
294 | let smallTopGearPath = UIBezierPath()
295 | smallTopGearPath.move(to: CGPoint(x: -2.49, y: -33.46))
296 | smallTopGearPath.addCurve(to: CGPoint(x: 3.07, y: -24.18), controlPoint1: CGPoint(x: -2.5, y: -33.47), controlPoint2: CGPoint(x: 3.02, y: -28.06))
297 | smallTopGearPath.addCurve(to: CGPoint(x: 2.24, y: -18.71), controlPoint1: CGPoint(x: 3.09, y: -22.77), controlPoint2: CGPoint(x: 2.57, y: -20.17))
298 | smallTopGearPath.addCurve(to: CGPoint(x: 8.37, y: -16.87), controlPoint1: CGPoint(x: 4.37, y: -18.45), controlPoint2: CGPoint(x: 6.44, y: -17.83))
299 | smallTopGearPath.addCurve(to: CGPoint(x: 11.63, y: -22.88), controlPoint1: CGPoint(x: 8.86, y: -18.34), controlPoint2: CGPoint(x: 10.05, y: -21.52))
300 | smallTopGearPath.addCurve(to: CGPoint(x: 20.66, y: -26.7), controlPoint1: CGPoint(x: 14.71, y: -25.57), controlPoint2: CGPoint(x: 20.66, y: -26.7))
301 | smallTopGearPath.addLine(to: CGPoint(x: 22.07, y: -25.28))
302 | smallTopGearPath.addCurve(to: CGPoint(x: 19.37, y: -14.8), controlPoint1: CGPoint(x: 22.07, y: -25.28), controlPoint2: CGPoint(x: 22.09, y: -17.55))
303 | smallTopGearPath.addCurve(to: CGPoint(x: 14.9, y: -11.55), controlPoint1: CGPoint(x: 18.38, y: -13.79), controlPoint2: CGPoint(x: 16.16, y: -12.34))
304 | smallTopGearPath.addCurve(to: CGPoint(x: 16.03, y: -9.92), controlPoint1: CGPoint(x: 15.3, y: -11.03), controlPoint2: CGPoint(x: 15.68, y: -10.49))
305 | smallTopGearPath.addCurve(to: CGPoint(x: 17.86, y: -6.1), controlPoint1: CGPoint(x: 16.8, y: -8.7), controlPoint2: CGPoint(x: 17.41, y: -7.42))
306 | smallTopGearPath.addCurve(to: CGPoint(x: 24.37, y: -8.06), controlPoint1: CGPoint(x: 19.27, y: -6.81), controlPoint2: CGPoint(x: 22.31, y: -8.19))
307 | smallTopGearPath.addCurve(to: CGPoint(x: 33.47, y: -4.41), controlPoint1: CGPoint(x: 28.45, y: -7.79), controlPoint2: CGPoint(x: 33.47, y: -4.41))
308 | smallTopGearPath.addLine(to: CGPoint(x: 33.47, y: -2.41))
309 | smallTopGearPath.addCurve(to: CGPoint(x: 24.17, y: 3.14), controlPoint1: CGPoint(x: 33.47, y: -2.41), controlPoint2: CGPoint(x: 28.05, y: 3.1))
310 | smallTopGearPath.addCurve(to: CGPoint(x: 18.79, y: 2.31), controlPoint1: CGPoint(x: 22.78, y: 3.15), controlPoint2: CGPoint(x: 20.27, y: 2.64))
311 | smallTopGearPath.addCurve(to: CGPoint(x: 17.09, y: 8.3), controlPoint1: CGPoint(x: 18.56, y: 4.38), controlPoint2: CGPoint(x: 17.98, y: 6.41))
312 | smallTopGearPath.addCurve(to: CGPoint(x: 22.97, y: 11.46), controlPoint1: CGPoint(x: 18.62, y: 8.81), controlPoint2: CGPoint(x: 21.63, y: 9.95))
313 | smallTopGearPath.addCurve(to: CGPoint(x: 26.84, y: 20.47), controlPoint1: CGPoint(x: 25.67, y: 14.53), controlPoint2: CGPoint(x: 26.84, y: 20.47))
314 | smallTopGearPath.addLine(to: CGPoint(x: 25.44, y: 21.89))
315 | smallTopGearPath.addCurve(to: CGPoint(x: 14.94, y: 19.26), controlPoint1: CGPoint(x: 25.44, y: 21.89), controlPoint2: CGPoint(x: 17.71, y: 21.97))
316 | smallTopGearPath.addCurve(to: CGPoint(x: 11.78, y: 15.01), controlPoint1: CGPoint(x: 13.97, y: 18.33), controlPoint2: CGPoint(x: 12.6, y: 16.29))
317 | smallTopGearPath.addCurve(to: CGPoint(x: 9.98, y: 16.28), controlPoint1: CGPoint(x: 11.21, y: 15.46), controlPoint2: CGPoint(x: 10.61, y: 15.88))
318 | smallTopGearPath.addCurve(to: CGPoint(x: 6.26, y: 18.07), controlPoint1: CGPoint(x: 8.79, y: 17.02), controlPoint2: CGPoint(x: 7.54, y: 17.62))
319 | smallTopGearPath.addCurve(to: CGPoint(x: 8.12, y: 24.35), controlPoint1: CGPoint(x: 7, y: 19.56), controlPoint2: CGPoint(x: 8.24, y: 22.39))
320 | smallTopGearPath.addCurve(to: CGPoint(x: 4.49, y: 33.46), controlPoint1: CGPoint(x: 7.87, y: 28.43), controlPoint2: CGPoint(x: 4.49, y: 33.46))
321 | smallTopGearPath.addLine(to: CGPoint(x: 2.5, y: 33.47))
322 | smallTopGearPath.addCurve(to: CGPoint(x: -3.07, y: 24.18), controlPoint1: CGPoint(x: 2.5, y: 33.47), controlPoint2: CGPoint(x: -3.02, y: 28.06))
323 | smallTopGearPath.addCurve(to: CGPoint(x: -2.31, y: 19.03), controlPoint1: CGPoint(x: -3.09, y: 22.86), controlPoint2: CGPoint(x: -2.64, y: 20.52))
324 | smallTopGearPath.addCurve(to: CGPoint(x: -8.49, y: 17.21), controlPoint1: CGPoint(x: -4.45, y: 18.78), controlPoint2: CGPoint(x: -6.54, y: 18.16))
325 | smallTopGearPath.addCurve(to: CGPoint(x: -11.63, y: 22.88), controlPoint1: CGPoint(x: -9.03, y: 18.79), controlPoint2: CGPoint(x: -10.17, y: 21.61))
326 | smallTopGearPath.addCurve(to: CGPoint(x: -20.66, y: 26.7), controlPoint1: CGPoint(x: -14.71, y: 25.57), controlPoint2: CGPoint(x: -20.66, y: 26.7))
327 | smallTopGearPath.addLine(to: CGPoint(x: -22.07, y: 25.28))
328 | smallTopGearPath.addCurve(to: CGPoint(x: -19.37, y: 14.8), controlPoint1: CGPoint(x: -22.07, y: 25.28), controlPoint2: CGPoint(x: -22.09, y: 17.55))
329 | smallTopGearPath.addCurve(to: CGPoint(x: -15.18, y: 11.73), controlPoint1: CGPoint(x: -18.45, y: 13.86), controlPoint2: CGPoint(x: -16.47, y: 12.54))
330 | smallTopGearPath.addCurve(to: CGPoint(x: -16.22, y: 10.23), controlPoint1: CGPoint(x: -15.54, y: 11.25), controlPoint2: CGPoint(x: -15.89, y: 10.75))
331 | smallTopGearPath.addCurve(to: CGPoint(x: -18.11, y: 6.23), controlPoint1: CGPoint(x: -17.02, y: 8.94), controlPoint2: CGPoint(x: -17.65, y: 7.6))
332 | smallTopGearPath.addCurve(to: CGPoint(x: -24.37, y: 8.06), controlPoint1: CGPoint(x: -19.6, y: 6.96), controlPoint2: CGPoint(x: -22.42, y: 8.19))
333 | smallTopGearPath.addCurve(to: CGPoint(x: -33.47, y: 4.41), controlPoint1: CGPoint(x: -28.45, y: 7.79), controlPoint2: CGPoint(x: -33.47, y: 4.41))
334 | smallTopGearPath.addLine(to: CGPoint(x: -33.47, y: 2.41))
335 | smallTopGearPath.addCurve(to: CGPoint(x: -24.17, y: -3.14), controlPoint1: CGPoint(x: -33.47, y: 2.41), controlPoint2: CGPoint(x: -28.05, y: -3.1))
336 | smallTopGearPath.addCurve(to: CGPoint(x: -18.94, y: -2.34), controlPoint1: CGPoint(x: -22.83, y: -3.15), controlPoint2: CGPoint(x: -20.42, y: -2.67))
337 | smallTopGearPath.addCurve(to: CGPoint(x: -17.12, y: -8.31), controlPoint1: CGPoint(x: -18.66, y: -4.41), controlPoint2: CGPoint(x: -18.05, y: -6.43))
338 | smallTopGearPath.addCurve(to: CGPoint(x: -22.97, y: -11.46), controlPoint1: CGPoint(x: -18.66, y: -8.82), controlPoint2: CGPoint(x: -21.64, y: -9.96))
339 | smallTopGearPath.addCurve(to: CGPoint(x: -26.84, y: -20.47), controlPoint1: CGPoint(x: -25.67, y: -14.53), controlPoint2: CGPoint(x: -26.84, y: -20.47))
340 | smallTopGearPath.addCurve(to: CGPoint(x: -26.58, y: -20.74), controlPoint1: CGPoint(x: -26.84, y: -20.47), controlPoint2: CGPoint(x: -26.73, y: -20.58))
341 | smallTopGearPath.addCurve(to: CGPoint(x: -25.44, y: -21.89), controlPoint1: CGPoint(x: -26.17, y: -21.15), controlPoint2: CGPoint(x: -25.44, y: -21.89))
342 | smallTopGearPath.addCurve(to: CGPoint(x: -14.94, y: -19.27), controlPoint1: CGPoint(x: -25.44, y: -21.89), controlPoint2: CGPoint(x: -17.71, y: -21.97))
343 | smallTopGearPath.addCurve(to: CGPoint(x: -11.71, y: -14.9), controlPoint1: CGPoint(x: -13.94, y: -18.3), controlPoint2: CGPoint(x: -12.52, y: -16.17))
344 | smallTopGearPath.addCurve(to: CGPoint(x: -10.17, y: -15.97), controlPoint1: CGPoint(x: -11.22, y: -15.28), controlPoint2: CGPoint(x: -10.7, y: -15.64))
345 | smallTopGearPath.addCurve(to: CGPoint(x: -6.16, y: -17.87), controlPoint1: CGPoint(x: -8.88, y: -16.77), controlPoint2: CGPoint(x: -7.54, y: -17.41))
346 | smallTopGearPath.addCurve(to: CGPoint(x: -8.12, y: -24.35), controlPoint1: CGPoint(x: -6.87, y: -19.28), controlPoint2: CGPoint(x: -8.25, y: -22.3))
347 | smallTopGearPath.addCurve(to: CGPoint(x: -4.49, y: -33.46), controlPoint1: CGPoint(x: -7.87, y: -28.43), controlPoint2: CGPoint(x: -4.49, y: -33.46))
348 | smallTopGearPath.addLine(to: CGPoint(x: -2.5, y: -33.47))
349 | smallTopGearPath.addLine(to: CGPoint(x: -2.49, y: -33.46))
350 | smallTopGearPath.close()
351 | smallTopGearPath.move(to: CGPoint(x: 0, y: -10))
352 | smallTopGearPath.addCurve(to: CGPoint(x: -2.41, y: -9.71), controlPoint1: CGPoint(x: -0.83, y: -10), controlPoint2: CGPoint(x: -1.64, y: -9.9))
353 | smallTopGearPath.addCurve(to: CGPoint(x: -10, y: 0), controlPoint1: CGPoint(x: -6.77, y: -8.63), controlPoint2: CGPoint(x: -10, y: -4.69))
354 | smallTopGearPath.addCurve(to: CGPoint(x: 0, y: 10), controlPoint1: CGPoint(x: -10, y: 5.52), controlPoint2: CGPoint(x: -5.52, y: 10))
355 | smallTopGearPath.addCurve(to: CGPoint(x: 10, y: 0), controlPoint1: CGPoint(x: 5.52, y: 10), controlPoint2: CGPoint(x: 10, y: 5.52))
356 | smallTopGearPath.addCurve(to: CGPoint(x: 0, y: -10), controlPoint1: CGPoint(x: 10, y: -5.52), controlPoint2: CGPoint(x: 5.52, y: -10))
357 | smallTopGearPath.close()
358 | lightProgressBarColor.setFill()
359 | smallTopGearPath.fill()
360 | progressBarColor.setStroke()
361 | smallTopGearPath.lineWidth = 1.5
362 | smallTopGearPath.stroke()
363 |
364 | context.restoreGState()
365 |
366 |
367 | //// Small Bottom Gear Drawing
368 | context.saveGState()
369 | context.translateBy(x: 41.79, y: 139.2)
370 | context.rotate(by: -(gear1Rotation - 360) * CGFloat.pi/180)
371 |
372 | let smallBottomGearPath = UIBezierPath()
373 | smallBottomGearPath.move(to: CGPoint(x: -2.49, y: -33.46))
374 | smallBottomGearPath.addCurve(to: CGPoint(x: 3.07, y: -24.18), controlPoint1: CGPoint(x: -2.5, y: -33.47), controlPoint2: CGPoint(x: 3.02, y: -28.06))
375 | smallBottomGearPath.addCurve(to: CGPoint(x: 2.24, y: -18.71), controlPoint1: CGPoint(x: 3.09, y: -22.77), controlPoint2: CGPoint(x: 2.57, y: -20.17))
376 | smallBottomGearPath.addCurve(to: CGPoint(x: 8.37, y: -16.87), controlPoint1: CGPoint(x: 4.37, y: -18.45), controlPoint2: CGPoint(x: 6.44, y: -17.83))
377 | smallBottomGearPath.addCurve(to: CGPoint(x: 11.63, y: -22.88), controlPoint1: CGPoint(x: 8.86, y: -18.34), controlPoint2: CGPoint(x: 10.05, y: -21.52))
378 | smallBottomGearPath.addCurve(to: CGPoint(x: 20.66, y: -26.7), controlPoint1: CGPoint(x: 14.71, y: -25.57), controlPoint2: CGPoint(x: 20.66, y: -26.7))
379 | smallBottomGearPath.addLine(to: CGPoint(x: 22.07, y: -25.28))
380 | smallBottomGearPath.addCurve(to: CGPoint(x: 19.37, y: -14.8), controlPoint1: CGPoint(x: 22.07, y: -25.28), controlPoint2: CGPoint(x: 22.09, y: -17.55))
381 | smallBottomGearPath.addCurve(to: CGPoint(x: 14.9, y: -11.55), controlPoint1: CGPoint(x: 18.38, y: -13.79), controlPoint2: CGPoint(x: 16.16, y: -12.34))
382 | smallBottomGearPath.addCurve(to: CGPoint(x: 16.03, y: -9.92), controlPoint1: CGPoint(x: 15.3, y: -11.03), controlPoint2: CGPoint(x: 15.68, y: -10.49))
383 | smallBottomGearPath.addCurve(to: CGPoint(x: 17.86, y: -6.1), controlPoint1: CGPoint(x: 16.8, y: -8.7), controlPoint2: CGPoint(x: 17.41, y: -7.42))
384 | smallBottomGearPath.addCurve(to: CGPoint(x: 24.37, y: -8.06), controlPoint1: CGPoint(x: 19.27, y: -6.81), controlPoint2: CGPoint(x: 22.31, y: -8.19))
385 | smallBottomGearPath.addCurve(to: CGPoint(x: 33.47, y: -4.41), controlPoint1: CGPoint(x: 28.45, y: -7.79), controlPoint2: CGPoint(x: 33.47, y: -4.41))
386 | smallBottomGearPath.addLine(to: CGPoint(x: 33.47, y: -2.41))
387 | smallBottomGearPath.addCurve(to: CGPoint(x: 24.17, y: 3.14), controlPoint1: CGPoint(x: 33.47, y: -2.41), controlPoint2: CGPoint(x: 28.05, y: 3.1))
388 | smallBottomGearPath.addCurve(to: CGPoint(x: 18.79, y: 2.31), controlPoint1: CGPoint(x: 22.78, y: 3.15), controlPoint2: CGPoint(x: 20.27, y: 2.64))
389 | smallBottomGearPath.addCurve(to: CGPoint(x: 17.09, y: 8.3), controlPoint1: CGPoint(x: 18.56, y: 4.38), controlPoint2: CGPoint(x: 17.98, y: 6.41))
390 | smallBottomGearPath.addCurve(to: CGPoint(x: 22.97, y: 11.46), controlPoint1: CGPoint(x: 18.62, y: 8.81), controlPoint2: CGPoint(x: 21.63, y: 9.95))
391 | smallBottomGearPath.addCurve(to: CGPoint(x: 26.84, y: 20.47), controlPoint1: CGPoint(x: 25.67, y: 14.53), controlPoint2: CGPoint(x: 26.84, y: 20.47))
392 | smallBottomGearPath.addLine(to: CGPoint(x: 25.44, y: 21.89))
393 | smallBottomGearPath.addCurve(to: CGPoint(x: 14.94, y: 19.26), controlPoint1: CGPoint(x: 25.44, y: 21.89), controlPoint2: CGPoint(x: 17.71, y: 21.97))
394 | smallBottomGearPath.addCurve(to: CGPoint(x: 11.78, y: 15.01), controlPoint1: CGPoint(x: 13.97, y: 18.33), controlPoint2: CGPoint(x: 12.6, y: 16.29))
395 | smallBottomGearPath.addCurve(to: CGPoint(x: 9.98, y: 16.28), controlPoint1: CGPoint(x: 11.21, y: 15.46), controlPoint2: CGPoint(x: 10.61, y: 15.88))
396 | smallBottomGearPath.addCurve(to: CGPoint(x: 6.26, y: 18.07), controlPoint1: CGPoint(x: 8.79, y: 17.02), controlPoint2: CGPoint(x: 7.54, y: 17.62))
397 | smallBottomGearPath.addCurve(to: CGPoint(x: 8.12, y: 24.35), controlPoint1: CGPoint(x: 7, y: 19.56), controlPoint2: CGPoint(x: 8.24, y: 22.39))
398 | smallBottomGearPath.addCurve(to: CGPoint(x: 4.49, y: 33.46), controlPoint1: CGPoint(x: 7.87, y: 28.43), controlPoint2: CGPoint(x: 4.49, y: 33.46))
399 | smallBottomGearPath.addLine(to: CGPoint(x: 2.5, y: 33.47))
400 | smallBottomGearPath.addCurve(to: CGPoint(x: -3.07, y: 24.18), controlPoint1: CGPoint(x: 2.5, y: 33.47), controlPoint2: CGPoint(x: -3.02, y: 28.06))
401 | smallBottomGearPath.addCurve(to: CGPoint(x: -2.31, y: 19.03), controlPoint1: CGPoint(x: -3.09, y: 22.86), controlPoint2: CGPoint(x: -2.64, y: 20.52))
402 | smallBottomGearPath.addCurve(to: CGPoint(x: -8.49, y: 17.21), controlPoint1: CGPoint(x: -4.45, y: 18.78), controlPoint2: CGPoint(x: -6.54, y: 18.16))
403 | smallBottomGearPath.addCurve(to: CGPoint(x: -11.63, y: 22.88), controlPoint1: CGPoint(x: -9.03, y: 18.79), controlPoint2: CGPoint(x: -10.17, y: 21.61))
404 | smallBottomGearPath.addCurve(to: CGPoint(x: -20.66, y: 26.7), controlPoint1: CGPoint(x: -14.71, y: 25.57), controlPoint2: CGPoint(x: -20.66, y: 26.7))
405 | smallBottomGearPath.addLine(to: CGPoint(x: -22.07, y: 25.28))
406 | smallBottomGearPath.addCurve(to: CGPoint(x: -19.37, y: 14.8), controlPoint1: CGPoint(x: -22.07, y: 25.28), controlPoint2: CGPoint(x: -22.09, y: 17.55))
407 | smallBottomGearPath.addCurve(to: CGPoint(x: -15.18, y: 11.73), controlPoint1: CGPoint(x: -18.45, y: 13.86), controlPoint2: CGPoint(x: -16.47, y: 12.54))
408 | smallBottomGearPath.addCurve(to: CGPoint(x: -16.22, y: 10.23), controlPoint1: CGPoint(x: -15.54, y: 11.25), controlPoint2: CGPoint(x: -15.89, y: 10.75))
409 | smallBottomGearPath.addCurve(to: CGPoint(x: -18.11, y: 6.23), controlPoint1: CGPoint(x: -17.02, y: 8.94), controlPoint2: CGPoint(x: -17.65, y: 7.6))
410 | smallBottomGearPath.addCurve(to: CGPoint(x: -24.37, y: 8.06), controlPoint1: CGPoint(x: -19.6, y: 6.96), controlPoint2: CGPoint(x: -22.42, y: 8.19))
411 | smallBottomGearPath.addCurve(to: CGPoint(x: -33.47, y: 4.41), controlPoint1: CGPoint(x: -28.45, y: 7.79), controlPoint2: CGPoint(x: -33.47, y: 4.41))
412 | smallBottomGearPath.addLine(to: CGPoint(x: -33.47, y: 2.41))
413 | smallBottomGearPath.addCurve(to: CGPoint(x: -24.17, y: -3.14), controlPoint1: CGPoint(x: -33.47, y: 2.41), controlPoint2: CGPoint(x: -28.05, y: -3.1))
414 | smallBottomGearPath.addCurve(to: CGPoint(x: -18.94, y: -2.34), controlPoint1: CGPoint(x: -22.83, y: -3.15), controlPoint2: CGPoint(x: -20.42, y: -2.67))
415 | smallBottomGearPath.addCurve(to: CGPoint(x: -17.12, y: -8.31), controlPoint1: CGPoint(x: -18.66, y: -4.41), controlPoint2: CGPoint(x: -18.05, y: -6.43))
416 | smallBottomGearPath.addCurve(to: CGPoint(x: -22.97, y: -11.46), controlPoint1: CGPoint(x: -18.66, y: -8.82), controlPoint2: CGPoint(x: -21.64, y: -9.96))
417 | smallBottomGearPath.addCurve(to: CGPoint(x: -26.84, y: -20.47), controlPoint1: CGPoint(x: -25.67, y: -14.53), controlPoint2: CGPoint(x: -26.84, y: -20.47))
418 | smallBottomGearPath.addCurve(to: CGPoint(x: -26.58, y: -20.74), controlPoint1: CGPoint(x: -26.84, y: -20.47), controlPoint2: CGPoint(x: -26.73, y: -20.58))
419 | smallBottomGearPath.addCurve(to: CGPoint(x: -25.44, y: -21.89), controlPoint1: CGPoint(x: -26.17, y: -21.15), controlPoint2: CGPoint(x: -25.44, y: -21.89))
420 | smallBottomGearPath.addCurve(to: CGPoint(x: -14.94, y: -19.27), controlPoint1: CGPoint(x: -25.44, y: -21.89), controlPoint2: CGPoint(x: -17.71, y: -21.97))
421 | smallBottomGearPath.addCurve(to: CGPoint(x: -11.71, y: -14.9), controlPoint1: CGPoint(x: -13.94, y: -18.3), controlPoint2: CGPoint(x: -12.52, y: -16.17))
422 | smallBottomGearPath.addCurve(to: CGPoint(x: -10.17, y: -15.97), controlPoint1: CGPoint(x: -11.22, y: -15.28), controlPoint2: CGPoint(x: -10.7, y: -15.64))
423 | smallBottomGearPath.addCurve(to: CGPoint(x: -6.16, y: -17.87), controlPoint1: CGPoint(x: -8.88, y: -16.77), controlPoint2: CGPoint(x: -7.54, y: -17.41))
424 | smallBottomGearPath.addCurve(to: CGPoint(x: -8.12, y: -24.35), controlPoint1: CGPoint(x: -6.87, y: -19.28), controlPoint2: CGPoint(x: -8.25, y: -22.3))
425 | smallBottomGearPath.addCurve(to: CGPoint(x: -4.49, y: -33.46), controlPoint1: CGPoint(x: -7.87, y: -28.43), controlPoint2: CGPoint(x: -4.49, y: -33.46))
426 | smallBottomGearPath.addLine(to: CGPoint(x: -2.5, y: -33.47))
427 | smallBottomGearPath.addLine(to: CGPoint(x: -2.49, y: -33.46))
428 | smallBottomGearPath.close()
429 | smallBottomGearPath.move(to: CGPoint(x: 0, y: -10))
430 | smallBottomGearPath.addCurve(to: CGPoint(x: -2.41, y: -9.71), controlPoint1: CGPoint(x: -0.83, y: -10), controlPoint2: CGPoint(x: -1.64, y: -9.9))
431 | smallBottomGearPath.addCurve(to: CGPoint(x: -10, y: 0), controlPoint1: CGPoint(x: -6.77, y: -8.63), controlPoint2: CGPoint(x: -10, y: -4.69))
432 | smallBottomGearPath.addCurve(to: CGPoint(x: 0, y: 10), controlPoint1: CGPoint(x: -10, y: 5.52), controlPoint2: CGPoint(x: -5.52, y: 10))
433 | smallBottomGearPath.addCurve(to: CGPoint(x: 10, y: 0), controlPoint1: CGPoint(x: 5.52, y: 10), controlPoint2: CGPoint(x: 10, y: 5.52))
434 | smallBottomGearPath.addCurve(to: CGPoint(x: 0, y: -10), controlPoint1: CGPoint(x: 10, y: -5.52), controlPoint2: CGPoint(x: 5.52, y: -10))
435 | smallBottomGearPath.close()
436 | lightProgressBarColor.setFill()
437 | smallBottomGearPath.fill()
438 | progressBarColor.setStroke()
439 | smallBottomGearPath.lineWidth = 1.5
440 | smallBottomGearPath.stroke()
441 |
442 | context.restoreGState()
443 |
444 |
445 | //// Big Gear Drawing
446 | context.saveGState()
447 | context.translateBy(x: 104.86, y: 85.15)
448 | context.rotate(by: -gear2Rotation * CGFloat.pi/180)
449 |
450 | let bigGearPath = UIBezierPath()
451 | bigGearPath.move(to: CGPoint(x: 4.44, y: -51))
452 | bigGearPath.addCurve(to: CGPoint(x: 4.69, y: -45.99), controlPoint1: CGPoint(x: 4.86, y: -49.62), controlPoint2: CGPoint(x: 4.95, y: -47.74))
453 | bigGearPath.addCurve(to: CGPoint(x: 10.17, y: -45.08), controlPoint1: CGPoint(x: 6.55, y: -45.8), controlPoint2: CGPoint(x: 8.38, y: -45.49))
454 | bigGearPath.addCurve(to: CGPoint(x: 12.47, y: -50.32), controlPoint1: CGPoint(x: 10.37, y: -46.61), controlPoint2: CGPoint(x: 11.03, y: -48.7))
455 | bigGearPath.addCurve(to: CGPoint(x: 20.09, y: -57.19), controlPoint1: CGPoint(x: 15.05, y: -53.2), controlPoint2: CGPoint(x: 16.89, y: -55.29))
456 | bigGearPath.addLine(to: CGPoint(x: 22.36, y: -56.29))
457 | bigGearPath.addCurve(to: CGPoint(x: 23.42, y: -45.49), controlPoint1: CGPoint(x: 23.25, y: -52.48), controlPoint2: CGPoint(x: 23.7, y: -48.32))
458 | bigGearPath.addCurve(to: CGPoint(x: 21.72, y: -40.7), controlPoint1: CGPoint(x: 23.28, y: -44.04), controlPoint2: CGPoint(x: 22.64, y: -42.23))
459 | bigGearPath.addCurve(to: CGPoint(x: 26.6, y: -37.64), controlPoint1: CGPoint(x: 23.41, y: -39.78), controlPoint2: CGPoint(x: 25.04, y: -38.76))
460 | bigGearPath.addCurve(to: CGPoint(x: 30.77, y: -41.67), controlPoint1: CGPoint(x: 27.36, y: -38.99), controlPoint2: CGPoint(x: 28.78, y: -40.71))
461 | bigGearPath.addCurve(to: CGPoint(x: 40.44, y: -45.08), controlPoint1: CGPoint(x: 34.25, y: -43.34), controlPoint2: CGPoint(x: 36.75, y: -44.56))
462 | bigGearPath.addLine(to: CGPoint(x: 42.18, y: -43.37))
463 | bigGearPath.addCurve(to: CGPoint(x: 39.03, y: -32.99), controlPoint1: CGPoint(x: 41.55, y: -39.51), controlPoint2: CGPoint(x: 40.37, y: -35.5))
464 | bigGearPath.addCurve(to: CGPoint(x: 35.57, y: -29.18), controlPoint1: CGPoint(x: 38.34, y: -31.69), controlPoint2: CGPoint(x: 37.04, y: -30.25))
465 | bigGearPath.addCurve(to: CGPoint(x: 38.91, y: -24.51), controlPoint1: CGPoint(x: 36.78, y: -27.7), controlPoint2: CGPoint(x: 37.89, y: -26.14))
466 | bigGearPath.addCurve(to: CGPoint(x: 44.34, y: -26.66), controlPoint1: CGPoint(x: 40.13, y: -25.47), controlPoint2: CGPoint(x: 42.11, y: -26.54))
467 | bigGearPath.addCurve(to: CGPoint(x: 54.58, y: -26.1), controlPoint1: CGPoint(x: 48.2, y: -26.87), controlPoint2: CGPoint(x: 50.97, y: -27.03))
468 | bigGearPath.addLine(to: CGPoint(x: 55.54, y: -23.85))
469 | bigGearPath.addCurve(to: CGPoint(x: 48.66, y: -15.47), controlPoint1: CGPoint(x: 53.48, y: -20.52), controlPoint2: CGPoint(x: 50.85, y: -17.27))
470 | bigGearPath.addCurve(to: CGPoint(x: 43.98, y: -13.28), controlPoint1: CGPoint(x: 47.51, y: -14.52), controlPoint2: CGPoint(x: 45.74, y: -13.69))
471 | bigGearPath.addCurve(to: CGPoint(x: 45.27, y: -7.65), controlPoint1: CGPoint(x: 44.52, y: -11.44), controlPoint2: CGPoint(x: 44.96, y: -9.57))
472 | bigGearPath.addCurve(to: CGPoint(x: 51.15, y: -7.55), controlPoint1: CGPoint(x: 46.77, y: -8.07), controlPoint2: CGPoint(x: 49.02, y: -8.3))
473 | bigGearPath.addCurve(to: CGPoint(x: 60.38, y: -3.09), controlPoint1: CGPoint(x: 54.79, y: -6.26), controlPoint2: CGPoint(x: 57.41, y: -5.34))
474 | bigGearPath.addLine(to: CGPoint(x: 60.41, y: -0.64))
475 | bigGearPath.addCurve(to: CGPoint(x: 50.85, y: 4.45), controlPoint1: CGPoint(x: 57.23, y: 1.63), controlPoint2: CGPoint(x: 53.57, y: 3.62))
476 | bigGearPath.addCurve(to: CGPoint(x: 45.66, y: 4.66), controlPoint1: CGPoint(x: 49.42, y: 4.88), controlPoint2: CGPoint(x: 47.46, y: 4.96))
477 | bigGearPath.addCurve(to: CGPoint(x: 44.76, y: 10.18), controlPoint1: CGPoint(x: 45.47, y: 6.54), controlPoint2: CGPoint(x: 45.16, y: 8.38))
478 | bigGearPath.addCurve(to: CGPoint(x: 50.17, y: 12.51), controlPoint1: CGPoint(x: 46.3, y: 10.35), controlPoint2: CGPoint(x: 48.48, y: 11))
479 | bigGearPath.addCurve(to: CGPoint(x: 57.02, y: 20.15), controlPoint1: CGPoint(x: 53.05, y: 15.09), controlPoint2: CGPoint(x: 55.13, y: 16.94))
480 | bigGearPath.addLine(to: CGPoint(x: 56.12, y: 22.43))
481 | bigGearPath.addCurve(to: CGPoint(x: 45.35, y: 23.5), controlPoint1: CGPoint(x: 52.32, y: 23.33), controlPoint2: CGPoint(x: 48.18, y: 23.77))
482 | bigGearPath.addCurve(to: CGPoint(x: 40.46, y: 21.71), controlPoint1: CGPoint(x: 43.87, y: 23.35), controlPoint2: CGPoint(x: 42.01, y: 22.68))
483 | bigGearPath.addCurve(to: CGPoint(x: 37.42, y: 26.64), controlPoint1: CGPoint(x: 39.55, y: 23.42), controlPoint2: CGPoint(x: 38.53, y: 25.07))
484 | bigGearPath.addCurve(to: CGPoint(x: 41.53, y: 30.88), controlPoint1: CGPoint(x: 38.78, y: 27.39), controlPoint2: CGPoint(x: 40.55, y: 28.84))
485 | bigGearPath.addCurve(to: CGPoint(x: 44.93, y: 40.58), controlPoint1: CGPoint(x: 43.2, y: 34.37), controlPoint2: CGPoint(x: 44.41, y: 36.88))
486 | bigGearPath.addLine(to: CGPoint(x: 43.22, y: 42.33))
487 | bigGearPath.addCurve(to: CGPoint(x: 32.87, y: 39.17), controlPoint1: CGPoint(x: 39.37, y: 41.7), controlPoint2: CGPoint(x: 35.38, y: 40.51))
488 | bigGearPath.addCurve(to: CGPoint(x: 29.05, y: 35.65), controlPoint1: CGPoint(x: 31.56, y: 38.46), controlPoint2: CGPoint(x: 30.11, y: 37.13))
489 | bigGearPath.addCurve(to: CGPoint(x: 24.3, y: 39.08), controlPoint1: CGPoint(x: 27.54, y: 36.89), controlPoint2: CGPoint(x: 25.96, y: 38.03))
490 | bigGearPath.addCurve(to: CGPoint(x: 26.44, y: 44.56), controlPoint1: CGPoint(x: 25.26, y: 40.3), controlPoint2: CGPoint(x: 26.32, y: 42.31))
491 | bigGearPath.addCurve(to: CGPoint(x: 25.85, y: 54.82), controlPoint1: CGPoint(x: 26.64, y: 48.42), controlPoint2: CGPoint(x: 26.79, y: 51.21))
492 | bigGearPath.addLine(to: CGPoint(x: 23.6, y: 55.77))
493 | bigGearPath.addCurve(to: CGPoint(x: 15.27, y: 48.85), controlPoint1: CGPoint(x: 20.29, y: 53.7), controlPoint2: CGPoint(x: 17.06, y: 51.06))
494 | bigGearPath.addCurve(to: CGPoint(x: 13.11, y: 44.19), controlPoint1: CGPoint(x: 14.34, y: 47.71), controlPoint2: CGPoint(x: 13.52, y: 45.95))
495 | bigGearPath.addCurve(to: CGPoint(x: 7.64, y: 45.47), controlPoint1: CGPoint(x: 11.33, y: 44.72), controlPoint2: CGPoint(x: 9.5, y: 45.15))
496 | bigGearPath.addCurve(to: CGPoint(x: 7.52, y: 51.3), controlPoint1: CGPoint(x: 8.05, y: 46.97), controlPoint2: CGPoint(x: 8.26, y: 49.2))
497 | bigGearPath.addCurve(to: CGPoint(x: 3.08, y: 60.56), controlPoint1: CGPoint(x: 6.23, y: 54.95), controlPoint2: CGPoint(x: 5.32, y: 57.58))
498 | bigGearPath.addLine(to: CGPoint(x: 0.63, y: 60.59))
499 | bigGearPath.addCurve(to: CGPoint(x: -4.44, y: 51), controlPoint1: CGPoint(x: -1.64, y: 57.4), controlPoint2: CGPoint(x: -3.62, y: 53.73))
500 | bigGearPath.addCurve(to: CGPoint(x: -4.67, y: 45.92), controlPoint1: CGPoint(x: -4.86, y: 49.6), controlPoint2: CGPoint(x: -4.95, y: 47.69))
501 | bigGearPath.addCurve(to: CGPoint(x: -10.16, y: 45.04), controlPoint1: CGPoint(x: -6.54, y: 45.73), controlPoint2: CGPoint(x: -8.37, y: 45.44))
502 | bigGearPath.addCurve(to: CGPoint(x: -12.47, y: 50.32), controlPoint1: CGPoint(x: -10.36, y: 46.58), controlPoint2: CGPoint(x: -11.02, y: 48.68))
503 | bigGearPath.addCurve(to: CGPoint(x: -20.09, y: 57.19), controlPoint1: CGPoint(x: -15.05, y: 53.2), controlPoint2: CGPoint(x: -16.89, y: 55.29))
504 | bigGearPath.addLine(to: CGPoint(x: -22.36, y: 56.29))
505 | bigGearPath.addCurve(to: CGPoint(x: -23.42, y: 45.49), controlPoint1: CGPoint(x: -23.25, y: 52.48), controlPoint2: CGPoint(x: -23.7, y: 48.32))
506 | bigGearPath.addCurve(to: CGPoint(x: -21.75, y: 40.75), controlPoint1: CGPoint(x: -23.29, y: 44.05), controlPoint2: CGPoint(x: -22.66, y: 42.27))
507 | bigGearPath.addCurve(to: CGPoint(x: -26.65, y: 37.73), controlPoint1: CGPoint(x: -23.45, y: 39.84), controlPoint2: CGPoint(x: -25.08, y: 38.83))
508 | bigGearPath.addCurve(to: CGPoint(x: -30.77, y: 41.67), controlPoint1: CGPoint(x: -27.42, y: 39.06), controlPoint2: CGPoint(x: -28.82, y: 40.73))
509 | bigGearPath.addCurve(to: CGPoint(x: -40.44, y: 45.08), controlPoint1: CGPoint(x: -34.25, y: 43.34), controlPoint2: CGPoint(x: -36.75, y: 44.56))
510 | bigGearPath.addLine(to: CGPoint(x: -42.18, y: 43.37))
511 | bigGearPath.addCurve(to: CGPoint(x: -39.03, y: 32.99), controlPoint1: CGPoint(x: -41.55, y: 39.51), controlPoint2: CGPoint(x: -40.37, y: 35.5))
512 | bigGearPath.addCurve(to: CGPoint(x: -35.72, y: 29.29), controlPoint1: CGPoint(x: -38.36, y: 31.73), controlPoint2: CGPoint(x: -37.12, y: 30.34))
513 | bigGearPath.addCurve(to: CGPoint(x: -39.08, y: 24.64), controlPoint1: CGPoint(x: -36.93, y: 27.81), controlPoint2: CGPoint(x: -38.05, y: 26.26))
514 | bigGearPath.addCurve(to: CGPoint(x: -44.34, y: 26.66), controlPoint1: CGPoint(x: -40.31, y: 25.57), controlPoint2: CGPoint(x: -42.21, y: 26.54))
515 | bigGearPath.addCurve(to: CGPoint(x: -54.58, y: 26.1), controlPoint1: CGPoint(x: -48.2, y: 26.87), controlPoint2: CGPoint(x: -50.97, y: 27.03))
516 | bigGearPath.addLine(to: CGPoint(x: -55.54, y: 23.85))
517 | bigGearPath.addCurve(to: CGPoint(x: -48.66, y: 15.47), controlPoint1: CGPoint(x: -53.48, y: 20.52), controlPoint2: CGPoint(x: -50.85, y: 17.27))
518 | bigGearPath.addCurve(to: CGPoint(x: -44.24, y: 13.34), controlPoint1: CGPoint(x: -47.57, y: 14.57), controlPoint2: CGPoint(x: -45.92, y: 13.78))
519 | bigGearPath.addCurve(to: CGPoint(x: -45.56, y: 7.73), controlPoint1: CGPoint(x: -44.8, y: 11.52), controlPoint2: CGPoint(x: -45.24, y: 9.64))
520 | bigGearPath.addCurve(to: CGPoint(x: -51.15, y: 7.55), controlPoint1: CGPoint(x: -47.05, y: 8.1), controlPoint2: CGPoint(x: -49.16, y: 8.25))
521 | bigGearPath.addCurve(to: CGPoint(x: -60.38, y: 3.09), controlPoint1: CGPoint(x: -54.79, y: 6.26), controlPoint2: CGPoint(x: -57.41, y: 5.34))
522 | bigGearPath.addLine(to: CGPoint(x: -60.41, y: 0.64))
523 | bigGearPath.addCurve(to: CGPoint(x: -50.85, y: -4.45), controlPoint1: CGPoint(x: -57.23, y: -1.63), controlPoint2: CGPoint(x: -53.57, y: -3.62))
524 | bigGearPath.addCurve(to: CGPoint(x: -45.98, y: -4.71), controlPoint1: CGPoint(x: -49.51, y: -4.85), controlPoint2: CGPoint(x: -47.69, y: -4.95))
525 | bigGearPath.addCurve(to: CGPoint(x: -45.09, y: -10.22), controlPoint1: CGPoint(x: -45.8, y: -6.58), controlPoint2: CGPoint(x: -45.5, y: -8.42))
526 | bigGearPath.addCurve(to: CGPoint(x: -50.17, y: -12.51), controlPoint1: CGPoint(x: -46.61, y: -10.45), controlPoint2: CGPoint(x: -48.6, y: -11.11))
527 | bigGearPath.addCurve(to: CGPoint(x: -57.02, y: -20.15), controlPoint1: CGPoint(x: -53.05, y: -15.09), controlPoint2: CGPoint(x: -55.13, y: -16.94))
528 | bigGearPath.addLine(to: CGPoint(x: -56.12, y: -22.43))
529 | bigGearPath.addCurve(to: CGPoint(x: -45.35, y: -23.5), controlPoint1: CGPoint(x: -52.32, y: -23.33), controlPoint2: CGPoint(x: -48.18, y: -23.77))
530 | bigGearPath.addCurve(to: CGPoint(x: -40.75, y: -21.89), controlPoint1: CGPoint(x: -43.96, y: -23.36), controlPoint2: CGPoint(x: -42.24, y: -22.76))
531 | bigGearPath.addCurve(to: CGPoint(x: -37.7, y: -26.8), controlPoint1: CGPoint(x: -39.83, y: -23.59), controlPoint2: CGPoint(x: -38.82, y: -25.23))
532 | bigGearPath.addCurve(to: CGPoint(x: -41.53, y: -30.88), controlPoint1: CGPoint(x: -39.01, y: -27.59), controlPoint2: CGPoint(x: -40.61, y: -28.98))
533 | bigGearPath.addCurve(to: CGPoint(x: -44.93, y: -40.58), controlPoint1: CGPoint(x: -43.2, y: -34.37), controlPoint2: CGPoint(x: -44.41, y: -36.88))
534 | bigGearPath.addLine(to: CGPoint(x: -43.22, y: -42.33))
535 | bigGearPath.addCurve(to: CGPoint(x: -32.87, y: -39.17), controlPoint1: CGPoint(x: -39.37, y: -41.69), controlPoint2: CGPoint(x: -35.38, y: -40.51))
536 | bigGearPath.addCurve(to: CGPoint(x: -29.22, y: -35.88), controlPoint1: CGPoint(x: -31.63, y: -38.5), controlPoint2: CGPoint(x: -30.26, y: -37.27))
537 | bigGearPath.addCurve(to: CGPoint(x: -24.46, y: -39.29), controlPoint1: CGPoint(x: -27.71, y: -37.11), controlPoint2: CGPoint(x: -26.12, y: -38.25))
538 | bigGearPath.addCurve(to: CGPoint(x: -26.44, y: -44.56), controlPoint1: CGPoint(x: -25.37, y: -40.53), controlPoint2: CGPoint(x: -26.33, y: -42.43))
539 | bigGearPath.addCurve(to: CGPoint(x: -26.18, y: -53.36), controlPoint1: CGPoint(x: -26.61, y: -47.89), controlPoint2: CGPoint(x: -26.75, y: -50.42))
540 | bigGearPath.addCurve(to: CGPoint(x: -25.85, y: -54.82), controlPoint1: CGPoint(x: -26.09, y: -53.84), controlPoint2: CGPoint(x: -25.98, y: -54.32))
541 | bigGearPath.addLine(to: CGPoint(x: -23.6, y: -55.77))
542 | bigGearPath.addCurve(to: CGPoint(x: -15.4, y: -49.01), controlPoint1: CGPoint(x: -20.37, y: -53.75), controlPoint2: CGPoint(x: -17.22, y: -51.18))
543 | bigGearPath.addLine(to: CGPoint(x: -15.27, y: -48.85))
544 | bigGearPath.addCurve(to: CGPoint(x: -13.15, y: -44.38), controlPoint1: CGPoint(x: -14.37, y: -47.75), controlPoint2: CGPoint(x: -13.58, y: -46.07))
545 | bigGearPath.addCurve(to: CGPoint(x: -7.68, y: -45.63), controlPoint1: CGPoint(x: -11.37, y: -44.9), controlPoint2: CGPoint(x: -9.55, y: -45.32))
546 | bigGearPath.addCurve(to: CGPoint(x: -7.52, y: -51.3), controlPoint1: CGPoint(x: -8.06, y: -47.13), controlPoint2: CGPoint(x: -8.23, y: -49.27))
547 | bigGearPath.addCurve(to: CGPoint(x: -3.08, y: -60.56), controlPoint1: CGPoint(x: -6.23, y: -54.95), controlPoint2: CGPoint(x: -5.32, y: -57.58))
548 | bigGearPath.addLine(to: CGPoint(x: -0.63, y: -60.59))
549 | bigGearPath.addCurve(to: CGPoint(x: 4.44, y: -51), controlPoint1: CGPoint(x: 1.64, y: -57.4), controlPoint2: CGPoint(x: 3.62, y: -53.73))
550 | bigGearPath.close()
551 | bigGearPath.move(to: CGPoint(x: -10.72, y: -35.9))
552 | bigGearPath.addCurve(to: CGPoint(x: -37.38, y: 0), controlPoint1: CGPoint(x: -26.16, y: -31.27), controlPoint2: CGPoint(x: -37.38, y: -16.94))
553 | bigGearPath.addCurve(to: CGPoint(x: -36.33, y: 8.85), controlPoint1: CGPoint(x: -37.38, y: 3.05), controlPoint2: CGPoint(x: -37.02, y: 6.01))
554 | bigGearPath.addCurve(to: CGPoint(x: -36.27, y: 8.84), controlPoint1: CGPoint(x: -36.28, y: 8.88), controlPoint2: CGPoint(x: -36.27, y: 8.84))
555 | bigGearPath.addCurve(to: CGPoint(x: -30.89, y: 13.86), controlPoint1: CGPoint(x: -35.89, y: 9.75), controlPoint2: CGPoint(x: -33.47, y: 15.3))
556 | bigGearPath.addLine(to: CGPoint(x: -8.41, y: 0.84))
557 | bigGearPath.addCurve(to: CGPoint(x: -8.45, y: 0), controlPoint1: CGPoint(x: -8.44, y: 0.57), controlPoint2: CGPoint(x: -8.45, y: 0.28))
558 | bigGearPath.addCurve(to: CGPoint(x: -3.77, y: -7.59), controlPoint1: CGPoint(x: -8.45, y: -3.32), controlPoint2: CGPoint(x: -6.54, y: -6.2))
559 | bigGearPath.addLine(to: CGPoint(x: -3.77, y: -33.72))
560 | bigGearPath.addCurve(to: CGPoint(x: -10.77, y: -35.89), controlPoint1: CGPoint(x: -3.81, y: -36.8), controlPoint2: CGPoint(x: -10.3, y: -35.96))
561 | bigGearPath.addLine(to: CGPoint(x: -10.72, y: -35.9))
562 | bigGearPath.close()
563 | bigGearPath.move(to: CGPoint(x: 0, y: -4.5))
564 | bigGearPath.addCurve(to: CGPoint(x: -1.32, y: -4.3), controlPoint1: CGPoint(x: -0.46, y: -4.5), controlPoint2: CGPoint(x: -0.9, y: -4.43))
565 | bigGearPath.addCurve(to: CGPoint(x: -4.5, y: 0), controlPoint1: CGPoint(x: -3.16, y: -3.74), controlPoint2: CGPoint(x: -4.5, y: -2.03))
566 | bigGearPath.addCurve(to: CGPoint(x: 0, y: 4.5), controlPoint1: CGPoint(x: -4.5, y: 2.49), controlPoint2: CGPoint(x: -2.49, y: 4.5))
567 | bigGearPath.addCurve(to: CGPoint(x: 4.5, y: 0), controlPoint1: CGPoint(x: 2.49, y: 4.5), controlPoint2: CGPoint(x: 4.5, y: 2.49))
568 | bigGearPath.addCurve(to: CGPoint(x: 0, y: -4.5), controlPoint1: CGPoint(x: 4.5, y: -2.49), controlPoint2: CGPoint(x: 2.49, y: -4.5))
569 | bigGearPath.close()
570 | bigGearPath.move(to: CGPoint(x: 4.39, y: 7.24))
571 | bigGearPath.addCurve(to: CGPoint(x: 0, y: 8.48), controlPoint1: CGPoint(x: 3.11, y: 8.02), controlPoint2: CGPoint(x: 1.61, y: 8.48))
572 | bigGearPath.addCurve(to: CGPoint(x: -4.39, y: 7.24), controlPoint1: CGPoint(x: -1.61, y: 8.48), controlPoint2: CGPoint(x: -3.11, y: 8.02))
573 | bigGearPath.addLine(to: CGPoint(x: -27.12, y: 20.4))
574 | bigGearPath.addCurve(to: CGPoint(x: -25.87, y: 27.05), controlPoint1: CGPoint(x: -29.34, y: 21.73), controlPoint2: CGPoint(x: -26.88, y: 25.62))
575 | bigGearPath.addCurve(to: CGPoint(x: 0, y: 37.49), controlPoint1: CGPoint(x: -19.16, y: 33.52), controlPoint2: CGPoint(x: -10.04, y: 37.49))
576 | bigGearPath.addCurve(to: CGPoint(x: 25.88, y: 27.05), controlPoint1: CGPoint(x: 10.04, y: 37.49), controlPoint2: CGPoint(x: 19.16, y: 33.52))
577 | bigGearPath.addCurve(to: CGPoint(x: 27.13, y: 20.4), controlPoint1: CGPoint(x: 26.89, y: 25.62), controlPoint2: CGPoint(x: 29.34, y: 21.73))
578 | bigGearPath.addLine(to: CGPoint(x: 4.39, y: 7.24))
579 | bigGearPath.close()
580 | bigGearPath.move(to: CGPoint(x: 3.77, y: -33.72))
581 | bigGearPath.addLine(to: CGPoint(x: 3.77, y: -7.59))
582 | bigGearPath.addCurve(to: CGPoint(x: 8.45, y: 0), controlPoint1: CGPoint(x: 6.54, y: -6.2), controlPoint2: CGPoint(x: 8.45, y: -3.32))
583 | bigGearPath.addCurve(to: CGPoint(x: 8.41, y: 0.84), controlPoint1: CGPoint(x: 8.45, y: 0.28), controlPoint2: CGPoint(x: 8.44, y: 0.56))
584 | bigGearPath.addLine(to: CGPoint(x: 30.89, y: 13.85))
585 | bigGearPath.addCurve(to: CGPoint(x: 36.23, y: 8.93), controlPoint1: CGPoint(x: 33.47, y: 15.29), controlPoint2: CGPoint(x: 35.89, y: 9.75))
586 | bigGearPath.addCurve(to: CGPoint(x: 36.31, y: 8.96), controlPoint1: CGPoint(x: 36.27, y: 8.83), controlPoint2: CGPoint(x: 36.28, y: 8.88))
587 | bigGearPath.addCurve(to: CGPoint(x: 37.38, y: 0), controlPoint1: CGPoint(x: 37.02, y: 6.01), controlPoint2: CGPoint(x: 37.38, y: 3.05))
588 | bigGearPath.addCurve(to: CGPoint(x: 10.77, y: -35.91), controlPoint1: CGPoint(x: 37.38, y: -16.94), controlPoint2: CGPoint(x: 26.16, y: -31.27))
589 | bigGearPath.addCurve(to: CGPoint(x: 3.77, y: -33.72), controlPoint1: CGPoint(x: 10.3, y: -35.96), controlPoint2: CGPoint(x: 3.81, y: -36.8))
590 | bigGearPath.close()
591 | lightProgressBarColor.setFill()
592 | bigGearPath.fill()
593 | progressBarColor.setStroke()
594 | bigGearPath.lineWidth = 1.5
595 | bigGearPath.stroke()
596 |
597 | context.restoreGState()
598 |
599 | context.restoreGState()
600 |
601 | }
602 |
603 |
604 |
605 |
606 | @objc(ActivityStyleKitResizingBehavior)
607 | public enum ResizingBehavior: Int {
608 | case aspectFit /// The content is proportionally resized to fit into the target rectangle.
609 | case aspectFill /// The content is proportionally resized to completely fill the target rectangle.
610 | case stretch /// The content is stretched to match the entire target rectangle.
611 | case center /// The content is centered in the target rectangle, but it is NOT resized.
612 |
613 | public func apply(rect: CGRect, target: CGRect) -> CGRect {
614 | if rect == target || target == CGRect.zero {
615 | return rect
616 | }
617 |
618 | var scales = CGSize.zero
619 | scales.width = abs(target.width / rect.width)
620 | scales.height = abs(target.height / rect.height)
621 |
622 | switch self {
623 | case .aspectFit:
624 | scales.width = min(scales.width, scales.height)
625 | scales.height = scales.width
626 | case .aspectFill:
627 | scales.width = max(scales.width, scales.height)
628 | scales.height = scales.width
629 | case .stretch:
630 | break
631 | case .center:
632 | scales.width = 1
633 | scales.height = 1
634 | }
635 |
636 | var result = rect.standardized
637 | result.size.width *= scales.width
638 | result.size.height *= scales.height
639 | result.origin.x = target.minX + (target.width - result.width) / 2
640 | result.origin.y = target.minY + (target.height - result.height) / 2
641 | return result
642 | }
643 | }
644 | }
645 |
--------------------------------------------------------------------------------