// // CustomAlertView.swift // PDF Master // // Created by wanjun on 2023/10/7. // import Cocoa enum KMCustomAlertStyle: Int { case black case blue } class CustomAlertView: NSView { override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) // Drawing code here. } static func alertView(message: String, fromView supverView: NSView, withStyle alertStyle: KMCustomAlertStyle, backgroundColor color: NSColor?) -> CustomAlertView? { if alertStyle != .black && alertStyle != .blue { return nil } let view = CustomAlertView() let style = NSMutableParagraphStyle() style.lineBreakMode = .byWordWrapping var fontSize: CGFloat = 0 var offsetSize = CGSize.zero if alertStyle == .black { fontSize = 16 } else { fontSize = 12 } let attributes: [NSAttributedString.Key: Any] = [ .font: NSFont.systemFont(ofSize: fontSize), .paragraphStyle: style ] let maxSize = CGSize(width: min(supverView.frame.size.width - 80, 500), height: supverView.frame.size.height - 40) let size = message.boundingRect(with: maxSize, options: [.truncatesLastVisibleLine, .usesLineFragmentOrigin, .usesFontLeading], attributes: attributes).size let ceilSize = NSSize(width: ceil(size.width), height: ceil(size.height)) if alertStyle == .black { offsetSize = NSSize(width: ceilSize.width + 60, height: ceilSize.height + 30) view.frame = NSRect(x: (supverView.frame.size.width - offsetSize.width) / 2, y: (supverView.frame.size.height - offsetSize.height) / 2, width: offsetSize.width, height: offsetSize.height) } else { offsetSize = NSSize(width: ceilSize.width + ceilSize.height + 14 + 10, height: ceilSize.height + 14) view.frame = NSRect(x: (supverView.frame.size.width - offsetSize.width) / 2, y: (supverView.frame.size.height - offsetSize.height) - 10, width: offsetSize.width, height: offsetSize.height) } supverView.addSubview(view) view.wantsLayer = true let messageLabel: NSTextField if alertStyle == .black { view.layer?.cornerRadius = 8 if let color1 = color { view.layer?.backgroundColor = color1.cgColor } else { view.layer?.backgroundColor = NSColor.black.withAlphaComponent(0.7).cgColor } messageLabel = NSTextField(frame: NSRect(x: 15, y: 15, width: ceilSize.width + 30, height: ceilSize.height)) } else { view.layer?.cornerRadius = view.frame.size.height / 2 if let color1 = color { view.layer?.backgroundColor = color1.cgColor } else { view.layer?.backgroundColor = NSColor(red: 78/255.0, green: 163/255.0, blue: 255/255.0, alpha: 1).cgColor } messageLabel = NSTextField(frame: NSRect(x: view.frame.size.height / 2, y: 7, width: ceilSize.width + 10, height: ceilSize.height)) } messageLabel.font = NSFont.systemFont(ofSize: fontSize) messageLabel.textColor = NSColor.white messageLabel.backgroundColor = NSColor.clear messageLabel.isBordered = false messageLabel.isEditable = false if #available(OSX 10.11, *) { messageLabel.lineBreakMode = .byWordWrapping } messageLabel.alignment = .center messageLabel.stringValue = message view.addSubview(messageLabel) view.alphaAnimation(from: 0, to: 1, duration: 0.3) { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { view.alphaAnimation(from: 1.0, to: 0.0, duration: 0.3) { view.removeFromSuperview() } } } return view } static func alertView(message: String, fromView supverView: NSView, withStyle alertStyle: KMCustomAlertStyle) -> CustomAlertView? { return CustomAlertView.alertView(message: message, fromView: supverView, withStyle: alertStyle, backgroundColor: nil) } func alphaAnimation(from fromValue: Float, to toValue: Float, duration: Float, finishedBlock block: @escaping () -> Void) { let flash = CABasicAnimation(keyPath: "opacity") flash.fromValue = NSNumber(value: fromValue) flash.toValue = NSNumber(value: toValue) flash.duration = 0.5 self.layer?.add(flash, forKey: "flashAnimation") DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(duration)) { block() } } }