// // KMBaseTextField.swift // PDF Reader Pro // // Created by lizhe on 2022/12/12. // import Cocoa typealias KMBaseTextFieldTextDidEndEditing = (_ string: String) -> Void typealias KMBaseTextFieldTextTextDidChange = (_ string: String) -> Void typealias KMBaseTextFieldTextTextDidBeginEditing = (_ string: String) -> Void typealias KMBaseTextFieldTextTextDeleteAction = (_ string: String) -> Void class KMBaseTextField: NSView { var textDidEndEditing: KMBaseTextFieldTextDidEndEditing? var textDidChange: KMBaseTextFieldTextTextDidChange? var textDidBeginEditing: KMBaseTextFieldTextTextDidBeginEditing? var textDeleteAction: KMBaseTextFieldTextTextDeleteAction? var presenter: KMBaseTextFieldPresenter = KMBaseTextFieldPresenter() var model: KMBaseTextFieldModel = KMBaseTextFieldModel() { didSet { self.textFormatter.model = model } } lazy var textField: FocusAwareTextField = FocusAwareTextField() var stringValue: String { set { textField.stringValue = newValue + self.model.specialChart self.model.value = stringValue } get { self.model.value } } var placeholderString: String? { didSet { self.textField.placeholderString = placeholderString! self.model.placeholderString = placeholderString! } } var isEnabled: Bool? { didSet { self.textField.isEnabled = isEnabled! self.model.isEnabled = isEnabled! } } var minLen: Int? { didSet { self.model.minLen = minLen! } } var maxLen: Int = 999 { didSet { self.model.maxLen = maxLen } } var minValue: Int? { didSet { self.model.minValue = minValue! } } var maxValue: Int? { didSet { self.model.maxValue = maxValue! } } var onlyNumber: Bool? { didSet { self.model.onlyNumber = onlyNumber! if onlyNumber! { self.textField.formatter = self.textFormatter } else { self.textField.formatter = nil } } } var inputType: KMBaseTextFieldInputType? { didSet { if (inputType == .int) { self.model.specialChart = "-" } else if (inputType == .float) { self.model.specialChart = ".-" } else if (inputType == .percent) { self.model.specialChart = "%" } } } var textFormatter: KMBaseTextFormatter = KMBaseTextFormatter() override func awakeFromNib() { self.addSubview(self.textField) self.textField.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ self.textField.topAnchor.constraint(equalTo: topAnchor), self.textField.leftAnchor.constraint(equalTo: leftAnchor), self.textField.rightAnchor.constraint(equalTo: rightAnchor), self.textField.bottomAnchor.constraint(equalTo: bottomAnchor)]) self.textField.updateConstraintsForSubtreeIfNeeded() self.textField.formatter = self.textFormatter self.textField.wantsLayer = true self.textField.layer?.borderWidth = 0 self.textField.layer?.borderColor = NSColor.clear.cgColor self.textField.drawsBackground = false self.textField.layer?.backgroundColor = NSColor.clear.cgColor self.textField.backgroundColor = NSColor.clear self.textField.isBordered = false // self.textField.font = FONT_R(13.); // self.textField.textColor = [[NSColor whiteColor] colorWithAlphaComponent:0.87]; self.textField.delegate = self self.textFormatter.model = self.model self.presenter.initPresenter(delegate: self, model: self.model) } } extension KMBaseTextField: NSTextFieldDelegate { func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool { switch commandSelector { case #selector(NSResponder.insertNewline(_:)): if let inputView = control as? NSTextField { //当当前TextField按下enter if inputView == textField { KMPrint("按下 enter") if self.textDidEndEditing != nil { self.textDidEndEditing!(self.model.stringValue) } } } return true case #selector(NSResponder.deleteBackward(_:)): if let inputView = control as? NSTextField { //当当前TextField按下enter if inputView == textField { KMPrint("按下 delete") if inputView.stringValue == "" { if self.textDeleteAction != nil { self.textDeleteAction!(self.model.stringValue) } return true } } } return false default: return false } } func controlTextDidChange(_ obj: Notification) { KMPrint("controlTextDidChange") if self.textField.stringValue.count >= self.maxLen { var string = self.textField.stringValue string = String(string.prefix(1)) self.textField.stringValue = string } self.presenter.changeValue(value: self.textField.stringValue) if self.textDidChange != nil { self.textDidChange!(self.model.stringValue) } } func controlTextDidEndEditing(_ obj: Notification) { KMPrint("controlTextDidEndEditing") self.presenter.changeValue(value: self.textField.stringValue) if self.textDidEndEditing != nil { self.textDidEndEditing!(self.model.stringValue) } } func controlTextDidBeginEditing(_ obj: Notification) { KMPrint("controlTextDidBeginEditing") if self.textDidBeginEditing != nil { self.textDidBeginEditing!(self.model.stringValue) } } func control(_ control: NSControl, textShouldEndEditing fieldEditor: NSText) -> Bool { KMPrint("textShouldEndEditing") return true } } extension KMBaseTextField: KMBaseTextFieldPresenterDelegate { func valueDidChange(presenter: KMBaseTextFieldPresenter, model: KMBaseTextFieldModel) { self.model = model self.textField.stringValue = model.stringValue } } //extension NSTextField { // open override func becomeFirstResponder() -> Bool { // let success = super.becomeFirstResponder() // if success { // let textView: NSTextView = self.currentEditor() as! NSTextView // if textView?.responds(to: #selector(insetionpoint)) { // let color = self.textColor // textView.setInsertionPointColor(color) // } // } // return success // } //} //extension NSTextField { //// var onFocus: () -> Void = {} //// var onUnfocus: () -> Void = {} // // open override func becomeFirstResponder() -> Bool { //// onFocus() // let textView = window?.fieldEditor(true, for: nil) as? NSTextView // textView?.insertionPointColor = NSColor.red // return super.becomeFirstResponder() // } // // open override func resignFirstResponder() -> Bool { //// onUnfocus() // return super.resignFirstResponder() // } //} class FocusAwareTextField: NSTextField, NSTextFieldDelegate { var onFocus: () -> Void = {} var onUnfocus: () -> Void = {} override func becomeFirstResponder() -> Bool { onFocus() let textView = window?.fieldEditor(true, for: nil) as? NSTextView textView?.insertionPointColor = NSColor.km_init(hex: "#252629") return super.becomeFirstResponder() } // override func resignFirstResponder() -> Bool { // onUnfocus() // return super.resignFirstResponder() // } func controlTextDidEndEditing(_ obj: Notification) { let textField = obj.object as? NSTextField if (textField == self) { onUnfocus() } } }