GithubHelp home page GithubHelp logo

sindresorhus / circularprogress Goto Github PK

View Code? Open in Web Editor NEW
558.0 12.0 50.0 3.9 MB

Circular progress indicator for your macOS app

License: MIT License

Swift 100.00%
progress-indicator progress-circle progress-view macos swift swift-package carthage cocoapods

circularprogress's Introduction

CircularProgress

Circular progress indicator for your macOS app

This package is used in production by apps like Gifski and HEIC Converter.

Requirements

macOS 10.15+

Install

Add https://github.com/sindresorhus/CircularProgress in the “Swift Package Manager” tab in Xcode.

Latest version: 3.0.1

Usage

Also check out the example app in the Xcode project.

Manually set the progress

import Cocoa
import CircularProgress

@main
final class AppDelegate: NSObject, NSApplicationDelegate {
	@IBOutlet private var window: NSWindow!

	let circularProgress = CircularProgress(size: 200)

	func applicationDidFinishLaunching(_ notification: Notification) {
		window.contentView!.addSubview(circularProgress)

		foo.onUpdate = { progress in
			self.circularProgress.progress = progress
		}
	}
}

Specify a Progress instance

The given Progress instance is strongly kept alive as long as the CircularProgress instance or until you set .progressInstance = nil.

import Cocoa
import CircularProgress

@main
final class AppDelegate: NSObject, NSApplicationDelegate {
	@IBOutlet private var window: NSWindow!

	let circularProgress = CircularProgress(size: 200)
	let progress = Progress(totalUnitCount: 1)

	func applicationDidFinishLaunching(_ notification: Notification) {
		window.contentView!.addSubview(circularProgress)

		progress?.becomeCurrent(withPendingUnitCount: 1)
		circularProgress.progressInstance = progress
	}
}

Cancel button

If you use the .progress property, you need to opt into the cancel button by setting .isCancellable = true. You can be notified of when the button is clicked by setting the .onCancelled property to a closure.

If you use the .progressInstance property, setting a Progress object that is isCancellable, which is the default, automatically enables the cancel button.

Per default, the cancelled state is indicated by desaturing the current color and reducing the opacity. You can customize this by implementing the .cancelledStateColorHandler callback and returning a color to use for the cancelled state instead. The opacity is not automatically reduced when the callback has been set. To disable the cancelled state visualization entirely, set .visualizeCancelledState to false.

Indeterminate state

Displays a state that indicates that the remaining progress is indeterminate.

Note that the .progress property and .isIndeterminate are not tied together. You'll need to manually set .isIndeterminate = false when progress is being made again.

If you use the .progressInstance property, the isIndeterminate property will automatically be observed. The view will then switch back and forth to the indeterminate state when appropriate.

Hidden progress label

Displays a spinner without a percentage indicator in the center.

This is accomplished by setting the .isLabelHidden property to true. The default state is false (the label is displayed).

API

/**
Color of the circular progress view.
*/
@IBInspectable var color: NSColor = .controlAccentColor

/**
Line width of the circular progress view.
*/
@IBInspectable var lineWidth: Double = 2

/**
Show an animated checkmark instead of `100%`.
*/
@IBInspectable var showCheckmarkAtHundredPercent = true

/**
Hide the progress label.

The property supports KVO.
*/
@IBInspectable var isLabelHidden = true

/**
The progress value in the range `0...1`.

- Note: The value will be clamped to `0...1`.
*/
@IBInspectable var progress: Double = 0

/**
Let a `Progress` instance update the `progress` for you.
*/
var progressInstance: Progress?

/**
Reset the progress back to zero without animating.
*/
func resetProgress() {}

/**
Cancels `Progress` if it's set and prevents further updates.
*/
func cancelProgress() {}

/**
Triggers when the progress was cancelled succesfully.
*/
var onCancelled: (() -> Void)?

/**
Returns whether the progress is finished.

The property supports KVO.
*/
@IBInspectable var isFinished: Bool { get }

/**
If the progress view is cancellable it shows the cancel button.
*/
@IBInspectable var isCancellable: Bool

/**
Make the progress indeterminate.

The property supports KVO.
*/
@IBInspectable var isIndeterminate: Bool

/**
Returns whether the progress has been cancelled.

The property supports KVO.
*/
@IBInspectable var isCancelled: Bool { get }

/**
Determines whether to visualize changing into the cancelled state.
*/
var visualizeCancelledState: Bool = true

/**
Supply the base color to use for displaying the cancelled state.
*/
var cancelledStateColorHandler: ((NSColor) -> NSColor)?

init(frame: CGRect) {}
init?(coder: NSCoder) {}

/**
Initialize the progress view with a width/height of the given `size`.
*/
convenience init(size: Double) {}

Related

circularprogress's People

Contributors

allewun avatar boyvanamstel avatar fredyshox avatar rcobelli avatar serhii-londar avatar sindresorhus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

circularprogress's Issues

Add option to reduce saturation of the circular progress when it's cancelled

Issuehunt badges

We could provide a default state through desaturation or an opacity change later.
- #4 (comment)

I think it could just be on by default.

When the CircularProgress is cancelled, it should animate the saturation.

Could be something like:

circularProgress.visualizeCancelledState = false

// @boyvanamstel Open to suggestions about the naming.

boyvanamstel earned $60.00 by resolving this issue!

Make a nicer success view

Issuehunt badges

