// // KMPageNumberDisplayView.swift // PDF Reader Pro // // Created by lizhe on 2023/4/25. // import Cocoa protocol KMPageNumberDisplayViewDelegate: NSObject { func gotoPageIndex(view: KMPageNumberDisplayView, pageIndex: Int) func updateWidth(view: KMPageNumberDisplayView, width: CGFloat) } class KMPageNumberDisplayView: KMBaseXibView { @IBOutlet weak var totalPageCountLabel: NSTextField! @IBOutlet weak var pageWidthConstraint: NSLayoutConstraint! @IBOutlet weak var lineLabel: NSTextFieldCell! @IBOutlet weak var currentPageIndexLabel: FocusAwareTextField! @IBOutlet weak var currentPageContentView: NSView! @IBOutlet weak var pageLabelConstraint: NSLayoutConstraint! var displayType: KMPreferencePageIndicatorDisplayType? { didSet { self.updateViewDispaly() } } var timer: Timer? weak var delegate: KMPageNumberDisplayViewDelegate? var currentPageIndex: Int? { didSet { let string = (currentPageIndex! + 1).description self.currentPageIndexLabel.stringValue = string self.updateUI() } } var totalPagesCount: Int? { didSet { self.totalPageCountLabel.stringValue = totalPagesCount?.description ?? "1" self.updateUI() } } var hover: Bool = false { didSet{ self.updateViewDispaly() } } var isEdit: Bool = false { didSet { self.currentPageIndexLabel.isEditable = isEdit if isEdit { _ = self.currentPageIndexLabel.becomeFirstResponder() self.currentPageIndexLabel.currentEditor()?.selectAll(nil) } self.updateUI() } } deinit { self.dismiss() } override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) // Drawing code here. } override func setup() { self.backgroundColor(NSColor.km_init(hex: "#36383B")) self.shadow = NSShadow() self.wantsLayer = true self.layer?.shadowColor = NSColor.km_init(hex: "#000000", alpha: 0.16).cgColor self.layer?.shadowOffset = CGSize(width: 0, height: -2) self.layer?.shadowRadius = 8 self.layer?.shadowOpacity = 1 self.layer?.cornerRadius = 4 self.currentPageIndexLabel.delegate = self } //刷新界面UI 和 数据 override func reloadData() { } override func updateLanguage() { } override func updateUI() { // NSString(string: self.currentPageLabel.stringValue).boundingRect(with: NSSize(width: 1000, height: 1000)).size.width + 8 self.totalPageCountLabel.textColor = NSColor.km_init(hex: "#FFFFFF") self.totalPageCountLabel.font = NSFont.SFProTextRegularFont(12.0) self.lineLabel.textColor = NSColor.km_init(hex: "#FFFFFF") self.lineLabel.font = NSFont.SFProTextRegularFont(12.0) if isEdit { currentPageIndexLabel.textColor = NSColor.km_init(hex: "#252629") currentPageIndexLabel.font = NSFont.SFProTextRegularFont(12.0) currentPageContentView.backgroundColor(NSColor.km_init(hex: "#FFFFFF")) currentPageContentView.border(NSColor.km_init(hex: "#DFE1E5"), 1, 4) } else { currentPageIndexLabel.textColor = NSColor.km_init(hex: "#FFFFFF") currentPageIndexLabel.font = NSFont.SFProTextRegularFont(12.0) currentPageContentView.backgroundColor(NSColor.km_init(hex: "#FFFFFF", alpha: 0)) currentPageContentView.border(NSColor.km_init(hex: "#DFE1E5"), 0, 4) } self.delegate?.updateWidth(view: self, width: self.fetchWith(edit: self.isEdit)) } override func resetData() { } override func addNotification() { } override func removeNotification() { } func fetchWith(edit: Bool = false) -> CGFloat { let currentIndexString: NSString = self.currentPageIndexLabel.stringValue as NSString let totalPageCountString: NSString = self.totalPageCountLabel.stringValue as NSString let attributes = [NSAttributedString.Key.font : NSFont.SFProTextRegularFont(12.0), NSAttributedString.Key.foregroundColor: NSColor.km_init(hex: "#FFFFFF")] let currentIndexStringWidth = currentIndexString.boundingRect(with: CGSize(width: 100, height: 36), attributes: attributes).width let totalPageCountStringWidth = totalPageCountString.boundingRect(with: CGSize(width: 100, height: 36), attributes: attributes).width var width = 16 + currentIndexStringWidth + 8 + 4 + 8 + totalPageCountStringWidth + 16 if edit { self.pageWidthConstraint.constant = currentIndexStringWidth + 40 self.pageLabelConstraint.constant = currentIndexStringWidth + 24 width += 40 } else { self.pageWidthConstraint.constant = currentIndexStringWidth self.pageLabelConstraint.constant = currentIndexStringWidth } return width } } //MARK: mouse extension KMPageNumberDisplayView { override func mouseDown(with event: NSEvent) { KMPrint("mouseDown") if !self.isEdit { self.isEdit = true self.delegate?.updateWidth(view: self, width: self.fetchWith(edit: self.isEdit)) } } } //MARK: extension KMPageNumberDisplayView: NSTextFieldDelegate { func controlTextDidEndEditing(_ obj: Notification) { if obj.object is FocusAwareTextField { self.toPageIndex() } } func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool { switch commandSelector { case #selector(NSResponder.insertNewline(_:)): if let _ = control as? NSTextField { //当当前TextField按下enter if (textView.string == self.currentPageIndexLabel.stringValue) { KMPrint("按下 enter") self.isEdit = false self.toPageIndex() } } return true default: return false } } func toPageIndex() { var index = (self.currentPageIndex ?? 0) + 1 if Int(self.currentPageIndexLabel.stringValue) != nil { index = min(max(1, Int(self.currentPageIndexLabel.stringValue)!), totalPagesCount!) } self.currentPageIndexLabel.stringValue = String(index) self.delegate?.gotoPageIndex(view: self, pageIndex: index - 1) self.updateUI() } } //MARK: In out extension KMPageNumberDisplayView { @objc fileprivate func inView() { self.dismiss() NSAnimationContext.runAnimationGroup { NSAnimationContext in self.animator().alphaValue = 1 } } @objc func outView() { NSAnimationContext.runAnimationGroup { NSAnimationContext in self.animator().alphaValue = 0 self.dismiss() self.isEdit = false } } func reset() { self.dismiss() self.show() } func show(type: KMPreferencePageIndicatorDisplayType = .automatic) { self.displayType = type } func dismiss() { self.timer?.invalidate() self.timer = nil } func updateViewDispaly() { var type = self.displayType if hover { type = .always } if type == .automatic { if self.timer != nil { self.dismiss() } self.inView() self.timer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(outView), userInfo: nil, repeats: true) } else if type == .never { self.dismiss() } else if type == .always { self.inView() } } }