|
|
|
@ -1,13 +1,14 @@
|
|
|
|
|
// Copyright © 2015 Abhishek Banthia |
|
|
|
|
|
|
|
|
|
import Foundation |
|
|
|
|
import AppKit |
|
|
|
|
import Foundation |
|
|
|
|
|
|
|
|
|
extension CGRect { |
|
|
|
|
static func center(of layer: CALayer) -> CGPoint { |
|
|
|
|
let parentSize = layer.frame.size |
|
|
|
|
return CGPoint(x: parentSize.width / 2, y: parentSize.height / 2) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static func center(of parent: NSView) -> CGPoint { |
|
|
|
|
let parentSize = parent.frame.size |
|
|
|
|
return CGPoint(x: parentSize.width / 2, y: parentSize.height / 6) |
|
|
|
@ -22,18 +23,21 @@ extension String {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate class HideAnimationDelegate: NSObject, CAAnimationDelegate { |
|
|
|
|
private class HideAnimationDelegate: NSObject, CAAnimationDelegate { |
|
|
|
|
private weak var view: NSView? |
|
|
|
|
fileprivate init(view: NSView) { |
|
|
|
|
self.view = view |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fileprivate static func delegate(forView NSView: NSView) -> CAAnimationDelegate { |
|
|
|
|
return HideAnimationDelegate(view: NSView) |
|
|
|
|
} |
|
|
|
|
fileprivate func animationDidStart(_ anim: CAAnimation) { |
|
|
|
|
|
|
|
|
|
fileprivate func animationDidStart(_: CAAnimation) { |
|
|
|
|
view?.layer?.opacity = 0.0 |
|
|
|
|
} |
|
|
|
|
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { |
|
|
|
|
|
|
|
|
|
func animationDidStop(_: CAAnimation, finished _: Bool) { |
|
|
|
|
view?.removeFromSuperview() |
|
|
|
|
view = nil |
|
|
|
|
} |
|
|
|
@ -55,46 +59,48 @@ func hideAnimation(view: NSView, style: Style) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public protocol Style { |
|
|
|
|
var fontSize: CGFloat {get} |
|
|
|
|
var horizontalMargin: CGFloat {get} |
|
|
|
|
var verticalMargin: CGFloat {get} |
|
|
|
|
var cornerRadius: CGFloat {get} |
|
|
|
|
var font: NSFont {get} |
|
|
|
|
var backgroundColor: NSColor {get} |
|
|
|
|
var foregroundColor: NSColor {get} |
|
|
|
|
var fadeInOutDuration: CGFloat {get} |
|
|
|
|
var fadeInOutDelay: CGFloat {get} |
|
|
|
|
var labelOriginWithMargin: CGPoint {get} |
|
|
|
|
var activitySize: CGSize {get} |
|
|
|
|
var fontSize: CGFloat { get } |
|
|
|
|
var horizontalMargin: CGFloat { get } |
|
|
|
|
var verticalMargin: CGFloat { get } |
|
|
|
|
var cornerRadius: CGFloat { get } |
|
|
|
|
var font: NSFont { get } |
|
|
|
|
var backgroundColor: NSColor { get } |
|
|
|
|
var foregroundColor: NSColor { get } |
|
|
|
|
var fadeInOutDuration: CGFloat { get } |
|
|
|
|
var fadeInOutDelay: CGFloat { get } |
|
|
|
|
var labelOriginWithMargin: CGPoint { get } |
|
|
|
|
var activitySize: CGSize { get } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
extension Style { |
|
|
|
|
public var labelOriginWithMargin: CGPoint { |
|
|
|
|
public extension Style { |
|
|
|
|
var labelOriginWithMargin: CGPoint { |
|
|
|
|
return CGPoint(x: horizontalMargin, y: verticalMargin) |
|
|
|
|
} |
|
|
|
|
public var fontSize: CGFloat {return 12} |
|
|
|
|
public var font: NSFont { |
|
|
|
|
|
|
|
|
|
var fontSize: CGFloat { return 12 } |
|
|
|
|
var font: NSFont { |
|
|
|
|
if let avenirFont = NSFont(name: "Avenir-Light", size: fontSize) { |
|
|
|
|
return avenirFont |
|
|
|
|
} |
|
|
|
|
return NSFont.systemFont(ofSize: fontSize) |
|
|
|
|
} |
|
|
|
|
public var horizontalMargin: CGFloat {return 10} |
|
|
|
|
public var verticalMargin: CGFloat {return 5} |
|
|
|
|
public var cornerRadius: CGFloat {return 8} |
|
|
|
|
public var backgroundColor: NSColor {return .black} |
|
|
|
|
public var foregroundColor: NSColor {return .white} |
|
|
|
|
public var activitySize: CGSize {return CGSize(width: 100, height: 100)} |
|
|
|
|
public var fadeInOutDuration: CGFloat {return 1.0} |
|
|
|
|
public var fadeInOutDelay: CGFloat {return 1.0} |
|
|
|
|
|
|
|
|
|
var horizontalMargin: CGFloat { return 10 } |
|
|
|
|
var verticalMargin: CGFloat { return 5 } |
|
|
|
|
var cornerRadius: CGFloat { return 8 } |
|
|
|
|
var backgroundColor: NSColor { return .black } |
|
|
|
|
var foregroundColor: NSColor { return .white } |
|
|
|
|
var activitySize: CGSize { return CGSize(width: 100, height: 100) } |
|
|
|
|
var fadeInOutDuration: CGFloat { return 1.0 } |
|
|
|
|
var fadeInOutDelay: CGFloat { return 1.0 } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public struct DefaultStyle: Style { |
|
|
|
|
public static let shared = DefaultStyle() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private struct ToastKeys { |
|
|
|
|
static var ActiveToast = "TSToastActiveToastKey" |
|
|
|
|
private enum ToastKeys { |
|
|
|
|
static var ActiveToast = "TSToastActiveToastKey" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
class ToastView: NSView { |
|
|
|
@ -103,31 +109,33 @@ class ToastView: NSView {
|
|
|
|
|
private let style: Style |
|
|
|
|
init(message: String) { |
|
|
|
|
self.message = message |
|
|
|
|
self.style = DefaultStyle() |
|
|
|
|
self.labelSize = message.size(with: style.fontSize) |
|
|
|
|
style = DefaultStyle() |
|
|
|
|
labelSize = message.size(with: style.fontSize) |
|
|
|
|
let size = CGSize( |
|
|
|
|
width: labelSize.width + style.horizontalMargin*2, |
|
|
|
|
height: labelSize.height + style.verticalMargin*2 |
|
|
|
|
width: labelSize.width + style.horizontalMargin * 2, |
|
|
|
|
height: labelSize.height + style.verticalMargin * 2 |
|
|
|
|
) |
|
|
|
|
let rect = CGRect(origin: .zero, size: size) |
|
|
|
|
super.init(frame: rect) |
|
|
|
|
wantsLayer = true |
|
|
|
|
} |
|
|
|
|
required init?(coder aDecoder: NSCoder) { fatalError() } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@available(*, unavailable) |
|
|
|
|
required init?(coder _: NSCoder) { fatalError() } |
|
|
|
|
|
|
|
|
|
override func viewDidMoveToSuperview() { |
|
|
|
|
super.viewDidMoveToSuperview() |
|
|
|
|
if superview != nil { |
|
|
|
|
configure() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private func configure() { |
|
|
|
|
frame = superview?.bounds ?? NSRect.zero |
|
|
|
|
let rect = CGRect(origin: style.labelOriginWithMargin, size: labelSize) |
|
|
|
|
let sizeWithMargin = CGSize( |
|
|
|
|
width: rect.width + style.horizontalMargin*2, |
|
|
|
|
height: rect.height + style.verticalMargin*2 |
|
|
|
|
width: rect.width + style.horizontalMargin * 2, |
|
|
|
|
height: rect.height + style.verticalMargin * 2 |
|
|
|
|
) |
|
|
|
|
let rectWithMargin = CGRect( |
|
|
|
|
origin: .zero, // position is manipulated later anyways |
|
|
|
@ -155,10 +163,10 @@ class ToastView: NSView {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
extension NSView { |
|
|
|
|
public func makeToast(_ message: String) { |
|
|
|
|
public extension NSView { |
|
|
|
|
func makeToast(_ message: String) { |
|
|
|
|
let toast = ToastView(message: message) |
|
|
|
|
self.addSubview(toast) |
|
|
|
|
addSubview(toast) |
|
|
|
|
hideAnimation(view: toast, style: DefaultStyle.shared) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|