KMReadModelView.swift 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. //
  2. // KMReadModelView.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lizhe on 2023/3/23.
  6. //
  7. import Cocoa
  8. enum KMReadModelViewScaleType: String, CaseIterable {
  9. case fitWidth = "Fit"
  10. case actualSize = "Actual Size"
  11. case autoSize = "Auto"
  12. case _10 = "10%"
  13. case _25 = "25%"
  14. case _50 = "50%"
  15. case _100 = "100%"
  16. case _150 = "150%"
  17. case _200 = "200%"
  18. case _400 = "400%"
  19. case _800 = "800%"
  20. static func allValues() -> [String] {
  21. var array: [String] = []
  22. for key in KMReadModelViewScaleType.allCases {
  23. array.append(NSLocalizedString(key.rawValue, comment: ""))
  24. }
  25. return array
  26. }
  27. static func typeOfRawValue(value: String) -> KMReadModelViewScaleType {
  28. var type: KMReadModelViewScaleType
  29. switch value {
  30. case NSLocalizedString(KMReadModelViewScaleType.fitWidth.rawValue, comment: ""): type = .fitWidth
  31. case NSLocalizedString(KMReadModelViewScaleType.actualSize.rawValue, comment: ""): type = .actualSize
  32. case NSLocalizedString(KMReadModelViewScaleType.autoSize.rawValue, comment: ""): type = .autoSize
  33. case KMReadModelViewScaleType._10.rawValue: type = ._10
  34. case KMReadModelViewScaleType._25.rawValue: type = ._25
  35. case KMReadModelViewScaleType._50.rawValue: type = ._50
  36. case KMReadModelViewScaleType._100.rawValue: type = ._100
  37. case KMReadModelViewScaleType._150.rawValue: type = ._150
  38. case KMReadModelViewScaleType._200.rawValue: type = ._200
  39. case KMReadModelViewScaleType._400.rawValue: type = ._400
  40. case KMReadModelViewScaleType._800.rawValue: type = ._800
  41. default:
  42. type = .autoSize
  43. }
  44. return type
  45. }
  46. }
  47. protocol KMReadModelViewDelegate: NSObject {
  48. func firstPageButtonDidChange(view: KMReadModelView, sender: Any)
  49. func beforePageButtonDidChange(view: KMReadModelView, sender: Any)
  50. func afterPageButtonDidChange(view: KMReadModelView, sender: Any)
  51. func lastPageButtonDidChange(view: KMReadModelView, sender: Any)
  52. func currentPageButtonDidChange(view: KMReadModelView, sender: Any, pageIndex: Int)
  53. func scaleDidChange(view: KMReadModelView, sender: Any, type: KMReadModelViewScaleType)
  54. func cancelReadModel(view: KMReadModelView, sender: Any)
  55. func readModelViewWidthChange(view: KMReadModelView, width: CGFloat)
  56. }
  57. class KMReadModelView: BaseXibView {
  58. @IBOutlet weak var firstPageView: NSView!
  59. @IBOutlet weak var beforePageView: NSView!
  60. @IBOutlet weak var currentPageView: NSView!
  61. @IBOutlet weak var totalPageView: NSTextField!
  62. @IBOutlet weak var afterPageView: NSView!
  63. @IBOutlet weak var lastPageView: NSView!
  64. @IBOutlet weak var totalLable: NSTextField!
  65. @IBOutlet weak var zoomView: NSView!
  66. @IBOutlet weak var backgroundContentView: NSView!
  67. @IBOutlet weak var currentPageTextField: NSTextField!
  68. @IBOutlet weak var currentPageBackgroundView: NSView!
  69. @IBOutlet weak var contentBox: KMBox!
  70. @IBOutlet weak var contentViewWidthConstraint: NSLayoutConstraint!
  71. @IBOutlet weak var currentContentViewWidthConstraint: NSLayoutConstraint!
  72. @IBOutlet weak var totalPageCountWidthConstraint: NSLayoutConstraint!
  73. @IBOutlet weak var scaleWidthConstraint: NSLayoutConstraint!
  74. var firstPageButton: KMDesignButton!
  75. var beforePageButton: KMDesignButton!
  76. var afterPageButton: KMDesignButton!
  77. var lastPageButton: KMDesignButton!
  78. var zoomButton: KMDesignSelect!
  79. var timer: Timer?
  80. weak var delegate: KMReadModelViewDelegate?
  81. var currentPageIndex: Int? {
  82. didSet {
  83. self.currentPageTextField.stringValue = (currentPageIndex! + 1).description
  84. self.updateButtonState()
  85. self.updateUI()
  86. }
  87. }
  88. var totalPagesCount: Int? {
  89. didSet {
  90. self.totalLable.stringValue = totalPagesCount?.description ?? "1"
  91. self.updateButtonState()
  92. self.updateUI()
  93. }
  94. }
  95. var scaleType: KMReadModelViewScaleType? {
  96. didSet {
  97. self.zoomButton.selectItem(at: KMReadModelViewScaleType.allValues().firstIndex(of: scaleType!.rawValue)!)
  98. }
  99. }
  100. deinit {
  101. self.endTimer()
  102. }
  103. override func draw(_ dirtyRect: NSRect) {
  104. super.draw(dirtyRect)
  105. // Drawing code here.
  106. }
  107. func setup() {
  108. self.backgroundColor(NSColor.km_init(hex: "#FFFFFF"))
  109. self.shadow = NSShadow()
  110. self.wantsLayer = true
  111. self.layer?.shadowColor = NSColor.km_init(hex: "#000000", alpha: 0.16).cgColor
  112. self.layer?.shadowOffset = CGSize(width: 0, height: -2)
  113. self.layer?.shadowRadius = 8
  114. self.layer?.shadowOpacity = 1
  115. self.layer?.cornerRadius = 4
  116. firstPageButton = KMDesignButton(withType: .Image)
  117. self.firstPageView.addSubview(firstPageButton.view)
  118. firstPageButton.view.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
  119. firstPageButton.target = self
  120. firstPageButton.image = NSImage(named: "icon_btn_readModel_first")!
  121. firstPageButton.image_disabled = NSImage(named: "icon_btn_readModel_first_dis")!
  122. firstPageButton.action = #selector(firstPageButtonAction)
  123. firstPageButton.pagination()
  124. firstPageButton.borderWidth = 1
  125. firstPageButton.borderColor = NSColor.km_init(hex: "#DFE1E5")
  126. firstPageButton.updateUI()
  127. beforePageButton = KMDesignButton(withType: .Image)
  128. self.beforePageView.addSubview(beforePageButton.view)
  129. beforePageButton.view.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
  130. beforePageButton.target = self
  131. beforePageButton.image = NSImage(named: "icon_btn_readModel_before")!
  132. beforePageButton.image_disabled = NSImage(named: "icon_btn_readModel_before_dis")!
  133. beforePageButton.action = #selector(beforePageButtonAction)
  134. beforePageButton.pagination()
  135. beforePageButton.borderWidth = 1
  136. beforePageButton.borderColor = NSColor.km_init(hex: "#DFE1E5")
  137. beforePageButton.updateUI()
  138. afterPageButton = KMDesignButton(withType: .Image)
  139. self.afterPageView.addSubview(afterPageButton.view)
  140. afterPageButton.view.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
  141. afterPageButton.target = self
  142. afterPageButton.image = NSImage(named: "icon_btn_readModel_after")!
  143. afterPageButton.image_disabled = NSImage(named: "icon_btn_readModel_after_dis")!
  144. afterPageButton.action = #selector(afterPageButtonAction)
  145. afterPageButton.pagination()
  146. afterPageButton.borderWidth = 1
  147. afterPageButton.borderColor = NSColor.km_init(hex: "#DFE1E5")
  148. afterPageButton.updateUI()
  149. lastPageButton = KMDesignButton(withType: .Image)
  150. self.lastPageView.addSubview(lastPageButton.view)
  151. lastPageButton.view.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
  152. lastPageButton.target = self
  153. lastPageButton.image = NSImage(named: "icon_btn_readModel_last")!
  154. lastPageButton.image_disabled = NSImage(named: "icon_btn_readModel_last_dis")!
  155. lastPageButton.action = #selector(lastPageButtonAction)
  156. lastPageButton.pagination()
  157. lastPageButton.borderWidth = 1
  158. lastPageButton.borderColor = NSColor.km_init(hex: "#DFE1E5")
  159. lastPageButton.updateUI()
  160. zoomButton = KMDesignSelect(withType: .PopButton)
  161. self.zoomView.addSubview(zoomButton.view)
  162. zoomButton.view.frame = CGRect(x: 0, y: 0, width: 65, height: 24)
  163. zoomButton.selectItem(at: 0)
  164. zoomButton.delete = self
  165. zoomButton.font = NSFont.SFProTextRegularFont(12.0)
  166. zoomButton.font_hov = NSFont.SFProTextRegularFont(12.0)
  167. zoomButton.font_focus = NSFont.SFProTextRegularFont(12.0)
  168. zoomButton.font_disabled = NSFont.SFProTextRegularFont(12.0)
  169. zoomButton.borderWidth = 0
  170. zoomButton.updateUI()
  171. currentPageBackgroundView.border(NSColor.km_init(hex: "#DFE1E5"), 1, 4)
  172. currentPageTextField.textColor = NSColor.km_init(hex: "#252629")
  173. currentPageTextField.font = NSFont.SFProTextRegularFont(12.0)
  174. currentPageTextField.delegate = self
  175. totalLable.textColor = NSColor.km_init(hex: "#252629")
  176. totalLable.font = NSFont.SFProTextRegularFont(12.0)
  177. contentBox.moveCallback = { [unowned self] (enter, box) in
  178. if enter {
  179. self.inReadModelView()
  180. } else {
  181. self.beginTimer()
  182. }
  183. }
  184. }
  185. //刷新界面UI 和 数据
  186. func reloadData() {
  187. }
  188. func updateLanguage() {
  189. zoomButton.removeAllItems()
  190. zoomButton.addItems(withObjectValues: KMReadModelViewScaleType.allValues())
  191. }
  192. func updateUI() {
  193. let width = self.fetchWidth()
  194. // if self.contentViewWidthConstraint.constant != width {
  195. self.delegate?.readModelViewWidthChange(view: self, width: width)
  196. // }
  197. self.contentViewWidthConstraint.constant = width
  198. self.currentContentViewWidthConstraint.constant = self.fetchCurrentPageIndexWidth(string: self.currentPageTextField.stringValue as NSString)
  199. self.totalPageCountWidthConstraint.constant = self.fetchTotalPageIndexWidth(string: self.totalPageView.stringValue as NSString)
  200. self.scaleWidthConstraint.constant = self.fetchScaleWidth(string: self.zoomButton.stringValue as NSString)
  201. zoomButton.view.frame = self.zoomView.bounds
  202. }
  203. }
  204. //MARK: data
  205. extension KMReadModelView {
  206. func fetchWidth() -> CGFloat {
  207. var width = 16.0
  208. width += self.firstPageView.frame.size.width
  209. width += 8.0
  210. width += self.beforePageView.frame.size.width
  211. width += 8.0
  212. width += self.fetchCurrentPageIndexWidth(string: self.currentPageTextField.stringValue as NSString)
  213. width += 8.0
  214. width += 4.0
  215. width += 8.0
  216. width += self.fetchTotalPageIndexWidth(string: self.totalLable.stringValue as NSString)
  217. width += 8.0
  218. width += self.afterPageView.frame.size.width
  219. width += 8.0
  220. width += self.lastPageView.frame.size.width
  221. width += 16.0
  222. width += self.fetchScaleWidth(string: self.zoomButton.stringValue as NSString)
  223. width += 16.0
  224. return width
  225. }
  226. func fetchCurrentPageIndexWidth(string: NSString) -> CGFloat {
  227. var width = 28.0
  228. let attributes = [NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0)]
  229. width += string.boundingRect(with: CGSize(width: 100, height: 24), attributes: attributes).size.width
  230. width = max(width, 48)
  231. return width
  232. }
  233. func fetchTotalPageIndexWidth(string: NSString) -> CGFloat {
  234. var width = 0.0
  235. let attributes = [NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0)]
  236. width += string.boundingRect(with: CGSize(width: 100, height: 24), attributes: attributes).size.width
  237. width = max(width, 30)
  238. return width
  239. }
  240. func fetchScaleWidth(string: NSString) -> CGFloat {
  241. var width = 40.0
  242. let attributes = [NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0)]
  243. width += string.boundingRect(with: CGSize(width: 100, height: 24), attributes: attributes).size.width
  244. width = max(width, 80)
  245. return width
  246. }
  247. }
  248. //MARK: Mouse
  249. extension KMReadModelView {
  250. override func mouseDown(with event: NSEvent) {
  251. KMPrint("mouseDown")
  252. }
  253. override func mouseUp(with event: NSEvent) {
  254. KMPrint("mouseUp")
  255. }
  256. override func mouseMoved(with event: NSEvent) {
  257. KMPrint("mouseMoved")
  258. }
  259. override func mouseEntered(with event: NSEvent) {
  260. KMPrint("mouseEntered")
  261. }
  262. override func mouseExited(with event: NSEvent) {
  263. KMPrint("mouseExited")
  264. }
  265. }
  266. //MARK: PopButton
  267. extension KMReadModelView: KMSelectPopButtonDelegate {
  268. func km_comboBoxSelectionDidChange(_ obj: KMDesignSelect) {
  269. KMPrint("km_comboBoxSelectionDidChange")
  270. self.updateUI()
  271. self.delegate?.scaleDidChange(view: self, sender: obj, type: KMReadModelViewScaleType(rawValue: KMReadModelViewScaleType.allValues()[obj.indexOfSelectedItem]) ?? .autoSize)
  272. }
  273. }
  274. //MARK:
  275. extension KMReadModelView: NSTextFieldDelegate {
  276. func controlTextDidEndEditing(_ obj: Notification) {
  277. let string = Int(self.currentPageTextField.stringValue)?.description ?? "1"
  278. currentPageTextField.stringValue = string
  279. self.delegate?.currentPageButtonDidChange(view: self, sender: obj, pageIndex: Int(string) ?? 1)
  280. }
  281. }
  282. //MARK: In out
  283. extension KMReadModelView {
  284. @objc fileprivate func inReadModelView() {
  285. self.endTimer()
  286. self.updateUI()
  287. NSAnimationContext.runAnimationGroup { NSAnimationContext in
  288. self.animator().alphaValue = 1
  289. }
  290. }
  291. @objc fileprivate func outReadModelView() {
  292. NSAnimationContext.runAnimationGroup { NSAnimationContext in
  293. self.animator().alphaValue = 0
  294. self.endTimer()
  295. }
  296. }
  297. func resetTimer() {
  298. self.endTimer()
  299. self.beginTimer()
  300. }
  301. func beginTimer() {
  302. if self.timer != nil {
  303. self.endTimer()
  304. }
  305. self.inReadModelView()
  306. self.timer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(outReadModelView), userInfo: nil, repeats: true)
  307. }
  308. func endTimer() {
  309. self.timer?.invalidate()
  310. self.timer = nil
  311. }
  312. }
  313. //MARK: Action
  314. extension KMReadModelView {
  315. @IBAction func escButtonAction(_ sender: Any) {
  316. KMPrint("read model escButtonAction")
  317. self.delegate?.cancelReadModel(view: self, sender: sender)
  318. }
  319. @objc func firstPageButtonAction(sender: Any) {
  320. KMPrint("firstPageButtonAction")
  321. if self.canFirstPageButtonAction() {
  322. self.delegate?.firstPageButtonDidChange(view: self, sender: sender)
  323. }
  324. self.updateButtonState()
  325. }
  326. @objc func beforePageButtonAction(sender: Any) {
  327. KMPrint("beforePageButtonAction")
  328. if self.canBeforePageButtonAction() {
  329. self.delegate?.beforePageButtonDidChange(view: self, sender: sender)
  330. }
  331. self.updateButtonState()
  332. }
  333. @objc func afterPageButtonAction(sender: Any) {
  334. KMPrint("afterPageButtonAction")
  335. if self.canAfterPageButtonAction() {
  336. self.delegate?.afterPageButtonDidChange(view: self, sender: sender)
  337. }
  338. self.updateButtonState()
  339. }
  340. @objc func lastPageButtonAction(sender: Any) {
  341. KMPrint("lastPageButtonAction")
  342. if self.canLastPageButtonAction() {
  343. self.delegate?.lastPageButtonDidChange(view: self, sender: sender)
  344. }
  345. self.updateButtonState()
  346. }
  347. func canFirstPageButtonAction() -> Bool {
  348. guard let pageIndex = self.currentPageIndex else { return false }
  349. if pageIndex != 0 {
  350. return true
  351. } else {
  352. return false
  353. }
  354. }
  355. func canBeforePageButtonAction() -> Bool {
  356. guard let pageIndex = self.currentPageIndex else { return false }
  357. if pageIndex != 0 {
  358. return true
  359. } else {
  360. return false
  361. }
  362. }
  363. func canAfterPageButtonAction() -> Bool {
  364. guard let totalCount = self.totalPagesCount else { return false }
  365. guard let pageIndex = self.currentPageIndex else { return false }
  366. if pageIndex < totalCount - 1 {
  367. return true
  368. } else {
  369. return false
  370. }
  371. }
  372. func canLastPageButtonAction() -> Bool {
  373. guard let totalCount = self.totalPagesCount else { return false }
  374. guard let pageIndex = self.currentPageIndex else { return false }
  375. if pageIndex != totalCount - 1 {
  376. return true
  377. } else {
  378. return false
  379. }
  380. }
  381. func updateButtonState() {
  382. self.firstPageButton.enabled = self.canFirstPageButtonAction()
  383. self.beforePageButton.enabled = self.canBeforePageButtonAction()
  384. self.afterPageButton.enabled = self.canAfterPageButtonAction()
  385. self.lastPageButton.enabled = self.canLastPageButtonAction()
  386. }
  387. }