ActivityView.swift 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. //
  2. // ActivityButton.swift
  3. // KdanAuto
  4. //
  5. // Created by 朱东勇 on 2022/12/7.
  6. //
  7. import Foundation
  8. import AppKit
  9. enum ActivityStatus : Int {
  10. case Normal = 0
  11. case Wait = 1
  12. case Process = 2
  13. case Finished = 3
  14. }
  15. class ActivityView : NSView {
  16. var _status : ActivityStatus = ActivityStatus(rawValue: 0) ?? .Normal
  17. var _timer : Timer = Timer()
  18. var _titleLbl : NSTextField = NSTextField()
  19. let kActivityTitleHeight = 25.0
  20. var _activityView : NSProgressIndicator = NSProgressIndicator()
  21. // var _activityView : NSView = NSView()
  22. // var _angle : CGFloat = 0
  23. // var _shapeLayer : CAShapeLayer = CAShapeLayer()
  24. public override init(frame frameRect: NSRect) {
  25. super.init(frame: frameRect)
  26. if (self != nil) {
  27. loadSubviews()
  28. }
  29. }
  30. public required init?(coder: NSCoder) {
  31. super.init(coder: coder)
  32. if (self != nil) {
  33. loadSubviews()
  34. }
  35. }
  36. override func awakeFromNib() {
  37. super.awakeFromNib()
  38. loadSubviews()
  39. }
  40. override func layout() {
  41. reloadSubviews()
  42. }
  43. // Reload subviews
  44. func loadSubviews() {
  45. reloadSubviews()
  46. }
  47. func reloadSubviews() {
  48. self.wantsLayer = true
  49. self.layer?.backgroundColor = NSColor.clear.cgColor
  50. let width = self.frame.width
  51. let height = self.frame.height
  52. if nil == _titleLbl {
  53. _titleLbl = NSTextField.init(frame: self.frame)
  54. }
  55. _titleLbl.isSelectable = false
  56. _titleLbl.isEditable = false
  57. if nil == _titleLbl.superview {
  58. self.addSubview(_titleLbl)
  59. }
  60. _titleLbl.wantsLayer = true
  61. _titleLbl.frame = NSMakeRect(0, (height - kActivityTitleHeight) / 2.0, width, kActivityTitleHeight)
  62. _titleLbl.backgroundColor = NSColor.clear
  63. _titleLbl.layer?.backgroundColor = NSColor.clear.cgColor
  64. _titleLbl.autoresizingMask = .width.union(.minXMargin).union(.maxXMargin).union(.height)
  65. _titleLbl.alignment = .center
  66. _titleLbl.layer?.borderWidth = 1
  67. _titleLbl.layer?.cornerRadius = 4
  68. _titleLbl.textColor = NSColor.gray
  69. _titleLbl.layer?.borderColor = NSColor.lightGray.cgColor
  70. if nil == _activityView {
  71. _activityView = NSProgressIndicator.init(frame: self.bounds)
  72. }
  73. _activityView.controlSize = .small
  74. _activityView.style = .spinning
  75. if nil == _activityView.superview {
  76. self.addSubview(_activityView)
  77. }
  78. _activityView.startAnimation(self)
  79. let activitySize = kActivityTitleHeight
  80. // min(_activityView.frame.width, _activityView.frame.height)
  81. _activityView.frame = NSMakeRect((width - activitySize)/2.0,
  82. (height - activitySize)/2.0,
  83. activitySize,
  84. activitySize)
  85. //
  86. // if nil == _shapeLayer {
  87. // _shapeLayer = CAShapeLayer()
  88. // }
  89. // _shapeLayer.frame = _activityView.bounds
  90. // _activityView.wantsLayer = true;
  91. // _activityView.layer?.addSublayer(_shapeLayer)
  92. //
  93. // var mulPath = CGMutablePath()
  94. // let inRadius = activitySize/2 - 3
  95. // let outRadius = activitySize/2
  96. // let endRage = _angle - Double.pi / 3.0
  97. // mulPath.move(to: CGPointMake(activitySize/2.0 + inRadius*sin(_angle),
  98. // activitySize/2.0 + inRadius * cos(_angle)))
  99. // mulPath.addLine(to: CGPointMake(activitySize/2.0 + outRadius*sin(_angle),
  100. // activitySize/2.0 + outRadius * cos(_angle)))
  101. // mulPath.addArc(center: CGPoint(x: activitySize/2.0, y: activitySize/2.0),
  102. // radius: outRadius,
  103. // startAngle: _angle, endAngle: endRage, clockwise: true)
  104. // mulPath.addLine(to: CGPointMake(activitySize/2 + inRadius*sin(endRage),
  105. // activitySize/2 + inRadius * cos(endRage)))
  106. // mulPath.addArc(center: CGPoint(x: activitySize/2.0, y: activitySize/2.0),
  107. // radius: inRadius,
  108. // startAngle: endRage, endAngle: _angle, clockwise: false)
  109. // _shapeLayer.path = mulPath
  110. //// _shapeLayer.lineWidth = 5;
  111. //// _shapeLayer.lineJoin = .bevel
  112. //// _shapeLayer.lineCap = .square
  113. //// _shapeLayer.fillRule = .nonZero
  114. // _shapeLayer.fillColor = NSColor.blue.cgColor
  115. }
  116. /// Update Status
  117. func updateStatus() {
  118. _titleLbl.isHidden = (_status == .Normal || _status == .Process)
  119. // _titleLbl.layer?.opacity = (_status == .Normal || _status == .Process) ? 0:1
  120. _activityView.isHidden = (_status == .Normal || _status == .Wait || _status == .Finished)
  121. // _activityView.layer?.opacity = (_status == .Normal || _status == .Wait || _status == .Finished) ? 0:1
  122. switch _status {
  123. case .Wait: do {
  124. _titleLbl.textColor = NSColor.gray
  125. _titleLbl.layer?.borderColor = NSColor.lightGray.cgColor
  126. _titleLbl.stringValue = "Waiting"
  127. _timer.invalidate()
  128. _timer = Timer()
  129. }
  130. case .Process: do {
  131. // _timer = Timer.scheduledTimer(timeInterval: 1.0/30,
  132. // target: self,
  133. // selector: #selector(updateAnge),
  134. // userInfo: nil, repeats: true)
  135. }
  136. case .Finished: do {
  137. _titleLbl.textColor = NSColor.blue
  138. _titleLbl.layer?.borderColor = NSColor.blue.cgColor
  139. _titleLbl.stringValue = "Done"
  140. _timer.invalidate()
  141. _timer = Timer()
  142. }
  143. default: do {
  144. _titleLbl.stringValue = ""
  145. _timer.invalidate()
  146. _timer = Timer()
  147. }
  148. }
  149. }
  150. // @objc func updateAnge() {
  151. // _angle = self._angle + Double.pi/30.0
  152. //
  153. //
  154. // let width = self.frame.width
  155. // let height = self.frame.height
  156. //
  157. // let activitySize = min(width, height)
  158. // var mulPath = CGMutablePath()
  159. // let inRadius = activitySize/2 - 3
  160. // let outRadius = activitySize/2
  161. // let endRage = self._angle - Double.pi / 3.0
  162. // mulPath.move(to: CGPointMake(activitySize/2.0 + inRadius*sin(self._angle),
  163. // activitySize/2.0 + inRadius * cos(self._angle)))
  164. // mulPath.addLine(to: CGPointMake(activitySize/2.0 + outRadius*sin(self._angle),
  165. // activitySize/2.0 + outRadius * cos(self._angle)))
  166. // mulPath.addArc(center: CGPoint(x: activitySize/2.0, y: activitySize/2.0),
  167. // radius: outRadius,
  168. // startAngle: self._angle, endAngle: endRage, clockwise: true)
  169. // mulPath.addLine(to: CGPointMake(activitySize/2 + inRadius*sin(endRage),
  170. // activitySize/2 + inRadius * cos(endRage)))
  171. // mulPath.addArc(center: CGPoint(x: activitySize/2.0, y: activitySize/2.0),
  172. // radius: inRadius,
  173. // startAngle: endRage, endAngle: self._angle, clockwise: false)
  174. // self._shapeLayer.path = mulPath
  175. // }
  176. /// Setter & Getter
  177. ///
  178. func setActivityStatus(_ status:ActivityStatus) {
  179. // if (_status != status) {
  180. _status = status
  181. updateStatus()
  182. // }
  183. }
  184. func activityStatus() -> ActivityStatus {
  185. return _status
  186. }
  187. }