Would be nice if it matched the thin style used for the cancel button in #4. So instead of just using a checkmark character, we could build it using paths.

And some kind of animation. I like organic animations like https://twitter.com/twostraws/status/1088368799928193024

IssueHunt Summary

allewun allewun has been rewarded.

Sponsors (Total: $142.00)

Tips

Support for macOS < 10.12

Is there any reason the deployment target for the whole project is macOS 10.12?

Except the test app which uses a single call to a macOS 10.12 only API, it seems that the whole project builds and runs fine on macOS 10.10.

The test app uses NSTimer.scheduledTimer, passing a closure, but this could easily be replaced with the selector variant in order to support macOS 10.10.

Deployment Target 10.10

Given this is a generic library, could the macOS deployment target be reduced to the 10.10 (Yosemite)?

It compiles and runs just fine for 10.10, and allows broader support for applications that support older macOS versions.

(There is one error with 10.9, the oldest version of macOS that supports Swift).

Improve mouse tracking

Issuehunt badges

We currently do mouse tracking as a square around the circle, but that leads to the cancel state being activated even when the mouse is not over the circle. We should only activate the cancel state when the mouse is actually over the circle.

https://stackoverflow.com/questions/38963011/nstrackingarea-for-custom-shapes


IssueHunt Summary

eonist eonist has been rewarded.

Backers (Total: $60.00)

Submitted pull Requests


Tips


IssueHunt has been backed by the following sponsors. Become a sponsor

Enforce aspect ratio in Interface Builder

Issuehunt badges

Currently, you're able to set it to 300x100 in Interface Builder, which makes it look broken. Would be nice to enforce aspect ratio of 1:1 using auto layout. According to https://forums.developer.apple.com/thread/4108, it should be possible:

Currently Interface Builder does not allow overriding the layout interactions of a view via IBDesignable (e.g. overriding the standard resizing behaviors in IB). You should, however, be able to add an aspect ratio constraint to your view in your code and IB's auto layout integration will pick this up and properly size the view whenever you choose the "Update Frames" command in the canvas.

But I could not get it working.

How to create aspect ratio constraint: https://stackoverflow.com/questions/31334017/how-can-i-set-aspect-ratio-constraints-programmatically-in-ios

boyvanamstel earned $50.00 by resolving this issue!

Please make @objc available

Hi there,

love your app. Could you please add a few @objc to make public vars available from objective-c code?

Line 4 (necessary)
@objc public final class CircularProgress

Line 329 (var example)
'@objc public var onCancelled: (() -> Void)?'

etc. for other public vars

It's not necessary for IBInspectable as these are mapped automatically.

Please make isCancelled KV observable

Could you add

willChangeValue(for: \.isCancelled)

and

didChangeValue(for: \.isCancelled)

on line 367 to make isCancelled observeable. The completion onCancelled cannot be set when including in objective-c project. KVO would help to get cancelled state.

Great project!

SwiftUI and Combine support

https://developer.apple.com/tutorials/swiftui/
https://developer.apple.com/documentation/combine

  • Accept a AsyncSequence<Double, Never> to update the progress. (Does this make sense?)
  • Make it Swift View compatible by conforming to NSViewRepresentable
  • Expose SwiftUI bindings for the various states and ability to control states using bindings.
  • Add another example app that uses the SwiftUI interface and bindings.
  • Docs
  • Tests

Anything other ideas?


*This issue requires you to have advanced Swift knowledge.

Use strongly-typed KeyPath in `CALayer#animate()`

Issuehunt badges

In this extension:

extension CALayer {
// TODO: Find a way to use a strongly-typed KeyPath here.
// TODO: Accept NSColor instead of CGColor.
func animate(color: CGColor, keyPath: String, duration: Double) {
guard (value(forKey: keyPath) as! CGColor?) != color else {
return
}
let animation = CABasicAnimation(keyPath: keyPath)
animation.fromValue = value(forKey: keyPath)
animation.toValue = color
animation.duration = duration
animation.fillMode = .forwards
animation.isRemovedOnCompletion = false
add(animation, forKey: keyPath) { [weak self] _ in
self?.setValue(color, forKey: keyPath)
}
}
func add(_ animation: CAAnimation, forKey key: String?, completion: @escaping ((Bool) -> Void)) {
let animationDelegate = AnimationDelegate()
animationDelegate.didStopHandler = completion
animation.delegate = animationDelegate
add(animation, forKey: key)
}
}


IssueHunt Summary

fredyshox fredyshox has been rewarded.

Backers (Total: $40.00)

Submitted pull Requests


Tips


IssueHunt has been backed by the following sponsors. Become a sponsor

Set up automatic docs generation

I don't want to maintain a manual copy of the docs forever, but there are certain things I need before it's worth automating it:

  • GitHub Actions, so that I can automatically generate docs when a new Git tag is created. Yes, I could use Travis now, but I don't want to.
  • Jazzy / Swift support for showing default arguments. I think this will be supported in Swift 5, and Jazzy could then take advantage of it.

Expose a `lineWidth` property

Issuehunt badges

I tried changing 'lineWidthandradius` but it's not working. Please make it configurable.
Snip20190704_6


IssueHunt Summary

serhii-londar serhii-londar has been rewarded.

Backers (Total: $50.00)

Submitted pull Requests


Tips


IssueHunt has been backed by the following sponsors. Become a sponsor

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.