93 lines
2.9 KiB
Swift
93 lines
2.9 KiB
Swift
//
|
|
// CheckmarkView.swift
|
|
// PrivadoVPN
|
|
//
|
|
// Created by Murad Shabanov on 05.08.2021.
|
|
// Copyright © 2021 Privado LLC. All rights reserved.
|
|
|
|
//
|
|
import Cocoa
|
|
|
|
final class CheckmarkView: NSView {
|
|
private var checkmarkLayer = CAShapeLayer()
|
|
private let configuration: Configuration
|
|
private var animationCompletion: (() -> Void)?
|
|
|
|
init(with configuration: Configuration) {
|
|
self.configuration = configuration
|
|
super.init(frame: .zero)
|
|
configureView()
|
|
}
|
|
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func layout() {
|
|
super.layout()
|
|
checkmarkLayer.path = makeCheckmarkPath()
|
|
}
|
|
|
|
override var isFlipped: Bool {
|
|
return true
|
|
}
|
|
|
|
private func configureView() {
|
|
wantsLayer = true
|
|
|
|
checkmarkLayer.fillColor = NSColor.clear.cgColor
|
|
checkmarkLayer.lineWidth = configuration.menuItemCheckmarkThikness
|
|
checkmarkLayer.path = makeCheckmarkPath()
|
|
checkmarkLayer.strokeEnd = 0
|
|
checkmarkLayer.strokeColor = configuration.menuItemCheckmarkColor.cgColor
|
|
checkmarkLayer.lineCap = CAShapeLayerLineCap.round
|
|
checkmarkLayer.lineJoin = CAShapeLayerLineJoin.round
|
|
layer?.addSublayer(checkmarkLayer)
|
|
}
|
|
|
|
public func animate(duration: TimeInterval = 0.15, with completion: (() -> Void)? = nil) {
|
|
guard duration != 0 else {
|
|
CATransaction.begin()
|
|
CATransaction.setDisableActions(true)
|
|
checkmarkLayer.strokeEnd = 1
|
|
CATransaction.commit()
|
|
completion?()
|
|
return
|
|
}
|
|
animationCompletion = completion
|
|
let animation = CABasicAnimation(keyPath: "strokeEnd")
|
|
animation.delegate = self
|
|
animation.fromValue = 0
|
|
animation.toValue = 1
|
|
animation.timingFunction = .easeInEaseOut
|
|
animation.duration = duration
|
|
animation.isRemovedOnCompletion = false
|
|
|
|
checkmarkLayer.strokeEnd = 1
|
|
checkmarkLayer.add(animation, forKey: "animateCheckmark")
|
|
}
|
|
|
|
private func makeCheckmarkPath() -> CGPath {
|
|
let scale = bounds.width / 100
|
|
let centerX = bounds.size.width / 2
|
|
let centerY = bounds.size.height / 2
|
|
|
|
let path = CGMutablePath()
|
|
let center = CGPoint(x: centerX, y: centerY)
|
|
let startAngle = CGFloat(Double.pi)
|
|
let endAngle = CGFloat(Double.pi) * 5
|
|
|
|
path.addArc(center: center, radius: centerX, startAngle: startAngle, endAngle: endAngle, clockwise: true)
|
|
path.move(to: CGPoint(x: centerX - 23 * scale, y: centerY - 1 * scale))
|
|
path.addLine(to: CGPoint(x: centerX - 6 * scale, y: centerY + 15.9 * scale))
|
|
path.addLine(to: CGPoint(x: centerX + 22.8 * scale, y: centerY - 13.4 * scale))
|
|
return path
|
|
}
|
|
}
|
|
|
|
extension CheckmarkView: CAAnimationDelegate {
|
|
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
|
|
animationCompletion?()
|
|
}
|
|
}
|