// // 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() public override init(frame frameRect: NSRect) { super.init(frame: frameRect) if (self != nil) { loadSubviews() } } public required init?(coder: NSCoder) { super.init(coder: coder) if (self != nil) { loadSubviews() } } override func awakeFromNib() { super.awakeFromNib() loadSubviews() } 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.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 _titleLbl.textColor = NSColor.gray _titleLbl.layer?.borderColor = NSColor.lightGray.cgColor 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 = "Waiting" _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.textColor = NSColor.blue _titleLbl.layer?.borderColor = NSColor.blue.cgColor _titleLbl.stringValue = "Done" _timer.invalidate() _timer = Timer() } default: do { _titleLbl.stringValue = "" _timer.invalidate() _timer = Timer() } } } // @objc func updateAnge() { // _angle = self._angle + Double.pi/30.0 // // // let width = self.frame.width // let height = self.frame.height // // let activitySize = min(width, height) // var mulPath = CGMutablePath() // let inRadius = activitySize/2 - 3 // let outRadius = activitySize/2 // let endRage = self._angle - Double.pi / 3.0 // mulPath.move(to: CGPointMake(activitySize/2.0 + inRadius*sin(self._angle), // activitySize/2.0 + inRadius * cos(self._angle))) // mulPath.addLine(to: CGPointMake(activitySize/2.0 + outRadius*sin(self._angle), // activitySize/2.0 + outRadius * cos(self._angle))) // mulPath.addArc(center: CGPoint(x: activitySize/2.0, y: activitySize/2.0), // radius: outRadius, // startAngle: self._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: self._angle, clockwise: false) // self._shapeLayer.path = mulPath // } /// Setter & Getter /// func setActivityStatus(_ status:ActivityStatus) { // if (_status != status) { _status = status updateStatus() // } } func activityStatus() -> ActivityStatus { return _status } }