KMReadModelView.swift 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  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: KMBaseXibView {
  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. override 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. override func reloadData() {
  187. }
  188. override func updateLanguage() {
  189. zoomButton.removeAllItems()
  190. zoomButton.addItems(withObjectValues: KMReadModelViewScaleType.allValues())
  191. }
  192. override 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. override func resetData() {
  204. }
  205. override func addNotification() {
  206. }
  207. override func removeNotification() {
  208. }
  209. }
  210. //MARK: data
  211. extension KMReadModelView {
  212. func fetchWidth() -> CGFloat {
  213. var width = 16.0
  214. width += self.firstPageView.frame.size.width
  215. width += 8.0
  216. width += self.beforePageView.frame.size.width
  217. width += 8.0
  218. width += self.fetchCurrentPageIndexWidth(string: self.currentPageTextField.stringValue as NSString)
  219. width += 8.0
  220. width += 4.0
  221. width += 8.0
  222. width += self.fetchTotalPageIndexWidth(string: self.totalLable.stringValue as NSString)
  223. width += 8.0
  224. width += self.afterPageView.frame.size.width
  225. width += 8.0
  226. width += self.lastPageView.frame.size.width
  227. width += 16.0
  228. width += self.fetchScaleWidth(string: self.zoomButton.stringValue as NSString)
  229. width += 16.0
  230. return width
  231. }
  232. func fetchCurrentPageIndexWidth(string: NSString) -> CGFloat {
  233. var width = 28.0
  234. let attributes = [NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0)]
  235. width += string.boundingRect(with: CGSize(width: 100, height: 24), attributes: attributes).size.width
  236. width = max(width, 48)
  237. return width
  238. }
  239. func fetchTotalPageIndexWidth(string: NSString) -> CGFloat {
  240. var width = 0.0
  241. let attributes = [NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0)]
  242. width += string.boundingRect(with: CGSize(width: 100, height: 24), attributes: attributes).size.width
  243. width = max(width, 30)
  244. return width
  245. }
  246. func fetchScaleWidth(string: NSString) -> CGFloat {
  247. var width = 40.0
  248. let attributes = [NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0)]
  249. width += string.boundingRect(with: CGSize(width: 100, height: 24), attributes: attributes).size.width
  250. width = max(width, 80)
  251. return width
  252. }
  253. }
  254. //MARK: Mouse
  255. extension KMReadModelView {
  256. override func mouseDown(with event: NSEvent) {
  257. KMPrint("mouseDown")
  258. }
  259. override func mouseUp(with event: NSEvent) {
  260. KMPrint("mouseUp")
  261. }
  262. override func mouseMoved(with event: NSEvent) {
  263. KMPrint("mouseMoved")
  264. }
  265. override func mouseEntered(with event: NSEvent) {
  266. KMPrint("mouseEntered")
  267. }
  268. override func mouseExited(with event: NSEvent) {
  269. KMPrint("mouseExited")
  270. }
  271. }
  272. //MARK: PopButton
  273. extension KMReadModelView: KMSelectPopButtonDelegate {
  274. func km_comboBoxSelectionDidChange(_ obj: KMDesignSelect) {
  275. KMPrint("km_comboBoxSelectionDidChange")
  276. self.updateUI()
  277. self.delegate?.scaleDidChange(view: self, sender: obj, type: KMReadModelViewScaleType(rawValue: KMReadModelViewScaleType.allValues()[obj.indexOfSelectedItem]) ?? .autoSize)
  278. }
  279. }
  280. //MARK:
  281. extension KMReadModelView: NSTextFieldDelegate {
  282. func controlTextDidEndEditing(_ obj: Notification) {
  283. let string = Int(self.currentPageTextField.stringValue)?.description ?? "1"
  284. currentPageTextField.stringValue = string
  285. self.delegate?.currentPageButtonDidChange(view: self, sender: obj, pageIndex: Int(string) ?? 1)
  286. }
  287. }
  288. //MARK: In out
  289. extension KMReadModelView {
  290. @objc fileprivate func inReadModelView() {
  291. self.endTimer()
  292. self.updateUI()
  293. NSAnimationContext.runAnimationGroup { NSAnimationContext in
  294. self.animator().alphaValue = 1
  295. }
  296. }
  297. @objc fileprivate func outReadModelView() {
  298. NSAnimationContext.runAnimationGroup { NSAnimationContext in
  299. self.animator().alphaValue = 0
  300. self.endTimer()
  301. }
  302. }
  303. func resetTimer() {
  304. self.endTimer()
  305. self.beginTimer()
  306. }
  307. func beginTimer() {
  308. if self.timer != nil {
  309. self.endTimer()
  310. }
  311. self.inReadModelView()
  312. self.timer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(outReadModelView), userInfo: nil, repeats: true)
  313. }
  314. func endTimer() {
  315. self.timer?.invalidate()
  316. self.timer = nil
  317. }
  318. }
  319. //MARK: Action
  320. extension KMReadModelView {
  321. @IBAction func escButtonAction(_ sender: Any) {
  322. KMPrint("read model escButtonAction")
  323. self.delegate?.cancelReadModel(view: self, sender: sender)
  324. }
  325. @objc func firstPageButtonAction(sender: Any) {
  326. KMPrint("firstPageButtonAction")
  327. if self.canFirstPageButtonAction() {
  328. self.delegate?.firstPageButtonDidChange(view: self, sender: sender)
  329. }
  330. self.updateButtonState()
  331. }
  332. @objc func beforePageButtonAction(sender: Any) {
  333. KMPrint("beforePageButtonAction")
  334. if self.canBeforePageButtonAction() {
  335. self.delegate?.beforePageButtonDidChange(view: self, sender: sender)
  336. }
  337. self.updateButtonState()
  338. }
  339. @objc func afterPageButtonAction(sender: Any) {
  340. KMPrint("afterPageButtonAction")
  341. if self.canAfterPageButtonAction() {
  342. self.delegate?.afterPageButtonDidChange(view: self, sender: sender)
  343. }
  344. self.updateButtonState()
  345. }
  346. @objc func lastPageButtonAction(sender: Any) {
  347. KMPrint("lastPageButtonAction")
  348. if self.canLastPageButtonAction() {
  349. self.delegate?.lastPageButtonDidChange(view: self, sender: sender)
  350. }
  351. self.updateButtonState()
  352. }
  353. func canFirstPageButtonAction() -> Bool {
  354. guard let pageIndex = self.currentPageIndex else { return false }
  355. if pageIndex != 0 {
  356. return true
  357. } else {
  358. return false
  359. }
  360. }
  361. func canBeforePageButtonAction() -> Bool {
  362. guard let pageIndex = self.currentPageIndex else { return false }
  363. if pageIndex != 0 {
  364. return true
  365. } else {
  366. return false
  367. }
  368. }
  369. func canAfterPageButtonAction() -> Bool {
  370. guard let totalCount = self.totalPagesCount else { return false }
  371. guard let pageIndex = self.currentPageIndex else { return false }
  372. if pageIndex < totalCount - 1 {
  373. return true
  374. } else {
  375. return false
  376. }
  377. }
  378. func canLastPageButtonAction() -> Bool {
  379. guard let totalCount = self.totalPagesCount else { return false }
  380. guard let pageIndex = self.currentPageIndex else { return false }
  381. if pageIndex != totalCount - 1 {
  382. return true
  383. } else {
  384. return false
  385. }
  386. }
  387. func updateButtonState() {
  388. self.firstPageButton.enabled = self.canFirstPageButtonAction()
  389. self.beforePageButton.enabled = self.canBeforePageButtonAction()
  390. self.afterPageButton.enabled = self.canAfterPageButtonAction()
  391. self.lastPageButton.enabled = self.canLastPageButtonAction()
  392. }
  393. }