// // KMNBotaSearchTopVIew.swift // PDF Reader Pro // // Created by User-Tangchao on 2024/12/1. // import Cocoa import KMComponentLibrary enum KMNBotaSearchTopItemKey: Int { case search = 1 case replace = 2 case `switch` = 3 case previous = 4 case next = 5 } class KMNBotaSearchTopView: NSView, NibLoadable { @IBOutlet weak var topBox: NSBox! @IBOutlet weak var centerBox: NSBox! @IBOutlet weak var bottomBox: NSBox! @IBOutlet weak var centerHeightConst: NSLayoutConstraint! var itemClick: KMCommonClickBlock? var valueDidChange: KMValueDidChangeBlock? private var topHeight_: CGFloat = 40 private var centerHeight_ : CGFloat = 72 private var bottomHeight_: CGFloat = 32 private var vSpace_: CGFloat = 8 private lazy var searchButton_: ComponentButton = { let view = ComponentButton() view.properties = ComponentButtonProperty(type: .text_gray, size: .xxxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearch")) view.setTarget(self, action: #selector(searchAction)) return view }() private lazy var searchInput_: NSTextField = { let view = NSTextField() view.placeholderString = KMLocalizedString("Search (⌥⌘F)") view.delegate = self return view }() private lazy var replaceButton_: ComponentButton = { let view = ComponentButton() view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchReplace")) view.setTarget(self, action: #selector(replaceAction)) return view }() private lazy var switchButton_: ComponentButton = { let view = ComponentButton() view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchSwitch")) view.setTarget(self, action: #selector(switchAction)) return view }() private lazy var centerView_: KMNSearchReplaceItemView = { let view = KMNSearchReplaceItemView() return view }() private lazy var resultLabel_: NSTextField = { let view = NSTextField(labelWithString: "") view.font = ComponentLibrary.shared.getFontFromKey("mac/body-xs-medium") return view }() private lazy var previousButton_: ComponentButton = { let view = ComponentButton() view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchPreviousDisable")) view.setTarget(self, action: #selector(previousAction)) return view }() private lazy var nextButton_: ComponentButton = { let view = ComponentButton() view.properties = ComponentButtonProperty(type: .text_gray_low, size: .xxxs, state: .normal, onlyIcon: true, icon: NSImage(named: "KMImageNameBotaSearchNext")) view.setTarget(self, action: #selector(nextActon)) return view }() var resultLabel: NSTextField { get { return resultLabel_ } } var inputValue: String? { get { return searchInput_.stringValue } set { searchInput_.stringValue = newValue ?? "" } } var replaceText: String? { get { return centerView_.inputValue } set { centerView_.inputValue = newValue ?? "" } } override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) // Drawing code here. } override func awakeFromNib() { super.awakeFromNib() initSubviews() } func initSubviews() { topBox.borderWidth = 0 topBox.contentView?.addSubview(searchButton_) searchButton_.km_add_leading_constraint(constant: 12) searchButton_.km_add_size_constraint(size: NSSize(width: 16, height: 16)) searchButton_.km_add_centerY_constraint() topBox.contentView?.addSubview(searchInput_) searchInput_.km_add_leading_constraint(equalTo: searchButton_, attribute: .trailing, constant: 8) searchInput_.km_add_centerY_constraint() searchInput_.km_add_height_constraint(constant: 20) searchInput_.km_add_trailing_constraint(constant: -76) topBox.contentView?.addSubview(switchButton_) switchButton_.km_add_trailing_constraint(constant: -12) switchButton_.km_add_centerY_constraint() switchButton_.km_add_size_constraint(size: NSSize(width: 24, height: 24)) topBox.contentView?.addSubview(replaceButton_) replaceButton_.km_add_trailing_constraint(equalTo: switchButton_, attribute: .leading, constant: -8) replaceButton_.km_add_centerY_constraint() replaceButton_.km_add_size_constraint(size: NSSize(width: 24, height: 24)) centerBox.isHidden = true centerBox.borderWidth = 0 centerBox.contentView = centerView_ bottomBox.isHidden = true bottomBox.borderWidth = 0 bottomBox.contentView?.addSubview(resultLabel_) resultLabel_.km_add_top_constraint(constant: 16) resultLabel_.km_add_leading_constraint(constant: 16) bottomBox.contentView?.addSubview(nextButton_) nextButton_.km_add_trailing_constraint(constant: -16) nextButton_.km_add_top_constraint(constant: 16) nextButton_.km_add_size_constraint(size: .init(width: 16, height: 16)) bottomBox.contentView?.addSubview(previousButton_) previousButton_.km_add_trailing_constraint(equalTo: nextButton_, attribute: .leading, constant: -8) previousButton_.km_add_top_constraint(constant: 16) previousButton_.km_add_size_constraint(size: .init(width: 16, height: 16)) } func showSearch() { centerBox.isHidden = true centerHeightConst.constant = 0 } func showReplace() { centerBox.isHidden = false centerHeightConst.constant = centerHeight_ } func showResult(type: KMNBotaSearchType) { bottomBox.isHidden = false } func hideResult(type: KMNBotaSearchType) { bottomBox.isHidden = true } func fetchContentHeight(type: KMNBotaSearchType, hasResult: Bool) -> CGFloat { var height: CGFloat = topHeight_ if type == .search { } else if type == .replace { height += centerHeight_ } height += (hasResult ? bottomHeight_+vSpace_ : 0) return height } // MARK: - Actions @objc func searchAction() { itemClick?(KMNBotaSearchTopItemKey.search.rawValue, searchButton_) } @objc func replaceAction() { itemClick?(KMNBotaSearchTopItemKey.replace.rawValue) } @objc func switchAction() { itemClick?(KMNBotaSearchTopItemKey.switch.rawValue) } @objc func previousAction() { itemClick?(KMNBotaSearchTopItemKey.previous.rawValue) } @objc func nextActon() { itemClick?(KMNBotaSearchTopItemKey.next.rawValue) } } extension KMNBotaSearchTopView: NSTextFieldDelegate { func controlTextDidChange(_ obj: Notification) { if searchInput_.isEqual(to: obj.object) { valueDidChange?(searchInput_, [.newKey : searchInput_.stringValue]) } } }