// // ActivityButton.swift // KdanAuto // // Created by 朱东勇 on 2022/12/7. // import Foundation import AppKit enum ActivityStatus : Int { case Normal = 0 case Wait = 1 case Process = 2 case Finished = 3 } class ActivityView : NSView { var _status : ActivityStatus = ActivityStatus(rawValue: 0) ?? .Normal var _timer : Timer = Timer() var _titleLbl : NSTextField = NSTextField() let kActivityTitleHeight = 25.0 var _activityView : NSProgressIndicator = NSProgressIndicator() // var _activityView : NSView = NSView() // var _angle : CGFloat = 0 // var _shapeLayer : CAShapeLayer = CAShapeLayer() var _degree : Double = 0 public override init(frame frameRect: NSRect) { super.init(frame: frameRect) loadSubviews() } public required init?(coder: NSCoder) { super.init(coder: coder) loadSubviews() } override func awakeFromNib() { super.awakeFromNib() loadSubviews() updateStatus() } override func layout() { reloadSubviews() } // Reload subviews func loadSubviews() { reloadSubviews() } func reloadSubviews() { self.wantsLayer = true self.layer?.backgroundColor = NSColor.clear.cgColor let width = self.frame.width let height = self.frame.height // if nil == _titleLbl { // _titleLbl = NSTextField.init(frame: self.frame) // } _titleLbl.isSelectable = false _titleLbl.isEditable = false if nil == _titleLbl.superview { self.addSubview(_titleLbl) } _titleLbl.wantsLayer = true _titleLbl.frame = NSMakeRect(0, (height - kActivityTitleHeight) / 2.0, width, kActivityTitleHeight) _titleLbl.backgroundColor = NSColor.clear _titleLbl.font = NSFont.systemFont(ofSize: 12.0) _titleLbl.layer?.backgroundColor = NSColor.clear.cgColor _titleLbl.autoresizingMask = .width.union(.minXMargin).union(.maxXMargin).union(.height) _titleLbl.alignment = .center _titleLbl.layer?.borderWidth = 1 _titleLbl.layer?.cornerRadius = 4 // if nil == _activityView { // _activityView = NSProgressIndicator.init(frame: self.bounds) // } _activityView.controlSize = .small _activityView.style = .spinning if nil == _activityView.superview { self.addSubview(_activityView) } _activityView.startAnimation(self) let activitySize = kActivityTitleHeight // min(_activityView.frame.width, _activityView.frame.height) _activityView.frame = NSMakeRect((width - activitySize)/2.0, (height - activitySize)/2.0, activitySize, activitySize) // // if nil == _shapeLayer { // _shapeLayer = CAShapeLayer() // } // _shapeLayer.frame = _activityView.bounds // _activityView.wantsLayer = true; // _activityView.layer?.addSublayer(_shapeLayer) // // var mulPath = CGMutablePath() // let inRadius = activitySize/2 - 3 // let outRadius = activitySize/2 // let endRage = _angle - Double.pi / 3.0 // mulPath.move(to: CGPointMake(activitySize/2.0 + inRadius*sin(_angle), // activitySize/2.0 + inRadius * cos(_angle))) // mulPath.addLine(to: CGPointMake(activitySize/2.0 + outRadius*sin(_angle), // activitySize/2.0 + outRadius * cos(_angle))) // mulPath.addArc(center: CGPoint(x: activitySize/2.0, y: activitySize/2.0), // radius: outRadius, // startAngle: _angle, endAngle: endRage, clockwise: true) // mulPath.addLine(to: CGPointMake(activitySize/2 + inRadius*sin(endRage), // activitySize/2 + inRadius * cos(endRage))) // mulPath.addArc(center: CGPoint(x: activitySize/2.0, y: activitySize/2.0), // radius: inRadius, // startAngle: endRage, endAngle: _angle, clockwise: false) // _shapeLayer.path = mulPath //// _shapeLayer.lineWidth = 5; //// _shapeLayer.lineJoin = .bevel //// _shapeLayer.lineCap = .square //// _shapeLayer.fillRule = .nonZero // _shapeLayer.fillColor = NSColor.blue.cgColor } /// Update Status func updateStatus() { _titleLbl.isHidden = (_status == .Normal || _status == .Process) // _titleLbl.layer?.opacity = (_status == .Normal || _status == .Process) ? 0:1 _activityView.isHidden = (_status == .Normal || _status == .Wait || _status == .Finished) // _activityView.layer?.opacity = (_status == .Normal || _status == .Wait || _status == .Finished) ? 0:1 switch _status { case .Wait: do { _titleLbl.textColor = NSColor.gray _titleLbl.layer?.borderColor = NSColor.lightGray.cgColor _titleLbl.stringValue = "等待中..." _timer.invalidate() _timer = Timer() } case .Process: do { // _timer = Timer.scheduledTimer(timeInterval: 1.0/30, // target: self, // selector: #selector(updateAnge), // userInfo: nil, repeats: true) } case .Finished: do { _titleLbl.stringValue = NSString(format: "完成 %.0f%%", floor(_degree)) as String if fabs(_degree-100)>=0.1 { _titleLbl.textColor = NSColor.red _titleLbl.layer?.borderColor = NSColor.red.cgColor }else { _titleLbl.textColor = NSColor.blue _titleLbl.layer?.borderColor = NSColor.blue.cgColor } _timer.invalidate() _timer = Timer() } default: do { _titleLbl.stringValue = "" _timer.invalidate() _timer = Timer() } } } /// Setter & Getter /// func setActivityStatus(_ status:ActivityStatus) { // if (_status != status) { _status = status updateStatus() // } } func activityStatus() -> ActivityStatus { return _status } func setDegree(_ degree:Double) { _degree = degree; updateStatus() } }